Skip to content

Commit

Permalink
[POC] support live editing
Browse files Browse the repository at this point in the history
  • Loading branch information
Neo Nie committed Mar 22, 2022
1 parent 50d1578 commit 1f92b1f
Show file tree
Hide file tree
Showing 52 changed files with 372 additions and 86 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
"react-github-btn": "1.2.0",
"react-helmet": "6.1.0",
"react-hook-form": "6.0.0-rc.1",
"react-hook-form-v7": "npm:react-hook-form@7",
"react-runner": "^1.0.0",
"react-simple-animate": "^3.3.12",
"react-simple-code-editor": "^0.11.0",
"react-simple-img": "2.3.9",
"react-sortablejs": "1.5.1",
"sortablejs": "1.10.2"
Expand Down
33 changes: 33 additions & 0 deletions src/components/CodeArea.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,36 @@
.wrapper pre code.showCode {
display: block;
}

.liveRunnerWrapper {
overflow: auto;
margin: 14px 0;
}

:global(.light) .liveRunnerWrapper {
border: 1px solid var(--color-light-grey);
}

.liveRunner {
background: var(--color-purple);
color: white;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
font-size: 14px;
white-space: pre;
caret-color: #fff;
min-width: 100%;
float: left;
}

:global(.light) .liveRunner {
background: #fff;
color: #000;
caret-color: #000;
}

.liveRunner > textarea,
.liveRunner > pre {
outline: none;
white-space: pre !important;
line-height: 1.5 !important;
}
39 changes: 4 additions & 35 deletions src/components/CodeArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react"
import copyClipBoard from "./utils/copyClipBoard"
import { useStateMachine } from "little-state-machine"
import generic from "../data/generic"
import Prism from "prismjs"
import { LiveRunner } from "./LiveRunner"
import * as styles from "./CodeArea.module.css"

export const CodeSandBoxLink = ({
Expand Down Expand Up @@ -98,15 +98,6 @@ export default function CodeArea({
const { currentLanguage } =
language && language.currentLanguage ? language : { currentLanguage: "en" }

React.useEffect(() => {
const highlight = async () => {
if (codeAreaRef.current) {
Prism.highlightAllUnder(codeAreaRef.current)
}
}
highlight()
}, [])

return (
<section
style={{
Expand Down Expand Up @@ -168,31 +159,9 @@ export default function CodeArea({
)}
</div>

<div className={styles.wrapper} ref={codeAreaRef}>
<pre style={style} className="raw-code">
<code
className={`language-javascript ${
currentType === ToggleTypes.js ? styles.showCode : ""
}`}
>
{rawData}
</code>
<code
className={`language-javascript ${
currentType === ToggleTypes.ts ? styles.showCode : ""
}`}
>
{tsRawData}
</code>
<code
className={`language-javascript ${
currentType === ToggleTypes.types ? styles.showCode : ""
}`}
>
{rawTypes}
</code>
</pre>
</div>
<LiveRunner
initialCode={currentType === ToggleTypes.js ? rawData : tsRawData}
/>
</section>
)
}
175 changes: 175 additions & 0 deletions src/components/LiveRunner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import * as React from "react"
import * as HookForm from "react-hook-form-v7"
import { useRunner } from "react-runner"
import Editor from "react-simple-code-editor"
import Prism from "prismjs"

import { ShadowRoot } from "./ShadowRoot"
import * as styles from "./CodeArea.module.css"

const scope = {
import: {
react: React,
"react-hook-form": HookForm,
},
}

const style = `
body, :host {
background: #0e101c;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
padding: 14px;
}
form {
max-width: 500px;
margin: 0 auto;
}
h1 {
font-weight: 100;
color: white;
text-align: center;
padding-bottom: 10px;
border-bottom: 1px solid rgb(79, 98, 148);
}
.form {
background: #0e101c;
max-width: 400px;
margin: 0 auto;
}
p {
color: #bf1650;
}
p::before {
display: inline;
content: "⚠ ";
}
input {
display: block;
box-sizing: border-box;
width: 100%;
border-radius: 4px;
border: 1px solid white;
padding: 10px 15px;
margin-bottom: 10px;
font-size: 14px;
}
label {
line-height: 2;
text-align: left;
display: block;
margin-bottom: 13px;
margin-top: 20px;
color: white;
font-size: 14px;
font-weight: 200;
}
button[type="submit"],
input[type="submit"] {
background: #ec5990;
color: white;
text-transform: uppercase;
border: none;
margin-top: 40px;
padding: 20px;
font-size: 16px;
font-weight: 100;
letter-spacing: 10px;
}
button[type="submit"]:hover,
input[type="submit"]:hover {
background: #bf1650;
}
button[type="submit"]:active,
input[type="button"]:active,
input[type="submit"]:active {
transition: 0.3s all;
transform: translateY(3px);
border: 1px solid transparent;
opacity: 0.8;
}
input:disabled {
opacity: 0.4;
}
input[type="button"]:hover {
transition: 0.3s all;
}
button[type="submit"],
input[type="button"],
input[type="submit"] {
-webkit-appearance: none;
}
.App {
max-width: 600px;
margin: 0 auto;
}
button[type="button"] {
display: block;
appearance: none;
background: #333;
color: white;
border: none;
text-transform: uppercase;
padding: 10px 20px;
border-radius: 4px;
}
hr {
margin-top: 30px;
}
button {
display: block;
appearance: none;
margin-top: 40px;
border: 1px solid #333;
margin-bottom: 20px;
text-transform: uppercase;
padding: 10px 20px;
border-radius: 4px;
}`

export const LiveRunner = ({ initialCode }: { initialCode: string }) => {
const [code, setCode] = React.useState(initialCode)
const { element, error } = useRunner({ code, scope })
React.useEffect(() => {
setCode(initialCode)
}, [initialCode])

return (
<>
<div className={styles.liveRunnerWrapper}>
<Editor
value={code}
onValueChange={setCode}
padding={15}
className={styles.liveRunner}
highlight={(code) =>
Prism.highlight(code, Prism.languages.javascript)
}
/>
</div>
<ShadowRoot>
{element}
{error && <div>{error}</div>}
<style>{style}</style>
</ShadowRoot>
</>
)
}
20 changes: 20 additions & 0 deletions src/components/ShadowRoot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from "react"
import { createPortal } from "react-dom"

export const ShadowRoot: React.FC<JSX.IntrinsicElements["div"]> = ({
children,
...rest
}) => {
const ref = React.useRef<HTMLDivElement>(null)
const [shadowRoot, setShadowRoot] = React.useState<ShadowRoot>()

React.useEffect(() => {
setShadowRoot(ref.current?.attachShadow({ mode: "open" }))
}, [])

return (
<div ref={ref} {...rest}>
{shadowRoot && createPortal(children, shadowRoot as any)}
</div>
)
}
2 changes: 1 addition & 1 deletion src/components/codeExamples/clearError.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default `import * as React from "react";
import { useForm } from "react-hook-form";
const App = () => {
export default function App() {
const { register, formState: { errors }, handleSubmit, clearErrors } = useForm();
const onSubmit = data => console.log(data);
Expand Down
2 changes: 1 addition & 1 deletion src/components/codeExamples/clearErrorTs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type FormInputs = {
username: string;
};
const App = () => {
export default function App() {
const { register, formState: { errors }, handleSubmit, clearErrors } = useForm<FormInputs>();
const onSubmit = (data: FormInputs) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/codeExamples/connectForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const DeepNest = () => (
</ConnectForm>
);
export const App = () => {
export export default function App() {
const methods = useForm();
return (
Expand Down
10 changes: 6 additions & 4 deletions src/components/codeExamples/getStarted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const Select = React.forwardRef(({ onChange, onBlur, name, label }, ref) => (
</>
));
const App = () => {
export default function App() {
const { register, handleSubmit } = useForm();
const onSubmit = (data) => {
Expand Down Expand Up @@ -128,7 +128,7 @@ const Select = React.forwardRef<
</>
));
const App = () => {
export default function App() {
const { register, handleSubmit } = useForm<IFormValues>();
const onSubmit: SubmitHandler<IFormValues> = data => {
Expand Down Expand Up @@ -207,7 +207,7 @@ import Select from "react-select";
import { useForm, Controller } from "react-hook-form";
import Input from "@material-ui/core/Input";
const App = () => {
export default function App() {
const { control, handleSubmit } = useForm({
defaultValues: {
firstName: '',
Expand Down Expand Up @@ -252,7 +252,7 @@ interface IFormInput {
iceCreamType: {label: string; value: string };
}
const App = () => {
export default function App() {
const { control, handleSubmit } = useForm<IFormInput>();
const onSubmit: SubmitHandler<IFormInput> = data => {
Expand Down Expand Up @@ -364,6 +364,8 @@ connect(({ firstName, lastName }) => ({ firstName, lastName }), updateAction)(Yo
export const errors = `import React from "react";
import { useForm } from "react-hook-form";
const onSubmit = data => console.log(data);
export default function App() {
const { register, formState: { errors }, handleSubmit } = useForm();
Expand Down
2 changes: 1 addition & 1 deletion src/components/codeExamples/joiResolver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const schema = Joi.object({
age: Joi.string().required(),
});
const App = () => {
export default function App() {
const { register, handleSubmit } = useForm({
resolver: joiResolver(schema),
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/codeExamples/joiResolverTs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const schema = Joi.object({
age: Joi.number().required()
});
const App = () => {
export default function App() {
const { register, handleSubmit, formState: { errors } } = useForm<IFormInput>({
resolver: joiResolver(schema)
});
Expand Down

0 comments on commit 1f92b1f

Please sign in to comment.