diff --git a/docs/docs/api/canvas.md b/docs/docs/api/canvas.md
index b6af6680e..c16ba62c5 100644
--- a/docs/docs/api/canvas.md
+++ b/docs/docs/api/canvas.md
@@ -36,6 +36,12 @@ sidebar_position: 12
`@type {boolean}`
+### clipboard
+全局剪贴板实例
+
+`@type {IPublicModelClipboard}`
+
+相关类型:[IPublicModelClipboard](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/clipboard.ts)
## 方法
diff --git a/docs/docs/api/model/clipboard.md b/docs/docs/api/model/clipboard.md
new file mode 100644
index 000000000..15d9e280c
--- /dev/null
+++ b/docs/docs/api/model/clipboard.md
@@ -0,0 +1,43 @@
+---
+title: Clipboard
+sidebar_position: 14
+---
+
+> **@types** [IPublicModelClipboard](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/clipboard.ts)
+> **@since** v1.1.0
+
+## 方法
+
+### setData
+
+给剪贴板赋值
+
+```typescript
+/**
+ * 给剪贴板赋值
+ * set data to clipboard
+ *
+ * @param {*} data
+ * @since v1.1.0
+ */
+setData(data: any): void;
+```
+
+### waitPasteData
+
+设置剪贴板数据设置的回调
+
+```typescript
+/**
+ * 设置剪贴板数据设置的回调
+ * set callback for clipboard provide paste data
+ *
+ * @param {KeyboardEvent} keyboardEvent
+ * @param {(data: any, clipboardEvent: ClipboardEvent) => void} cb
+ * @since v1.1.0
+ */
+waitPasteData(
+ keyboardEvent: KeyboardEvent,
+ cb: (data: any, clipboardEvent: ClipboardEvent) => void,
+ ): void;
+```
\ No newline at end of file
diff --git a/docs/docs/api/model/node.md b/docs/docs/api/model/node.md
index fbc88034b..333e973f0 100644
--- a/docs/docs/api/model/node.md
+++ b/docs/docs/api/model/node.md
@@ -160,7 +160,7 @@ sidebar_position: 1
`@type {IPublicModelComponentMeta | null}`
-相关类型:[IPublicTypeIconType](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/component-meta.ts)
+相关类型:[IPublicModelComponentMeta](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/component-meta.ts)
### document
@@ -644,4 +644,4 @@ isConditionalVisible(): boolean | undefined;
setConditionalVisible(): void;
```
-**@since v1.1.0**
\ No newline at end of file
+**@since v1.1.0**
diff --git a/docs/docs/api/model/resource.md b/docs/docs/api/model/resource.md
index 30b1e9f41..74f8d8f71 100644
--- a/docs/docs/api/model/resource.md
+++ b/docs/docs/api/model/resource.md
@@ -1,6 +1,6 @@
---
title: Resource
-sidebar_position: 12
+sidebar_position: 13
---
> **[@experimental](./#experimental)**
diff --git a/docs/docs/guide/design/specs.md b/docs/docs/guide/design/specs.md
index 3e2b1342c..0d97f5cc0 100644
--- a/docs/docs/guide/design/specs.md
+++ b/docs/docs/guide/design/specs.md
@@ -23,7 +23,7 @@ sidebar_position: 1
对于低代码物料来说,A 平台创建的物料无法使用到 B 平台上,如果想在 B 平台实现同样的物料,需要按照 B 平台的标准搭建一份物料。
-对于 ProCode 物料来说,需要在低代码平台进行消费,是需要进行转换的,包括搭建配置项的生成、物料搭建试图等,可能还需要特殊的描述文件进行描述。由于这一层没有统一,同一份 ProCode 物料每接入一个低代码,可能需要的描述文件格式不同,转换的代码不同,使用的工具也不同。
+对于 ProCode 物料来说,需要在低代码平台进行消费,是需要进行转换的,包括搭建配置项的生成、物料搭建视图等,可能还需要特殊的描述文件进行描述。由于这一层没有统一,同一份 ProCode 物料每接入一个低代码,可能需要的描述文件格式不同,转换的代码不同,使用的工具也不同。
### 生态隔离
diff --git a/docs/docs/specs/material-spec.md b/docs/docs/specs/material-spec.md
index 234ec62f6..3bee847c0 100644
--- a/docs/docs/specs/material-spec.md
+++ b/docs/docs/specs/material-spec.md
@@ -84,7 +84,7 @@ component // 组件名称, 比如 biz-button
```
-#### README.md
+##### README.md
- README.md 应该包含业务组件的源信息、使用说明以及 API,示例如下:
@@ -126,7 +126,7 @@ npm install @alifd/ice-layout -S
| type | type | String | `primray`、`normal` | normal |
```
-#### package.json
+##### package.json
`package.json` 中包含了一些依赖信息和配置信息,示例如下:
```json
@@ -159,7 +159,7 @@ npm install @alifd/ice-layout -S
}
```
-#### src/index.js
+##### src/index.js
包含组件的出口文件,示例如下:
@@ -178,7 +178,7 @@ export default Button;
import Button, { Group } form '@scope/button';
```
-#### src/index.scss
+##### src/index.scss
```css
/* 不引入依赖组件的样式,比如组件 import { Button } from '@alifd/next'; */
@@ -193,7 +193,7 @@ import Button, { Group } form '@scope/button';
}
```
-#### demo
+##### demo
demo 目录存放的是组件的文档,无文档的业务组件无法带来任何价值,因此 demo 是必选项。demo 目录下的文件采取 markdown 的写法,可以是多个文件,示例(demo/basic.md)如下:
demo/basic.md
@@ -236,12 +236,12 @@ ReactDOM.render(
API 是组件的属性解释,给开发者作为组件属性配置的参考。为了保持 API 的一致性,我们制定这个 API 命名规范。对于业界通用的,约定俗成的命名,我们遵循社区的约定。对于业界有多种规则难以确定的,我们确定其中一种,大家共同遵守。
-#### 通用规则
+##### 通用规则
- 所有的 API 采用小驼峰的书写规则,如 `onChange`、`direction`、`defaultVisible`。
- 标签名采用大驼峰书写规则,如 `Menu`、`Slider`、`DatePicker`。
-#### 通用命名
+##### 通用命名
| API 名称 | 类型 | 描述 | 常见变量 |
| :------------- | :------------- | :----------------------------------------------------------- | :---------------------------------------------------- |
@@ -261,7 +261,7 @@ API 是组件的属性解释,给开发者作为组件属性配置的参考。
| has+'属性' | boolean | 拥有某个属性 | 例如 `hasArrow`, `hasHeader`, `hasClose` 等等 |
-#### 多选枚举
+##### 多选枚举
当某个 API 的接口,允许用户指定多个枚举值的时候,我们把这个接口定义为多选枚举。一个很典型的例子是某个弹层组件的 `closable` 属性,我们会允许:键盘 esc 按键、点击 mask、点击 close 按钮、点击组件以外的任何区域进行关闭。
@@ -280,11 +280,11 @@ true 表示触发规则都会关闭,false 表示触发规则不会关闭。
- `
`,任何情况下都不关闭,只能通过受控设置 visible
- `
`,用户按 esc 或者点击关闭按钮会关闭
-#### 事件
+##### 事件
- 标准事件或者自定义的符合 w3c 标准的事件,命名必须 on 开头, 即 `on` + 事件名,如 onExpand。
-#### 表单规范
+##### 表单规范
- 支持[受控模式](https://reactjs.org/docs/forms.html#controlled-components)(value + onChange) (A)
- value 控制组件数据展现
@@ -292,7 +292,7 @@ true 表示触发规则都会关闭,false 表示触发规则不会关闭。
- `value={undefined}`的时候清空数据,field 的 reset 函数会给所有组件下发 undefined 数据 (AA))
- 一次完整操作抛一次 onChange 事件 `建议` 比如有 Process 表示进展中的状态,建议增加 API `onProcess`;如果有 Start 表示启动状态,建议增加 API `onStart` (AA)
-#### 属性的传递
+##### 属性的传递
**1. 原子组件(Atomic Component)**
> 最小粒子,不能再拆分的组件
@@ -354,7 +354,7 @@ $ iceworks sync
文件命名采取 [bcp47](https://tools.ietf.org/html/bcp47) 规范
-#### 目录规范
+##### 目录规范
在 `src` 目录新增 `locale` 目录用于管理不同语言的文案。
@@ -367,7 +367,7 @@ $ iceworks sync
|------ ja-JP.js
```
-#### 定义不同的语言
+##### 定义不同的语言
```javascript
// zh-CN.js
@@ -390,7 +390,7 @@ export default {
};
```
-#### 组件支持多语言建议方案
+##### 组件支持多语言建议方案
```jsx
// index.jsx
@@ -417,7 +417,7 @@ export default class BizHello extends Component {
}
```
-#### 组件支持全局替换国际化文案
+##### 组件支持全局替换国际化文案
配合 ConfigProvider 支持全局替换国际化文案。
@@ -451,7 +451,7 @@ export default ConfigProvider.config(BizHello, {
业务组件中如果有自定义的需要跟随主题色的 UI,一定要引入变量的形式,增加组件的流通性。
-#### src/index.scss
+##### src/index.scss
```css
/* 如果需要引入主题变量引入此段 */
@@ -503,7 +503,7 @@ api 属性标准参考 [https://fusion.design/help.html#/dev-biz](https://fusio
无障碍需要符合 [WCAG 2.1 A 级标准](https://www.w3.org/TR/WCAG21/),可参考 [W3C 无障碍最佳实践](https://www.w3.org/TR/wai-aria-practices-1.1/)、[Fusion 无障碍指引 2.3.1](https://alibaba-fusion.github.io/next/part1/basics.html) 章节等。
-#### 增加 a11y.md 无障碍 demo
+##### 增加 a11y.md 无障碍 demo
必须借助 API 才能完成无障碍工作的组件必须为开发者提供无障碍的使用文档,请[参考](https://fusion.design/pc/component/select?themeid=2#accessibility-container)组件 API 中 `ARIA and Keyboard` ,建议在 `demo` 目录新增 `a11y.md` 文件用于演示组件的无障碍使用。
@@ -517,7 +517,7 @@ component
详细指引查看无障碍开发指南 [https://alibaba-fusion.github.io/next/part1/basics.html](https://alibaba-fusion.github.io/next/part1/basics.html)。
-#### 通过键盘快速访问
+##### 通过键盘快速访问
一般键盘事件有 Up Arrow/Down Arrow/Enter/Esc/Tab
@@ -531,7 +531,7 @@ component
| Esc | 关闭列表 |
-#### 对读屏软件友好
+##### 对读屏软件友好
- 对于组件,我们为开发者内置 `role` 和特定 `aria-_属性`,开发者也可以对非组件 API 属性都可以透传至 DOM 元素,进行修改 `role` 和 `aria-_参数`,但是要注意对应关系,请[参考](https://alibaba-fusion.github.io/next/part1/WAI-ARIA.html)。
- 对一些特殊的组件传递参数才能支持无障碍,设置 `id`,`autoFocus` 和传参数,如下:
@@ -925,18 +925,18 @@ props 数组下对象字段描述:
|initialChildren | 组件拖入“设计器”时根据此配置自动生成 children 节点 schema |NodeData[]/Function NodeData[] | ((target: SettingTarget) => NodeData[]);|
|getResizingHandlers| 用于配置设计器中组件 resize 操作工具的样式和内容 | Function| (currentNode: any) => Array<{ type: 'N' | 'W' | 'S' | 'E' | 'NW' | 'NE' | 'SE' | 'SW'; content?: ReactElement; propTarget?: string; appearOn?: 'mouse-enter' | 'mouse-hover' | 'selected' | 'always'; }> / ReactElement[];
|callbacks| 配置 callbacks 可捕获引擎抛出的一些事件,例如 onNodeAdd、onResize 等 | Callback| -
-|callbacks.onNodeAdd| 在容器中拖入组件时触发的事件回调| Function| (e: MouseEvent, currentNode: any) => any
-|callbacks.onNodeRemove| 在容器中删除组件时触发的事件回调| Function| (e: MouseEvent, currentNode: any) => any
+|callbacks.onNodeAdd| 在容器中拖入组件时触发的事件回调 | Function| (e: MouseEvent, currentNode: any) => any
+|callbacks.onNodeRemove| 在容器中删除组件时触发的事件回调 | Function| (e: MouseEvent, currentNode: any) => any
|callbacks.onResize| 调整容器尺寸时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义
|callbacks.onResizeStart| 调整容器尺寸开始时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义
|callbacks.onResizeEnd| 调整容器尺寸结束时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义
-|callbacks.onSubtreeModified| 容器节点结构树发生变化时触发的回调| Function| (currentNode: any, options: any) => void;
-|callbacks.onMouseDownHook| 鼠标按下操作回调| Function| (e: MouseEvent, currentNode: any) => any;
-|callbacks.onClickHook| 鼠标单击操作回调| Function| (e: MouseEvent, currentNode: any) => any;
-|callbacks.onDblClickHook| 鼠标双击操作回调| Function| (e: MouseEvent, currentNode: any) => any;
+|callbacks.onSubtreeModified| 容器节点结构树发生变化时触发的回调 | Function| (currentNode: any, options: any) => void;
+|callbacks.onMouseDownHook| 鼠标按下操作回调 | Function| (e: MouseEvent, currentNode: any) => any;
+|callbacks.onClickHook| 鼠标单击操作回调 | Function| (e: MouseEvent, currentNode: any) => any;
+|callbacks.onDblClickHook| 鼠标双击操作回调 | Function| (e: MouseEvent, currentNode: any) => any;
|callbacks.onMoveHook| 节点被拖动回调 | Function| (currentNode: any) => boolean;
|callbacks.onHoverHook| 节点被 hover 回调 | Function| (currentNode: any) => boolean;
-|callbacks.onChildMoveHook| 容器节点的子节点被拖动回调| Function| (childNode: any, currentNode: any) => boolean;
+|callbacks.onChildMoveHook| 容器节点的子节点被拖动回调 | Function| (childNode: any, currentNode: any) => boolean;
描述举例:
@@ -1543,7 +1543,7 @@ block/
```
-#### 入口文件
+##### 入口文件
(/src/index.jsx)
@@ -1559,7 +1559,7 @@ const App = hot(router);
ReactDOM.render(
, document.getElementById(pkg.config && pkg.config.targetRootID || 'root'));
```
-#### 应用参数配置文件
+##### 应用参数配置文件
(/src/config/app.js)
@@ -1596,7 +1596,7 @@ export default {
}
```
-#### 应用扩展配置规范:
+##### 应用扩展配置规范:
(/src/utils/index.js)
@@ -1618,7 +1618,7 @@ export default {
}
```
-#### 应用常量配置
+##### 应用常量配置
(/src/config/constants.js)
@@ -1628,7 +1628,7 @@ export default {
}
```
-#### 应用样式配置
+##### 应用样式配置
(/src/global.scss)
diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index 97a0237b4..0aaa4c50f 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -39,7 +39,6 @@ const config = {
presets: [
[
'classic',
- /** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve('./config/sidebars.js'),
@@ -55,7 +54,6 @@ const config = {
],
themeConfig:
- /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
docs: {
sidebar: {
@@ -76,7 +74,7 @@ const config = {
metadata: [{ name: 'referrer', content: 'no-referrer' }],
tableOfContents: {
minHeadingLevel: 2,
- maxHeadingLevel: 5,
+ maxHeadingLevel: 6,
},
}),
diff --git a/packages/designer/src/component-meta.ts b/packages/designer/src/component-meta.ts
index 70d8630b5..9a74d0ddb 100644
--- a/packages/designer/src/component-meta.ts
+++ b/packages/designer/src/component-meta.ts
@@ -13,9 +13,9 @@ import {
IPublicTypeMetadataTransducer,
IPublicModelComponentMeta,
} from '@alilc/lowcode-types';
-import { deprecate, isRegExp, isTitleConfig } from '@alilc/lowcode-utils';
+import { deprecate, isRegExp, isTitleConfig, isNode } from '@alilc/lowcode-utils';
import { computed, createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core';
-import { isNode, Node, INode } from './document';
+import { Node, INode } from './document';
import { Designer } from './designer';
import {
IconContainer,
@@ -161,6 +161,9 @@ export class ComponentMeta implements IComponentMeta {
return this._acceptable!;
}
+ // compatiable vision
+ prototype?: any;
+
constructor(readonly designer: Designer, metadata: IPublicTypeComponentMetadata) {
this.parseMetadata(metadata);
}
@@ -347,8 +350,6 @@ export class ComponentMeta implements IComponentMeta {
};
}
- // compatiable vision
- prototype?: any;
}
export function isComponentMeta(obj: any): obj is ComponentMeta {
@@ -373,4 +374,3 @@ function preprocessMetadata(metadata: IPublicTypeComponentMetadata): IPublicType
configure: {},
};
}
-
diff --git a/packages/designer/src/designer/clipboard.ts b/packages/designer/src/designer/clipboard.ts
index a43b51b0e..941f91442 100644
--- a/packages/designer/src/designer/clipboard.ts
+++ b/packages/designer/src/designer/clipboard.ts
@@ -1,3 +1,5 @@
+import { IPublicModelClipboard } from '@alilc/lowcode-types';
+
function getDataFromPasteEvent(event: ClipboardEvent) {
const { clipboardData } = event;
if (!clipboardData) {
@@ -23,7 +25,13 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
}
}
-class Clipboard {
+export interface IClipboard extends IPublicModelClipboard {
+
+ initCopyPaster(el: HTMLTextAreaElement): void;
+
+ injectCopyPaster(document: Document): void;
+}
+class Clipboard implements IClipboard {
private copyPasters: HTMLTextAreaElement[] = [];
private waitFn?: (data: any, e: ClipboardEvent) => void;
@@ -56,7 +64,7 @@ class Clipboard {
}
injectCopyPaster(document: Document) {
- if (this.copyPasters.find(x => x.ownerDocument === document)) {
+ if (this.copyPasters.find((x) => x.ownerDocument === document)) {
return;
}
const copyPaster = document.createElement<'textarea'>('textarea');
@@ -69,8 +77,8 @@ class Clipboard {
};
}
- setData(data: any) {
- const copyPaster = this.copyPasters.find(x => x.ownerDocument);
+ setData(data: any): void {
+ const copyPaster = this.copyPasters.find((x) => x.ownerDocument);
if (!copyPaster) {
return;
}
@@ -81,12 +89,12 @@ class Clipboard {
copyPaster.blur();
}
- waitPasteData(e: KeyboardEvent, cb: (data: any, e: ClipboardEvent) => void) {
- const win = e.view;
+ waitPasteData(keyboardEvent: KeyboardEvent, cb: (data: any, e: ClipboardEvent) => void) {
+ const win = keyboardEvent.view;
if (!win) {
return;
}
- const copyPaster = this.copyPasters.find(cp => cp.ownerDocument === win.document);
+ const copyPaster = this.copyPasters.find((cp) => cp.ownerDocument === win.document);
if (copyPaster) {
copyPaster.select();
this.waitFn = cb;
diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts
index 6ade5fea0..0e3559e0a 100644
--- a/packages/designer/src/designer/designer.ts
+++ b/packages/designer/src/designer/designer.ts
@@ -30,7 +30,6 @@ import { ActiveTracker, IActiveTracker } from './active-tracker';
import { Detecting } from './detecting';
import { DropLocation } from './location';
import { OffsetObserver, createOffsetObserver } from './offset-observer';
-import { focusing } from './focusing';
import { SettingTopEntry } from './setting';
import { BemToolsManager } from '../builtin-simulator/bem-tools/manager';
import { ComponentActions } from '../component-actions';
@@ -241,9 +240,6 @@ export class Designer implements IDesigner {
this.postEvent('init', this);
this.setupSelection();
setupHistory();
-
- // TODO: 先简单实现,后期通过焦点赋值
- focusing.focusDesigner = this;
}
setupSelection = () => {
@@ -341,6 +337,7 @@ export class Designer implements IDesigner {
/**
* 获得合适的插入位置
+ * @deprecated
*/
getSuitableInsertion(
insertNode?: INode | IPublicTypeNodeSchema | IPublicTypeNodeSchema[],
diff --git a/packages/designer/src/designer/focusing.ts b/packages/designer/src/designer/focusing.ts
deleted file mode 100644
index 66816bc03..000000000
--- a/packages/designer/src/designer/focusing.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Designer } from './designer';
-
-// TODO: use focus-tracker replace
-class Focusing {
- focusDesigner?: Designer;
-}
-
-export const focusing = new Focusing();
diff --git a/packages/designer/src/designer/index.ts b/packages/designer/src/designer/index.ts
index 105291885..34d7a8c09 100644
--- a/packages/designer/src/designer/index.ts
+++ b/packages/designer/src/designer/index.ts
@@ -7,6 +7,5 @@ export * from './offset-observer';
export * from './scroller';
export * from './setting';
export * from './active-tracker';
-export * from './focusing';
export * from '../document';
export * from './clipboard';
diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts
index 26648403b..5eb60c396 100644
--- a/packages/designer/src/document/document-model.ts
+++ b/packages/designer/src/document/document-model.ts
@@ -17,11 +17,11 @@ import { IProject, Project } from '../project';
import { ISimulatorHost } from '../simulator';
import { ComponentMeta } from '../component-meta';
import { IDropLocation, Designer, IHistory } from '../designer';
-import { Node, insertChildren, insertChild, isNode, RootNode, INode } from './node/node';
+import { Node, insertChildren, insertChild, RootNode, INode } from './node/node';
import { Selection, ISelection } from './selection';
import { History } from './history';
import { IModalNodesManager, ModalNodesManager } from './node';
-import { uniqueId, isPlainObject, compatStage, isJSExpression, isDOMText, isNodeSchema, isDragNodeObject, isDragNodeDataObject } from '@alilc/lowcode-utils';
+import { uniqueId, isPlainObject, compatStage, isJSExpression, isDOMText, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isNode } from '@alilc/lowcode-utils';
import { EDITOR_EVENT } from '../types';
export type GetDataType
= T extends undefined
@@ -32,7 +32,7 @@ export type GetDataType = T extends undefined
: any
: T;
-export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'selection' > {
+export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'selection' | 'checkNesting' > {
readonly designer: Designer;
@@ -59,6 +59,11 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'select
get rootNode(): INode | null;
+ checkNesting(
+ dropTarget: INode,
+ dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject,
+ ): boolean;
+
}
export class DocumentModel implements IDocumentModel {
@@ -569,7 +574,10 @@ export class DocumentModel implements IDocumentModel {
this.rootNode = null;
}
- checkNesting(dropTarget: INode, dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | Node | IPublicTypeDragNodeDataObject): boolean {
+ checkNesting(
+ dropTarget: INode,
+ dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject,
+ ): boolean {
let items: Array;
if (isDragNodeDataObject(dragObject)) {
items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts
index 5525493a1..1d294663b 100644
--- a/packages/designer/src/document/node/node.ts
+++ b/packages/designer/src/document/node/node.ts
@@ -16,7 +16,7 @@ import {
IPublicModelExclusiveGroup,
IPublicEnumTransformStage,
} from '@alilc/lowcode-types';
-import { compatStage, isDOMText, isJSExpression } from '@alilc/lowcode-utils';
+import { compatStage, isDOMText, isJSExpression, isNode } from '@alilc/lowcode-utils';
import { SettingTopEntry } from '@alilc/lowcode-designer';
import { Props, getConvertedExtraKey, IProps } from './props/props';
import { DocumentModel, IDocumentModel } from '../document-model';
@@ -109,6 +109,8 @@ export interface INode extends IPublicModelNode {
getExtraProp(key: string, createIfNone?: boolean): IProp | null;
replaceChild(node: INode, data: any): INode;
+
+ getSuitablePlace(node: INode, ref: any): any;
}
/**
@@ -913,7 +915,7 @@ export class Node
/**
* 判断是否包含特定节点
*/
- contains(node: Node): boolean {
+ contains(node: INode): boolean {
return contains(this, node);
}
@@ -1147,16 +1149,16 @@ export class Node
}
/**
- * TODO: replace non standard metas with standard ones.
+ * @deprecated no one is using this, will be removed in a future release
*/
- getSuitablePlace(node: Node, ref: any): any {
+ getSuitablePlace(node: INode, ref: any): any {
const focusNode = this.document?.focusNode;
// 如果节点是模态框,插入到根节点下
if (node?.componentMeta?.isModal) {
return { container: focusNode, ref };
}
- if (!ref && this.contains(focusNode)) {
+ if (!ref && focusNode && this.contains(focusNode)) {
const rootCanDropIn = focusNode.componentMeta?.prototype?.options?.canDropIn;
if (
rootCanDropIn === undefined ||
@@ -1171,7 +1173,7 @@ export class Node
if (this.isRoot() && this.children) {
const dropElement = this.children.filter((c) => {
- if (!c.isContainer()) {
+ if (!c.isContainerNode) {
return false;
}
const canDropIn = c.componentMeta?.prototype?.options?.canDropIn;
@@ -1304,22 +1306,15 @@ export type PageNode = Node;
export type ComponentNode = Node;
export type RootNode = PageNode | ComponentNode;
-/**
- * @deprecated use same function from '@alilc/lowcode-utils' instead
- */
-export function isNode(node: any): node is Node {
- return node && node.isNode;
+export function isRootNode(node: INode): node is INode {
+ return node && node.isRootNode;
}
-export function isRootNode(node: Node): node is RootNode {
- return node && node.isRoot();
-}
-
-export function isLowCodeComponent(node: Node): boolean {
+export function isLowCodeComponent(node: INode): node is INode {
return node.componentMeta?.getMetadata().devMode === 'lowCode';
}
-export function getZLevelTop(child: Node, zLevel: number): Node | null {
+export function getZLevelTop(child: INode, zLevel: number): INode | null {
let l = child.zLevel;
if (l < zLevel || zLevel < 0) {
return null;
@@ -1340,12 +1335,12 @@ export function getZLevelTop(child: Node, zLevel: number): Node | null {
* @param node2 测试的被包含节点
* @returns 是否包含
*/
-export function contains(node1: Node, node2: Node): boolean {
+export function contains(node1: INode, node2: INode): boolean {
if (node1 === node2) {
return true;
}
- if (!node1.isParental() || !node2.parent) {
+ if (!node1.isParentalNode || !node2.parent) {
return false;
}
@@ -1367,7 +1362,7 @@ export enum PositionNO {
BeforeOrAfter = 2,
TheSame = 0,
}
-export function comparePosition(node1: Node, node2: Node): PositionNO {
+export function comparePosition(node1: INode, node2: INode): PositionNO {
if (node1 === node2) {
return PositionNO.TheSame;
}
@@ -1396,11 +1391,11 @@ export function comparePosition(node1: Node, node2: Node): PositionNO {
export function insertChild(
container: INode,
- thing: Node | IPublicTypeNodeData,
+ thing: INode | IPublicTypeNodeData,
at?: number | null,
copy?: boolean,
-): Node {
- let node: Node;
+): INode {
+ let node: INode;
if (isNode(thing) && (copy || thing.isSlot())) {
thing = thing.export(IPublicEnumTransformStage.Clone);
}
@@ -1410,20 +1405,20 @@ export function insertChild(
node = container.document.createNode(thing);
}
- container.children.internalInsert(node, at);
+ container.children.insert(node, at);
return node;
}
export function insertChildren(
container: INode,
- nodes: Node[] | IPublicTypeNodeData[],
+ nodes: INode[] | IPublicTypeNodeData[],
at?: number | null,
copy?: boolean,
-): Node[] {
+): INode[] {
let index = at;
let node: any;
- const results: Node[] = [];
+ const results: INode[] = [];
// eslint-disable-next-line no-cond-assign
while ((node = nodes.pop())) {
node = insertChild(container, node, index, copy);
diff --git a/packages/designer/tests/document/node/node.test.ts b/packages/designer/tests/document/node/node.test.ts
index d8915c991..f7d35f6d6 100644
--- a/packages/designer/tests/document/node/node.test.ts
+++ b/packages/designer/tests/document/node/node.test.ts
@@ -7,7 +7,6 @@ import { DocumentModel } from '../../../src/document/document-model';
import {
isRootNode,
Node,
- isNode,
comparePosition,
contains,
PositionNO,
@@ -23,6 +22,7 @@ import rootHeaderMetadata from '../../fixtures/component-metadata/root-header';
import rootContentMetadata from '../../fixtures/component-metadata/root-content';
import rootFooterMetadata from '../../fixtures/component-metadata/root-footer';
import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory';
+import { isNode } from '@alilc/lowcode-utils';
describe('Node 方法测试', () => {
let editor: Editor;
diff --git a/packages/editor-skeleton/src/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts
index 1b5c27015..855dbe569 100644
--- a/packages/editor-skeleton/src/transducers/addon-combine.ts
+++ b/packages/editor-skeleton/src/transducers/addon-combine.ts
@@ -1,8 +1,14 @@
-import { IPublicTypeTransformedComponentMetadata, IPublicTypeFieldConfig, IPublicModelSettingTarget } from '@alilc/lowcode-types';
+import {
+ IPublicTypeTransformedComponentMetadata,
+ IPublicTypeFieldConfig,
+ IPublicModelSettingTarget,
+} from '@alilc/lowcode-types';
import { IconSlot } from '../icons/slot';
import { getConvertedExtraKey } from '@alilc/lowcode-designer';
-export default function (metadata: IPublicTypeTransformedComponentMetadata): IPublicTypeTransformedComponentMetadata {
+export default function (
+ metadata: IPublicTypeTransformedComponentMetadata,
+): IPublicTypeTransformedComponentMetadata {
const { componentName, configure = {} } = metadata;
// 如果已经处理过,不再重新执行一遍
@@ -111,35 +117,33 @@ export default function (metadata: IPublicTypeTransformedComponentMetadata): IPu
},
];
}
- /*
- propsGroup.push({
- name: '#generals',
- title: { type: 'i18n', 'zh-CN': '通用', 'en-US': 'General' },
- items: [
- {
- name: 'id',
- title: 'ID',
- setter: 'StringSetter',
- },
- {
- name: 'key',
- title: 'Key',
- // todo: use Mixin
- setter: 'StringSetter',
- },
- {
- name: 'ref',
- title: 'Ref',
- setter: 'StringSetter',
- },
- {
- name: '!more',
- title: '更多',
- setter: 'PropertiesSetter',
- },
- ],
- });
- */
+ // propsGroup.push({
+ // name: '#generals',
+ // title: { type: 'i18n', 'zh-CN': '通用', 'en-US': 'General' },
+ // items: [
+ // {
+ // name: 'id',
+ // title: 'ID',
+ // setter: 'StringSetter',
+ // },
+ // {
+ // name: 'key',
+ // title: 'Key',
+ // // todo: use Mixin
+ // setter: 'StringSetter',
+ // },
+ // {
+ // name: 'ref',
+ // title: 'Ref',
+ // setter: 'StringSetter',
+ // },
+ // {
+ // name: '!more',
+ // title: '更多',
+ // setter: 'PropertiesSetter',
+ // },
+ // ],
+ // });
const stylesGroup: IPublicTypeFieldConfig[] = [];
const advancedGroup: IPublicTypeFieldConfig[] = [];
if (propsGroup) {
@@ -216,18 +220,24 @@ export default function (metadata: IPublicTypeTransformedComponentMetadata): IPu
setValue(field: IPublicModelSettingTarget, eventData) {
const { eventDataList, eventList } = eventData;
- Array.isArray(eventList) && eventList.map((item) => {
- field.parent.clearPropValue(item.name);
- return item;
- });
- Array.isArray(eventDataList) && eventDataList.map((item) => {
- field.parent.setPropValue(item.name, {
- type: 'JSFunction',
- // 需要传下入参
- value: `function(){return this.${item.relatedEventName}.apply(this,Array.prototype.slice.call(arguments).concat([${item.paramStr ? item.paramStr : ''}])) }`,
+ Array.isArray(eventList) &&
+ eventList.map((item) => {
+ field.parent.clearPropValue(item.name);
+ return item;
+ });
+ Array.isArray(eventDataList) &&
+ eventDataList.map((item) => {
+ field.parent.setPropValue(item.name, {
+ type: 'JSFunction',
+ // 需要传下入参
+ value: `function(){return this.${
+ item.relatedEventName
+ }.apply(this,Array.prototype.slice.call(arguments).concat([${
+ item.paramStr ? item.paramStr : ''
+ }])) }`,
+ });
+ return item;
});
- return item;
- });
},
},
],
@@ -296,7 +306,7 @@ export default function (metadata: IPublicTypeTransformedComponentMetadata): IPu
},
{
name: 'key',
- title: '循环 Key',
+ title: { type: 'i18n', 'zh-CN': '循环 Key', 'en-US': 'Loop Key' },
setter: [
{
componentName: 'StringSetter',
@@ -317,8 +327,16 @@ export default function (metadata: IPublicTypeTransformedComponentMetadata): IPu
advancedGroup.push({
name: 'key',
title: {
- label: '渲染唯一标识(key)',
- tip: '搭配「条件渲染」或「循环渲染」时使用,和 react 组件中的 key 原理相同,点击查看帮助',
+ label: {
+ type: 'i18n',
+ 'zh-CN': '渲染唯一标识 (key)',
+ 'en-US': 'Render unique identifier (key)',
+ },
+ tip: {
+ type: 'i18n',
+ 'zh-CN': '搭配「条件渲染」或「循环渲染」时使用,和 react 组件中的 key 原理相同,点击查看帮助',
+ 'en-US': 'Used with 「Conditional Rendering」or「Cycle Rendering」, the same principle as the key in the react component, click to view the help',
+ },
docUrl: 'https://www.yuque.com/lce/doc/qm75w3',
},
setter: [
diff --git a/packages/engine/src/inner-plugins/builtin-hotkey.ts b/packages/engine/src/inner-plugins/builtin-hotkey.ts
index 3ee79831b..73aac64aa 100644
--- a/packages/engine/src/inner-plugins/builtin-hotkey.ts
+++ b/packages/engine/src/inner-plugins/builtin-hotkey.ts
@@ -1,18 +1,102 @@
/* eslint-disable max-len */
-import { isFormEvent } from '@alilc/lowcode-utils';
-import {
- focusing,
- insertChildren,
- clipboard,
-} from '@alilc/lowcode-designer';
+import { isFormEvent, isNodeSchema, isNode } from '@alilc/lowcode-utils';
import {
IPublicModelPluginContext,
IPublicEnumTransformStage,
IPublicModelNode,
+ IPublicTypeNodeSchema,
+ IPublicTypeNodeData,
+ IPublicEnumDragObjectType,
+ IPublicTypeDragNodeObject,
} from '@alilc/lowcode-types';
-import symbols from '../modules/symbols';
-const { nodeSymbol, documentSymbol } = symbols;
+function insertChild(
+ container: IPublicModelNode,
+ originalChild: IPublicModelNode | IPublicTypeNodeData,
+ at?: number | null,
+): IPublicModelNode | null {
+ let child = originalChild;
+ if (isNode(child) && (child as IPublicModelNode).isSlotNode) {
+ child = (child as IPublicModelNode).exportSchema(IPublicEnumTransformStage.Clone);
+ }
+ let node = null;
+ if (isNode(child)) {
+ node = (child as IPublicModelNode);
+ container.children?.insert(node, at);
+ } else {
+ node = container.document?.createNode(child) || null;
+ if (node) {
+ container.children?.insert(node, at);
+ }
+ }
+
+ return (node as IPublicModelNode) || null;
+}
+
+function insertChildren(
+ container: IPublicModelNode,
+ nodes: IPublicModelNode[] | IPublicTypeNodeData[],
+ at?: number | null,
+): IPublicModelNode[] {
+ let index = at;
+ let node: any;
+ const results: IPublicModelNode[] = [];
+ // eslint-disable-next-line no-cond-assign
+ while ((node = nodes.pop())) {
+ node = insertChild(container, node, index);
+ results.push(node);
+ index = node.index;
+ }
+ return results;
+}
+
+/**
+ * 获得合适的插入位置
+ */
+function getSuitableInsertion(
+ pluginContext: IPublicModelPluginContext,
+ insertNode?: IPublicModelNode | IPublicTypeNodeSchema | IPublicTypeNodeSchema[],
+): { target: IPublicModelNode; index?: number } | null {
+ const { project, material } = pluginContext;
+ const activeDoc = project.currentDocument;
+ if (!activeDoc) {
+ return null;
+ }
+ if (
+ Array.isArray(insertNode) &&
+ isNodeSchema(insertNode[0]) &&
+ material.getComponentMeta(insertNode[0].componentName)?.isModal
+ ) {
+ if (!activeDoc.root) {
+ return null;
+ }
+
+ return {
+ target: activeDoc.root,
+ };
+ }
+
+ const focusNode = activeDoc.focusNode!;
+ const nodes = activeDoc.selection.getNodes();
+ const refNode = nodes.find((item) => focusNode.contains(item));
+ let target;
+ let index: number | undefined;
+ if (!refNode || refNode === focusNode) {
+ target = focusNode;
+ } else if (refNode.componentMeta?.isContainer) {
+ target = refNode;
+ } else {
+ // FIXME!!, parent maybe null
+ target = refNode.parent!;
+ index = refNode.index + 1;
+ }
+
+ if (target && insertNode && !target.componentMeta?.checkNestingDown(target, insertNode)) {
+ return null;
+ }
+
+ return { target, index };
+}
/* istanbul ignore next */
function getNextForSelect(next: IPublicModelNode | null, head?: any, parent?: IPublicModelNode | null): any {
@@ -76,11 +160,73 @@ function getPrevForSelect(prev: IPublicModelNode | null, head?: any, parent?: IP
return null;
}
+function getSuitablePlaceForNode(targetNode: IPublicModelNode, node: IPublicModelNode, ref: any): any {
+ const { document } = targetNode;
+ if (!document) {
+ return null;
+ }
+
+ const dragNodeObject: IPublicTypeDragNodeObject = {
+ type: IPublicEnumDragObjectType.Node,
+ nodes: [node],
+ };
+
+ const focusNode = document?.focusNode;
+ // 如果节点是模态框,插入到根节点下
+ if (node?.componentMeta?.isModal) {
+ return { container: focusNode, ref };
+ }
+ const canDropInFn = document.checkNesting;
+
+ if (!ref && focusNode && targetNode.contains(focusNode)) {
+ if (canDropInFn(focusNode, dragNodeObject)) {
+ return { container: focusNode };
+ }
+
+ return null;
+ }
+
+ if (targetNode.isRootNode && targetNode.children) {
+ const dropElement = targetNode.children.filter((c) => {
+ if (!c.isContainerNode) {
+ return false;
+ }
+ if (canDropInFn(c, dragNodeObject)) {
+ return true;
+ }
+ return false;
+ })[0];
+
+ if (dropElement) {
+ return { container: dropElement, ref };
+ }
+
+ if (canDropInFn(targetNode, dragNodeObject)) {
+ return { container: targetNode, ref };
+ }
+
+ return null;
+ }
+
+ if (targetNode.isContainerNode) {
+ if (canDropInFn(targetNode, dragNodeObject)) {
+ return { container: targetNode, ref };
+ }
+ }
+
+ if (targetNode.parent) {
+ return getSuitablePlaceForNode(targetNode.parent, node, { index: targetNode.index });
+ }
+
+ return null;
+}
+
// 注册默认的 setters
export const builtinHotkey = (ctx: IPublicModelPluginContext) => {
return {
init() {
const { hotkey, project, logger, canvas } = ctx;
+ const { clipboard } = canvas;
// hotkey binding
hotkey.bind(['backspace', 'del'], (e: KeyboardEvent, action) => {
logger.info(`action ${action} is triggered`);
@@ -108,11 +254,11 @@ export const builtinHotkey = (ctx: IPublicModelPluginContext) => {
hotkey.bind('escape', (e: KeyboardEvent, action) => {
logger.info(`action ${action} is triggered`);
- // const currentFocus = focusing.current;
+
if (canvas.isInLiveEditing) {
return;
}
- const sel = focusing.focusDesigner?.currentDocument?.selection;
+ const sel = project.currentDocument?.selection;
if (isFormEvent(e) || !sel) {
return;
}
@@ -168,26 +314,31 @@ export const builtinHotkey = (ctx: IPublicModelPluginContext) => {
return;
}
// TODO
- const designer = focusing.focusDesigner;
const doc = project?.currentDocument;
- if (isFormEvent(e) || !designer || !doc) {
+ if (isFormEvent(e) || !doc) {
return;
}
/* istanbul ignore next */
clipboard.waitPasteData(e, ({ componentsTree }) => {
if (componentsTree) {
- const { target, index } = designer.getSuitableInsertion(componentsTree) || {};
+ const { target, index } = getSuitableInsertion(ctx, componentsTree) || {};
if (!target) {
return;
}
- let canAddComponentsTree = componentsTree.filter((i) => {
- return (doc as any)[documentSymbol].checkNestingUp(target, i);
+ let canAddComponentsTree = componentsTree.filter((node: IPublicModelNode) => {
+ const dragNodeObject: IPublicTypeDragNodeObject = {
+ type: IPublicEnumDragObjectType.Node,
+ nodes: [node],
+ };
+ return doc.checkNesting(target, dragNodeObject);
});
- if (canAddComponentsTree.length === 0) return;
+ if (canAddComponentsTree.length === 0) {
+ return;
+ }
const nodes = insertChildren(target, canAddComponentsTree, index);
if (nodes) {
doc.selection.selectAll(nodes.map((o) => o.id));
- setTimeout(() => designer.activeTracker.track(nodes[0]), 10);
+ setTimeout(() => canvas.activeTracker?.track(nodes[0]), 10);
}
}
});
@@ -333,14 +484,14 @@ export const builtinHotkey = (ctx: IPublicModelPluginContext) => {
const silbing = firstNode.prevSibling;
if (silbing) {
if (silbing.isContainerNode) {
- const place = (silbing as any)[nodeSymbol].getSuitablePlace(firstNode, null);
+ const place = getSuitablePlaceForNode(silbing, firstNode, null);
silbing.insertAfter(firstNode, place.ref, true);
} else {
parent.insertBefore(firstNode, silbing, true);
}
firstNode?.select();
} else {
- const place = (parent as any)[nodeSymbol].getSuitablePlace(firstNode, null); // upwards
+ const place = getSuitablePlaceForNode(parent, firstNode, null); // upwards
if (place) {
const container = place.container.internalToShellNode();
container.insertBefore(firstNode, place.ref);
@@ -381,7 +532,7 @@ export const builtinHotkey = (ctx: IPublicModelPluginContext) => {
}
firstNode?.select();
} else {
- const place = (parent as any)[nodeSymbol].getSuitablePlace(firstNode, null); // upwards
+ const place = getSuitablePlaceForNode(parent, firstNode, null); // upwards
if (place) {
const container = place.container.internalToShellNode();
container.insertAfter(firstNode, place.ref, true);
diff --git a/packages/plugin-outline-pane/src/locale/en-US.json b/packages/plugin-outline-pane/src/locale/en-US.json
index 8bb4221f7..b0f3d3e4a 100644
--- a/packages/plugin-outline-pane/src/locale/en-US.json
+++ b/packages/plugin-outline-pane/src/locale/en-US.json
@@ -11,5 +11,12 @@
"Slots": "Slots",
"Slot for {prop}": "Slot for {prop}",
"Outline Tree": "Outline Tree",
+ "Filter Node": "Filter Node",
+ "Check All": "Check All",
+ "Conditional rendering": "Conditional rendering",
+ "Loop rendering": "Loop rendering",
+ "Locked": "Locked",
+ "Hidden": "Hidden",
+ "Modal View": "Modal View",
"Rename": "Rename"
}
diff --git a/packages/plugin-outline-pane/src/locale/zh-CN.json b/packages/plugin-outline-pane/src/locale/zh-CN.json
index 822bf9e94..8036688f2 100644
--- a/packages/plugin-outline-pane/src/locale/zh-CN.json
+++ b/packages/plugin-outline-pane/src/locale/zh-CN.json
@@ -11,5 +11,12 @@
"Slots": "插槽",
"Slot for {prop}": "属性 {prop} 的插槽",
"Outline Tree": "大纲树",
+ "Filter Node": "过滤节点",
+ "Check All": "全选",
+ "Conditional rendering": "条件渲染",
+ "Loop rendering": "循环渲染",
+ "Locked": "已锁定",
+ "Hidden": "已隐藏",
+ "Modal View": "模态视图层",
"Rename": "重命名"
}
diff --git a/packages/plugin-outline-pane/src/views/filter-tree.ts b/packages/plugin-outline-pane/src/views/filter-tree.ts
index 61ecb9c02..2a07e15c6 100644
--- a/packages/plugin-outline-pane/src/views/filter-tree.ts
+++ b/packages/plugin-outline-pane/src/views/filter-tree.ts
@@ -9,16 +9,16 @@ export const FilterType = {
export const FILTER_OPTIONS = [{
value: FilterType.CONDITION,
- label: '条件渲染',
+ label: 'Conditional rendering',
}, {
value: FilterType.LOOP,
- label: '循环渲染',
+ label: 'Loop rendering',
}, {
value: FilterType.LOCKED,
- label: '已锁定',
+ label: 'Locked',
}, {
value: FilterType.HIDDEN,
- label: '已隐藏',
+ label: 'Hidden',
}];
export const matchTreeNode = (
diff --git a/packages/plugin-outline-pane/src/views/filter.tsx b/packages/plugin-outline-pane/src/views/filter.tsx
index 223a4eab0..d4fa792ae 100644
--- a/packages/plugin-outline-pane/src/views/filter.tsx
+++ b/packages/plugin-outline-pane/src/views/filter.tsx
@@ -5,10 +5,11 @@ import { Search, Checkbox, Balloon, Divider } from '@alifd/next';
import TreeNode from '../controllers/tree-node';
import { Tree } from '../controllers/tree';
import { matchTreeNode, FILTER_OPTIONS } from './filter-tree';
-
+import { IPublicModelPluginContext } from '@alilc/lowcode-types';
export default class Filter extends Component<{
tree: Tree;
+ pluginContext: IPublicModelPluginContext;
}, {
keywords: string;
filterOps: string[];
@@ -55,7 +56,7 @@ export default class Filter extends Component<{
- 全选
+ {this.props.pluginContext.intlNode('Check All')}
- {op.label}
+ {this.props.pluginContext.intlNode(op.label)}
))}
diff --git a/packages/plugin-outline-pane/src/views/pane.tsx b/packages/plugin-outline-pane/src/views/pane.tsx
index 1ed4c74ba..4cee54a51 100644
--- a/packages/plugin-outline-pane/src/views/pane.tsx
+++ b/packages/plugin-outline-pane/src/views/pane.tsx
@@ -6,7 +6,6 @@ import { IPublicModelPluginContext } from '@alilc/lowcode-types';
import Filter from './filter';
import { TreeMaster } from '../controllers/tree-master';
-
export class Pane extends Component<{
config: any;
pluginContext: IPublicModelPluginContext;
@@ -40,7 +39,7 @@ export class Pane extends Component<{
return (
-
+
this.controller.mount(shell)} className="lc-outline-tree-container">
diff --git a/packages/plugin-outline-pane/src/views/tree-node.tsx b/packages/plugin-outline-pane/src/views/tree-node.tsx
index a6dc03f08..789068c18 100644
--- a/packages/plugin-outline-pane/src/views/tree-node.tsx
+++ b/packages/plugin-outline-pane/src/views/tree-node.tsx
@@ -38,7 +38,7 @@ class ModalTreeNodeView extends Component<{
return (
-
模态视图层
+
{this.pluginContext.intlNode('Modal View')}
> = {
+ 'zh-CN': zhCN as Record
,
+ 'en-US': enUS as Record,
+};
+
+export function createIntl(locale: string = 'zh-CN') {
+ const intl = (id: string) => {
+ return instance[locale][id];
+ };
+
+ const intlNode = (id: string) => createElement('span', instance[locale][id]);
+
+ return {
+ intl,
+ intlNode,
+ };
+}
diff --git a/packages/react-simulator-renderer/src/locale/zh-CN.json b/packages/react-simulator-renderer/src/locale/zh-CN.json
new file mode 100644
index 000000000..74bb821dd
--- /dev/null
+++ b/packages/react-simulator-renderer/src/locale/zh-CN.json
@@ -0,0 +1,4 @@
+{
+ "Drag and drop components or templates here": "拖拽组件或模板到这里",
+ "Locked elements and child elements cannot be edited": "锁定元素及子元素无法编辑"
+}
\ No newline at end of file
diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx
index d1c7abe30..68e66fc02 100644
--- a/packages/react-simulator-renderer/src/renderer-view.tsx
+++ b/packages/react-simulator-renderer/src/renderer-view.tsx
@@ -10,6 +10,7 @@ import { SimulatorRendererContainer, DocumentInstance } from './renderer';
import { host } from './host';
import { isRendererDetached } from './utils/misc';
import './renderer.less';
+import { createIntl } from './locale';
// patch cloneElement avoid lost keyProps
const originCloneElement = window.React.cloneElement;
@@ -130,6 +131,7 @@ class Renderer extends Component<{
documentInstance: DocumentInstance;
}> {
startTime: number | null = null;
+ schemaChangedSymbol = false;
componentDidUpdate() {
this.recordTime();
@@ -152,8 +154,6 @@ class Renderer extends Component<{
this.recordTime();
}
- schemaChangedSymbol = false;
-
getSchemaChangedSymbol = () => {
return this.schemaChangedSymbol;
};
@@ -172,6 +172,8 @@ class Renderer extends Component<{
if (!container.autoRender || isRendererDetached()) return null;
+ const { intl } = createIntl(locale);
+
return (
{
return node?.getExtraProp('isLocked')?.getValue() === true;
});
if (lockedNode) {
- defaultPlaceholder = '锁定元素及子元素无法编辑';
+ defaultPlaceholder = intl('Locked elements and child elements cannot be edited');
}
children = (
diff --git a/packages/shell/src/api/canvas.ts b/packages/shell/src/api/canvas.ts
index 5489a8b75..444894452 100644
--- a/packages/shell/src/api/canvas.ts
+++ b/packages/shell/src/api/canvas.ts
@@ -8,6 +8,7 @@ import {
IPublicModelEditor,
IPublicModelDragon,
IPublicModelActiveTracker,
+ IPublicModelClipboard,
} from '@alilc/lowcode-types';
import {
ScrollTarget as InnerScrollTarget,
@@ -18,10 +19,14 @@ import {
Dragon as ShellDragon,
DropLocation as ShellDropLocation,
ActiveTracker as ShellActiveTracker,
+ Clipboard as ShellClipboard,
} from '../model';
+const clipboardInstanceSymbol = Symbol('clipboardInstace');
+
export class Canvas implements IPublicApiCanvas {
private readonly [editorSymbol]: IPublicModelEditor;
+ private readonly [clipboardInstanceSymbol]: IPublicModelClipboard;
private get [designerSymbol](): IDesigner {
return this[editorSymbol].get('designer') as IDesigner;
@@ -40,8 +45,13 @@ export class Canvas implements IPublicApiCanvas {
return Boolean(this[editorSymbol].get('designer')?.project?.simulator?.liveEditing?.editing);
}
+ get clipboard(): IPublicModelClipboard {
+ return this[clipboardInstanceSymbol];
+ }
+
constructor(editor: IPublicModelEditor, readonly workspaceMode: boolean = false) {
this[editorSymbol] = editor;
+ this[clipboardInstanceSymbol] = new ShellClipboard();
}
createScrollTarget(shell: HTMLDivElement): IPublicModelScrollTarget {
diff --git a/packages/shell/src/index.ts b/packages/shell/src/index.ts
index 92d616945..0307349ab 100644
--- a/packages/shell/src/index.ts
+++ b/packages/shell/src/index.ts
@@ -9,6 +9,7 @@ import {
Dragon,
SettingPropEntry,
SettingTopEntry,
+ Clipboard,
} from './model';
import {
Project,
@@ -57,4 +58,5 @@ export {
Logger,
Canvas,
Workspace,
+ Clipboard,
};
\ No newline at end of file
diff --git a/packages/shell/src/model/clipboard.ts b/packages/shell/src/model/clipboard.ts
new file mode 100644
index 000000000..9c4b30945
--- /dev/null
+++ b/packages/shell/src/model/clipboard.ts
@@ -0,0 +1,22 @@
+import { IPublicModelClipboard } from '@alilc/lowcode-types';
+import { clipboardSymbol } from '../symbols';
+import { IClipboard, clipboard } from '@alilc/lowcode-designer';
+
+export class Clipboard implements IPublicModelClipboard {
+ private readonly [clipboardSymbol]: IClipboard;
+
+ constructor() {
+ this[clipboardSymbol] = clipboard;
+ }
+
+ setData(data: any): void {
+ this[clipboardSymbol].setData(data);
+ }
+
+ waitPasteData(
+ keyboardEvent: KeyboardEvent,
+ cb: (data: any, clipboardEvent: ClipboardEvent) => void,
+ ): void {
+ this[clipboardSymbol].waitPasteData(keyboardEvent, cb);
+ }
+}
\ No newline at end of file
diff --git a/packages/shell/src/model/document-model.ts b/packages/shell/src/model/document-model.ts
index 13fc49bae..ba371543a 100644
--- a/packages/shell/src/model/document-model.ts
+++ b/packages/shell/src/model/document-model.ts
@@ -8,7 +8,6 @@ import {
GlobalEvent,
IPublicModelDocumentModel,
IPublicTypeOnChangeOptions,
- IPublicModelDragObject,
IPublicTypeDragNodeObject,
IPublicTypeDragNodeDataObject,
IPublicModelNode,
@@ -227,9 +226,11 @@ export class DocumentModel implements IPublicModelDocumentModel {
dropTarget: IPublicModelNode,
dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject,
): boolean {
- let innerDragObject: IPublicModelDragObject = dragObject;
+ let innerDragObject = dragObject;
if (isDragNodeObject(dragObject)) {
- innerDragObject.nodes = innerDragObject.nodes.map((node: Node) => (node[nodeSymbol] || node));
+ innerDragObject.nodes = innerDragObject.nodes?.map(
+ (node: IPublicModelNode) => ((node as any)[nodeSymbol] || node),
+ );
}
return this[documentSymbol].checkNesting(
((dropTarget as any)[nodeSymbol] || dropTarget) as any,
diff --git a/packages/shell/src/model/index.ts b/packages/shell/src/model/index.ts
index d20120c3e..f2805342e 100644
--- a/packages/shell/src/model/index.ts
+++ b/packages/shell/src/model/index.ts
@@ -17,4 +17,5 @@ export * from './setting-top-entry';
export * from './resource';
export * from './active-tracker';
export * from './plugin-instance';
-export * from './window';
\ No newline at end of file
+export * from './window';
+export * from './clipboard';
\ No newline at end of file
diff --git a/packages/shell/src/symbols.ts b/packages/shell/src/symbols.ts
index cd164f62a..dac981e96 100644
--- a/packages/shell/src/symbols.ts
+++ b/packages/shell/src/symbols.ts
@@ -30,4 +30,5 @@ export const workspaceSymbol = Symbol('workspace');
export const windowSymbol = Symbol('window');
export const pluginInstanceSymbol = Symbol('plugin-instance');
export const resourceTypeSymbol = Symbol('resourceType');
-export const resourceSymbol = Symbol('resource');
\ No newline at end of file
+export const resourceSymbol = Symbol('resource');
+export const clipboardSymbol = Symbol('clipboard');
\ No newline at end of file
diff --git a/packages/types/src/shell/api/canvas.ts b/packages/types/src/shell/api/canvas.ts
index f7983e094..33fbc7781 100644
--- a/packages/types/src/shell/api/canvas.ts
+++ b/packages/types/src/shell/api/canvas.ts
@@ -1,4 +1,4 @@
-import { IPublicModelDragon, IPublicModelDropLocation, IPublicModelScrollTarget, IPublicModelScrollable, IPublicModelScroller, IPublicModelActiveTracker } from '../model';
+import { IPublicModelDragon, IPublicModelDropLocation, IPublicModelScrollTarget, IPublicModelScrollable, IPublicModelScroller, IPublicModelActiveTracker, IPublicModelClipboard } from '../model';
import { IPublicTypeLocationData } from '../type';
/**
@@ -54,4 +54,12 @@ export interface IPublicApiCanvas {
* @since v1.1.0
*/
get isInLiveEditing(): boolean;
+
+ /**
+ * 获取全局剪贴板实例
+ * get clipboard instance
+ *
+ * @since v1.1.0
+ */
+ get clipboard(): IPublicModelClipboard;
}
diff --git a/packages/types/src/shell/model/clipboard.ts b/packages/types/src/shell/model/clipboard.ts
new file mode 100644
index 000000000..7fdcc4b1c
--- /dev/null
+++ b/packages/types/src/shell/model/clipboard.ts
@@ -0,0 +1,25 @@
+
+export interface IPublicModelClipboard {
+
+ /**
+ * 给剪贴板赋值
+ * set data to clipboard
+ *
+ * @param {*} data
+ * @since v1.1.0
+ */
+ setData(data: any): void;
+
+ /**
+ * 设置剪贴板数据设置的回调
+ * set callback for clipboard provide paste data
+ *
+ * @param {KeyboardEvent} keyboardEvent
+ * @param {(data: any, clipboardEvent: ClipboardEvent) => void} cb
+ * @since v1.1.0
+ */
+ waitPasteData(
+ keyboardEvent: KeyboardEvent,
+ cb: (data: any, clipboardEvent: ClipboardEvent) => void,
+ ): void;
+}
diff --git a/packages/types/src/shell/model/index.ts b/packages/types/src/shell/model/index.ts
index 67335e062..b37b77dd6 100644
--- a/packages/types/src/shell/model/index.ts
+++ b/packages/types/src/shell/model/index.ts
@@ -29,3 +29,4 @@ export * from './preference';
export * from './plugin-instance';
export * from './sensor';
export * from './resource';
+export * from './clipboard';
diff --git a/packages/types/src/shell/type/resource-list.ts b/packages/types/src/shell/type/resource-list.ts
index e5fbcba7e..9b8cc3272 100644
--- a/packages/types/src/shell/type/resource-list.ts
+++ b/packages/types/src/shell/type/resource-list.ts
@@ -1,7 +1,7 @@
export interface IPublicResourceData {
resourceName: string;
title: string;
- category: string;
+ category?: string;
options: {
[key: string]: any;
};
diff --git a/packages/workspace/src/base-context.ts b/packages/workspace/src/context/base-context.ts
similarity index 95%
rename from packages/workspace/src/base-context.ts
rename to packages/workspace/src/context/base-context.ts
index 0ff63ee02..b90a131a3 100644
--- a/packages/workspace/src/base-context.ts
+++ b/packages/workspace/src/context/base-context.ts
@@ -1,5 +1,3 @@
-/* eslint-disable no-param-reassign */
-/* eslint-disable max-len */
import {
Editor,
engineConfig, Setters as InnerSetters,
@@ -33,8 +31,8 @@ import {
IPublicTypePluginMeta,
} from '@alilc/lowcode-types';
import { getLogger } from '@alilc/lowcode-utils';
-import { Workspace as InnerWorkspace } from './workspace';
-import { EditorWindow } from './editor-window/context';
+import { Workspace as InnerWorkspace } from '../workspace';
+import { EditorWindow } from '../window';
export class BasicContext {
skeleton: Skeleton;
diff --git a/packages/workspace/src/editor-view/context.ts b/packages/workspace/src/context/view-context.ts
similarity index 93%
rename from packages/workspace/src/editor-view/context.ts
rename to packages/workspace/src/context/view-context.ts
index b991532fb..55bbf2d57 100644
--- a/packages/workspace/src/editor-view/context.ts
+++ b/packages/workspace/src/context/view-context.ts
@@ -2,8 +2,8 @@ import { makeObservable, obx } from '@alilc/lowcode-editor-core';
import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types';
import { flow } from 'mobx';
import { Workspace as InnerWorkspace } from '../workspace';
-import { BasicContext } from '../base-context';
-import { EditorWindow } from '../editor-window/context';
+import { BasicContext } from './base-context';
+import { EditorWindow } from '../window';
import { getWebviewPlugin } from '../inner-plugins/webview';
export class Context extends BasicContext {
@@ -17,6 +17,10 @@ export class Context extends BasicContext {
@obx isInit: boolean = false;
+ get active() {
+ return this._activate;
+ }
+
init = flow(function* (this: any) {
if (this.viewType === 'webview') {
const url = yield this.instance?.url?.();
@@ -44,10 +48,6 @@ export class Context extends BasicContext {
this.innerHotkey.activate(this._activate);
};
- get active() {
- return this._activate;
- }
-
async save() {
return await this.instance?.save?.();
}
diff --git a/packages/workspace/src/index.ts b/packages/workspace/src/index.ts
index 2f6da97a8..9442266bb 100644
--- a/packages/workspace/src/index.ts
+++ b/packages/workspace/src/index.ts
@@ -1,4 +1,4 @@
export { Workspace } from './workspace';
-export * from './editor-window/context';
+export * from './window';
export * from './layouts/workbench';
export { Resource } from './resource';
diff --git a/packages/workspace/src/layouts/workbench.tsx b/packages/workspace/src/layouts/workbench.tsx
index 7ffb0e531..fe5ef846f 100644
--- a/packages/workspace/src/layouts/workbench.tsx
+++ b/packages/workspace/src/layouts/workbench.tsx
@@ -1,6 +1,6 @@
import { Component } from 'react';
import { TipContainer, observer } from '@alilc/lowcode-editor-core';
-import { EditorWindowView } from '../editor-window/view';
+import { WindowView } from '../view/window-view';
import classNames from 'classnames';
import TopArea from './top-area';
import LeftArea from './left-area';
@@ -46,9 +46,9 @@ export class Workbench extends Component<{
{
workspace.windows.map(d => (
-
))
diff --git a/packages/workspace/src/resource.ts b/packages/workspace/src/resource.ts
index 2495909b4..effa6abee 100644
--- a/packages/workspace/src/resource.ts
+++ b/packages/workspace/src/resource.ts
@@ -1,6 +1,6 @@
import { IPublicTypeEditorView, IPublicModelResource, IPublicResourceData, IPublicResourceTypeConfig } from '@alilc/lowcode-types';
import { Logger } from '@alilc/lowcode-utils';
-import { BasicContext } from './base-context';
+import { BasicContext } from './context/base-context';
import { ResourceType } from './resource-type';
import { Workspace as InnerWorkSpace } from './workspace';
@@ -13,20 +13,6 @@ export class Resource implements IPublicModelResource {
editorViewMap: Map
= new Map();
- constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, workspace: InnerWorkSpace) {
- this.context = new BasicContext(workspace, '');
- this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, {});
- this.init();
- if (this.resourceTypeInstance.editorViews) {
- this.resourceTypeInstance.editorViews.forEach((d: any) => {
- this.editorViewMap.set(d.viewName, d);
- });
- }
- if (!resourceType) {
- logger.error(`resourceType[${resourceType}] is unValid.`);
- }
- }
-
get name() {
return this.resourceType.name;
}
@@ -55,6 +41,24 @@ export class Resource implements IPublicModelResource {
return this.resourceData?.category;
}
+ get skeleton() {
+ return this.context.innerSkeleton;
+ }
+
+ constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, workspace: InnerWorkSpace) {
+ this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`);
+ this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, {});
+ this.init();
+ if (this.resourceTypeInstance.editorViews) {
+ this.resourceTypeInstance.editorViews.forEach((d: any) => {
+ this.editorViewMap.set(d.viewName, d);
+ });
+ }
+ if (!resourceType) {
+ logger.error(`resourceType[${resourceType}] is unValid.`);
+ }
+ }
+
async init() {
await this.resourceTypeInstance.init?.();
await this.context.innerPlugins.init();
@@ -63,6 +67,7 @@ export class Resource implements IPublicModelResource {
async import(schema: any) {
return await this.resourceTypeInstance.import?.(schema);
}
+
async save(value: any) {
return await this.resourceTypeInstance.save?.(value);
}
diff --git a/packages/workspace/src/editor-view/view.tsx b/packages/workspace/src/view/editor-view.tsx
similarity index 69%
rename from packages/workspace/src/editor-view/view.tsx
rename to packages/workspace/src/view/editor-view.tsx
index 77f0dffeb..7ada5c911 100644
--- a/packages/workspace/src/editor-view/view.tsx
+++ b/packages/workspace/src/view/editor-view.tsx
@@ -4,9 +4,9 @@ import {
Workbench,
} from '@alilc/lowcode-editor-skeleton';
import { PureComponent } from 'react';
-import { Context } from './context';
+import { Context } from '../context/view-context';
-export * from '../base-context';
+export * from '../context/base-context';
@observer
export class EditorView extends PureComponent<{
@@ -23,13 +23,11 @@ export class EditorView extends PureComponent<{
}
return (
- <>
-
- >
+
);
}
}
diff --git a/packages/workspace/src/view/resource-view.less b/packages/workspace/src/view/resource-view.less
new file mode 100644
index 000000000..4c281f8d8
--- /dev/null
+++ b/packages/workspace/src/view/resource-view.less
@@ -0,0 +1,14 @@
+.workspace-resource-view {
+ display: flex;
+ position: absolute;
+ flex-direction: column;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.workspace-editor-body {
+ position: relative;
+ height: 100%;
+}
\ No newline at end of file
diff --git a/packages/workspace/src/view/resource-view.tsx b/packages/workspace/src/view/resource-view.tsx
new file mode 100644
index 000000000..37e960b99
--- /dev/null
+++ b/packages/workspace/src/view/resource-view.tsx
@@ -0,0 +1,36 @@
+import { PureComponent } from 'react';
+import { EditorView } from './editor-view';
+import { observer } from '@alilc/lowcode-editor-core';
+import TopArea from '../layouts/top-area';
+import { Resource } from '../resource';
+import { EditorWindow } from '../window';
+import './resource-view.less';
+
+@observer
+export class ResourceView extends PureComponent<{
+ window: EditorWindow;
+ resource: Resource;
+}, any> {
+ render() {
+ const { skeleton } = this.props.resource;
+ const { editorViews } = this.props.window;
+ return (
+
+
+
+ {
+ Array.from(editorViews.values()).map((editorView: any) => {
+ return (
+
+ );
+ })
+ }
+
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/packages/workspace/src/editor-window/view.tsx b/packages/workspace/src/view/window-view.tsx
similarity index 52%
rename from packages/workspace/src/editor-window/view.tsx
rename to packages/workspace/src/view/window-view.tsx
index eb049aeed..396582a02 100644
--- a/packages/workspace/src/editor-window/view.tsx
+++ b/packages/workspace/src/view/window-view.tsx
@@ -1,17 +1,17 @@
import { PureComponent } from 'react';
-import { EditorView } from '../editor-view/view';
+import { ResourceView } from './resource-view';
import { engineConfig, observer } from '@alilc/lowcode-editor-core';
-import { EditorWindow } from './context';
+import { EditorWindow } from '../window';
import { BuiltinLoading } from '@alilc/lowcode-designer';
@observer
-export class EditorWindowView extends PureComponent<{
- editorWindow: EditorWindow;
+export class WindowView extends PureComponent<{
+ window: EditorWindow;
active: boolean;
}, any> {
render() {
const { active } = this.props;
- const { editorView, editorViews } = this.props.editorWindow;
+ const { editorView, resource } = this.props.window;
if (!editorView) {
const Loading = engineConfig.get('loadingComponent', BuiltinLoading);
return (
@@ -23,17 +23,10 @@ export class EditorWindowView extends PureComponent<{
return (
- {
- Array.from(editorViews.values()).map((editorView: any) => {
- return (
-
- );
- })
- }
+
);
}
diff --git a/packages/workspace/src/editor-window/context.ts b/packages/workspace/src/window.ts
similarity index 95%
rename from packages/workspace/src/editor-window/context.ts
rename to packages/workspace/src/window.ts
index 680647587..73064c6b4 100644
--- a/packages/workspace/src/editor-window/context.ts
+++ b/packages/workspace/src/window.ts
@@ -1,8 +1,8 @@
import { uniqueId } from '@alilc/lowcode-utils';
import { makeObservable, obx } from '@alilc/lowcode-editor-core';
-import { Context } from '../editor-view/context';
-import { Workspace } from '../workspace';
-import { Resource } from '../resource';
+import { Context } from './context/view-context';
+import { Workspace } from './workspace';
+import { Resource } from './resource';
export class EditorWindow {
id: string = uniqueId('window');
diff --git a/packages/workspace/src/workspace.ts b/packages/workspace/src/workspace.ts
index c4462a71a..509ca9d9d 100644
--- a/packages/workspace/src/workspace.ts
+++ b/packages/workspace/src/workspace.ts
@@ -2,8 +2,8 @@ import { Designer } from '@alilc/lowcode-designer';
import { createModuleEventBus, Editor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core';
import { Plugins } from '@alilc/lowcode-shell';
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType } from '@alilc/lowcode-types';
-import { BasicContext } from './base-context';
-import { EditorWindow } from './editor-window/context';
+import { BasicContext } from './context/base-context';
+import { EditorWindow } from './window';
import { Resource } from './resource';
import { ResourceType } from './resource-type';
@@ -20,6 +20,12 @@ export class Workspace implements IPublicApiWorkspace {
private emitter: IEventBus = createModuleEventBus('workspace');
+ private _isActive = false;
+
+ private resourceTypeMap: Map = new Map();
+
+ private resourceList: Resource[] = [];
+
get skeleton() {
return this.context.innerSkeleton;
}
@@ -28,7 +34,17 @@ export class Workspace implements IPublicApiWorkspace {
return this.context.innerPlugins;
}
- private _isActive = false;
+ get isActive() {
+ return this._isActive;
+ }
+
+ get defaultResourceType(): ResourceType | null {
+ if (this.resourceTypeMap.size >= 1) {
+ return Array.from(this.resourceTypeMap.values())[0];
+ }
+
+ return null;
+ }
windows: EditorWindow[] = [];
@@ -36,10 +52,6 @@ export class Workspace implements IPublicApiWorkspace {
@obx.ref window: EditorWindow;
- private resourceTypeMap: Map = new Map();
-
- private resourceList: Resource[] = [];
-
constructor(
readonly registryInnerPlugin: (designer: Designer, editor: Editor, plugins: Plugins) => Promise,
readonly shellModelFactory: any,
@@ -66,10 +78,6 @@ export class Workspace implements IPublicApiWorkspace {
this.emitChangeActiveWindow();
}
- get isActive() {
- return this._isActive;
- }
-
setActive(value: boolean) {
this._isActive = value;
}
@@ -105,14 +113,6 @@ export class Workspace implements IPublicApiWorkspace {
return this.resourceTypeMap.get(resourceName)!;
}
- get defaultResourceType(): ResourceType | null {
- if (this.resourceTypeMap.size >= 1) {
- return Array.from(this.resourceTypeMap.values())[0];
- }
-
- return null;
- }
-
removeResourceType(resourceName: string) {
if (this.resourceTypeMap.has(resourceName)) {
this.resourceTypeMap.delete(resourceName);
@@ -153,13 +153,17 @@ export class Workspace implements IPublicApiWorkspace {
console.error(`${name} is not available`);
return;
}
- const filterWindows = this.windows.filter(d => (d.resource.name === name && d.title == title));
+ const filterWindows = this.windows.filter(d => (d.resource.name === name && d.resource.title == title));
if (filterWindows && filterWindows.length) {
this.window = filterWindows[0];
this.emitChangeActiveWindow();
return;
}
- const resource = new Resource({}, resourceType, this);
+ const resource = new Resource({
+ resourceName: name,
+ title,
+ options,
+ }, resourceType, this);
this.window = new EditorWindow(resource, this, title, options);
this.windows.push(this.window);
this.editorWindowMap.set(this.window.id, this.window);