mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-27 08:39:59 +08:00
Merge pull request #37 from webzard-io/runtime
define UI API service, related to #9
This commit is contained in:
commit
b1f41cdaff
@ -8,7 +8,7 @@
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module">
|
||||
import renderApp from "../../src/main.tsx";
|
||||
import renderApp, { runTest } from "../../src/main.tsx";
|
||||
renderApp({
|
||||
version: "example/v1",
|
||||
metadata: {
|
||||
|
@ -7,10 +7,6 @@
|
||||
</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";
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
"@sinclair/typebox": "^0.19.2",
|
||||
"@vue-reactivity/watch": "^0.1.6",
|
||||
"@vue/reactivity": "^3.1.5",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"dayjs": "^1.10.6",
|
||||
"framer-motion": "^4",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -12,11 +12,13 @@ import {
|
||||
} from "@meta-ui/core";
|
||||
import { merge } from "lodash";
|
||||
import { registry } from "./registry";
|
||||
import { emitter, stateStore, deepEval } from "./store";
|
||||
import { stateStore, deepEval } from "./store";
|
||||
import { apiService } from "./api-service";
|
||||
import { ContainerPropertySchema } from "./traits/core/slot";
|
||||
import { Static } from "@sinclair/typebox";
|
||||
import { watch } from "@vue-reactivity/watch";
|
||||
import _ from "lodash";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
const ImplWrapper = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@ -39,16 +41,23 @@ const ImplWrapper = React.forwardRef<
|
||||
|
||||
const handlerMap = useRef<Record<string, (parameters?: any) => void>>({});
|
||||
useEffect(() => {
|
||||
const handler = (s: { name: string; parameters?: any }) => {
|
||||
const handler = (s: {
|
||||
componentId: string;
|
||||
name: string;
|
||||
parameters?: any;
|
||||
}) => {
|
||||
if (s.componentId !== c.id) {
|
||||
return;
|
||||
}
|
||||
if (!handlerMap.current[s.name]) {
|
||||
// maybe log?
|
||||
return;
|
||||
}
|
||||
handlerMap.current[s.name](s.parameters);
|
||||
};
|
||||
emitter.on(c.id, handler);
|
||||
apiService.on("uiMethod", handler);
|
||||
return () => {
|
||||
emitter.off(c.id, handler);
|
||||
apiService.off("uiMethod", handler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@ -180,26 +189,35 @@ const DebugEvent: React.FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (type: string, event: unknown) => {
|
||||
setEvents((cur) =>
|
||||
cur.concat({ type, event, t: new Date().toLocaleString() })
|
||||
);
|
||||
setEvents((cur) => cur.concat({ type, event, t: new Date() }));
|
||||
};
|
||||
emitter.on("*", handler);
|
||||
return () => emitter.off("*", handler);
|
||||
apiService.on("*", handler);
|
||||
return () => apiService.off("*", handler);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: "0.5em",
|
||||
border: "2px solid black",
|
||||
maxHeight: "200px",
|
||||
overflow: "auto",
|
||||
}}
|
||||
>
|
||||
{events.map((event, idx) => (
|
||||
<pre key={idx}>{JSON.stringify(event)}</pre>
|
||||
))}
|
||||
<div>
|
||||
<div>
|
||||
<button
|
||||
onClick={() => {
|
||||
copy(JSON.stringify(events));
|
||||
}}
|
||||
>
|
||||
copy test case
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
padding: "0.5em",
|
||||
border: "2px solid black",
|
||||
maxHeight: "200px",
|
||||
overflow: "auto",
|
||||
}}
|
||||
>
|
||||
{events.map((event, idx) => (
|
||||
<pre key={idx}>{JSON.stringify(event)}</pre>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
19
packages/runtime/src/api-service.ts
Normal file
19
packages/runtime/src/api-service.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import mitt from "mitt";
|
||||
|
||||
const emitter = mitt<{
|
||||
/**
|
||||
* @description: trigger component's method
|
||||
* @example: { componentId: "btn1", name: "click" }
|
||||
*/
|
||||
uiMethod: {
|
||||
componentId: string;
|
||||
name: string;
|
||||
parameters?: any;
|
||||
};
|
||||
}>();
|
||||
|
||||
export const apiService = {
|
||||
on: emitter.on,
|
||||
off: emitter.off,
|
||||
send: emitter.emit,
|
||||
};
|
@ -2,6 +2,9 @@ import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Application } from "@meta-ui/core";
|
||||
import App from "./App";
|
||||
import { mountUtilMethods } from "./util-methods";
|
||||
|
||||
mountUtilMethods();
|
||||
|
||||
export default function renderApp(options: Application) {
|
||||
ReactDOM.render(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import _ from "lodash";
|
||||
import mitt from "mitt";
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { reactive } from "@vue/reactivity";
|
||||
@ -30,15 +29,6 @@ function parseExpression(raw: string): {
|
||||
};
|
||||
}
|
||||
|
||||
export const emitter = mitt<Record<string, any>>();
|
||||
|
||||
// EXPERIMENT: utils
|
||||
emitter.on("$utils", ({ name, parameters }) => {
|
||||
if (name === "alert") {
|
||||
window.alert(parameters);
|
||||
}
|
||||
});
|
||||
|
||||
function isNumeric(x: string | number) {
|
||||
return !isNaN(Number(x));
|
||||
}
|
||||
|
@ -1,32 +1,22 @@
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef } from "react";
|
||||
import { createTrait } from "@meta-ui/core";
|
||||
import { Static, Type } from "@sinclair/typebox";
|
||||
import { nanoid } from "nanoid";
|
||||
import { debounce, throttle, delay } from "lodash";
|
||||
import { TraitImplementation } from "../../registry";
|
||||
import { emitter } from "../../store";
|
||||
import { apiService } from "../../api-service";
|
||||
|
||||
const useEventTrait: TraitImplementation<{
|
||||
events: Static<typeof EventsPropertySchema>;
|
||||
}> = ({ events }) => {
|
||||
const hookId = useMemo(() => {
|
||||
return nanoid();
|
||||
}, []);
|
||||
const handlerMap = useRef<Record<string, Array<(parameters?: any) => void>>>(
|
||||
{}
|
||||
);
|
||||
useEffect(() => {
|
||||
const handler = (s: { name: string; parameters?: any }) => {
|
||||
if (!handlerMap.current[s.name]) {
|
||||
// maybe log?
|
||||
return;
|
||||
}
|
||||
handlerMap.current[s.name].forEach((fn) => fn(s.parameters));
|
||||
};
|
||||
emitter.on(hookId, handler);
|
||||
return () => {
|
||||
emitter.off(hookId, handler);
|
||||
};
|
||||
const eventHandler = useCallback((s: { name: string; parameters?: any }) => {
|
||||
if (!handlerMap.current[s.name]) {
|
||||
// maybe log?
|
||||
return;
|
||||
}
|
||||
handlerMap.current[s.name].forEach((fn) => fn(s.parameters));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
@ -42,7 +32,8 @@ const useEventTrait: TraitImplementation<{
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
emitter.emit(event.componentId, {
|
||||
apiService.send("uiMethod", {
|
||||
componentId: event.componentId,
|
||||
name: event.method.name,
|
||||
parameters: event.method.parameters,
|
||||
});
|
||||
@ -66,7 +57,9 @@ const useEventTrait: TraitImplementation<{
|
||||
return {
|
||||
// HARDCODE
|
||||
onClick() {
|
||||
emitter.emit(hookId, { name: "click" });
|
||||
eventHandler({
|
||||
name: "click",
|
||||
});
|
||||
},
|
||||
};
|
||||
}, []);
|
||||
|
17
packages/runtime/src/util-methods.ts
Normal file
17
packages/runtime/src/util-methods.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { apiService } from "./api-service";
|
||||
|
||||
export function mountUtilMethods() {
|
||||
apiService.on("uiMethod", ({ componentId, name, parameters }) => {
|
||||
if (componentId !== "$utils") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (name) {
|
||||
case "alert":
|
||||
window.alert(parameters);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
@ -3226,7 +3226,7 @@ convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0,
|
||||
dependencies:
|
||||
safe-buffer "~5.1.1"
|
||||
|
||||
copy-to-clipboard@3.3.1:
|
||||
copy-to-clipboard@3.3.1, copy-to-clipboard@^3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "http://192.168.26.29:7001/copy-to-clipboard/download/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
|
||||
integrity sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=
|
||||
|
Loading…
Reference in New Issue
Block a user