diff --git a/packages/runtime/src/components/core/Watcher.ts b/packages/runtime/src/components/core/Watcher.ts new file mode 100644 index 000000000..91f5ae6bf --- /dev/null +++ b/packages/runtime/src/components/core/Watcher.ts @@ -0,0 +1,52 @@ +import { Type } from '@sinclair/typebox'; +import { + CORE_VERSION_V2, + CoreComponentName, + PRESET_PROPERTY_CATEGORY, +} from '@sunmao-ui/shared'; +import { implementRuntimeComponent } from '../../utils/buildKit'; +import { useEffect } from 'react'; +import { watch } from '../..'; + +export default implementRuntimeComponent({ + version: CORE_VERSION_V2, + metadata: { + name: CoreComponentName.Watcher, + displayName: 'Watcher', + description: 'Watch expression changing and trigger events', + exampleProperties: { exp: '' }, + isDataSource: true, + annotations: { + category: 'Data', + }, + }, + spec: { + properties: Type.Object({ + exp: Type.String({ + title: 'Expression', + category: PRESET_PROPERTY_CATEGORY.Basic, + }), + }), + state: Type.Object({ value: Type.Any() }), + methods: {}, + slots: {}, + styleSlots: [], + events: ['onChange'], + }, +})(({ component, services, mergeState, callbackMap }) => { + useEffect(() => { + const stop = watch( + () => { + const v = services.stateManager.deepEval(component.properties.exp, {}); + return v; + }, + newV => { + mergeState({ value: newV }); + callbackMap?.onChange(); + } + ); + + return stop; + }, [callbackMap, component.properties.exp, mergeState, services.stateManager]); + return null; +}); diff --git a/packages/runtime/src/services/Registry.tsx b/packages/runtime/src/services/Registry.tsx index 5491eb597..728d781fb 100644 --- a/packages/runtime/src/services/Registry.tsx +++ b/packages/runtime/src/services/Registry.tsx @@ -11,6 +11,7 @@ import CoreStack from '../components/core/Stack'; import CoreFileInput from '../components/core/FileInput'; import CoreList from '../components/core/List'; import CoreIframe from '../components/core/Iframe'; +import CoreWatcher from '../components/core/Watcher'; // traits import CoreArrayState from '../traits/core/ArrayState'; @@ -257,6 +258,7 @@ export function initRegistry( registry.registerComponent(CoreFileInput); registry.registerComponent(CoreList); registry.registerComponent(CoreIframe); + registry.registerComponent(CoreWatcher); registry.registerTrait(CoreState); registry.registerTrait(CoreArrayState); diff --git a/packages/shared/src/constants/core.ts b/packages/shared/src/constants/core.ts index 1e8ef397d..b33c9a954 100644 --- a/packages/shared/src/constants/core.ts +++ b/packages/shared/src/constants/core.ts @@ -7,6 +7,7 @@ export enum CoreComponentName { ModuleContainer = 'moduleContainer', Text = 'text', Iframe = 'iframe', + Watcher = 'watcher', } // core traits export enum CoreTraitName {