mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
add basic module
This commit is contained in:
parent
8363143459
commit
c682e3b360
@ -3,3 +3,4 @@ export * from './trait';
|
||||
export * from './scope';
|
||||
export * from './application';
|
||||
export * from './method';
|
||||
export * from './module';
|
||||
|
33
packages/core/src/module.ts
Normal file
33
packages/core/src/module.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { JSONSchema7Object } from 'json-schema';
|
||||
import { parseVersion } from './version';
|
||||
import { Metadata } from './metadata';
|
||||
import { Version } from './version';
|
||||
import { ApplicationComponent } from './application';
|
||||
|
||||
// spec
|
||||
|
||||
export type Module = {
|
||||
version: string;
|
||||
kind: 'Module';
|
||||
metadata: Metadata;
|
||||
spec: ModuleSpec;
|
||||
};
|
||||
|
||||
type ModuleSpec = {
|
||||
components: ApplicationComponent[];
|
||||
properties: JSONSchema7Object;
|
||||
events: string[];
|
||||
};
|
||||
|
||||
// extended runtime
|
||||
export type RuntimeModule = Module & {
|
||||
parsedVersion: Version;
|
||||
};
|
||||
|
||||
export function createModule(options: Omit<Module, 'kind'>): RuntimeModule {
|
||||
return {
|
||||
...options,
|
||||
kind: 'Module',
|
||||
parsedVersion: parseVersion(options.version),
|
||||
};
|
||||
}
|
100
packages/runtime/example/list/listModule.html
Normal file
100
packages/runtime/example/list/listModule.html
Normal file
@ -0,0 +1,100 @@
|
||||
<!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: list component</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module">
|
||||
import renderApp from '../../src/main.tsx';
|
||||
const listdata = [
|
||||
{
|
||||
id: 1,
|
||||
name: '马云',
|
||||
email: 'jack.ma@deck.com',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '马化腾',
|
||||
email: 'pony.ma@conversation.com',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '李彦宏',
|
||||
email: 'robin.li@response.com',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '张一鸣',
|
||||
email: 'yiming.zhang@example.com',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '王兴',
|
||||
email: 'xing.wang@widget.org',
|
||||
},
|
||||
];
|
||||
|
||||
renderApp({
|
||||
version: 'example/v1',
|
||||
metadata: {
|
||||
name: 'list_component',
|
||||
description: 'list component example',
|
||||
},
|
||||
spec: {
|
||||
components: [
|
||||
{
|
||||
id: 'root',
|
||||
type: 'chakra_ui/v1/root',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/state',
|
||||
properties: {
|
||||
key: 'listTitle',
|
||||
initialValue: '客户列表',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/arrayState',
|
||||
properties: {
|
||||
key: 'listData',
|
||||
initialValue: listdata,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'list',
|
||||
type: 'chakra_ui/v1/list',
|
||||
properties: {
|
||||
listData: '{{ root.listData }}',
|
||||
template: {
|
||||
type: 'core/v1/littleItem',
|
||||
properties: {
|
||||
$id: '{{$listItem.id}}{{$i}}',
|
||||
value: '{{$listItem.name}}',
|
||||
value2: '{{$listItem.email}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'root',
|
||||
slot: 'root',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -34,7 +34,8 @@ const List: ComponentImplementation<Static<typeof PropsSchema>> = ({
|
||||
return null;
|
||||
}
|
||||
const itemElementMemo = useRef(new Map());
|
||||
const parsedtemplete = template.map(parseTypeComponents);
|
||||
const moduleTemplate = services.registry.getModuleByType(template.type);
|
||||
const parsedtemplete = moduleTemplate.spec.components.map(parseTypeComponents);
|
||||
|
||||
const listItems = listData.map((listItem, i) => {
|
||||
// this memo only diff listItem, dosen't compare expressions
|
||||
@ -44,8 +45,8 @@ const List: ComponentImplementation<Static<typeof PropsSchema>> = ({
|
||||
}
|
||||
}
|
||||
|
||||
const evaledTemplate = services.stateManager.mapValuesDeep(
|
||||
{ parsedtemplete },
|
||||
const evaledModuleProperties = services.stateManager.mapValuesDeep(
|
||||
template.properties,
|
||||
({ value }) => {
|
||||
if (typeof value === 'string') {
|
||||
return services.stateManager.maskedEval(value, true, {
|
||||
@ -55,10 +56,20 @@ const List: ComponentImplementation<Static<typeof PropsSchema>> = ({
|
||||
}
|
||||
return value;
|
||||
}
|
||||
).parsedtemplete;
|
||||
);
|
||||
|
||||
const eventModuleTemplate = services.stateManager.mapValuesDeep(
|
||||
{ template: parsedtemplete },
|
||||
({ value }) => {
|
||||
if (typeof value === 'string') {
|
||||
return services.stateManager.maskedEval(value, true, evaledModuleProperties);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
).template;
|
||||
|
||||
const { topLevelComponents, slotComponentsMap } = resolveAppComponents(
|
||||
evaledTemplate,
|
||||
eventModuleTemplate,
|
||||
{
|
||||
services,
|
||||
app,
|
||||
@ -96,7 +107,10 @@ const List: ComponentImplementation<Static<typeof PropsSchema>> = ({
|
||||
|
||||
const PropsSchema = Type.Object({
|
||||
listData: Type.Array(Type.Record(Type.String(), Type.String())),
|
||||
template: Type.Array(Type.Any()),
|
||||
template: Type.Object({
|
||||
type: Type.String(),
|
||||
properties: Type.Object({}),
|
||||
}),
|
||||
});
|
||||
|
||||
const exampleProperties = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { RuntimeComponent, RuntimeTrait } from '@meta-ui/core';
|
||||
import { RuntimeComponent, RuntimeTrait, RuntimeModule } from '@meta-ui/core';
|
||||
// components
|
||||
/* --- plain --- */
|
||||
import PlainButton from '../components/plain/Button';
|
||||
@ -56,9 +56,77 @@ type ImplementedRuntimeTrait = RuntimeTrait & {
|
||||
impl: TraitImplementation;
|
||||
};
|
||||
|
||||
const exampleModule: RuntimeModule = {
|
||||
version: 'core/v1',
|
||||
kind: 'Module',
|
||||
parsedVersion: {
|
||||
category: 'core/v1',
|
||||
value: 'littleItem',
|
||||
},
|
||||
metadata: {
|
||||
name: 'littleItem',
|
||||
},
|
||||
// name: 'littleItem',
|
||||
spec: {
|
||||
components: [
|
||||
{
|
||||
id: '{{$id}}hstack',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
properties: {},
|
||||
traits: [],
|
||||
},
|
||||
{
|
||||
id: '{{$id}}1',
|
||||
type: 'core/v1/text',
|
||||
properties: {
|
||||
value: {
|
||||
raw: '**{{value}}**',
|
||||
format: 'md',
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: '{{$id}}hstack',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '{{$id}}2',
|
||||
type: 'core/v1/text',
|
||||
properties: {
|
||||
value: {
|
||||
raw: '**{{value2}}**',
|
||||
format: 'md',
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: '{{$id}}hstack',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
properties: {},
|
||||
events: [],
|
||||
},
|
||||
};
|
||||
|
||||
export class Registry {
|
||||
components: Map<string, Map<string, ImplementedRuntimeComponent>> = new Map();
|
||||
traits: Map<string, Map<string, ImplementedRuntimeTrait>> = new Map();
|
||||
modules: Map<string, Map<string, RuntimeModule>> = new Map();
|
||||
|
||||
registerComponent(c: ImplementedRuntimeComponent) {
|
||||
if (this.components.get(c.version)?.has(c.metadata.name)) {
|
||||
@ -119,6 +187,31 @@ export class Registry {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
registerModule(c: RuntimeModule) {
|
||||
if (this.modules.get(c.version)?.has(c.metadata.name)) {
|
||||
throw new Error(
|
||||
`Already has module ${c.version}/${c.metadata.name} in this registry.`
|
||||
);
|
||||
}
|
||||
if (!this.modules.has(c.version)) {
|
||||
this.modules.set(c.version, new Map());
|
||||
}
|
||||
this.modules.get(c.version)?.set(c.metadata.name, c);
|
||||
}
|
||||
|
||||
getModule(version: string, name: string): RuntimeModule {
|
||||
const m = this.modules.get(version)?.get(name);
|
||||
if (!m) {
|
||||
throw new Error(`Module ${version}/${name} has not registered yet.`);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
getModuleByType(type: string): RuntimeModule {
|
||||
const { version, name } = parseType(type);
|
||||
return this.getModule(version, name);
|
||||
}
|
||||
}
|
||||
|
||||
export function initRegistry(): Registry {
|
||||
@ -162,5 +255,7 @@ export function initRegistry(): Registry {
|
||||
registry.registerTrait(CoreFetch);
|
||||
registry.registerTrait(CoreValidation);
|
||||
|
||||
registry.registerModule(exampleModule);
|
||||
|
||||
return registry;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user