Merge branch 'develop' into release/1.1.0-beta

This commit is contained in:
JackLian 2023-01-05 12:02:14 +08:00
commit 26036f89d1
21 changed files with 481 additions and 123 deletions

View File

@ -14,13 +14,13 @@ sidebar_position: 10
**方法定义** **方法定义**
```typescript ```typescript
function init(container?: Element, options?: EngineOptions): void function init(container?: Element, options?: IPublicTypeEngineOptions): void
``` ```
**初始化引擎的参数** **初始化引擎的参数**
```typescript ```typescript
interface EngineOptions { interface IPublicTypeEngineOptions {
/** /**
* 指定初始化的 device * 指定初始化的 device
*/ */
@ -107,7 +107,7 @@ interface EngineOptions {
[key: string]: any; [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)
## 使用示例 ## 使用示例

View File

@ -13,111 +13,298 @@ sidebar_position: 2
返回当前 children 实例所属的节点实例 返回当前 children 实例所属的节点实例
`@type {IPublicModelNode | null}`
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
### size ### size
children 内的节点实例数 children 内的节点实例数
### isEmpty `@type {number}`
### isEmptyNode
是否为空 是否为空
`@type {boolean}`
**@since v1.1.0**
> v1.1.0 之前请使用 `isEmpty`
### notEmptyNode
是否不为空
`@type {boolean}`
**@since v1.1.0**
## 方法签名 ## 方法签名
### delete ### 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
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
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
splice(start: number, deleteCount: number, node?: Node)
类似数组 splice 操作 类似数组 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
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
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
forEach(fn: (node: Node, index: number) => void)
类似数组的 forEach 类似数组的 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
map<T\>(fn: (node: Node, index: number) => T[])
类似数组的 map 类似数组的 map
```typescript
/**
* 类似数组的 map
* provide the same function with {Array.prototype.map}
* @param fn
*/
map<T>(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
every(fn: (node: Node, index: number) => boolean)
类似数组的 every 类似数组的 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
some(fn: (node: Node, index: number) => boolean)
类似数组的 some 类似数组的 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
filter(fn: (node: Node, index: number) => boolean)
类似数组的 filter 类似数组的 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
find(fn: (node: Node, index: number) => boolean)
类似数组的 find 类似数组的 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
reduce(fn: (acc: any, cur: Node) => any, initialValue: any)
类似数组的 reduce 类似数组的 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
importSchema(data?: NodeData | NodeData[])
导入 schema 导入 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
exportSchema(stage: IPulicEnumTransformStage = IPulicEnumTransformStage.Render)
导出 schema 导出 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
mergeChildren( 执行新增、删除、排序等操作
remover: (node: Node, idx: number) => boolean,
adder: (children: Node[]) => any,
sorter: (firstNode: Node, secondNode: Node) => number,
)
执行新增、删除、排序等操作 ```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)

View File

@ -1,6 +1,6 @@
{ {
"name": "@alilc/lowcode-engine-docs", "name": "@alilc/lowcode-engine-docs",
"version": "1.0.12", "version": "1.0.13",
"description": "低代码引擎版本化文档", "description": "低代码引擎版本化文档",
"license": "MIT", "license": "MIT",
"files": [ "files": [

View File

@ -59,7 +59,7 @@ export interface DesignerProps {
export class Designer implements IDesigner { export class Designer implements IDesigner {
readonly dragon = new Dragon(this); dragon: Dragon;
readonly componentActions = new ComponentActions(); readonly componentActions = new ComponentActions();
@ -99,6 +99,7 @@ export class Designer implements IDesigner {
this.project = new Project(this, props.defaultSchema, viewName); this.project = new Project(this, props.defaultSchema, viewName);
this.dragon = new Dragon(this);
this.dragon.onDragstart((e) => { this.dragon.onDragstart((e) => {
this.detecting.enable = false; this.detecting.enable = false;
const { dragObject } = e; const { dragObject } = e;
@ -564,6 +565,10 @@ export class Designer implements IDesigner {
} }
addPropsReducer(reducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage) { addPropsReducer(reducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage) {
if (!reducer) {
logger.error('reducer is not available');
return;
}
const reducers = this.propsReducers.get(stage); const reducers = this.propsReducers.get(stage);
if (reducers) { if (reducers) {
reducers.push(reducer); reducers.push(reducer);

View File

@ -10,18 +10,68 @@ export interface IOnChangeOptions {
node: Node; node: Node;
} }
export interface INodeChildren extends IPublicModelNodeChildren { export interface INodeChildren extends Omit<IPublicModelNodeChildren, 'forEach' | 'map' | 'every' | 'some' | 'filter' | 'find' | 'reduce' | 'mergeChildren' > {
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<T>(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 { export class NodeChildren implements INodeChildren {
@obx.shallow private children: INode[]; @obx.shallow private children: INode[];
private emitter: IEventBus = createModuleEventBus('NodeChildren'); 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); makeObservable(this);
this.children = (Array.isArray(data) ? data : [data]).map((child) => { 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); stage = compatStage(stage);
return this.children.map((node) => { return this.children.map((node) => {
const data = node.export(stage); const data = node.export(stage);
if (node.isLeaf() && IPublicEnumTransformStage.Save === stage) { if (node.isLeafNode && IPublicEnumTransformStage.Save === stage) {
// FIXME: filter empty // FIXME: filter empty
return data.children as IPublicTypeNodeData; return data.children as IPublicTypeNodeData;
} }
@ -88,13 +138,21 @@ export class NodeChildren implements INodeChildren {
} }
/** /**
* *
*/ */
isEmpty() { isEmpty() {
return this.isEmptyNode;
}
get isEmptyNode(): boolean {
return this.size < 1; return this.size < 1;
} }
notEmpty() { notEmpty() {
return this.notEmptyNode;
}
get notEmptyNode(): boolean {
return this.size > 0; 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(); node.internalPurgeStart();
if (node.isParental()) { if (node.isParentalNode) {
foreachReverse( foreachReverse(
node.children, node.children,
(subNode: Node) => { (subNode: Node) => {
@ -168,9 +233,9 @@ export class NodeChildren implements INodeChildren {
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor'); const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
editor.eventBus.emit('node.remove', { node, index: i }); editor.eventBus.emit('node.remove', { node, index: i });
} }
document.unlinkNode(node); document?.unlinkNode(node);
document.selection.remove(node.id); document?.selection.remove(node.id);
document.destroyNode(node); document?.destroyNode(node);
this.emitter.emit('change', { this.emitter.emit('change', {
type: 'delete', type: 'delete',
node, node,
@ -191,10 +256,14 @@ export class NodeChildren implements INodeChildren {
return false; 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; const { children } = this;
let index = at == null || at === -1 ? children.length : at; 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)); 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); return this.children.filter(fn);
} }
@ -384,7 +453,7 @@ export class NodeChildren implements INodeChildren {
const items = adder(this.children); const items = adder(this.children);
if (items && items.length > 0) { if (items && items.length > 0) {
items.forEach((child: IPublicTypeNodeData) => { items.forEach((child: IPublicTypeNodeData) => {
const node = this.owner.document.createNode(child); const node = this.owner.document?.createNode(child);
this.children.push(node); this.children.push(node);
node.internalSetParent(this.owner); node.internalSetParent(this.owner);
}); });
@ -423,10 +492,10 @@ export class NodeChildren implements INodeChildren {
if (!node) { if (!node) {
return; return;
} }
if (node.isRoot()) { if (node.isRootNode) {
return; return;
} }
const callbacks = owner.componentMeta.getMetadata().configure.advanced?.callbacks; const callbacks = owner.componentMeta?.getMetadata().configure.advanced?.callbacks;
if (callbacks?.onSubtreeModified) { if (callbacks?.onSubtreeModified) {
try { try {
callbacks?.onSubtreeModified.call( 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 }); this.reportModified(node, owner.parent, { ...options, propagated: true });
} }
} }

View File

@ -22,7 +22,7 @@ import { compatStage, isDOMText, isJSExpression } from '@alilc/lowcode-utils';
import { SettingTopEntry } from '@alilc/lowcode-designer'; import { SettingTopEntry } from '@alilc/lowcode-designer';
import { Props, getConvertedExtraKey } from './props/props'; import { Props, getConvertedExtraKey } from './props/props';
import { DocumentModel } from '../document-model'; import { DocumentModel } from '../document-model';
import { NodeChildren } from './node-children'; import { NodeChildren, INodeChildren } from './node-children';
import { Prop } from './props/prop'; import { Prop } from './props/prop';
import { ComponentMeta } from '../../component-meta'; import { ComponentMeta } from '../../component-meta';
import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group'; import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
@ -36,6 +36,22 @@ export interface INode extends IPublicModelNode {
setVisible(flag: boolean): void; setVisible(flag: boolean): void;
getVisible(): boolean; 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<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
*/ */
props: Props; props: Props;
protected _children?: NodeChildren; protected _children?: INodeChildren;
/** /**
* @deprecated * @deprecated
@ -135,7 +151,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/** /**
* *
*/ */
get children(): NodeChildren | null { get children(): INodeChildren | null {
return this._children || null; return this._children || null;
} }
@ -390,7 +406,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
if (this.isSlot()) { if (this.isSlot()) {
this._parent.unlinkSlot(this); this._parent.unlinkSlot(this);
} else { } else {
this._parent.children.unlinkChild(this); this._parent.children?.unlinkChild(this);
} }
} }
if (useMutator) { if (useMutator) {
@ -449,9 +465,9 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
} }
if (this.isSlot()) { if (this.isSlot()) {
this.parent.removeSlot(this, purge); this.parent.removeSlot(this, purge);
this.parent.children.delete(this, purge, useMutator, { suppressRemoveEvent: true }); this.parent.children.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true });
} else { } 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<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
insertBefore(node: Node, ref?: Node, useMutator = true) { insertBefore(node: Node, ref?: Node, useMutator = true) {
const nodeInstance = ensureNode(node, this.document); 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) { insertAfter(node: any, ref?: Node, useMutator = true) {
const nodeInstance = ensureNode(node, this.document); 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() { getParent() {
@ -1337,7 +1353,7 @@ export function insertChild(
node = container.document.createNode(thing); node = container.document.createNode(thing);
} }
container.children.insert(node, at); container.children.internalInsert(node, at);
return node; return node;
} }

View File

@ -103,6 +103,7 @@ describe('Designer 测试', () => {
return x; return x;
}, },
insert() {}, insert() {},
internalInsert() {},
}, },
}; };
const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } }; const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } };
@ -172,6 +173,7 @@ describe('Designer 测试', () => {
return x; return x;
}, },
insert() {}, insert() {},
internalInsert() {},
}, },
}; };
const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } }; const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } };
@ -407,6 +409,7 @@ describe('Designer 测试', () => {
return x; return x;
}, },
insert() {}, insert() {},
internalInsert() {},
}, },
}; };
const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } }; const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } };
@ -431,6 +434,7 @@ describe('Designer 测试', () => {
return x; return x;
}, },
insert() {}, insert() {},
internalInsert() {},
}, },
}, },
detail: mockDetail, detail: mockDetail,

View File

@ -1,7 +1,7 @@
import { get as lodashGet } from 'lodash'; import { get as lodashGet } from 'lodash';
import { isPlainObject } from '@alilc/lowcode-utils'; import { isPlainObject } from '@alilc/lowcode-utils';
import { import {
EngineOptions, IPublicTypeEngineOptions,
IPublicModelEngineConfig, IPublicModelEngineConfig,
IPublicModelPreference, IPublicModelPreference,
} from '@alilc/lowcode-types'; } 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)) { if (!engineOptions || !isPlainObject(engineOptions)) {
return defaultValue; return defaultValue;
} }
@ -165,10 +165,9 @@ export interface IEngineConfigPrivate {
/** /**
* if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions. * if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions.
* *
* @param {EngineOptions} engineOptions * @param {IPublicTypeEngineOptions} engineOptions
* @memberof EngineConfig
*/ */
setEngineOptions(engineOptions: EngineOptions): void; setEngineOptions(engineOptions: IPublicTypeEngineOptions): void;
notifyGot(key: string): void; notifyGot(key: string): void;
@ -203,7 +202,6 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv
/** /**
* key * key
* @param key * @param key
* @returns
*/ */
has(key: string): boolean { has(key: string): boolean {
return this.config[key] !== undefined; return this.config[key] !== undefined;
@ -213,7 +211,6 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv
* key * key
* @param key * @param key
* @param defaultValue * @param defaultValue
* @returns
*/ */
get(key: string, defaultValue?: any): any { get(key: string, defaultValue?: any): any {
return lodashGet(this.config, key, defaultValue); 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. * if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions.
* *
* @param {EngineOptions} engineOptions * @param {IPublicTypeEngineOptions} engineOptions
* @memberof EngineConfig
*/ */
setEngineOptions(engineOptions: EngineOptions) { setEngineOptions(engineOptions: IPublicTypeEngineOptions) {
if (!engineOptions || !isPlainObject(engineOptions)) { if (!engineOptions || !isPlainObject(engineOptions)) {
return; return;
} }

View File

@ -11,7 +11,7 @@ import {
Hotkey as InnerHotkey, Hotkey as InnerHotkey,
} from '@alilc/lowcode-editor-core'; } from '@alilc/lowcode-editor-core';
import { import {
EngineOptions, IPublicTypeEngineOptions,
IPublicModelDocumentModel, IPublicModelDocumentModel,
IPublicTypePluginMeta, IPublicTypePluginMeta,
} from '@alilc/lowcode-types'; } from '@alilc/lowcode-types';
@ -158,7 +158,7 @@ engineConfig.set('ENGINE_VERSION', version);
export async function init( export async function init(
container?: HTMLElement, container?: HTMLElement,
options?: EngineOptions, options?: IPublicTypeEngineOptions,
pluginPreference?: PluginPreference, pluginPreference?: PluginPreference,
) { ) {
await destroy(); await destroy();

View File

@ -1,5 +1,5 @@
import { BuiltinSimulatorHost, Node, IPublicTypePropChangeOptions } from '@alilc/lowcode-designer'; 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 { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils';
import { debounce } from '../utils/common'; import { debounce } from '../utils/common';
import adapter from '../adapter'; import adapter from '../adapter';
@ -30,7 +30,7 @@ export interface IComponentHocState {
nodeProps: any; nodeProps: any;
} }
type DesignMode = Pick<EngineOptions, 'designMode'>['designMode']; type DesignMode = Pick<IPublicTypeEngineOptions, 'designMode'>['designMode'];
export interface IComponentHoc { export interface IComponentHoc {
designMode: DesignMode | DesignMode[]; designMode: DesignMode | DesignMode[];

View File

@ -26,7 +26,7 @@ export class Canvas implements IPublicApiCanvas {
return this[editorSymbol].get('designer') as IDesigner; return this[editorSymbol].get('designer') as IDesigner;
} }
constructor(editor: IPublicModelEditor) { constructor(editor: IPublicModelEditor, readonly workspaceMode: boolean = false) {
this[editorSymbol] = editor; this[editorSymbol] = editor;
} }
@ -49,7 +49,7 @@ export class Canvas implements IPublicApiCanvas {
} }
get dragon(): IPublicModelDragon | null { get dragon(): IPublicModelDragon | null {
return Dragon.create(this[designerSymbol].dragon); return Dragon.create(this[designerSymbol].dragon, this.workspaceMode);
} }
get activeTracker(): IPublicModelActiveTracker | null { get activeTracker(): IPublicModelActiveTracker | null {

View File

@ -19,11 +19,14 @@ export const innerDragonSymbol = Symbol('innerDragonSymbol');
export class Dragon implements IPublicModelDragon { export class Dragon implements IPublicModelDragon {
private readonly [innerDragonSymbol]: IPublicModelDragon; private readonly [innerDragonSymbol]: IPublicModelDragon;
constructor(innerDragon: IPublicModelDragon) { constructor(innerDragon: IPublicModelDragon, readonly workspaceMode: boolean) {
this[innerDragonSymbol] = innerDragon; this[innerDragonSymbol] = innerDragon;
} }
get [dragonSymbol](): any { get [dragonSymbol](): any {
if (this.workspaceMode) {
return this[innerDragonSymbol];
}
const workspace = globalContext.get('workspace'); const workspace = globalContext.get('workspace');
let editor = globalContext.get('editor'); let editor = globalContext.get('editor');
@ -35,11 +38,11 @@ export class Dragon implements IPublicModelDragon {
return designer.dragon; return designer.dragon;
} }
static create(dragon: IPublicModelDragon | null): IPublicModelDragon | null { static create(dragon: IPublicModelDragon | null, workspaceMode: boolean): IPublicModelDragon | null {
if (!dragon) { if (!dragon) {
return null; return null;
} }
return new Dragon(dragon); return new Dragon(dragon, workspaceMode);
} }
/** /**

View File

@ -1,16 +1,16 @@
import { Node as InnerNode } from '@alilc/lowcode-designer'; import { INode as InnerNode, INodeChildren } from '@alilc/lowcode-designer';
import { IPublicTypeNodeSchema, IPublicTypeNodeData, IPublicEnumTransformStage, IPublicModelNodeChildren, IPublicModelNode } from '@alilc/lowcode-types'; import { IPublicTypeNodeData, IPublicEnumTransformStage, IPublicModelNodeChildren, IPublicModelNode } from '@alilc/lowcode-types';
import { Node } from './node'; import { Node } from './node';
import { nodeSymbol, nodeChildrenSymbol } from '../symbols'; import { nodeSymbol, nodeChildrenSymbol } from '../symbols';
export class NodeChildren implements IPublicModelNodeChildren { export class NodeChildren implements IPublicModelNodeChildren {
private readonly [nodeChildrenSymbol]: IPublicModelNodeChildren; private readonly [nodeChildrenSymbol]: INodeChildren;
constructor(nodeChildren: IPublicModelNodeChildren) { constructor(nodeChildren: INodeChildren) {
this[nodeChildrenSymbol] = nodeChildren; this[nodeChildrenSymbol] = nodeChildren;
} }
static create(nodeChildren: IPublicModelNodeChildren | null): IPublicModelNodeChildren | null { static create(nodeChildren: INodeChildren | null): IPublicModelNodeChildren | null {
if (!nodeChildren) { if (!nodeChildren) {
return null; return null;
} }
@ -37,7 +37,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @returns * @returns
*/ */
get isEmpty(): boolean { get isEmpty(): boolean {
return this[nodeChildrenSymbol].isEmpty(); return this[nodeChildrenSymbol].isEmptyNode;
} }
/** /**
@ -45,7 +45,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @returns * @returns
*/ */
get isEmptyNode(): boolean { 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 * judge if it is not empty
*/ */
get notEmpty(): boolean { get notEmpty(): boolean {
return this[nodeChildrenSymbol].notEmpty(); return this[nodeChildrenSymbol].notEmptyNode;
} }
/** /**
* judge if it is not empty * judge if it is not empty
*/ */
get notEmptyNode(): boolean { get notEmptyNode(): boolean {
return this[nodeChildrenSymbol].notEmpty(); return this[nodeChildrenSymbol].notEmptyNode;
} }
/** /**
* *
* delete the node
* @param node * @param node
* @returns
*/ */
delete(node: IPublicModelNode): boolean { 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 * @returns
*/ */
insert(node: IPublicModelNode, at?: number | null): void { 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 * @returns
*/ */
indexOf(node: IPublicModelNode): number { 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 * @param index
* @returns * @returns
*/ */
get(index: number): any { get(index: number): IPublicModelNode | null {
return Node.create(this[nodeChildrenSymbol].get(index)); return Node.create(this[nodeChildrenSymbol].get(index));
} }
@ -116,7 +116,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @returns * @returns
*/ */
has(node: IPublicModelNode): boolean { 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 * @param fn
*/ */
forEach(fn: (node: IPublicModelNode, index: number) => void): void { forEach(fn: (node: IPublicModelNode, index: number) => void): void {
this[nodeChildrenSymbol].forEach((item: InnerNode<IPublicTypeNodeSchema>, index: number) => { this[nodeChildrenSymbol].forEach((item: InnerNode, index: number) => {
fn(Node.create(item)!, index); fn(Node.create(item)!, index);
}); });
} }
@ -134,7 +134,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @param fn * @param fn
*/ */
map<T>(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null { map<T>(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null {
return this[nodeChildrenSymbol].map((item: InnerNode<IPublicTypeNodeSchema>, index: number) => { return this[nodeChildrenSymbol].map((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index); return fn(Node.create(item)!, index);
}); });
} }
@ -144,7 +144,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @param fn * @param fn
*/ */
every(fn: (node: IPublicModelNode, index: number) => boolean): boolean { every(fn: (node: IPublicModelNode, index: number) => boolean): boolean {
return this[nodeChildrenSymbol].every((item: InnerNode<IPublicTypeNodeSchema>, index: number) => { return this[nodeChildrenSymbol].every((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index); return fn(Node.create(item)!, index);
}); });
} }
@ -154,7 +154,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @param fn * @param fn
*/ */
some(fn: (node: IPublicModelNode, index: number) => boolean): boolean { some(fn: (node: IPublicModelNode, index: number) => boolean): boolean {
return this[nodeChildrenSymbol].some((item: InnerNode<IPublicTypeNodeSchema>, index: number) => { return this[nodeChildrenSymbol].some((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index); return fn(Node.create(item)!, index);
}); });
} }
@ -165,10 +165,10 @@ export class NodeChildren implements IPublicModelNodeChildren {
*/ */
filter(fn: (node: IPublicModelNode, index: number) => boolean): any { filter(fn: (node: IPublicModelNode, index: number) => boolean): any {
return this[nodeChildrenSymbol] return this[nodeChildrenSymbol]
.filter((item: InnerNode<IPublicTypeNodeSchema>, index: number) => { .filter((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index); return fn(Node.create(item)!, index);
}) })
.map((item: InnerNode<IPublicTypeNodeSchema>) => 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 { find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null {
return Node.create( return Node.create(
this[nodeChildrenSymbol].find((item: InnerNode<IPublicTypeNodeSchema>, index: number) => { this[nodeChildrenSymbol].find((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index); return fn(Node.create(item)!, index);
}), }),
); );
@ -219,8 +219,9 @@ export class NodeChildren implements IPublicModelNodeChildren {
mergeChildren( mergeChildren(
remover: (node: IPublicModelNode, idx: number) => boolean, remover: (node: IPublicModelNode, idx: number) => boolean,
adder: (children: IPublicModelNode[]) => any, adder: (children: IPublicModelNode[]) => any,
sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number, originalSorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number,
) { ) {
let sorter = originalSorter;
if (!sorter) { if (!sorter) {
sorter = () => 0; sorter = () => 0;
} }

View File

@ -26,6 +26,5 @@ export * from './designer';
export * from './dragon'; export * from './dragon';
export * from './shell'; export * from './shell';
export * from './shell-model-factory'; export * from './shell-model-factory';
export * from './engine-config';
// TODO: remove this in future versions // TODO: remove this in future versions
export * from './deprecated'; export * from './deprecated';

View File

@ -5,11 +5,13 @@ import { IPublicModelNode } from './';
export interface IPublicModelNodeChildren { export interface IPublicModelNodeChildren {
/** /**
* children * children
* get owner node of this nodeChildren
*/ */
get owner(): IPublicModelNode | null; get owner(): IPublicModelNode | null;
/** /**
* children * children
* get count of child nodes
*/ */
get size(): number; get size(): number;
@ -39,13 +41,14 @@ export interface IPublicModelNodeChildren {
/** /**
* *
* delete the node
* @param node * @param node
* @returns
*/ */
delete(node: IPublicModelNode): boolean; delete(node: IPublicModelNode): boolean;
/** /**
* *
* insert a node at specific position
* @param node * @param node
* @param at * @param at
* @returns * @returns
@ -54,6 +57,7 @@ export interface IPublicModelNodeChildren {
/** /**
* *
* get index of node in current children
* @param node * @param node
* @returns * @returns
*/ */
@ -61,6 +65,7 @@ export interface IPublicModelNodeChildren {
/** /**
* splice * splice
* provide the same function with {Array.prototype.splice}
* @param start * @param start
* @param deleteCount * @param deleteCount
* @param node * @param node
@ -69,13 +74,15 @@ export interface IPublicModelNodeChildren {
/** /**
* *
* get node with index
* @param index * @param index
* @returns * @returns
*/ */
get(index: number): any; get(index: number): IPublicModelNode | null;
/** /**
* *
* check if node exists in current children
* @param node * @param node
* @returns * @returns
*/ */
@ -83,55 +90,74 @@ export interface IPublicModelNodeChildren {
/** /**
* forEach * forEach
* provide the same function with {Array.prototype.forEach}
* @param fn * @param fn
*/ */
forEach(fn: (node: IPublicModelNode, index: number) => void): void; forEach(fn: (node: IPublicModelNode, index: number) => void): void;
/** /**
* map * map
* provide the same function with {Array.prototype.map}
* @param fn * @param fn
*/ */
map<T>(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null; map<T>(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null;
/** /**
* every * every
* provide the same function with {Array.prototype.every}
* @param fn * @param fn
*/ */
every(fn: (node: IPublicModelNode, index: number) => boolean): boolean; every(fn: (node: IPublicModelNode, index: number) => boolean): boolean;
/** /**
* some * some
* provide the same function with {Array.prototype.some}
* @param fn * @param fn
*/ */
some(fn: (node: IPublicModelNode, index: number) => boolean): boolean; some(fn: (node: IPublicModelNode, index: number) => boolean): boolean;
/** /**
* filter * filter
* provide the same function with {Array.prototype.filter}
* @param fn * @param fn
*/ */
filter(fn: (node: IPublicModelNode, index: number) => boolean): any; filter(fn: (node: IPublicModelNode, index: number) => boolean): any;
/** /**
* find * find
* provide the same function with {Array.prototype.find}
* @param fn * @param fn
*/ */
find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null; 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; reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void;
/** /**
* schema * schema
* import schema
* @param data * @param data
*/ */
importSchema(data?: IPublicTypeNodeData | IPublicTypeNodeData[]): void; importSchema(data?: IPublicTypeNodeData | IPublicTypeNodeData[]): void;
/** /**
* schema * schema
* export schema
* @param stage * @param stage
* @returns
*/ */
exportSchema(stage: IPublicEnumTransformStage): IPublicTypeNodeSchema; exportSchema(stage: IPublicEnumTransformStage): IPublicTypeNodeSchema;
/**
*
* excute remove/add/sort operations
* @param remover
* @param adder
* @param sorter
*/
mergeChildren( mergeChildren(
remover: (node: IPublicModelNode, idx: number) => boolean, remover: (node: IPublicModelNode, idx: number) => boolean,
adder: (children: IPublicModelNode[]) => IPublicTypeNodeData[] | null, adder: (children: IPublicModelNode[]) => IPublicTypeNodeData[] | null,

View File

@ -1,99 +1,129 @@
import { RequestHandlersMap } from '@alilc/lowcode-datasource-types'; import { RequestHandlersMap } from '@alilc/lowcode-datasource-types';
import { ComponentType } from 'react'; import { ComponentType } from 'react';
export interface EngineOptions { export interface IPublicTypeEngineOptions {
/** /**
* condition condition * condition condition
* when this is true, node that configured as conditional not renderring
* will not display in canvas.
* @default false
*/ */
enableCondition?: boolean; enableCondition?: boolean;
/** /**
* @todo designMode * TODO: designMode
* *
* live 'design' * live 'design'
*
* @default 'design'
* @experimental
*/ */
designMode?: 'design' | 'live'; designMode?: 'design' | 'live';
/** /**
* 'default' * 'default'
* @default 'default'
*/ */
device?: 'default' | 'mobile' | string; device?: 'default' | 'mobile' | string;
/** /**
* deviceClassName * deviceClassName
*/ */
deviceClassName?: string; deviceClassName?: string;
/** /**
* 'zh-CN' * 'zh-CN'
* @default 'zh-CN'
*/ */
locale?: string; locale?: string;
/** /**
* 'react' * 'react'
*/ */
renderEnv?: 'react' | 'rax' | string; renderEnv?: 'react' | 'rax' | string;
/** /**
* device * device
*/ */
deviceMapper?: { deviceMapper?: {
transform: (originalDevice: string) => string; transform: (originalDevice: string) => string;
}; };
/** /**
* STRICT_PLUGIN_MODE_DEFAULT , engineOptions * STRICT_PLUGIN_MODE_DEFAULT , engineOptions
* enable strict plugin mode, default value: false * enable strict plugin mode, default value: false
* under strict mode, customed engineOption is not accepted. * under strict mode, customed engineOption is not accepted.
*/ */
enableStrictPluginMode?: boolean; enableStrictPluginMode?: boolean;
/** /**
* false * false
*/ */
enableReactiveContainer?: boolean; enableReactiveContainer?: boolean;
/** /**
* false * false
*/ */
disableAutoRender?: boolean; disableAutoRender?: boolean;
/** /**
* 线false * 线false
*/ */
disableDetecting?: boolean; disableDetecting?: boolean;
/** /**
* selectorsundefined * selectorsundefined
*/ */
customizeIgnoreSelectors?: (defaultIgnoreSelectors: string[], e: MouseEvent) => string[]; customizeIgnoreSelectors?: (defaultIgnoreSelectors: string[], e: MouseEvent) => string[];
/** /**
* false * false
*/ */
disableDefaultSettingPanel?: boolean; disableDefaultSettingPanel?: boolean;
/** /**
* false * false
*/ */
disableDefaultSetters?: boolean; disableDefaultSetters?: boolean;
/** /**
* false * false
*/ */
enableCanvasLock?: boolean; enableCanvasLock?: boolean;
/** /**
* false * false
*/ */
enableLockedNodeSetting?: boolean; enableLockedNodeSetting?: boolean;
/** /**
* tab false * tab false
*/ */
stayOnTheSameSettingTab?: boolean; stayOnTheSameSettingTab?: boolean;
/** /**
* item tabsfalse * item tabsfalse
*/ */
hideSettingsTabsWhenOnlyOneItem?: boolean; hideSettingsTabsWhenOnlyOneItem?: boolean;
/** /**
* loading * loading
*/ */
loadingComponent?: ComponentType; loadingComponent?: ComponentType;
/** /**
* false * false
*/ */
supportVariableGlobally?: boolean; supportVariableGlobally?: boolean;
/** /**
* simulator urlundefined * simulator urlundefined
*/ */
simulatorUrl?: string[]; simulatorUrl?: string[];
/** /**
* Vision-polyfill settings * Vision-polyfill settings
* @deprecated this exists for some legacy reasons
*/ */
visionSettings?: { visionSettings?: {
// 是否禁用降级 reducer默认值false // 是否禁用降级 reducer默认值false
@ -101,6 +131,7 @@ export interface EngineOptions {
// 是否开启在 render 阶段开启 filter reducer默认值false // 是否开启在 render 阶段开启 filter reducer默认值false
enableFilterReducerInRenderStage?: boolean; enableFilterReducerInRenderStage?: boolean;
}; };
/** /**
* react-renderer appHelper https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper * react-renderer appHelper https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper
*/ */
@ -138,3 +169,10 @@ export interface EngineOptions {
*/ */
enableWorkspaceMode?: boolean; enableWorkspaceMode?: boolean;
} }
/**
* @deprecated use IPublicTypeEngineOptions instead
*/
export interface EngineOptions {
}

View File

@ -73,4 +73,5 @@ export * from './tip-config';
export * from './widget-config-area'; export * from './widget-config-area';
export * from './hotkey-callback'; export * from './hotkey-callback';
export * from './plugin-register-options'; export * from './plugin-register-options';
export * from './resource-options'; export * from './resource-options';
export * from './engine-options';

View File

@ -81,7 +81,7 @@ export class BasicContext {
const event = new Event(commonEvent, { prefix: 'common' }); const event = new Event(commonEvent, { prefix: 'common' });
const logger = getLogger({ level: 'warn', bizName: 'common' }); const logger = getLogger({ level: 'warn', bizName: 'common' });
const skeleton = new Skeleton(innerSkeleton, 'any', true); const skeleton = new Skeleton(innerSkeleton, 'any', true);
const canvas = new Canvas(editor); const canvas = new Canvas(editor, true);
editor.set('setters', setters); editor.set('setters', setters);
editor.set('project', project); editor.set('project', project);
editor.set('material', material); editor.set('material', material);

View File

@ -153,6 +153,7 @@ body {
.lc-top-area-left, .lc-sub-top-area-left { .lc-top-area-left, .lc-sub-top-area-left {
display: flex; display: flex;
align-items: center; align-items: center;
max-width: 100%;
} }
.lc-top-area-center, .lc-sub-top-area-center { .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 { .lc-workspace-workbench-window {
position: relative; position: relative;
height: 100%; height: 100%;

View File

@ -41,7 +41,7 @@ export class Workbench extends Component<{
<LeftFloatPane area={skeleton.leftFloatArea} /> <LeftFloatPane area={skeleton.leftFloatArea} />
<LeftFixedPane area={skeleton.leftFixedArea} /> <LeftFixedPane area={skeleton.leftFixedArea} />
<div className="lc-workspace-workbench-center"> <div className="lc-workspace-workbench-center">
<> <div className="lc-workspace-workbench-center-content">
<SubTopArea area={skeleton.subTopArea} itemClassName={topAreaItemClassName} /> <SubTopArea area={skeleton.subTopArea} itemClassName={topAreaItemClassName} />
<div className="lc-workspace-workbench-window"> <div className="lc-workspace-workbench-window">
{ {
@ -54,7 +54,7 @@ export class Workbench extends Component<{
)) ))
} }
</div> </div>
</> </div>
<MainArea area={skeleton.mainArea} /> <MainArea area={skeleton.mainArea} />
<BottomArea area={skeleton.bottomArea} /> <BottomArea area={skeleton.bottomArea} />
</div> </div>

View File

@ -101,7 +101,7 @@ export class Workspace implements IPublicApiWorkspace {
private remove(index: number) { private remove(index: number) {
const window = this.windows[index]; const window = this.windows[index];
this.windows = this.windows.splice(index - 1, 1); this.windows.splice(index, 1);
if (this.window === window) { if (this.window === window) {
this.window = this.windows[index] || this.windows[index + 1] || this.windows[index - 1]; this.window = this.windows[index] || this.windows[index + 1] || this.windows[index - 1];
this.emitChangeActiveWindow(); this.emitChangeActiveWindow();