Skip to content

Commit 674b9fe

Browse files
committed
chore: output component
1 parent 127470e commit 674b9fe

File tree

17 files changed

+291
-35
lines changed

17 files changed

+291
-35
lines changed

biome.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"ignore": [
2525
"node_modules/**",
2626
"dist/**",
27-
".vscode/**"
27+
".vscode/**",
28+
"src/template"
2829
]
2930
},
3031
"formatter": {

src/Repl.tsx

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
1-
import CodeMirror from "./components/CodeMirror"
2-
import Preview from "./components/Preview"
1+
import type { FC } from "react"
2+
3+
import EditorContainer from "./components/Editor"
4+
import Output from "./components/Output"
35
import SplitPane from "./components/SplitPanel"
46

5-
import Hello from "./template/hello?raw"
7+
import { ReplProvider } from "./ReplProvider"
8+
import type { ReplState } from "./store"
69

710
import "./repl.css"
8-
import { useState } from "react"
9-
10-
export const ReplReact = () => {
11-
const [code, setCode] = useState(Hello)
12-
13-
const handleCodeChange = (newCode: string) => {
14-
setCode(newCode)
15-
}
1611

12+
export const Repl: FC<ReplState> = (props) => {
1713
return (
18-
<main className="react-repl">
19-
<SplitPane
20-
left={<CodeMirror value={code} onChange={handleCodeChange} />}
21-
right={<Preview value={code} />}
22-
/>
23-
</main>
14+
<ReplProvider config={props}>
15+
<main className="react-repl">
16+
<SplitPane left={<EditorContainer />} right={<Output />} />
17+
</main>
18+
</ReplProvider>
2419
)
2520
}

src/ReplProvider.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { type FC, type PropsWithChildren, useState } from "react"
2+
import { DEFAULT_REPL_STATE, ReplContext, type ReplState } from "./store"
3+
4+
interface Props extends PropsWithChildren {
5+
config?: ReplState
6+
}
7+
8+
export const ReplProvider: FC<Props> = ({ children, config = {} }) => {
9+
const value: ReplState = {
10+
...DEFAULT_REPL_STATE,
11+
...config,
12+
}
13+
14+
const [state, setState] = useState<ReplState>(value)
15+
16+
return (
17+
<ReplContext.Provider value={{ state, setState }}>
18+
{children}
19+
</ReplContext.Provider>
20+
)
21+
}

src/components/CodeMirror/index.tsx renamed to src/components/Editor/CodeMirror/index.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { autocompletion } from "@codemirror/autocomplete"
1+
import { type CompletionSource, autocompletion } from "@codemirror/autocomplete"
22
import { javascript } from "@codemirror/lang-javascript"
33
import { EditorView, basicSetup } from "codemirror"
44
import { type FC, useLayoutEffect, useRef } from "react"
@@ -8,8 +8,12 @@ import { vitesse } from "./theme"
88

99
import "./styles.css"
1010

11+
import type { Extension } from "@codemirror/state"
12+
1113
interface Props {
12-
value: string
14+
code: string
15+
autoComplete?: CompletionSource[]
16+
cmExtensions?: Extension[]
1317
onChange?: (code: string) => void
1418
}
1519

@@ -24,15 +28,16 @@ const CodeMirror: FC<Props> = (props) => {
2428
jsx: true,
2529
}),
2630
autocompletion({
27-
override: [replJSXCompletion],
31+
override: [replJSXCompletion, ...(props.autoComplete || [])],
2832
}),
33+
...(props.cmExtensions || []),
2934
]
3035

3136
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
3237
useLayoutEffect(() => {
3338
if (containerRef.current && !editorRef.current) {
3439
editorRef.current = new EditorView({
35-
doc: props.value,
40+
doc: props.code,
3641
extensions,
3742
parent: containerRef.current,
3843
dispatch(tr) {

src/components/Editor/index.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1+
import { ReplContext } from "@/store"
2+
import { useContext } from "react"
3+
4+
import CodeMirror from "./CodeMirror"
5+
16
const EditorContainer = () => {
2-
return <div>EditorContainer</div>
7+
const { state, setState } = useContext(ReplContext)
8+
const { code = "" } = state
9+
10+
const onChange = (code: string) => {
11+
setState({ ...state, code })
12+
}
13+
14+
return (
15+
<div>
16+
<CodeMirror code={code} onChange={onChange} />
17+
</div>
18+
)
319
}
420

521
export default EditorContainer

src/components/Preview/index.tsx renamed to src/components/Output/Preview/index.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import logger from "@/utils/logger"
77
import basicTemplate from "./basic.html?raw"
88

99
interface Props {
10-
value: string
10+
className?: string
11+
code: string
1112
}
1213

13-
const Preview: React.FC<Props> = ({ value }) => {
14+
const Preview: React.FC<Props> = ({ code, className }) => {
1415
const iframeRef = useRef<HTMLIFrameElement>(null)
1516

1617
// function reload() {
@@ -24,7 +25,7 @@ const Preview: React.FC<Props> = ({ value }) => {
2425
}
2526

2627
try {
27-
const { transformedCode } = await transformCode(value)
28+
const { transformedCode } = await transformCode(code)
2829
const iframeDoc = iframeRef.current.contentDocument
2930
if (!iframeDoc) {
3031
logger.warn(
@@ -66,10 +67,10 @@ const Preview: React.FC<Props> = ({ value }) => {
6667
executeCode()
6768

6869
return cleanup
69-
}, [value])
70+
}, [code])
7071

7172
return (
72-
<div className="react-repl-iframe-container">
73+
<div className={`react-repl-iframe-container ${className}`}>
7374
<iframe
7475
ref={iframeRef}
7576
title="preview"

0 commit comments

Comments
 (0)