diff --git a/docs/README.md b/docs/README.md index 85da75163..78ca20006 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,7 +36,7 @@ $ yarn build ## 功能 -- [x] 支持本地离线搜搜 +- [x] 支持本地离线搜索 - [x] 版本化文档管理 - [x] 离线静态部署 - [x] 主题(fork 宜搭开发者中心) diff --git a/docs/docs/api/command.md b/docs/docs/api/command.md index fc36c8ad8..d1b8ad992 100644 --- a/docs/docs/api/command.md +++ b/docs/docs/api/command.md @@ -25,8 +25,7 @@ sidebar_position: 10 注册一个新命令及其处理函数。 -``` -typescriptCopy code +```typescript /** * 注册一个新的命令及其处理程序。 * @param command {IPublicTypeCommand} - 要注册的命令。 @@ -38,8 +37,7 @@ registerCommand(command: IPublicTypeCommand): void; 注销一个已存在的命令。 -``` -typescriptCopy code +```typescript /** * 注销一个已存在的命令。 * @param name {string} - 要注销的命令的名称。 @@ -51,8 +49,7 @@ unregisterCommand(name: string): void; 根据名称和提供的参数执行命令,确保参数符合命令的定义。 -``` -typescriptCopy code +```typescript /** * 根据名称和提供的参数执行命令。 * @param name {string} - 要执行的命令的名称。 @@ -65,8 +62,7 @@ executeCommand(name: string, args?: IPublicTypeCommandHandlerArgs): void; 批量执行命令,在所有命令执行后进行重绘,历史记录中只记录一次。 -``` -typescriptCopy code +```typescript /** * 批量执行命令,随后进行重绘,历史记录中只记录一次。 * @param commands {Array} - 命令对象的数组,包含名称和可选参数。 @@ -78,8 +74,7 @@ batchExecuteCommand(commands: { name: string; args?: IPublicTypeCommandHandlerAr 列出所有已注册的命令。 -``` -typescriptCopy code +```typescript /** * 列出所有已注册的命令。 * @returns {IPublicTypeListCommand[]} - 已注册命令的数组。 @@ -91,8 +86,7 @@ listCommands(): IPublicTypeListCommand[]; 为命令执行过程中的错误注册错误处理回调函数。 -``` -typescriptCopy code +```typescript /** * 为命令执行过程中的错误注册一个回调函数。 * @param callback {(name: string, error: Error) => void} - 错误处理的回调函数。 diff --git a/docs/docs/api/commonUI.md b/docs/docs/api/commonUI.md index 45640051f..e997ac003 100644 --- a/docs/docs/api/commonUI.md +++ b/docs/docs/api/commonUI.md @@ -3,6 +3,8 @@ title: commonUI - UI 组件库 sidebar_position: 10 --- +> **@since** v1.3.0 + ## 简介 CommonUI API 是一个专为低代码引擎设计的组件 UI 库,使用它开发的插件,可以保证在不同项目和主题切换中能够保持一致性和兼容性。 diff --git a/docs/docs/api/hotkey.md b/docs/docs/api/hotkey.md index be6a3033d..b391e367b 100644 --- a/docs/docs/api/hotkey.md +++ b/docs/docs/api/hotkey.md @@ -32,6 +32,19 @@ bind( - [IPublicTypeHotkeyCallback](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/hotkey-callback.ts) - [IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts) +### mount + +给指定窗口绑定快捷键 + +```typescript +/** + * 给指定窗口绑定快捷键 + * @param window 窗口的 window 对象 + */ +mount(window: Window): IPublicTypeDisposable; + +``` + ## 使用示例 ### 基础示例 diff --git a/docs/docs/api/skeleton.md b/docs/docs/api/skeleton.md index 396fad9e9..3ae0e3524 100644 --- a/docs/docs/api/skeleton.md +++ b/docs/docs/api/skeleton.md @@ -11,8 +11,9 @@ sidebar_position: 10 ![image.png](https://img.alicdn.com/imgextra/i4/O1CN01eVA0U41xYRP3e5zo0_!!6000000006455-2-tps-1780-996.png) -页面上可以扩展的区域共 5 个,具体如下: -![image.png](https://img.alicdn.com/imgextra/i3/O1CN014d2AcS1D5c9TshEiQ_!!6000000000165-2-tps-1892-974.png) +页面上可以扩展的区域共 6 个,具体如下: +![image](https://github.com/alibaba/lowcode-engine/assets/11935995/ba4641dd-d346-4ef7-8b71-8ca211e6eaf4) + ### 基本概念 #### 扩展区域位置 (area) ##### topArea @@ -41,6 +42,11 @@ sidebar_position: 10 ##### rightArea 右侧区域,常用于组件的配置。常见的扩展有:统一处理组件的配置项,例如统一删除某一个配置项,统一添加某一个配置项的。 + +##### bottomArea + +底部扩展区域。 + ##### toolbar 跟 topArea 类似,按需放置面板插件~ diff --git a/docs/docs/guide/appendix/npms.md b/docs/docs/guide/appendix/npms.md index b0292c273..257e6b126 100644 --- a/docs/docs/guide/appendix/npms.md +++ b/docs/docs/guide/appendix/npms.md @@ -43,5 +43,5 @@ sidebar_position: 3 | @alilc/lowcode-materials | [https://github.com/alibaba/lowcode-materials](https://github.com/alibaba/lowcode-materials) | packages/fusion-lowcode-materials | | @alilc/antd-lowcode-materials | [https://github.com/alibaba/lowcode-materials](https://github.com/alibaba/lowcode-materials) | packages/antd-lowcode-materials | | @alifd/layout(原 @alifd/pro-layout 升级后的版本) | [https://github.com/alibaba-fusion/layout](https://github.com/alibaba-fusion/layout) | | -| | | | +| @alilc/lowcode-engine-docs | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | docs | | | | | diff --git a/docs/docs/guide/create/useRenderer.md b/docs/docs/guide/create/useRenderer.md index a9fc79909..9a577bac6 100644 --- a/docs/docs/guide/create/useRenderer.md +++ b/docs/docs/guide/create/useRenderer.md @@ -20,7 +20,7 @@ sidebar_position: 1 [在 Demo 中](https://lowcode-engine.cn/demo/demo-general/index.html),右上角有渲染模块的示例使用方式: ![Mar-13-2022 16-52-49.gif](https://img.alicdn.com/imgextra/i2/O1CN01PRsEl61o7Zct5fJML_!!6000000005178-1-tps-1534-514.gif) -基于官方提供的渲染模块 [@alifd/lowcode-react-renderer](https://github.com/alibaba/lowcode-engine/tree/main/packages/react-renderer),你可以在 React 上下文渲染低代码编辑器产出的页面。 +基于官方提供的渲染模块 [@alilc/lowcode-react-renderer](https://github.com/alibaba/lowcode-engine/tree/main/packages/react-renderer),你可以在 React 上下文渲染低代码编辑器产出的页面。 ### 构造渲染模块所需数据 diff --git a/docs/docs/participate/index.md b/docs/docs/participate/index.md index e09f2ddad..7f6452fb1 100644 --- a/docs/docs/participate/index.md +++ b/docs/docs/participate/index.md @@ -70,7 +70,7 @@ npm start 在 lowcode-engine 目录下执行下面命令 ``` cd docs - +npm install npm start ``` diff --git a/docs/docs/specs/lowcode-spec.md b/docs/docs/specs/lowcode-spec.md index c27721410..480698354 100644 --- a/docs/docs/specs/lowcode-spec.md +++ b/docs/docs/specs/lowcode-spec.md @@ -20,7 +20,7 @@ sidebar_position: 0 ### 1.2 协议草案起草人 - 撰写:月飞、康为、林熠 -- 审阅:大果、潕量、九神、元彦、戊子、屹凡、金禅、前道、天晟、戊子、游鹿、光弘、力皓 +- 审阅:大果、潕量、九神、元彦、戊子、屹凡、金禅、前道、天晟、游鹿、光弘、力皓 ### 1.3 版本号 @@ -94,7 +94,7 @@ sidebar_position: 0 ### 1.9 使用范围 -本协议描述的是低代码搭建平台产物(应用、页面、区块、组件)的 schema 结构,以及实现其数据状态更新(内置 api)、能力扩展、国际化等方面完整,只在低代码搭建场景下可用; +本协议描述的是低代码搭建平台产物(应用、页面、区块、组件)的 schema 结构,以及实现其数据状态更新(内置 api)、能力扩展、国际化等方面完整,只在低代码搭建场景下可用; ### 1.10 协议目标 @@ -430,7 +430,7 @@ import { Input as CustomInput } from '@ali/custom/lib/input'; | 参数 | 说明 | 类型 | 支持变量 | 默认值 | 备注 | | ----------- | ---------------------- | -------------------------------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------- | | list[] | 数据源列表 | **ComponentDataSourceItem**[] | - | - | 成为为单个请求配置, 内容定义详见 [ComponentDataSourceItem 对象描述](#2314-componentdatasourceitem-对象描述) | -| dataHandler | 所有请求数据的处理函数 | Function | - | - | 详见 [dataHandler Function 描述](#2317-datahandler-function 描述) | +| dataHandler | 所有请求数据的处理函数 | Function | - | - | 详见 [dataHandler Function 描述](#2317-datahandler-function-描述) | ##### 2.3.1.4 ComponentDataSourceItem 对象描述 @@ -447,7 +447,7 @@ import { Input as CustomInput } from '@ali/custom/lib/input'; | errorHandler | request 失败后的回调函数 | Function | - | - | 参数:请求出错 promise 的 error 内容 | | options {} | 请求参数 | **ComponentDataSourceItemOptions**| - | - | 每种请求类型对应不同参数,详见 | 每种请求类型对应不同参数,详见 [ComponentDataSourceItemOptions 对象描述](#2315-componentdatasourceitemoptions-对象描述) | -**关于 dataHandler 于 errorHandler 的细节说明:** +**关于 dataHandler 与 errorHandler 的细节说明:** request 返回的是一个 promise,dataHandler 和 errorHandler 遵循 Promise 对象的 then 方法,实际使用方式如下: @@ -560,7 +560,7 @@ try { | 参数 | 说明 | 类型 | 支持变量 | 默认值 | 备注 | | ------------- | ---------------------- | ---------------- | -------- | ----------------- | ---------------------------------------------------------------------------------------------------------- | | id | 组件唯一标识 | String | - | | 可选,组件 id 由引擎随机生成(UUID),并保证唯一性,消费方为上层应用平台,在组件发生移动等场景需保持 id 不变 | -| componentName | 组件名称 | String | - | Div | 必填,首字母大写,同 [componentsMap](#22-组件映射关系 a) 中的要求 | +| componentName | 组件名称 | String | - | Div | 必填,首字母大写,同 [componentsMap](#22-组件映射关系a) 中的要求 | | props {} | 组件属性对象 | **Props**| - | {} | 必填,详见 | 必填,详见 [Props 结构描述](#2311-props-结构描述) | | condition | 渲染条件 | Boolean | ✅ | true | 选填,根据表达式结果判断是否渲染物料;支持变量表达式 | | loop | 循环数据 | Array | ✅ | - | 选填,默认不进行循环渲染;支持变量表达式 | @@ -797,7 +797,7 @@ try { | 参数 | 说明 | 值类型 | 默认值 | 备注 | | ------ | ---------- | --------------------- | -------- | -------------------------------------------------------------- | | type | 值类型描述 | String | 'JSSlot' | 固定值 | -| value | 具体的值 | NodeSchema \| NodeSchema[] | null | 内容为 NodeSchema 类型,详见[组件结构描述](#232-组件结构描述 a) | +| value | 具体的值 | NodeSchema \| NodeSchema[] | null | 内容为 NodeSchema 类型,详见[组件结构描述](#232-组件结构描述(A)) | | params | 函数的参数 | String[] | null | 函数的入参,其子节点可以通过 `this[参数名]` 来获取对应的参数。 | @@ -1124,7 +1124,7 @@ this.setState((prevState) => ({ count: prevState.count + 1 })); | utils[] | 工具类扩展映射关系 | **UtilItem**[] | - | | | *UtilItem*.name | 工具类扩展项名称 | String | - | | | *UtilItem*.type | 工具类扩展项类型 | 枚举, `'npm'` (代表公网 npm 类型) / `'tnpm'` (代表阿里巴巴内部 npm 类型) / `'function'` (代表 Javascript 函数类型) | - | | -| *UtilItem*.content | 工具类扩展项内容 | [ComponentMap 类型](#22-组件映射关系 a) 或 [JSFunction](#2432事件函数类型 a) | - | | +| *UtilItem*.content | 工具类扩展项内容 | [ComponentMap 类型](#22-组件映射关系a) 或 [JSFunction](#2342事件函数类型a) | - | | 描述示例: diff --git a/docs/package.json b/docs/package.json index 7facd9db8..f6b649506 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@alilc/lowcode-engine-docs", - "version": "1.2.31", + "version": "1.2.36", "description": "低代码引擎版本化文档", "license": "MIT", "files": [ diff --git a/packages/designer/jest.config.js b/packages/designer/jest.config.js index 3684a48ac..0d0f7f8f8 100644 --- a/packages/designer/jest.config.js +++ b/packages/designer/jest.config.js @@ -22,6 +22,7 @@ const jestConfig = { // testMatch: ['**/selection.test.ts'], // testMatch: ['**/plugin/sequencify.test.ts'], // testMatch: ['**/builtin-simulator/utils/parse-metadata.test.ts'], + // testMatch: ['**/setting/setting-top-entry.test.ts'], transformIgnorePatterns: [ `/node_modules/(?!${esModules})/`, ], diff --git a/packages/designer/src/context-menu-actions.ts b/packages/designer/src/context-menu-actions.ts index c88e03ac6..3b0283fc4 100644 --- a/packages/designer/src/context-menu-actions.ts +++ b/packages/designer/src/context-menu-actions.ts @@ -5,18 +5,6 @@ import { Menu } from '@alifd/next'; import { engineConfig } from '@alilc/lowcode-editor-core'; import './context-menu-actions.scss'; -export interface IContextMenuActions { - actions: IPublicTypeContextMenuAction[]; - - adjustMenuLayoutFn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]; - - addMenuAction: IPublicApiMaterial['addContextMenuOption']; - - removeMenuAction: IPublicApiMaterial['removeContextMenuOption']; - - adjustMenuLayout: IPublicApiMaterial['adjustContextMenuLayout']; -} - let adjustMenuLayoutFn: Function = (actions: IPublicTypeContextMenuAction[]) => actions; export class GlobalContextMenuActions { @@ -116,7 +104,7 @@ export class GlobalContextMenuActions { const globalContextMenuActions = new GlobalContextMenuActions(); -export class ContextMenuActions implements IContextMenuActions { +export class ContextMenuActions { actions: IPublicTypeContextMenuAction[] = []; designer: IDesigner; @@ -204,30 +192,32 @@ export class ContextMenuActions implements IContextMenuActions { originalEvent.stopPropagation(); originalEvent.preventDefault(); // 如果右键的节点不在 当前选中的节点中,选中该节点 - if (!designer.currentSelection.has(node.id)) { - designer.currentSelection.select(node.id); + if (!designer.currentSelection?.has(node.id)) { + designer.currentSelection?.select(node.id); } - const nodes = designer.currentSelection.getNodes(); + const nodes = designer.currentSelection?.getNodes(); this.handleContextMenu(nodes, originalEvent); }), ); } - addMenuAction(action: IPublicTypeContextMenuAction) { + addMenuAction: IPublicApiMaterial['addContextMenuOption'] = (action: IPublicTypeContextMenuAction) => { this.actions.push({ type: IPublicEnumContextMenuType.MENU_ITEM, ...action, }); - } + }; - removeMenuAction(name: string) { + removeMenuAction: IPublicApiMaterial['removeContextMenuOption'] = (name: string) => { const i = this.actions.findIndex((action) => action.name === name); if (i > -1) { this.actions.splice(i, 1); } - } + }; - adjustMenuLayout(fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]) { + adjustMenuLayout: IPublicApiMaterial['adjustContextMenuLayout'] = (fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]) => { adjustMenuLayoutFn = fn; - } -} \ No newline at end of file + }; +} + +export interface IContextMenuActions extends ContextMenuActions {} \ No newline at end of file diff --git a/packages/designer/src/designer/designer-view.tsx b/packages/designer/src/designer/designer-view.tsx index aaf0c9583..851decf14 100644 --- a/packages/designer/src/designer/designer-view.tsx +++ b/packages/designer/src/designer/designer-view.tsx @@ -1,16 +1,16 @@ import { Component } from 'react'; import classNames from 'classnames'; import BuiltinDragGhostComponent from './drag-ghost'; -import { Designer, DesignerProps } from './designer'; +import { Designer, DesignerProps, IDesigner } from './designer'; import { ProjectView } from '../project'; import './designer.less'; type IProps = DesignerProps & { - designer?: Designer; + designer?: IDesigner; }; export class DesignerView extends Component { - readonly designer: Designer; + readonly designer: IDesigner; readonly viewName: string | undefined; constructor(props: IProps) { diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts index 1dd4bc04e..48c163493 100644 --- a/packages/designer/src/designer/designer.ts +++ b/packages/designer/src/designer/designer.ts @@ -6,7 +6,6 @@ import { IPublicTypeComponentAction, IPublicTypeNpmInfo, IPublicModelEditor, - IPublicTypeCompositeObject, IPublicTypePropsList, IPublicTypeNodeSchema, IPublicTypePropsTransducer, @@ -17,15 +16,16 @@ import { IPublicTypeLocationData, IPublicEnumTransformStage, IPublicModelLocateEvent, + IPublicTypePropsMap, } from '@alilc/lowcode-types'; import { mergeAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils'; import { IProject, Project } from '../project'; -import { Node, DocumentModel, insertChildren, INode, ISelection } from '../document'; +import { Node, DocumentModel, insertChildren, INode } from '../document'; import { ComponentMeta, IComponentMeta } from '../component-meta'; import { INodeSelector, Component } from '../simulator'; import { Scroller } from './scroller'; import { Dragon, IDragon } from './dragon'; -import { ActiveTracker, IActiveTracker } from './active-tracker'; +import { ActiveTracker } from './active-tracker'; import { Detecting } from './detecting'; import { DropLocation } from './location'; import { OffsetObserver, createOffsetObserver } from './offset-observer'; @@ -47,7 +47,7 @@ export interface DesignerProps { viewName?: string; simulatorProps?: Record | ((document: DocumentModel) => object); simulatorComponent?: ComponentType; - dragGhostComponent?: ComponentType; + dragGhostComponent?: ComponentType<{ designer: IDesigner }>; suspensed?: boolean; componentMetadatas?: IPublicTypeComponentMetadata[]; globalComponentActions?: IPublicTypeComponentAction[]; @@ -60,70 +60,10 @@ export interface DesignerProps { ) => void; } -export interface IDesigner { - readonly shellModelFactory: IShellModelFactory; - - viewName: string | undefined; - - readonly project: IProject; - - get dragon(): IDragon; - - get activeTracker(): IActiveTracker; - - get componentActions(): ComponentActions; - - get contextMenuActions(): ContextMenuActions; - - get editor(): IPublicModelEditor; - - get detecting(): Detecting; - - get simulatorComponent(): ComponentType | undefined; - - get currentSelection(): ISelection; - - createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller; - - refreshComponentMetasMap(): void; - - createOffsetObserver(nodeInstance: INodeSelector): OffsetObserver | null; - - /** - * 创建插入位置,考虑放到 dragon 中 - */ - createLocation(locationData: IPublicTypeLocationData): DropLocation; - - get componentsMap(): { [key: string]: IPublicTypeNpmInfo | Component }; - - loadIncrementalAssets(incrementalAssets: IPublicTypeAssetsJson): Promise; - - getComponentMeta( - componentName: string, - generateMetadata?: () => IPublicTypeComponentMetadata | null, - ): IComponentMeta; - - clearLocation(): void; - - createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null; - - getComponentMetasMap(): Map; - - addPropsReducer(reducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage): void; - - postEvent(event: string, ...args: any[]): void; - - transformProps(props: IPublicTypeCompositeObject | IPublicTypePropsList, node: Node, stage: IPublicEnumTransformStage): IPublicTypeCompositeObject | IPublicTypePropsList; - - createSettingEntry(nodes: INode[]): ISettingTopEntry; - - autorun(effect: (reaction: IReactionPublic) => void, options?: IReactionOptions): IReactionDisposer; -} - -export class Designer implements IDesigner { +export class Designer { dragon: IDragon; - viewName: string | undefined; + readonly viewName: string | undefined; readonly componentActions = new ComponentActions(); @@ -423,7 +363,7 @@ export class Designer implements IDesigner { if (props.simulatorProps !== this.props.simulatorProps) { this._simulatorProps = props.simulatorProps; // 重新 setupSelection - if (props.simulatorProps?.designMode !== this.props.simulatorProps?.designMode) { + if ((props.simulatorProps as any)?.designMode !== (this.props.simulatorProps as any)?.designMode) { this.setupSelection(); } } @@ -612,7 +552,7 @@ export class Designer implements IDesigner { return maps; } - transformProps(props: IPublicTypeCompositeObject | IPublicTypePropsList, node: Node, stage: IPublicEnumTransformStage) { + transformProps(props: IPublicTypePropsMap | IPublicTypePropsList, node: Node, stage: IPublicEnumTransformStage): IPublicTypePropsMap | IPublicTypePropsList { if (Array.isArray(props)) { // current not support, make this future return props; @@ -623,7 +563,7 @@ export class Designer implements IDesigner { return props; } - return reducers.reduce((xprops, reducer) => { + return reducers.reduce((xprops, reducer: IPublicTypePropsTransducer) => { try { return reducer(xprops, node.internalToShellNode() as any, { stage }); } catch (e) { @@ -655,3 +595,5 @@ export class Designer implements IDesigner { // TODO: } } + +export interface IDesigner extends Designer {} diff --git a/packages/designer/src/designer/dragon.ts b/packages/designer/src/designer/dragon.ts index 8dcce2b4a..f96b667b1 100644 --- a/packages/designer/src/designer/dragon.ts +++ b/packages/designer/src/designer/dragon.ts @@ -13,7 +13,7 @@ import { import { setNativeSelection, cursor } from '@alilc/lowcode-utils'; import { INode, Node } from '../document'; import { ISimulatorHost, isSimulatorHost } from '../simulator'; -import { IDesigner } from './designer'; +import type { IDesigner } from './designer'; import { makeEventsHandler } from '../utils/misc'; export interface ILocateEvent extends IPublicModelLocateEvent { @@ -95,17 +95,13 @@ function isDragEvent(e: any): e is DragEvent { return e?.type?.startsWith('drag'); } -export interface IDragon extends IPublicModelDragon< - INode, - ILocateEvent -> { - emitter: IEventBus; -} - /** * Drag-on 拖拽引擎 */ -export class Dragon implements IDragon { +export class Dragon implements IPublicModelDragon< + INode, + ILocateEvent +> { private sensors: IPublicModelSensor[] = []; private nodeInstPointerEvents: boolean; @@ -637,3 +633,5 @@ export class Dragon implements IDragon { }; } } + +export interface IDragon extends Dragon { } diff --git a/packages/designer/src/designer/offset-observer.ts b/packages/designer/src/designer/offset-observer.ts index 2cf5bfee2..3c37be02d 100644 --- a/packages/designer/src/designer/offset-observer.ts +++ b/packages/designer/src/designer/offset-observer.ts @@ -28,11 +28,11 @@ export class OffsetObserver { @obx private _bottom = 0; @computed get height() { - return this.isRoot ? this.viewport.height : this._height * this.scale; + return this.isRoot ? this.viewport?.height : this._height * this.scale; } @computed get width() { - return this.isRoot ? this.viewport.width : this._width * this.scale; + return this.isRoot ? this.viewport?.width : this._width * this.scale; } @computed get top() { @@ -44,51 +44,51 @@ export class OffsetObserver { } @computed get bottom() { - return this.isRoot ? this.viewport.height : this._bottom * this.scale; + return this.isRoot ? this.viewport?.height : this._bottom * this.scale; } @computed get right() { - return this.isRoot ? this.viewport.width : this._right * this.scale; + return this.isRoot ? this.viewport?.width : this._right * this.scale; } @obx hasOffset = false; @computed get offsetLeft() { if (this.isRoot) { - return this.viewport.scrollX * this.scale; + return (this.viewport?.scrollX || 0) * this.scale; } - if (!this.viewport.scrolling || this.lastOffsetLeft == null) { - this.lastOffsetLeft = this.left + this.viewport.scrollX * this.scale; + if (!this.viewport?.scrolling || this.lastOffsetLeft == null) { + this.lastOffsetLeft = this.left + (this.viewport?.scrollX || 0) * this.scale; } return this.lastOffsetLeft; } @computed get offsetTop() { if (this.isRoot) { - return this.viewport.scrollY * this.scale; + return (this.viewport?.scrollY || 0) * this.scale; } - if (!this.viewport.scrolling || this.lastOffsetTop == null) { - this.lastOffsetTop = this.top + this.viewport.scrollY * this.scale; + if (!this.viewport?.scrolling || this.lastOffsetTop == null) { + this.lastOffsetTop = this.top + (this.viewport?.scrollY || 0) * this.scale; } return this.lastOffsetTop; } @computed get offsetHeight() { - if (!this.viewport.scrolling || this.lastOffsetHeight == null) { - this.lastOffsetHeight = this.isRoot ? this.viewport.height : this.height; + if (!this.viewport?.scrolling || this.lastOffsetHeight == null) { + this.lastOffsetHeight = this.isRoot ? (this.viewport?.height || 0) : this.height; } return this.lastOffsetHeight; } @computed get offsetWidth() { - if (!this.viewport.scrolling || this.lastOffsetWidth == null) { - this.lastOffsetWidth = this.isRoot ? this.viewport.width : this.width; + if (!(this.viewport?.scrolling || 0) || this.lastOffsetWidth == null) { + this.lastOffsetWidth = this.isRoot ? (this.viewport?.width || 0) : this.width; } return this.lastOffsetWidth; } @computed get scale() { - return this.viewport.scale; + return this.viewport?.scale || 0; } private pid: number | undefined; @@ -124,11 +124,11 @@ export class OffsetObserver { return; } - const rect = host.computeComponentInstanceRect(instance!, node.componentMeta.rootSelector); + const rect = host?.computeComponentInstanceRect(instance!, node.componentMeta.rootSelector); if (!rect) { this.hasOffset = false; - } else if (!this.viewport.scrolling || !this.hasOffset) { + } else if (!this.viewport?.scrolling || !this.hasOffset) { this._height = rect.height; this._width = rect.width; this._left = rect.left; diff --git a/packages/designer/src/designer/setting/setting-entry-type.ts b/packages/designer/src/designer/setting/setting-entry-type.ts index 1aee9016e..5cbe232ab 100644 --- a/packages/designer/src/designer/setting/setting-entry-type.ts +++ b/packages/designer/src/designer/setting/setting-entry-type.ts @@ -1,7 +1,7 @@ -import { IPublicApiSetters, IPublicModelEditor } from '@alilc/lowcode-types'; -import { IDesigner } from '../designer'; -import { INode } from '../../document'; -import { ISettingField } from './setting-field'; +import type { IPublicApiSetters, IPublicModelEditor } from '@alilc/lowcode-types'; +import type { IDesigner } from '../designer'; +import type { INode } from '../../document'; +import type { ISettingField } from './setting-field'; export interface ISettingEntry { readonly designer: IDesigner | undefined; diff --git a/packages/designer/src/designer/setting/setting-field.ts b/packages/designer/src/designer/setting/setting-field.ts index 1a63fb7a4..87415dd98 100644 --- a/packages/designer/src/designer/setting/setting-field.ts +++ b/packages/designer/src/designer/setting/setting-field.ts @@ -1,4 +1,3 @@ -import { ReactNode } from 'react'; import { IPublicTypeTitleContent, IPublicTypeSetterType, @@ -7,18 +6,15 @@ import { IPublicTypeFieldConfig, IPublicTypeCustomView, IPublicTypeDisposable, - IPublicModelSettingField, - IBaseModelSettingField, } from '@alilc/lowcode-types'; import type { IPublicTypeSetValueOptions, } from '@alilc/lowcode-types'; import { Transducer } from './utils'; -import { ISettingPropEntry, SettingPropEntry } from './setting-prop-entry'; +import { SettingPropEntry } from './setting-prop-entry'; import { computed, obx, makeObservable, action, untracked, intl } from '@alilc/lowcode-editor-core'; import { cloneDeep, isCustomView, isDynamicSetter, isJSExpression } from '@alilc/lowcode-utils'; -import { ISettingTopEntry } from './setting-top-entry'; -import { IComponentMeta, INode } from '@alilc/lowcode-designer'; +import type { ISettingTopEntry } from './setting-top-entry'; function getSettingFieldCollectorKey(parent: ISettingTopEntry | ISettingField, config: IPublicTypeFieldConfig) { let cur = parent; @@ -32,53 +28,7 @@ function getSettingFieldCollectorKey(parent: ISettingTopEntry | ISettingField, c return path.join('.'); } -export interface ISettingField extends ISettingPropEntry, Omit, 'setValue' | 'key' | 'node'> { - readonly isSettingField: true; - - readonly isRequired: boolean; - - readonly isGroup: boolean; - - extraProps: IPublicTypeFieldExtraProps; - - get items(): Array; - - get title(): string | ReactNode | undefined; - - get setter(): IPublicTypeSetterType | null; - - get expanded(): boolean; - - get valueState(): number; - - setExpanded(value: boolean): void; - - purge(): void; - - setValue( - val: any, - isHotValue?: boolean, - force?: boolean, - extraOptions?: IPublicTypeSetValueOptions, - ): void; - - clearValue(): void; - - valueChange(options: IPublicTypeSetValueOptions): void; - - createField(config: IPublicTypeFieldConfig): ISettingField; - - onEffect(action: () => void): IPublicTypeDisposable; - - internalToShellField(): IPublicModelSettingField; -} - -export class SettingField extends SettingPropEntry implements ISettingField { +export class SettingField extends SettingPropEntry { readonly isSettingField = true; readonly isRequired: boolean; @@ -321,3 +271,5 @@ export class SettingField extends SettingPropEntry implements ISettingField { export function isSettingField(obj: any): obj is ISettingField { return obj && obj.isSettingField; } + +export type ISettingField = typeof SettingField; diff --git a/packages/designer/src/designer/setting/setting-prop-entry.ts b/packages/designer/src/designer/setting/setting-prop-entry.ts index d6904f0c8..6cce4cddc 100644 --- a/packages/designer/src/designer/setting/setting-prop-entry.ts +++ b/packages/designer/src/designer/setting/setting-prop-entry.ts @@ -1,12 +1,12 @@ import { obx, computed, makeObservable, runInAction, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import { GlobalEvent, IPublicApiSetters, IPublicModelEditor, IPublicModelSettingField, IPublicTypeFieldExtraProps, IPublicTypeSetValueOptions } from '@alilc/lowcode-types'; -import { uniqueId, isJSExpression } from '@alilc/lowcode-utils'; -import { ISettingEntry } from './setting-entry-type'; -import { INode } from '../../document'; +import { uniqueId, isJSExpression, isSettingField } from '@alilc/lowcode-utils'; +import type { ISettingEntry } from './setting-entry-type'; +import type { INode } from '../../document'; import type { IComponentMeta } from '../../component-meta'; -import { IDesigner } from '../designer'; -import { ISettingTopEntry } from './setting-top-entry'; -import { ISettingField, isSettingField } from './setting-field'; +import type { IDesigner } from '../designer'; +import type { ISettingTopEntry } from './setting-top-entry'; +import type { ISettingField } from './setting-field'; export interface ISettingPropEntry extends ISettingEntry { readonly isGroup: boolean; diff --git a/packages/designer/src/designer/setting/setting-top-entry.ts b/packages/designer/src/designer/setting/setting-top-entry.ts index 85be74b7f..3a1739788 100644 --- a/packages/designer/src/designer/setting/setting-top-entry.ts +++ b/packages/designer/src/designer/setting/setting-top-entry.ts @@ -1,11 +1,12 @@ import { IPublicTypeCustomView, IPublicModelEditor, IPublicModelSettingTopEntry, IPublicApiSetters } from '@alilc/lowcode-types'; import { isCustomView } from '@alilc/lowcode-utils'; -import { computed, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; -import { ISettingEntry } from './setting-entry-type'; -import { ISettingField, SettingField } from './setting-field'; -import { INode } from '../../document'; +import { computed, IEventBus, createModuleEventBus, obx, makeObservable } from '@alilc/lowcode-editor-core'; +import { SettingField } from './setting-field'; +import type { ISettingEntry } from './setting-entry-type'; +import type { ISettingField } from './setting-field'; +import type { INode } from '../../document'; import type { IComponentMeta } from '../../component-meta'; -import { IDesigner } from '../designer'; +import type { IDesigner } from '../designer'; function generateSessionId(nodes: INode[]) { return nodes @@ -14,33 +15,17 @@ function generateSessionId(nodes: INode[]) { .join(','); } -export interface ISettingTopEntry extends ISettingEntry, IPublicModelSettingTopEntry< +export interface ISettingTopEntry extends SettingTopEntry {} + +export class SettingTopEntry implements ISettingEntry, IPublicModelSettingTopEntry< INode, ISettingField > { - readonly top: ISettingTopEntry; - - readonly parent: ISettingTopEntry; - - readonly path: never[]; - - items: Array; - - componentMeta: IComponentMeta | null; - - purge(): void; - - getExtraPropValue(propName: string): void; - - setExtraPropValue(propName: string, value: any): void; -} - -export class SettingTopEntry implements ISettingTopEntry { private emitter: IEventBus = createModuleEventBus('SettingTopEntry'); - private _items: Array = []; + private _items: Array = []; - private _componentMeta: IComponentMeta | null = null; + private _componentMeta: IComponentMeta | null | undefined = null; private _isSame = true; @@ -75,7 +60,7 @@ export class SettingTopEntry implements ISettingTopEntry { } get isLocked(): boolean { - return this.first.isLocked; + return this.first?.isLocked ?? false; } /** @@ -87,7 +72,11 @@ export class SettingTopEntry implements ISettingTopEntry { readonly id: string; - readonly first: INode; + @computed get first(): INode | null { + return this._first; + } + + @obx.ref _first: INode | null; readonly designer: IDesigner | undefined; @@ -96,12 +85,14 @@ export class SettingTopEntry implements ISettingTopEntry { disposeFunctions: any[] = []; constructor(readonly editor: IPublicModelEditor, readonly nodes: INode[]) { + makeObservable(this); + if (!Array.isArray(nodes) || nodes.length < 1) { throw new ReferenceError('nodes should not be empty'); } this.id = generateSessionId(nodes); - this.first = nodes[0]; - this.designer = this.first.document?.designer; + this._first = nodes[0]; + this.designer = this._first.document?.designer; this.setters = editor.get('setters') as IPublicApiSetters; // setups @@ -116,7 +107,7 @@ export class SettingTopEntry implements ISettingTopEntry { private setupComponentMeta() { // todo: enhance compile a temp configure.compiled const { first } = this; - const meta = first.componentMeta; + const meta = first?.componentMeta; const l = this.nodes.length; let theSame = true; for (let i = 1; i < l; i++) { @@ -160,7 +151,7 @@ export class SettingTopEntry implements ISettingTopEntry { /** * 获取当前属性值 */ - @computed getValue(): any { + getValue(): any { return this.first?.propsData; } @@ -202,14 +193,14 @@ export class SettingTopEntry implements ISettingTopEntry { * 获取子级属性值 */ getPropValue(propName: string | number): any { - return this.first.getProp(propName.toString(), true)?.getValue(); + return this.first?.getProp(propName.toString(), true)?.getValue(); } /** * 获取顶层附属属性值 */ getExtraPropValue(propName: string) { - return this.first.getExtraProp(propName, false)?.getValue(); + return this.first?.getExtraProp(propName, false)?.getValue(); } /** @@ -244,8 +235,9 @@ export class SettingTopEntry implements ISettingTopEntry { this.disposeItems(); this._settingFieldMap = {}; this.emitter.removeAllListeners(); - this.disposeFunctions.forEach(f => f()); + this.disposeFunctions.forEach(f => f?.()); this.disposeFunctions = []; + this._first = null; } getProp(propName: string | number) { @@ -274,7 +266,7 @@ export class SettingTopEntry implements ISettingTopEntry { } getPage() { - return this.first.document; + return this.first?.document; } /** @@ -292,6 +284,7 @@ export class SettingTopEntry implements ISettingTopEntry { interface Purgeable { purge(): void; } + function isPurgeable(obj: any): obj is Purgeable { return obj && obj.purge; } diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts index edca8fd81..dd9258fc1 100644 --- a/packages/designer/src/document/document-model.ts +++ b/packages/designer/src/document/document-model.ts @@ -37,10 +37,10 @@ import { isDragNodeDataObject, isNode, } from '@alilc/lowcode-utils'; -import { IProject } from '../project'; -import { ISimulatorHost } from '../simulator'; +import type { IProject } from '../project'; +import type { ISimulatorHost } from '../simulator'; import type { IComponentMeta } from '../component-meta'; -import { IDesigner, IHistory } from '../designer'; +import type { IDesigner, IHistory } from '../designer'; import { insertChildren, insertChild, IRootNode } from './node/node'; import type { INode } from './node/node'; import { Selection, ISelection } from './selection'; @@ -56,104 +56,30 @@ export type GetDataType = T extends undefined : any : T; -export interface IDocumentModel extends Omit, - 'detecting' | - 'checkNesting' | - 'getNodeById' | - // 以下属性在内部的 document 中不存在 - 'exportSchema' | - 'importSchema' | - 'onAddNode' | - 'onRemoveNode' | - 'onChangeDetecting' | - 'onChangeSelection' | - 'onChangeNodeProp' | - 'onImportSchema' | - 'isDetectingNode' | - 'onFocusNodeChanged' | - 'onDropLocationChanged' +'detecting' | +'checkNesting' | +'getNodeById' | +// 以下属性在内部的 document 中不存在 +'exportSchema' | +'importSchema' | +'onAddNode' | +'onRemoveNode' | +'onChangeDetecting' | +'onChangeSelection' | +'onChangeNodeProp' | +'onImportSchema' | +'isDetectingNode' | +'onFocusNodeChanged' | +'onDropLocationChanged' > { - - readonly designer: IDesigner; - - selection: ISelection; - - get rootNode(): INode | null; - - get simulator(): ISimulatorHost | null; - - get active(): boolean; - - get nodesMap(): Map; - - /** - * 是否为非激活状态 - */ - get suspensed(): boolean; - - get fileName(): string; - - get currentRoot(): INode | null; - - isBlank(): boolean; - - /** - * 根据 id 获取节点 - */ - getNode(id: string): INode | null; - - getRoot(): INode | null; - - getHistory(): IHistory; - - checkNesting( - dropTarget: INode, - dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject, - ): boolean; - - getNodeCount(): number; - - nextId(possibleId: string | undefined): string; - - import(schema: IPublicTypeRootSchema, checkId?: boolean): void; - - export(stage: IPublicEnumTransformStage): IPublicTypeRootSchema | undefined; - - onNodeCreate(func: (node: INode) => void): IPublicTypeDisposable; - - onNodeDestroy(func: (node: INode) => void): IPublicTypeDisposable; - - onChangeNodeVisible(fn: (node: INode, visible: boolean) => void): IPublicTypeDisposable; - - addWillPurge(node: INode): void; - - removeWillPurge(node: INode): void; - - getComponentMeta(componentName: string): IComponentMeta; - - insertNodes(parent: INode, thing: INode[] | IPublicTypeNodeData[], at?: number | null, copy?: boolean): INode[]; - - open(): IDocumentModel; - - remove(): void; - - suspense(): void; - - close(): void; - - unlinkNode(node: INode): void; - - destroyNode(node: INode): void; -} - -export class DocumentModel implements IDocumentModel { /** * 根节点 类型有:Page/Component/Block */ @@ -322,7 +248,7 @@ export class DocumentModel implements IDocumentModel { // 兼容 vision this.id = project.getSchema()?.id || this.id; - this.rootNode = this.createNode( + this.rootNode = this.createNode( schema || { componentName: 'Page', id: 'root', @@ -425,7 +351,7 @@ export class DocumentModel implements IDocumentModel { * 根据 schema 创建一个节点 */ @action - createNode(data: GetDataType): T { + createNode(data: S): T { let schema: any; if (isDOMText(data) || isJSExpression(data)) { schema = { @@ -529,7 +455,7 @@ export class DocumentModel implements IDocumentModel { return null; } const wrapper = this.createNode(schema); - if (wrapper.isParental()) { + if (wrapper?.isParental()) { const first = nodes[0]; // TODO: check nesting rules x 2 insertChild(first.parent!, wrapper, first.index); @@ -538,7 +464,7 @@ export class DocumentModel implements IDocumentModel { return wrapper; } - this.removeNode(wrapper); + wrapper && this.removeNode(wrapper); return null; } @@ -928,3 +854,5 @@ export function isDocumentModel(obj: any): obj is IDocumentModel { export function isPageSchema(obj: any): obj is IPublicTypePageSchema { return obj?.componentName === 'Page'; } + +export interface IDocumentModel extends DocumentModel {} \ No newline at end of file diff --git a/packages/designer/src/document/document-view.tsx b/packages/designer/src/document/document-view.tsx index c6dbe76a8..ec588e223 100644 --- a/packages/designer/src/document/document-view.tsx +++ b/packages/designer/src/document/document-view.tsx @@ -1,7 +1,7 @@ import { Component } from 'react'; import classNames from 'classnames'; import { observer } from '@alilc/lowcode-editor-core'; -import { DocumentModel, IDocumentModel } from './document-model'; +import type { IDocumentModel } from './document-model'; import { BuiltinSimulatorHostView } from '../builtin-simulator'; @observer diff --git a/packages/designer/src/document/history.ts b/packages/designer/src/document/history.ts index ca288c03a..10695e235 100644 --- a/packages/designer/src/document/history.ts +++ b/packages/designer/src/document/history.ts @@ -1,7 +1,7 @@ import { reaction, untracked, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; import { IPublicTypeNodeSchema, IPublicModelHistory, IPublicTypeDisposable } from '@alilc/lowcode-types'; import { Logger } from '@alilc/lowcode-utils'; -import { IDocumentModel } from '../designer'; +import type { IDocumentModel } from '../designer'; const logger = new Logger({ level: 'warn', bizName: 'history' }); diff --git a/packages/designer/src/document/node/node-children.ts b/packages/designer/src/document/node/node-children.ts index 65210fe62..0f0c4a459 100644 --- a/packages/designer/src/document/node/node-children.ts +++ b/packages/designer/src/document/node/node-children.ts @@ -1,5 +1,5 @@ import { obx, computed, makeObservable, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; -import { Node, INode } from './node'; +import type { INode } from './node'; import { IPublicTypeNodeData, IPublicModelNodeChildren, IPublicEnumTransformStage, IPublicTypeDisposable } from '@alilc/lowcode-types'; import { shallowEqual, compatStage, isNodeSchema } from '@alilc/lowcode-utils'; import { foreachReverse } from '../../utils/tree'; @@ -7,66 +7,15 @@ import { NodeRemoveOptions } from '../../types'; export interface IOnChangeOptions { type: string; - node: Node; + node: INode; } -export interface INodeChildren extends Omit, - 'importSchema' | - 'exportSchema' | - 'isEmpty' | - 'notEmpty' +export class NodeChildren implements Omit, +'importSchema' | +'exportSchema' | +'isEmpty' | +'notEmpty' > { - children: INode[]; - - get owner(): INode; - - get length(): number; - - unlinkChild(node: INode): void; - - /** - * 删除一个节点 - */ - internalDelete( - node: INode, - purge: boolean, - useMutator: boolean, - options: NodeRemoveOptions - ): boolean; - - /** - * 插入一个节点,返回新长度 - */ - internalInsert(node: INode, at?: number | null, useMutator?: boolean): void; - - import(data?: IPublicTypeNodeData | IPublicTypeNodeData[], checkId?: boolean): void; - - /** - * 导出 schema - */ - export(stage: IPublicEnumTransformStage): IPublicTypeNodeData[]; - - /** following methods are overriding super interface, using different param types */ - /** overriding methods start */ - - forEach(fn: (item: INode, index: number) => void): void; - - /** - * 根据索引获得节点 - */ - get(index: number): INode | null; - - isEmpty(): boolean; - - notEmpty(): boolean; - - internalInitParent(): void; - - onChange(fn: (info?: IOnChangeOptions) => void): IPublicTypeDisposable; - - /** overriding methods end */ -} -export class NodeChildren implements INodeChildren { @obx.shallow children: INode[]; private emitter: IEventBus = createModuleEventBus('NodeChildren'); @@ -99,11 +48,10 @@ export class NodeChildren implements INodeChildren { constructor( readonly owner: INode, data: IPublicTypeNodeData | IPublicTypeNodeData[], - options: any = {}, ) { makeObservable(this); this.children = (Array.isArray(data) ? data : [data]).filter(child => !!child).map((child) => { - return this.owner.document?.createNode(child, options.checkId); + return this.owner.document?.createNode(child); }); } @@ -132,7 +80,7 @@ export class NodeChildren implements INodeChildren { const originChildren = this.children.slice(); this.children.forEach((child) => child.internalSetParent(null)); - const children = new Array(data.length); + const children = new Array(data.length); for (let i = 0, l = data.length; i < l; i++) { const child = originChildren[i]; const item = data[i]; @@ -142,9 +90,17 @@ export class NodeChildren implements INodeChildren { node = child; node.import(item); } else { - node = this.owner.document?.createNode(item, checkId); + node = this.owner.document?.createNode(item); + child?.purge(); + } + + if (node) { + children[i] = node; } - children[i] = node; + } + + for (let i = data.length; i < originChildren.length; i++) { + originChildren[i].purge(); } this.children = children; @@ -176,13 +132,13 @@ export class NodeChildren implements INodeChildren { /** * 回收销毁 */ - purge(useMutator = true) { + purge() { if (this.purged) { return; } this.purged = true; this.children.forEach((child) => { - child.purge(useMutator); + child.purge(); }); } @@ -212,15 +168,15 @@ export class NodeChildren implements INodeChildren { node.internalPurgeStart(); if (node.isParentalNode) { foreachReverse( - node.children, - (subNode: Node) => { + node.children!, + (subNode: INode) => { subNode.remove(useMutator, purge, options); }, (iterable, idx) => (iterable as NodeChildren).get(idx), ); foreachReverse( node.slots, - (slotNode: Node) => { + (slotNode: INode) => { slotNode.remove(useMutator, purge); }, (iterable, idx) => (iterable as [])[idx], @@ -351,10 +307,17 @@ export class NodeChildren implements INodeChildren { * */ splice(start: number, deleteCount: number, node?: INode): INode[] { + let removedNode; if (node) { - return this.children.splice(start, deleteCount, node); + removedNode = this.children.splice(start, deleteCount, node); + node.internalSetParent(this.owner); + } else { + removedNode = this.children.splice(start, deleteCount); } - return this.children.splice(start, deleteCount); + + removedNode.forEach(d => d?.purge()); + + return removedNode; } /** @@ -459,11 +422,11 @@ export class NodeChildren implements INodeChildren { const items = adder(this.children); if (items && items.length > 0) { items.forEach((child: IPublicTypeNodeData) => { - const node: INode = this.owner.document?.createNode(child); - this.children.push(node); - node.internalSetParent(this.owner); + const node: INode | null = this.owner.document?.createNode(child); + node && this.children.push(node); + node?.internalSetParent(this.owner); /* istanbul ignore next */ - const editor = node.document?.designer.editor; + const editor = node?.document?.designer.editor; editor?.eventBus.emit('node.add', { node }); }); changed = true; @@ -504,7 +467,7 @@ export class NodeChildren implements INodeChildren { try { callbacks?.onSubtreeModified.call( node.internalToShellNode(), - owner.internalToShellNode(), + owner.internalToShellNode()!, options, ); } catch (e) { @@ -517,3 +480,5 @@ export class NodeChildren implements INodeChildren { } } } + +export interface INodeChildren extends NodeChildren {} \ No newline at end of file diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index c8363d058..5a43fc15c 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -13,17 +13,16 @@ import { GlobalEvent, IPublicTypeComponentAction, IPublicModelNode, - IPublicModelExclusiveGroup, IPublicEnumTransformStage, IPublicTypeDisposable, IBaseModelNode, } from '@alilc/lowcode-types'; import { compatStage, isDOMText, isJSExpression, isNode, isNodeSchema } from '@alilc/lowcode-utils'; -import { ISettingTopEntry } from '@alilc/lowcode-designer'; +import type { ISettingTopEntry } from '@alilc/lowcode-designer'; import { Props, getConvertedExtraKey, IProps } from './props/props'; import type { IDocumentModel } from '../document-model'; import { NodeChildren, INodeChildren } from './node-children'; -import { IProp, Prop } from './props/prop'; +import type { IProp } from './props/prop'; import type { IComponentMeta } from '../../component-meta'; import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group'; import type { IExclusiveGroup } from './exclusive-group'; @@ -37,132 +36,7 @@ export interface NodeStatus { inPlaceEditing: boolean; } -export interface IBaseNode extends Omit, - 'isRoot' | - 'isPage' | - 'isComponent' | - 'isModal' | - 'isSlot' | - 'isParental' | - 'isLeaf' | - 'settingEntry' | - // 在内部的 node 模型中不存在 - 'getExtraPropValue' | - 'setExtraPropValue' | - 'exportSchema' | - 'visible' | - 'importSchema' | - // 内外实现有差异 - 'isContainer' | - 'isEmpty' -> { - isNode: boolean; - - get componentMeta(): IComponentMeta; - - get settingEntry(): ISettingTopEntry; - - get isPurged(): boolean; - - get index(): number | undefined; - - get isPurging(): boolean; - - getId(): string; - - getParent(): INode | null; - - /** - * 内部方法,请勿使用 - * @param useMutator 是否触发联动逻辑 - */ - internalSetParent(parent: INode | null, useMutator?: boolean): void; - - setConditionGroup(grp: IPublicModelExclusiveGroup | string | null): void; - - internalToShellNode(): IPublicModelNode | null; - - internalPurgeStart(): void; - - unlinkSlot(slotNode: INode): void; - - /** - * 导出 schema - */ - export(stage: IPublicEnumTransformStage, options?: any): T; - - emitPropChange(val: IPublicTypePropChangeOptions): void; - - import(data: Schema, checkId?: boolean): void; - - internalSetSlotFor(slotFor: Prop | null | undefined): void; - - addSlot(slotNode: INode): void; - - onVisibleChange(func: (flag: boolean) => any): () => void; - - getSuitablePlace(node: INode, ref: any): any; - - onChildrenChange(fn: (param?: { type: string; node: INode }) => void): IPublicTypeDisposable | undefined; - - onPropChange(func: (info: IPublicTypePropChangeOptions) => void): IPublicTypeDisposable; - - isModal(): boolean; - - isRoot(): boolean; - - isPage(): boolean; - - isComponent(): boolean; - - isSlot(): boolean; - - isParental(): boolean; - - isLeaf(): boolean; - - isContainer(): boolean; - - isEmpty(): boolean; - - remove( - useMutator?: boolean, - purge?: boolean, - options?: NodeRemoveOptions, - ): void; - - didDropIn(dragment: INode): void; - - didDropOut(dragment: INode): void; - - purge(): void; - - removeSlot(slotNode: INode): boolean; - - setVisible(flag: boolean): void; - - getVisible(): boolean; - - getChildren(): INodeChildren | null; - - clearPropValue(path: string | number): void; - - setProps(props?: IPublicTypePropsMap | IPublicTypePropsList | Props | null): void; - - mergeProps(props: IPublicTypePropsMap): void; - - /** 是否可以选中 */ - canSelect(): boolean; -} +export interface IBaseNode extends Node {} /** * 基础节点 @@ -212,7 +86,34 @@ export interface IBaseNode