Skip to content

Commit 9d682d6

Browse files
authored
Merge pull request #99 from code-hike/slides
Slideshow component
2 parents b790fab + 4abcdea commit 9d682d6

File tree

12 files changed

+966
-10
lines changed

12 files changed

+966
-10
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.ch-slideshow {
2+
margin: 1rem 0;
3+
}
4+
5+
.ch-slideshow-slide {
6+
display: flex;
7+
flex-flow: row;
8+
gap: 0.5rem;
9+
align-items: stretch;
10+
aspect-ratio: 16 / 9;
11+
}
12+
13+
.ch-slideshow-slide .ch-editor-frame,
14+
.ch-slideshow-slide .ch-code {
15+
flex: 2;
16+
}
17+
18+
.ch-slideshow-preview {
19+
flex: 1;
20+
height: auto;
21+
min-width: 0;
22+
}
23+
24+
.ch-slideshow-range {
25+
display: flex;
26+
flex-flow: row;
27+
gap: 0.5rem;
28+
}
29+
30+
.ch-slideshow-range input {
31+
flex: 1;
32+
}
33+
34+
.ch-slideshow-notes {
35+
border-radius: 0.25rem;
36+
margin-top: 1rem;
37+
padding: 1rem;
38+
border: 1px solid #e3e3e3;
39+
}
40+
41+
.ch-slideshow-note {
42+
min-height: 140px;
43+
max-height: 140px;
44+
padding: 0.05px;
45+
overflow: auto;
46+
}

packages/mdx/src/client/slideshow.tsx

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import React from "react"
2+
import {
3+
EditorProps,
4+
EditorStep,
5+
} from "@code-hike/mini-editor"
6+
import { InnerCode, updateEditorStep } from "./code"
7+
import { Preview, PresetConfig } from "./preview"
8+
9+
export function Slideshow({
10+
children,
11+
editorSteps,
12+
codeConfig,
13+
presetConfig,
14+
code,
15+
}: {
16+
children: React.ReactNode
17+
editorSteps: EditorStep[]
18+
codeConfig: EditorProps["codeConfig"]
19+
presetConfig?: PresetConfig
20+
code?: EditorProps["codeConfig"]
21+
}) {
22+
const stepsChildren = React.Children.toArray(children)
23+
24+
const hasNotes = stepsChildren.some(
25+
(child: any) => child.props?.children
26+
)
27+
28+
const [state, setState] = React.useState({
29+
stepIndex: 0,
30+
step: editorSteps[0],
31+
})
32+
const tab = state.step
33+
34+
function onTabClick(filename: string) {
35+
const newStep = updateEditorStep(
36+
state.step,
37+
filename,
38+
null
39+
)
40+
setState({ ...state, step: newStep })
41+
}
42+
43+
return (
44+
<div
45+
className={`ch-slideshow ${
46+
presetConfig ? "ch-slideshow-with-preview" : ""
47+
}`}
48+
>
49+
<div className="ch-slideshow-slide">
50+
<InnerCode
51+
{...(tab as any)}
52+
codeConfig={{
53+
...codeConfig,
54+
...code,
55+
}}
56+
onTabClick={onTabClick}
57+
/>
58+
{presetConfig && (
59+
<Preview
60+
className="ch-slideshow-preview"
61+
files={tab.files}
62+
presetConfig={presetConfig}
63+
/>
64+
)}
65+
</div>
66+
67+
<div className="ch-slideshow-notes">
68+
<div className="ch-slideshow-range">
69+
<button
70+
onClick={() =>
71+
setState(s => {
72+
const stepIndex = Math.max(
73+
0,
74+
s.stepIndex - 1
75+
)
76+
return {
77+
stepIndex,
78+
step: editorSteps[stepIndex],
79+
}
80+
})
81+
}
82+
>
83+
Prev
84+
</button>
85+
<input
86+
type="range"
87+
min={0}
88+
max={editorSteps.length - 1}
89+
value={state.stepIndex}
90+
step={1}
91+
onChange={e =>
92+
setState({
93+
stepIndex: +e.target.value,
94+
step: editorSteps[+e.target.value],
95+
})
96+
}
97+
/>
98+
<button
99+
onClick={() =>
100+
setState(s => {
101+
const stepIndex = Math.min(
102+
editorSteps.length - 1,
103+
s.stepIndex + 1
104+
)
105+
return {
106+
stepIndex,
107+
step: editorSteps[stepIndex],
108+
}
109+
})
110+
}
111+
>
112+
Next
113+
</button>
114+
</div>
115+
116+
{hasNotes && (
117+
<div className="ch-slideshow-note">
118+
{stepsChildren[state.stepIndex]}
119+
</div>
120+
)}
121+
</div>
122+
</div>
123+
)
124+
}

packages/mdx/src/components.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { Code } from "./client/code"
77
import { Spotlight } from "./client/spotlight"
88
import { Scrollycoding } from "./client/scrollycoding"
9+
import { Slideshow } from "./client/slideshow"
910
import {
1011
annotationsMap,
1112
Annotation,
@@ -20,4 +21,5 @@ export const CH = {
2021
Scrollycoding,
2122
annotations: annotationsMap,
2223
Annotation,
24+
Slideshow,
2325
}

packages/mdx/src/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
@import "~@code-hike/mini-browser/dist/index.scss";
33
@import "./client/spotlight.scss";
44
@import "./client/scrollycoding.scss";
5+
@import "./client/slideshow.scss";
56

67
.ch-code {
78
border-radius: 6px;

packages/mdx/src/plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { transformSections } from "./plugin/section"
55
import { transformSpotlights } from "./plugin/spotlight"
66
import { transformScrollycodings } from "./plugin/scrollycoding"
77
import visit from "unist-util-visit"
8+
import { transformSlideshows } from "./plugin/slideshow"
89

910
export function remarkCodeHike({ theme }: { theme: any }) {
1011
return async (tree: Node) => {
@@ -27,6 +28,7 @@ export function remarkCodeHike({ theme }: { theme: any }) {
2728
try {
2829
await transformScrollycodings(tree, { theme })
2930
await transformSpotlights(tree, { theme })
31+
await transformSlideshows(tree, { theme })
3032
await transformSections(tree, { theme })
3133
await transformEditorNodes(tree, { theme })
3234
await transformCodeNodes(tree, { theme })

packages/mdx/src/plugin/slideshow.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { visitAsync, toJSX } from "./unist-utils"
2+
import { Node, Parent } from "unist"
3+
import { extractStepsInfo } from "./steps"
4+
import { getPresetConfig } from "./preview"
5+
6+
export async function transformSlideshows(
7+
tree: Node,
8+
config: { theme: any }
9+
) {
10+
await visitAsync(
11+
tree,
12+
"mdxJsxFlowElement",
13+
async node => {
14+
if (node.name === "CH.Slideshow") {
15+
await transformSlideshow(node, config)
16+
}
17+
}
18+
)
19+
}
20+
async function transformSlideshow(
21+
node: Node,
22+
{ theme }: { theme: any }
23+
) {
24+
const editorSteps = await extractStepsInfo(
25+
node as Parent,
26+
{ theme },
27+
"merge step with previous"
28+
)
29+
30+
const presetConfig = await getPresetConfig(
31+
(node as any).attributes
32+
)
33+
34+
toJSX(node, {
35+
props: {
36+
codeConfig: { theme },
37+
editorSteps: editorSteps,
38+
presetConfig,
39+
},
40+
appendProps: true,
41+
})
42+
}

packages/mini-browser/src/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
flex: 1;
2222
padding: 0 10px;
2323
color: #544;
24+
min-width: 5px;
2425
}
2526

2627
.ch-browser-button {

0 commit comments

Comments
 (0)