diff --git a/docs/docs/api/init.md b/docs/docs/api/init.md index fd0d4fff3..185e76355 100644 --- a/docs/docs/api/init.md +++ b/docs/docs/api/init.md @@ -14,13 +14,13 @@ sidebar_position: 10 **方法定义** ```typescript -function init(container?: Element, options?: EngineOptions): void +function init(container?: Element, options?: IPublicTypeEngineOptions): void ``` **初始化引擎的参数** ```typescript -interface EngineOptions { +interface IPublicTypeEngineOptions { /** * 指定初始化的 device */ @@ -107,7 +107,7 @@ interface EngineOptions { [key: string]: any; } ``` -> 源码详见 [EngineOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/engine-config.ts) +> 源码详见 [IPublicTypeEngineOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/engine-options.ts) ## 使用示例 diff --git a/docs/docs/api/model/node-children.md b/docs/docs/api/model/node-children.md index 4c1b76b61..2e8769411 100644 --- a/docs/docs/api/model/node-children.md +++ b/docs/docs/api/model/node-children.md @@ -13,111 +13,298 @@ sidebar_position: 2 返回当前 children 实例所属的节点实例 +`@type {IPublicModelNode | null}` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + ### size children 内的节点实例数 -### isEmpty +`@type {number}` + + +### isEmptyNode 是否为空 +`@type {boolean}` + +**@since v1.1.0** +> v1.1.0 之前请使用 `isEmpty` + +### notEmptyNode + +是否不为空 + +`@type {boolean}` + +**@since v1.1.0** + ## 方法签名 ### delete - -delete(node: Node) - 删除指定节点 +```typescript +/** + * 删除指定节点 + * delete the node + * @param node + */ +delete(node: IPublicModelNode): boolean; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + ### insert -insert(node: Node, at?: number | null) - 插入一个节点 +```typescript +/** + * 删除指定节点 + * delete the node + * @param node + */ +delete(node: IPublicModelNode): boolean; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### indexOf -indexOf(node: Node) - 返回指定节点的下标 +```typescript +/** + * 返回指定节点的下标 + * get index of node in current children + * @param node + * @returns + */ +indexOf(node: IPublicModelNode): number; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + ### splice -splice(start: number, deleteCount: number, node?: Node) - 类似数组 splice 操作 +```typescript +/** + * 类似数组 splice 操作 + * provide the same function with {Array.prototype.splice} + * @param start + * @param deleteCount + * @param node + */ +splice(start: number, deleteCount: number, node?: IPublicModelNode): any; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### get -get(index: number) - 返回指定下标的节点 +```typescript +/** + * 返回指定下标的节点 + * get node with index + * @param index + * @returns + */ +get(index: number): IPublicModelNode | null; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### has -has(node: Node) - 是否包含指定节点 +```typescript +/** + * 是否包含指定节点 + * check if node exists in current children + * @param node + * @returns + */ +has(node: IPublicModelNode): boolean; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### forEach -forEach(fn: (node: Node, index: number) => void) - 类似数组的 forEach +```typescript +/** + * 类似数组的 forEach + * provide the same function with {Array.prototype.forEach} + * @param fn + */ +forEach(fn: (node: IPublicModelNode, index: number) => void): void; + +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### map -map(fn: (node: Node, index: number) => T[]) - 类似数组的 map +```typescript +/** + * 类似数组的 map + * provide the same function with {Array.prototype.map} + * @param fn + */ +map(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### every -every(fn: (node: Node, index: number) => boolean) - 类似数组的 every +```typescript +/** + * 类似数组的 every + * provide the same function with {Array.prototype.every} + * @param fn + */ +every(fn: (node: IPublicModelNode, index: number) => boolean): boolean; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### some -some(fn: (node: Node, index: number) => boolean) - 类似数组的 some +```typescript +/** + * 类似数组的 some + * provide the same function with {Array.prototype.some} + * @param fn + */ +some(fn: (node: IPublicModelNode, index: number) => boolean): boolean; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### filter -filter(fn: (node: Node, index: number) => boolean) - 类似数组的 filter +```typescript +/** + * 类似数组的 filter + * provide the same function with {Array.prototype.filter} + * @param fn + */ +filter(fn: (node: IPublicModelNode, index: number) => boolean): any; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### find -find(fn: (node: Node, index: number) => boolean) - 类似数组的 find +```typescript +/** + * 类似数组的 find + * provide the same function with {Array.prototype.find} + * @param fn + */ +find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### reduce -reduce(fn: (acc: any, cur: Node) => any, initialValue: any) - 类似数组的 reduce +```typescript +/** + * 类似数组的 reduce + * provide the same function with {Array.prototype.reduce} + * @param fn + */ +reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void; +``` + +相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) + + ### importSchema -importSchema(data?: NodeData | NodeData[]) - 导入 schema +```typescript +/** + * 导入 schema + * import schema + * @param data + */ +importSchema(data?: IPublicTypeNodeData | IPublicTypeNodeData[]): void; +``` + +相关类型:[IPublicTypeNodeData](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/node-data.ts) + + ### exportSchema - -exportSchema(stage: IPulicEnumTransformStage = IPulicEnumTransformStage.Render) - 导出 schema +```typescript +/** + * 导出 schema + * export schema + * @param stage + */ +exportSchema(stage: IPublicEnumTransformStage): IPublicTypeNodeSchema; +``` + +相关类型: +- [IPublicEnumTransformStage](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/enum/transform-stage.ts) +- [IPublicTypeNodeSchema](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/node-schema.ts) + + ### mergeChildren -mergeChildren( - remover: (node: Node, idx: number) => boolean, - adder: (children: Node[]) => any, - sorter: (firstNode: Node, secondNode: Node) => number, - ) +执行新增、删除、排序等操作 -执行新增、删除、排序等操作 \ No newline at end of file +```typescript +/** + * 执行新增、删除、排序等操作 + * excute remove/add/sort operations + * @param remover + * @param adder + * @param sorter + */ +mergeChildren( + remover: (node: IPublicModelNode, idx: number) => boolean, + adder: (children: IPublicModelNode[]) => IPublicTypeNodeData[] | null, + sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number +): any; +``` + +相关类型: +- [IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) +- [IPublicTypeNodeData](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/node-data.ts) diff --git a/docs/package.json b/docs/package.json index 309eaf23b..797a1e3e0 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@alilc/lowcode-engine-docs", - "version": "1.0.12", + "version": "1.0.13", "description": "低代码引擎版本化文档", "license": "MIT", "files": [ diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts index 118d068cf..999dc84a5 100644 --- a/packages/designer/src/designer/designer.ts +++ b/packages/designer/src/designer/designer.ts @@ -59,7 +59,7 @@ export interface DesignerProps { export class Designer implements IDesigner { - readonly dragon = new Dragon(this); + dragon: Dragon; readonly componentActions = new ComponentActions(); @@ -99,6 +99,7 @@ export class Designer implements IDesigner { this.project = new Project(this, props.defaultSchema, viewName); + this.dragon = new Dragon(this); this.dragon.onDragstart((e) => { this.detecting.enable = false; const { dragObject } = e; @@ -564,6 +565,10 @@ export class Designer implements IDesigner { } addPropsReducer(reducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage) { + if (!reducer) { + logger.error('reducer is not available'); + return; + } const reducers = this.propsReducers.get(stage); if (reducers) { reducers.push(reducer); diff --git a/packages/designer/src/document/node/node-children.ts b/packages/designer/src/document/node/node-children.ts index 3604ce4be..9993f4c04 100644 --- a/packages/designer/src/document/node/node-children.ts +++ b/packages/designer/src/document/node/node-children.ts @@ -10,18 +10,68 @@ export interface IOnChangeOptions { node: Node; } -export interface INodeChildren extends IPublicModelNodeChildren { +export interface INodeChildren extends Omit { + 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; + + map(fn: (item: INode, index: number) => T): T[] | null; + + every(fn: (item: INode, index: number) => any): boolean; + + some(fn: (item: INode, index: number) => any): boolean; + + filter(fn: (item: INode, index: number) => any): any; + + find(fn: (item: INode, index: number) => boolean): any; + + reduce(fn: (acc: any, cur: INode) => any, initialValue: any): void; + + mergeChildren( + remover: (node: INode, idx: number) => boolean, + adder: (children: INode[]) => IPublicTypeNodeData[] | null, + sorter: (firstNode: INode, secondNode: INode) => number, + ): any; + + /** overriding methods end */ } export class NodeChildren implements INodeChildren { @obx.shallow private children: INode[]; private emitter: IEventBus = createModuleEventBus('NodeChildren'); - constructor(readonly owner: INode, data: IPublicTypeNodeData | IPublicTypeNodeData[], options: any = {}) { + constructor( + readonly owner: INode, + data: IPublicTypeNodeData | IPublicTypeNodeData[], + options: any = {}, + ) { makeObservable(this); this.children = (Array.isArray(data) ? data : [data]).map((child) => { - return this.owner.document.createNode(child, options.checkId); + return this.owner.document?.createNode(child, options.checkId); }); } @@ -36,7 +86,7 @@ export class NodeChildren implements INodeChildren { stage = compatStage(stage); return this.children.map((node) => { const data = node.export(stage); - if (node.isLeaf() && IPublicEnumTransformStage.Save === stage) { + if (node.isLeafNode && IPublicEnumTransformStage.Save === stage) { // FIXME: filter empty return data.children as IPublicTypeNodeData; } @@ -88,13 +138,21 @@ export class NodeChildren implements INodeChildren { } /** - * 是否空 + * */ isEmpty() { + return this.isEmptyNode; + } + + get isEmptyNode(): boolean { return this.size < 1; } notEmpty() { + return this.notEmptyNode; + } + + get notEmptyNode(): boolean { return this.size > 0; } @@ -132,9 +190,16 @@ export class NodeChildren implements INodeChildren { /** * 删除一个节点 */ - delete(node: INode, purge = false, useMutator = true, options: NodeRemoveOptions = {}): boolean { + delete(node: INode): boolean { + return this.internalDelete(node); + } + + /** + * 删除一个节点 + */ + internalDelete(node: INode, purge = false, useMutator = true, options: NodeRemoveOptions = {}): boolean { node.internalPurgeStart(); - if (node.isParental()) { + if (node.isParentalNode) { foreachReverse( node.children, (subNode: Node) => { @@ -168,9 +233,9 @@ export class NodeChildren implements INodeChildren { const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor'); editor.eventBus.emit('node.remove', { node, index: i }); } - document.unlinkNode(node); - document.selection.remove(node.id); - document.destroyNode(node); + document?.unlinkNode(node); + document?.selection.remove(node.id); + document?.destroyNode(node); this.emitter.emit('change', { type: 'delete', node, @@ -191,10 +256,14 @@ export class NodeChildren implements INodeChildren { return false; } + insert(node: INode, at?: number | null): void { + this.internalInsert(node, at, true); + } + /** * 插入一个节点,返回新长度 */ - insert(node: INode, at?: number | null, useMutator = true): void { + internalInsert(node: INode, at?: number | null, useMutator = true): void { const { children } = this; let index = at == null || at === -1 ? children.length : at; @@ -349,7 +418,7 @@ export class NodeChildren implements INodeChildren { return this.children.some((child, index) => fn(child, index)); } - filter(fn: (item: INode, index: number) => any) { + filter(fn: (item: INode, index: number) => any): any { return this.children.filter(fn); } @@ -384,7 +453,7 @@ export class NodeChildren implements INodeChildren { const items = adder(this.children); if (items && items.length > 0) { items.forEach((child: IPublicTypeNodeData) => { - const node = this.owner.document.createNode(child); + const node = this.owner.document?.createNode(child); this.children.push(node); node.internalSetParent(this.owner); }); @@ -423,10 +492,10 @@ export class NodeChildren implements INodeChildren { if (!node) { return; } - if (node.isRoot()) { + if (node.isRootNode) { return; } - const callbacks = owner.componentMeta.getMetadata().configure.advanced?.callbacks; + const callbacks = owner.componentMeta?.getMetadata().configure.advanced?.callbacks; if (callbacks?.onSubtreeModified) { try { callbacks?.onSubtreeModified.call( @@ -439,7 +508,7 @@ export class NodeChildren implements INodeChildren { } } - if (owner.parent && !owner.parent.isRoot()) { + if (owner.parent && !owner.parent.isRootNode) { this.reportModified(node, owner.parent, { ...options, propagated: true }); } } diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 169dc5cbf..67eb817bf 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -22,7 +22,7 @@ import { compatStage, isDOMText, isJSExpression } from '@alilc/lowcode-utils'; import { SettingTopEntry } from '@alilc/lowcode-designer'; import { Props, getConvertedExtraKey } from './props/props'; import { DocumentModel } from '../document-model'; -import { NodeChildren } from './node-children'; +import { NodeChildren, INodeChildren } from './node-children'; import { Prop } from './props/prop'; import { ComponentMeta } from '../../component-meta'; import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group'; @@ -36,6 +36,22 @@ export interface INode extends IPublicModelNode { setVisible(flag: boolean): void; getVisible(): boolean; + + /** + * 内部方法,请勿使用 + * @param useMutator 是否触发联动逻辑 + */ + internalSetParent(parent: INode | null, useMutator: boolean): void; + + setConditionGroup(grp: IPublicModelExclusiveGroup | string | null): void; + + internalToShellNode(): IPublicModelNode | null; + + internalPurgeStart(): void; + + unlinkSlot(slotNode: Node): void; + + didDropOut(dragment: Node): void; } /** @@ -116,7 +132,7 @@ export class Node */ props: Props; - protected _children?: NodeChildren; + protected _children?: INodeChildren; /** * @deprecated @@ -135,7 +151,7 @@ export class Node /** * 当前节点子集 */ - get children(): NodeChildren | null { + get children(): INodeChildren | null { return this._children || null; } @@ -390,7 +406,7 @@ export class Node if (this.isSlot()) { this._parent.unlinkSlot(this); } else { - this._parent.children.unlinkChild(this); + this._parent.children?.unlinkChild(this); } } if (useMutator) { @@ -449,9 +465,9 @@ export class Node } if (this.isSlot()) { this.parent.removeSlot(this, purge); - this.parent.children.delete(this, purge, useMutator, { suppressRemoveEvent: true }); + this.parent.children.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true }); } else { - this.parent.children.delete(this, purge, useMutator, { suppressRemoveEvent: true }); + this.parent.children.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true }); } } } @@ -965,12 +981,12 @@ export class Node insertBefore(node: Node, ref?: Node, useMutator = true) { const nodeInstance = ensureNode(node, this.document); - this.children?.insert(nodeInstance, ref ? ref.index : null, useMutator); + this.children?.internalInsert(nodeInstance, ref ? ref.index : null, useMutator); } insertAfter(node: any, ref?: Node, useMutator = true) { const nodeInstance = ensureNode(node, this.document); - this.children?.insert(nodeInstance, ref ? ref.index + 1 : null, useMutator); + this.children?.internalInsert(nodeInstance, ref ? ref.index + 1 : null, useMutator); } getParent() { @@ -1337,7 +1353,7 @@ export function insertChild( node = container.document.createNode(thing); } - container.children.insert(node, at); + container.children.internalInsert(node, at); return node; } diff --git a/packages/designer/tests/designer/designer.test.ts b/packages/designer/tests/designer/designer.test.ts index 4a00017e8..8bca7d84a 100644 --- a/packages/designer/tests/designer/designer.test.ts +++ b/packages/designer/tests/designer/designer.test.ts @@ -103,6 +103,7 @@ describe('Designer 测试', () => { return x; }, insert() {}, + internalInsert() {}, }, }; const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } }; @@ -172,6 +173,7 @@ describe('Designer 测试', () => { return x; }, insert() {}, + internalInsert() {}, }, }; const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } }; @@ -407,6 +409,7 @@ describe('Designer 测试', () => { return x; }, insert() {}, + internalInsert() {}, }, }; const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } }; @@ -431,6 +434,7 @@ describe('Designer 测试', () => { return x; }, insert() {}, + internalInsert() {}, }, }, detail: mockDetail, diff --git a/packages/editor-core/src/config.ts b/packages/editor-core/src/config.ts index 344529690..91ef33adb 100644 --- a/packages/editor-core/src/config.ts +++ b/packages/editor-core/src/config.ts @@ -1,7 +1,7 @@ import { get as lodashGet } from 'lodash'; import { isPlainObject } from '@alilc/lowcode-utils'; import { - EngineOptions, + IPublicTypeEngineOptions, IPublicModelEngineConfig, IPublicModelPreference, } from '@alilc/lowcode-types'; @@ -150,7 +150,7 @@ const VALID_ENGINE_OPTIONS = { }; -const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean): boolean => { +const getStrictModeValue = (engineOptions: IPublicTypeEngineOptions, defaultValue: boolean): boolean => { if (!engineOptions || !isPlainObject(engineOptions)) { return defaultValue; } @@ -165,10 +165,9 @@ export interface IEngineConfigPrivate { /** * if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions. * - * @param {EngineOptions} engineOptions - * @memberof EngineConfig + * @param {IPublicTypeEngineOptions} engineOptions */ - setEngineOptions(engineOptions: EngineOptions): void; + setEngineOptions(engineOptions: IPublicTypeEngineOptions): void; notifyGot(key: string): void; @@ -203,7 +202,6 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv /** * 判断指定 key 是否有值 * @param key - * @returns */ has(key: string): boolean { return this.config[key] !== undefined; @@ -213,7 +211,6 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv * 获取指定 key 的值 * @param key * @param defaultValue - * @returns */ get(key: string, defaultValue?: any): any { return lodashGet(this.config, key, defaultValue); @@ -244,10 +241,9 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv /** * if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions. * - * @param {EngineOptions} engineOptions - * @memberof EngineConfig + * @param {IPublicTypeEngineOptions} engineOptions */ - setEngineOptions(engineOptions: EngineOptions) { + setEngineOptions(engineOptions: IPublicTypeEngineOptions) { if (!engineOptions || !isPlainObject(engineOptions)) { return; } diff --git a/packages/engine/src/engine-core.ts b/packages/engine/src/engine-core.ts index a580380a1..b4302f86b 100644 --- a/packages/engine/src/engine-core.ts +++ b/packages/engine/src/engine-core.ts @@ -11,7 +11,7 @@ import { Hotkey as InnerHotkey, } from '@alilc/lowcode-editor-core'; import { - EngineOptions, + IPublicTypeEngineOptions, IPublicModelDocumentModel, IPublicTypePluginMeta, } from '@alilc/lowcode-types'; @@ -158,7 +158,7 @@ engineConfig.set('ENGINE_VERSION', version); export async function init( container?: HTMLElement, - options?: EngineOptions, + options?: IPublicTypeEngineOptions, pluginPreference?: PluginPreference, ) { await destroy(); diff --git a/packages/renderer-core/src/hoc/leaf.tsx b/packages/renderer-core/src/hoc/leaf.tsx index 695d1bf29..8af892f05 100644 --- a/packages/renderer-core/src/hoc/leaf.tsx +++ b/packages/renderer-core/src/hoc/leaf.tsx @@ -1,5 +1,5 @@ import { BuiltinSimulatorHost, Node, IPublicTypePropChangeOptions } from '@alilc/lowcode-designer'; -import { GlobalEvent, IPublicEnumTransformStage, IPublicTypeNodeSchema, EngineOptions } from '@alilc/lowcode-types'; +import { GlobalEvent, IPublicEnumTransformStage, IPublicTypeNodeSchema, IPublicTypeEngineOptions } from '@alilc/lowcode-types'; import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils'; import { debounce } from '../utils/common'; import adapter from '../adapter'; @@ -30,7 +30,7 @@ export interface IComponentHocState { nodeProps: any; } -type DesignMode = Pick['designMode']; +type DesignMode = Pick['designMode']; export interface IComponentHoc { designMode: DesignMode | DesignMode[]; diff --git a/packages/shell/src/api/canvas.ts b/packages/shell/src/api/canvas.ts index 6c7040311..9e729467f 100644 --- a/packages/shell/src/api/canvas.ts +++ b/packages/shell/src/api/canvas.ts @@ -26,7 +26,7 @@ export class Canvas implements IPublicApiCanvas { return this[editorSymbol].get('designer') as IDesigner; } - constructor(editor: IPublicModelEditor) { + constructor(editor: IPublicModelEditor, readonly workspaceMode: boolean = false) { this[editorSymbol] = editor; } @@ -49,7 +49,7 @@ export class Canvas implements IPublicApiCanvas { } get dragon(): IPublicModelDragon | null { - return Dragon.create(this[designerSymbol].dragon); + return Dragon.create(this[designerSymbol].dragon, this.workspaceMode); } get activeTracker(): IPublicModelActiveTracker | null { diff --git a/packages/shell/src/model/dragon.ts b/packages/shell/src/model/dragon.ts index 38fa6323e..cc3f7a0f1 100644 --- a/packages/shell/src/model/dragon.ts +++ b/packages/shell/src/model/dragon.ts @@ -19,11 +19,14 @@ export const innerDragonSymbol = Symbol('innerDragonSymbol'); export class Dragon implements IPublicModelDragon { private readonly [innerDragonSymbol]: IPublicModelDragon; - constructor(innerDragon: IPublicModelDragon) { + constructor(innerDragon: IPublicModelDragon, readonly workspaceMode: boolean) { this[innerDragonSymbol] = innerDragon; } get [dragonSymbol](): any { + if (this.workspaceMode) { + return this[innerDragonSymbol]; + } const workspace = globalContext.get('workspace'); let editor = globalContext.get('editor'); @@ -35,11 +38,11 @@ export class Dragon implements IPublicModelDragon { return designer.dragon; } - static create(dragon: IPublicModelDragon | null): IPublicModelDragon | null { + static create(dragon: IPublicModelDragon | null, workspaceMode: boolean): IPublicModelDragon | null { if (!dragon) { return null; } - return new Dragon(dragon); + return new Dragon(dragon, workspaceMode); } /** diff --git a/packages/shell/src/model/node-children.ts b/packages/shell/src/model/node-children.ts index 702cfa82f..9f8792ee3 100644 --- a/packages/shell/src/model/node-children.ts +++ b/packages/shell/src/model/node-children.ts @@ -1,16 +1,16 @@ -import { Node as InnerNode } from '@alilc/lowcode-designer'; -import { IPublicTypeNodeSchema, IPublicTypeNodeData, IPublicEnumTransformStage, IPublicModelNodeChildren, IPublicModelNode } from '@alilc/lowcode-types'; +import { INode as InnerNode, INodeChildren } from '@alilc/lowcode-designer'; +import { IPublicTypeNodeData, IPublicEnumTransformStage, IPublicModelNodeChildren, IPublicModelNode } from '@alilc/lowcode-types'; import { Node } from './node'; import { nodeSymbol, nodeChildrenSymbol } from '../symbols'; export class NodeChildren implements IPublicModelNodeChildren { - private readonly [nodeChildrenSymbol]: IPublicModelNodeChildren; + private readonly [nodeChildrenSymbol]: INodeChildren; - constructor(nodeChildren: IPublicModelNodeChildren) { + constructor(nodeChildren: INodeChildren) { this[nodeChildrenSymbol] = nodeChildren; } - static create(nodeChildren: IPublicModelNodeChildren | null): IPublicModelNodeChildren | null { + static create(nodeChildren: INodeChildren | null): IPublicModelNodeChildren | null { if (!nodeChildren) { return null; } @@ -37,7 +37,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @returns */ get isEmpty(): boolean { - return this[nodeChildrenSymbol].isEmpty(); + return this[nodeChildrenSymbol].isEmptyNode; } /** @@ -45,7 +45,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @returns */ get isEmptyNode(): boolean { - return this[nodeChildrenSymbol].isEmpty(); + return this[nodeChildrenSymbol].isEmptyNode; } /** @@ -53,23 +53,23 @@ export class NodeChildren implements IPublicModelNodeChildren { * judge if it is not empty */ get notEmpty(): boolean { - return this[nodeChildrenSymbol].notEmpty(); + return this[nodeChildrenSymbol].notEmptyNode; } /** * judge if it is not empty */ get notEmptyNode(): boolean { - return this[nodeChildrenSymbol].notEmpty(); + return this[nodeChildrenSymbol].notEmptyNode; } /** * 删除指定节点 + * delete the node * @param node - * @returns */ delete(node: IPublicModelNode): boolean { - return this[nodeChildrenSymbol].delete((node as any)); + return this[nodeChildrenSymbol].delete((node as any)?.[nodeSymbol]); } /** @@ -79,7 +79,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @returns */ insert(node: IPublicModelNode, at?: number | null): void { - return this[nodeChildrenSymbol].insert((node as any), at, true); + return this[nodeChildrenSymbol].insert((node as any)?.[nodeSymbol], at); } /** @@ -88,7 +88,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @returns */ indexOf(node: IPublicModelNode): number { - return this[nodeChildrenSymbol].indexOf((node as any)); + return this[nodeChildrenSymbol].indexOf((node as any)?.[nodeSymbol]); } /** @@ -106,7 +106,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @param index * @returns */ - get(index: number): any { + get(index: number): IPublicModelNode | null { return Node.create(this[nodeChildrenSymbol].get(index)); } @@ -116,7 +116,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @returns */ has(node: IPublicModelNode): boolean { - return this[nodeChildrenSymbol].has((node as any)); + return this[nodeChildrenSymbol].has((node as any)?.[nodeSymbol]); } /** @@ -124,7 +124,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @param fn */ forEach(fn: (node: IPublicModelNode, index: number) => void): void { - this[nodeChildrenSymbol].forEach((item: InnerNode, index: number) => { + this[nodeChildrenSymbol].forEach((item: InnerNode, index: number) => { fn(Node.create(item)!, index); }); } @@ -134,7 +134,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @param fn */ map(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null { - return this[nodeChildrenSymbol].map((item: InnerNode, index: number) => { + return this[nodeChildrenSymbol].map((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }); } @@ -144,7 +144,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @param fn */ every(fn: (node: IPublicModelNode, index: number) => boolean): boolean { - return this[nodeChildrenSymbol].every((item: InnerNode, index: number) => { + return this[nodeChildrenSymbol].every((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }); } @@ -154,7 +154,7 @@ export class NodeChildren implements IPublicModelNodeChildren { * @param fn */ some(fn: (node: IPublicModelNode, index: number) => boolean): boolean { - return this[nodeChildrenSymbol].some((item: InnerNode, index: number) => { + return this[nodeChildrenSymbol].some((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }); } @@ -165,10 +165,10 @@ export class NodeChildren implements IPublicModelNodeChildren { */ filter(fn: (node: IPublicModelNode, index: number) => boolean): any { return this[nodeChildrenSymbol] - .filter((item: InnerNode, index: number) => { + .filter((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }) - .map((item: InnerNode) => Node.create(item)!); + .map((item: InnerNode) => Node.create(item)!); } /** @@ -177,7 +177,7 @@ export class NodeChildren implements IPublicModelNodeChildren { */ find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null { return Node.create( - this[nodeChildrenSymbol].find((item: InnerNode, index: number) => { + this[nodeChildrenSymbol].find((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }), ); @@ -219,8 +219,9 @@ export class NodeChildren implements IPublicModelNodeChildren { mergeChildren( remover: (node: IPublicModelNode, idx: number) => boolean, adder: (children: IPublicModelNode[]) => any, - sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number, + originalSorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number, ) { + let sorter = originalSorter; if (!sorter) { sorter = () => 0; } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 3c80e6389..5e7217550 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -26,6 +26,5 @@ export * from './designer'; export * from './dragon'; export * from './shell'; export * from './shell-model-factory'; -export * from './engine-config'; // TODO: remove this in future versions export * from './deprecated'; diff --git a/packages/types/src/shell/model/node-children.ts b/packages/types/src/shell/model/node-children.ts index e0df7d24c..c6fde9403 100644 --- a/packages/types/src/shell/model/node-children.ts +++ b/packages/types/src/shell/model/node-children.ts @@ -5,11 +5,13 @@ import { IPublicModelNode } from './'; export interface IPublicModelNodeChildren { /** * 返回当前 children 实例所属的节点实例 + * get owner node of this nodeChildren */ get owner(): IPublicModelNode | null; /** * children 内的节点实例数 + * get count of child nodes */ get size(): number; @@ -39,13 +41,14 @@ export interface IPublicModelNodeChildren { /** * 删除指定节点 + * delete the node * @param node - * @returns */ delete(node: IPublicModelNode): boolean; /** * 插入一个节点 + * insert a node at specific position * @param node 待插入节点 * @param at 插入下标 * @returns @@ -54,6 +57,7 @@ export interface IPublicModelNodeChildren { /** * 返回指定节点的下标 + * get index of node in current children * @param node * @returns */ @@ -61,6 +65,7 @@ export interface IPublicModelNodeChildren { /** * 类似数组 splice 操作 + * provide the same function with {Array.prototype.splice} * @param start * @param deleteCount * @param node @@ -69,13 +74,15 @@ export interface IPublicModelNodeChildren { /** * 返回指定下标的节点 + * get node with index * @param index * @returns */ - get(index: number): any; + get(index: number): IPublicModelNode | null; /** * 是否包含指定节点 + * check if node exists in current children * @param node * @returns */ @@ -83,55 +90,74 @@ export interface IPublicModelNodeChildren { /** * 类似数组的 forEach + * provide the same function with {Array.prototype.forEach} * @param fn */ forEach(fn: (node: IPublicModelNode, index: number) => void): void; /** * 类似数组的 map + * provide the same function with {Array.prototype.map} * @param fn */ map(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null; /** * 类似数组的 every + * provide the same function with {Array.prototype.every} * @param fn */ every(fn: (node: IPublicModelNode, index: number) => boolean): boolean; /** * 类似数组的 some + * provide the same function with {Array.prototype.some} * @param fn */ some(fn: (node: IPublicModelNode, index: number) => boolean): boolean; /** * 类似数组的 filter + * provide the same function with {Array.prototype.filter} * @param fn */ filter(fn: (node: IPublicModelNode, index: number) => boolean): any; /** * 类似数组的 find + * provide the same function with {Array.prototype.find} * @param fn */ find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null; + /** + * 类似数组的 reduce + * provide the same function with {Array.prototype.reduce} + * @param fn + */ reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void; /** * 导入 schema + * import schema * @param data */ importSchema(data?: IPublicTypeNodeData | IPublicTypeNodeData[]): void; /** * 导出 schema + * export schema * @param stage - * @returns */ exportSchema(stage: IPublicEnumTransformStage): IPublicTypeNodeSchema; + /** + * 执行新增、删除、排序等操作 + * excute remove/add/sort operations + * @param remover + * @param adder + * @param sorter + */ mergeChildren( remover: (node: IPublicModelNode, idx: number) => boolean, adder: (children: IPublicModelNode[]) => IPublicTypeNodeData[] | null, diff --git a/packages/types/src/engine-config.ts b/packages/types/src/shell/type/engine-options.ts similarity index 89% rename from packages/types/src/engine-config.ts rename to packages/types/src/shell/type/engine-options.ts index 4c97433fb..195db8912 100644 --- a/packages/types/src/engine-config.ts +++ b/packages/types/src/shell/type/engine-options.ts @@ -1,99 +1,129 @@ import { RequestHandlersMap } from '@alilc/lowcode-datasource-types'; import { ComponentType } from 'react'; -export interface EngineOptions { +export interface IPublicTypeEngineOptions { /** * 是否开启 condition 的能力,默认在设计器中不管 condition 是啥都正常展示 + * when this is true, node that configured as conditional not renderring + * will not display in canvas. + * @default false */ enableCondition?: boolean; + /** - * @todo designMode 无法映射到文档渲染模块 + * TODO: designMode 无法映射到文档渲染模块 * * 设计模式,live 模式将会实时展示变量值,默认值:'design' + * + * @default 'design' + * @experimental */ designMode?: 'design' | 'live'; + /** * 设备类型,默认值:'default' + * @default 'default' */ device?: 'default' | 'mobile' | string; + /** * 指定初始化的 deviceClassName,挂载到画布的顶层节点上 */ deviceClassName?: string; + /** * 语言,默认值:'zh-CN' + * @default 'zh-CN' */ locale?: string; + /** * 渲染器类型,默认值:'react' */ renderEnv?: 'react' | 'rax' | string; + /** * 设备类型映射器,处理设计器与渲染器中 device 的映射 */ deviceMapper?: { transform: (originalDevice: string) => string; }; + /** * 开启严格插件模式,默认值:STRICT_PLUGIN_MODE_DEFAULT , 严格模式下,插件将无法通过 engineOptions 传递自定义配置项 * enable strict plugin mode, default value: false * under strict mode, customed engineOption is not accepted. */ - enableStrictPluginMode?: boolean; + enableStrictPluginMode?: boolean; + /** * 开启拖拽组件时,即将被放入的容器是否有视觉反馈,默认值:false */ enableReactiveContainer?: boolean; + /** * 关闭画布自动渲染,在资产包多重异步加载的场景有效,默认值:false */ disableAutoRender?: boolean; + /** * 关闭拖拽组件时的虚线响应,性能考虑,默认值:false */ disableDetecting?: boolean; + /** * 定制画布中点击被忽略的 selectors,默认值:undefined */ customizeIgnoreSelectors?: (defaultIgnoreSelectors: string[], e: MouseEvent) => string[]; + /** * 禁止默认的设置面板,默认值:false */ disableDefaultSettingPanel?: boolean; + /** * 禁止默认的设置器,默认值:false */ disableDefaultSetters?: boolean; + /** * 打开画布的锁定操作,默认值:false */ enableCanvasLock?: boolean; + /** * 容器锁定后,容器本身是否可以设置属性,仅当画布锁定特性开启时生效,默认值为:false */ enableLockedNodeSetting?: boolean; + /** * 当选中节点切换时,是否停留在相同的设置 tab 上,默认值:false */ stayOnTheSameSettingTab?: boolean; + /** * 是否在只有一个 item 的时候隐藏设置 tabs,默认值:false */ hideSettingsTabsWhenOnlyOneItem?: boolean; + /** * 自定义 loading 组件 */ loadingComponent?: ComponentType; + /** * 设置所有属性支持变量配置,默认值:false */ supportVariableGlobally?: boolean; + /** * 设置 simulator 相关的 url,默认值:undefined */ simulatorUrl?: string[]; + /** * Vision-polyfill settings + * @deprecated this exists for some legacy reasons */ visionSettings?: { // 是否禁用降级 reducer,默认值:false @@ -101,6 +131,7 @@ export interface EngineOptions { // 是否开启在 render 阶段开启 filter reducer,默认值:false enableFilterReducerInRenderStage?: boolean; }; + /** * 与 react-renderer 的 appHelper 一致,https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper */ @@ -138,3 +169,10 @@ export interface EngineOptions { */ enableWorkspaceMode?: boolean; } + +/** + * @deprecated use IPublicTypeEngineOptions instead + */ +export interface EngineOptions { + +} \ No newline at end of file diff --git a/packages/types/src/shell/type/index.ts b/packages/types/src/shell/type/index.ts index 99a510292..c1f70b605 100644 --- a/packages/types/src/shell/type/index.ts +++ b/packages/types/src/shell/type/index.ts @@ -73,4 +73,5 @@ export * from './tip-config'; export * from './widget-config-area'; export * from './hotkey-callback'; export * from './plugin-register-options'; -export * from './resource-options'; \ No newline at end of file +export * from './resource-options'; +export * from './engine-options'; \ No newline at end of file diff --git a/packages/workspace/src/base-context.ts b/packages/workspace/src/base-context.ts index 8ab26e455..0ff63ee02 100644 --- a/packages/workspace/src/base-context.ts +++ b/packages/workspace/src/base-context.ts @@ -81,7 +81,7 @@ export class BasicContext { const event = new Event(commonEvent, { prefix: 'common' }); const logger = getLogger({ level: 'warn', bizName: 'common' }); const skeleton = new Skeleton(innerSkeleton, 'any', true); - const canvas = new Canvas(editor); + const canvas = new Canvas(editor, true); editor.set('setters', setters); editor.set('project', project); editor.set('material', material); diff --git a/packages/workspace/src/layouts/workbench.less b/packages/workspace/src/layouts/workbench.less index 0639a1fa1..95574871a 100644 --- a/packages/workspace/src/layouts/workbench.less +++ b/packages/workspace/src/layouts/workbench.less @@ -153,6 +153,7 @@ body { .lc-top-area-left, .lc-sub-top-area-left { display: flex; align-items: center; + max-width: 100%; } .lc-top-area-center, .lc-sub-top-area-center { @@ -361,6 +362,18 @@ body { } } + .lc-workspace-workbench-center-content { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .engine-actionitem { + max-width: 100%; + } + .lc-workspace-workbench-window { position: relative; height: 100%; diff --git a/packages/workspace/src/layouts/workbench.tsx b/packages/workspace/src/layouts/workbench.tsx index 66ddb7de0..7ffb0e531 100644 --- a/packages/workspace/src/layouts/workbench.tsx +++ b/packages/workspace/src/layouts/workbench.tsx @@ -41,7 +41,7 @@ export class Workbench extends Component<{
- <> +
{ @@ -54,7 +54,7 @@ export class Workbench extends Component<{ )) }
- +
diff --git a/packages/workspace/src/workspace.ts b/packages/workspace/src/workspace.ts index 8256ee9f5..05d2e666a 100644 --- a/packages/workspace/src/workspace.ts +++ b/packages/workspace/src/workspace.ts @@ -101,7 +101,7 @@ export class Workspace implements IPublicApiWorkspace { private remove(index: number) { const window = this.windows[index]; - this.windows = this.windows.splice(index - 1, 1); + this.windows.splice(index, 1); if (this.window === window) { this.window = this.windows[index] || this.windows[index + 1] || this.windows[index - 1]; this.emitChangeActiveWindow();