mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-04-18 22:00:22 +08:00
Merge pull request #204 from webzard-io/refactor/type
rename types in core and runtime
This commit is contained in:
commit
862c9d71ea
@ -4,14 +4,14 @@ import {
|
||||
implementRuntimeComponent,
|
||||
LIST_ITEM_EXP,
|
||||
LIST_ITEM_INDEX_EXP,
|
||||
RuntimeModuleSchema,
|
||||
ModuleSchema,
|
||||
ModuleRenderer,
|
||||
} from '@sunmao-ui/runtime';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
const PropsSchema = Type.Object({
|
||||
listData: Type.Array(Type.Record(Type.String(), Type.String())),
|
||||
template: RuntimeModuleSchema,
|
||||
template: ModuleSchema,
|
||||
});
|
||||
|
||||
const exampleProperties = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { RuntimeModuleSchema, EventHandlerSchema } from '@sunmao-ui/runtime';
|
||||
import { ModuleSchema, EventHandlerSchema } from '@sunmao-ui/runtime';
|
||||
|
||||
export const MajorKeyPropertySchema = Type.String();
|
||||
export const RowsPerPagePropertySchema = Type.Number();
|
||||
@ -30,7 +30,7 @@ export const ColumnSchema = Type.Object({
|
||||
text: Type.String(),
|
||||
handlers: Type.Array(EventHandlerSchema),
|
||||
}),
|
||||
module: RuntimeModuleSchema,
|
||||
module: ModuleSchema,
|
||||
});
|
||||
|
||||
export const ColumnsPropertySchema = Type.Array(ColumnSchema);
|
||||
|
@ -7,47 +7,45 @@ export type Application = {
|
||||
version: string;
|
||||
kind: 'Application';
|
||||
metadata: Metadata;
|
||||
spec: ApplicationSpec;
|
||||
spec: {
|
||||
components: ComponentSchema[];
|
||||
};
|
||||
};
|
||||
|
||||
type ApplicationSpec = {
|
||||
components: ApplicationComponent[];
|
||||
};
|
||||
|
||||
export type ApplicationComponent = {
|
||||
export type ComponentSchema = {
|
||||
id: string;
|
||||
type: string;
|
||||
// do runtime type check
|
||||
properties: Record<string, unknown>;
|
||||
traits: ComponentTrait[];
|
||||
traits: TraitSchema[];
|
||||
// scopes TBD
|
||||
};
|
||||
|
||||
export type ComponentTrait = {
|
||||
export type TraitSchema = {
|
||||
type: string;
|
||||
// do runtime type check
|
||||
properties: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type RuntimeTraitSchema = TraitSchema & {
|
||||
parsedType: VersionAndName;
|
||||
}
|
||||
|
||||
type VersionAndName = {
|
||||
version: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type RuntimeComponentSchema = Omit<ComponentSchema, 'traits'> & {
|
||||
parsedType: VersionAndName;
|
||||
traits: RuntimeTraitSchema[];
|
||||
};
|
||||
|
||||
// extended runtime
|
||||
export type RuntimeApplication = Omit<Application, 'spec'> & {
|
||||
parsedVersion: Version;
|
||||
spec: Omit<ApplicationSpec, 'components'> & {
|
||||
components: Array<
|
||||
Omit<ApplicationComponent, 'traits'> & {
|
||||
parsedType: VersionAndName;
|
||||
traits: Array<
|
||||
ComponentTrait & {
|
||||
parsedType: VersionAndName;
|
||||
}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
spec: {
|
||||
components: RuntimeComponentSchema[];
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ type ComponentSpec<
|
||||
events: ReadonlyArray<KEvent>;
|
||||
};
|
||||
|
||||
export type ComponentDefinition<
|
||||
export type Component<
|
||||
KMethodName extends string,
|
||||
KStyleSlot extends string,
|
||||
KSlot extends string,
|
||||
@ -32,12 +32,12 @@ export type ComponentDefinition<
|
||||
spec: ComponentSpec<KMethodName, KStyleSlot, KSlot, KEvent>;
|
||||
};
|
||||
|
||||
export type RuntimeComponentSpec<
|
||||
export type RuntimeComponent<
|
||||
KMethodName extends string,
|
||||
KStyleSlot extends string,
|
||||
KSlot extends string,
|
||||
KEvent extends string
|
||||
> = ComponentDefinition<KMethodName, KStyleSlot, KSlot, KEvent> & {
|
||||
> = Component<KMethodName, KStyleSlot, KSlot, KEvent> & {
|
||||
parsedVersion: Version;
|
||||
};
|
||||
|
||||
@ -46,7 +46,7 @@ export type CreateComponentOptions<
|
||||
KStyleSlot extends string,
|
||||
KSlot extends string,
|
||||
KEvent extends string
|
||||
> = Omit<ComponentDefinition<KMethodName, KStyleSlot, KSlot, KEvent>, 'kind'>;
|
||||
> = Omit<Component<KMethodName, KStyleSlot, KSlot, KEvent>, 'kind'>;
|
||||
|
||||
export function createComponent<
|
||||
KMethodName extends string,
|
||||
@ -55,7 +55,7 @@ export function createComponent<
|
||||
KEvent extends string
|
||||
>(
|
||||
options: CreateComponentOptions<KMethodName, KStyleSlot, KSlot, KEvent>
|
||||
): RuntimeComponentSpec<KMethodName, KStyleSlot, KSlot, KEvent> {
|
||||
): RuntimeComponent<KMethodName, KStyleSlot, KSlot, KEvent> {
|
||||
return {
|
||||
...options,
|
||||
kind: 'Component',
|
||||
|
@ -19,18 +19,18 @@ type ModuleSpec = {
|
||||
};
|
||||
|
||||
// extended runtime
|
||||
export type RuntimeModuleSpec = Module & {
|
||||
export type RuntimeModule = Module & {
|
||||
parsedVersion: Version;
|
||||
};
|
||||
|
||||
// partial some fields, use as param createModule
|
||||
export type ModuleDefinition = {
|
||||
type CreateModuleOptions = {
|
||||
version: string;
|
||||
metadata: Metadata;
|
||||
spec?: Partial<ModuleSpec>;
|
||||
};
|
||||
|
||||
export function createModule(options: ModuleDefinition): RuntimeModuleSpec {
|
||||
export function createModule(options: CreateModuleOptions): RuntimeModule {
|
||||
return {
|
||||
version: options.version,
|
||||
kind: 'Module',
|
||||
|
@ -19,33 +19,32 @@ type TraitSpec = {
|
||||
};
|
||||
|
||||
// extended runtime
|
||||
export type RuntimeTraitSpec = Trait & {
|
||||
export type RuntimeTrait = Trait & {
|
||||
parsedVersion: Version;
|
||||
};
|
||||
|
||||
// partial some fields, use as param createTrait
|
||||
export type TraitDefinition = {
|
||||
// partial some fields, use as param createModule
|
||||
type CreateTraitOptions = {
|
||||
version: string;
|
||||
metadata: Metadata;
|
||||
spec?: Partial<TraitSpec>;
|
||||
};
|
||||
|
||||
export function createTrait(options: TraitDefinition): RuntimeTraitSpec {
|
||||
return (
|
||||
{
|
||||
version: options.version,
|
||||
kind: ('Trait' as any),
|
||||
parsedVersion: parseVersion(options.version),
|
||||
metadata: {
|
||||
name: options.metadata.name,
|
||||
description: options.metadata.description || '',
|
||||
},
|
||||
spec: {
|
||||
properties: {},
|
||||
state: {},
|
||||
methods: [],
|
||||
...options.spec
|
||||
},
|
||||
}
|
||||
);
|
||||
// partial some field
|
||||
export function createTrait(options: CreateTraitOptions): RuntimeTrait {
|
||||
return {
|
||||
version: options.version,
|
||||
kind: 'Trait' as any,
|
||||
parsedVersion: parseVersion(options.version),
|
||||
metadata: {
|
||||
name: options.metadata.name,
|
||||
description: options.metadata.description || '',
|
||||
},
|
||||
spec: {
|
||||
properties: {},
|
||||
state: {},
|
||||
methods: [],
|
||||
...options.spec,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Application, ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { Application, ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
export const AppSchema: Application = {
|
||||
kind: 'Application',
|
||||
@ -128,7 +128,7 @@ export const AppSchema: Application = {
|
||||
},
|
||||
};
|
||||
|
||||
export const DuplicatedIdSchema: ApplicationComponent[] = [
|
||||
export const DuplicatedIdSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'hstack1',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
export const OrphanComponentSchema: ApplicationComponent[] = [
|
||||
export const OrphanComponentSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'hstack1',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
@ -31,7 +31,7 @@ export const OrphanComponentSchema: ApplicationComponent[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const ComponentInvalidSchema: ApplicationComponent[] = [
|
||||
export const ComponentInvalidSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'text1',
|
||||
type: 'core/v1/text',
|
||||
@ -55,7 +55,7 @@ export const ComponentInvalidSchema: ApplicationComponent[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const ComponentPropertyExpressionSchema: ApplicationComponent[] = [
|
||||
export const ComponentPropertyExpressionSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'text1',
|
||||
type: 'chakra_ui/v1/list',
|
||||
@ -67,7 +67,7 @@ export const ComponentPropertyExpressionSchema: ApplicationComponent[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const TraitInvalidSchema: ApplicationComponent[] = [
|
||||
export const TraitInvalidSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'text1',
|
||||
type: 'core/v1/text',
|
||||
@ -102,7 +102,7 @@ export const TraitInvalidSchema: ApplicationComponent[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const EventTraitSchema: ApplicationComponent[] = [
|
||||
export const EventTraitSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'input1',
|
||||
type: 'chakra_ui/v1/input',
|
||||
@ -177,7 +177,7 @@ export const EventTraitSchema: ApplicationComponent[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const EventTraitTraitMethodSchema: ApplicationComponent[] = [
|
||||
export const EventTraitTraitMethodSchema: ComponentSchema[] = [
|
||||
{
|
||||
id: 'text1',
|
||||
type: 'core/v1/text',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent, parseType } from '@sunmao-ui/core';
|
||||
import { ComponentSchema, parseType } from '@sunmao-ui/core';
|
||||
import { ComponentModel } from './ComponentModel';
|
||||
import {
|
||||
ComponentId,
|
||||
@ -12,11 +12,11 @@ import { genComponent } from './utils';
|
||||
export class AppModel implements IAppModel {
|
||||
topComponents: IComponentModel[] = [];
|
||||
// modules: IModuleModel[] = [];
|
||||
private schema: ApplicationComponent[] = [];
|
||||
private schema: ComponentSchema[] = [];
|
||||
private componentMap: Record<ComponentId, IComponentModel> = {};
|
||||
private componentsCount = 0;
|
||||
|
||||
constructor(components: ApplicationComponent[]) {
|
||||
constructor(components: ComponentSchema[]) {
|
||||
this.schema = components;
|
||||
this.componentsCount = components.length;
|
||||
this.resolveTree(components);
|
||||
@ -35,7 +35,7 @@ export class AppModel implements IAppModel {
|
||||
return Object.values(this.componentMap);
|
||||
}
|
||||
|
||||
toSchema(): ApplicationComponent[] {
|
||||
toSchema(): ComponentSchema[] {
|
||||
this.schema = this.allComponents.map(c => {
|
||||
return c.toSchema();
|
||||
});
|
||||
@ -88,7 +88,7 @@ export class AppModel implements IAppModel {
|
||||
return newId;
|
||||
}
|
||||
|
||||
private resolveTree(components: ApplicationComponent[]) {
|
||||
private resolveTree(components: ComponentSchema[]) {
|
||||
const allComponents = components.map(c => {
|
||||
if (this.componentMap[c.id as ComponentId]) {
|
||||
throw new Error(`Duplicate component id: ${c.id}`);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {
|
||||
ApplicationComponent,
|
||||
ComponentSchema,
|
||||
MethodSchema,
|
||||
RuntimeComponentSpec,
|
||||
RuntimeComponent,
|
||||
} from '@sunmao-ui/core';
|
||||
import { registry } from '../setup';
|
||||
import { genComponent, genTrait } from './utils';
|
||||
@ -22,7 +22,7 @@ import {
|
||||
} from './IAppModel';
|
||||
import { TraitModel } from './TraitModel';
|
||||
import { FieldModel } from './FieldModel';
|
||||
type ComponentSpecModel = RuntimeComponentSpec<MethodName, StyleSlotName, SlotName, EventName>
|
||||
type ComponentSpecModel = RuntimeComponent<MethodName, StyleSlotName, SlotName, EventName>
|
||||
const SlotTraitType: TraitType = 'core/v1/slot' as TraitType;
|
||||
export class ComponentModel implements IComponentModel {
|
||||
private spec: ComponentSpecModel;
|
||||
@ -37,7 +37,7 @@ export class ComponentModel implements IComponentModel {
|
||||
traits: ITraitModel[] = [];
|
||||
_isDirty = false;
|
||||
|
||||
constructor(public appModel: IAppModel, private schema: ApplicationComponent) {
|
||||
constructor(public appModel: IAppModel, private schema: ComponentSchema) {
|
||||
this.schema = schema;
|
||||
|
||||
this.id = schema.id as ComponentId;
|
||||
@ -134,7 +134,7 @@ export class ComponentModel implements IComponentModel {
|
||||
return result;
|
||||
}
|
||||
|
||||
toSchema(): ApplicationComponent {
|
||||
toSchema(): ComponentSchema {
|
||||
if (this._isDirty) {
|
||||
this._isDirty = false;
|
||||
const newProperties = this.rawProperties;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent, ComponentTrait, MethodSchema } from '@sunmao-ui/core';
|
||||
import { ComponentSchema, TraitSchema, MethodSchema } from '@sunmao-ui/core';
|
||||
|
||||
export type ComponentId = string & {
|
||||
kind: 'componentId';
|
||||
@ -41,7 +41,7 @@ export interface IAppModel {
|
||||
allComponents: IComponentModel[];
|
||||
// all components, including orphan component
|
||||
allComponentsWithOrphan: IComponentModel[];
|
||||
toSchema(): ApplicationComponent[];
|
||||
toSchema(): ComponentSchema[];
|
||||
createComponent(type: ComponentType, id?: ComponentId): IComponentModel;
|
||||
getComponentById(id: ComponentId): IComponentModel | undefined;
|
||||
removeComponent(componentId: ComponentId): void;
|
||||
@ -80,7 +80,7 @@ export interface IComponentModel {
|
||||
prevSilbling: IComponentModel | null;
|
||||
_isDirty: boolean;
|
||||
_slotTrait: ITraitModel | null;
|
||||
toSchema(): ApplicationComponent;
|
||||
toSchema(): ComponentSchema;
|
||||
updateComponentProperty: (property: string, value: unknown) => void;
|
||||
// move component from old parent to new parent(or top level if parent is undefined).
|
||||
appendTo: (parent?: IComponentModel, slot?: SlotName) => void;
|
||||
@ -106,7 +106,7 @@ export interface ITraitModel {
|
||||
methods: MethodSchema[];
|
||||
stateKeys: StateKey[];
|
||||
_isDirty: boolean;
|
||||
toSchema(): ComponentTrait;
|
||||
toSchema(): TraitSchema;
|
||||
updateProperty: (key: string, value: any) => void;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ComponentTrait, RuntimeTraitSpec } from '@sunmao-ui/core';
|
||||
import { TraitSchema, RuntimeTrait } from '@sunmao-ui/core';
|
||||
import { registry } from '../setup';
|
||||
import {
|
||||
IComponentModel,
|
||||
@ -14,14 +14,14 @@ import { genTrait } from './utils';
|
||||
let traitIdCount = 0;
|
||||
|
||||
export class TraitModel implements ITraitModel {
|
||||
private schema: ComponentTrait;
|
||||
private spec: RuntimeTraitSpec;
|
||||
private schema: TraitSchema;
|
||||
private spec: RuntimeTrait;
|
||||
id: TraitId;
|
||||
type: TraitType;
|
||||
properties: Record<string, IFieldModel> = {};
|
||||
_isDirty = false;
|
||||
|
||||
constructor(trait: ComponentTrait, public parent: IComponentModel) {
|
||||
constructor(trait: TraitSchema, public parent: IComponentModel) {
|
||||
this.schema = trait;
|
||||
this.parent = parent;
|
||||
this.type = trait.type as TraitType;
|
||||
@ -50,7 +50,7 @@ export class TraitModel implements ITraitModel {
|
||||
return (this.spec ? Object.keys(this.spec.spec.state.properties || {}) : []) as StateKey[];
|
||||
}
|
||||
|
||||
toSchema(): ComponentTrait {
|
||||
toSchema(): TraitSchema {
|
||||
if (this._isDirty) {
|
||||
this.schema = genTrait(this.type, this.rawProperties);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ApplicationComponent, ComponentTrait } from '@sunmao-ui/core';
|
||||
import { ComponentSchema, TraitSchema } from '@sunmao-ui/core';
|
||||
import { registry } from '../setup';
|
||||
|
||||
export function genComponent(
|
||||
type: string,
|
||||
id: string,
|
||||
properties?: Record<string, unknown>,
|
||||
traits: ComponentTrait[] = []
|
||||
): ApplicationComponent {
|
||||
traits: TraitSchema[] = []
|
||||
): ComponentSchema {
|
||||
const cImpl = registry.getComponentByType(type);
|
||||
const initProperties = properties || cImpl.metadata.exampleProperties;
|
||||
return {
|
||||
@ -20,7 +20,7 @@ export function genComponent(
|
||||
export function genTrait(
|
||||
type: string,
|
||||
properties: Record<string, unknown> = {}
|
||||
): ComponentTrait {
|
||||
): TraitSchema {
|
||||
return {
|
||||
type,
|
||||
properties,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { observable, makeObservable, action, toJS } from 'mobx';
|
||||
import { Application, ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { Application, ComponentSchema } from '@sunmao-ui/core';
|
||||
import { ImplementedRuntimeModule } from '@sunmao-ui/runtime';
|
||||
import { produce } from 'immer';
|
||||
import { DefaultNewModule, EmptyAppSchema } from './constants';
|
||||
@ -61,7 +61,7 @@ export class AppStorage {
|
||||
type: 'app' | 'module',
|
||||
version: string,
|
||||
name: string,
|
||||
components: ApplicationComponent[]
|
||||
components: ComponentSchema[]
|
||||
) {
|
||||
switch (type) {
|
||||
case 'app':
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { action, makeAutoObservable, observable, reaction, toJS } from 'mobx';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { eventBus } from './eventBus';
|
||||
import { AppStorage } from './AppStorage';
|
||||
import { registry, stateManager } from './setup';
|
||||
@ -12,7 +12,7 @@ type EditingTarget = {
|
||||
};
|
||||
|
||||
class EditorStore {
|
||||
components: ApplicationComponent[] = [];
|
||||
components: ComponentSchema[] = [];
|
||||
// currentEditingComponents, it could be app's or module's components
|
||||
selectedComponentId = '';
|
||||
hoverComponentId = '';
|
||||
@ -94,7 +94,7 @@ class EditorStore {
|
||||
|
||||
// origin components of app of module
|
||||
// when switch app or module, components should refresh
|
||||
get originComponents(): ApplicationComponent[] {
|
||||
get originComponents(): ComponentSchema[] {
|
||||
switch (this.currentEditingTarget.kind) {
|
||||
case 'module':
|
||||
const module = this.modules.find(
|
||||
@ -141,7 +141,7 @@ class EditorStore {
|
||||
setHoverComponentId = (val: string) => {
|
||||
this.hoverComponentId = val;
|
||||
};
|
||||
setComponents = (val: ApplicationComponent[]) => {
|
||||
setComponents = (val: ComponentSchema[]) => {
|
||||
this.components = val;
|
||||
};
|
||||
pushDragIdStack = (val: string) => {
|
||||
|
@ -3,7 +3,7 @@ import { AddIcon } from '@chakra-ui/icons';
|
||||
import { HStack, IconButton, VStack } from '@chakra-ui/react';
|
||||
import { Static } from '@sinclair/typebox';
|
||||
import produce from 'immer';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { EventHandlerSchema } from '@sunmao-ui/runtime';
|
||||
import { eventBus } from '../../../eventBus';
|
||||
import { EventHandlerForm } from './EventHandlerForm';
|
||||
@ -14,7 +14,7 @@ type EventHandler = Static<typeof EventHandlerSchema>;
|
||||
|
||||
type Props = {
|
||||
registry: Registry;
|
||||
component: ApplicationComponent;
|
||||
component: ComponentSchema;
|
||||
};
|
||||
|
||||
export const EventTraitForm: React.FC<Props> = props => {
|
||||
|
@ -12,7 +12,7 @@ import { Static } from '@sinclair/typebox';
|
||||
import { AddIcon, CloseIcon } from '@chakra-ui/icons';
|
||||
import { useFormik } from 'formik';
|
||||
import produce from 'immer';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { EventCallBackHandlerSchema, FetchTraitPropertiesSchema } from '@sunmao-ui/runtime';
|
||||
import { formWrapperCSS } from '../style';
|
||||
import { KeyValueEditor } from '../../KeyValueEditor';
|
||||
@ -24,7 +24,7 @@ import { genOperation } from '../../../operations';
|
||||
type EventHandler = Static<typeof EventCallBackHandlerSchema>;
|
||||
|
||||
type Props = {
|
||||
component: ApplicationComponent;
|
||||
component: ComponentSchema;
|
||||
registry: Registry;
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent, ComponentTrait } from '@sunmao-ui/core';
|
||||
import { ComponentSchema, TraitSchema } from '@sunmao-ui/core';
|
||||
import { HStack, IconButton, VStack } from '@chakra-ui/react';
|
||||
import { parseTypeBox } from '@sunmao-ui/runtime';
|
||||
import { CloseIcon } from '@chakra-ui/icons';
|
||||
@ -9,8 +9,8 @@ import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
|
||||
|
||||
type Props = {
|
||||
registry: Registry;
|
||||
component: ApplicationComponent;
|
||||
trait: ComponentTrait;
|
||||
component: ComponentSchema;
|
||||
trait: TraitSchema;
|
||||
traitIndex: number;
|
||||
onRemove: () => void;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { parseTypeBox } from '@sunmao-ui/runtime';
|
||||
import { HStack, VStack } from '@chakra-ui/react';
|
||||
import { TSchema } from '@sinclair/typebox';
|
||||
@ -11,7 +11,7 @@ import { genOperation } from '../../../operations';
|
||||
|
||||
type Props = {
|
||||
registry: Registry;
|
||||
component: ApplicationComponent;
|
||||
component: ComponentSchema;
|
||||
};
|
||||
|
||||
export const GeneralTraitFormList: React.FC<Props> = props => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ComponentDefinition } from '@sunmao-ui/core';
|
||||
import { Component } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime';
|
||||
|
||||
type Schema = ComponentDefinition<string, string, string, string>['spec']['properties'];
|
||||
type Schema = Component<string, string, string, string>['spec']['properties'];
|
||||
type EditorSchema = {
|
||||
widget?: string;
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
Text,
|
||||
Select,
|
||||
} from '@chakra-ui/react';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime';
|
||||
import { CssEditor } from '../../../components/CodeEditor';
|
||||
import { eventBus } from '../../../eventBus';
|
||||
@ -19,7 +19,7 @@ import { formWrapperCSS } from '../style';
|
||||
|
||||
type Props = {
|
||||
registry: Registry;
|
||||
component: ApplicationComponent;
|
||||
component: ComponentSchema;
|
||||
};
|
||||
|
||||
type Styles = Array<{
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { css } from '@emotion/css';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import React, { useRef } from 'react';
|
||||
import { eventBus } from '../eventBus';
|
||||
import { genOperation } from '../operations';
|
||||
@ -8,7 +8,7 @@ import { PasteManager } from '../operations/PasteManager';
|
||||
|
||||
type Props = {
|
||||
selectedComponentId: string;
|
||||
components: ApplicationComponent[];
|
||||
components: ComponentSchema[];
|
||||
};
|
||||
|
||||
export const KeyboardEventWrapper: React.FC<Props> = ({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Box, Text, VStack } from '@chakra-ui/react';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { eventBus } from '../../eventBus';
|
||||
@ -10,7 +10,7 @@ import { genOperation } from '../../operations';
|
||||
|
||||
type Props = {
|
||||
registry: Registry;
|
||||
component: ApplicationComponent;
|
||||
component: ComponentSchema;
|
||||
childrenMap: ChildrenMap;
|
||||
selectedComponentId: string;
|
||||
onSelectComponent: (id: string) => void;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { Box, Text, VStack } from '@chakra-ui/react';
|
||||
import { eventBus } from '../../eventBus';
|
||||
import { ComponentItemView } from './ComponentItemView';
|
||||
@ -11,11 +11,11 @@ import { resolveApplicationComponents } from '../../utils/resolveApplicationComp
|
||||
import ErrorBoundary from '../ErrorBoundary';
|
||||
|
||||
export type ChildrenMap = Map<string, SlotsMap>;
|
||||
type SlotsMap = Map<string, ApplicationComponent[]>;
|
||||
type SlotsMap = Map<string, ComponentSchema[]>;
|
||||
|
||||
type Props = {
|
||||
registry: Registry;
|
||||
components: ApplicationComponent[];
|
||||
components: ComponentSchema[];
|
||||
selectedComponentId: string;
|
||||
onSelectComponent: (id: string) => void;
|
||||
};
|
||||
@ -24,8 +24,8 @@ export const StructureTree: React.FC<Props> = props => {
|
||||
const { components, selectedComponentId, onSelectComponent, registry } = props;
|
||||
|
||||
const [realComponents, dataSources] = useMemo(() => {
|
||||
const _realComponent: ApplicationComponent[] = [];
|
||||
const _datasources: ApplicationComponent[] = [];
|
||||
const _realComponent: ComponentSchema[] = [];
|
||||
const _datasources: ComponentSchema[] = [];
|
||||
components.forEach(c => {
|
||||
if (c.type === 'core/v1/dummy') {
|
||||
_datasources.push(c);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import mitt from 'mitt';
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { IOperation } from './operations/type';
|
||||
|
||||
export type EventNames = {
|
||||
@ -7,9 +7,9 @@ export type EventNames = {
|
||||
redo: undefined;
|
||||
undo: undefined;
|
||||
// when switch app or module, current components refresh
|
||||
componentsRefresh: ApplicationComponent[];
|
||||
componentsRefresh: ComponentSchema[];
|
||||
// components change by operation
|
||||
componentsChange: ApplicationComponent[];
|
||||
componentsChange: ComponentSchema[];
|
||||
// it is only used for some operations' side effect
|
||||
selectComponent: string;
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { eventBus } from '../eventBus';
|
||||
import { IUndoRedoManager, IOperation, OperationList } from './type';
|
||||
|
||||
export class AppModelManager implements IUndoRedoManager {
|
||||
components: ApplicationComponent[] = [];
|
||||
components: ComponentSchema[] = [];
|
||||
operationStack: OperationList<IOperation> = new OperationList();
|
||||
|
||||
constructor() {
|
||||
@ -16,7 +16,7 @@ export class AppModelManager implements IUndoRedoManager {
|
||||
});
|
||||
}
|
||||
|
||||
updateComponents(components: ApplicationComponent[]) {
|
||||
updateComponents(components: ComponentSchema[]) {
|
||||
this.components = components;
|
||||
eventBus.send('componentsChange', this.components);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { getComponentAndChildrens } from './util';
|
||||
|
||||
export class PasteManager {
|
||||
rootComponentId = ''
|
||||
componentsCache: ApplicationComponent[] = [];
|
||||
componentsCache: ComponentSchema[] = [];
|
||||
copyTimes = 0;
|
||||
|
||||
setPasteComponents(componentId: string, allComponents: ApplicationComponent[]) {
|
||||
setPasteComponents(componentId: string, allComponents: ComponentSchema[]) {
|
||||
this.rootComponentId = componentId;
|
||||
const children = getComponentAndChildrens(componentId, allComponents);
|
||||
this.componentsCache = [...children];
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import produce from 'immer';
|
||||
import { ComponentId, SlotName } from '../../AppModel/IAppModel';
|
||||
import {
|
||||
@ -17,7 +17,7 @@ export type CreateComponentBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class CreateComponentBranchOperation extends BaseBranchOperation<CreateComponentBranchOperationContext> {
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
// gen component id
|
||||
if (!this.context.componentId) {
|
||||
this.context.componentId = genId(this.context.componentType, prev);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { BaseBranchOperation } from '../type';
|
||||
import {
|
||||
ModifyComponentIdLeafOperation,
|
||||
@ -11,7 +11,7 @@ export type ModifyComponentIdBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class ModifyComponentIdBranchOperation extends BaseBranchOperation<ModifyComponentIdBranchOperationContext> {
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
this.operationStack.insert(new ModifyComponentIdLeafOperation(this.context));
|
||||
|
||||
// update selectid
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { BaseBranchOperation } from '../type';
|
||||
import { CreateTraitLeafOperation, ModifyTraitPropertiesLeafOperation, RemoveTraitLeafOperation } from '../leaf';
|
||||
|
||||
@ -9,7 +9,7 @@ export type MoveComponentBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class MoveComponentBranchOperation extends BaseBranchOperation<MoveComponentBranchOperationContext> {
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const from = prev.find(c => c.id === this.context.fromId);
|
||||
if (!from) return prev;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import produce from 'immer';
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../AppModel/IAppModel';
|
||||
@ -13,7 +13,7 @@ export type RemoveComponentBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class RemoveComponentBranchOperation extends BaseBranchOperation<RemoveComponentBranchOperationContext> {
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const parent = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -8,18 +8,18 @@ export type AdjustComponentOrderLeafOperationContext = {
|
||||
};
|
||||
|
||||
export class AdjustComponentOrderLeafOperation extends BaseLeafOperation<AdjustComponentOrderLeafOperationContext> {
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.move(prev, this.context.orientation);
|
||||
}
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev)
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.move(prev, this.context.orientation === 'up' ? 'down' : 'up');
|
||||
}
|
||||
|
||||
private move(prev: ApplicationComponent[], orientation: 'up' | 'down'): ApplicationComponent[] {
|
||||
private move(prev: ComponentSchema[], orientation: 'up' | 'down'): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, ComponentType, IComponentModel, SlotName } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -13,7 +13,7 @@ export type CreateComponentLeafOperationContext = {
|
||||
export class CreateComponentLeafOperation extends BaseLeafOperation<CreateComponentLeafOperationContext> {
|
||||
private component!: IComponentModel;
|
||||
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.createComponent(this.context.componentType as ComponentType, this.context.componentId as ComponentId);
|
||||
if (this.context.parentId) {
|
||||
@ -29,11 +29,11 @@ export class CreateComponentLeafOperation extends BaseLeafOperation<CreateCompon
|
||||
return newSchema
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev)
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
appModel.removeComponent(this.component.id)
|
||||
return appModel.toSchema()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -9,7 +9,7 @@ export type ModifyComponentIdLeafOperationContext = {
|
||||
};
|
||||
|
||||
export class ModifyComponentIdLeafOperation extends BaseLeafOperation<ModifyComponentIdLeafOperationContext> {
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
@ -19,10 +19,10 @@ export class ModifyComponentIdLeafOperation extends BaseLeafOperation<ModifyComp
|
||||
component.changeId(this.context.newId as ComponentId);
|
||||
return appModel.toSchema();
|
||||
}
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev);
|
||||
}
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.newId as ComponentId)!;
|
||||
component.changeId(this.context.componentId as ComponentId);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
import _ from 'lodash-es';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
@ -10,7 +10,7 @@ export type ModifyComponentPropertiesLeafOperationContext = {
|
||||
|
||||
export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<ModifyComponentPropertiesLeafOperationContext> {
|
||||
private previousState: Record<string, any> = {};
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (component) {
|
||||
@ -34,7 +34,7 @@ export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<Mo
|
||||
const newSchema = appModel.toSchema();
|
||||
return newSchema;
|
||||
}
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
@ -47,7 +47,7 @@ export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<Mo
|
||||
}
|
||||
return appModel.toSchema();
|
||||
}
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, IComponentModel, SlotName } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -7,14 +7,14 @@ export type PasteComponentLeafOperationContext = {
|
||||
parentId: string;
|
||||
slot: string;
|
||||
rootComponentId: string;
|
||||
components: ApplicationComponent[];
|
||||
components: ComponentSchema[];
|
||||
copyTimes: number;
|
||||
};
|
||||
|
||||
export class PasteComponentLeafOperation extends BaseLeafOperation<PasteComponentLeafOperationContext> {
|
||||
private componentCopy!: IComponentModel
|
||||
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const targetParent = appModel.getComponentById(this.context.parentId as ComponentId);
|
||||
if (!targetParent) {
|
||||
@ -34,11 +34,11 @@ export class PasteComponentLeafOperation extends BaseLeafOperation<PasteComponen
|
||||
return appModel.toSchema();
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev)
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
appModel.removeComponent(this.componentCopy.id);
|
||||
return appModel.toSchema()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, IComponentModel, SlotName } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -11,7 +11,7 @@ export class RemoveComponentLeafOperation extends BaseLeafOperation<RemoveCompon
|
||||
private deletedComponent?: IComponentModel;
|
||||
private prevComponent?: IComponentModel;
|
||||
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
this.deletedComponent = appModel.getComponentById(
|
||||
this.context.componentId as ComponentId
|
||||
@ -21,11 +21,11 @@ export class RemoveComponentLeafOperation extends BaseLeafOperation<RemoveCompon
|
||||
return appModel.toSchema();
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
if (!this.deletedComponent) {
|
||||
return prev;
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import produce from 'immer';
|
||||
import { BaseLeafOperation } from '../type';
|
||||
|
||||
export type ReplaceAppLeafOperationContext = {
|
||||
app: ApplicationComponent[];
|
||||
app: ComponentSchema[];
|
||||
};
|
||||
|
||||
export class ReplaceAppLeafOperation extends BaseLeafOperation<ReplaceAppLeafOperationContext> {
|
||||
private previousState!: ApplicationComponent[];
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
private previousState!: ComponentSchema[];
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
this.previousState = prev;
|
||||
return produce(prev, () => {
|
||||
return this.context.app;
|
||||
});
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return produce(prev, () => {
|
||||
return this.context.app;
|
||||
});
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return produce(prev, () => {
|
||||
return this.previousState;
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, TraitId, TraitType } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -12,7 +12,7 @@ export type CreateTraitLeafOperationContext = {
|
||||
export class CreateTraitLeafOperation extends BaseLeafOperation<CreateTraitLeafOperationContext> {
|
||||
private traitId!: TraitId;
|
||||
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
@ -23,11 +23,11 @@ export class CreateTraitLeafOperation extends BaseLeafOperation<CreateTraitLeafO
|
||||
return appModel.toSchema()
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import _ from 'lodash-es';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
@ -12,7 +12,7 @@ export type ModifyTraitPropertiesLeafOperationContext = {
|
||||
|
||||
export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<ModifyTraitPropertiesLeafOperationContext> {
|
||||
private previousState: Record<string, any> = {};
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
@ -34,7 +34,7 @@ export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<Modify
|
||||
|
||||
return appModel.toSchema();
|
||||
}
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
@ -50,7 +50,7 @@ export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<Modify
|
||||
return appModel.toSchema();
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, ITraitModel } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -10,7 +10,7 @@ export type RemoveTraitLeafOperationContext = {
|
||||
|
||||
export class RemoveTraitLeafOperation extends BaseLeafOperation<RemoveTraitLeafOperationContext> {
|
||||
private deletedTrait!: ITraitModel;
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
@ -23,11 +23,11 @@ export class RemoveTraitLeafOperation extends BaseLeafOperation<RemoveTraitLeafO
|
||||
return appModel.toSchema();
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { eventBus } from '../../eventBus';
|
||||
import { BaseLeafOperation } from '../type';
|
||||
|
||||
@ -9,7 +9,7 @@ export type UpdateSelectComponentLeafOperationContext = {
|
||||
|
||||
export class UpdateSelectComponentLeafOperation extends BaseLeafOperation<UpdateSelectComponentLeafOperationContext> {
|
||||
private prevId!: string;
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
this.prevId = this.context.componentId || prev[0].id;
|
||||
setTimeout(() => {
|
||||
eventBus.send('selectComponent', this.context.newId);
|
||||
@ -17,14 +17,14 @@ export class UpdateSelectComponentLeafOperation extends BaseLeafOperation<Update
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
setTimeout(() => {
|
||||
eventBus.send('selectComponent', this.context.newId);
|
||||
});
|
||||
return prev;
|
||||
}
|
||||
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
setTimeout(() => {
|
||||
eventBus.send('selectComponent', this.prevId);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
export const leafSymbol = Symbol('leaf');
|
||||
export const branchSymbol = Symbol('branch');
|
||||
@ -130,9 +130,9 @@ export interface IOperation<TContext = any> extends IUndoRedo {
|
||||
* infer the type of operation, leaf or branch
|
||||
*/
|
||||
type: symbol;
|
||||
do(prev: ApplicationComponent[]): ApplicationComponent[];
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[];
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[];
|
||||
do(prev: ComponentSchema[]): ComponentSchema[];
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[];
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,13 +150,13 @@ export abstract class BaseLeafOperation<TContext> implements IOperation<TContext
|
||||
* @param prev prev application schema
|
||||
* @returns changed application schema
|
||||
*/
|
||||
abstract do(prev: ApplicationComponent[]): ApplicationComponent[];
|
||||
abstract do(prev: ComponentSchema[]): ComponentSchema[];
|
||||
/**
|
||||
* for leaf operation, most time redo is the same as do, override it if not
|
||||
* @param prev prev application schema
|
||||
* @returns changed application schema
|
||||
*/
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev);
|
||||
}
|
||||
/**
|
||||
@ -164,7 +164,7 @@ export abstract class BaseLeafOperation<TContext> implements IOperation<TContext
|
||||
* @param prev prev application schema
|
||||
* @returns changed application schema
|
||||
*/
|
||||
abstract undo(prev: ApplicationComponent[]): ApplicationComponent[];
|
||||
abstract undo(prev: ComponentSchema[]): ComponentSchema[];
|
||||
|
||||
static isLeafOperation<T>(op: IOperation<T>): op is BaseLeafOperation<T> {
|
||||
return op.type === leafSymbol;
|
||||
@ -191,14 +191,14 @@ export abstract class BaseBranchOperation<TContext>
|
||||
* @param prev prev application schema
|
||||
* @returns changed application schema
|
||||
*/
|
||||
abstract do(prev: ApplicationComponent[]): ApplicationComponent[];
|
||||
abstract do(prev: ComponentSchema[]): ComponentSchema[];
|
||||
|
||||
/**
|
||||
* for branch operation, redo is the same as do
|
||||
* @param prev prev application schema
|
||||
* @returns changed application schema
|
||||
*/
|
||||
redo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.operationStack.reduce((prev, node) => {
|
||||
prev = node.redo(prev);
|
||||
return prev;
|
||||
@ -211,7 +211,7 @@ export abstract class BaseBranchOperation<TContext>
|
||||
* @param prev prev application schema
|
||||
* @returns changed application schema
|
||||
*/
|
||||
undo(prev: ApplicationComponent[]): ApplicationComponent[] {
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.operationStack.reduceRight((prev, node) => {
|
||||
prev = node.undo(prev);
|
||||
return prev;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { ApplicationComponent, parseType } from '@sunmao-ui/core';
|
||||
import { ComponentSchema, parseType } from '@sunmao-ui/core';
|
||||
import { isDraft, original } from 'immer';
|
||||
import { get } from 'lodash-es';
|
||||
import { registry } from '../setup';
|
||||
|
||||
export function genComponent(type: string, id: string): ApplicationComponent {
|
||||
export function genComponent(type: string, id: string): ComponentSchema {
|
||||
const { version, name } = parseType(type);
|
||||
const cImpl = registry.getComponent(version, name);
|
||||
const initProperties = cImpl.metadata.exampleProperties;
|
||||
@ -15,7 +15,7 @@ export function genComponent(type: string, id: string): ApplicationComponent {
|
||||
};
|
||||
}
|
||||
|
||||
export function genId(componentType: string, components: ApplicationComponent[]): string {
|
||||
export function genId(componentType: string, components: ComponentSchema[]): string {
|
||||
const { name } = parseType(componentType);
|
||||
const componentsCount = components.filter(
|
||||
component => component.type === componentType
|
||||
@ -29,13 +29,13 @@ export function tryOriginal<T>(val: T): T {
|
||||
|
||||
export function getComponentAndChildrens(
|
||||
componentId: string,
|
||||
allComponents: ApplicationComponent[]
|
||||
): ApplicationComponent[] {
|
||||
allComponents: ComponentSchema[]
|
||||
): ComponentSchema[] {
|
||||
const target = allComponents.find(c => c.id === componentId);
|
||||
if (!target) {
|
||||
return [];
|
||||
}
|
||||
return allComponents.reduce<ApplicationComponent[]>(
|
||||
return allComponents.reduce<ComponentSchema[]>(
|
||||
(result, component) => {
|
||||
const slotTrait = component.traits.find(trait => trait.type === 'core/v1/slot');
|
||||
const slotId = get(slotTrait, 'properties.container.id');
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
export type ChildrenMap = Map<string, SlotsMap>;
|
||||
type SlotsMap = Map<string, ApplicationComponent[]>;
|
||||
type SlotsMap = Map<string, ComponentSchema[]>;
|
||||
|
||||
export function resolveApplicationComponents(components: ApplicationComponent[]): {
|
||||
topLevelComponents: ApplicationComponent[];
|
||||
export function resolveApplicationComponents(components: ComponentSchema[]): {
|
||||
topLevelComponents: ComponentSchema[];
|
||||
childrenMap: ChildrenMap;
|
||||
} {
|
||||
const topLevelComponents: ApplicationComponent[] = [];
|
||||
const topLevelComponents: ComponentSchema[] = [];
|
||||
const childrenMap: ChildrenMap = new Map();
|
||||
components.forEach(c => {
|
||||
const slotTrait = c.traits.find(t => t.type === 'core/v1/slot');
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent, RuntimeComponentSpec } from '@sunmao-ui/core';
|
||||
import { ComponentSchema, RuntimeComponent } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime';
|
||||
import Ajv from 'ajv';
|
||||
import { AppModel } from '../AppModel/AppModel';
|
||||
@ -20,7 +20,7 @@ export class SchemaValidator implements ISchemaValidator {
|
||||
private allComponentsRules: AllComponentsValidatorRule[] = [];
|
||||
private componentIdSpecMap: Record<
|
||||
string,
|
||||
RuntimeComponentSpec<string, string, string, string>
|
||||
RuntimeComponent<string, string, string, string>
|
||||
> = {};
|
||||
private ajv!: Ajv;
|
||||
private validatorMap!: ValidatorMap;
|
||||
@ -46,7 +46,7 @@ export class SchemaValidator implements ISchemaValidator {
|
||||
});
|
||||
}
|
||||
|
||||
validate(components: ApplicationComponent[]) {
|
||||
validate(components: ComponentSchema[]) {
|
||||
const appModel = new AppModel(components);
|
||||
this.genComponentIdSpecMap(components);
|
||||
this.result = [];
|
||||
@ -90,7 +90,7 @@ export class SchemaValidator implements ISchemaValidator {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
genComponentIdSpecMap(components: ApplicationComponent[]) {
|
||||
genComponentIdSpecMap(components: ComponentSchema[]) {
|
||||
components.forEach(c => {
|
||||
this.componentIdSpecMap[c.id] = this.registry.getComponentByType(c.type);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime';
|
||||
import Ajv, { ValidateFunction } from 'ajv';
|
||||
import { IAppModel, IComponentModel, ITraitModel } from '../AppModel/IAppModel';
|
||||
@ -55,7 +55,7 @@ export type ValidatorRule =
|
||||
|
||||
export interface ISchemaValidator {
|
||||
addRules: (rule: ValidatorRule[]) => void;
|
||||
validate: (components: ApplicationComponent[]) => ValidateErrorResult[];
|
||||
validate: (components: ComponentSchema[]) => ValidateErrorResult[];
|
||||
fix?: () => void;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useRef } from 'react';
|
||||
import { initStateAndMethod } from './utils/initStateAndMethod';
|
||||
import { ImplWrapper } from './components/_internal/ImplWrapper';
|
||||
import { AppProps, UIServices } from './types/RuntimeSchema';
|
||||
import { AppProps, UIServices } from './types';
|
||||
import { DebugEvent, DebugStore } from './services/DebugComponents';
|
||||
import { RuntimeAppSchemaManager } from './services/RuntimeAppSchemaManager';
|
||||
import { resolveChildrenMap } from './utils/resolveChildrenMap';
|
||||
|
@ -1,18 +1,13 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { merge } from 'lodash-es';
|
||||
import { RuntimeComponentSchema, RuntimeTraitSchema } from '@sunmao-ui/core';
|
||||
import { watch } from '../../utils/watchReactivity';
|
||||
import {
|
||||
RuntimeApplicationComponent,
|
||||
ImplWrapperProps,
|
||||
TraitResult,
|
||||
} from '../../types/RuntimeSchema';
|
||||
} from '../../types';
|
||||
import { shallowCompareArray } from '../../utils/shallowCompareArray';
|
||||
|
||||
type ArrayElement<ArrayType extends readonly unknown[]> =
|
||||
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
||||
|
||||
type ApplicationTrait = ArrayElement<RuntimeApplicationComponent['traits']>;
|
||||
|
||||
const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props, ref) => {
|
||||
const {
|
||||
component: c,
|
||||
@ -23,7 +18,7 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
|
||||
childrenMap,
|
||||
} = props;
|
||||
const { registry, stateManager, globalHandlerMap, apiService } = props.services;
|
||||
const childrenCache = new Map<RuntimeApplicationComponent, React.ReactElement>();
|
||||
const childrenCache = new Map<RuntimeComponentSchema, React.ReactElement>();
|
||||
|
||||
const Impl = registry.getComponent(c.parsedType.version, c.parsedType.name).impl;
|
||||
|
||||
@ -65,7 +60,7 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
|
||||
);
|
||||
|
||||
const excecuteTrait = useCallback(
|
||||
(trait: ApplicationTrait, traitProperty: ApplicationTrait['properties']) => {
|
||||
(trait: RuntimeTraitSchema, traitProperty: RuntimeTraitSchema['properties']) => {
|
||||
const tImpl = registry.getTrait(
|
||||
trait.parsedType.version,
|
||||
trait.parsedType.name
|
||||
@ -91,7 +86,7 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
|
||||
// eval traits' properties then excecute traits
|
||||
useEffect(() => {
|
||||
const stops: ReturnType<typeof watch>[] = [];
|
||||
const properties: Array<ApplicationTrait['properties']> = [];
|
||||
const properties: Array<RuntimeTraitSchema['properties']> = [];
|
||||
c.traits.forEach((t, i) => {
|
||||
const { result, stop } = stateManager.deepEval(
|
||||
t.properties,
|
||||
|
@ -2,19 +2,19 @@ import { Static } from '@sinclair/typebox';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { get } from 'lodash-es';
|
||||
import { useDeepCompareMemo } from 'use-deep-compare';
|
||||
import { Application, parseType, RuntimeApplication } from '@sunmao-ui/core';
|
||||
import {
|
||||
UIServices,
|
||||
RuntimeModuleSchema,
|
||||
RuntimeApplicationComponent,
|
||||
} from '../../types/RuntimeSchema';
|
||||
import { EventHandlerSchema } from '../../types/TraitPropertiesSchema';
|
||||
Application,
|
||||
parseType,
|
||||
RuntimeApplication,
|
||||
RuntimeComponentSchema,
|
||||
} from '@sunmao-ui/core';
|
||||
import { UIServices, ModuleSchema } from '../../types';
|
||||
import { ImplWrapper } from './ImplWrapper';
|
||||
import { watch } from '../../utils/watchReactivity';
|
||||
import { ImplementedRuntimeModule } from '../../services/registry';
|
||||
import { ImplementedRuntimeModule, EventHandlerSchema } from '../../types';
|
||||
import { resolveChildrenMap } from '../../utils/resolveChildrenMap';
|
||||
|
||||
type Props = Static<typeof RuntimeModuleSchema> & {
|
||||
type Props = Static<typeof ModuleSchema> & {
|
||||
evalScope?: Record<string, any>;
|
||||
services: UIServices;
|
||||
app?: RuntimeApplication;
|
||||
@ -30,144 +30,141 @@ export const ModuleRenderer: React.FC<Props> = props => {
|
||||
}
|
||||
};
|
||||
|
||||
const ModuleRendererContent: React.FC<Props & { moduleSpec: ImplementedRuntimeModule }> =
|
||||
props => {
|
||||
const { moduleSpec, properties, handlers, evalScope, services, app } = props;
|
||||
const moduleId = services.stateManager.maskedEval(
|
||||
props.id,
|
||||
true,
|
||||
evalScope
|
||||
) as string;
|
||||
const ModuleRendererContent: React.FC<
|
||||
Props & { moduleSpec: ImplementedRuntimeModule }
|
||||
> = props => {
|
||||
const { moduleSpec, properties, handlers, evalScope, services, app } = props;
|
||||
const moduleId = services.stateManager.maskedEval(props.id, true, evalScope) as string;
|
||||
|
||||
function evalObject<T extends Record<string, any>>(obj: T): T {
|
||||
function evalObject<T extends Record<string, any>>(obj: T): T {
|
||||
return services.stateManager.mapValuesDeep({ obj }, ({ value }) => {
|
||||
if (typeof value === 'string') {
|
||||
return services.stateManager.maskedEval(value, true, evalScope);
|
||||
}
|
||||
return value;
|
||||
}).obj;
|
||||
}
|
||||
|
||||
const evalWithScope = useCallback(
|
||||
<T extends Record<string, any>>(obj: T, scope: Record<string, any>): T => {
|
||||
const hasScopeKey = (exp: string) => {
|
||||
return Object.keys(scope).some(key => exp.includes('{{') && exp.includes(key));
|
||||
};
|
||||
return services.stateManager.mapValuesDeep({ obj }, ({ value }) => {
|
||||
if (typeof value === 'string') {
|
||||
return services.stateManager.maskedEval(value, true, evalScope);
|
||||
if (typeof value === 'string' && hasScopeKey(value)) {
|
||||
return services.stateManager.maskedEval(value, true, scope);
|
||||
}
|
||||
return value;
|
||||
}).obj;
|
||||
},
|
||||
[services.stateManager]
|
||||
);
|
||||
|
||||
// first eval the property, handlers, id of module
|
||||
const evaledProperties = evalObject(properties);
|
||||
const evaledHanlders = evalObject(handlers);
|
||||
const parsedtemplete = useMemo(
|
||||
() => moduleSpec.impl.map(parseTypeComponents),
|
||||
[moduleSpec]
|
||||
);
|
||||
|
||||
// then eval the template and stateMap of module
|
||||
const evaledStateMap = useMemo(() => {
|
||||
// stateMap only use state i
|
||||
return evalWithScope(moduleSpec.spec.stateMap, { $moduleId: moduleId });
|
||||
}, [evalWithScope, moduleSpec.spec.stateMap, moduleId]);
|
||||
|
||||
const evaledModuleTemplate = useDeepCompareMemo(() => {
|
||||
// here should only eval with evaledProperties, any other key not in evaledProperties should be ignored
|
||||
// so we can asumme that template will not change if evaledProperties is the same
|
||||
return evalWithScope(parsedtemplete, {
|
||||
...evaledProperties,
|
||||
$moduleId: moduleId,
|
||||
});
|
||||
}, [parsedtemplete, evaledProperties, moduleId]);
|
||||
|
||||
// listen component state change
|
||||
useEffect(() => {
|
||||
if (!evaledStateMap) return;
|
||||
|
||||
const stops: ReturnType<typeof watch>[] = [];
|
||||
|
||||
if (!services.stateManager.store[moduleId]) {
|
||||
services.stateManager.store[moduleId] = {};
|
||||
}
|
||||
for (const stateKey in evaledStateMap) {
|
||||
// init state
|
||||
services.stateManager.store[moduleId][stateKey] = get(
|
||||
services.stateManager.store,
|
||||
evaledStateMap[stateKey]
|
||||
);
|
||||
// watch state
|
||||
const stop = watch(
|
||||
() => {
|
||||
return get(services.stateManager.store, evaledStateMap[stateKey]);
|
||||
},
|
||||
newV => {
|
||||
services.stateManager.store[moduleId] = {
|
||||
...services.stateManager.store[moduleId],
|
||||
[stateKey]: newV,
|
||||
};
|
||||
}
|
||||
);
|
||||
stops.push(stop);
|
||||
}
|
||||
|
||||
const evalWithScope = useCallback(
|
||||
<T extends Record<string, any>>(obj: T, scope: Record<string, any>): T => {
|
||||
const hasScopeKey = (exp: string) => {
|
||||
return Object.keys(scope).some(key => exp.includes('{{') && exp.includes(key));
|
||||
};
|
||||
return services.stateManager.mapValuesDeep({ obj }, ({ value }) => {
|
||||
if (typeof value === 'string' && hasScopeKey(value)) {
|
||||
return services.stateManager.maskedEval(value, true, scope);
|
||||
}
|
||||
return value;
|
||||
}).obj;
|
||||
},
|
||||
[services.stateManager]
|
||||
);
|
||||
return () => {
|
||||
stops.forEach(s => s());
|
||||
};
|
||||
}, [evaledStateMap, moduleId, services]);
|
||||
|
||||
// first eval the property, handlers, id of module
|
||||
const evaledProperties = evalObject(properties);
|
||||
const evaledHanlders = evalObject(handlers);
|
||||
const parsedtemplete = useMemo(
|
||||
() => moduleSpec.impl.map(parseTypeComponents),
|
||||
[moduleSpec]
|
||||
);
|
||||
|
||||
// then eval the template and stateMap of module
|
||||
const evaledStateMap = useMemo(() => {
|
||||
// stateMap only use state i
|
||||
return evalWithScope(moduleSpec.spec.stateMap, { $moduleId: moduleId });
|
||||
}, [evalWithScope, moduleSpec.spec.stateMap, moduleId]);
|
||||
|
||||
const evaledModuleTemplate = useDeepCompareMemo(() => {
|
||||
// here should only eval with evaledProperties, any other key not in evaledProperties should be ignored
|
||||
// so we can asumme that template will not change if evaledProperties is the same
|
||||
return evalWithScope(parsedtemplete, {
|
||||
...evaledProperties,
|
||||
$moduleId: moduleId,
|
||||
});
|
||||
}, [parsedtemplete, evaledProperties, moduleId]);
|
||||
|
||||
// listen component state change
|
||||
useEffect(() => {
|
||||
if (!evaledStateMap) return;
|
||||
|
||||
const stops: ReturnType<typeof watch>[] = [];
|
||||
|
||||
if (!services.stateManager.store[moduleId]) {
|
||||
services.stateManager.store[moduleId] = {};
|
||||
}
|
||||
for (const stateKey in evaledStateMap) {
|
||||
// init state
|
||||
services.stateManager.store[moduleId][stateKey] = get(
|
||||
services.stateManager.store,
|
||||
evaledStateMap[stateKey]
|
||||
);
|
||||
// watch state
|
||||
const stop = watch(
|
||||
() => {
|
||||
return get(services.stateManager.store, evaledStateMap[stateKey]);
|
||||
},
|
||||
newV => {
|
||||
services.stateManager.store[moduleId] = {
|
||||
...services.stateManager.store[moduleId],
|
||||
[stateKey]: newV,
|
||||
};
|
||||
}
|
||||
);
|
||||
stops.push(stop);
|
||||
}
|
||||
|
||||
return () => {
|
||||
stops.forEach(s => s());
|
||||
// listen module event
|
||||
useEffect(() => {
|
||||
if (!evaledHanlders) return;
|
||||
const _handlers = evaledHanlders as Array<Static<typeof EventHandlerSchema>>;
|
||||
const moduleEventHanlders: any[] = [];
|
||||
_handlers.forEach(h => {
|
||||
const moduleEventHanlder = ({ fromId, eventType }: Record<string, string>) => {
|
||||
if (eventType === h.type && fromId === moduleId) {
|
||||
services.apiService.send('uiMethod', {
|
||||
componentId: h.componentId,
|
||||
name: h.method.name,
|
||||
parameters: h.method.parameters,
|
||||
});
|
||||
}
|
||||
};
|
||||
}, [evaledStateMap, moduleId, services]);
|
||||
services.apiService.on('moduleEvent', moduleEventHanlder);
|
||||
moduleEventHanlders.push(moduleEventHanlder);
|
||||
});
|
||||
|
||||
// listen module event
|
||||
useEffect(() => {
|
||||
if (!evaledHanlders) return;
|
||||
const _handlers = evaledHanlders as Array<Static<typeof EventHandlerSchema>>;
|
||||
const moduleEventHanlders: any[] = [];
|
||||
_handlers.forEach(h => {
|
||||
const moduleEventHanlder = ({ fromId, eventType }: Record<string, string>) => {
|
||||
if (eventType === h.type && fromId === moduleId) {
|
||||
services.apiService.send('uiMethod', {
|
||||
componentId: h.componentId,
|
||||
name: h.method.name,
|
||||
parameters: h.method.parameters,
|
||||
});
|
||||
}
|
||||
};
|
||||
services.apiService.on('moduleEvent', moduleEventHanlder);
|
||||
moduleEventHanlders.push(moduleEventHanlder);
|
||||
return () => {
|
||||
moduleEventHanlders.forEach(h => {
|
||||
services.apiService.off('moduleEvent', h);
|
||||
});
|
||||
};
|
||||
}, [evaledHanlders, moduleId, services.apiService]);
|
||||
|
||||
return () => {
|
||||
moduleEventHanlders.forEach(h => {
|
||||
services.apiService.off('moduleEvent', h);
|
||||
});
|
||||
};
|
||||
}, [evaledHanlders, moduleId, services.apiService]);
|
||||
const result = useMemo(() => {
|
||||
const { childrenMap, topLevelComponents } = resolveChildrenMap(evaledModuleTemplate);
|
||||
return topLevelComponents.map(c => {
|
||||
return (
|
||||
<ImplWrapper
|
||||
key={c.id}
|
||||
component={c}
|
||||
services={services}
|
||||
app={app}
|
||||
childrenMap={childrenMap}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}, [evaledModuleTemplate, services, app]);
|
||||
|
||||
const result = useMemo(() => {
|
||||
const { childrenMap, topLevelComponents } = resolveChildrenMap(evaledModuleTemplate);
|
||||
return topLevelComponents.map(c => {
|
||||
return (
|
||||
<ImplWrapper
|
||||
key={c.id}
|
||||
component={c}
|
||||
services={services}
|
||||
app={app}
|
||||
childrenMap={childrenMap}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}, [evaledModuleTemplate, services, app]);
|
||||
|
||||
return <>{result}</>;
|
||||
};
|
||||
return <>{result}</>;
|
||||
};
|
||||
|
||||
function parseTypeComponents(
|
||||
c: Application['spec']['components'][0]
|
||||
): RuntimeApplicationComponent {
|
||||
): RuntimeComponentSchema {
|
||||
return {
|
||||
...c,
|
||||
parsedType: parseType(c.type),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { implementRuntimeComponent } from '../../utils/buildKit';
|
||||
import { RuntimeModuleSchema } from '../../types/RuntimeSchema';
|
||||
import { ModuleSchema } from '../../types';
|
||||
import { ModuleRenderer } from '../_internal/ModuleRenderer';
|
||||
|
||||
export default implementRuntimeComponent({
|
||||
@ -17,7 +17,7 @@ export default implementRuntimeComponent({
|
||||
exampleSize: [6, 6],
|
||||
},
|
||||
spec: {
|
||||
properties: RuntimeModuleSchema,
|
||||
properties: ModuleSchema,
|
||||
state: {},
|
||||
methods: {},
|
||||
slots: [],
|
||||
|
@ -22,10 +22,10 @@ import {
|
||||
useNavigate,
|
||||
} from './hooks';
|
||||
import {
|
||||
RuntimeApplicationComponent,
|
||||
UIServices,
|
||||
ChildrenMap,
|
||||
} from '../../../types/RuntimeSchema';
|
||||
} from '../../../types';
|
||||
import { RuntimeComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
export type RouteLikeElement = PropsWithChildren<{
|
||||
path?: string;
|
||||
@ -63,7 +63,7 @@ export const Route: React.FC<RouteProps> = ({ match, children, mergeState }) =>
|
||||
type SwitchProps = {
|
||||
location?: string;
|
||||
switchPolicy: SwitchPolicy;
|
||||
component: RuntimeApplicationComponent;
|
||||
component: RuntimeComponentSchema;
|
||||
childrenMap: ChildrenMap<string>;
|
||||
services: UIServices;
|
||||
slotsElements: Record<string, ReactElement[]>;
|
||||
|
@ -25,7 +25,7 @@ export function initSunmaoUI(dependencies = {}) {
|
||||
export * from './utils/parseTypeBox';
|
||||
export * from './utils/buildKit';
|
||||
export * from './utils/encodeDragDataTransfer';
|
||||
export * from './types/RuntimeSchema';
|
||||
export * from './types';
|
||||
export * from './types/TraitPropertiesSchema';
|
||||
export * from './constants';
|
||||
export * from './services/registry';
|
||||
|
@ -1,15 +1,15 @@
|
||||
import {
|
||||
Application,
|
||||
ApplicationComponent,
|
||||
ComponentSchema,
|
||||
RuntimeApplication,
|
||||
isValidId,
|
||||
parseType,
|
||||
parseVersion,
|
||||
RuntimeComponentSchema,
|
||||
} from '@sunmao-ui/core';
|
||||
import { RuntimeApplicationComponent } from '../types/RuntimeSchema';
|
||||
export class RuntimeAppSchemaManager {
|
||||
private runtimeComponentsCache: Record<string, RuntimeApplicationComponent> = {};
|
||||
private componentsCache: Record<string, ApplicationComponent> = {};
|
||||
private runtimeComponentsCache: Record<string, RuntimeComponentSchema> = {};
|
||||
private componentsCache: Record<string, ComponentSchema> = {};
|
||||
|
||||
update(schema: Application): RuntimeApplication {
|
||||
return {
|
||||
@ -25,7 +25,7 @@ export class RuntimeAppSchemaManager {
|
||||
};
|
||||
}
|
||||
|
||||
genComponent(component: ApplicationComponent): RuntimeApplicationComponent {
|
||||
genComponent(component: ComponentSchema): RuntimeComponentSchema {
|
||||
const componentInCache = this.componentsCache[component.id];
|
||||
if (componentInCache && componentInCache === component) {
|
||||
return this.runtimeComponentsCache[component.id];
|
||||
@ -33,7 +33,7 @@ export class RuntimeAppSchemaManager {
|
||||
if (!isValidId(component.id)) {
|
||||
throw new Error(`Invalid id: "${component.id}"`);
|
||||
}
|
||||
const componentSchema: RuntimeApplicationComponent = {
|
||||
const componentSchema: RuntimeComponentSchema = {
|
||||
...component,
|
||||
parsedType: parseType(component.type),
|
||||
traits: component.traits.map(t => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
type HandlerMap = Record<string, (parameters?: any) => void>;
|
||||
|
||||
export type GlobalHandlerMap = ReturnType<typeof initGlobalHandlerMap>;
|
||||
export type GlobalHandlerMap = Map<string, HandlerMap>;
|
||||
|
||||
export function initGlobalHandlerMap() {
|
||||
return new Map<string, HandlerMap>();
|
||||
|
@ -1,10 +1,4 @@
|
||||
import {
|
||||
RuntimeTraitSpec,
|
||||
RuntimeModuleSpec,
|
||||
ApplicationComponent,
|
||||
RuntimeComponentSpec,
|
||||
parseType,
|
||||
} from '@sunmao-ui/core';
|
||||
import { parseType } from '@sunmao-ui/core';
|
||||
// components
|
||||
/* --- plain --- */
|
||||
import PlainButton from '../components/plain/Button';
|
||||
@ -24,40 +18,13 @@ import CoreHidden from '../traits/core/hidden';
|
||||
import CoreFetch from '../traits/core/fetch';
|
||||
import CoreValidation from '../traits/core/validation';
|
||||
import {
|
||||
ComponentImplementationProps,
|
||||
TraitImplementation,
|
||||
} from '../types/RuntimeSchema';
|
||||
ImplementedRuntimeComponent,
|
||||
ImplementedRuntimeTrait,
|
||||
ImplementedRuntimeModule,
|
||||
} from '../types';
|
||||
import { parseModuleSchema } from '../utils/parseModuleSchema';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
export type ImplementedRuntimeComponent<
|
||||
KMethodName extends string,
|
||||
KStyleSlot extends string,
|
||||
KSlot extends string,
|
||||
KEvent extends string
|
||||
> = RuntimeComponentSpec<KMethodName, KStyleSlot, KSlot, KEvent> & {
|
||||
impl: ComponentImplementation;
|
||||
};
|
||||
|
||||
export type ComponentImplementation<
|
||||
TProps = any,
|
||||
TState = any,
|
||||
TMethods = Record<string, any>,
|
||||
KSlot extends string = string,
|
||||
KStyleSlot extends string = string,
|
||||
KEvent extends string = string
|
||||
> = React.FC<
|
||||
TProps & ComponentImplementationProps<TState, TMethods, KSlot, KStyleSlot, KEvent>
|
||||
>;
|
||||
|
||||
export type ImplementedRuntimeTrait = RuntimeTraitSpec & {
|
||||
impl: TraitImplementation;
|
||||
};
|
||||
|
||||
export type ImplementedRuntimeModule = RuntimeModuleSpec & {
|
||||
impl: ApplicationComponent[];
|
||||
};
|
||||
|
||||
export type SunmaoLib = {
|
||||
components?: ImplementedRuntimeComponent<string, string, string, string>[];
|
||||
traits?: ImplementedRuntimeTrait[];
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { TraitImpl } from '../../types';
|
||||
|
||||
const HasInitializedMap = new Map<string, boolean>();
|
||||
|
||||
type KeyValue = { key: string; value: unknown };
|
||||
|
||||
const ArrayStateTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
const ArrayStateTrait: TraitImpl<Static<typeof PropsSchema>> = ({
|
||||
key,
|
||||
initialValue,
|
||||
componentId,
|
||||
@ -130,6 +130,7 @@ export default {
|
||||
name: 'reset',
|
||||
},
|
||||
],
|
||||
state: {},
|
||||
},
|
||||
}),
|
||||
impl: ArrayStateTrait,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { debounce, throttle, delay } from 'lodash-es';
|
||||
import { CallbackMap, TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { CallbackMap, TraitImpl } from '../../types';
|
||||
import { EventHandlerSchema } from '../../types/TraitPropertiesSchema';
|
||||
|
||||
const useEventTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
const useEventTrait: TraitImpl<Static<typeof PropsSchema>> = ({
|
||||
handlers,
|
||||
services,
|
||||
}) => {
|
||||
@ -77,6 +77,8 @@ export default {
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSchema,
|
||||
methods: [],
|
||||
state: {},
|
||||
},
|
||||
}),
|
||||
impl: useEventTrait,
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { TraitImpl } from '../../types';
|
||||
import { FetchTraitPropertiesSchema } from '../../types/TraitPropertiesSchema';
|
||||
|
||||
const hasFetchedMap = new Map<string, boolean>();
|
||||
|
||||
const useFetchTrait: TraitImplementation<Static<typeof FetchTraitPropertiesSchema>> = ({
|
||||
const useFetchTrait: TraitImpl<Static<typeof FetchTraitPropertiesSchema>> = ({
|
||||
url,
|
||||
method,
|
||||
lazy: _lazy,
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { TraitImpl } from '../../types';
|
||||
|
||||
const useHiddenTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
const useHiddenTrait: TraitImpl<Static<typeof PropsSchema>> = ({
|
||||
hidden,
|
||||
visually,
|
||||
}) => {
|
||||
@ -36,6 +36,8 @@ export default {
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSchema,
|
||||
state: {},
|
||||
methods: [],
|
||||
},
|
||||
}),
|
||||
impl: useHiddenTrait,
|
||||
|
@ -19,6 +19,8 @@ export default {
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSchema,
|
||||
state: {},
|
||||
methods: [],
|
||||
},
|
||||
}),
|
||||
impl: () => ({
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { TraitImpl } from '../../types';
|
||||
|
||||
const HasInitializedMap = new Map<string, boolean>();
|
||||
|
||||
type KeyValue = { key: string; value: unknown };
|
||||
|
||||
const useStateTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
const useStateTrait: TraitImpl<Static<typeof PropsSchema>> = ({
|
||||
key,
|
||||
initialValue,
|
||||
componentId,
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { TraitImpl } from '../../types';
|
||||
|
||||
const StyleTrait: TraitImplementation<Static<typeof PropsSchema>> = ({ styles }) => {
|
||||
const StyleTrait: TraitImpl<Static<typeof PropsSchema>> = ({ styles }) => {
|
||||
const customStyle: Record<string, string> = {};
|
||||
styles.forEach(style => {
|
||||
customStyle[style.styleSlot] = style.style;
|
||||
@ -32,6 +32,8 @@ export default {
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSchema,
|
||||
methods: [],
|
||||
state: {},
|
||||
},
|
||||
}),
|
||||
impl: StyleTrait,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createTrait } from '@sunmao-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { TraitImplementation } from '../../types/RuntimeSchema';
|
||||
import { TraitImpl } from '../../types';
|
||||
import { ValidResultSchema } from '../../types/ValidResultSchema';
|
||||
|
||||
type ValidationResult = Static<typeof ValidResultSchema>;
|
||||
@ -43,7 +43,7 @@ addValidationRule('phoneNumber', text => {
|
||||
|
||||
const ValidationResultCache: Record<string, ValidationResult> = {};
|
||||
|
||||
const ValidationTraitImpl: TraitImplementation<Static<typeof PropsSchema>> = props => {
|
||||
const ValidationTraitImpl: TraitImpl<Static<typeof PropsSchema>> = props => {
|
||||
const { value, minLength, maxLength, mergeState, componentId, rule } = props;
|
||||
|
||||
const result: ValidationResult = {
|
||||
@ -103,6 +103,7 @@ export default {
|
||||
state: Type.Object({
|
||||
validResult: ValidResultSchema,
|
||||
}),
|
||||
methods: [],
|
||||
},
|
||||
}),
|
||||
impl: ValidationTraitImpl,
|
||||
|
38
packages/runtime/src/types/Application.ts
Normal file
38
packages/runtime/src/types/Application.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import RGL from 'react-grid-layout';
|
||||
import { ApiService } from '../services/apiService';
|
||||
import { GlobalHandlerMap } from '../services/handler';
|
||||
import { Registry } from '../services/registry';
|
||||
import { StateManager } from '../services/stateStore';
|
||||
import { Application, RuntimeComponentSchema } from '@sunmao-ui/core';
|
||||
import React from 'react';
|
||||
|
||||
export type UIServices = {
|
||||
registry: Registry;
|
||||
stateManager: StateManager;
|
||||
globalHandlerMap: GlobalHandlerMap;
|
||||
apiService: ApiService;
|
||||
};
|
||||
|
||||
export type ComponentWrapperProps = {
|
||||
parentType: string;
|
||||
component: RuntimeComponentSchema;
|
||||
};
|
||||
|
||||
export type ComponentWrapperType = React.FC<ComponentWrapperProps>;
|
||||
|
||||
export type GridCallbacks = {
|
||||
onDragStop?: (id: string, layout: RGL.Layout[]) => void;
|
||||
onDrop?: (id: string, layout: RGL.Layout[], item: RGL.Layout, event: DragEvent) => void;
|
||||
};
|
||||
|
||||
export type ComponentParamsFromApp = {
|
||||
gridCallbacks?: GridCallbacks;
|
||||
componentWrapper?: ComponentWrapperType;
|
||||
};
|
||||
|
||||
export type AppProps = {
|
||||
options: Application;
|
||||
services: UIServices;
|
||||
debugStore?: boolean;
|
||||
debugEvent?: boolean;
|
||||
} & ComponentParamsFromApp;
|
64
packages/runtime/src/types/Component.ts
Normal file
64
packages/runtime/src/types/Component.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import {
|
||||
RuntimeApplication,
|
||||
RuntimeComponentSchema,
|
||||
RuntimeComponent,
|
||||
} from '@sunmao-ui/core';
|
||||
import React from 'react';
|
||||
import { UIServices, ComponentParamsFromApp } from './Application';
|
||||
import { TraitResult } from './Trait';
|
||||
|
||||
// TODO: (type-safe), remove fallback type
|
||||
export type ImplWrapperProps<KSlot extends string = string> = {
|
||||
component: RuntimeComponentSchema;
|
||||
childrenMap: ChildrenMap<KSlot>;
|
||||
services: UIServices;
|
||||
app?: RuntimeApplication;
|
||||
} & ComponentParamsFromApp;
|
||||
|
||||
export type ComponentImplProps<
|
||||
TState,
|
||||
TMethods,
|
||||
KSlot extends string,
|
||||
KStyleSlot extends string,
|
||||
KEvent extends string
|
||||
> = ImplWrapperProps<KSlot> &
|
||||
TraitResult<KStyleSlot, KEvent>['props'] &
|
||||
RuntimeFunctions<TState, TMethods> & {
|
||||
slotsElements: Record<KSlot, React.ReactElement[]>;
|
||||
};
|
||||
|
||||
export type ComponentImpl<
|
||||
TProps = any,
|
||||
TState = any,
|
||||
TMethods = Record<string, any>,
|
||||
KSlot extends string = string,
|
||||
KStyleSlot extends string = string,
|
||||
KEvent extends string = string
|
||||
> = React.FC<TProps & ComponentImplProps<TState, TMethods, KSlot, KStyleSlot, KEvent>>;
|
||||
|
||||
export type ImplementedRuntimeComponent<
|
||||
KMethodName extends string,
|
||||
KStyleSlot extends string,
|
||||
KSlot extends string,
|
||||
KEvent extends string
|
||||
> = RuntimeComponent<KMethodName, KStyleSlot, KSlot, KEvent> & {
|
||||
impl: ComponentImpl;
|
||||
};
|
||||
|
||||
export type ChildrenMap<KSlot extends string> = Record<
|
||||
string,
|
||||
Record<KSlot, RuntimeComponentSchema[]> & {
|
||||
_grandChildren?: RuntimeComponentSchema[];
|
||||
_allChildren: RuntimeComponentSchema[];
|
||||
}
|
||||
>;
|
||||
|
||||
type SubscribeMethods<U> = (map: {
|
||||
[K in keyof U]: (parameters: U[K]) => void;
|
||||
}) => void;
|
||||
type MergeState<T> = (partialState: Partial<T>) => void;
|
||||
|
||||
export type RuntimeFunctions<TState, TMethods> = {
|
||||
mergeState: MergeState<TState>;
|
||||
subscribeMethods: SubscribeMethods<TMethods>;
|
||||
};
|
14
packages/runtime/src/types/Module.ts
Normal file
14
packages/runtime/src/types/Module.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { EventHandlerSchema } from './TraitPropertiesSchema';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { ComponentSchema, RuntimeModule } from '@sunmao-ui/core';
|
||||
|
||||
export const ModuleSchema = Type.Object({
|
||||
id: Type.String(),
|
||||
type: Type.String(),
|
||||
properties: Type.Record(Type.String(), Type.Any()),
|
||||
handlers: Type.Array(EventHandlerSchema),
|
||||
});
|
||||
|
||||
export type ImplementedRuntimeModule = RuntimeModule & {
|
||||
impl: ComponentSchema[];
|
||||
};
|
@ -1,107 +0,0 @@
|
||||
import RGL from 'react-grid-layout';
|
||||
import { ApiService } from '../services/apiService';
|
||||
import { GlobalHandlerMap } from '../services/handler';
|
||||
import { Registry } from '../services/registry';
|
||||
import { StateManager } from '../services/stateStore';
|
||||
import { Application, RuntimeApplication } from '@sunmao-ui/core';
|
||||
import { EventHandlerSchema } from './TraitPropertiesSchema';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import React from 'react';
|
||||
|
||||
export type RuntimeApplicationComponent = RuntimeApplication['spec']['components'][0];
|
||||
|
||||
export type UIServices = {
|
||||
registry: Registry;
|
||||
stateManager: StateManager;
|
||||
globalHandlerMap: GlobalHandlerMap;
|
||||
apiService: ApiService;
|
||||
};
|
||||
|
||||
export type ComponentWrapperProps = {
|
||||
parentType: string;
|
||||
component: RuntimeApplicationComponent;
|
||||
};
|
||||
|
||||
export type ComponentWrapperType = React.FC<ComponentWrapperProps>;
|
||||
|
||||
export type GridCallbacks = {
|
||||
onDragStop?: (id: string, layout: RGL.Layout[]) => void;
|
||||
onDrop?: (id: string, layout: RGL.Layout[], item: RGL.Layout, event: DragEvent) => void;
|
||||
};
|
||||
|
||||
export type ComponentParamsFromApp = {
|
||||
gridCallbacks?: GridCallbacks;
|
||||
componentWrapper?: ComponentWrapperType;
|
||||
};
|
||||
|
||||
export type AppProps = {
|
||||
options: Application;
|
||||
services: UIServices;
|
||||
debugStore?: boolean;
|
||||
debugEvent?: boolean;
|
||||
} & ComponentParamsFromApp;
|
||||
|
||||
// TODO: (type-safe), remove fallback type
|
||||
export type ImplWrapperProps<KSlot extends string = string> = {
|
||||
component: RuntimeApplicationComponent;
|
||||
childrenMap: ChildrenMap<KSlot>;
|
||||
services: UIServices;
|
||||
app?: RuntimeApplication;
|
||||
} & ComponentParamsFromApp;
|
||||
|
||||
export type ChildrenMap<KSlot extends string> = Record<
|
||||
string,
|
||||
Record<KSlot, RuntimeApplicationComponent[]> & {
|
||||
_grandChildren?: RuntimeApplicationComponent[];
|
||||
_allChildren: RuntimeApplicationComponent[];
|
||||
}
|
||||
>;
|
||||
|
||||
export type CallbackMap<K extends string> = Record<K, () => void>;
|
||||
|
||||
export type SubscribeMethods<U> = (map: {
|
||||
[K in keyof U]: (parameters: U[K]) => void;
|
||||
}) => void;
|
||||
export type MergeState<T> = (partialState: Partial<T>) => void;
|
||||
|
||||
type RuntimeFunctions<TState, TMethods> = {
|
||||
mergeState: MergeState<TState>;
|
||||
subscribeMethods: SubscribeMethods<TMethods>;
|
||||
};
|
||||
|
||||
export type ComponentImplementationProps<
|
||||
TState,
|
||||
TMethods,
|
||||
KSlot extends string,
|
||||
KStyleSlot extends string,
|
||||
KEvent extends string
|
||||
> = ImplWrapperProps<KSlot> &
|
||||
TraitResult<KStyleSlot, KEvent>['props'] &
|
||||
RuntimeFunctions<TState, TMethods> & {
|
||||
slotsElements: Record<KSlot, React.ReactElement[]>
|
||||
};
|
||||
|
||||
export type TraitResult<KStyleSlot extends string, KEvent extends string> = {
|
||||
props: {
|
||||
data?: unknown;
|
||||
customStyle?: Record<KStyleSlot, string>;
|
||||
callbackMap?: CallbackMap<KEvent>;
|
||||
effects?: Array<() => void>;
|
||||
} | null;
|
||||
unmount?: boolean;
|
||||
};
|
||||
|
||||
export type TraitImplementation<T = any> = (
|
||||
props: T &
|
||||
RuntimeFunctions<unknown, unknown> & {
|
||||
componentId: string;
|
||||
services: UIServices;
|
||||
}
|
||||
) => TraitResult<string, string>;
|
||||
|
||||
export const RuntimeModuleSchema = Type.Object({
|
||||
id: Type.String(),
|
||||
type: Type.String(),
|
||||
properties: Type.Record(Type.String(), Type.Any()),
|
||||
handlers: Type.Array(EventHandlerSchema),
|
||||
});
|
27
packages/runtime/src/types/Trait.ts
Normal file
27
packages/runtime/src/types/Trait.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { RuntimeTrait } from '@sunmao-ui/core';
|
||||
import { UIServices } from './Application';
|
||||
import { RuntimeFunctions } from './Component';
|
||||
|
||||
export type TraitResult<KStyleSlot extends string, KEvent extends string> = {
|
||||
props: {
|
||||
data?: unknown;
|
||||
customStyle?: Record<KStyleSlot, string>;
|
||||
callbackMap?: CallbackMap<KEvent>;
|
||||
effects?: Array<() => void>;
|
||||
} | null;
|
||||
unmount?: boolean;
|
||||
};
|
||||
|
||||
export type TraitImpl<T = any> = (
|
||||
props: T &
|
||||
RuntimeFunctions<unknown, unknown> & {
|
||||
componentId: string;
|
||||
services: UIServices;
|
||||
}
|
||||
) => TraitResult<string, string>;
|
||||
|
||||
export type ImplementedRuntimeTrait = RuntimeTrait & {
|
||||
impl: TraitImpl;
|
||||
};
|
||||
|
||||
export type CallbackMap<K extends string> = Record<K, () => void>;
|
6
packages/runtime/src/types/index.ts
Normal file
6
packages/runtime/src/types/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export * from './Application';
|
||||
export * from './Component';
|
||||
export * from './Trait';
|
||||
export * from './Module';
|
||||
export * from './TraitPropertiesSchema';
|
||||
export * from './ValidResultSchema';
|
@ -1,9 +1,6 @@
|
||||
import { Static } from '@sinclair/typebox';
|
||||
import { createComponent, CreateComponentOptions } from '@sunmao-ui/core';
|
||||
import {
|
||||
ComponentImplementation,
|
||||
ImplementedRuntimeComponent,
|
||||
} from '../services/registry';
|
||||
import { ComponentImpl, ImplementedRuntimeComponent } from '../types';
|
||||
|
||||
type ToMap<U> = {
|
||||
[K in keyof U]: Static<U[K]>;
|
||||
@ -20,7 +17,7 @@ export function implementRuntimeComponent<
|
||||
>(
|
||||
options: T
|
||||
): (
|
||||
impl: ComponentImplementation<
|
||||
impl: ComponentImpl<
|
||||
Static<T['spec']['properties']>,
|
||||
Static<T['spec']['state']>,
|
||||
ToMap<T['spec']['methods']>,
|
||||
|
@ -2,7 +2,7 @@ import { RuntimeApplication } from '@sunmao-ui/core';
|
||||
import { Static, TSchema } from '@sinclair/typebox';
|
||||
import { Registry } from '../services/registry';
|
||||
import { StateManager } from '../services/stateStore';
|
||||
import { RuntimeModuleSchema } from '../types/RuntimeSchema';
|
||||
import { ModuleSchema } from '../types';
|
||||
import { parseTypeBox } from './parseTypeBox';
|
||||
|
||||
export function initStateAndMethod(
|
||||
@ -25,7 +25,7 @@ export function initStateAndMethod(
|
||||
stateManager.store[c.id] = state;
|
||||
|
||||
if (c.type === 'core/v1/moduleContainer') {
|
||||
const moduleSchema = c.properties as Static<typeof RuntimeModuleSchema>;
|
||||
const moduleSchema = c.properties as Static<typeof ModuleSchema>;
|
||||
try {
|
||||
const mSpec = registry.getModuleByType(moduleSchema.type).spec;
|
||||
const moduleInitState: Record<string, unknown> = {};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ImplementedRuntimeModule } from '../services/registry';
|
||||
import { ImplementedRuntimeModule } from '../types';
|
||||
|
||||
// add {{$moduleId}} in moduleSchema
|
||||
export function parseModuleSchema(
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { RuntimeApplicationComponent, ChildrenMap } from '../types/RuntimeSchema';
|
||||
import { RuntimeComponentSchema } from '@sunmao-ui/core';
|
||||
import { ChildrenMap } from '../types';
|
||||
|
||||
export function resolveChildrenMap(components: RuntimeApplicationComponent[]): {
|
||||
export function resolveChildrenMap(components: RuntimeComponentSchema[]): {
|
||||
childrenMap: ChildrenMap<string>;
|
||||
topLevelComponents: RuntimeApplicationComponent[];
|
||||
topLevelComponents: RuntimeComponentSchema[];
|
||||
} {
|
||||
const childrenMap: ChildrenMap<string> = {};
|
||||
const topLevelComponents: RuntimeApplicationComponent[] = [];
|
||||
const topLevelComponents: RuntimeComponentSchema[] = [];
|
||||
|
||||
for (const c of components) {
|
||||
const slotTrait = c.traits.find(t => t.parsedType.name === 'slot');
|
||||
@ -28,7 +29,7 @@ export function resolveChildrenMap(components: RuntimeApplicationComponent[]): {
|
||||
}
|
||||
|
||||
// get allChildren and grand children
|
||||
function getAllChildren(id: string): RuntimeApplicationComponent[] {
|
||||
function getAllChildren(id: string): RuntimeComponentSchema[] {
|
||||
if (!childrenMap[id]) {
|
||||
return [];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user