Skip to content

Commit ed6e00d

Browse files
authored
Merge pull request #56 from code-hike/rename-editor-components
Rename editor components
2 parents 39190e1 + 84f43ab commit ed6e00d

File tree

10 files changed

+720
-717
lines changed

10 files changed

+720
-717
lines changed

external/new-react-website

packages/mini-editor/src/index.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import "./index.scss"
22

3-
import { MiniEditor, MiniEditorProps } from "./mini-editor"
43
import {
5-
MiniEditorWithState,
6-
StatefulEditorProps,
7-
} from "./stateful-editor"
4+
MiniEditorHike,
5+
MiniEditorHikeProps,
6+
} from "./mini-editor-hike"
7+
import { MiniEditor, MiniEditorProps } from "./mini-editor"
88

99
export {
10+
MiniEditorHike,
1011
MiniEditor,
11-
MiniEditorWithState,
12+
MiniEditorHikeProps,
1213
MiniEditorProps,
13-
StatefulEditorProps,
1414
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
import React from "react"
2+
import { EditorFrame, TerminalPanel } from "./editor-frame"
3+
import { InnerTerminal } from "@code-hike/mini-terminal"
4+
import { Code } from "./code"
5+
import {
6+
useBackwardTransitions,
7+
useForwardTransitions,
8+
} from "./steps"
9+
import { Classes } from "@code-hike/classer"
10+
// import "./theme.css"
11+
12+
export { MiniEditorHike }
13+
14+
type MiniEditorStep = {
15+
code?: string
16+
focus?: string
17+
lang?: string
18+
file?: string
19+
tabs?: string[]
20+
terminal?: string
21+
}
22+
23+
export type MiniEditorHikeProps = {
24+
progress?: number
25+
backward?: boolean
26+
code?: string
27+
focus?: string
28+
lang?: string
29+
file?: string
30+
tabs?: string[]
31+
steps?: MiniEditorStep[]
32+
height?: number
33+
minColumns?: number
34+
minZoom?: number
35+
maxZoom?: number
36+
button?: React.ReactNode
37+
classes?: Classes
38+
} & React.PropsWithoutRef<JSX.IntrinsicElements["div"]>
39+
40+
function MiniEditorHike(props: MiniEditorHikeProps) {
41+
const {
42+
progress = 0,
43+
backward = false,
44+
code,
45+
focus,
46+
lang,
47+
file,
48+
steps: ogSteps,
49+
tabs: ogTabs,
50+
minColumns = 50,
51+
minZoom = 0.2,
52+
maxZoom = 1,
53+
height,
54+
...rest
55+
} = props
56+
const { steps, files, stepsByFile } = useSteps(ogSteps, {
57+
code,
58+
focus,
59+
lang,
60+
file,
61+
tabs: ogTabs,
62+
})
63+
64+
const activeStepIndex = backward
65+
? Math.floor(progress)
66+
: Math.ceil(progress)
67+
const activeStep = steps[activeStepIndex]
68+
const activeFile = (activeStep && activeStep.file) || ""
69+
70+
const activeSteps = stepsByFile[activeFile] || []
71+
72+
const tabs = activeStep.tabs || files
73+
74+
const terminalHeight = getTerminalHeight(steps, progress)
75+
76+
const terminalSteps = steps.map(s => ({
77+
text: (s && s.terminal) || "",
78+
}))
79+
80+
const contentSteps = useStepsWithDefaults(
81+
{ code, focus, lang, file },
82+
ogSteps || []
83+
)
84+
85+
return (
86+
<EditorFrame
87+
files={tabs}
88+
active={activeFile}
89+
terminalPanel={
90+
<TerminalPanel height={terminalHeight}>
91+
<InnerTerminal
92+
steps={terminalSteps}
93+
progress={progress}
94+
/>
95+
</TerminalPanel>
96+
}
97+
height={height}
98+
{...rest}
99+
>
100+
{activeSteps.length > 0 && (
101+
<EditorContent
102+
key={activeFile}
103+
backward={backward}
104+
progress={progress}
105+
steps={contentSteps}
106+
parentHeight={height}
107+
minColumns={minColumns}
108+
minZoom={minZoom}
109+
maxZoom={maxZoom}
110+
/>
111+
)}
112+
</EditorFrame>
113+
)
114+
}
115+
116+
function useStepsWithDefaults(
117+
defaults: MiniEditorStep,
118+
steps: MiniEditorStep[]
119+
): ContentStep[] {
120+
const files = [
121+
...new Set(
122+
steps.map(s => coalesce(s.file, defaults.file, ""))
123+
),
124+
]
125+
return steps.map(step => {
126+
return {
127+
code: coalesce(step.code, defaults.code, ""),
128+
file: coalesce(step.file, defaults.file, ""),
129+
focus: coalesce(step.focus, defaults.focus, ""),
130+
lang: coalesce(
131+
step.lang,
132+
defaults.lang,
133+
"javascript"
134+
),
135+
tabs: coalesce(step.tabs, defaults.tabs, files),
136+
terminal: step.terminal || defaults.terminal,
137+
}
138+
})
139+
}
140+
141+
function coalesce<T>(
142+
a: T | null | undefined,
143+
b: T | null | undefined,
144+
c: T
145+
): T {
146+
return a != null ? a : b != null ? b : c
147+
}
148+
149+
type ContentStep = {
150+
code: string
151+
focus: string
152+
lang: string
153+
file: string
154+
tabs: string[]
155+
terminal?: string
156+
}
157+
158+
type ContentProps = {
159+
progress: number
160+
backward: boolean
161+
steps: ContentStep[]
162+
parentHeight?: number
163+
minColumns: number
164+
minZoom: number
165+
maxZoom: number
166+
}
167+
168+
function EditorContent({
169+
progress,
170+
backward,
171+
steps,
172+
parentHeight,
173+
minColumns,
174+
minZoom,
175+
maxZoom,
176+
}: ContentProps) {
177+
const fwdTransitions = useForwardTransitions(steps)
178+
const bwdTransitions = useBackwardTransitions(steps)
179+
180+
const transitionIndex = Math.ceil(progress)
181+
const {
182+
prevCode,
183+
nextCode,
184+
prevFocus,
185+
nextFocus,
186+
lang,
187+
} = backward
188+
? bwdTransitions[transitionIndex]
189+
: fwdTransitions[transitionIndex]
190+
191+
return (
192+
<Code
193+
prevCode={prevCode || nextCode!}
194+
nextCode={nextCode || prevCode!}
195+
prevFocus={prevFocus}
196+
nextFocus={nextFocus}
197+
language={lang}
198+
progress={progress - transitionIndex + 1}
199+
parentHeight={parentHeight}
200+
minColumns={minColumns}
201+
minZoom={minZoom}
202+
maxZoom={maxZoom}
203+
/>
204+
)
205+
}
206+
207+
function useSteps(
208+
ogSteps: MiniEditorStep[] | undefined,
209+
{ code = "", focus, lang, file, tabs }: MiniEditorStep
210+
) {
211+
return React.useMemo(() => {
212+
const steps = ogSteps?.map(s => ({
213+
code,
214+
focus,
215+
lang,
216+
file,
217+
tabs,
218+
...s,
219+
})) || [{ code, focus, lang, file, tabs }]
220+
221+
const files = [
222+
...new Set(
223+
steps
224+
.map((s: any) => s.file)
225+
.filter((f: any) => f != null)
226+
),
227+
]
228+
229+
const stepsByFile: Record<string, MiniEditorStep[]> = {}
230+
steps.forEach(s => {
231+
if (s.file == null) return
232+
if (!stepsByFile[s.file]) {
233+
stepsByFile[s.file] = []
234+
}
235+
stepsByFile[s.file].push(s)
236+
})
237+
238+
return { steps, files, stepsByFile }
239+
}, [ogSteps, code, focus, lang, file, tabs])
240+
}
241+
242+
const MAX_HEIGHT = 150
243+
function getTerminalHeight(steps: any, progress: number) {
244+
if (!steps.length) {
245+
return 0
246+
}
247+
248+
const prevIndex = Math.floor(progress)
249+
const nextIndex = Math.ceil(progress)
250+
const prevTerminal =
251+
steps[prevIndex] && steps[prevIndex].terminal
252+
const nextTerminal = steps[nextIndex].terminal
253+
254+
if (!prevTerminal && !nextTerminal) return 0
255+
256+
if (!prevTerminal && nextTerminal)
257+
return MAX_HEIGHT * Math.min((progress % 1) * 4, 1)
258+
if (prevTerminal && !nextTerminal)
259+
return MAX_HEIGHT * Math.max(1 - (progress % 1) * 4, 0)
260+
261+
return MAX_HEIGHT
262+
}

0 commit comments

Comments
 (0)