Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9d682d6

Browse files
authoredDec 27, 2021
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 {

‎packages/playground/content/slideshow-demo.mdx

Lines changed: 529 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# Slideshow with preview
2+
3+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.
4+
5+
<CH.Slideshow preset="https://codesandbox.io/s/w5wfe">
6+
7+
Lorem ipsum dolor sit amet, consectetur adipiscing something about points, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
8+
9+
```jsx src/App.js
10+
import { motion } from "framer-motion"
11+
12+
const transition = { duration: 1 }
13+
14+
export default function App() {
15+
const bg = "hsl(20, 100%, 50%)"
16+
return (
17+
<div className="container">
18+
<motion.div
19+
className="swatch"
20+
animate={{
21+
backgroundColor: bg,
22+
}}
23+
transition={transition}
24+
/>
25+
</div>
26+
)
27+
}
28+
```
29+
30+
---
31+
32+
## Step 2
33+
34+
Velit euismod in pellentesque massa placerat. Mi bibendum neque egestas congue quisque egestas diam in arcu. Nisi lacus sed viverra tellus in.
35+
36+
```jsx src/App.js focus=1,6,9:15
37+
import { motion } from "framer-motion"
38+
39+
const transition = { duration: 1 }
40+
41+
export default function App() {
42+
const bg = "hsl(110, 100%, 50%)"
43+
return (
44+
<div className="container">
45+
<motion.div
46+
className="swatch"
47+
animate={{
48+
backgroundColor: bg,
49+
}}
50+
transition={transition}
51+
/>
52+
</div>
53+
)
54+
}
55+
```
56+
57+
---
58+
59+
## Step 3
60+
61+
Id aliquet risus feugiat in ante metus dictum at tempor. Sed blandit libero volutpat sed cras.
62+
63+
```jsx src/App.js focus=1,6,9:15
64+
import { motion } from "framer-motion"
65+
66+
const transition = { duration: 1 }
67+
68+
export default function App() {
69+
const bg = "hsl(200, 100%, 50%)"
70+
return (
71+
<div className="container">
72+
<motion.div
73+
className="swatch"
74+
animate={{
75+
backgroundColor: bg,
76+
}}
77+
transition={transition}
78+
/>
79+
</div>
80+
)
81+
}
82+
```
83+
84+
---
85+
86+
## Step 4
87+
88+
Velit euismod in pellentesque massa placerat. Mi bibendum neque egestas congue quisque egestas diam in arcu.
89+
90+
```jsx src/App.js focus=1,6,9:15
91+
import { motion } from "framer-motion"
92+
93+
const transition = { duration: 1 }
94+
95+
export default function App() {
96+
const bg = "hsl(290, 100%, 50%)"
97+
return (
98+
<div className="container">
99+
<motion.div
100+
className="swatch"
101+
animate={{
102+
backgroundColor: bg,
103+
}}
104+
transition={transition}
105+
/>
106+
</div>
107+
)
108+
}
109+
```
110+
111+
</CH.Slideshow>
112+
113+
---
114+
115+
Middle
116+
117+
---
118+
119+
<CH.Slideshow>
120+
121+
```jsx src/App.js
122+
import { motion } from "framer-motion"
123+
124+
const transition = { duration: 1 }
125+
126+
export default function App() {
127+
const bg = "hsl(20, 100%, 50%)"
128+
return <div className="container"> </div>
129+
}
130+
```
131+
132+
---
133+
134+
```jsx src/App.js focus=1,6,9:15
135+
import { motion } from "framer-motion"
136+
137+
const transition = { duration: 1 }
138+
139+
export default function App() {
140+
const bg = "hsl(110, 100%, 50%)"
141+
return (
142+
<div className="container">
143+
<motion.div
144+
className="swatch"
145+
animate={{
146+
backgroundColor: bg,
147+
}}
148+
transition={transition}
149+
/>
150+
</div>
151+
)
152+
}
153+
```
154+
155+
---
156+
157+
```jsx src/App.js focus=1,6,9:15
158+
import { motion } from "framer-motion"
159+
160+
const transition = { duration: 1 }
161+
162+
export default function App() {
163+
const bg = "hsl(200, 100%, 50%)"
164+
return (
165+
<div className="container">
166+
<motion.div
167+
className="swatch"
168+
animate={{
169+
backgroundColor: bg,
170+
}}
171+
transition={transition}
172+
/>
173+
</div>
174+
)
175+
}
176+
```
177+
178+
---
179+
180+
```jsx src/App.js focus=1,6,9:15
181+
import { motion } from "framer-motion"
182+
183+
const transition = { duration: 1 }
184+
185+
export default function App() {
186+
const bg = "hsl(290, 100%, 50%)"
187+
return (
188+
<div className="container">
189+
<motion.div
190+
className="swatch"
191+
animate={{
192+
backgroundColor: bg,
193+
}}
194+
transition={transition}
195+
/>
196+
</div>
197+
)
198+
}
199+
```
200+
201+
</CH.Slideshow>
202+
203+
# Rest
204+
205+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.
206+
207+
Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.

‎packages/smooth-code/src/smooth-container.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,7 @@ function Container({
9090
width,
9191
height,
9292
position: "relative",
93-
overflowX: "auto",
94-
// padding: "0 16px",
95-
// boxSizing: "border-box",
96-
// overflow: "auto",
93+
// overflowX: "auto",
9794
}}
9895
>
9996
{children}
@@ -134,7 +131,7 @@ function Content({
134131
top: 0,
135132
left: 0,
136133
transform: `translateX(${dx}px) translateY(${dy}px) scale(${scale})`,
137-
transformOrigin: "top left",
134+
transformOrigin: "16px top",
138135
width: "100%",
139136
}}
140137
>
@@ -214,7 +211,7 @@ function getContentProps({
214211
(extremes[1] - extremes[0] + 3) * lineHeight
215212
const zoom = Math.max(
216213
Math.min(
217-
containerWidth / lineWidth,
214+
(containerWidth - 16 * 2) / lineWidth,
218215
containerHeight / originalFocusHeight,
219216
maxZoom
220217
),

‎packages/smooth-code/src/use-dimensions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ function getLongestLine(
173173
function getWidthWithoutPadding(element: HTMLElement) {
174174
const computedStyle = getComputedStyle(element)
175175
return (
176-
element.clientWidth -
176+
parseFloat(computedStyle.width) -
177177
parseFloat(computedStyle.paddingLeft) -
178178
parseFloat(computedStyle.paddingRight)
179179
)

‎packages/storybook/src/code-tween.story.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ console.log(3)
3030
const nextCode = `
3131
console.log(1)
3232
console.log(3)
33-
const x = (y) => y++
33+
const x = (y) => y++ * foobarbaz
3434
`.trim()
3535

3636
const prevAnnotations = [
@@ -58,7 +58,7 @@ const x = (y) => y++
5858
},
5959
next: {
6060
code: nextCode,
61-
focus: "2",
61+
focus: "2,3",
6262
annotations: nextAnnotations,
6363
},
6464
})
@@ -78,7 +78,12 @@ const x = (y) => y++
7878
progress={progress}
7979
tween={tween}
8080
style={{ height: "100%" }}
81-
config={{ horizontalCenter: center, theme }}
81+
config={{
82+
horizontalCenter: center,
83+
theme,
84+
minZoom: 0.5,
85+
maxZoom: 2,
86+
}}
8287
/>
8388
) : (
8489
"Loading..."

0 commit comments

Comments
 (0)
Please sign in to comment.