Merge pull request #35 from webzard-io/runtime

experimental editor component
This commit is contained in:
yz-yu 2021-08-11 13:34:27 +08:00 committed by GitHub
commit d9117b824b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 204 additions and 6 deletions

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>meta-ui runtime example: app editor</title>
</head>
<body>
<div id="root"></div>
<script>
// https://github.com/satya164/react-simple-code-editor/issues/86
const global = globalThis;
</script>
<script type="module">
import renderApp from "../../src/main.tsx";
renderApp({
version: "example/v1",
metadata: {
name: "editor",
description: "nested meta-ui editor",
},
spec: {
components: [
{
id: "root",
type: "chakra_ui/v1/root",
properties: {},
traits: [],
},
{
id: "editor",
type: "lab/v1/editor",
properties: {},
traits: [
{
type: "core/v1/slot",
properties: {
container: {
id: "root",
slot: "root",
},
},
},
],
},
],
},
});
</script>
</body>
</html>

View File

@ -17,13 +17,16 @@
"lodash": "^4.17.21",
"mitt": "^3.0.0",
"nanoid": "^3.1.23",
"prismjs": "^1.24.1",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-grid-layout": "^1.2.5",
"react-markdown": "^6.0.2"
"react-markdown": "^6.0.2",
"react-simple-code-editor": "^0.11.0"
},
"devDependencies": {
"@types/lodash": "^4.14.170",
"@types/prismjs": "^1.16.6",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-grid-layout": "^1.1.2",

View File

@ -260,7 +260,11 @@ export function resolveNestedComponents(app: RuntimeApplication): {
};
}
const App: React.FC<{ options: Application }> = ({ options }) => {
const App: React.FC<{
options: Application;
debugStore?: boolean;
debugEvent?: boolean;
}> = ({ options, debugStore = true, debugEvent = true }) => {
const app = createApplication(options);
const { topLevelComponents, componentsMap } = useMemo(
() => resolveNestedComponents(app),
@ -280,8 +284,8 @@ const App: React.FC<{ options: Application }> = ({ options }) => {
/>
);
})}
<DebugStore />
<DebugEvent />
{debugStore && <DebugStore />}
{debugEvent && <DebugEvent />}
</div>
);
};

View File

@ -0,0 +1,23 @@
import React from "react";
class ErrorBoundary extends React.Component<{}, { error: unknown }> {
constructor(props: {}) {
super(props);
this.state = { error: null };
}
static getDerivedStateFromError(error: unknown) {
console.log("!!!", { error });
return { error };
}
render() {
if (this.state.error) {
return String(this.state.error);
}
return this.props.children;
}
}
export default ErrorBoundary;

View File

@ -0,0 +1,99 @@
import React, { useEffect, useState } from "react";
import { Application, createComponent, createApplication } from "@meta-ui/core";
import { Box, Button } from "@chakra-ui/react";
import CodeEditor from "react-simple-code-editor";
import { highlight, languages } from "prismjs";
import "prismjs/components/prism-json";
import "prismjs/themes/prism.css";
import { ComponentImplementation } from "../../registry";
import ErrorBoundary from "../_internal/ErrorBoundary";
import App from "../../App";
const Editor: ComponentImplementation<{}> = () => {
const [code, setCode] = useState(
JSON.stringify(
{
version: "example/v1",
kind: "Application",
metadata: {
name: "live_edit",
description:
"build meta-ui app with a editor component based on meta-ui",
},
spec: {
components: [],
},
},
null,
2
)
);
const [codeError, setCodeError] = useState("");
const [app, setApp] = useState<Application>(() => JSON.parse(code));
useEffect(() => {
try {
const newApp = JSON.parse(code);
// as validation
createApplication(newApp);
setApp(newApp);
setCodeError("");
} catch (error) {
console.warn(error);
setCodeError(String(error));
}
}, [code]);
return (
<Box display="flex" height="100vh">
<Box flex="1" borderRight="2px solid black">
<ErrorBoundary key={JSON.stringify(app)}>
<App debugStore={false} debugEvent={false} options={app} />
</ErrorBoundary>
</Box>
<Box width="400px">
<Box py={1}>
<Button
size="sm"
onClick={() => {
try {
setCode(JSON.stringify(JSON.parse(code), null, 2));
} catch {}
}}
>
format
</Button>
</Box>
<Box background={codeError ? "red.50" : "blue.50"}>
<CodeEditor
value={code}
onValueChange={(code) => setCode(code)}
highlight={(code) => highlight(code, languages.json, "JSON")}
padding={10}
style={{
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: 12,
}}
/>
</Box>
{codeError && <Box>{codeError}</Box>}
</Box>
</Box>
);
};
export default {
...createComponent({
version: "lab/v1",
metadata: {
name: "editor",
description: "experimental app editor",
},
spec: {
properties: [],
acceptTraits: [],
state: {},
methods: [],
},
}),
impl: Editor,
};

View File

@ -1,6 +1,5 @@
import React from "react";
import { RuntimeComponent, RuntimeTrait } from "@meta-ui/core";
import { setStore } from "./store";
import { SlotsMap } from "./App";
// components
/* --- plain --- */
@ -20,6 +19,8 @@ import ChakraUICheckbox from "./components/chakra-ui/Checkbox";
import ChakraUIStack from "./components/chakra-ui/Stack";
import ChakraUIHStack from "./components/chakra-ui/HStack";
import ChakraUIVStack from "./components/chakra-ui/VStack";
/* --- lab --- */
import LabEditor from "./components/lab/Editor";
// traits
import CoreState from "./traits/core/state";
import CoreEvent from "./traits/core/event";
@ -40,7 +41,7 @@ type SubscribeMethods = <U>(
[K in keyof U]: (parameters: U[K]) => void;
}
) => void;
type MergeState = (partialState: Parameters<typeof setStore>[0]) => void;
type MergeState = (partialState: any) => void;
export type ComponentImplementation<T = any> = React.FC<
T & {
@ -122,6 +123,7 @@ registry.registerComponent(ChakraUICheckbox);
registry.registerComponent(ChakraUIStack);
registry.registerComponent(ChakraUIHStack);
registry.registerComponent(ChakraUIVStack);
registry.registerComponent(LabEditor);
registry.registerTrait(CoreState);
registry.registerTrait(CoreEvent);

View File

@ -2255,6 +2255,11 @@
resolved "http://192.168.26.29:7001/@types/prettier/download/@types/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3"
integrity sha1-/IwoJeTtIUJHO0qBBk5uCBRj0bM=
"@types/prismjs@^1.16.6":
version "1.16.6"
resolved "http://192.168.26.29:7001/@types/prismjs/download/@types/prismjs-1.16.6.tgz#377054f72f671b36dbe78c517ce2b279d83ecc40"
integrity sha1-N3BU9y9nGzbb54xRfOKyedg+zEA=
"@types/prop-types@*":
version "15.7.4"
resolved "http://192.168.26.29:7001/@types/prop-types/download/@types/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
@ -6519,6 +6524,11 @@ pretty-format@^27.0.6:
ansi-styles "^5.0.0"
react-is "^17.0.1"
prismjs@^1.24.1:
version "1.24.1"
resolved "http://192.168.26.29:7001/prismjs/download/prismjs-1.24.1.tgz#c4d7895c4d6500289482fa8936d9cdd192684036"
integrity sha1-xNeJXE1lACiUgvqJNtnN0ZJoQDY=
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "http://192.168.26.29:7001/process-nextick-args/download/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@ -6743,6 +6753,11 @@ react-resizable@^3.0.1:
prop-types "15.x"
react-draggable "^4.0.3"
react-simple-code-editor@^0.11.0:
version "0.11.0"
resolved "http://192.168.26.29:7001/react-simple-code-editor/download/react-simple-code-editor-0.11.0.tgz#bb57c7c29b570f2ab229872599eac184f5bc673c"
integrity sha1-u1fHwptXDyqyKYclmerBhPW8Zzw=
react-style-singleton@^2.1.0:
version "2.1.1"
resolved "http://192.168.26.29:7001/react-style-singleton/download/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66"