Skip to content

Commit 63c113e

Browse files
committed
Support links in scrollycoding
1 parent 942167f commit 63c113e

File tree

6 files changed

+216
-122
lines changed

6 files changed

+216
-122
lines changed

packages/mdx/src/client/scrollycoding.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Step as ScrollerStep,
1010
} from "@code-hike/scroller"
1111
import { Preview, PresetConfig } from "./preview"
12+
import { LinkableSection } from "./section"
1213

1314
export function Scrollycoding({
1415
children,
@@ -45,6 +46,19 @@ export function Scrollycoding({
4546
setState({ ...state, step: newStep })
4647
}
4748

49+
function onLinkActivation(
50+
stepIndex: number,
51+
filename: string | undefined,
52+
focus: string | null
53+
) {
54+
const newStep = updateEditorStep(
55+
editorSteps[stepIndex],
56+
filename,
57+
focus
58+
)
59+
setState({ ...state, stepIndex, step: newStep })
60+
}
61+
4862
return (
4963
<section
5064
className={`ch-scrollycoding ${
@@ -64,7 +78,16 @@ export function Scrollycoding({
6478
i === state.stepIndex ? "true" : undefined
6579
}
6680
>
67-
{children}
81+
<LinkableSection
82+
onActivation={({ fileName, focus }) => {
83+
onLinkActivation(i, fileName, focus)
84+
}}
85+
onReset={() => {
86+
onStepChange(i)
87+
}}
88+
>
89+
{children}
90+
</LinkableSection>
6891
</ScrollerStep>
6992
))}
7093
</Scroller>

packages/mdx/src/client/section.tsx

Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ import { InnerCode, updateEditorStep } from "./code"
44

55
const SectionContext = React.createContext<{
66
props: EditorProps
7-
selectedId?: string
87
setFocus: (x: {
98
fileName?: string
109
focus: string | null
1110
id: string
1211
}) => void
13-
resetFocus: () => void
1412
}>({
1513
props: null!,
1614
setFocus: () => {},
17-
resetFocus: () => {},
1815
})
1916

2017
export function Section({
@@ -48,16 +45,21 @@ export function Section({
4845
const { selectedId, ...rest } = state
4946

5047
return (
51-
<SectionContext.Provider
52-
value={{
53-
props: rest,
54-
setFocus,
55-
resetFocus,
56-
selectedId,
57-
}}
58-
>
59-
<section>{children}</section>
60-
</SectionContext.Provider>
48+
<section>
49+
<SectionContext.Provider
50+
value={{
51+
props: rest,
52+
setFocus,
53+
}}
54+
>
55+
<LinkableSection
56+
onActivation={setFocus}
57+
onReset={resetFocus}
58+
>
59+
{children}
60+
</LinkableSection>
61+
</SectionContext.Provider>
62+
</section>
6163
)
6264
}
6365

@@ -83,10 +85,10 @@ export function SectionLink({
8385
file?: string
8486
children: React.ReactNode
8587
}) {
86-
const { setFocus, resetFocus, selectedId } =
87-
React.useContext(SectionContext)
88+
const { activate, reset, activatedId } =
89+
React.useContext(LinkableContext)
8890

89-
const isSelected = selectedId === id
91+
const isSelected = activatedId === id
9092
// const handleClick = isSelected
9193
// ? resetFocus
9294
// : () => setFocus({ fileName: file, focus, id })
@@ -96,17 +98,74 @@ export function SectionLink({
9698
style={{
9799
textDecoration: "underline",
98100
textDecorationStyle: "dotted",
99-
cursor: "pointer",
101+
// cursor: "pointer",
100102
backgroundColor: isSelected
101103
? "#bae6fd66"
102104
: undefined,
103105
}}
104106
// onClick={handleClick}
105107
children={children}
106108
onMouseOver={() =>
107-
setFocus({ fileName: file, focus, id })
109+
activate({ fileName: file, focus, id })
108110
}
109-
onMouseOut={resetFocus}
111+
onMouseOut={reset}
110112
/>
111113
)
112114
}
115+
116+
// ---
117+
118+
const LinkableContext = React.createContext<{
119+
activate: (x: {
120+
fileName?: string
121+
focus: string | null
122+
id: string
123+
}) => void
124+
reset: () => void
125+
activatedId: string | undefined
126+
}>({
127+
activatedId: undefined,
128+
activate: () => {},
129+
reset: () => {},
130+
})
131+
132+
export function LinkableSection({
133+
onActivation,
134+
onReset,
135+
children,
136+
}: {
137+
onActivation: (x: {
138+
fileName?: string
139+
focus: string | null
140+
id: string
141+
}) => void
142+
onReset: () => void
143+
children: React.ReactNode
144+
}) {
145+
const [activatedId, setActivatedId] =
146+
React.useState<any>(undefined)
147+
148+
const activate = React.useCallback(
149+
x => {
150+
setActivatedId(x.id)
151+
onActivation(x)
152+
},
153+
[onActivation]
154+
)
155+
const reset = React.useCallback(() => {
156+
setActivatedId(undefined)
157+
onReset()
158+
}, [onReset])
159+
160+
return (
161+
<LinkableContext.Provider
162+
value={{
163+
activate,
164+
reset,
165+
activatedId,
166+
}}
167+
>
168+
{children}
169+
</LinkableContext.Provider>
170+
)
171+
}

packages/mdx/src/plugin/scrollycoding.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { Node, Parent } from "unist"
77
import { extractStepsInfo } from "./steps"
88
import { getPresetConfig } from "./preview"
9+
import { transformLinks } from "./section"
910

1011
export async function transformScrollycodings(
1112
tree: Node,
@@ -35,6 +36,8 @@ async function transformScrollycoding(
3536
(node as any).attributes
3637
)
3738

39+
transformLinks(node)
40+
3841
toJSX(node, {
3942
props: {
4043
codeConfig: CH_CODE_CONFIG_PLACEHOLDER,

packages/mdx/src/plugin/section.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async function transformSection(
4646
}
4747
}
4848

49-
function transformLinks(tree: Node) {
49+
export function transformLinks(tree: Node) {
5050
visit(tree, "link", (linkNode: any) => {
5151
const url = decodeURI(linkNode["url"])
5252
if (url.startsWith("focus://")) {

0 commit comments

Comments
 (0)