diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfa027327..b7813f9b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+### Bug Fixes
+
+* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
+
+
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/lerna.json b/lerna.json
index 65f6a7d0d..65c7d3bd9 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
{
"lerna": "2.11.0",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"npmClient": "tyarn",
"registry": "http://registry.npm.alibaba-inc.com",
"useWorkspaces": true,
diff --git a/packages/code-generator/CHANGELOG.md b/packages/code-generator/CHANGELOG.md
index 9936155ba..ba3fca12c 100644
--- a/packages/code-generator/CHANGELOG.md
+++ b/packages/code-generator/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-code-generator
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/code-generator/package.json b/packages/code-generator/package.json
index 44be8fe8d..c60f82331 100644
--- a/packages/code-generator/package.json
+++ b/packages/code-generator/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-code-generator",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "出码引擎 for LowCode Engine",
"main": "lib/index.js",
"files": [
diff --git a/packages/demo-server/CHANGELOG.md b/packages/demo-server/CHANGELOG.md
index 61e3ef71b..545b5d9ac 100644
--- a/packages/demo-server/CHANGELOG.md
+++ b/packages/demo-server/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-demo-server
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/demo-server/package.json b/packages/demo-server/package.json
index ee5d486f8..e43c5ed7a 100644
--- a/packages/demo-server/package.json
+++ b/packages/demo-server/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-demo-server",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"private": true,
"description": "低代码引擎 DEMO Server 端",
"scripts": {
diff --git a/packages/demo/CHANGELOG.md b/packages/demo/CHANGELOG.md
index 016ccb49d..a1f655d59 100644
--- a/packages/demo/CHANGELOG.md
+++ b/packages/demo/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+### Bug Fixes
+
+* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
+
+
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/demo/build.plugin.js b/packages/demo/build.plugin.js
index b271703c3..c4255c125 100644
--- a/packages/demo/build.plugin.js
+++ b/packages/demo/build.plugin.js
@@ -1,6 +1,6 @@
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
-module.exports = ({ onGetWebpackConfig }) => {
+module.exports = ({ context, onGetWebpackConfig }) => {
onGetWebpackConfig((config) => {
config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [
{
@@ -9,5 +9,8 @@ module.exports = ({ onGetWebpackConfig }) => {
]);
config.plugins.delete('hot');
config.devServer.hot(false);
+ if (context.command === 'start') {
+ config.devtool('inline-source-map');
+ }
});
};
diff --git a/packages/demo/package.json b/packages/demo/package.json
index f155d3282..e15c767cb 100644
--- a/packages/demo/package.json
+++ b/packages/demo/package.json
@@ -1,29 +1,30 @@
{
"name": "@ali/lowcode-demo",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"private": true,
"description": "低代码引擎 DEMO",
"scripts": {
- "cloud-build": "build-scripts build --config cloud-build.json",
- "start": "build-scripts start"
+ "start": "build-scripts start",
+ "build": "build-scripts build",
+ "cloud-build": "build-scripts build --config cloud-build.json"
},
"config": {},
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-editor-skeleton": "^0.13.1-10",
- "@ali/lowcode-plugin-components-pane": "^0.13.1-10",
- "@ali/lowcode-plugin-designer": "^0.13.1-10",
- "@ali/lowcode-plugin-event-bind-dialog": "^0.13.1-10",
- "@ali/lowcode-plugin-outline-pane": "^0.13.1-10",
- "@ali/lowcode-plugin-sample-logo": "^0.13.1-10",
- "@ali/lowcode-plugin-sample-preview": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-editor-skeleton": "^0.13.1-11",
+ "@ali/lowcode-plugin-components-pane": "^0.13.1-11",
+ "@ali/lowcode-plugin-designer": "^0.13.1-11",
+ "@ali/lowcode-plugin-event-bind-dialog": "^0.13.1-11",
+ "@ali/lowcode-plugin-outline-pane": "^0.13.1-11",
+ "@ali/lowcode-plugin-sample-logo": "^0.13.1-11",
+ "@ali/lowcode-plugin-sample-preview": "^0.13.1-11",
"@ali/lowcode-plugin-settings-pane": "^0.8.8",
- "@ali/lowcode-plugin-undo-redo": "^0.13.1-10",
- "@ali/lowcode-plugin-variable-bind-dialog": "^0.13.1-10",
- "@ali/lowcode-plugin-zh-en": "^0.13.1-10",
- "@ali/lowcode-react-renderer": "^0.13.1-10",
- "@ali/lowcode-runtime": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-plugin-undo-redo": "^0.13.1-11",
+ "@ali/lowcode-plugin-variable-bind-dialog": "^0.13.1-11",
+ "@ali/lowcode-plugin-zh-en": "^0.13.1-11",
+ "@ali/lowcode-react-renderer": "^0.13.1-11",
+ "@ali/lowcode-runtime": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@ali/ve-action-pane": "^4.7.0-beta.0",
"@ali/ve-datapool-pane": "^6.4.3",
"@ali/ve-history-pane": "4.0.0",
diff --git a/packages/designer/.eslintrc.js b/packages/designer/.eslintrc.js
index a44376585..35f9add82 100644
--- a/packages/designer/.eslintrc.js
+++ b/packages/designer/.eslintrc.js
@@ -14,5 +14,6 @@ module.exports = {
'no-useless-constructor': 1,
'no-empty-function': 1,
'@typescript-eslint/member-ordering': 0,
+ 'lines-between-class-members': 0
}
}
\ No newline at end of file
diff --git a/packages/designer/CHANGELOG.md b/packages/designer/CHANGELOG.md
index dca6d9f0e..776adcdef 100644
--- a/packages/designer/CHANGELOG.md
+++ b/packages/designer/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+### Bug Fixes
+
+* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
+
+
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/designer/build.test.json b/packages/designer/build.test.json
index 93dfcd983..228c07e7f 100644
--- a/packages/designer/build.test.json
+++ b/packages/designer/build.test.json
@@ -1,5 +1,6 @@
{
"plugins": [
+ "build-plugin-component",
"@ali/lowcode-test-mate/plugin/index.ts"
]
}
diff --git a/packages/designer/jest.config.js b/packages/designer/jest.config.js
index 83eb1dc90..b1c191127 100644
--- a/packages/designer/jest.config.js
+++ b/packages/designer/jest.config.js
@@ -14,6 +14,7 @@ module.exports = {
collectCoverage: false,
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
+ '!src/**/*.d.ts',
'!**/node_modules/**',
'!**/vendor/**',
],
diff --git a/packages/designer/package.json b/packages/designer/package.json
index d8dd526f8..5d07e9f8e 100644
--- a/packages/designer/package.json
+++ b/packages/designer/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-designer",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Designer for Ali LowCode Engine",
"main": "lib/index.js",
"module": "es/index.js",
@@ -10,13 +10,13 @@
],
"scripts": {
"build": "build-scripts build --skip-demo",
- "test": "build-scripts --config build.test.json test"
+ "test": "build-scripts test --config build.test.json"
},
"license": "MIT",
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"classnames": "^2.2.6",
"event": "^1.0.0",
"react": "^16",
@@ -33,8 +33,7 @@
"build-plugin-component": "^0.2.10",
"build-scripts-config": "^0.1.8",
"jest": "^26.5.2",
- "lodash.clonedeep": "^4.5.0",
- "lodash.set": "^4.3.2",
+ "lodash": "^4.17.20",
"ts-jest": "^26.4.1",
"typescript": "^4.0.3"
},
diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx
index 12aa99174..7c60e0143 100644
--- a/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx
+++ b/packages/designer/src/builtin-simulator/bem-tools/border-resizing.tsx
@@ -179,7 +179,7 @@ export class BoxResizingInstance extends Component<{
typeof metaData.experimental.callbacks.onResizeEnd === 'function'
) {
(e as any).trigger = direction;
- metaData.experimental.callbacks.onResizeStart(e, node);
+ metaData.experimental.callbacks.onResizeEnd(e, node);
}
const editor = globalContext.get(Editor);
diff --git a/packages/designer/src/builtin-simulator/utils/parse-metadata.ts b/packages/designer/src/builtin-simulator/utils/parse-metadata.ts
index 3bcf9d6d4..96c92943a 100644
--- a/packages/designer/src/builtin-simulator/utils/parse-metadata.ts
+++ b/packages/designer/src/builtin-simulator/utils/parse-metadata.ts
@@ -54,7 +54,7 @@ const LowcodeTypes: any = {
(window as any).PropTypes = LowcodeTypes;
(window as any).React.PropTypes = LowcodeTypes;
-// override primitive type chechers
+// override primitive type checkers
primitiveTypes.forEach(type => {
const propType = (PropTypes as any)[type];
if (!propType) {
diff --git a/packages/designer/src/designer/setting/setting-top-entry.ts b/packages/designer/src/designer/setting/setting-top-entry.ts
index 507fc053c..405c76faa 100644
--- a/packages/designer/src/designer/setting/setting-top-entry.ts
+++ b/packages/designer/src/designer/setting/setting-top-entry.ts
@@ -68,7 +68,7 @@ export class SettingTopEntry implements SettingEntry {
readonly designer: Designer;
constructor(readonly editor: IEditor, readonly nodes: Node[]) {
- if (nodes.length < 1) {
+ if (!Array.isArray(nodes) || nodes.length < 1) {
throw new ReferenceError('nodes should not be empty');
}
this.id = generateSessionId(nodes);
diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts
index 42b292880..cef2bc77e 100644
--- a/packages/designer/src/document/document-model.ts
+++ b/packages/designer/src/document/document-model.ts
@@ -205,7 +205,7 @@ export class DocumentModel {
}
let node: Node | null = null;
- if (this.inited) {
+ if (this.hasNode(schema?.id)) {
schema.id = null;
}
if (schema.id) {
diff --git a/packages/designer/src/document/history.ts b/packages/designer/src/document/history.ts
index 972fced01..e4aa09e1a 100644
--- a/packages/designer/src/document/history.ts
+++ b/packages/designer/src/document/history.ts
@@ -9,7 +9,7 @@ export interface Serialization {
unserialize(data: T): NodeSchema;
}
-let currentSerializion: Serialization = {
+let currentSerialization: Serialization = {
serialize(data: NodeSchema): string {
return JSON.stringify(data);
},
@@ -18,8 +18,8 @@ let currentSerializion: Serialization = {
},
};
-export function setSerialization(serializion: Serialization) {
- currentSerializion = serializion;
+export function setSerialization(serialization: Serialization) {
+ currentSerialization = serialization;
}
export class History {
@@ -46,7 +46,7 @@ export class History {
return;
}
untracked(() => {
- const log = currentSerializion.serialize(data);
+ const log = currentSerialization.serialize(data);
if (this.session.cursor === 0 && this.session.isActive()) {
// first log
this.session.log(log);
@@ -98,7 +98,7 @@ export class History {
this.obx.sleep();
try {
- this.redoer(currentSerializion.unserialize(hotData));
+ this.redoer(currentSerialization.unserialize(hotData));
this.emitter.emit('cursor', hotData);
} catch (e) {
//
@@ -222,7 +222,7 @@ class Session {
end() {
if (this.isActive()) {
this.clearTimer();
- console.info('session end');
+ // console.info('session end');
}
}
diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts
index df0ebef6e..a2deabff7 100644
--- a/packages/designer/src/document/node/node.ts
+++ b/packages/designer/src/document/node/node.ts
@@ -23,6 +23,7 @@ import { ReactElement } from 'react';
import { SettingTopEntry } from 'designer/src/designer';
import { EventEmitter } from 'events';
import { includeSlot, removeSlot } from '../../utils/slot';
+import { foreachReverse } from '../../utils/tree';
/**
* 基础节点
@@ -294,9 +295,9 @@ export class Node {
if (useMutator) {
this._parent?.didDropOut(this);
}
- // 建立新的父子关系
- this._parent = parent;
if (parent) {
+ // 建立新的父子关系,尤其注意:对于 parent 为 null 的场景,不会赋值,因为 subtreeModified 等事件可能需要知道该 node 被删除前的父子关系
+ this._parent = parent;
this.document.removeWillPurge(this);
if (!this.conditionGroup) {
// initial conditionGroup
@@ -594,7 +595,11 @@ export class Node {
import(data: Schema, checkId = false) {
const { componentName, id, children, props, ...extras } = data;
-
+ if (this.isSlot()) {
+ foreachReverse(this.children, (subNode: Node) => {
+ subNode.remove(true, true);
+ }, (iterable, idx) => (iterable as NodeChildren).get(idx));
+ }
if (this.isParental()) {
this.props.import(props, extras);
(this._children as NodeChildren).import(children, checkId);
@@ -709,12 +714,12 @@ export class Node {
}
addSlot(slotNode: Node) {
- slotNode.internalSetParent(this as ParentalNode, true);
const slotName = slotNode?.getExtraProp('name')?.getAsString();
// 一个组件下的所有 slot,相同 slotName 的 slot 应该是唯一的
if (includeSlot(this, slotName)) {
removeSlot(this, slotName);
}
+ slotNode.internalSetParent(this as ParentalNode, true);
this._slots.push(slotNode);
}
@@ -756,7 +761,7 @@ export class Node {
this.purged = true;
this.autoruns?.forEach((dispose) => dispose());
this.props.purge();
- this.document.destroyNode(this);
+ // this.document.destroyNode(this);
}
/**
diff --git a/packages/designer/src/document/node/props/prop.ts b/packages/designer/src/document/node/props/prop.ts
index 704a99ba6..8fdea7d66 100644
--- a/packages/designer/src/document/node/props/prop.ts
+++ b/packages/designer/src/document/node/props/prop.ts
@@ -269,7 +269,7 @@ export class Prop implements IPropParent {
this.stash.clear();
}
if (this._type !== 'slot' && this._slotNode) {
- this._slotNode.purge();
+ this._slotNode.remove();
this._slotNode = undefined;
}
}
diff --git a/packages/designer/src/project/project.ts b/packages/designer/src/project/project.ts
index 2c16c25b0..9a482d3ee 100644
--- a/packages/designer/src/project/project.ts
+++ b/packages/designer/src/project/project.ts
@@ -101,7 +101,9 @@ export class Project {
if (this.documents.length < 1) {
return;
}
- this.documents.forEach((doc) => doc.remove());
+ for (let i = this.documents.length - 1; i >= 0; i--) {
+ this.documents[i].remove();
+ }
}
removeDocument(doc: DocumentModel) {
diff --git a/packages/designer/src/utils/slot.ts b/packages/designer/src/utils/slot.ts
index 9fe1ef5f7..9061326b1 100644
--- a/packages/designer/src/utils/slot.ts
+++ b/packages/designer/src/utils/slot.ts
@@ -11,6 +11,7 @@ export function removeSlot(node: Node, slotName: string | undefined): boolean {
const { slots = [] } = node;
return slots.some((slot, idx) => {
if (slotName && slotName === slot?.getExtraProp('name')?.getAsString()) {
+ slot.remove();
slots.splice(idx, 1);
return true;
}
diff --git a/packages/designer/tests/bugs/misc.ts b/packages/designer/tests/bugs/misc.ts
new file mode 100644
index 000000000..e101d868f
--- /dev/null
+++ b/packages/designer/tests/bugs/misc.ts
@@ -0,0 +1,55 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Project } from '../../src/project/project';
+// import { Node } from '../../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getComponentMeta() {
+ return {
+ getMetadata() {
+ return { experimental: null };
+ },
+ };
+ },
+ transformProps(props) { return props; },
+ createSettingEntry: mockCreateSettingEntry,
+ postEvent() {},
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+it.todo('在同一个节点下,相同名称的 slot 只能有一个', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ expect(nodesMap.size).toBe(expectedNodeCnt);
+ ids.forEach(id => {
+ expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
+ });
+
+ const exportSchema = currentDocument?.export(1);
+ expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
+ expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
+});
\ No newline at end of file
diff --git a/packages/designer/tests/builtin-simulator/parse-metadata.test.ts b/packages/designer/tests/builtin-simulator/parse-metadata.test.ts
new file mode 100644
index 000000000..eefb55f7c
--- /dev/null
+++ b/packages/designer/tests/builtin-simulator/parse-metadata.test.ts
@@ -0,0 +1,9 @@
+import '../fixtures/window';
+import { parseMetadata } from '../../src/builtin-simulator/utils/parse-metadata';
+
+describe('parseMetadata', () => {
+ it('parseMetadata', async () => {
+ console.log(parseMetadata('Div'))
+ console.log(parseMetadata({ componentName: 'Div' }));
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/builtin-simulator/path.test.ts b/packages/designer/tests/builtin-simulator/path.test.ts
new file mode 100644
index 000000000..6a15edbcf
--- /dev/null
+++ b/packages/designer/tests/builtin-simulator/path.test.ts
@@ -0,0 +1,78 @@
+import {
+ generateComponentName,
+ getNormalizedImportPath,
+ isPackagePath,
+ toTitleCase,
+ makeRelativePath,
+ removeVersion,
+ resolveAbsoluatePath,
+ joinPath,
+} from '../../src/builtin-simulator/utils/path';
+
+describe('builtin-simulator/utils/path 测试', () => {
+ it('isPackagePath', () => {
+ expect(isPackagePath('a')).toBeTruthy;
+ expect(isPackagePath('@ali/a')).toBeTruthy;
+ expect(isPackagePath('@alife/a')).toBeTruthy;
+ expect(isPackagePath('a.b')).toBeTruthy;
+ expect(isPackagePath('./a')).toBeFalsy;
+ expect(isPackagePath('../a')).toBeFalsy;
+ expect(isPackagePath('/a')).toBeFalsy;
+ });
+
+ it('toTitleCase', () => {
+ expect(toTitleCase('a')).toBe('A');
+ expect(toTitleCase('a_b')).toBe('AB');
+ expect(toTitleCase('a b')).toBe('AB');
+ expect(toTitleCase('a-b')).toBe('AB');
+ expect(toTitleCase('a.b')).toBe('AB');
+ expect(toTitleCase('a.b.cx')).toBe('ABCx');
+ });
+
+ it('generateComponentName', () => {
+ expect(generateComponentName('a/index.js')).toBe('A');
+ expect(generateComponentName('a_b/index.js')).toBe('AB');
+ expect(generateComponentName('a_b/index.web.js')).toBe('AB');
+ expect(generateComponentName('a_b/index.xxx.js')).toBe('AB');
+ expect(generateComponentName('a_b')).toBe('AB');
+ expect(generateComponentName('')).toBe('Component');
+ });
+
+ it('getNormalizedImportPath', () => {
+ expect(getNormalizedImportPath('/a')).toBe('/a');
+ expect(getNormalizedImportPath('/a/')).toBe('/a/');
+ expect(getNormalizedImportPath('/a/index.js')).toBe('/a');
+ expect(getNormalizedImportPath('/a/index.ts')).toBe('/a');
+ expect(getNormalizedImportPath('/a/index.jsx')).toBe('/a');
+ expect(getNormalizedImportPath('/a/index.tsx')).toBe('/a');
+ expect(getNormalizedImportPath('/a/index.x')).toBe('/a/index.x');
+ });
+
+ it('makeRelativePath', () => {
+ expect(makeRelativePath('/a/b/c', '/a/b')).toBe('c');
+ expect(makeRelativePath('a/b/c', '/a/c')).toBe('a/b/c');
+ expect(makeRelativePath('/a/b/c', '/a/c')).toBe('./b/c');
+ expect(makeRelativePath('/a/b/c', '/a/c/d')).toBe('../b/c');
+ });
+
+ it('resolveAbsoluatePath', () => {
+ expect(resolveAbsoluatePath('/a/b/c', '/a')).toBe('/a/b/c');
+ expect(resolveAbsoluatePath('@ali/fe', '/a')).toBe('@ali/fe');
+ expect(resolveAbsoluatePath('./a/b', '/c')).toBe('/c/a/b');
+ expect(resolveAbsoluatePath('./a/b/d', '/c')).toBe('/c/a/b/d');
+ expect(resolveAbsoluatePath('../a/b', '/c')).toBe('/a/b');
+ expect(resolveAbsoluatePath('../a/b/d', '/c')).toBe('/a/b/d');
+ expect(resolveAbsoluatePath('../../a', 'c')).toBe('../a');
+ });
+
+ it('joinPath', () => {
+ expect(joinPath('/a', 'b', 'c')).toBe('/a/b/c');
+ expect(joinPath('a', 'b', 'c')).toBe('./a/b/c');
+ });
+
+ it('removeVersion', () => {
+ expect(removeVersion('@ali/fe')).toBe('@ali/fe');
+ expect(removeVersion('@ali/fe@1.0.0/index')).toBe('@ali/fe/index');
+ expect(removeVersion('haha')).toBe('haha');
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/builtin-simulator/throttle.test.ts b/packages/designer/tests/builtin-simulator/throttle.test.ts
new file mode 100644
index 000000000..fd2d7ce33
--- /dev/null
+++ b/packages/designer/tests/builtin-simulator/throttle.test.ts
@@ -0,0 +1,22 @@
+import '../fixtures/disable-raf';
+import { throttle } from '../../src/builtin-simulator/utils/throttle';
+
+const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
+
+const cb = jest.fn();
+
+describe('throttle', () => {
+ it('simple', async () => {
+ const fn = throttle(cb, 1000);
+ fn();
+
+ expect(cb).toBeCalledTimes(1);
+
+ await delay(200);
+ fn();
+
+ await delay(400);
+ fn();
+ expect(cb).toBeCalledTimes(1);
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/document/document-model/document-model.test.ts b/packages/designer/tests/document/document-model/document-model.test.ts
index ca0c9f173..94eda1871 100644
--- a/packages/designer/tests/document/document-model/document-model.test.ts
+++ b/packages/designer/tests/document/document-model/document-model.test.ts
@@ -1,12 +1,11 @@
import '../../fixtures/window';
-console.log('window.matchMedia', window.matchMedia);
window.matchMedia('width=600px');
import { DocumentModel } from '../../../src/document/document-model';
// const { DocumentModel } = require('../../../src/document/document-model');
// const { Node } = require('../__mocks__/node');
-describe('basic utility', () => {
- test.only('delegateMethod - useOriginMethodName', () => {
+describe.skip('basic utility', () => {
+ test('delegateMethod - useOriginMethodName', () => {
const node = new DocumentModel({}, {
componentName: 'Component',
diff --git a/packages/designer/tests/document/document-model/node.test.ts b/packages/designer/tests/document/document-model/node.test.ts
index e183aa6bd..29ea34123 100644
--- a/packages/designer/tests/document/document-model/node.test.ts
+++ b/packages/designer/tests/document/document-model/node.test.ts
@@ -17,7 +17,7 @@ jest.mock('../../../src/document/document-model', () => {
};
});
-describe('basic utility', () => {
+describe.skip('basic utility', () => {
test('delegateMethod - useOriginMethodName', () => {
const dm = new DocumentModel({} as any, {} as any);
console.log(dm.nextId);
diff --git a/packages/designer/tests/document/selection.test.ts b/packages/designer/tests/document/selection.test.ts
new file mode 100644
index 000000000..4d81e935e
--- /dev/null
+++ b/packages/designer/tests/document/selection.test.ts
@@ -0,0 +1,245 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getComponentMeta() {
+ return {
+ getMetadata() {
+ return { experimental: null };
+ },
+ };
+ },
+ transformProps(props) { return props; },
+ createSettingEntry: mockCreateSettingEntry,
+ postEvent() {},
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+describe('选择区测试', () => {
+ it('常规方法', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+ const selectionChangeHandler = jest.fn();
+ selection.onSelectionChange(selectionChangeHandler);
+
+ selection.select('form');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selection.selected).toEqual(['form']);
+ selectionChangeHandler.mockClear();
+
+ selection.select('form');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
+ expect(selection.selected).toEqual(['form']);
+
+ selection.select('node_k1ow3cbj');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['node_k1ow3cbj']);
+ expect(selection.selected).toEqual(['node_k1ow3cbj']);
+ selectionChangeHandler.mockClear();
+
+ selection.selectAll(['node_k1ow3cbj', 'form']);
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['node_k1ow3cbj', 'form']);
+ expect(selection.selected).toEqual(['node_k1ow3cbj', 'form']);
+ selectionChangeHandler.mockClear();
+
+ selection.remove('node_k1ow3cbj');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
+ expect(selection.selected).toEqual(['form']);
+ selectionChangeHandler.mockClear();
+
+ selection.clear();
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual([]);
+ expect(selection.selected).toEqual([]);
+ selectionChangeHandler.mockClear();
+
+ // 无选中时调用 clear,不再触发事件
+ selection.clear();
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
+ expect(selection.selected).toEqual([]);
+ selectionChangeHandler.mockClear();
+ });
+
+ it('add 方法', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+ const selectionChangeHandler = jest.fn();
+ selection.onSelectionChange(selectionChangeHandler);
+
+ selection.add('form');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
+ expect(selection.selected).toEqual(['form']);
+ selectionChangeHandler.mockClear();
+
+ // 再加一次相同的节点,不触发事件
+ selection.add('form');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
+ expect(selection.selected).toEqual(['form']);
+ selectionChangeHandler.mockClear();
+
+ selection.add('form2');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'form2']);
+ expect(selection.selected).toEqual(['form', 'form2']);
+ selectionChangeHandler.mockClear();
+ });
+
+ it('dispose 方法', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+
+ selection.selectAll(['form', 'node_k1ow3cbj', 'form2']);
+
+ const selectionChangeHandler = jest.fn();
+ selection.onSelectionChange(selectionChangeHandler);
+ selection.dispose();
+
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'node_k1ow3cbj']);
+ expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']);
+ selectionChangeHandler.mockClear();
+ });
+
+ it('dispose 方法', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+
+ selection.selectAll(['form', 'node_k1ow3cbj', 'form2']);
+
+ const selectionChangeHandler = jest.fn();
+ selection.onSelectionChange(selectionChangeHandler);
+ selection.dispose();
+
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'node_k1ow3cbj']);
+ expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']);
+ selectionChangeHandler.mockClear();
+ });
+
+ it('containsNode 方法', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+ const selectionChangeHandler = jest.fn();
+ selection.onSelectionChange(selectionChangeHandler);
+
+ selection.select('form');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
+ expect(selection.selected).toEqual(['form']);
+ expect(selection.has('form')).toBe(true);
+ expect(selection.containsNode(currentDocument?.getNode('form'))).toBe(true);
+ expect(selection.containsNode(currentDocument?.getNode('node_k1ow3cbj'))).toBe(true);
+ expect(selection.containsNode(currentDocument?.getNode('node_k1ow3cb9'))).toBe(false);
+ expect(selection.getNodes()).toEqual([currentDocument?.getNode('form')]);
+ selectionChangeHandler.mockClear();
+
+ selection.add('node_k1ow3cbj');
+ expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']);
+ expect(selection.getTopNodes()).toEqual([currentDocument?.getNode('form')]);
+ expect(selection.getTopNodes(true)).toEqual([currentDocument?.getNode('form')]);
+ });
+
+ it('containsNode 方法 - excludeRoot: true', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+ const selectionChangeHandler = jest.fn();
+ selection.onSelectionChange(selectionChangeHandler);
+
+ selection.select('node_k1ow3cb9');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['node_k1ow3cb9']);
+ expect(selection.selected).toEqual(['node_k1ow3cb9']);
+ expect(selection.has('node_k1ow3cb9')).toBe(true);
+ expect(selection.containsNode(currentDocument?.getNode('form'))).toBe(true);
+ expect(selection.containsNode(currentDocument?.getNode('form'), true)).toBe(false);
+ selectionChangeHandler.mockClear();
+ });
+
+ it('containsNode 方法 - excludeRoot: true', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap, selection } = currentDocument!;
+ const selectionChangeHandler = jest.fn();
+ const dispose = selection.onSelectionChange(selectionChangeHandler);
+
+ selection.select('form');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
+ expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
+ selectionChangeHandler.mockClear();
+
+ // dispose 后,selected 会被赋值,但是变更事件不会被触发
+ dispose();
+ selection.select('node_k1ow3cb9');
+ expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
+ expect(selection.selected).toEqual(['node_k1ow3cb9']);
+ selectionChangeHandler.mockClear();
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/fixtures/component-metadata/div.ts b/packages/designer/tests/fixtures/component-metadata/div.ts
new file mode 100644
index 000000000..395cb58bb
--- /dev/null
+++ b/packages/designer/tests/fixtures/component-metadata/div.ts
@@ -0,0 +1,275 @@
+export default {
+ componentName: 'Div',
+ title: '容器',
+ docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ devMode: 'procode',
+ tags: ['布局'],
+ configure: {
+ props: [
+ {
+ type: 'field',
+ name: 'behavior',
+ title: '默认状态',
+ extraProps: {
+ display: 'inline',
+ defaultValue: 'NORMAL',
+ },
+ setter: {
+ componentName: 'MixedSetter',
+ props: {
+ setters: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ 'VariableSetter',
+ ],
+ },
+ },
+ },
+ {
+ type: 'field',
+ name: '__style__',
+ title: {
+ label: '样式设置',
+ tip: '点击 ? 查看样式设置器用法指南',
+ docUrl: 'https://lark.alipay.com/legao/help/design-tool-style',
+ },
+ extraProps: {
+ display: 'accordion',
+ defaultValue: {},
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ advanced: true,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'group',
+ name: 'groupkgzzeo41',
+ title: '高级',
+ extraProps: {
+ display: 'accordion',
+ },
+ items: [
+ {
+ type: 'field',
+ name: 'fieldId',
+ title: {
+ label: '唯一标识',
+ },
+ extraProps: {
+ display: 'block',
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: '请输入唯一标识',
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'useFieldIdAsDomId',
+ title: {
+ label: '将唯一标识用作 DOM ID',
+ },
+ extraProps: {
+ display: 'block',
+ defaultValue: false,
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {},
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'customClassName',
+ title: '自定义样式类',
+ extraProps: {
+ display: 'block',
+ defaultValue: '',
+ },
+ setter: {
+ componentName: 'MixedSetter',
+ props: {
+ setters: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: null,
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ 'VariableSetter',
+ ],
+ },
+ },
+ },
+ {
+ type: 'field',
+ name: 'events',
+ title: {
+ label: '动作设置',
+ tip: '点击 ? 查看如何设置组件的事件响应动作',
+ docUrl: 'https://lark.alipay.com/legao/legao/events-call',
+ },
+ extraProps: {
+ display: 'accordion',
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ events: [
+ {
+ name: 'onClick',
+ title: '当点击时',
+ initialValue:
+ "/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
+ },
+ {
+ name: 'onMouseEnter',
+ title: '当鼠标进入时',
+ initialValue:
+ "/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
+ },
+ {
+ name: 'onMouseLeave',
+ title: '当鼠标离开时',
+ initialValue:
+ "/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
+ },
+ ],
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'onClick',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ {
+ type: 'field',
+ name: 'onMouseEnter',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ {
+ type: 'field',
+ name: 'onMouseLeave',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ ],
+ },
+ ],
+ component: {
+ isContainer: true,
+ nestingRule: {
+ parentWhitelist: 'Div',
+ childWhitelist: 'Div',
+ },
+ },
+ supports: {},
+ },
+ experimental: {
+ callbacks: {},
+ initials: [
+ {
+ name: 'behavior',
+ },
+ {
+ name: '__style__',
+ },
+ {
+ name: 'fieldId',
+ },
+ {
+ name: 'useFieldIdAsDomId',
+ },
+ {
+ name: 'customClassName',
+ },
+ {
+ name: 'events',
+ },
+ {
+ name: 'onClick',
+ },
+ {
+ name: 'onMouseEnter',
+ },
+ {
+ name: 'onMouseLeave',
+ },
+ ],
+ filters: [
+ {
+ name: 'events',
+ },
+ {
+ name: 'onClick',
+ },
+ {
+ name: 'onMouseEnter',
+ },
+ {
+ name: 'onMouseLeave',
+ },
+ ],
+ autoruns: [],
+ },
+};
diff --git a/packages/designer/tests/fixtures/disable-raf.ts b/packages/designer/tests/fixtures/disable-raf.ts
new file mode 100644
index 000000000..14b710125
--- /dev/null
+++ b/packages/designer/tests/fixtures/disable-raf.ts
@@ -0,0 +1,3 @@
+Object.defineProperty(window, 'requestAnimationFrame', {
+ value: null,
+})
\ No newline at end of file
diff --git a/packages/designer/tests/fixtures/prototype/div-meta.ts b/packages/designer/tests/fixtures/prototype/div-meta.ts
new file mode 100644
index 000000000..a2b410494
--- /dev/null
+++ b/packages/designer/tests/fixtures/prototype/div-meta.ts
@@ -0,0 +1,259 @@
+export default {
+ componentName: 'Div',
+ title: '容器',
+ docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ devMode: 'procode',
+ tags: ['布局'],
+ configure: {
+ props: [
+ {
+ type: 'field',
+ name: 'behavior',
+ title: '默认状态',
+ extraProps: {
+ display: 'inline',
+ defaultValue: 'NORMAL',
+ },
+ setter: {
+ componentName: 'MixedSetter',
+ props: {
+ setters: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ 'VariableSetter',
+ ],
+ },
+ },
+ },
+ {
+ type: 'field',
+ name: '__style__',
+ title: {
+ label: '样式设置',
+ tip: '点击 ? 查看样式设置器用法指南',
+ docUrl: 'https://lark.alipay.com/legao/help/design-tool-style',
+ },
+ extraProps: {
+ display: 'accordion',
+ defaultValue: {},
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ advanced: true,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'group',
+ name: 'groupkh97h5kc',
+ title: '高级',
+ extraProps: {
+ display: 'accordion',
+ },
+ items: [
+ {
+ type: 'field',
+ name: 'fieldId',
+ title: {
+ label: '唯一标识',
+ },
+ extraProps: {
+ display: 'block',
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: '请输入唯一标识',
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'useFieldIdAsDomId',
+ title: {
+ label: '将唯一标识用作 DOM ID',
+ },
+ extraProps: {
+ display: 'block',
+ defaultValue: false,
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {},
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'customClassName',
+ title: '自定义样式类',
+ extraProps: {
+ display: 'block',
+ defaultValue: '',
+ },
+ setter: {
+ componentName: 'MixedSetter',
+ props: {
+ setters: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: null,
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ 'VariableSetter',
+ ],
+ },
+ },
+ },
+ {
+ type: 'field',
+ name: 'events',
+ title: {
+ label: '动作设置',
+ tip: '点击 ? 查看如何设置组件的事件响应动作',
+ docUrl: 'https://lark.alipay.com/legao/legao/events-call',
+ },
+ extraProps: {
+ display: 'accordion',
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ events: [
+ {
+ name: 'onClick',
+ title: '当点击时',
+ initialValue:
+ "/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
+ },
+ {
+ name: 'onMouseEnter',
+ title: '当鼠标进入时',
+ initialValue:
+ "/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
+ },
+ {
+ name: 'onMouseLeave',
+ title: '当鼠标离开时',
+ initialValue:
+ "/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
+ },
+ ],
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'onClick',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ {
+ type: 'field',
+ name: 'onMouseEnter',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ {
+ type: 'field',
+ name: 'onMouseLeave',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ ],
+ },
+ ],
+ component: {
+ isContainer: true,
+ nestingRule: {},
+ },
+ supports: {},
+ },
+ experimental: {
+ callbacks: {},
+ initials: [
+ {
+ name: 'behavior',
+ },
+ {
+ name: '__style__',
+ },
+ {
+ name: 'fieldId',
+ },
+ {
+ name: 'useFieldIdAsDomId',
+ },
+ {
+ name: 'customClassName',
+ },
+ {
+ name: 'events',
+ },
+ {
+ name: 'onClick',
+ },
+ {
+ name: 'onMouseEnter',
+ },
+ {
+ name: 'onMouseLeave',
+ },
+ ],
+ filters: [],
+ autoruns: [],
+ },
+};
diff --git a/packages/designer/tests/fixtures/schema/form.ts b/packages/designer/tests/fixtures/schema/form.ts
index 8438c8b39..903b21756 100644
--- a/packages/designer/tests/fixtures/schema/form.ts
+++ b/packages/designer/tests/fixtures/schema/form.ts
@@ -1,6 +1,7 @@
export default {
componentName: 'Page',
id: 'node_k1ow3cb9',
+ title: 'hey, i\' a page!',
props: {
extensions: {
启用页头: true,
@@ -111,7 +112,8 @@ export default {
children: [
{
componentName: 'Form',
- id: 'node_k1ow3cbq',
+ id: 'form',
+ extraPropA: 'extraPropA',
props: {
size: 'medium',
labelAlign: 'top',
@@ -123,9 +125,15 @@ export default {
type: 'variable',
variable: 'state.formData',
},
+ obj: {
+ a: 1,
+ b: false,
+ c: 'string',
+ },
__style__: {},
fieldId: 'form',
fieldOptions: {},
+ slotA: '',
},
condition: true,
children: [
@@ -949,6 +957,13 @@ export default {
},
__style__: ':root {\n width: 80px;\n}',
fieldId: 'button_k1ow3h1p',
+ greeting: {
+ // type: 'JSSlot',
+ value: [{
+ componentName: 'Text',
+ props: {},
+ }]
+ }
},
condition: true,
},
diff --git a/packages/designer/tests/fixtures/schema/setting.ts b/packages/designer/tests/fixtures/schema/setting.ts
new file mode 100644
index 000000000..a0d45d0d9
--- /dev/null
+++ b/packages/designer/tests/fixtures/schema/setting.ts
@@ -0,0 +1,90 @@
+export default {
+ componentName: 'Page',
+ id: 'node_k1ow3cb9',
+ title: 'hey, i\' a page!',
+ props: {
+ extensions: {
+ 启用页头: true,
+ },
+ pageStyle: {
+ backgroundColor: '#f2f3f5',
+ },
+ containerStyle: {},
+ className: 'page_kgaqfbm4',
+ templateVersion: '1.0.0',
+ },
+ lifeCycles: {
+ constructor: {
+ type: 'js',
+ compiled:
+ "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
+ source:
+ "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
+ },
+ },
+ condition: true,
+ css:
+ 'body{background-color:#f2f3f5}.card_kgaqfbm5 {\n margin-bottom: 12px;\n}.card_kgaqfbm6 {\n margin-bottom: 12px;\n}.button_kgaqfbm7 {\n margin-right: 16px;\n width: 80px\n}.button_kgaqfbm8 {\n width: 80px;\n}.div_kgaqfbm9 {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
+ methods: {
+ __initMethods__: {
+ type: 'js',
+ source: 'function (exports, module) { /*set actions code here*/ }',
+ compiled: 'function (exports, module) { /*set actions code here*/ }',
+ },
+ },
+ children: [
+ {
+ componentName: 'Div',
+ id: 'div',
+ props: {
+ className: 'div_kgaqfbm9',
+ behavior: 'NORMAL',
+ __style__:
+ ':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
+ events: {},
+ fieldId: 'div_k1ow3h1o',
+ useFieldIdAsDomId: false,
+ customClassName: {
+ type: 'JSExpression',
+ value: 'getFromSomewhere()'
+ },
+ customClassName2: {
+ type: 'JSExpression',
+ mock: { hi: 'mock' },
+ value: 'getFromSomewhere()'
+ },
+ },
+ extraPropA: 'haha',
+ },
+ {
+ componentName: 'Div',
+ id: 'div2',
+ props: {
+ className: 'div_kgaqfbm9',
+ behavior: 'NORMAL',
+ __style__:
+ ':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
+ events: {},
+ fieldId: 'div_k1ow3h1o',
+ useFieldIdAsDomId: false,
+ customClassName: '',
+ },
+ extraPropA: 'haha',
+ },
+ {
+ componentName: 'Test',
+ id: 'test',
+ props: {
+ className: 'div_kgaqfbm9',
+ behavior: 'NORMAL',
+ __style__:
+ ':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
+ events: {},
+ fieldId: 'div_k1ow3h1o',
+ useFieldIdAsDomId: false,
+ customClassName: '',
+ },
+ extraPropA: 'haha',
+ }
+ ],
+};
diff --git a/packages/designer/tests/meta/component-meta.test.ts b/packages/designer/tests/meta/component-meta.test.ts
new file mode 100644
index 000000000..f3cdfd2a6
--- /dev/null
+++ b/packages/designer/tests/meta/component-meta.test.ts
@@ -0,0 +1,71 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import divMeta from '../fixtures/component-metadata/div';
+import { ComponentMeta, isComponentMeta, removeBuiltinComponentAction, addBuiltinComponentAction } from '../../src/component-meta';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getGlobalComponentActions: () => [],
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+describe('组件元数据处理', () => {
+ it('构造函数', () => {
+ const meta = new ComponentMeta(designer, divMeta);
+ expect(meta.isContainer).toBeTruthy;
+ expect(isComponentMeta(meta)).toBeTruthy;
+ expect(meta.acceptable).toBeTruthy;
+ expect(meta.isRootComponent()).toBeTruthy;
+ expect(meta.isModal).toBeFalsy;
+ expect(meta.rootSelector).toBeUndefined;
+ expect(meta.liveTextEditing).toBeUndefined;
+ expect(meta.descriptor).toBeUndefined;
+ expect(meta.icon).toBeUndefined;
+ expect(meta.getMetadata().title).toBe('容器');
+ expect(meta.title).toEqual({ type: 'i18n', 'en-US': 'Div', 'zh-CN': '容器' });
+
+ meta.setNpm({ package: '@ali/vc-div', componentName: 'Div' });
+ expect(meta.npm).toEqual({ package: '@ali/vc-div', componentName: 'Div' });
+
+ meta.setMetadata(divMeta);
+ });
+
+ it('availableActions', () => {
+ const meta = new ComponentMeta(designer, divMeta);
+ expect(meta.availableActions).toHaveLength(3);
+ expect(meta.availableActions[0].name).toBe('remove');
+ expect(meta.availableActions[1].name).toBe('hide');
+ expect(meta.availableActions[2].name).toBe('copy');
+
+ removeBuiltinComponentAction('remove');
+ // availableActions 有 computed 缓存
+ expect(meta.availableActions[0].name).toBe('remove');
+ expect(meta.availableActions[1].name).toBe('hide');
+ expect(meta.availableActions[2].name).toBe('copy');
+
+ addBuiltinComponentAction({
+ name: 'new',
+ content: {
+ action() {}
+ }
+ });
+ // availableActions 有 computed 缓存
+ expect(meta.availableActions).toHaveLength(3);
+ expect(meta.availableActions[0].name).toBe('remove');
+ expect(meta.availableActions[1].name).toBe('hide');
+ expect(meta.availableActions[2].name).toBe('copy');
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/node/node.add.test.ts b/packages/designer/tests/node/node.add.test.ts
new file mode 100644
index 000000000..9da7a3473
--- /dev/null
+++ b/packages/designer/tests/node/node.add.test.ts
@@ -0,0 +1,564 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+import { EBADF } from 'constants';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getComponentMeta() {
+ return {
+ getMetadata() {
+ return { experimental: null };
+ },
+ };
+ },
+ transformProps(props) { return props; },
+ createSettingEntry: mockCreateSettingEntry,
+ postEvent() {},
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+describe('schema 生成节点模型测试', () => {
+ describe('block ❌ | component ❌ | slot ❌', () => {
+ let project: Project;
+ beforeEach(() => {
+ project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ });
+ afterEach(() => {
+ project.unload();
+ });
+ it('基本的节点模型初始化,模型导出', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ expect(nodesMap.size).toBe(expectedNodeCnt);
+ ids.forEach(id => {
+ expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
+ });
+
+ const pageNode = currentDocument?.getNode('node_k1ow3cb9');
+ expect(pageNode?.getComponentName()).toBe('Page');
+ expect(pageNode?.getIcon()).toBeUndefined;
+
+ const exportSchema = currentDocument?.export(1);
+ expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
+ expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
+ });
+
+ it('基本的节点模型初始化,节点深度', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const getNode = currentDocument.getNode.bind(currentDocument);
+
+ const pageNode = getNode('node_k1ow3cb9');
+ const rootHeaderNode = getNode('node_k1ow3cba');
+ const rootContentNode = getNode('node_k1ow3cbb');
+ const rootFooterNode = getNode('node_k1ow3cbc');
+ const formNode = getNode('form');
+ const cardNode = getNode('node_k1ow3cbj');
+ const cardContentNode = getNode('node_k1ow3cbk');
+ const columnsLayoutNode = getNode('node_k1ow3cbw');
+ const columnNode = getNode('node_k1ow3cbx');
+ const textFieldNode = getNode('node_k1ow3cbz');
+
+ expect(pageNode?.zLevel).toBe(0);
+ expect(rootHeaderNode?.zLevel).toBe(1);
+ expect(rootContentNode?.zLevel).toBe(1);
+ expect(rootFooterNode?.zLevel).toBe(1);
+ expect(formNode?.zLevel).toBe(2);
+ expect(cardNode?.zLevel).toBe(3);
+ expect(cardContentNode?.zLevel).toBe(4);
+ expect(columnsLayoutNode?.zLevel).toBe(5);
+ expect(columnNode?.zLevel).toBe(6);
+ expect(textFieldNode?.zLevel).toBe(7);
+
+ expect(textFieldNode?.getZLevelTop(7)).toEqual(textFieldNode);
+ expect(textFieldNode?.getZLevelTop(6)).toEqual(columnNode);
+ expect(textFieldNode?.getZLevelTop(5)).toEqual(columnsLayoutNode);
+ expect(textFieldNode?.getZLevelTop(4)).toEqual(cardContentNode);
+ expect(textFieldNode?.getZLevelTop(3)).toEqual(cardNode);
+ expect(textFieldNode?.getZLevelTop(2)).toEqual(formNode);
+ expect(textFieldNode?.getZLevelTop(1)).toEqual(rootContentNode);
+ expect(textFieldNode?.getZLevelTop(0)).toEqual(pageNode);
+
+ // 异常情况
+ expect(textFieldNode?.getZLevelTop(8)).toBeNull;
+ expect(textFieldNode?.getZLevelTop(-1)).toBeNull;
+ });
+
+ it('基本的节点模型初始化,节点父子、兄弟相关方法', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const getNode = currentDocument.getNode.bind(currentDocument);
+
+ const pageNode = getNode('node_k1ow3cb9');
+ const rootHeaderNode = getNode('node_k1ow3cba');
+ const rootContentNode = getNode('node_k1ow3cbb');
+ const rootFooterNode = getNode('node_k1ow3cbc');
+ const formNode = getNode('form');
+ const cardNode = getNode('node_k1ow3cbj');
+ const cardContentNode = getNode('node_k1ow3cbk');
+ const columnsLayoutNode = getNode('node_k1ow3cbw');
+ const columnNode = getNode('node_k1ow3cbx');
+ const textFieldNode = getNode('node_k1ow3cbz');
+
+ expect(pageNode?.index).toBe(-1);
+ expect(pageNode?.children.toString()).toBe('[object Array]');
+ expect(pageNode?.children?.get(1)).toBe(rootContentNode);
+ expect(pageNode?.getChildren()?.get(1)).toBe(rootContentNode);
+ expect(pageNode?.getNode()).toBe(pageNode);
+
+ expect(rootFooterNode?.index).toBe(2);
+
+ expect(textFieldNode?.getParent()).toBe(columnNode);
+ expect(columnNode?.getParent()).toBe(columnsLayoutNode);
+ expect(columnsLayoutNode?.getParent()).toBe(cardContentNode);
+ expect(cardContentNode?.getParent()).toBe(cardNode);
+ expect(cardNode?.getParent()).toBe(formNode);
+ expect(formNode?.getParent()).toBe(rootContentNode);
+ expect(rootContentNode?.getParent()).toBe(pageNode);
+ expect(rootContentNode?.prevSibling).toBe(rootHeaderNode);
+ expect(rootContentNode?.nextSibling).toBe(rootFooterNode);
+
+ expect(pageNode?.isRoot()).toBe(true);
+ expect(pageNode?.contains(textFieldNode)).toBe(true);
+ expect(textFieldNode?.getRoot()).toBe(pageNode);
+ expect(columnNode?.getRoot()).toBe(pageNode);
+ expect(columnsLayoutNode?.getRoot()).toBe(pageNode);
+ expect(cardContentNode?.getRoot()).toBe(pageNode);
+ expect(cardNode?.getRoot()).toBe(pageNode);
+ expect(formNode?.getRoot()).toBe(pageNode);
+ expect(rootContentNode?.getRoot()).toBe(pageNode);
+ });
+
+ it('基本的节点模型初始化,节点新建、删除等事件', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const getNode = currentDocument.getNode.bind(currentDocument);
+ const createNode = currentDocument.createNode.bind(currentDocument);
+
+ const pageNode = getNode('node_k1ow3cb9');
+ const nodeCreateHandler = jest.fn();
+ currentDocument?.onNodeCreate(nodeCreateHandler);
+
+ const node = createNode({
+ componentName: 'TextInput',
+ props: {
+ propA: 'haha',
+ }
+ });
+ currentDocument?.insertNode(pageNode, node);
+
+ expect(nodeCreateHandler).toHaveBeenCalledTimes(1);
+ expect(nodeCreateHandler.mock.calls[0][0]).toBe(node);
+ expect(nodeCreateHandler.mock.calls[0][0].componentName).toBe('TextInput');
+ expect(nodeCreateHandler.mock.calls[0][0].getPropValue('propA')).toBe('haha');
+
+ const nodeDestroyHandler = jest.fn();
+ currentDocument?.onNodeDestroy(nodeDestroyHandler);
+ node.remove();
+ expect(nodeDestroyHandler).toHaveBeenCalledTimes(1);
+ expect(nodeDestroyHandler.mock.calls[0][0]).toBe(node);
+ expect(nodeDestroyHandler.mock.calls[0][0].componentName).toBe('TextInput');
+ expect(nodeDestroyHandler.mock.calls[0][0].getPropValue('propA')).toBe('haha');
+ });
+
+ it.skip('基本的节点模型初始化,节点插入等方法', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const getNode = currentDocument.getNode.bind(currentDocument);
+
+ const formNode = getNode('form');
+ const node1 = currentDocument.createNode({
+ componentName: 'TextInput',
+ props: {
+ propA: 'haha',
+ }
+ });
+ const node2 = currentDocument.createNode({
+ componentName: 'TextInput',
+ props: {
+ propA: 'heihei',
+ }
+ });
+ const node3 = currentDocument.createNode({
+ componentName: 'TextInput',
+ props: {
+ propA: 'heihei2',
+ }
+ });
+ const node4 = currentDocument.createNode({
+ componentName: 'TextInput',
+ props: {
+ propA: 'heihei3',
+ }
+ });
+
+ formNode?.insertBefore(node2);
+ // formNode?.insertBefore(node1, node2);
+ // formNode?.insertAfter(node3);
+ // formNode?.insertAfter(node4, node3);
+
+ expect(formNode?.children?.get(0)).toBe(node1);
+ expect(formNode?.children?.get(1)).toBe(node2);
+ // expect(formNode?.children?.get(5)).toBe(node3);
+ // expect(formNode?.children?.get(6)).toBe(node4);
+ });
+
+ it('基本的节点模型初始化,节点其他方法', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const getNode = currentDocument.getNode.bind(currentDocument);
+
+ const pageNode = getNode('node_k1ow3cb9');
+ expect(pageNode?.isPage()).toBe(true);
+ expect(pageNode?.isComponent()).toBe(false);
+ expect(pageNode?.isSlot()).toBe(false);
+ expect(pageNode?.title).toBe('hey, i\' a page!');
+ });
+
+ describe('节点新增(insertNode)', () => {
+ let project: Project;
+ beforeEach(() => {
+ project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ });
+ it('场景一:插入 NodeSchema,不指定 index', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form') as Node;
+ const formNode2 = currentDocument?.getNode('form');
+ expect(formNode).toEqual(formNode2);
+ currentDocument?.insertNode(formNode, {
+ componentName: 'TextInput',
+ id: 'nodeschema-id1',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ });
+ expect(nodesMap.size).toBe(ids.length + 1);
+ expect(formNode.children?.length).toBe(4);
+ const insertedNode = formNode.children.get(formNode.children.length - 1);
+ expect(insertedNode.componentName).toBe('TextInput');
+ expect(insertedNode.propsData).toEqual({
+ propA: 'haha',
+ propB: 3
+ });
+ // TODO: 把 checkId 的 commit pick 过来
+ // expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
+ });
+
+ it('场景一:插入 NodeSchema,指定 index: 0', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const nodesMap = currentDocument.nodesMap;
+ const formNode = nodesMap.get('form');
+ currentDocument?.insertNode(formNode, {
+ componentName: 'TextInput',
+ id: 'nodeschema-id1',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ }, 0);
+ expect(nodesMap.size).toBe(ids.length + 1);
+ expect(formNode.children.length).toBe(4);
+ const insertedNode = formNode.children.get(0);
+ expect(insertedNode.componentName).toBe('TextInput');
+ expect(insertedNode.propsData).toEqual({
+ propA: 'haha',
+ propB: 3
+ });
+ // TODO: 把 checkId 的 commit pick 过来
+ // expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
+ });
+
+ it('场景一:插入 NodeSchema,指定 index: 1', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form');
+ currentDocument?.insertNode(formNode, {
+ componentName: 'TextInput',
+ id: 'nodeschema-id1',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ }, 1);
+ expect(nodesMap.size).toBe(ids.length + 1);
+ expect(formNode.children.length).toBe(4);
+ const insertedNode = formNode.children.get(1);
+ expect(insertedNode.componentName).toBe('TextInput');
+ expect(insertedNode.propsData).toEqual({
+ propA: 'haha',
+ propB: 3
+ });
+ // TODO: 把 checkId 的 commit pick 过来
+ // expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
+ });
+
+ it('场景一:插入 NodeSchema,有 children', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form') as Node;
+ currentDocument?.insertNode(formNode, {
+ componentName: 'ParentNode',
+ props: {
+ propA: 'haha',
+ propB: 3
+ },
+ children: [
+ {
+ componentName: 'SubNode',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ },
+ {
+ componentName: 'SubNode2',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ }
+ ]
+ });
+ expect(nodesMap.size).toBe(ids.length + 3);
+ expect(formNode.children.length).toBe(4);
+ expect(formNode.children?.get(3)?.componentName).toBe('ParentNode');
+ expect(formNode.children?.get(3)?.children?.get(0)?.componentName).toBe('SubNode');
+ expect(formNode.children?.get(3)?.children?.get(1)?.componentName).toBe('SubNode2');
+ });
+
+ it.skip('场景一:插入 NodeSchema,id 与现有 schema 里的 id 重复', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form');
+ currentDocument?.insertNode(formNode, {
+ componentName: 'TextInput',
+ id: 'nodeschema-id1',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ });
+ expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
+ expect(nodesMap.size).toBe(ids.length + 1);
+ });
+
+ it.skip('场景一:插入 NodeSchema,id 与现有 schema 里的 id 重复,但关闭了 id 检测器', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form');
+ currentDocument?.insertNode(formNode, {
+ componentName: 'TextInput',
+ id: 'nodeschema-id1',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ });
+ expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
+ expect(nodesMap.size).toBe(ids.length + 1);
+ });
+
+ it('场景二:插入 Node 实例', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form');
+ const inputNode = currentDocument?.createNode({
+ componentName: 'TextInput',
+ id: 'nodeschema-id2',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ });
+ currentDocument?.insertNode(formNode, inputNode);
+ expect(formNode.children?.get(3)?.componentName).toBe('TextInput');
+ expect(nodesMap.size).toBe(ids.length + 1);
+ });
+
+ it('场景三:插入 JSExpression', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form') as Node;
+ currentDocument?.insertNode(formNode, {
+ type: 'JSExpression',
+ value: 'just a expression'
+ });
+ expect(nodesMap.size).toBe(ids.length + 1);
+ expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
+ // expect(formNode.children?.get(3)?.children).toEqual({
+ // type: 'JSExpression',
+ // value: 'just a expression'
+ // });
+ });
+ it('场景四:插入 string', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form') as Node;
+ currentDocument?.insertNode(formNode, 'just a string');
+ expect(nodesMap.size).toBe(ids.length + 1);
+ expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
+ // expect(formNode.children?.get(3)?.children).toBe('just a string');
+ });
+ });
+
+ describe('节点新增(insertNodes)', () => {
+ let project: Project;
+ beforeEach(() => {
+ project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ });
+ it('场景一:插入 NodeSchema,指定 index', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form') as Node;
+ const formNode2 = currentDocument?.getNode('form');
+ expect(formNode).toEqual(formNode2);
+ currentDocument?.insertNodes(formNode, [
+ {
+ componentName: 'TextInput',
+ props: {
+ propA: 'haha2',
+ propB: 3
+ }
+ },
+ {
+ componentName: 'TextInput2',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ }
+ ], 1);
+ expect(nodesMap.size).toBe(ids.length + 2);
+ expect(formNode.children?.length).toBe(5);
+ const insertedNode1 = formNode.children.get(1);
+ const insertedNode2 = formNode.children.get(2);
+ expect(insertedNode1.componentName).toBe('TextInput');
+ expect(insertedNode1.propsData).toEqual({
+ propA: 'haha2',
+ propB: 3
+ });
+ expect(insertedNode2.componentName).toBe('TextInput2');
+ expect(insertedNode2.propsData).toEqual({
+ propA: 'haha',
+ propB: 3
+ });
+ });
+
+ it('场景二:插入 Node 实例,指定 index', () => {
+ expect(project).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const formNode = nodesMap.get('form') as Node;
+ const formNode2 = currentDocument?.getNode('form');
+ expect(formNode).toEqual(formNode2);
+ const createdNode1 = currentDocument?.createNode({
+ componentName: 'TextInput',
+ props: {
+ propA: 'haha2',
+ propB: 3
+ }
+ });
+ const createdNode2 = currentDocument?.createNode({
+ componentName: 'TextInput2',
+ props: {
+ propA: 'haha',
+ propB: 3
+ }
+ });
+ currentDocument?.insertNodes(formNode, [ createdNode1, createdNode2 ], 1);
+ expect(nodesMap.size).toBe(ids.length + 2);
+ expect(formNode.children?.length).toBe(5);
+ const insertedNode1 = formNode.children.get(1);
+ const insertedNode2 = formNode.children.get(2);
+ expect(insertedNode1.componentName).toBe('TextInput');
+ expect(insertedNode1.propsData).toEqual({
+ propA: 'haha2',
+ propB: 3
+ });
+ expect(insertedNode2.componentName).toBe('TextInput2');
+ expect(insertedNode2.propsData).toEqual({
+ propA: 'haha',
+ propB: 3
+ });
+ });
+ });
+ })
+
+ describe('block ❌ | component ❌ | slot ✅', () => {
+ it('基本的 slot 创建', () => {
+ const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchemaWithSlot,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ // 目前每个 slot 会新增(1 + children.length)个节点
+ const expectedNodeCnt = ids.length + 2;
+ expect(nodesMap.size).toBe(expectedNodeCnt);
+ // PageHeader
+ expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/node/node.dragdrop.test.ts b/packages/designer/tests/node/node.dragdrop.test.ts
new file mode 100644
index 000000000..be15bdfa7
--- /dev/null
+++ b/packages/designer/tests/node/node.dragdrop.test.ts
@@ -0,0 +1,61 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getComponentMeta() {
+ return {
+ getMetadata() {
+ return { experimental: null };
+ },
+ };
+ },
+ transformProps(props) { return props; },
+ createSettingEntry: mockCreateSettingEntry,
+ postEvent() {},
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+describe.skip('节点拖拽测试', () => {
+ describe('block ❌ | component ❌ | slot ❌', () => {
+ it('修改普通属性,string | number', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ expect(nodesMap.size).toBe(expectedNodeCnt);
+ ids.forEach(id => {
+ expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
+ });
+
+ const exportSchema = currentDocument?.export(1);
+ expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
+ expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
+ });
+
+
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/node/node.modify.test.ts b/packages/designer/tests/node/node.modify.test.ts
new file mode 100644
index 000000000..e064d273f
--- /dev/null
+++ b/packages/designer/tests/node/node.modify.test.ts
@@ -0,0 +1,456 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getComponentMeta() {
+ return {
+ getMetadata() {
+ return { experimental: null };
+ },
+ };
+ },
+ transformProps(props) { return props; },
+ createSettingEntry: mockCreateSettingEntry,
+ postEvent() {},
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+describe('schema 生成节点模型测试', () => {
+ describe('block ❌ | component ❌ | slot ❌', () => {
+ let project: Project;
+ beforeEach(() => {
+ project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ });
+ it('读取普通属性,string | number | object', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+ /*
+ props: {
+ size: 'medium',
+ labelAlign: 'top',
+ autoValidate: true,
+ scrollToFirstError: true,
+ autoUnmount: true,
+ behavior: 'NORMAL',
+ dataSource: {
+ type: 'variable',
+ variable: 'state.formData',
+ },
+ obj: {
+ a: 1,
+ b: false,
+ c: 'string',
+ },
+ __style__: {},
+ fieldId: 'form',
+ fieldOptions: {},
+ },
+ id: 'form',
+ condition: true,
+ */
+ const sizeProp = formNode?.getProp('size');
+ const sizeProp2 = formNode?.getProps().getProp('size');
+ expect(sizeProp).toBe(sizeProp2);
+ expect(sizeProp?.getAsString()).toBe('medium');
+ expect(sizeProp?.getValue()).toBe('medium');
+
+ const autoValidateProp = formNode?.getProp('autoValidate');
+ expect(autoValidateProp?.getValue()).toBe(true);
+
+ const objProp = formNode?.getProp('obj');
+ expect(objProp?.getValue()).toEqual({
+ a: 1,
+ b: false,
+ c: 'string',
+ });
+ const objAProp = formNode?.getProp('obj.a');
+ const objBProp = formNode?.getProp('obj.b');
+ const objCProp = formNode?.getProp('obj.c');
+ expect(objAProp?.getValue()).toBe(1);
+ expect(objBProp?.getValue()).toBe(false);
+ expect(objCProp?.getValue()).toBe('string');
+
+ const idProp = formNode?.getExtraProp('extraPropA');
+ expect(idProp?.getValue()).toBe('extraPropA');
+ });
+
+ it('修改普通属性,string | number | object,使用 Node 实例接口', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+ /*
+ props: {
+ size: 'medium',
+ labelAlign: 'top',
+ autoValidate: true,
+ scrollToFirstError: true,
+ autoUnmount: true,
+ behavior: 'NORMAL',
+ dataSource: {
+ type: 'variable',
+ variable: 'state.formData',
+ },
+ obj: {
+ a: 1,
+ b: false,
+ c: 'string',
+ },
+ __style__: {},
+ fieldId: 'form',
+ fieldOptions: {},
+ },
+ id: 'form',
+ condition: true,
+ */
+ formNode?.setPropValue('size', 'large');
+ const sizeProp = formNode?.getProp('size');
+ expect(sizeProp?.getAsString()).toBe('large');
+ expect(sizeProp?.getValue()).toBe('large');
+
+ formNode?.setPropValue('autoValidate', false);
+ const autoValidateProp = formNode?.getProp('autoValidate');
+ expect(autoValidateProp?.getValue()).toBe(false);
+
+ formNode?.setPropValue('obj', {
+ a: 2,
+ b: true,
+ c: 'another string'
+ });
+ const objProp = formNode?.getProp('obj');
+ expect(objProp?.getValue()).toEqual({
+ a: 2,
+ b: true,
+ c: 'another string',
+ });
+ formNode?.setPropValue('obj.a', 3);
+ formNode?.setPropValue('obj.b', false);
+ formNode?.setPropValue('obj.c', 'string');
+ const objAProp = formNode?.getProp('obj.a');
+ const objBProp = formNode?.getProp('obj.b');
+ const objCProp = formNode?.getProp('obj.c');
+ expect(objAProp?.getValue()).toBe(3);
+ expect(objBProp?.getValue()).toBe(false);
+ expect(objCProp?.getValue()).toBe('string');
+ expect(objProp?.getValue()).toEqual({
+ a: 3,
+ b: false,
+ c: 'string',
+ });
+ });
+
+ it('修改普通属性,string | number | object,使用 Props 实例接口', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+ /*
+ props: {
+ size: 'medium',
+ labelAlign: 'top',
+ autoValidate: true,
+ scrollToFirstError: true,
+ autoUnmount: true,
+ behavior: 'NORMAL',
+ dataSource: {
+ type: 'variable',
+ variable: 'state.formData',
+ },
+ obj: {
+ a: 1,
+ b: false,
+ c: 'string',
+ },
+ __style__: {},
+ fieldId: 'form',
+ fieldOptions: {},
+ },
+ id: 'form',
+ condition: true,
+ */
+ const props = formNode?.getProps();
+ props?.setPropValue('size', 'large');
+ const sizeProp = formNode?.getProp('size');
+ expect(sizeProp?.getAsString()).toBe('large');
+ expect(sizeProp?.getValue()).toBe('large');
+
+ props?.setPropValue('autoValidate', false);
+ const autoValidateProp = formNode?.getProp('autoValidate');
+ expect(autoValidateProp?.getValue()).toBe(false);
+
+ props?.setPropValue('obj', {
+ a: 2,
+ b: true,
+ c: 'another string'
+ });
+ const objProp = formNode?.getProp('obj');
+ expect(objProp?.getValue()).toEqual({
+ a: 2,
+ b: true,
+ c: 'another string',
+ });
+ props?.setPropValue('obj.a', 3);
+ props?.setPropValue('obj.b', false);
+ props?.setPropValue('obj.c', 'string');
+ const objAProp = formNode?.getProp('obj.a');
+ const objBProp = formNode?.getProp('obj.b');
+ const objCProp = formNode?.getProp('obj.c');
+ expect(objAProp?.getValue()).toBe(3);
+ expect(objBProp?.getValue()).toBe(false);
+ expect(objCProp?.getValue()).toBe('string');
+ expect(objProp?.getValue()).toEqual({
+ a: 3,
+ b: false,
+ c: 'string',
+ });
+ });
+
+ it('修改普通属性,string | number | object,使用 Prop 实例接口', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+ /*
+ props: {
+ size: 'medium',
+ labelAlign: 'top',
+ autoValidate: true,
+ scrollToFirstError: true,
+ autoUnmount: true,
+ behavior: 'NORMAL',
+ dataSource: {
+ type: 'variable',
+ variable: 'state.formData',
+ },
+ obj: {
+ a: 1,
+ b: false,
+ c: 'string',
+ },
+ __style__: {},
+ fieldId: 'form',
+ fieldOptions: {},
+ },
+ id: 'form',
+ condition: true,
+ */
+ const sizeProp = formNode?.getProp('size');
+ sizeProp?.setValue('large');
+ expect(sizeProp?.getAsString()).toBe('large');
+ expect(sizeProp?.getValue()).toBe('large');
+
+ const autoValidateProp = formNode?.getProp('autoValidate');
+ autoValidateProp?.setValue(false);
+ expect(autoValidateProp?.getValue()).toBe(false);
+
+
+ const objProp = formNode?.getProp('obj');
+ objProp?.setValue({
+ a: 2,
+ b: true,
+ c: 'another string'
+ });
+ expect(objProp?.getValue()).toEqual({
+ a: 2,
+ b: true,
+ c: 'another string',
+ });
+ const objAProp = formNode?.getProp('obj.a');
+ const objBProp = formNode?.getProp('obj.b');
+ const objCProp = formNode?.getProp('obj.c');
+ objAProp?.setValue(3);
+ objBProp?.setValue(false);
+ objCProp?.setValue('string');
+ expect(objAProp?.getValue()).toBe(3);
+ expect(objBProp?.getValue()).toBe(false);
+ expect(objCProp?.getValue()).toBe('string');
+ expect(objProp?.getValue()).toEqual({
+ a: 3,
+ b: false,
+ c: 'string',
+ });
+ });
+ });
+
+ describe('block ❌ | component ❌ | slot ✅', () => {
+ let project: Project;
+ beforeEach(() => {
+ project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ });
+ it('修改 slot 属性,初始存在 slot 属性名,正常生成节点模型', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+
+ formNode?.setPropValue('slotA', {
+ type: 'JSSlot',
+ value: [{
+ componentName: 'TextInput1',
+ props: {
+ txt: 'haha',
+ num: 1,
+ bool: true
+ }
+ }, {
+ componentName: 'TextInput2',
+ props: {
+ txt: 'heihei',
+ num: 2,
+ bool: false
+ }
+ }]
+ });
+
+ expect(nodesMap.size).toBe(ids.length + 3);
+ expect(formNode?.slots).toHaveLength(1);
+ expect(formNode?.slots[0].children).toHaveLength(2);
+ const firstChildNode = formNode?.slots[0].children?.get(0);
+ const secondChildNode = formNode?.slots[0].children?.get(1);
+ expect(firstChildNode?.componentName).toBe('TextInput1');
+ expect(firstChildNode?.getPropValue('txt')).toBe('haha');
+ expect(firstChildNode?.getPropValue('num')).toBe(1);
+ expect(firstChildNode?.getPropValue('bool')).toBe(true);
+ expect(secondChildNode?.componentName).toBe('TextInput2');
+ expect(secondChildNode?.getPropValue('txt')).toBe('heihei');
+ expect(secondChildNode?.getPropValue('num')).toBe(2);
+ expect(secondChildNode?.getPropValue('bool')).toBe(false);
+ });
+
+ it('修改 slot 属性,初始存在 slot 属性名,关闭 slot', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+
+ formNode?.setPropValue('slotA', {
+ type: 'JSSlot',
+ value: [{
+ componentName: 'TextInput1',
+ props: {
+ txt: 'haha',
+ num: 1,
+ bool: true
+ }
+ }, {
+ componentName: 'TextInput2',
+ props: {
+ txt: 'heihei',
+ num: 2,
+ bool: false
+ }
+ }]
+ });
+
+ expect(nodesMap.size).toBe(ids.length + 3);
+ expect(formNode?.slots).toHaveLength(1);
+
+ formNode?.setPropValue('slotA', '');
+
+ expect(nodesMap.size).toBe(ids.length);
+ expect(formNode?.slots).toHaveLength(0);
+ });
+
+ it('修改 slot 属性,初始存在 slot 属性名,同名覆盖 slot', () => {
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const formNode = currentDocument?.getNode('form');
+
+ formNode?.setPropValue('slotA', {
+ type: 'JSSlot',
+ name: 'slotA',
+ value: [{
+ componentName: 'TextInput1',
+ props: {
+ txt: 'haha',
+ num: 1,
+ bool: true
+ }
+ }, {
+ componentName: 'TextInput2',
+ props: {
+ txt: 'heihei',
+ num: 2,
+ bool: false
+ }
+ }]
+ });
+
+ expect(nodesMap.size).toBe(ids.length + 3);
+ expect(formNode?.slots).toHaveLength(1);
+ expect(formNode?.slots[0].children).toHaveLength(2);
+
+ let firstChildNode = formNode?.slots[0].children?.get(0);
+ expect(firstChildNode?.componentName).toBe('TextInput1');
+ expect(firstChildNode?.getPropValue('txt')).toBe('haha');
+ expect(firstChildNode?.getPropValue('num')).toBe(1);
+ expect(firstChildNode?.getPropValue('bool')).toBe(true);
+
+ formNode?.setPropValue('slotA', {
+ type: 'JSSlot',
+ name: 'slotA',
+ value: [{
+ componentName: 'TextInput3',
+ props: {
+ txt: 'xixi',
+ num: 3,
+ bool: false
+ }
+ }]
+ });
+
+ expect(nodesMap.size).toBe(ids.length + 2);
+ expect(formNode?.slots).toHaveLength(1);
+ expect(formNode?.slots[0].children).toHaveLength(1);
+ firstChildNode = formNode?.slots[0].children?.get(0);
+ expect(firstChildNode?.componentName).toBe('TextInput3');
+ expect(firstChildNode?.getPropValue('txt')).toBe('xixi');
+ expect(firstChildNode?.getPropValue('num')).toBe(3);
+ expect(firstChildNode?.getPropValue('bool')).toBe(false);
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/node/node.remove.test.ts b/packages/designer/tests/node/node.remove.test.ts
new file mode 100644
index 000000000..f68d57ca1
--- /dev/null
+++ b/packages/designer/tests/node/node.remove.test.ts
@@ -0,0 +1,122 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
+import '../fixtures/window';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const mockCreateSettingEntry = jest.fn();
+jest.mock('../../src/designer/designer', () => {
+ return {
+ Designer: jest.fn().mockImplementation(() => {
+ return {
+ getComponentMeta() {
+ return {
+ getMetadata() {
+ return { experimental: null };
+ },
+ };
+ },
+ transformProps(props) { return props; },
+ createSettingEntry: mockCreateSettingEntry,
+ postEvent() {},
+ };
+ }),
+ };
+});
+
+let designer = null;
+beforeAll(() => {
+ designer = new Designer({});
+});
+
+describe('节点模型删除测试', () => {
+ it('删除叶子节点', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const originalNodeCnt = ids.length;
+ expect(nodesMap.size).toBe(originalNodeCnt);
+
+ currentDocument?.removeNode('node_k1ow3cbn');
+ // Button#1
+ expect(nodesMap.size).toBe(originalNodeCnt - 1);
+
+ currentDocument?.removeNode(nodesMap.get('node_k1ow3cbp'));
+ // Button#2
+ expect(nodesMap.size).toBe(originalNodeCnt - 2);
+
+ currentDocument?.removeNode('unexisting_node');
+ expect(nodesMap.size).toBe(originalNodeCnt - 2);
+ });
+
+ it('删除叶子节点,带有 slot', () => {
+ const formSchemaWithSlot = set(cloneDeep(formSchema),
+ 'children[1].children[0].children[2].children[1].props.greeting.type', 'JSSlot');
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchemaWithSlot,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const originalNodeCnt = ids.length + 2;
+ expect(nodesMap.size).toBe(originalNodeCnt);
+
+ currentDocument?.removeNode('node_k1ow3cbp');
+ // Button + Slot + Text
+ expect(nodesMap.size).toBe(originalNodeCnt - 3);
+ });
+
+ it('删除分支节点', () => {
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchema,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const originalNodeCnt = ids.length;
+ expect(nodesMap.size).toBe(originalNodeCnt);
+
+ currentDocument?.removeNode('node_k1ow3cbo');
+ // Div + 2 * Button
+ expect(nodesMap.size).toBe(originalNodeCnt - 3);
+ });
+
+ it('删除分支节点,带有 slot', () => {
+ const formSchemaWithSlot = set(cloneDeep(formSchema),
+ 'children[1].children[0].children[2].children[1].props.greeting.type', 'JSSlot');
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchemaWithSlot,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const originalNodeCnt = ids.length + 2;
+ expect(nodesMap.size).toBe(originalNodeCnt);
+
+ currentDocument?.removeNode('node_k1ow3cbo');
+ // Div + 2 * Button + Slot + Text
+ expect(nodesMap.size).toBe(originalNodeCnt - 5);
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/project/project.test.ts b/packages/designer/tests/project/project.test.ts
index 54ccedf18..31ece4526 100644
--- a/packages/designer/tests/project/project.test.ts
+++ b/packages/designer/tests/project/project.test.ts
@@ -1,8 +1,8 @@
-import set from 'lodash.set';
-import cloneDeep from 'lodash.clonedeep';
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
import '../fixtures/window';
import { Project } from '../../src/project/project';
-// import { Node } from '../../../src/document/node/node';
+import { Node } from '../../src/document/node/node';
import { Designer } from '../../src/designer/designer';
import formSchema from '../fixtures/schema/form';
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
@@ -34,7 +34,11 @@ beforeAll(() => {
describe('schema 生成节点模型测试', () => {
describe('block ❌ | component ❌ | slot ❌', () => {
- it('基本的节点模型初始化,模型导出', () => {
+ beforeEach(() => {
+ mockCreateSettingEntry.mockClear();
+ });
+
+ it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
const project = new Project(designer, {
componentsTree: [
formSchema,
@@ -56,129 +60,75 @@ describe('schema 生成节点模型测试', () => {
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
});
- describe('节点新增(insertNode)', () => {
- let project;
- beforeEach(() => {
- project = new Project(designer, {
- componentsTree: [
- formSchema,
- ],
- });
- project.open();
- });
- it.only('场景一:插入 NodeSchema', () => {
- expect(project).toBeTruthy();
- const ids = getIdsFromSchema(formSchema);
- const { currentDocument } = project;
- const { nodesMap } = currentDocument;
- const formNode = nodesMap.get('node_k1ow3cbq');
- currentDocument?.insertNode(formNode, {
- componentName: 'TextInput',
- id: 'nodeschema-id1',
- props: {
- propA: 'haha',
- propB: 3
- }
- });
- expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
- expect(nodesMap.size).toBe(ids.length + 1);
+ it('基本的节点模型初始化,模型导出,project.open 传入 schema', () => {
+ const project = new Project(designer);
+ project.open(formSchema);
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ expect(nodesMap.size).toBe(expectedNodeCnt);
+ ids.forEach(id => {
+ expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
});
- it.only('场景一:插入 NodeSchema,有 children', () => {
- expect(project).toBeTruthy();
- const ids = getIdsFromSchema(formSchema);
- const { currentDocument } = project;
- const { nodesMap } = currentDocument;
- const formNode = nodesMap.get('node_k1ow3cbq');
- currentDocument?.insertNode(formNode, {
- componentName: 'TextInput',
- id: 'nodeschema-id1',
- props: {
- propA: 'haha',
- propB: 3
- }
- });
- expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
- expect(nodesMap.size).toBe(ids.length + 1);
- });
-
- it.only('场景一:插入 NodeSchema,id 与现有 schema 重复', () => {
- expect(project).toBeTruthy();
- const ids = getIdsFromSchema(formSchema);
- const { currentDocument } = project;
- const { nodesMap } = currentDocument;
- const formNode = nodesMap.get('node_k1ow3cbq');
- currentDocument?.insertNode(formNode, {
- componentName: 'TextInput',
- id: 'nodeschema-id1',
- props: {
- propA: 'haha',
- propB: 3
- }
- });
- expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
- expect(nodesMap.size).toBe(ids.length + 1);
- });
-
- it.only('场景一:插入 NodeSchema,id 与现有 schema 重复,但关闭了 id 检测器', () => {
- expect(project).toBeTruthy();
- const ids = getIdsFromSchema(formSchema);
- const { currentDocument } = project;
- const { nodesMap } = currentDocument;
- const formNode = nodesMap.get('node_k1ow3cbq');
- currentDocument?.insertNode(formNode, {
- componentName: 'TextInput',
- id: 'nodeschema-id1',
- props: {
- propA: 'haha',
- propB: 3
- }
- });
- expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
- expect(nodesMap.size).toBe(ids.length + 1);
- });
-
- it('场景二:插入 Node 实例', () => {
- expect(project).toBeTruthy();
- const ids = getIdsFromSchema(formSchema);
- const { currentDocument } = project;
- const { nodesMap } = currentDocument;
- const formNode = nodesMap.get('node_k1ow3cbq');
- const inputNode = currentDocument?.createNode({
- componentName: 'TextInput',
- id: 'nodeschema-id2',
- props: {
- propA: 'haha',
- propB: 3
- }
- });
- expect(inputNode.id).toBe('nodeschema-id2');
- currentDocument?.insertNode(formNode, inputNode);
- expect(nodesMap.get('nodeschema-id2').componentName).toBe('TextInput');
- expect(nodesMap.size).toBe(ids.length + 1);
- });
-
- it('场景二:插入 JSExpression', () => {});
+ const exportSchema = currentDocument?.export(1);
+ expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
+ expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
});
- })
+ it('project 卸载所有 document - unload()', () => {
+ const project = new Project(designer);
+ project.open(formSchema);
+ expect(project).toBeTruthy();
+ const { currentDocument, documents } = project;
- it('block ❌ | component ❌ | slot ✅', () => {
- const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
- const project = new Project(designer, {
- componentsTree: [
- formSchemaWithSlot,
- ],
+ expect(documents).toHaveLength(1);
+ expect(currentDocument).toBe(documents[0]);
+
+ project.unload();
+
+ expect(documents).toHaveLength(0);
});
- project.open();
- expect(project).toBeTruthy();
- const { currentDocument } = project;
- const { nodesMap } = currentDocument;
- const ids = getIdsFromSchema(formSchema);
- // 目前每个 slot 会新增 1 + children.length 个节点
- const expectedNodeCnt = ids.length + 2;
- expect(nodesMap.size).toBe(expectedNodeCnt);
- // PageHeader
- expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
+
+ it('project 卸载指定 document - removeDocument()', () => {
+ const project = new Project(designer);
+ project.open(formSchema);
+ expect(project).toBeTruthy();
+ const { currentDocument, documents } = project;
+
+ expect(documents).toHaveLength(1);
+ expect(currentDocument).toBe(documents[0]);
+
+ project.removeDocument(currentDocument);
+
+ expect(documents).toHaveLength(0);
+ });
+ });
+
+ describe('block ❌ | component ❌ | slot ✅', () => {
+ it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
+ const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
+ const project = new Project(designer, {
+ componentsTree: [
+ formSchemaWithSlot,
+ ],
+ });
+ project.open();
+ expect(project).toBeTruthy();
+ const { currentDocument } = project;
+ const { nodesMap } = currentDocument!;
+ const ids = getIdsFromSchema(formSchema);
+ // 目前每个 slot 会新增(1 + children.length)个节点
+ const expectedNodeCnt = ids.length + 2;
+ expect(nodesMap.size).toBe(expectedNodeCnt);
+ // PageHeader
+ expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
+ });
+ });
+
+ describe.skip('多 document 测试', () => {
+
});
});
\ No newline at end of file
diff --git a/packages/designer/tests/setting-entry/setting-prop-entry.test.ts b/packages/designer/tests/setting-entry/setting-prop-entry.test.ts
new file mode 100644
index 000000000..1169dc70d
--- /dev/null
+++ b/packages/designer/tests/setting-entry/setting-prop-entry.test.ts
@@ -0,0 +1,105 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import { Editor } from '@ali/lowcode-editor-core';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import settingSchema from '../fixtures/schema/setting';
+import divMeta from '../fixtures/prototype/div-meta';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const editor = new Editor();
+
+describe('setting-prop-entry 测试', () => {
+ let designer: Designer;
+ beforeEach(() => {
+ designer = new Designer({ editor });
+ });
+ afterEach(() => {
+ designer._componentMetasMap.clear();
+ designer = null;
+ });
+
+ describe('node 构造函数生成 settingEntry', () => {
+ it.only('常规方法测试', () => {
+ designer.createComponentMeta(divMeta);
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+
+ const { settingEntry } = divNode!;
+ const behaviorProp = settingEntry.getProp('behavior');
+ expect(behaviorProp.getProps()).toBe(settingEntry);
+ expect(behaviorProp.props).toBe(settingEntry);
+ expect(behaviorProp.getName()).toBe('behavior');
+ expect(behaviorProp.getKey()).toBe('behavior');
+ expect(behaviorProp.isIgnore()).toBeFalsy;
+ behaviorProp.setKey('behavior2');
+ expect(behaviorProp.getKey()).toBe('behavior2');
+ behaviorProp.setKey('behavior');
+ expect(behaviorProp.getValue()).toBe('NORMAL');
+ expect(behaviorProp.getMockOrValue()).toBe('NORMAL');
+
+ behaviorProp.setValue('LARGE');
+ expect(behaviorProp.getValue()).toBe('LARGE');
+ // behaviorProp.setPropValue('behavior', 'SMALL');
+ // expect(behaviorProp.getValue()).toBe('SMALL');
+ behaviorProp.setValue('NORMAL');
+ expect(behaviorProp.getValue()).toBe('NORMAL');
+
+ behaviorProp.clearValue();
+ behaviorProp.clearPropValue();
+ expect(settingEntry.getProp('behavior').getValue()).toBeUndefined;
+
+ behaviorProp.setValue('LARGE');
+ expect(behaviorProp.getValue()).toBe('LARGE');
+ behaviorProp.remove();
+ expect(settingEntry.getProp('behavior').getValue()).toBeUndefined;
+
+ expect(behaviorProp.getNode()).toBe(divNode);
+ expect(behaviorProp.getId().startsWith('entry')).toBeTruthy;
+ expect(behaviorProp.designer).toBe(designer);
+ expect(behaviorProp.isSingle).toBeTruthy;
+ expect(behaviorProp.isMultiple).toBeFalsy;
+ expect(behaviorProp.isGroup).toBeFalsy;
+ expect(behaviorProp.isSameComponent).toBeTruthy;
+ expect(typeof settingEntry.getValue).toBe('function');
+ settingEntry.getValue();
+
+ behaviorProp.setExtraPropValue('extraPropA', 'heihei');
+ expect(behaviorProp.getExtraPropValue('extraPropA', 'heihei'));
+ });
+
+ it.skip('type: group 场景测试', () => {
+
+ });
+
+ it('JSExpression 类型的 prop', () => {
+ designer.createComponentMeta(divMeta);
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+
+ const { settingEntry } = divNode!;
+ const customClassNameProp = settingEntry.getProp('customClassName');
+ expect(customClassNameProp.isUseVariable()).toBeTruthy;
+ expect(customClassNameProp.useVariable).toBeTruthy;
+
+ expect(customClassNameProp.getValue()).toEqual({
+ type: 'JSExpression',
+ value: 'getFromSomewhere()'
+ });
+ expect(customClassNameProp.getMockOrValue()).toBeUndefined;
+ expect(customClassNameProp.getVariableValue()).toBe('getFromSomewhere()');
+ customClassNameProp.setVariableValue('xxx');
+ expect(customClassNameProp.getVariableValue()).toBe('xxx');
+
+ const customClassName2Prop = settingEntry.getProp('customClassName2');
+ expect(customClassName2Prop.getMockOrValue()).toEqual({
+ hi: 'mock',
+ });
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/designer/tests/setting-entry/setting-top-entry.test.ts b/packages/designer/tests/setting-entry/setting-top-entry.test.ts
new file mode 100644
index 000000000..435993926
--- /dev/null
+++ b/packages/designer/tests/setting-entry/setting-top-entry.test.ts
@@ -0,0 +1,174 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import { Editor } from '@ali/lowcode-editor-core';
+import { Project } from '../../src/project/project';
+import { Node } from '../../src/document/node/node';
+import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import settingSchema from '../fixtures/schema/setting';
+import divMeta from '../fixtures/prototype/div-meta';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+const editor = new Editor();
+
+describe('setting-top-entry 测试', () => {
+ let designer: Designer;
+ beforeEach(() => {
+ designer = new Designer({ editor });
+ });
+ afterEach(() => {
+ designer._componentMetasMap.clear();
+ designer = null;
+ });
+
+ describe('node 构造函数生成 settingEntry', () => {
+ it('常规方法测试', () => {
+ designer.createComponentMeta(divMeta);
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+
+ const { settingEntry } = divNode!;
+ expect(settingEntry.getPropValue('behavior')).toBe('NORMAL');
+ expect(settingEntry.getProp('behavior').getValue()).toBe('NORMAL');
+ settingEntry.setPropValue('behavior', 'LARGE');
+ expect(settingEntry.getPropValue('behavior')).toBe('LARGE');
+ expect(settingEntry.get('behavior').getValue()).toBe('LARGE');
+ settingEntry.getProp('behavior').setValue('SMALL');
+ expect(settingEntry.getPropValue('behavior')).toBe('SMALL');
+ settingEntry.clearPropValue('behavior');
+ expect(settingEntry.getPropValue('behavior')).toBeUndefined;
+
+ expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o');
+ settingEntry.setPropValue('fieldId', 'div_k1ow3h1o_new');
+ expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o_new');
+
+ expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha');
+ settingEntry.setExtraPropValue('extraPropA', 'haha2');
+ expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha2');
+
+ settingEntry.mergeProps({
+ newPropA: 'haha',
+ });
+ expect(settingEntry.getPropValue('newPropA')).toBe('haha');
+ settingEntry.setProps({
+ newPropB: 'haha',
+ });
+ expect(settingEntry.getPropValue('newPropB')).toBe('haha');
+ settingEntry.setValue({
+ newPropC: 'haha',
+ });
+ expect(settingEntry.getPropValue('newPropC')).toBe('haha');
+
+ expect(settingEntry.getPage()).toBe(currentDocument);
+ expect(settingEntry.getNode()).toBe(divNode);
+ expect(settingEntry.node).toBe(divNode);
+ expect(settingEntry.getId()).toBe('div');
+ expect(settingEntry.first).toBe(divNode);
+ expect(settingEntry.designer).toBe(designer);
+ expect(settingEntry.isSingle).toBeTruthy;
+ expect(settingEntry.isMultiple).toBeFalsy;
+ expect(settingEntry.isSameComponent).toBeTruthy;
+
+ expect(typeof settingEntry.getValue).toBe('function');
+ settingEntry.getValue();
+ });
+
+ it('清理方法测试', () => {
+ designer.createComponentMeta(divMeta);
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+
+ const { settingEntry } = divNode!;
+ expect(settingEntry.items).toHaveLength(3);
+ settingEntry.purge();
+ expect(settingEntry.items).toHaveLength(0);
+ });
+
+ it('vision 兼容测试', () => {
+ designer.createComponentMeta(divMeta);
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+
+ console.log(divNode?.getPropValue('behavior'));
+ const { settingEntry } = divNode!;
+
+ expect(typeof settingEntry.getChildren).toBe('function');
+ expect(typeof settingEntry.getDOMNode).toBe('function');
+ expect(typeof settingEntry.getStatus).toBe('function');
+ expect(typeof settingEntry.setStatus).toBe('function');
+ settingEntry.getStatus();
+ settingEntry.setStatus();
+ settingEntry.getChildren();
+ settingEntry.getDOMNode();
+ });
+
+ it('没有 node', () => {
+ const create1 = designer.createSettingEntry.bind(designer);
+ const create2 = designer.createSettingEntry.bind(designer, []);
+ expect(create1).toThrowError('nodes should not be empty');
+ expect(create2).toThrowError('nodes should not be empty');
+ });
+ });
+
+ describe('designer.createSettingEntry 生成 settingEntry(多 node 场景)', () => {
+ it('相同类型的 node', () => {
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+ const divNode2 = currentDocument?.getNode('div2');
+ const settingEntry = designer.createSettingEntry([divNode, divNode2]);
+
+ expect(settingEntry.isMultiple).toBeTruthy;
+ expect(settingEntry.isSameComponent).toBeTruthy;
+ expect(settingEntry.isSingle).toBeFalsy;
+
+ expect(settingEntry.getPropValue('behavior')).toBe('NORMAL');
+ expect(settingEntry.getProp('behavior').getValue()).toBe('NORMAL');
+ settingEntry.setPropValue('behavior', 'LARGE');
+ expect(settingEntry.getPropValue('behavior')).toBe('LARGE');
+ expect(settingEntry.get('behavior').getValue()).toBe('LARGE');
+ // 多个 node 都被成功设值
+ expect(divNode?.getPropValue('behavior')).toBe('LARGE');
+ expect(divNode2?.getPropValue('behavior')).toBe('LARGE');
+
+ settingEntry.getProp('behavior').setValue('SMALL');
+ expect(settingEntry.getPropValue('behavior')).toBe('SMALL');
+ // 多个 node 都被成功设值
+ expect(divNode?.getPropValue('behavior')).toBe('SMALL');
+ expect(divNode2?.getPropValue('behavior')).toBe('SMALL');
+
+ settingEntry.clearPropValue('behavior');
+ expect(settingEntry.getPropValue('behavior')).toBeUndefined;
+ // 多个 node 都被成功设值
+ expect(divNode?.getPropValue('behavior')).toBeUndefined;
+ expect(divNode2?.getPropValue('behavior')).toBeUndefined;
+
+ expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o');
+ settingEntry.setPropValue('fieldId', 'div_k1ow3h1o_new');
+ expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o_new');
+
+ expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha');
+ settingEntry.setExtraPropValue('extraPropA', 'haha2');
+ expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha2');
+ });
+
+ it('不同类型的 node', () => {
+ designer.project.open(settingSchema);
+ const { currentDocument } = designer.project;
+ const divNode = currentDocument?.getNode('div');
+ const testNode = currentDocument?.getNode('test');
+ const settingEntry = designer.createSettingEntry([divNode, testNode]);
+
+ expect(settingEntry.isMultiple).toBeTruthy;
+ expect(settingEntry.isSameComponent).toBeFalsy;
+ expect(settingEntry.isSingle).toBeFalsy;
+
+ // 不同类型的 node 场景下,理论上从页面上已没有修改属性的方法调用,所以此处不再断言各设值方法
+ // 思考:假如以后面向其他场景,比如用户用 API 强行调用,是否需要做健壮性保护?
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/editor-core/CHANGELOG.md b/packages/editor-core/CHANGELOG.md
index 2cb4a3616..e597100d8 100644
--- a/packages/editor-core/CHANGELOG.md
+++ b/packages/editor-core/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-editor-core
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/editor-core/package.json b/packages/editor-core/package.json
index 67c63b3ed..dd21910b9 100644
--- a/packages/editor-core/package.json
+++ b/packages/editor-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-core",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Core Api for Ali lowCode engine",
"license": "MIT",
"main": "lib/index.js",
@@ -15,8 +15,8 @@
"cloud-build": "build-scripts build --skip-demo"
},
"dependencies": {
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"@recore/obx": "^1.0.9",
"@recore/obx-react": "^1.0.8",
diff --git a/packages/editor-preset-general/CHANGELOG.md b/packages/editor-preset-general/CHANGELOG.md
index 5908c87fe..5c268dc06 100644
--- a/packages/editor-preset-general/CHANGELOG.md
+++ b/packages/editor-preset-general/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-editor-preset-general
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/editor-preset-general/package.json b/packages/editor-preset-general/package.json
index 1028c9a31..564ebdca1 100644
--- a/packages/editor-preset-general/package.json
+++ b/packages/editor-preset-general/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-preset-general",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Ali General Editor Preset",
"main": "lib/index.js",
"files": [
@@ -14,12 +14,12 @@
},
"license": "MIT",
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-editor-skeleton": "^0.13.1-10",
- "@ali/lowcode-plugin-designer": "^0.13.1-10",
- "@ali/lowcode-plugin-outline-pane": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-editor-skeleton": "^0.13.1-11",
+ "@ali/lowcode-plugin-designer": "^0.13.1-11",
+ "@ali/lowcode-plugin-outline-pane": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@alifd/next": "^1.19.12",
"@alife/theme-lowcode-dark": "^0.1.0",
"@alife/theme-lowcode-light": "^0.1.0",
@@ -27,7 +27,7 @@
"react-dom": "^16.8.1"
},
"devDependencies": {
- "@ali/lowcode-editor-setters": "^0.13.1-10",
+ "@ali/lowcode-editor-setters": "^0.13.1-11",
"@alib/build-scripts": "^0.1.18",
"@types/events": "^3.0.0",
"@types/react": "^16.8.3",
diff --git a/packages/editor-preset-vision/.eslintrc.js b/packages/editor-preset-vision/.eslintrc.js
index 4888cbdf0..4c845e2de 100644
--- a/packages/editor-preset-vision/.eslintrc.js
+++ b/packages/editor-preset-vision/.eslintrc.js
@@ -2,7 +2,7 @@ module.exports = {
extends: 'eslint-config-ali/typescript/react',
rules: {
'react/no-multi-comp': 1,
- 'no-unused-expressions': 1,
+ 'no-unused-expressions': 0,
'implicit-arrow-linebreak': 1,
'no-nested-ternary': 1,
'no-mixed-operators': 1,
@@ -16,5 +16,6 @@ module.exports = {
'react/no-deprecated': 1,
'no-useless-escape': 1,
'brace-style': 1,
+ '@typescript-eslint/member-ordering': 0,
}
}
\ No newline at end of file
diff --git a/packages/editor-preset-vision/CHANGELOG.md b/packages/editor-preset-vision/CHANGELOG.md
index 631e70cbb..25459023d 100644
--- a/packages/editor-preset-vision/CHANGELOG.md
+++ b/packages/editor-preset-vision/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+### Bug Fixes
+
+* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
+
+
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/editor-preset-vision/build.test.json b/packages/editor-preset-vision/build.test.json
new file mode 100644
index 000000000..4bde6acd1
--- /dev/null
+++ b/packages/editor-preset-vision/build.test.json
@@ -0,0 +1,19 @@
+{
+ "plugins": [
+ [
+ "build-plugin-component",
+ {
+ "filename": "editor-preset-vision",
+ "library": "LowcodeEditor",
+ "libraryTarget": "umd",
+ "externals": {
+ "react": "var window.React",
+ "react-dom": "var window.ReactDOM",
+ "prop-types": "var window.PropTypes",
+ "rax": "var window.Rax"
+ }
+ }
+ ],
+ "@ali/lowcode-test-mate/plugin/index.ts"
+ ]
+}
diff --git a/packages/editor-preset-vision/jest.config.js b/packages/editor-preset-vision/jest.config.js
new file mode 100644
index 000000000..5b9f59ab5
--- /dev/null
+++ b/packages/editor-preset-vision/jest.config.js
@@ -0,0 +1,26 @@
+const esModules = [
+ '@recore/obx-react',
+ // '@ali/lowcode-editor-core',
+].join('|');
+
+module.exports = {
+ // transform: {
+ // '^.+\\.[jt]sx?$': 'babel-jest',
+ // // '^.+\\.(ts|tsx)$': 'ts-jest',
+ // // '^.+\\.(js|jsx)$': 'babel-jest',
+ // },
+ // testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
+ transformIgnorePatterns: [
+ `/node_modules/(?!${esModules})/`,
+ ],
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
+ collectCoverage: false,
+ collectCoverageFrom: [
+ 'src/**/*.{ts,tsx}',
+ '!src/**/*.d.ts',
+ '!src/base/**',
+ '!src/prop.ts',
+ '!**/node_modules/**',
+ '!**/vendor/**',
+ ],
+};
diff --git a/packages/editor-preset-vision/package.json b/packages/editor-preset-vision/package.json
index 0d483efd3..4c92e2f1b 100644
--- a/packages/editor-preset-vision/package.json
+++ b/packages/editor-preset-vision/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-preset-vision",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Vision Polyfill for Ali lowCode engine",
"main": "lib/index.js",
"private": true,
@@ -11,17 +11,18 @@
],
"scripts": {
"build": "build-scripts build --skip-demo",
- "cloud-build": "build-scripts build --skip-demo"
+ "cloud-build": "build-scripts build --skip-demo",
+ "test": "build-scripts test --config build.test.json"
},
"license": "MIT",
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-editor-skeleton": "^0.13.1-10",
- "@ali/lowcode-plugin-designer": "^0.13.1-10",
- "@ali/lowcode-plugin-outline-pane": "^0.13.1-10",
- "@ali/lowcode-editor-setters": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-editor-setters": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-editor-skeleton": "^0.13.1-11",
+ "@ali/lowcode-plugin-designer": "^0.13.1-11",
+ "@ali/lowcode-plugin-outline-pane": "^0.13.1-11",
"@ali/ve-i18n-util": "^2.0.0",
"@ali/ve-icons": "^4.1.9",
"@ali/ve-less-variables": "2.0.3",
@@ -39,6 +40,7 @@
"react-dom": "^16.8.1"
},
"devDependencies": {
+ "@ali/lowcode-test-mate": "^1.0.0",
"@alib/build-scripts": "^0.1.18",
"@types/domready": "^1.0.0",
"@types/events": "^3.0.0",
@@ -47,6 +49,7 @@
"build-plugin-fusion": "^0.1.0",
"build-plugin-moment-locales": "^0.1.0",
"build-plugin-react-app": "^1.1.2",
+ "prop-types": "^15.7.2",
"tsconfig-paths-webpack-plugin": "^3.2.0"
},
"publishConfig": {
diff --git a/packages/editor-preset-vision/src/bus.ts b/packages/editor-preset-vision/src/bus.ts
index 5e595da29..329d4a27b 100644
--- a/packages/editor-preset-vision/src/bus.ts
+++ b/packages/editor-preset-vision/src/bus.ts
@@ -65,15 +65,15 @@ export class Bus {
const bus = new Bus();
-editor.on('hotkey.callback.call', (data) => {
+editor?.on('hotkey.callback.call', (data) => {
bus.emit('ve.hotkey.callback.call', data);
});
-editor.on('history.back', (data) => {
+editor?.on('history.back', (data) => {
bus.emit('ve.history.back', data);
});
-editor.on('history.forward', (data) => {
+editor?.on('history.forward', (data) => {
bus.emit('ve.history.forward', data);
});
diff --git a/packages/editor-preset-vision/src/editor.ts b/packages/editor-preset-vision/src/editor.ts
index 6a1933c54..3ff2575b3 100644
--- a/packages/editor-preset-vision/src/editor.ts
+++ b/packages/editor-preset-vision/src/editor.ts
@@ -3,8 +3,6 @@ import { isPlainObject, hasOwnProperty, cloneDeep, isI18NObject, isUseI18NSetter
import { globalContext, Editor } from '@ali/lowcode-editor-core';
import { Designer, LiveEditing, TransformStage, Node, getConvertedExtraKey } from '@ali/lowcode-designer';
import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane';
-import { toCss } from '@ali/vu-css-style';
-import logger from '@ali/vu-logger';
import bus from './bus';
import { VE_EVENTS } from './base/const';
@@ -13,7 +11,16 @@ import { Skeleton, SettingsPrimaryPane, registerDefaults } from '@ali/lowcode-ed
import { deepValueParser } from './deep-value-parser';
import { liveEditingRule, liveEditingSaveHander } from './vc-live-editing';
-import { isVariable } from './utils';
+import {
+ compatibleReducer,
+ compatiblePageReducer,
+ stylePropsReducer,
+ upgradePropsReducer,
+ filterReducer,
+ removeEmptyPropsReducer,
+ initNodeReducer,
+ liveLifecycleReducer,
+} from './props-reducers';
export const editor = new Editor();
globalContext.register(editor, Editor);
@@ -31,313 +38,31 @@ designer.project.onCurrentDocumentChange((doc) => {
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
});
-interface Variable {
- type: 'variable';
- variable: string;
- value: any;
-}
-
-function upgradePropsReducer(props: any) {
- if (!props || !isPlainObject(props)) {
- return props;
- }
- if (isJSBlock(props)) {
- if (props.value.componentName === 'Slot') {
- return {
- type: 'JSSlot',
- title: (props.value.props as any)?.slotTitle,
- name: (props.value.props as any)?.slotName,
- value: props.value.children,
- };
- } else {
- return props.value;
- }
- }
- if (isVariable(props)) {
- return {
- type: 'JSExpression',
- value: props.variable,
- mock: props.value,
- };
- }
- const newProps: any = {};
- Object.keys(props).forEach((key) => {
- if (/^__slot__/.test(key) && props[key] === true) {
- return;
- }
- newProps[key] = upgradePropsReducer(props[key]);
- });
- return newProps;
-}
-
// 升级 Props
designer.addPropsReducer(upgradePropsReducer, TransformStage.Upgrade);
-function getCurrentFieldIds() {
- const fieldIds: any = [];
- const nodesMap = designer?.currentDocument?.nodesMap || new Map();
- nodesMap.forEach((curNode: any) => {
- const fieldId = nodesMap?.get(curNode.id)?.getPropValue('fieldId');
- if (fieldId) {
- fieldIds.push(fieldId);
- }
- });
- return fieldIds;
-}
-
// 节点 props 初始化
-designer.addPropsReducer((props, node) => {
- // debugger;
- // run initials
- const newProps: any = {
- ...props,
- };
- if (newProps.fieldId) {
- const fieldIds = getCurrentFieldIds();
+designer.addPropsReducer(initNodeReducer, TransformStage.Init);
- // 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
- if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
- newProps.fieldId = undefined;
- }
- }
- const initials = node.componentMeta.getMetadata().experimental?.initials;
- if (initials) {
- const getRealValue = (propValue: any) => {
- if (isVariable(propValue)) {
- return propValue.value;
- }
- if (isJSExpression(propValue)) {
- return propValue.mock;
- }
- return propValue;
- };
- initials.forEach((item) => {
- // FIXME! this implements SettingTarget
- try {
- // FIXME! item.name could be 'xxx.xxx'
- const ov = newProps[item.name];
- const v = item.initial(node as any, getRealValue(ov));
- if (ov === undefined && v !== undefined) {
- newProps[item.name] = v;
- }
- // 兼容 props 中的属性为 i18n 类型,但是仅提供了一个字符串值,非变量绑定
- if (isUseI18NSetter(node.componentMeta.prototype, item.name) &&
- !isI18NObject(ov) &&
- !isJSExpression(ov) &&
- !isJSBlock(ov) &&
- !isJSSlot(ov) &&
- !isVariable(ov) &&
- isString(v)) {
- newProps[item.name] = convertToI18NObject(v);
- }
- } catch (e) {
- if (hasOwnProperty(props, item.name)) {
- newProps[item.name] = props[item.name];
- }
- }
- if (newProps[item.name] && !node.props.has(item.name)) {
- node.props.add(newProps[item.name], item.name, false, { skipSetSlot: true });
- }
- });
- }
- return newProps;
-}, TransformStage.Init);
+designer.addPropsReducer(liveLifecycleReducer, TransformStage.Render);
-designer.addPropsReducer((props: any, node: Node) => {
- // live 模式下解析 lifeCycles
- if (node.isRoot() && props && props.lifeCycles) {
- if (editor.get('designMode') === 'live') {
- const lifeCycleMap = {
- didMount: 'componentDidMount',
- willUnmount: 'componentWillUnMount',
- };
- const lifeCycles = props.lifeCycles;
- Object.keys(lifeCycleMap).forEach(key => {
- if (lifeCycles[key]) {
- lifeCycles[lifeCycleMap[key]] = lifeCycles[key];
- }
- });
- return props;
- }
- return {
- ...props,
- lifeCycles: {},
- };
- }
- return props;
-}, TransformStage.Render);
-
-function filterReducer(props: any, node: Node): any {
- const filters = node.componentMeta.getMetadata().experimental?.filters;
- if (filters && filters.length) {
- const newProps = { ...props };
- filters.forEach((item) => {
- // FIXME! item.name could be 'xxx.xxx'
- if (!hasOwnProperty(newProps, item.name)) {
- return;
- }
- try {
- if (item.filter(node.settingEntry.getProp(item.name), props[item.name]) === false) {
- delete newProps[item.name];
- }
- } catch (e) {
- console.warn(e);
- logger.trace(e);
- }
- });
- return newProps;
- }
- return props;
-}
designer.addPropsReducer(filterReducer, TransformStage.Save);
designer.addPropsReducer(filterReducer, TransformStage.Render);
-function compatiableReducer(props: any) {
- if (!props || !isPlainObject(props)) {
- return props;
- }
- // 为了能降级到老版本,建议在后期版本去掉以下代码
- if (isJSSlot(props)) {
- return {
- type: 'JSBlock',
- value: {
- componentName: 'Slot',
- children: props.value,
- props: {
- slotTitle: props.title,
- slotName: props.name,
- },
- },
- };
- }
- if (isJSExpression(props) && !props.events) {
- return {
- type: 'variable',
- value: props.mock,
- variable: props.value,
- };
- }
- const newProps: any = {};
- Object.entries(props).forEach(([key, val]) => {
- newProps[key] = compatiableReducer(val);
- });
- return newProps;
-}
// FIXME: Dirty fix, will remove this reducer
-designer.addPropsReducer(compatiableReducer, TransformStage.Save);
+designer.addPropsReducer(compatibleReducer, TransformStage.Save);
// 兼容历史版本的 Page 组件
-designer.addPropsReducer((props: any, node: Node) => {
- const lifeCycleNames = ['didMount', 'willUnmount'];
- if (node.isRoot()) {
- lifeCycleNames.forEach((key) => {
- if (props[key]) {
- const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
- lifeCycles[key] = props[key];
- node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
- }
- });
- }
- return props;
-}, TransformStage.Save);
-
-// designer.addPropsReducer((props: any, node: Node) => {
-// const lifeCycleNames = ['didMount', 'willUnmount'];
-// const lifeCycleMap = {
-// didMount: 'componentDidMount',
-// willUnmount: 'componentWillUnMount',
-// };
-// if (node.componentName === 'Page') {
-// debugger;
-// lifeCycleNames.forEach(key => {
-// if (props[key]) {
-// const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
-// lifeCycles[lifeCycleMap[key]] = props[key];
-// node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
-// } else if (node.props.getPropValue(getConvertedExtraKey('lifeCycles'))) {
-// const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
-// lifeCycles[lifeCycleMap[key]] = lifeCycles[key];
-// node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
-// }
-// });
-// }
-// return props;
-// }, TransformStage.Init);
+designer.addPropsReducer(compatiblePageReducer, TransformStage.Save);
// 设计器组件样式处理
-function stylePropsReducer(props: any, node: any) {
- if (props && typeof props === 'object' && props.__style__) {
- const cssId = `_style_pesudo_${ node.id.replace(/\$/g, '_')}`;
- const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
- const styleProp = props.__style__;
- appendStyleNode(props, styleProp, cssClass, cssId);
- }
- if (props && typeof props === 'object' && props.pageStyle) {
- const cssId = '_style_pesudo_engine-document';
- const cssClass = 'engine-document';
- const styleProp = props.pageStyle;
- appendStyleNode(props, styleProp, cssClass, cssId);
- }
- if (props && typeof props === 'object' && props.containerStyle) {
- const cssId = `_style_pesudo_${ node.id}`;
- const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
- const styleProp = props.containerStyle;
- appendStyleNode(props, styleProp, cssClass, cssId);
- }
- return props;
-}
-
-function appendStyleNode(props: any, styleProp: any, cssClass: string, cssId: string) {
- const doc = designer.currentDocument?.simulator?.contentDocument;
- if (!doc) {
- return;
- }
- const dom = doc.getElementById(cssId);
- if (dom) {
- dom.parentNode?.removeChild(dom);
- }
- if (typeof styleProp === 'object') {
- styleProp = toCss(styleProp);
- }
- if (typeof styleProp === 'string') {
- const s = doc.createElement('style');
- props.className = cssClass;
- s.setAttribute('type', 'text/css');
- s.setAttribute('id', cssId);
- doc.getElementsByTagName('head')[0].appendChild(s);
-
- s.appendChild(doc.createTextNode(styleProp.replace(/(\d+)rpx/g, (a, b) => {
- return `${b / 2}px`;
- }).replace(/:root/g, `.${ cssClass}`)));
- }
-}
designer.addPropsReducer(stylePropsReducer, TransformStage.Render);
// 国际化 & Expression 渲染时处理
designer.addPropsReducer(deepValueParser, TransformStage.Render);
-// 清除空的 props value
-function removeEmptyProps(props: any, node: Node) {
- if (node.isRoot() && props.dataSource) {
- const online = cloneDeep(props.dataSource.online);
- online.forEach((item: any) => {
- const newParam: any = {};
- if (Array.isArray(item?.options?.params)) {
- item.options.params.forEach((element: any) => {
- if (element.name) {
- newParam[element.name] = element.value;
- }
- });
- item.options.params = newParam;
- }
- });
- props.dataSource.list = online;
- }
- return props;
-}
-
// Init 的时候没有拿到 dataSource, 只能在 Render 和 Save 的时候都调用一次,理论上执行时机在 Init
// Render 和 Save 都要各调用一次,感觉也是有问题的,是不是应该在 Render 执行一次就行了?见上 filterReducer 也是一样的处理方式。
-designer.addPropsReducer(removeEmptyProps, TransformStage.Render);
-designer.addPropsReducer(removeEmptyProps, TransformStage.Save);
+designer.addPropsReducer(removeEmptyPropsReducer, TransformStage.Render);
+designer.addPropsReducer(removeEmptyPropsReducer, TransformStage.Save);
skeleton.add({
area: 'mainArea',
diff --git a/packages/editor-preset-vision/src/index.ts b/packages/editor-preset-vision/src/index.ts
index bed83f713..2dcc762a0 100644
--- a/packages/editor-preset-vision/src/index.ts
+++ b/packages/editor-preset-vision/src/index.ts
@@ -5,6 +5,7 @@ import logger from '@ali/vu-logger';
import { render } from 'react-dom';
import I18nUtil from './i18n-util';
import { hotkey as Hotkey, monitor } from '@ali/lowcode-editor-core';
+import { registerMetadataTransducer } from '@ali/lowcode-designer';
import { createElement } from 'react';
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const';
import Bus from './bus';
@@ -110,6 +111,7 @@ const VisualEngine = {
Project,
logger,
Symbols,
+ registerMetadataTransducer,
// Flags,
};
@@ -160,12 +162,13 @@ export {
Project,
logger,
Symbols,
+ registerMetadataTransducer,
};
-const version = '6.0.0(LowcodeEngine 0.9.3)';
+const version = '6.0.0 (LowcodeEngine 0.9.32)';
console.log(
`%c VisionEngine %c v${version} `,
- 'padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060;font-weight:bold;',
- 'padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e;font-weight:bold;',
+ 'padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold;',
+ 'padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e; font-weight: bold;',
);
diff --git a/packages/editor-preset-vision/src/pages.ts b/packages/editor-preset-vision/src/pages.ts
index 81ae1d672..b6d3dc0ef 100644
--- a/packages/editor-preset-vision/src/pages.ts
+++ b/packages/editor-preset-vision/src/pages.ts
@@ -64,7 +64,6 @@ const pages = Object.assign(project, {
item.methods = {};
}
});
- console.log(pages, componentsTree);
project.load(
{
version: '1.0.0',
diff --git a/packages/editor-preset-vision/src/props-reducers/downgrade-schema-reducer.ts b/packages/editor-preset-vision/src/props-reducers/downgrade-schema-reducer.ts
new file mode 100644
index 000000000..709d4390c
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/downgrade-schema-reducer.ts
@@ -0,0 +1,51 @@
+import { getConvertedExtraKey } from '@ali/lowcode-designer';
+import {
+ isPlainObject,
+} from '@ali/lowcode-utils';
+import { isJSExpression, isJSSlot } from '@ali/lowcode-types';
+
+export function compatibleReducer(props: any) {
+ if (!props || !isPlainObject(props)) {
+ return props;
+ }
+ // 为了能降级到老版本,建议在后期版本去掉以下代码
+ if (isJSSlot(props)) {
+ return {
+ type: 'JSBlock',
+ value: {
+ componentName: 'Slot',
+ children: props.value,
+ props: {
+ slotTitle: props.title,
+ slotName: props.name,
+ },
+ },
+ };
+ }
+ if (isJSExpression(props) && !props.events) {
+ return {
+ type: 'variable',
+ value: props.mock,
+ variable: props.value,
+ };
+ }
+ const newProps: any = {};
+ Object.entries(props).forEach(([key, val]) => {
+ newProps[key] = compatibleReducer(val);
+ });
+ return newProps;
+}
+
+export function compatiblePageReducer(props: any, node: Node) {
+ const lifeCycleNames = ['didMount', 'willUnmount'];
+ if (node.isRoot()) {
+ lifeCycleNames.forEach(key => {
+ if (props[key]) {
+ const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
+ lifeCycles[key] = props[key];
+ node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
+ }
+ });
+ }
+ return props;
+}
diff --git a/packages/editor-preset-vision/src/props-reducers/filter-reducer.ts b/packages/editor-preset-vision/src/props-reducers/filter-reducer.ts
new file mode 100644
index 000000000..928e8dd82
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/filter-reducer.ts
@@ -0,0 +1,25 @@
+import logger from '@ali/vu-logger';
+import { hasOwnProperty } from '@ali/lowcode-utils';
+
+export function filterReducer(props: any, node: Node): any {
+ const filters = node.componentMeta.getMetadata().experimental?.filters;
+ if (filters && filters.length) {
+ const newProps = { ...props };
+ filters.forEach((item) => {
+ // FIXME! item.name could be 'xxx.xxx'
+ if (!hasOwnProperty(newProps, item.name)) {
+ return;
+ }
+ try {
+ if (item.filter(node.settingEntry.getProp(item.name), props[item.name]) === false) {
+ delete newProps[item.name];
+ }
+ } catch (e) {
+ console.warn(e);
+ logger.trace(e);
+ }
+ });
+ return newProps;
+ }
+ return props;
+}
\ No newline at end of file
diff --git a/packages/editor-preset-vision/src/props-reducers/index.ts b/packages/editor-preset-vision/src/props-reducers/index.ts
new file mode 100644
index 000000000..347e5edf9
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/index.ts
@@ -0,0 +1,7 @@
+export * from './downgrade-schema-reducer';
+export * from './filter-reducer';
+export * from './init-node-reducer';
+export * from './live-lifecycle-reducer';
+export * from './remove-empty-prop-reducer';
+export * from './style-reducer';
+export * from './upgrade-reducer';
diff --git a/packages/editor-preset-vision/src/props-reducers/init-node-reducer.ts b/packages/editor-preset-vision/src/props-reducers/init-node-reducer.ts
new file mode 100644
index 000000000..031482f46
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/init-node-reducer.ts
@@ -0,0 +1,68 @@
+import {
+ hasOwnProperty,
+ isI18NObject,
+ isUseI18NSetter,
+ convertToI18NObject,
+ isString,
+} from '@ali/lowcode-utils';
+import { isJSExpression, isJSBlock, isJSSlot } from '@ali/lowcode-types';
+import { isVariable, getCurrentFieldIds } from '../utils';
+
+export function initNodeReducer(props, node) {
+ // run initials
+ const newProps: any = {
+ ...props,
+ };
+ if (newProps.fieldId) {
+ const fieldIds = getCurrentFieldIds();
+
+ // 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
+ if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
+ newProps.fieldId = undefined;
+ }
+ }
+ const initials = node.componentMeta.getMetadata().experimental?.initials;
+
+ if (initials) {
+ const getRealValue = (propValue: any) => {
+ if (isVariable(propValue)) {
+ return propValue.value;
+ }
+ if (isJSExpression(propValue)) {
+ return propValue.mock;
+ }
+ return propValue;
+ };
+ initials.forEach(item => {
+ // FIXME! this implements SettingTarget
+ try {
+ // FIXME! item.name could be 'xxx.xxx'
+ const ov = newProps[item.name];
+ const v = item.initial(node as any, getRealValue(ov));
+ if (ov === undefined && v !== undefined) {
+ newProps[item.name] = v;
+ }
+ // 兼容 props 中的属性为 i18n 类型,但是仅提供了一个字符串值,非变量绑定
+ if (
+ isUseI18NSetter(node.componentMeta.prototype, item.name) &&
+ !isI18NObject(ov) &&
+ !isJSExpression(ov) &&
+ !isJSBlock(ov) &&
+ !isJSSlot(ov) &&
+ !isVariable(ov) &&
+ (isString(v) || isI18NObject(v))
+ ) {
+ newProps[item.name] = convertToI18NObject(v);
+ }
+ } catch (e) {
+ if (hasOwnProperty(props, item.name)) {
+ newProps[item.name] = props[item.name];
+ }
+ }
+ if (newProps[item.name] && !node.props.has(item.name)) {
+ node.props.add(newProps[item.name], item.name, false, { skipSetSlot: true });
+ }
+ });
+ }
+ return newProps;
+}
diff --git a/packages/editor-preset-vision/src/props-reducers/live-lifecycle-reducer.ts b/packages/editor-preset-vision/src/props-reducers/live-lifecycle-reducer.ts
new file mode 100644
index 000000000..a626c3b30
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/live-lifecycle-reducer.ts
@@ -0,0 +1,27 @@
+import { globalContext, Editor } from '@ali/lowcode-editor-core';
+import { Node } from '@ali/lowcode-designer';
+
+export function liveLifecycleReducer(props: any, node: Node) {
+ const editor = globalContext.get(Editor);
+ // live 模式下解析 lifeCycles
+ if (node.isRoot() && props && props.lifeCycles) {
+ if (editor.get('designMode') === 'live') {
+ const lifeCycleMap = {
+ didMount: 'componentDidMount',
+ willUnmount: 'componentWillUnMount',
+ };
+ const lifeCycles = props.lifeCycles;
+ Object.keys(lifeCycleMap).forEach(key => {
+ if (lifeCycles[key]) {
+ lifeCycles[lifeCycleMap[key]] = lifeCycles[key];
+ }
+ });
+ return props;
+ }
+ return {
+ ...props,
+ lifeCycles: {},
+ };
+ }
+ return props;
+}
\ No newline at end of file
diff --git a/packages/editor-preset-vision/src/props-reducers/remove-empty-prop-reducer.ts b/packages/editor-preset-vision/src/props-reducers/remove-empty-prop-reducer.ts
new file mode 100644
index 000000000..305f0bdb7
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/remove-empty-prop-reducer.ts
@@ -0,0 +1,23 @@
+import {
+ cloneDeep,
+} from '@ali/lowcode-utils';
+
+// 清除空的 props value
+export function removeEmptyPropsReducer(props: any, node: Node) {
+ if (node.isRoot() && props.dataSource && Array.isArray(props.dataSource.online)) {
+ const online = cloneDeep(props.dataSource.online);
+ online.forEach((item: any) => {
+ const newParam: any = {};
+ if (Array.isArray(item?.options?.params)) {
+ item.options.params.forEach((element: any) => {
+ if (element.name) {
+ newParam[element.name] = element.value;
+ }
+ });
+ item.options.params = newParam;
+ }
+ });
+ props.dataSource.list = online;
+ }
+ return props;
+}
diff --git a/packages/editor-preset-vision/src/props-reducers/style-reducer.ts b/packages/editor-preset-vision/src/props-reducers/style-reducer.ts
new file mode 100644
index 000000000..d5facb0a6
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/style-reducer.ts
@@ -0,0 +1,51 @@
+import { globalContext, Editor } from '@ali/lowcode-editor-core';
+import { toCss } from '@ali/vu-css-style';
+
+export function stylePropsReducer(props: any, node: any) {
+ if (props && typeof props === 'object' && props.__style__) {
+ const cssId = `_style_pesudo_${ node.id.replace(/\$/g, '_')}`;
+ const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
+ const styleProp = props.__style__;
+ appendStyleNode(props, styleProp, cssClass, cssId);
+ }
+ if (props && typeof props === 'object' && props.pageStyle) {
+ const cssId = '_style_pesudo_engine-document';
+ const cssClass = 'engine-document';
+ const styleProp = props.pageStyle;
+ appendStyleNode(props, styleProp, cssClass, cssId);
+ }
+ if (props && typeof props === 'object' && props.containerStyle) {
+ const cssId = `_style_pesudo_${ node.id}`;
+ const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
+ const styleProp = props.containerStyle;
+ appendStyleNode(props, styleProp, cssClass, cssId);
+ }
+ return props;
+}
+
+function appendStyleNode(props: any, styleProp: any, cssClass: string, cssId: string) {
+ const editor = globalContext.get(Editor);
+ const designer = editor.get('designer');
+ const doc = designer.currentDocument?.simulator?.contentDocument;
+ if (!doc) {
+ return;
+ }
+ const dom = doc.getElementById(cssId);
+ if (dom) {
+ dom.parentNode?.removeChild(dom);
+ }
+ if (typeof styleProp === 'object') {
+ styleProp = toCss(styleProp);
+ }
+ if (typeof styleProp === 'string') {
+ const s = doc.createElement('style');
+ props.className = cssClass;
+ s.setAttribute('type', 'text/css');
+ s.setAttribute('id', cssId);
+ doc.getElementsByTagName('head')[0].appendChild(s);
+
+ s.appendChild(doc.createTextNode(styleProp.replace(/(\d+)rpx/g, (a, b) => {
+ return `${b / 2}px`;
+ }).replace(/:root/g, `.${ cssClass}`)));
+ }
+}
\ No newline at end of file
diff --git a/packages/editor-preset-vision/src/props-reducers/upgrade-reducer.ts b/packages/editor-preset-vision/src/props-reducers/upgrade-reducer.ts
new file mode 100644
index 000000000..38bbca7ff
--- /dev/null
+++ b/packages/editor-preset-vision/src/props-reducers/upgrade-reducer.ts
@@ -0,0 +1,38 @@
+import {
+ isPlainObject,
+} from '@ali/lowcode-utils';
+import { isJSBlock } from '@ali/lowcode-types';
+import { isVariable } from '../utils';
+
+export function upgradePropsReducer(props: any) {
+ if (!props || !isPlainObject(props)) {
+ return props;
+ }
+ if (isJSBlock(props)) {
+ if (props.value.componentName === 'Slot') {
+ return {
+ type: 'JSSlot',
+ title: (props.value.props as any)?.slotTitle,
+ name: (props.value.props as any)?.slotName,
+ value: props.value.children,
+ };
+ } else {
+ return props.value;
+ }
+ }
+ if (isVariable(props)) {
+ return {
+ type: 'JSExpression',
+ value: props.variable,
+ mock: props.value,
+ };
+ }
+ const newProps: any = {};
+ Object.keys(props).forEach((key) => {
+ if (/^__slot__/.test(key) && props[key] === true) {
+ return;
+ }
+ newProps[key] = upgradePropsReducer(props[key]);
+ });
+ return newProps;
+}
\ No newline at end of file
diff --git a/packages/editor-preset-vision/src/utils/index.ts b/packages/editor-preset-vision/src/utils/index.ts
index c07d6ad04..ec3d7ea31 100644
--- a/packages/editor-preset-vision/src/utils/index.ts
+++ b/packages/editor-preset-vision/src/utils/index.ts
@@ -1,3 +1,25 @@
-export function isVariable(obj: any) {
+import { globalContext, Editor } from '@ali/lowcode-editor-core';
+
+interface Variable {
+ type: 'variable';
+ variable: string;
+ value: any;
+}
+
+export function isVariable(obj: any): obj is Variable {
return obj && obj.type === 'variable';
}
+
+export function getCurrentFieldIds() {
+ const editor = globalContext.get(Editor);
+ const designer = editor.get('designer');
+ const fieldIds: any = [];
+ const nodesMap = designer?.currentDocument?.nodesMap || new Map();
+ nodesMap.forEach((curNode: any) => {
+ const fieldId = nodesMap?.get(curNode.id)?.getPropValue('fieldId');
+ if (fieldId) {
+ fieldIds.push(fieldId);
+ }
+ });
+ return fieldIds;
+}
diff --git a/packages/editor-preset-vision/tests/bundle/bundle.test.ts b/packages/editor-preset-vision/tests/bundle/bundle.test.ts
new file mode 100644
index 000000000..31174d481
--- /dev/null
+++ b/packages/editor-preset-vision/tests/bundle/bundle.test.ts
@@ -0,0 +1,116 @@
+import { Component } from 'react';
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import divPrototypeConfig from '../fixtures/prototype/div-vision';
+import trunk from '../../src/bundle/trunk';
+import Prototype from '../../src/bundle/prototype';
+import Bundle from '../../src/bundle/bundle';
+import { Editor } from '@ali/lowcode-editor-core';
+
+jest.mock('../../src/bundle/trunk', () => {
+ // mockComponentPrototype = jest.fn();
+ // return {
+ // mockComponentPrototype: jest.fn().mockImplementation(() => {
+ // return proto;
+ // }),
+ // }
+ // return jest.fn().mockImplementation(() => {
+ // return {playSoundFile: fakePlaySoundFile};
+ // });
+ // return jest.fn().mockImplementation(() => {
+ // return { mockComponentPrototype };
+ // });
+ return {
+ __esModule: true,
+ default: {
+ mockComponentPrototype: jest.fn(),
+ },
+ };
+});
+
+function wrap(name, thing) {
+ return {
+ name,
+ componentName: name,
+ category: '布局',
+ module: thing,
+ };
+}
+
+const proto1 = new Prototype(divPrototypeConfig);
+const protoConfig2 = cloneDeep(divPrototypeConfig);
+set(protoConfig2, 'componentName', 'Div2');
+const proto2 = new Prototype(protoConfig2);
+
+const protoConfig3 = cloneDeep(divPrototypeConfig);
+set(protoConfig3, 'componentName', 'Div3');
+const proto3 = new Prototype(protoConfig3);
+
+const protoConfig4 = cloneDeep(divPrototypeConfig);
+set(protoConfig4, 'componentName', 'Div4');
+const proto4 = new Prototype(protoConfig4);
+
+const protoConfig5 = cloneDeep(divPrototypeConfig);
+set(protoConfig5, 'componentName', 'Div5');
+const proto5 = new Prototype(protoConfig5);
+
+function getComponentProtos() {
+ return [
+ wrap('Div', proto1),
+ // wrap('Div2', proto2),
+ // wrap('Div3', proto3),
+ wrap('DivPortal', [proto2, proto3]),
+ ];
+}
+
+class Div extends Component {}
+Div.displayName = 'Div';
+class Div2 extends Component {}
+Div2.displayName = 'Div2';
+class Div3 extends Component {}
+Div3.displayName = 'Div3';
+class Div4 extends Component {}
+Div4.displayName = 'Div4';
+class Div5 extends Component {}
+Div5.displayName = 'Div5';
+
+function getComponentViews() {
+ return [
+ wrap('Div', Div),
+ // wrap('Div2', Div2),
+ // wrap('Div3', Div3),
+ wrap('DivPortal', [Div2, Div3]),
+ ];
+}
+
+describe('Bundle', () => {
+ it('构造函数', () => {
+ const protos = getComponentProtos();
+ const views = getComponentViews();
+ const bundle = new Bundle(protos, views);
+ expect(bundle.getList()).toHaveLength(3);
+ expect(bundle.get('Div')).toBe(proto1);
+ expect(bundle.get('Div2')).toBe(proto2);
+ expect(bundle.get('Div3')).toBe(proto3);
+ bundle.addComponentBundle([proto4, Div4]);
+ expect(bundle.getList()).toHaveLength(4);
+ expect(bundle.get('Div4')).toBe(proto4);
+ bundle.replacePrototype('Div4', proto3);
+ expect(proto3.getView()).toBe(Div4);
+
+ bundle.removeComponentBundle('Div2');
+ expect(bundle.getList()).toHaveLength(3);
+ expect(bundle.get('Div2')).toBeUndefined;
+
+ expect(bundle.getFromMeta('Div')).toBe(proto1);
+ bundle.getFromMeta('Div5');
+ expect(bundle.getList()).toHaveLength(4);
+ });
+ it('静态方法 create', () => {
+ const protos = getComponentProtos();
+ const views = getComponentViews();
+ const bundle = Bundle.create(protos, views);
+ expect(bundle).toBeTruthy();
+ });
+});
diff --git a/packages/editor-preset-vision/tests/bundle/prototype.test.ts b/packages/editor-preset-vision/tests/bundle/prototype.test.ts
new file mode 100644
index 000000000..4776ebb1e
--- /dev/null
+++ b/packages/editor-preset-vision/tests/bundle/prototype.test.ts
@@ -0,0 +1,219 @@
+import { Component } from 'react';
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+// import { Project } from '../../src/project/project';
+// import { Node } from '../../src/document/node/node';
+// import { Designer } from '../../src/designer/designer';
+import divPrototypeConfig from '../fixtures/prototype/div-vision';
+import divFullPrototypeConfig from '../fixtures/prototype/div-vision-full';
+import divPrototypeMeta from '../fixtures/prototype/div-meta';
+// import VisualEngine from '../../src';
+import { designer } from '../../src/editor';
+import Prototype, { isPrototype } from '../../src/bundle/prototype';
+import { Editor } from '@ali/lowcode-editor-core';
+// import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+
+describe('Prototype', () => {
+ it('构造函数 - OldPrototypeConfig', () => {
+ const proto = new Prototype(divPrototypeConfig);
+ expect(isPrototype(proto)).toBeTruthy;
+ expect(proto.getComponentName()).toBe('Div');
+ expect(proto.getId()).toBe('Div');
+ expect(proto.getCategory()).toBe('布局');
+ expect(proto.getDocUrl()).toBe(
+ 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ );
+ expect(proto.getIcon()).toBeUndefined;
+ expect(proto.getTitle()).toBe('Div');
+ expect(proto.isPrototype).toBeTruthy;
+ expect(proto.isContainer()).toBeTruthy;
+ expect(proto.isModal()).toBeFalsy;
+ });
+ it('构造函数 - 全量 OldPrototypeConfig', () => {
+ const proto = new Prototype(divFullPrototypeConfig);
+ expect(isPrototype(proto)).toBeTruthy;
+ expect(proto.getComponentName()).toBe('Div');
+ expect(proto.getId()).toBe('Div');
+ expect(proto.getCategory()).toBe('布局');
+ expect(proto.getDocUrl()).toBe(
+ 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ );
+ expect(proto.getIcon()).toBeUndefined;
+ expect(proto.getTitle()).toBe('Div');
+ expect(proto.isPrototype).toBeTruthy;
+ expect(proto.isContainer()).toBeTruthy;
+ expect(proto.isModal()).toBeFalsy;
+ });
+ it('构造函数 - ComponentMetadata', () => {
+ const proto = new Prototype(divPrototypeMeta);
+ expect(proto.getComponentName()).toBe('Div');
+ expect(proto.getId()).toBe('Div');
+ expect(proto.getCategory()).toBe('布局');
+ expect(proto.getDocUrl()).toBe(
+ 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ );
+ expect(proto.getIcon()).toBeUndefined;
+ expect(proto.getTitle()).toBe('Div');
+ expect(proto.isPrototype).toBeTruthy;
+ expect(proto.isContainer()).toBeTruthy;
+ expect(proto.isModal()).toBeFalsy;
+ });
+ it('构造函数 - ComponentMeta', () => {
+ const meta = designer.createComponentMeta(divPrototypeMeta);
+ const proto = new Prototype(meta);
+ expect(proto.getComponentName()).toBe('Div');
+ expect(proto.getId()).toBe('Div');
+ expect(proto.getCategory()).toBe('布局');
+ expect(proto.getDocUrl()).toBe(
+ 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ );
+ expect(proto.getIcon()).toBeUndefined;
+ expect(proto.getTitle()).toBe('Div');
+ expect(proto.isPrototype).toBeTruthy;
+ expect(proto.isContainer()).toBeTruthy;
+ expect(proto.isModal()).toBeFalsy;
+ });
+ it('构造函数 - 静态函数 create', () => {
+ const proto = Prototype.create(divPrototypeConfig);
+ expect(proto.getComponentName()).toBe('Div');
+ expect(proto.getId()).toBe('Div');
+ expect(proto.getCategory()).toBe('布局');
+ expect(proto.getDocUrl()).toBe(
+ 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ );
+ expect(proto.getIcon()).toBeUndefined;
+ expect(proto.getTitle()).toBe('Div');
+ expect(proto.isPrototype).toBeTruthy;
+ expect(proto.isContainer()).toBeTruthy;
+ expect(proto.isModal()).toBeFalsy;
+ });
+ it('构造函数 - lookup: true', () => {
+ const proto = Prototype.create(divPrototypeConfig);
+ const proto2 = Prototype.create(divPrototypeConfig, {}, true);
+ expect(proto).toBe(proto2);
+ });
+ describe('类成员函数', () => {
+ let proto: Prototype = null;
+ beforeEach(() => {
+ proto = new Prototype(divPrototypeConfig);
+ });
+ afterEach(() => {
+ proto = null;
+ });
+ it('各种函数', () => {
+ expect(proto.componentName).toBe('Div');
+ expect(proto.getComponentName()).toBe('Div');
+ expect(proto.getId()).toBe('Div');
+ expect(proto.getContextInfo('anything')).toBeUndefined;
+ expect(proto.getPropConfigs()).toBe(divPrototypeConfig);
+ expect(proto.getConfig()).toBe(divPrototypeConfig);
+ expect(proto.getConfig('componentName')).toBe('Div');
+ expect(proto.getConfig('configure')).toBe(divPrototypeConfig.configure);
+ expect(proto.getConfig('docUrl')).toBe(
+ 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ );
+ expect(proto.getConfig('title')).toBe('容器');
+ expect(proto.getConfig('isContainer')).toBeTruthy;
+
+ class MockView extends Component {}
+
+ expect(proto.getView()).toBeUndefined;
+ proto.setView(MockView);
+ expect(proto.getView()).toBe(MockView);
+ expect(proto.meta.getMetadata().experimental?.view).toBe(MockView);
+
+ expect(proto.getPackageName()).toBeUndefined;
+ proto.setPackageName('@ali/vc-div');
+ expect(proto.getPackageName()).toBe('@ali/vc-div');
+
+ expect(proto.getConfig('category')).toBe('布局');
+ proto.setCategory('布局 new');
+ expect(proto.getConfig('category')).toBe('布局 new');
+
+ expect(proto.getConfigure()).toHaveLength(3);
+ expect(proto.getConfigure()[0].name).toBe('#props');
+ expect(proto.getConfigure()[1].name).toBe('#styles');
+ expect(proto.getConfigure()[2].name).toBe('#advanced');
+
+ expect(proto.getRectSelector()).toBeUndefined;
+ expect(proto.isAutoGenerated()).toBeFalsy;
+ });
+ });
+
+ describe('类成员函数', () => {
+ it('addGlobalPropsConfigure', () => {
+ Prototype.addGlobalPropsConfigure({
+ name: 'globalInsertProp1',
+ });
+ const proto1 = new Prototype(divPrototypeConfig);
+ expect(proto1.getConfigure()[2].items).toHaveLength(4);
+ expect(proto1.getConfigure()[2].items[3].name).toBe('globalInsertProp1');
+ Prototype.addGlobalPropsConfigure({
+ name: 'globalInsertProp2',
+ });
+ const proto2 = new Prototype(divPrototypeConfig);
+ expect(proto2.getConfigure()[2].items).toHaveLength(5);
+ expect(proto1.getConfigure()[2].items[4].name).toBe('globalInsertProp2');
+
+ Prototype.addGlobalPropsConfigure({
+ name: 'globalInsertProp3',
+ position: 'top',
+ });
+
+ const proto3 = new Prototype(divPrototypeConfig);
+ expect(proto3.getConfigure()[0].items).toHaveLength(3);
+ expect(proto1.getConfigure()[0].items[0].name).toBe('globalInsertProp3');
+ });
+
+ it('removeGlobalPropsConfigure', () => {
+ Prototype.removeGlobalPropsConfigure('globalInsertProp1');
+ Prototype.removeGlobalPropsConfigure('globalInsertProp2');
+ Prototype.removeGlobalPropsConfigure('globalInsertProp3');
+ const proto2 = new Prototype(divPrototypeConfig);
+ expect(proto2.getConfigure()[0].items).toHaveLength(2);
+ expect(proto2.getConfigure()[2].items).toHaveLength(3);
+ });
+
+ it('overridePropsConfigure', () => {
+ Prototype.addGlobalPropsConfigure({
+ name: 'globalInsertProp1',
+ title: 'globalInsertPropTitle',
+ position: 'top',
+ });
+ const proto1 = new Prototype(divPrototypeConfig);
+ expect(proto1.getConfigure()[0].items).toHaveLength(3);
+ expect(proto1.getConfigure()[0].items[0].name).toBe('globalInsertProp1');
+ expect(proto1.getConfigure()[0].items[0].title).toBe('globalInsertPropTitle');
+
+ Prototype.overridePropsConfigure('Div', [
+ {
+ name: 'globalInsertProp1',
+ title: 'globalInsertPropTitleChanged',
+ },
+ ]);
+ const proto2 = new Prototype(divPrototypeConfig);
+ expect(proto2.getConfigure()[0].name).toBe('globalInsertProp1');
+ expect(proto2.getConfigure()[0].title).toBe('globalInsertPropTitleChanged');
+
+ Prototype.overridePropsConfigure('Div', {
+ globalInsertProp1: {
+ name: 'globalInsertProp1',
+ title: 'globalInsertPropTitleChanged new',
+ position: 'top',
+ },
+ });
+ const proto3 = new Prototype(divPrototypeConfig);
+ expect(proto3.getConfigure()[0].items[0].name).toBe('globalInsertProp1');
+ expect(proto3.getConfigure()[0].items[0].title).toBe('globalInsertPropTitleChanged new');
+ });
+
+ it('addGlobalExtraActions', () => {
+ function haha() { return 'heihei'; }
+ Prototype.addGlobalExtraActions(haha);
+ const proto1 = new Prototype(divPrototypeConfig);
+ expect(proto1.meta.availableActions).toHaveLength(4);
+ expect(proto1.meta.availableActions[3].name).toBe('haha');
+ });
+ });
+});
diff --git a/packages/editor-preset-vision/tests/bundle/trunk.test.ts b/packages/editor-preset-vision/tests/bundle/trunk.test.ts
new file mode 100644
index 000000000..d4bca021f
--- /dev/null
+++ b/packages/editor-preset-vision/tests/bundle/trunk.test.ts
@@ -0,0 +1,111 @@
+import { Component } from 'react';
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import divPrototypeConfig from '../fixtures/prototype/div-vision';
+import Prototype from '../../src/bundle/prototype';
+import Bundle from '../../src/bundle/bundle';
+import trunk from '../../src/bundle/trunk';
+import lg from '@ali/vu-logger';
+
+const proto1 = new Prototype(divPrototypeConfig);
+const protoConfig2 = cloneDeep(divPrototypeConfig);
+set(protoConfig2, 'componentName', 'Div2');
+const proto2 = new Prototype(protoConfig2);
+
+const protoConfig3 = cloneDeep(divPrototypeConfig);
+set(protoConfig3, 'componentName', 'Div3');
+const proto3 = new Prototype(protoConfig3);
+
+const mockComponentPrototype = jest.fn();
+jest.mock('../../src/bundle/bundle', () => {
+ // return {
+ // mockComponentPrototype: jest.fn().mockImplementation(() => {
+ // return proto;
+ // }),
+ // }
+ // return jest.fn().mockImplementation(() => {
+ // return {playSoundFile: fakePlaySoundFile};
+ // });
+ return jest.fn().mockImplementation(() => {
+ return {
+ get: () => {},
+ getList: () => { return []; },
+ getFromMeta: () => {},
+ };
+ });
+});
+
+const mockError = jest.fn();
+jest.mock('@ali/vu-logger');
+lg.error = mockError;
+
+function wrap(name, thing) {
+ return {
+ name,
+ componentName: name,
+ category: '布局',
+ module: thing,
+ };
+}
+
+function getComponentProtos() {
+ return [
+ wrap('Div', proto1),
+ // wrap('Div2', proto2),
+ // wrap('Div3', proto3),
+ wrap('DivPortal', [proto2, proto3]),
+ ];
+}
+
+class Div extends Component {}
+Div.displayName = 'Div';
+class Div2 extends Component {}
+Div2.displayName = 'Div2';
+class Div3 extends Component {}
+Div3.displayName = 'Div3';
+
+function getComponentViews() {
+ return [
+ wrap('Div', Div),
+ // wrap('Div2', Div2),
+ // wrap('Div3', Div3),
+ wrap('DivPortal', [Div2, Div3]),
+ ];
+}
+
+describe('Trunk', () => {
+ it('构造函数', () => {
+ const warn = console.warn = jest.fn();
+ const trunkChangeHandler = jest.fn();
+ const off = trunk.onTrunkChange(trunkChangeHandler);
+ trunk.addBundle(new Bundle([proto1], [Div]));
+ trunk.addBundle(new Bundle([proto2], [Div2]));
+ expect(trunkChangeHandler).toHaveBeenCalledTimes(2);
+ off();
+ trunk.addBundle(new Bundle([proto3], [Div3]));
+ expect(trunkChangeHandler).toHaveBeenCalledTimes(2);
+ trunk.getList();
+ trunk.getPrototype('Div');
+ trunk.getPrototypeById('Div');
+ trunk.getPrototypeView('Div');
+ trunk.listByCategory();
+ expect(trunk.mockComponentPrototype(new Bundle([proto3], [Div3]))).toBeUndefined;
+ expect(mockError).toHaveBeenCalled();
+ trunk.registerComponentPrototypeMocker({ mockPrototype: jest.fn().mockImplementation(() => { return proto3; }) });
+ expect(trunk.mockComponentPrototype(new Bundle([proto3], [Div3]))).toBe(proto3);
+ const hahaSetter = () => 'haha';
+ trunk.registerSetter('haha', hahaSetter);
+ expect(trunk.getSetter('haha')).toBe(hahaSetter);
+ trunk.getRecents(5);
+ trunk.setPackages();
+ expect(warn).toHaveBeenCalledTimes(1);
+ trunk.beforeLoadBundle();
+ expect(warn).toHaveBeenCalledTimes(2);
+ trunk.afterLoadBundle();
+ expect(warn).toHaveBeenCalledTimes(3);
+ trunk.getBundle();
+ expect(warn).toHaveBeenCalledTimes(4);
+ expect(trunk.isReady()).toBeTruthy;
+ });
+});
diff --git a/packages/editor-preset-vision/tests/fixtures/prototype/div-meta.ts b/packages/editor-preset-vision/tests/fixtures/prototype/div-meta.ts
new file mode 100644
index 000000000..a2b410494
--- /dev/null
+++ b/packages/editor-preset-vision/tests/fixtures/prototype/div-meta.ts
@@ -0,0 +1,259 @@
+export default {
+ componentName: 'Div',
+ title: '容器',
+ docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ devMode: 'procode',
+ tags: ['布局'],
+ configure: {
+ props: [
+ {
+ type: 'field',
+ name: 'behavior',
+ title: '默认状态',
+ extraProps: {
+ display: 'inline',
+ defaultValue: 'NORMAL',
+ },
+ setter: {
+ componentName: 'MixedSetter',
+ props: {
+ setters: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ 'VariableSetter',
+ ],
+ },
+ },
+ },
+ {
+ type: 'field',
+ name: '__style__',
+ title: {
+ label: '样式设置',
+ tip: '点击 ? 查看样式设置器用法指南',
+ docUrl: 'https://lark.alipay.com/legao/help/design-tool-style',
+ },
+ extraProps: {
+ display: 'accordion',
+ defaultValue: {},
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ advanced: true,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'group',
+ name: 'groupkh97h5kc',
+ title: '高级',
+ extraProps: {
+ display: 'accordion',
+ },
+ items: [
+ {
+ type: 'field',
+ name: 'fieldId',
+ title: {
+ label: '唯一标识',
+ },
+ extraProps: {
+ display: 'block',
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: '请输入唯一标识',
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'useFieldIdAsDomId',
+ title: {
+ label: '将唯一标识用作 DOM ID',
+ },
+ extraProps: {
+ display: 'block',
+ defaultValue: false,
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {},
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'customClassName',
+ title: '自定义样式类',
+ extraProps: {
+ display: 'block',
+ defaultValue: '',
+ },
+ setter: {
+ componentName: 'MixedSetter',
+ props: {
+ setters: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: null,
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ 'VariableSetter',
+ ],
+ },
+ },
+ },
+ {
+ type: 'field',
+ name: 'events',
+ title: {
+ label: '动作设置',
+ tip: '点击 ? 查看如何设置组件的事件响应动作',
+ docUrl: 'https://lark.alipay.com/legao/legao/events-call',
+ },
+ extraProps: {
+ display: 'accordion',
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ events: [
+ {
+ name: 'onClick',
+ title: '当点击时',
+ initialValue:
+ "/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
+ },
+ {
+ name: 'onMouseEnter',
+ title: '当鼠标进入时',
+ initialValue:
+ "/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
+ },
+ {
+ name: 'onMouseLeave',
+ title: '当鼠标离开时',
+ initialValue:
+ "/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
+ },
+ ],
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'field',
+ name: 'onClick',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ {
+ type: 'field',
+ name: 'onMouseEnter',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ {
+ type: 'field',
+ name: 'onMouseLeave',
+ extraProps: {
+ defaultValue: {
+ ignored: true,
+ },
+ },
+ setter: 'I18nSetter',
+ },
+ ],
+ },
+ ],
+ component: {
+ isContainer: true,
+ nestingRule: {},
+ },
+ supports: {},
+ },
+ experimental: {
+ callbacks: {},
+ initials: [
+ {
+ name: 'behavior',
+ },
+ {
+ name: '__style__',
+ },
+ {
+ name: 'fieldId',
+ },
+ {
+ name: 'useFieldIdAsDomId',
+ },
+ {
+ name: 'customClassName',
+ },
+ {
+ name: 'events',
+ },
+ {
+ name: 'onClick',
+ },
+ {
+ name: 'onMouseEnter',
+ },
+ {
+ name: 'onMouseLeave',
+ },
+ ],
+ filters: [],
+ autoruns: [],
+ },
+};
diff --git a/packages/editor-preset-vision/tests/fixtures/prototype/div-vision-full.ts b/packages/editor-preset-vision/tests/fixtures/prototype/div-vision-full.ts
new file mode 100644
index 000000000..756c37649
--- /dev/null
+++ b/packages/editor-preset-vision/tests/fixtures/prototype/div-vision-full.ts
@@ -0,0 +1,293 @@
+export default {
+ title: '容器',
+ componentName: 'Div',
+ docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ category: '布局',
+ isContainer: true,
+ canOperating: false,
+ extraActions: [],
+ canContain: 'Form',
+ canDropTo: 'Div',
+ canDropIn: 'Div',
+ canResizing: true,
+ canDraging: false,
+ context: {},
+ initialChildren() {},
+ didDropIn() {},
+ didDropOut() {},
+ subtreeModified() {},
+ onResize() {},
+ onResizeStart() {},
+ onResizeEnd() {},
+ canUseCondition: true,
+ canLoop: true,
+ snippets: [
+ {
+ screenshot: 'https://img.alicdn.com/tfs/TB1CHN3u4z1gK0jSZSgXXavwpXa-112-64.png',
+ label: '普通型',
+ schema: {
+ componentName: 'Div',
+ props: {},
+ },
+ },
+ ],
+ configure: [
+ {
+ name: 'myName',
+ title: '我的名字',
+ display: 'tab',
+ initialValue: 'NORMAL',
+ defaultValue: 'NORMAL',
+ collapsed: true,
+ supportVariable: true,
+ accessor(field, val) {},
+ mutator(field, val) {},
+ disabled() {
+ return true;
+ },
+ useVariableChange() {},
+ allowTextInput: true,
+ liveTextEditing: true,
+ setter: [
+ {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ ],
+ },
+ {
+ name: 'mySlotName',
+ slotName: 'mySlotName',
+ slotTitle: '我的 Slot 名字',
+ display: 'tab',
+ initialValue: 'NORMAL',
+ defaultValue: 'NORMAL',
+ collapsed: true,
+ supportVariable: true,
+ accessor(field, val) {},
+ mutator(field, val) {},
+ disabled() {
+ return true;
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'behavior',
+ title: '默认状态',
+ display: 'inline',
+ initialValue: 'NORMAL',
+ supportVariable: true,
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: '__style__',
+ title: '样式设置',
+ display: 'accordion',
+ collapsed: false,
+ initialValue: {},
+ tip: {
+ url: 'https://lark.alipay.com/legao/help/design-tool-style',
+ content: '点击 ? 查看样式设置器用法指南',
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ advanced: true,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'group',
+ title: '高级',
+ display: 'accordion',
+ items: [
+ {
+ name: 'fieldId',
+ title: '唯一标识',
+ display: 'block',
+ tip:
+ '组件的唯一标识符,不能够与其它组件重名,不能够为空,且只能够使用以字母开头的,下划线以及数字的组合。',
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: '请输入唯一标识',
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'useFieldIdAsDomId',
+ title: '将唯一标识用作 DOM ID',
+ display: 'block',
+ tip:
+ '开启这个配置项后,会在当前组件的 HTML 元素上加入 id="当前组件的 fieldId",一般用于做 utils 的绑定,不常用',
+ initialValue: false,
+ setter: {
+ key: null,
+ ref: null,
+ props: {},
+ _owner: null,
+ },
+ },
+ {
+ name: 'customClassName',
+ title: '自定义样式类',
+ display: 'block',
+ supportVariable: true,
+ initialValue: '',
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: null,
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'events',
+ title: '动作设置',
+ tip: {
+ url: 'https://lark.alipay.com/legao/legao/events-call',
+ content: '点击 ? 查看如何设置组件的事件响应动作',
+ },
+ display: 'accordion',
+ initialValue: {
+ ignored: true,
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ events: [
+ {
+ name: 'onClick',
+ title: '当点击时',
+ initialValue:
+ "/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
+ },
+ {
+ name: 'onMouseEnter',
+ title: '当鼠标进入时',
+ initialValue:
+ "/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
+ },
+ {
+ name: 'onMouseLeave',
+ title: '当鼠标离开时',
+ initialValue:
+ "/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
+ },
+ ],
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'onClick',
+ display: 'none',
+ initialValue: {
+ ignored: true,
+ },
+ },
+ {
+ name: 'onMouseEnter',
+ display: 'none',
+ initialValue: {
+ ignored: true,
+ },
+ },
+ {
+ name: 'onMouseLeave',
+ display: 'none',
+ initialValue: {
+ ignored: true,
+ },
+ },
+ ],
+ },
+ ],
+};
diff --git a/packages/editor-preset-vision/tests/fixtures/prototype/div-vision.ts b/packages/editor-preset-vision/tests/fixtures/prototype/div-vision.ts
new file mode 100644
index 000000000..c4ae4374f
--- /dev/null
+++ b/packages/editor-preset-vision/tests/fixtures/prototype/div-vision.ts
@@ -0,0 +1,175 @@
+export default {
+ title: '容器',
+ componentName: 'Div',
+ docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
+ category: '布局',
+ isContainer: true,
+ configure: [
+ {
+ name: 'behavior',
+ title: '默认状态',
+ display: 'inline',
+ initialValue: 'NORMAL',
+ supportVariable: true,
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ options: [
+ {
+ title: '普通',
+ value: 'NORMAL',
+ },
+ {
+ title: '隐藏',
+ value: 'HIDDEN',
+ },
+ ],
+ loose: false,
+ cancelable: false,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: '__style__',
+ title: '样式设置',
+ display: 'accordion',
+ collapsed: false,
+ initialValue: {},
+ tip: {
+ url: 'https://lark.alipay.com/legao/help/design-tool-style',
+ content: '点击 ? 查看样式设置器用法指南',
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ advanced: true,
+ },
+ _owner: null,
+ },
+ },
+ {
+ type: 'group',
+ title: '高级',
+ display: 'accordion',
+ items: [
+ {
+ name: 'fieldId',
+ title: '唯一标识',
+ display: 'block',
+ tip:
+ '组件的唯一标识符,不能够与其它组件重名,不能够为空,且只能够使用以字母开头的,下划线以及数字的组合。',
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: '请输入唯一标识',
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'useFieldIdAsDomId',
+ title: '将唯一标识用作 DOM ID',
+ display: 'block',
+ tip:
+ '开启这个配置项后,会在当前组件的 HTML 元素上加入 id="当前组件的 fieldId",一般用于做 utils 的绑定,不常用',
+ initialValue: false,
+ setter: {
+ key: null,
+ ref: null,
+ props: {},
+ _owner: null,
+ },
+ },
+ {
+ name: 'customClassName',
+ title: '自定义样式类',
+ display: 'block',
+ supportVariable: true,
+ initialValue: '',
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ placeholder: null,
+ multiline: false,
+ rows: 10,
+ required: false,
+ pattern: null,
+ maxLength: null,
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'events',
+ title: '动作设置',
+ tip: {
+ url: 'https://lark.alipay.com/legao/legao/events-call',
+ content: '点击 ? 查看如何设置组件的事件响应动作',
+ },
+ display: 'accordion',
+ initialValue: {
+ ignored: true,
+ },
+ setter: {
+ key: null,
+ ref: null,
+ props: {
+ events: [
+ {
+ name: 'onClick',
+ title: '当点击时',
+ initialValue:
+ "/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
+ },
+ {
+ name: 'onMouseEnter',
+ title: '当鼠标进入时',
+ initialValue:
+ "/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
+ },
+ {
+ name: 'onMouseLeave',
+ title: '当鼠标离开时',
+ initialValue:
+ "/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
+ },
+ ],
+ },
+ _owner: null,
+ },
+ },
+ {
+ name: 'onClick',
+ display: 'none',
+ initialValue: {
+ ignored: true,
+ },
+ },
+ {
+ name: 'onMouseEnter',
+ display: 'none',
+ initialValue: {
+ ignored: true,
+ },
+ },
+ {
+ name: 'onMouseLeave',
+ display: 'none',
+ initialValue: {
+ ignored: true,
+ },
+ },
+ ],
+ },
+ ],
+};
diff --git a/packages/editor-preset-vision/tests/fixtures/schema/form.ts b/packages/editor-preset-vision/tests/fixtures/schema/form.ts
new file mode 100644
index 000000000..5492a9ffb
--- /dev/null
+++ b/packages/editor-preset-vision/tests/fixtures/schema/form.ts
@@ -0,0 +1,955 @@
+export default {
+ componentName: 'Page',
+ id: 'node_k1ow3cb9',
+ props: {
+ extensions: {
+ 启用页头: true,
+ },
+ pageStyle: {
+ backgroundColor: '#f2f3f5',
+ },
+ containerStyle: {},
+ className: 'page_kh05zf9c',
+ templateVersion: '1.0.0',
+ },
+ lifeCycles: {
+ constructor: {
+ type: 'js',
+ compiled:
+ "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
+ source:
+ "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
+ },
+ },
+ condition: true,
+ css:
+ 'body{background-color:#f2f3f5}.card_kh05zf9d {\n margin-bottom: 12px;\n}.card_kh05zf9e {\n margin-bottom: 12px;\n}.button_kh05zf9f {\n margin-right: 16px;\n width: 80px\n}.button_kh05zf9g {\n width: 80px;\n}.div_kh05zf9h {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
+ methods: {
+ __initMethods__: {
+ type: 'js',
+ source: 'function (exports, module) { /*set actions code here*/ }',
+ compiled: 'function (exports, module) { /*set actions code here*/ }',
+ },
+ },
+ dataSource: {
+ offline: [],
+ globalConfig: {
+ fit: {
+ compiled: '',
+ source: '',
+ type: 'js',
+ error: {},
+ },
+ },
+ online: [],
+ sync: true,
+ list: [],
+ },
+ children: [
+ {
+ componentName: 'RootHeader',
+ id: 'node_k1ow3cba',
+ props: {},
+ condition: true,
+ children: [
+ {
+ componentName: 'PageHeader',
+ id: 'node_k1ow3cbd',
+ props: {
+ extraContent: '',
+ __slot__extraContent: false,
+ __slot__action: false,
+ title: '',
+ content: '',
+ __slot__logo: false,
+ __slot__crumb: false,
+ crumb: '',
+ tab: '',
+ logo: '',
+ action: '',
+ __slot__tab: false,
+ __style__: {},
+ __slot__content: false,
+ fieldId: 'pageHeader_k1ow3h1i',
+ subTitle: '',
+ },
+ condition: true,
+ },
+ ],
+ },
+ {
+ componentName: 'RootContent',
+ id: 'node_k1ow3cbb',
+ props: {
+ contentBgColor: 'transparent',
+ contentPadding: '0',
+ contentMargin: '20',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'Form',
+ id: 'form',
+ props: {
+ size: 'medium',
+ labelAlign: 'top',
+ autoValidate: true,
+ scrollToFirstError: true,
+ autoUnmount: true,
+ behavior: 'NORMAL',
+ dataSource: {
+ type: 'variable',
+ variable: 'state.formData',
+ },
+ __style__: {},
+ fieldId: 'form',
+ fieldOptions: {},
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'Card',
+ id: 'node_k1ow3cbj',
+ props: {
+ __slot__title: false,
+ subTitle: {
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ __slot__subTitle: false,
+ extra: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ className: 'card_kh05zf9d',
+ title: {
+ use: 'zh_CN',
+ en_US: 'Title',
+ zh_CN: '基本信息',
+ type: 'i18n',
+ },
+ __slot__extra: false,
+ showHeadDivider: true,
+ __style__: ':root {\n margin-bottom: 12px;\n}',
+ showTitleBullet: true,
+ contentHeight: '',
+ fieldId: 'card_k1ow3h1l',
+ dividerNoInset: false,
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'CardContent',
+ id: 'node_k1ow3cbk',
+ props: {},
+ condition: true,
+ children: [
+ {
+ componentName: 'ColumnsLayout',
+ id: 'node_k1ow3cbw',
+ props: {
+ layout: '4:8',
+ columnGap: '20',
+ rowGap: 0,
+ __style__: {},
+ fieldId: 'columns_k1ow3h1v',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'Column',
+ id: 'node_k1ow3cbx',
+ props: {
+ colSpan: '',
+ __style__: {},
+ fieldId: 'column_k1p1bnjm',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cbz',
+ props: {
+ fieldName: 'name',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [
+ {
+ type: 'required',
+ },
+ ],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h1w',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: '姓名',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cc1',
+ props: {
+ fieldName: 'englishName',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h1y',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: '英文名',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cc3',
+ props: {
+ fieldName: 'jobTitle',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h20',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: '职位',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ ],
+ },
+ {
+ componentName: 'Column',
+ id: 'node_k1ow3cby',
+ props: {
+ colSpan: '',
+ __style__: {},
+ fieldId: 'column_k1p1bnjn',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cc2',
+ props: {
+ fieldName: 'nickName',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h1z',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: '花名',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ {
+ componentName: 'SelectField',
+ id: 'node_k1ow3cc0',
+ props: {
+ fieldName: 'gender',
+ hasClear: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ mode: 'single',
+ showSearch: false,
+ autoWidth: true,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please select',
+ zh_CN: '请选择',
+ type: 'i18n',
+ },
+ hasBorder: true,
+ behavior: 'NORMAL',
+ value: '',
+ validation: [
+ {
+ type: 'required',
+ },
+ ],
+ __style__: {},
+ fieldId: 'select_k1ow3h1x',
+ notFoundContent: {
+ use: 'zh_CN',
+ type: 'i18n',
+ },
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'SelectField',
+ zh_CN: '性别',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ wrapperColOffset: 0,
+ hasSelectAll: false,
+ hasArrow: true,
+ size: 'medium',
+ labelAlign: 'top',
+ filterLocal: true,
+ dataSource: [
+ {
+ defaultChecked: false,
+ text: {
+ en_US: 'Option 1',
+ zh_CN: '男',
+ type: 'i18n',
+ __sid__: 'param_k1owc4tb',
+ },
+ __sid__: 'serial_k1owc4t1',
+ value: 'M',
+ sid: 'opt_k1owc4t2',
+ },
+ {
+ defaultChecked: false,
+ text: {
+ en_US: 'Option 2',
+ zh_CN: '女',
+ type: 'i18n',
+ __sid__: 'param_k1owc4tf',
+ },
+ __sid__: 'serial_k1owc4t2',
+ value: 'F',
+ sid: 'opt_k1owc4t3',
+ },
+ ],
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ useDetailValue: false,
+ searchDelay: 300,
+ },
+ condition: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ componentName: 'Card',
+ id: 'node_k1ow3cbl',
+ props: {
+ __slot__title: false,
+ subTitle: {
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ __slot__subTitle: false,
+ extra: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ className: 'card_kh05zf9e',
+ title: {
+ use: 'zh_CN',
+ en_US: 'Title',
+ zh_CN: '部门信息',
+ type: 'i18n',
+ },
+ __slot__extra: false,
+ showHeadDivider: true,
+ __style__: ':root {\n margin-bottom: 12px;\n}',
+ showTitleBullet: true,
+ contentHeight: '',
+ fieldId: 'card_k1ow3h1m',
+ dividerNoInset: false,
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'CardContent',
+ id: 'node_k1ow3cbm',
+ props: {},
+ condition: true,
+ children: [
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cc4',
+ props: {
+ fieldName: 'department',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h21',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: '所属部门',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ {
+ componentName: 'ColumnsLayout',
+ id: 'node_k1ow3cc5',
+ props: {
+ layout: '6:6',
+ columnGap: '20',
+ rowGap: 0,
+ __style__: {},
+ fieldId: 'columns_k1ow3h22',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'Column',
+ id: 'node_k1ow3cc6',
+ props: {
+ colSpan: '',
+ __style__: {},
+ fieldId: 'column_k1p1bnjo',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cc8',
+ props: {
+ fieldName: 'leader',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h23',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: '主管',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ ],
+ },
+ {
+ componentName: 'Column',
+ id: 'node_k1ow3cc7',
+ props: {
+ colSpan: '',
+ __style__: {},
+ fieldId: 'column_k1p1bnjp',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'TextField',
+ id: 'node_k1ow3cc9',
+ props: {
+ fieldName: 'hrg',
+ hasClear: false,
+ autoFocus: false,
+ tips: {
+ en_US: '',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ trim: false,
+ labelTextAlign: 'right',
+ placeholder: {
+ use: 'zh_CN',
+ en_US: 'please input',
+ zh_CN: '请输入',
+ type: 'i18n',
+ },
+ state: '',
+ behavior: 'NORMAL',
+ value: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ addonBefore: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ validation: [],
+ hasLimitHint: false,
+ cutString: false,
+ __style__: {},
+ fieldId: 'textField_k1ow3h24',
+ htmlType: 'input',
+ autoHeight: false,
+ labelColOffset: 0,
+ label: {
+ use: 'zh_CN',
+ en_US: 'TextField',
+ zh_CN: 'HRG',
+ type: 'i18n',
+ },
+ __category__: 'form',
+ labelColSpan: 4,
+ wrapperColSpan: 0,
+ rows: 4,
+ addonAfter: {
+ use: 'zh_CN',
+ zh_CN: '',
+ type: 'i18n',
+ },
+ wrapperColOffset: 0,
+ size: 'medium',
+ labelAlign: 'top',
+ __useMediator: 'value',
+ labelTipsTypes: 'none',
+ labelTipsIcon: '',
+ labelTipsText: {
+ type: 'i18n',
+ use: 'zh_CN',
+ en_US: '',
+ zh_CN: '',
+ },
+ maxLength: 200,
+ },
+ condition: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ componentName: 'Div',
+ id: 'node_k1ow3cbo',
+ props: {
+ className: 'div_kh05zf9h',
+ behavior: 'NORMAL',
+ __style__:
+ ':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
+ events: {},
+ fieldId: 'div_k1ow3h1o',
+ useFieldIdAsDomId: false,
+ customClassName: '',
+ },
+ condition: true,
+ children: [
+ {
+ componentName: 'Button',
+ id: 'node_k1ow3cbn',
+ props: {
+ triggerEventsWhenLoading: false,
+ onClick: {
+ rawType: 'events',
+ type: 'JSExpression',
+ value:
+ 'this.utils.legaoBuiltin.execEventFlow.bind(this, [this.submit])',
+ events: [
+ {
+ name: 'submit',
+ id: 'submit',
+ params: {},
+ type: 'actionRef',
+ uuid: '1570966253282_0',
+ },
+ ],
+ },
+ size: 'medium',
+ baseIcon: '',
+ otherIcon: '',
+ className: 'button_kh05zf9f',
+ type: 'primary',
+ behavior: 'NORMAL',
+ loading: false,
+ content: {
+ use: 'zh_CN',
+ en_US: 'Button',
+ zh_CN: '提交',
+ type: 'i18n',
+ },
+ __style__: ':root {\n margin-right: 16px;\n width: 80px\n}',
+ fieldId: 'button_k1ow3h1n',
+ },
+ condition: true,
+ },
+ {
+ componentName: 'Button',
+ id: 'node_k1ow3cbp',
+ props: {
+ triggerEventsWhenLoading: false,
+ size: 'medium',
+ baseIcon: '',
+ otherIcon: '',
+ className: 'button_kh05zf9g',
+ type: 'normal',
+ behavior: 'NORMAL',
+ loading: false,
+ content: {
+ use: 'zh_CN',
+ en_US: 'Button',
+ zh_CN: '取消',
+ type: 'i18n',
+ },
+ __style__: ':root {\n width: 80px;\n}',
+ fieldId: 'button_k1ow3h1p',
+ },
+ condition: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ componentName: 'RootFooter',
+ id: 'node_k1ow3cbc',
+ props: {},
+ condition: true,
+ },
+ ],
+};
diff --git a/packages/editor-preset-vision/tests/fixtures/window.ts b/packages/editor-preset-vision/tests/fixtures/window.ts
new file mode 100644
index 000000000..2e3cd691a
--- /dev/null
+++ b/packages/editor-preset-vision/tests/fixtures/window.ts
@@ -0,0 +1,5 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+React.PropTypes = PropTypes;
+window.React = React;
\ No newline at end of file
diff --git a/packages/editor-preset-vision/tests/props-reducer/init-node.test.ts b/packages/editor-preset-vision/tests/props-reducer/init-node.test.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/editor-preset-vision/tests/utils/index.ts b/packages/editor-preset-vision/tests/utils/index.ts
new file mode 100644
index 000000000..70fce0af2
--- /dev/null
+++ b/packages/editor-preset-vision/tests/utils/index.ts
@@ -0,0 +1 @@
+export { getIdsFromSchema, getNodeFromSchemaById } from '@ali/lowcode-test-mate/es/utils';
diff --git a/packages/editor-preset-vision/tests/vision-api/api-export.test.ts b/packages/editor-preset-vision/tests/vision-api/api-export.test.ts
new file mode 100644
index 000000000..50278dc72
--- /dev/null
+++ b/packages/editor-preset-vision/tests/vision-api/api-export.test.ts
@@ -0,0 +1,89 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+// import { Project } from '../../src/project/project';
+// import { Node } from '../../src/document/node/node';
+// import { Designer } from '../../src/designer/designer';
+import formSchema from '../fixtures/schema/form';
+import VisualEngine, {
+ designer,
+ editor,
+ skeleton,
+ /**
+ * VE.Popup
+ */
+ Popup,
+ /**
+ * VE Utils
+ */
+ utils,
+ I18nUtil,
+ Hotkey,
+ Env,
+ monitor,
+ /* pub/sub 集线器 */
+ Bus,
+ /* 事件 */
+ EVENTS,
+ /* 修饰方法 */
+ HOOKS,
+ Exchange,
+ context,
+ /**
+ * VE.init
+ *
+ * Initialized the whole VisualEngine UI
+ */
+ init,
+ ui,
+ Panes,
+ modules,
+ Trunk,
+ Prototype,
+ Bundle,
+ Pages,
+ DragEngine,
+ Viewport,
+ Version,
+ Project,
+ logger,
+ Symbols,
+} from '../../src';
+import { Editor } from '@ali/lowcode-editor-core';
+
+describe('API 多种导出场景测试', () => {
+ it('window.VisualEngine 和 npm 导出 API 测试', () => {
+ expect(VisualEngine).toBe(window.VisualEngine);
+ });
+
+ it('npm 导出 API 对比测试', () => {
+ expect(VisualEngine.designer).toBe(designer);
+ expect(VisualEngine.editor).toBe(editor);
+ expect(VisualEngine.skeleton).toBe(skeleton);
+ expect(VisualEngine.Popup).toBe(Popup);
+ expect(VisualEngine.utils).toBe(utils);
+ expect(VisualEngine.I18nUtil).toBe(I18nUtil);
+ expect(VisualEngine.Hotkey).toBe(Hotkey);
+ expect(VisualEngine.Env).toBe(Env);
+ expect(VisualEngine.monitor).toBe(monitor);
+ expect(VisualEngine.Bus).toBe(Bus);
+ expect(VisualEngine.EVENTS).toBe(EVENTS);
+ expect(VisualEngine.HOOKS).toBe(HOOKS);
+ expect(VisualEngine.Exchange).toBe(Exchange);
+ expect(VisualEngine.context).toBe(context);
+ expect(VisualEngine.init).toBe(init);
+ expect(VisualEngine.ui).toBe(ui);
+ expect(VisualEngine.Panes).toBe(Panes);
+ expect(VisualEngine.modules).toBe(modules);
+ expect(VisualEngine.Trunk).toBe(Trunk);
+ expect(VisualEngine.Prototype).toBe(Prototype);
+ expect(VisualEngine.Bundle).toBe(Bundle);
+ expect(VisualEngine.DragEngine).toBe(DragEngine);
+ expect(VisualEngine.Pages).toBe(Pages);
+ expect(VisualEngine.Viewport).toBe(Viewport);
+ expect(VisualEngine.Version).toBe(Version);
+ expect(VisualEngine.Project).toBe(Project);
+ expect(VisualEngine.logger).toBe(logger);
+ expect(VisualEngine.Symbols).toBe(Symbols);
+ });
+});
\ No newline at end of file
diff --git a/packages/editor-preset-vision/tests/vision-api/exchange.test.ts b/packages/editor-preset-vision/tests/vision-api/exchange.test.ts
new file mode 100644
index 000000000..972f49541
--- /dev/null
+++ b/packages/editor-preset-vision/tests/vision-api/exchange.test.ts
@@ -0,0 +1,18 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import formSchema from '../fixtures/schema/form';
+import VisualEngine from '../../src';
+
+describe('VisualEngine.Exchange 相关 API 测试', () => {
+ it('select / getSelected', () => {
+ const doc = VisualEngine.Pages.addPage(formSchema);
+ VisualEngine.Exchange.select(doc?.getNode('form'));
+ expect(VisualEngine.Exchange.getSelected()?.componentName).toBe('Form');
+ expect(VisualEngine.Exchange.getSelected()?.id).toBe('form');
+ });
+
+ it('onIntoView', () => {
+ expect(typeof VisualEngine.Exchange.onIntoView).toBe('function');
+ });
+});
diff --git a/packages/editor-preset-vision/tests/vision-api/pages.test.ts b/packages/editor-preset-vision/tests/vision-api/pages.test.ts
new file mode 100644
index 000000000..a6567bd24
--- /dev/null
+++ b/packages/editor-preset-vision/tests/vision-api/pages.test.ts
@@ -0,0 +1,170 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import formSchema from '../fixtures/schema/form';
+import VisualEngine, { Prototype } from '../../src';
+import { Editor } from '@ali/lowcode-editor-core';
+import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
+import divPrototypeConfig from '../fixtures/prototype/div-vision';
+
+const pageSchema = { componentsTree: [formSchema] };
+
+describe('VisualEngine.Pages 相关 API 测试', () => {
+ afterEach(() => {
+ VisualEngine.Pages.unload();
+ });
+ describe('addPage 系列', () => {
+ it('基本的节点模型初始化,初始化传入 schema', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema)!;
+ expect(doc).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ expect(doc.nodesMap.size).toBe(expectedNodeCnt);
+ });
+ it('基本的节点模型初始化,初始化传入 schema,带有 slot', () => {
+ const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title', {
+ type: 'JSBlock',
+ value: {
+ componentName: 'Slot',
+ children: [
+ {
+ componentName: 'Text',
+ id: 'node_k1ow3cbf',
+ props: {
+ showTitle: false,
+ behavior: 'NORMAL',
+ content: {
+ type: 'variable',
+ value: {
+ use: 'zh_CN',
+ en_US: 'Title',
+ zh_CN: '个人信息',
+ type: 'i18n',
+ },
+ variable: 'state.title',
+ },
+ __style__: {},
+ fieldId: 'text_k1ow3h1j',
+ maxLine: 0,
+ },
+ condition: true,
+ },
+ ],
+ props: {
+ slotTitle: '标题区域',
+ slotName: 'title',
+ },
+ },
+ });
+ const doc = VisualEngine.Pages.addPage({ componentsTree: [formSchemaWithSlot] })!;
+ expect(doc).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ // slot 会多出(1 + N)个节点
+ expect(doc.nodesMap.size).toBe(expectedNodeCnt + 2);
+ });
+ it.only('基本的节点模型初始化,初始化传入 schema,构造 prototype', () => {
+ const proto = new Prototype(divPrototypeConfig);
+ const doc = VisualEngine.Pages.addPage(pageSchema)!;
+ expect(doc).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ expect(doc.nodesMap.size).toBe(expectedNodeCnt);
+ });
+ it('导出 schema', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema)!;
+ expect(doc).toBeTruthy();
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const exportedData = doc.toData();
+ expect(exportedData).toHaveProperty('componentsMap');
+ expect(exportedData).toHaveProperty('componentsTree');
+ expect(exportedData.componentsTree).toHaveLength(1);
+ const exportedSchema = exportedData.componentsTree[0];
+ expect(getIdsFromSchema(exportedSchema).length).toBe(expectedNodeCnt);
+ });
+ });
+ describe('removePage 系列', () => {
+ it('removePage', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema)!;
+ expect(doc).toBeTruthy();
+ expect(VisualEngine.Pages.documents).toHaveLength(1);
+ VisualEngine.Pages.removePage(doc);
+ expect(VisualEngine.Pages.documents).toHaveLength(0);
+ });
+ });
+ describe('getPage 系列', () => {
+ it('getPage', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema);
+ const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
+ const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
+ expect(VisualEngine.Pages.getPage(0)).toBe(doc);
+ expect(VisualEngine.Pages.getPage((_doc) => _doc.rootNode.id === 'page')).toBe(doc2);
+ });
+ });
+ describe('setPages 系列', () => {
+ it('setPages componentsTree 只有一个元素', () => {
+ VisualEngine.Pages.setPages([pageSchema]);
+ const { currentDocument } = VisualEngine.Pages;
+ const ids = getIdsFromSchema(formSchema);
+ const expectedNodeCnt = ids.length;
+ const exportedData = currentDocument.toData();
+ expect(exportedData).toHaveProperty('componentsMap');
+ expect(exportedData).toHaveProperty('componentsTree');
+ expect(exportedData.componentsTree).toHaveLength(1);
+ const exportedSchema = exportedData.componentsTree[0];
+ expect(getIdsFromSchema(exportedSchema).length).toBe(expectedNodeCnt);
+ });
+ });
+ describe('setCurrentPage / getCurrentPage / currentPage / currentDocument 系列', () => {
+ it('getCurrentPage', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema)!;
+ expect(doc).toBeTruthy();
+ expect(doc).toBe(VisualEngine.Pages.getCurrentPage());
+ expect(doc).toBe(VisualEngine.Pages.currentDocument);
+ expect(doc).toBe(VisualEngine.Pages.currentPage);
+ });
+ it('setCurrentPage', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema);
+ expect(doc).toBe(VisualEngine.Pages.currentDocument);
+ const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
+ const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
+ expect(doc2).toBe(VisualEngine.Pages.currentDocument);
+ VisualEngine.Pages.setCurrentPage(doc);
+ expect(doc).toBe(VisualEngine.Pages.currentDocument);
+ });
+ });
+ describe('onCurrentPageChange 系列', () => {
+ it('多次切换', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema);
+ const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
+ const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
+ const docChangeHandler = jest.fn();
+ VisualEngine.Pages.onCurrentDocumentChange(docChangeHandler);
+ VisualEngine.Pages.setCurrentPage(doc);
+ expect(docChangeHandler).toHaveBeenCalledTimes(1);
+ expect(docChangeHandler).toHaveBeenLastCalledWith(doc);
+
+ VisualEngine.Pages.setCurrentPage(doc2);
+ expect(docChangeHandler).toHaveBeenCalledTimes(2);
+ expect(docChangeHandler).toHaveBeenLastCalledWith(doc2);
+ });
+ });
+ describe('toData 系列', () => {
+ it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
+ const doc = VisualEngine.Pages.addPage(pageSchema);
+ const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
+ const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
+ const dataList = VisualEngine.Pages.toData();
+ expect(dataList.length).toBe(2);
+ expect(dataList[0]).toHaveProperty('componentsMap');
+ expect(dataList[0]).toHaveProperty('componentsTree');
+ expect(dataList[0].componentsTree).toHaveLength(1);
+ expect(dataList[0].componentsTree[0].id).toBe('node_k1ow3cb9');
+ expect(dataList[1]).toHaveProperty('componentsMap');
+ expect(dataList[1]).toHaveProperty('componentsTree');
+ expect(dataList[1].componentsTree).toHaveLength(1);
+ expect(dataList[1].componentsTree[0].id).toBe('page');
+ });
+ });
+});
diff --git a/packages/editor-preset-vision/tests/vision-api/project.test.ts b/packages/editor-preset-vision/tests/vision-api/project.test.ts
new file mode 100644
index 000000000..6bb7cc566
--- /dev/null
+++ b/packages/editor-preset-vision/tests/vision-api/project.test.ts
@@ -0,0 +1,26 @@
+import set from 'lodash/set';
+import cloneDeep from 'lodash/clonedeep';
+import '../fixtures/window';
+import formSchema from '../fixtures/schema/form';
+import { Project } from '../../src';
+
+describe.skip('VisualEngine.Project 相关 API 测试', () => {
+ it('getSchema / setSchema 系列', () => {
+ Project.setSchema({
+ componentsMap: {},
+ componentsTree: [formSchema],
+ });
+ expect(Project.getSchema()).toEqual({
+ componentsMap: {},
+ componentsTree: [formSchema],
+ });
+
+ });
+
+ it('setConfig', () => {
+ Project.setConfig({ haha: 1 });
+ expect(Project.get('config')).toEqual({
+ haha: 1,
+ });
+ });
+});
diff --git a/packages/editor-setters/CHANGELOG.md b/packages/editor-setters/CHANGELOG.md
index e8c8ce42b..983509ec1 100644
--- a/packages/editor-setters/CHANGELOG.md
+++ b/packages/editor-setters/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-editor-setters
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/editor-setters/package.json b/packages/editor-setters/package.json
index d9505f6c3..1c0d745bf 100644
--- a/packages/editor-setters/package.json
+++ b/packages/editor-setters/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-setters",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Builtin setters for Ali lowCode engine",
"files": [
"es",
@@ -21,7 +21,7 @@
"@ali/iceluna-comp-react-node": "^1.0.5",
"@ali/iceluna-sdk": "^1.0.5-beta.24",
"@ali/lc-style-setter": "^0.0.1",
- "@ali/lowcode-editor-core": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"acorn": "^6.4.1",
"classnames": "^2.2.6",
diff --git a/packages/editor-skeleton/.eslintrc.js b/packages/editor-skeleton/.eslintrc.js
index 27e1e0d4f..c650ed99f 100644
--- a/packages/editor-skeleton/.eslintrc.js
+++ b/packages/editor-skeleton/.eslintrc.js
@@ -12,5 +12,6 @@ module.exports = {
'no-prototype-builtins': 1,
'no-confusing-arrow': 1,
'no-case-declarations': 1,
+ 'lines-between-class-members': 0,
}
}
\ No newline at end of file
diff --git a/packages/editor-skeleton/CHANGELOG.md b/packages/editor-skeleton/CHANGELOG.md
index d464b346f..ca517c4cf 100644
--- a/packages/editor-skeleton/CHANGELOG.md
+++ b/packages/editor-skeleton/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-editor-skeleton
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/editor-skeleton/package.json b/packages/editor-skeleton/package.json
index 1affbb8e5..dc45518cb 100644
--- a/packages/editor-skeleton/package.json
+++ b/packages/editor-skeleton/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-skeleton",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor skeleton",
"main": "lib/index.js",
"module": "es/index.js",
@@ -19,10 +19,10 @@
"editor"
],
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@ali/ve-icons": "latest",
"@ali/ve-less-variables": "^2.0.0",
"@alifd/next": "^1.20.12",
diff --git a/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx b/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx
index 69ba92a2f..6527cc690 100644
--- a/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx
+++ b/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx
@@ -11,7 +11,7 @@ import { createIcon } from '@ali/lowcode-utils';
@observer
export class SettingsPrimaryPane extends Component<{ editor: Editor; config: any }, { shouldIgnoreRoot: boolean }> {
state = {
- shouldIgnoreRoot: false,
+ shouldIgnoreRoot: false,
};
private main = new SettingsMain(this.props.editor);
@@ -24,12 +24,12 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor; config: any
componentDidMount() {
this.setShouldIgnoreRoot();
}
-
+
async setShouldIgnoreRoot() {
- let designMode = await this.props.editor.get('designMode');
+ const designMode = await this.props.editor.get('designMode');
this.setState({
shouldIgnoreRoot: designMode === 'live',
- })
+ });
}
componentWillUnmount() {
diff --git a/packages/editor-skeleton/src/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts
index fa8d846f8..4a4c5b598 100644
--- a/packages/editor-skeleton/src/transducers/addon-combine.ts
+++ b/packages/editor-skeleton/src/transducers/addon-combine.ts
@@ -329,7 +329,7 @@ export default function (metadata: TransformedComponentMetadata): TransformedCom
if (advanceGroup.length > 0) {
combined.push({
name: '#advanced',
- title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' },
+ title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advanced' },
items: advanceGroup,
});
}
diff --git a/packages/material-parser/CHANGELOG.md b/packages/material-parser/CHANGELOG.md
index abe423a4a..da624deaf 100644
--- a/packages/material-parser/CHANGELOG.md
+++ b/packages/material-parser/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/material-parser/package.json b/packages/material-parser/package.json
index b1eb4eba9..631a22f73 100644
--- a/packages/material-parser/package.json
+++ b/packages/material-parser/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-material-parser",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "material parser for Ali lowCode engine",
"main": "lib/index.js",
"files": [
diff --git a/packages/plugin-components-pane/CHANGELOG.md b/packages/plugin-components-pane/CHANGELOG.md
index 68dcc90de..287e0d051 100644
--- a/packages/plugin-components-pane/CHANGELOG.md
+++ b/packages/plugin-components-pane/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-components-pane/package.json b/packages/plugin-components-pane/package.json
index 4cf036e2f..bd529106e 100644
--- a/packages/plugin-components-pane/package.json
+++ b/packages/plugin-components-pane/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-components-pane",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor component-list plugin",
"files": [
"es/",
@@ -20,9 +20,9 @@
],
"author": "xiayang.xy",
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
"@alifd/next": "^1.19.19",
"react": "^16.8.1"
},
diff --git a/packages/plugin-designer/CHANGELOG.md b/packages/plugin-designer/CHANGELOG.md
index dff580821..0c99f3d48 100644
--- a/packages/plugin-designer/CHANGELOG.md
+++ b/packages/plugin-designer/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-designer
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-designer/package.json b/packages/plugin-designer/package.json
index 0be101962..d7b7ac77c 100644
--- a/packages/plugin-designer/package.json
+++ b/packages/plugin-designer/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-designer",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor designer plugin",
"files": [
"es",
@@ -20,8 +20,8 @@
],
"author": "xiayang.xy",
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
"react": "^16.8.1",
"react-dom": "^16.8.1"
},
diff --git a/packages/plugin-event-bind-dialog/CHANGELOG.md b/packages/plugin-event-bind-dialog/CHANGELOG.md
index 69bfdd3c3..8aa8b4d35 100644
--- a/packages/plugin-event-bind-dialog/CHANGELOG.md
+++ b/packages/plugin-event-bind-dialog/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-event-bind-dialog
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-event-bind-dialog/package.json b/packages/plugin-event-bind-dialog/package.json
index ba73780b4..960af4bac 100644
--- a/packages/plugin-event-bind-dialog/package.json
+++ b/packages/plugin-event-bind-dialog/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-event-bind-dialog",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor event bind dialog plugin",
"files": [
"es",
@@ -19,8 +19,8 @@
],
"author": "zude.hzd",
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"react": "^16.8.1",
"react-dom": "^16.8.1"
diff --git a/packages/plugin-outline-pane/CHANGELOG.md b/packages/plugin-outline-pane/CHANGELOG.md
index 5af5fdc61..b42ed4331 100644
--- a/packages/plugin-outline-pane/CHANGELOG.md
+++ b/packages/plugin-outline-pane/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-outline-pane/package.json b/packages/plugin-outline-pane/package.json
index 2d73f0e57..40936d333 100644
--- a/packages/plugin-outline-pane/package.json
+++ b/packages/plugin-outline-pane/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-outline-pane",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Outline pane for Ali lowCode engine",
"files": [
"es",
@@ -14,10 +14,10 @@
"test:snapshot": "ava --update-snapshots"
},
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"classnames": "^2.2.6",
"react": "^16",
diff --git a/packages/plugin-sample-logo/CHANGELOG.md b/packages/plugin-sample-logo/CHANGELOG.md
index 5089ba982..3b1e543db 100644
--- a/packages/plugin-sample-logo/CHANGELOG.md
+++ b/packages/plugin-sample-logo/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-sample-logo
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-sample-logo/package.json b/packages/plugin-sample-logo/package.json
index e486d7686..df8d097e8 100644
--- a/packages/plugin-sample-logo/package.json
+++ b/packages/plugin-sample-logo/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-sample-logo",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor logo plugin",
"files": [
"es/",
@@ -20,7 +20,7 @@
],
"author": "xiayang.xy",
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
"react": "^16.8.1"
},
"devDependencies": {
diff --git a/packages/plugin-sample-preview/CHANGELOG.md b/packages/plugin-sample-preview/CHANGELOG.md
index fd0a5d069..cd06d209e 100644
--- a/packages/plugin-sample-preview/CHANGELOG.md
+++ b/packages/plugin-sample-preview/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-sample-preview
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-sample-preview/package.json b/packages/plugin-sample-preview/package.json
index ee025dbfe..d8ea6a432 100644
--- a/packages/plugin-sample-preview/package.json
+++ b/packages/plugin-sample-preview/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-sample-preview",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor sample preview plugin",
"files": [
"es",
@@ -19,11 +19,11 @@
"editor"
],
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-react-renderer": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-react-renderer": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@alifd/next": "^1.x",
"react": "^16.8.1"
},
diff --git a/packages/plugin-source-editor/CHANGELOG.md b/packages/plugin-source-editor/CHANGELOG.md
index 0db1b81d7..62d373636 100644
--- a/packages/plugin-source-editor/CHANGELOG.md
+++ b/packages/plugin-source-editor/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-source-editor
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-source-editor/package.json b/packages/plugin-source-editor/package.json
index 5be712bd0..b0f62d5c9 100644
--- a/packages/plugin-source-editor/package.json
+++ b/packages/plugin-source-editor/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-source-editor",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor source-editor plugin",
"files": [
"es",
@@ -19,7 +19,7 @@
],
"author": "zude.hzd",
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"js-beautify": "^1.10.1",
"prettier": "^1.18.2",
diff --git a/packages/plugin-undo-redo/CHANGELOG.md b/packages/plugin-undo-redo/CHANGELOG.md
index 8a49bd3fa..14c8ca8a5 100644
--- a/packages/plugin-undo-redo/CHANGELOG.md
+++ b/packages/plugin-undo-redo/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-undo-redo
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-undo-redo/package.json b/packages/plugin-undo-redo/package.json
index d48bb0e4f..ed6040fb5 100644
--- a/packages/plugin-undo-redo/package.json
+++ b/packages/plugin-undo-redo/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-undo-redo",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor undo redo plugin",
"files": [
"es",
@@ -19,11 +19,11 @@
],
"author": "xiayang.xy",
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-editor-skeleton": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-editor-skeleton": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"react": "^16.8.1",
"react-dom": "^16.8.1"
},
diff --git a/packages/plugin-variable-bind-dialog/CHANGELOG.md b/packages/plugin-variable-bind-dialog/CHANGELOG.md
index ced698638..84eb4bd2a 100644
--- a/packages/plugin-variable-bind-dialog/CHANGELOG.md
+++ b/packages/plugin-variable-bind-dialog/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-variable-bind-dialog
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-variable-bind-dialog/package.json b/packages/plugin-variable-bind-dialog/package.json
index 8a65321a2..5c95bb310 100644
--- a/packages/plugin-variable-bind-dialog/package.json
+++ b/packages/plugin-variable-bind-dialog/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-variable-bind-dialog",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor variable bind dialog plugin",
"files": [
"es",
@@ -19,7 +19,7 @@
],
"author": "zude.hzd",
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"react": "^16.8.1",
"react-dom": "^16.8.1"
diff --git a/packages/plugin-zh-en/CHANGELOG.md b/packages/plugin-zh-en/CHANGELOG.md
index ba2c5e30f..e90c2636b 100644
--- a/packages/plugin-zh-en/CHANGELOG.md
+++ b/packages/plugin-zh-en/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-plugin-zh-en
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/plugin-zh-en/package.json b/packages/plugin-zh-en/package.json
index 150ea9ae1..663af1f27 100644
--- a/packages/plugin-zh-en/package.json
+++ b/packages/plugin-zh-en/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-zh-en",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "alibaba lowcode editor zhong english plugin",
"files": [
"es",
@@ -14,9 +14,9 @@
"test:snapshot": "ava --update-snapshots"
},
"dependencies": {
- "@ali/lowcode-editor-core": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-editor-core": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"react": "^16.8.1",
"react-dom": "^16.8.1"
},
diff --git a/packages/rax-provider/CHANGELOG.md b/packages/rax-provider/CHANGELOG.md
index 004fcfa80..0f025c5bd 100644
--- a/packages/rax-provider/CHANGELOG.md
+++ b/packages/rax-provider/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-rax-provider
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/rax-provider/package.json b/packages/rax-provider/package.json
index 2d74b8f8b..67eb8d4e5 100644
--- a/packages/rax-provider/package.json
+++ b/packages/rax-provider/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-rax-provider",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Rax Provider for Runtime",
"files": [
"es",
@@ -18,7 +18,7 @@
},
"license": "MIT",
"dependencies": {
- "@ali/lowcode-runtime": "^0.13.1-10",
+ "@ali/lowcode-runtime": "^0.13.1-11",
"driver-universal": "^3.1.3",
"history": "^4.10.1",
"rax-use-router": "^3.0.0"
diff --git a/packages/rax-render/CHANGELOG.md b/packages/rax-render/CHANGELOG.md
index d967228c2..8cdbf7f27 100644
--- a/packages/rax-render/CHANGELOG.md
+++ b/packages/rax-render/CHANGELOG.md
@@ -3,7 +3,15 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-rax-renderer
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
@@ -11,7 +19,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
**Note:** Version bump only for package @ali/lowcode-rax-renderer
-
+
## [0.13.1-9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-7...v0.13.1-9) (2020-10-26)
diff --git a/packages/rax-render/package.json b/packages/rax-render/package.json
index 7367ca4d3..9fecfd70b 100644
--- a/packages/rax-render/package.json
+++ b/packages/rax-render/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-rax-renderer",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Rax renderer for Ali lowCode engine",
"main": "lib/index.js",
"module": "lib/index.js",
@@ -36,7 +36,7 @@
"@ali/b3-one": "^0.0.17",
"@ali/bzb-request": "2.6.1",
"@ali/lib-mtop": "^2.5.1",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@ali/ui-table": "^1.0.1-beta.6",
"classnames": "^2.2.6",
"debug": "^4.1.1",
diff --git a/packages/rax-simulator-renderer/CHANGELOG.md b/packages/rax-simulator-renderer/CHANGELOG.md
index f31fcb062..3424a1d01 100644
--- a/packages/rax-simulator-renderer/CHANGELOG.md
+++ b/packages/rax-simulator-renderer/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-rax-simulator-renderer
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/rax-simulator-renderer/package.json b/packages/rax-simulator-renderer/package.json
index 2c4881461..5469de810 100644
--- a/packages/rax-simulator-renderer/package.json
+++ b/packages/rax-simulator-renderer/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-rax-simulator-renderer",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "rax simulator renderer for alibaba lowcode designer",
"main": "lib/index.js",
"module": "es/index.js",
@@ -13,10 +13,10 @@
"test:snapshot": "ava --update-snapshots"
},
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-rax-renderer": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-rax-renderer": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@ali/recore-rax": "^1.2.4",
"@ali/vu-css-style": "^1.0.2",
"@recore/obx": "^1.0.8",
@@ -57,5 +57,5 @@
"publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com"
},
- "homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-rax-simulator-renderer@0.13.1-10/build/index.html"
+ "homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-rax-simulator-renderer@0.13.1-11/build/index.html"
}
diff --git a/packages/react-provider/CHANGELOG.md b/packages/react-provider/CHANGELOG.md
index f05e1032c..1c96be202 100644
--- a/packages/react-provider/CHANGELOG.md
+++ b/packages/react-provider/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-react-provider
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/react-provider/package.json b/packages/react-provider/package.json
index 1499b31d6..9e314c371 100644
--- a/packages/react-provider/package.json
+++ b/packages/react-provider/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-react-provider",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "React Provider for Runtime",
"files": [
"es",
@@ -25,7 +25,7 @@
},
"license": "MIT",
"dependencies": {
- "@ali/lowcode-runtime": "^0.13.1-10",
+ "@ali/lowcode-runtime": "^0.13.1-11",
"@ali/lowcode-utils": "^1.0.7",
"@recore/router": "^1.0.11",
"react": "^16",
diff --git a/packages/react-renderer/CHANGELOG.md b/packages/react-renderer/CHANGELOG.md
index a6ecdc018..53a5ef6b0 100644
--- a/packages/react-renderer/CHANGELOG.md
+++ b/packages/react-renderer/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+### Bug Fixes
+
+* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
+
+
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/react-renderer/package.json b/packages/react-renderer/package.json
index 946612931..3da0c9537 100644
--- a/packages/react-renderer/package.json
+++ b/packages/react-renderer/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-react-renderer",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "react renderer for ali lowcode engine",
"main": "lib/index.js",
"module": "es/index.js",
@@ -54,5 +54,5 @@
"publishConfig": {
"registry": "http://registry.npm.alibaba-inc.com"
},
- "homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-react-renderer@0.13.1-10/build/index.html"
+ "homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-react-renderer@0.13.1-11/build/index.html"
}
diff --git a/packages/react-renderer/src/renderer/base.tsx b/packages/react-renderer/src/renderer/base.tsx
index 8efa3ef79..1eab49f5c 100644
--- a/packages/react-renderer/src/renderer/base.tsx
+++ b/packages/react-renderer/src/renderer/base.tsx
@@ -339,7 +339,7 @@ export default class BaseRender extends PureComponent {
if (refProps && typeof refProps === 'string') {
this[refProps] = ref;
}
- engine && engine.props.onCompGetRef(schema, ref);
+ ref && engine && engine.props.onCompGetRef(schema, ref);
};
}
// scope需要传入到组件上
diff --git a/packages/react-simulator-renderer/.eslintrc.js b/packages/react-simulator-renderer/.eslintrc.js
index 31d2e19c3..39a7d9067 100644
--- a/packages/react-simulator-renderer/.eslintrc.js
+++ b/packages/react-simulator-renderer/.eslintrc.js
@@ -11,6 +11,7 @@ module.exports = {
'no-shadow': 0,
'no-prototype-builtins': 0,
'array-callback-return': 0,
- '@typescript-eslint/member-ordering': 0
+ '@typescript-eslint/member-ordering': 0,
+ 'react/no-find-dom-node', 0
}
}
\ No newline at end of file
diff --git a/packages/react-simulator-renderer/CHANGELOG.md b/packages/react-simulator-renderer/CHANGELOG.md
index 8598bf198..106612ec7 100644
--- a/packages/react-simulator-renderer/CHANGELOG.md
+++ b/packages/react-simulator-renderer/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+### Bug Fixes
+
+* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
+
+
+
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/react-simulator-renderer/package.json b/packages/react-simulator-renderer/package.json
index 1b1d78350..a64bbaf7b 100644
--- a/packages/react-simulator-renderer/package.json
+++ b/packages/react-simulator-renderer/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-react-simulator-renderer",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "react simulator renderer for alibaba lowcode designer",
"main": "lib/index.js",
"module": "es/index.js",
@@ -16,10 +16,10 @@
"build": "build-scripts build --skip-demo"
},
"dependencies": {
- "@ali/lowcode-designer": "^0.13.1-10",
- "@ali/lowcode-react-renderer": "^0.13.1-10",
- "@ali/lowcode-types": "^0.13.1-10",
- "@ali/lowcode-utils": "^0.13.1-10",
+ "@ali/lowcode-designer": "^0.13.1-11",
+ "@ali/lowcode-react-renderer": "^0.13.1-11",
+ "@ali/lowcode-types": "^0.13.1-11",
+ "@ali/lowcode-utils": "^0.13.1-11",
"@ali/vu-css-style": "^1.0.2",
"@recore/obx": "^1.0.8",
"@recore/obx-react": "^1.0.7",
diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts
index 77d3769c9..64ef4d454 100644
--- a/packages/react-simulator-renderer/src/renderer.ts
+++ b/packages/react-simulator-renderer/src/renderer.ts
@@ -187,7 +187,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
this._componentsMap = host.designer.componentsMap;
// 需要注意的是,autorun 依赖收集的是同步执行的代码,所以 await / promise / callback 里的变量不会被收集依赖
// 此例中,host.designer.componentsMap 是需要被收集依赖的,否则无法响应式
- await host.waitForCurrentDocument();
+ // await host.waitForCurrentDocument();
this.buildComponents();
}
diff --git a/packages/react-simulator-renderer/src/utils/react-find-dom-nodes.ts b/packages/react-simulator-renderer/src/utils/react-find-dom-nodes.ts
index f7dde3925..36aa3bfb2 100644
--- a/packages/react-simulator-renderer/src/utils/react-find-dom-nodes.ts
+++ b/packages/react-simulator-renderer/src/utils/react-find-dom-nodes.ts
@@ -1,4 +1,5 @@
import { ReactInstance } from 'react';
+import { findDOMNode } from 'react-dom';
import { isElement } from '@ali/lowcode-utils';
import { isDOMNode } from './is-dom-node';
@@ -29,5 +30,5 @@ export function reactFindDOMNodes(elem: ReactInstance | null): Array = [];
const fiberNode = (elem as any)[FIBER_KEY];
elementsFromFiber(fiberNode.child, elements);
- return elements.length > 0 ? elements : null;
+ return elements.length > 0 ? elements : [findDOMNode(elem)];
}
diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md
index 9b587d125..84c90e1fc 100644
--- a/packages/runtime/CHANGELOG.md
+++ b/packages/runtime/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-runtime
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/runtime/package.json b/packages/runtime/package.json
index 02bd8ff64..4b0fa825f 100644
--- a/packages/runtime/package.json
+++ b/packages/runtime/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-runtime",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Runtime for Ali lowCode engine",
"files": [
"es",
diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md
index 7143cff9b..9b2fb33d1 100644
--- a/packages/types/CHANGELOG.md
+++ b/packages/types/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-types
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/types/package.json b/packages/types/package.json
index 8a1e7ffa4..d0d8216f0 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-types",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Types for Ali lowCode engine",
"files": [
"es",
diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md
index dc1b414a3..6fa46cca8 100644
--- a/packages/utils/CHANGELOG.md
+++ b/packages/utils/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-utils
+
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 79360b681..e9cb1a30f 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-utils",
- "version": "0.13.1-10",
+ "version": "0.13.1-11",
"description": "Utils for Ali lowCode engine",
"files": [
"es",
@@ -14,7 +14,7 @@
"test:snapshot": "ava --update-snapshots"
},
"dependencies": {
- "@ali/lowcode-types": "^0.13.1-10",
+ "@ali/lowcode-types": "^0.13.1-11",
"@alifd/next": "^1.19.16",
"react": "^16"
},