From 4072b03b3b56e54387fb9ce9755323d74b3c658c Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 8 Oct 2024 16:09:44 +0800 Subject: [PATCH] * core: support for using commands in HElement. --- lib/core/src/react/components/h-element.ts | 41 ++++++++++++++++++++- lib/core/src/react/types/h-element-props.ts | 11 ++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/core/src/react/components/h-element.ts b/lib/core/src/react/components/h-element.ts index 70314fca6e..735d474cc0 100644 --- a/lib/core/src/react/components/h-element.ts +++ b/lib/core/src/react/components/h-element.ts @@ -3,11 +3,13 @@ import {nextGid} from '../../helpers/gid'; import {classes} from '../../helpers/classes'; import {getReactComponent} from './components'; import {i18n} from '../../i18n'; +import {bindCommands, unbindCommands, type CommandContext} from '../../helpers'; import type {JSX, ComponentType, RenderableProps, ComponentChildren} from 'preact'; import type {ClassNameLike} from '../../helpers/classes'; import type {HElementProps} from '../types'; import type {I18nLangMap} from '../../i18n'; +import {deepCall} from '@zui/helpers/src/object'; /** * The base HTML element. @@ -60,6 +62,13 @@ export class HElement

extends Component { return [this.props.i18n, this.constructor.i18n]; } + /** + * Get the command scope. + */ + get commandScope() { + return this.constructor.NAME; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars getDefaultState(_props?: RenderableProps

): S { return {} as S; @@ -124,12 +133,24 @@ export class HElement

extends Component { }); } + executeCommand(context: CommandContext, params: unknown[]) { + const {onCommand} = this.props; + let result; + if (context.scope === this.commandScope) { + result = deepCall(this, context.name, params); + } + if (onCommand) { + result = onCommand.call(this, context, params); + } + return result; + } + protected _getClassName(props: RenderableProps

): ClassNameLike { return props.className; } protected _getProps(props: RenderableProps

): Record { - const {className, attrs, props: componentProps, data, forwardRef, children, component, style, class: classNameAlt, ...others} = props; + const {className, attrs, props: componentProps, data, forwardRef, children, component, style, class: classNameAlt, commands, onCommand, ...others} = props; const customProps = new Set((this.constructor as typeof HElement).customProps); const strDangerouslySetInnerHTML = 'dangerouslySetInnerHTML'; const other = Object.keys(others).reduce>((map, key) => { @@ -160,6 +181,24 @@ export class HElement

extends Component { return [component, componentProps, children]; } + componentDidMount(): void { + const {commands, onCommand} = this.props; + if (commands && onCommand) { + bindCommands(this.element, { + commands, + scope: this.commandScope, + onCommand: this.executeCommand.bind(this), + }); + } + } + + componentWillUnmount(): void { + const {commands, onCommand} = this.props; + if (commands || onCommand) { + unbindCommands(this.element, this.commandScope); + } + } + render(props: RenderableProps

) { props = this._beforeRender(props) || props; let component = this._getComponent(props); diff --git a/lib/core/src/react/types/h-element-props.ts b/lib/core/src/react/types/h-element-props.ts index d5fbce124f..4d6f4d5d41 100644 --- a/lib/core/src/react/types/h-element-props.ts +++ b/lib/core/src/react/types/h-element-props.ts @@ -1,6 +1,7 @@ import type {PreactDOMAttributes, JSX, RefObject, ComponentType, Attributes} from 'preact'; import type {ClassNameLike} from '../../helpers/classes'; import type {I18nLangMap} from '../../i18n'; +import type {CommandCallback} from '../../helpers'; /** * The HTML props that can be passed to a component which root not is a html element. @@ -61,4 +62,14 @@ export interface HElementProps extends PreactDOMAttributes, Attributes { * The other props of the element. */ [dataKey: `data-${string}` | `on${string}` | `zui-${string}`]: unknown; + + /** + * The command callback. + */ + onCommand?: CommandCallback, + + /** + * The commands callback map. + */ + commands?: Record, }