mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-12 00:48:16 +00:00
Merge branch 'develop' into release/code-gen-1.1.3-beta
This commit is contained in:
commit
fd87ddcdd1
@ -62,11 +62,11 @@ delete(node: IPublicModelNode): boolean;
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 删除指定节点
|
||||
* delete the node
|
||||
* 插入一个节点
|
||||
* insert the node
|
||||
* @param node
|
||||
*/
|
||||
delete(node: IPublicModelNode): boolean;
|
||||
insert(node: IPublicModelNode): boolean;
|
||||
```
|
||||
|
||||
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
|
||||
|
||||
@ -45,6 +45,8 @@ sidebar_position: 12
|
||||
|
||||
关联模型 [IPublicModelEditorView](./editor-view)
|
||||
|
||||
**@since v1.1.7**
|
||||
|
||||
### editorViews
|
||||
|
||||
窗口所有视图
|
||||
@ -53,6 +55,7 @@ sidebar_position: 12
|
||||
|
||||
关联模型 [IPublicModelEditorView](./editor-view)
|
||||
|
||||
**@since v1.1.7**
|
||||
|
||||
## 方法
|
||||
|
||||
@ -90,3 +93,15 @@ onChangeViewType(fn: (viewName: string) => void): IPublicTypeDisposable;
|
||||
```
|
||||
|
||||
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
|
||||
|
||||
### onSave
|
||||
|
||||
窗口视图保存事件
|
||||
|
||||
```
|
||||
onSave(fn: () => void): IPublicTypeDisposable;
|
||||
```
|
||||
|
||||
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
|
||||
|
||||
**@since v1.1.7**
|
||||
|
||||
155
docs/docs/guide/expand/editor/graph.md
Normal file
155
docs/docs/guide/expand/editor/graph.md
Normal file
@ -0,0 +1,155 @@
|
||||
---
|
||||
title: 图编排扩展
|
||||
sidebar_position: 9
|
||||
---
|
||||
## 项目运行
|
||||
### 前置准备
|
||||
1. 参考 https://lowcode-engine.cn/site/docs/guide/quickStart/start
|
||||
2. 参考至Demo下载 https://lowcode-engine.cn/site/docs/guide/quickStart/start#%E4%B8%8B%E8%BD%BD-demo
|
||||
### 选择demo-graph-x6
|
||||
在根目录下执行:
|
||||
```bash
|
||||
cd demo-graph-x6
|
||||
```
|
||||
### 安装依赖
|
||||
在 lowcode-demo/demo-graph-x6目录下执行:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
### 启动Demo
|
||||
在 lowcode-demo/demo-graph-x6 目录下执行:
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
之后就可以通过 http://localhost:5556/ 来访问我们的 DEMO 了。
|
||||
|
||||
## 认识Demo
|
||||
这里的Demo即通过图编排引擎加入了几个简单的物料而来,已经是可以面向真是用户的产品界面。
|
||||

|
||||
### 区域组成
|
||||
#### 顶部:操作区
|
||||
- 右侧:保存到本地、重置页面、自定义按钮
|
||||
#### 顶部:工具区
|
||||
- 左侧:删除、撤销、重做、放大、缩小
|
||||
#### 左侧:面板与操作区
|
||||
- 物料面板:可以查找节点,并在此拖动节点到编辑器画布中
|
||||
#### 中部:可视化页面编辑画布区域
|
||||
- 点击节点/边在右侧面板中能够显示出对应组件的属性配置选项
|
||||
- 拖拽修改节点的排列顺序
|
||||
#### 右侧:组件级别配置
|
||||
- 选中的组件:从页面开始一直到当前选中的节点/边位置,点击对应的名称可以切换到对应的节点上
|
||||
- 选中组件的配置:属性:节点的基础属性值设置
|
||||
|
||||
> 每个区域的组成都可以被替换和自定义来生成开发者需要的业务产品。
|
||||
|
||||
## 目录介绍
|
||||

|
||||
|
||||
- public:与其他demo保持一致,均是lowcode engine所必要依赖
|
||||
- src
|
||||
- plugins::自定义插件,完成了x6的切面回调处理功能
|
||||
- services:mock数据,真实场景中可能为异步获取数据
|
||||
|
||||
## 开发插件
|
||||
```typescript
|
||||
function pluginX6DesignerExtension(ctx: IPublicModelPluginContext) {
|
||||
return {
|
||||
init() {
|
||||
// 获取 x6 designer 内置插件的导出 api
|
||||
const x6Designer = ctx.plugins['plugin-x6-designer'] as IDesigner;
|
||||
|
||||
x6Designer.onNodeRender((model, node) => {
|
||||
// @ts-ignore
|
||||
// 自定义 node 渲染逻辑
|
||||
const { name, title } = model.propsData;
|
||||
node.attr('text/textWrap/text', title || name);
|
||||
});
|
||||
|
||||
x6Designer.onEdgeRender((model, edge) => {
|
||||
// @ts-ignore
|
||||
const { source, target, sourcePortId, targetPortId } = model.propsData;
|
||||
console.log(sourcePortId, targetPortId);
|
||||
requestAnimationFrame(() => {
|
||||
edge.setSource({ cell: source, port: sourcePortId });
|
||||
edge.setTarget({ cell: target, port: targetPortId });
|
||||
});
|
||||
|
||||
// https://x6.antv.vision/zh/docs/tutorial/intermediate/edge-labels x6 标签模块
|
||||
// appendLabel 会触发 onEdgeLabelRender
|
||||
edge.appendLabel({
|
||||
markup: Markup.getForeignObjectMarkup(),
|
||||
attrs: {
|
||||
fo: {
|
||||
width: 120,
|
||||
height: 30,
|
||||
x: -60,
|
||||
y: -15,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
x6Designer.onEdgeLabelRender((args) => {
|
||||
const { selectors } = args
|
||||
const content = selectors.foContent as HTMLDivElement
|
||||
if (content) {
|
||||
ReactDOM.render(<div>自定义 react 标签</div>, content)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pluginX6DesignerExtension.pluginName = 'plugin-x6-designer-extension';
|
||||
|
||||
export default pluginX6DesignerExtension;
|
||||
```
|
||||
x6Designer为图实例暴露出来的一些接口,可基于此进行一些图的必要插件的封装,整个插件的封装完全follow低代码引擎的插件,详情可参考 https://lowcode-engine.cn/site/docs/guide/expand/editor/pluginWidget
|
||||
|
||||
## 开发物料
|
||||
```bash
|
||||
npm init @alilc/element your-material-demo
|
||||
```
|
||||

|
||||
|
||||
仓库初始化完成
|
||||

|
||||
|
||||
接下来即可编写物料内容了
|
||||
图物料与低代码的dom场景存在画布的差异,因此暂不支持物料单独调试,须通过项目demo进行物料调试
|
||||
|
||||
### 资产描述
|
||||
```bash
|
||||
npm run lowcode:build
|
||||
```
|
||||
如果物料是个React组件,则在执行上述命令时会自动生成对应的meta.ts,<b>但图物料很多时候并非一个React组件,因此须手动生产meta.ts</b>
|
||||
|
||||
可参考: https://github.com/alibaba/lowcode-materials/blob/main/packages/graph-x6-materials/lowcode/send-email/meta.ts
|
||||
同时会自动生成物料描述文件
|
||||
|
||||
### 物料调试
|
||||
#### 物料侧
|
||||
物料想要支持被项目动态inject调试,须在build.lowcode.js中加入
|
||||
```javascript
|
||||
[
|
||||
'@alilc/build-plugin-alt',
|
||||
{
|
||||
type: 'component',
|
||||
inject: true,
|
||||
library
|
||||
},
|
||||
]
|
||||
```
|
||||

|
||||
|
||||
本地启动
|
||||
```bash
|
||||
npm run lowcode:dev
|
||||
```
|
||||
#### 项目侧
|
||||
通过@alilc/lce-graph-core加载物料的天然支持了debug,因此无须特殊处理。
|
||||
若项目中自行加载,则参考 https://lowcode-engine.cn/site/docs/guide/expand/editor/cli
|
||||
项目访问地址后拼接query "?debug"即可进入物料调试
|
||||

|
||||
|
||||
|
||||
@ -18,8 +18,7 @@ import { Icon, Message } from '@alifd/next';
|
||||
const addHelloAction = (ctx: IPublicModelPluginContext) => {
|
||||
return {
|
||||
async init() {
|
||||
const { addBuiltinComponentAction } = ctx.material;
|
||||
addBuiltinComponentAction({
|
||||
ctx.material.addBuiltinComponentAction({
|
||||
name: 'hello',
|
||||
content: {
|
||||
icon: <Icon type="atm" />,
|
||||
@ -54,8 +53,7 @@ import { IPublicModelPluginContext } from '@alilc/lowcode-types';
|
||||
const removeCopyAction = (ctx: IPublicModelPluginContext) => {
|
||||
return {
|
||||
async init() {
|
||||
const { removeBuiltinComponentAction } = ctx.material;
|
||||
removeBuiltinComponentAction('copy');
|
||||
ctx.material.removeBuiltinComponentAction('copy');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-engine-docs",
|
||||
"version": "1.0.28",
|
||||
"version": "1.0.30",
|
||||
"description": "低代码引擎版本化文档",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"lerna": "4.0.0",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": [
|
||||
|
||||
@ -106,6 +106,11 @@ function processChildren(schema: IPublicTypeNodeSchema): void {
|
||||
}
|
||||
}
|
||||
|
||||
function getInternalDep(internalDeps: Record<string, IInternalDependency>, depName: string) {
|
||||
const dep = internalDeps[depName];
|
||||
return (dep && dep.type !== InternalDependencyType.PAGE) ? dep : null;
|
||||
}
|
||||
|
||||
export class SchemaParser implements ISchemaParser {
|
||||
validate(schema: IPublicTypeProjectSchema): boolean {
|
||||
if (SUPPORT_SCHEMA_VERSION_LIST.indexOf(schema.version) < 0) {
|
||||
@ -221,12 +226,11 @@ export class SchemaParser implements ISchemaParser {
|
||||
}
|
||||
});
|
||||
|
||||
// 分析容器内部组件依赖
|
||||
containers.forEach((container) => {
|
||||
const depNames = this.getComponentNames(container);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
container.deps = uniqueArray<string>(depNames, (i: string) => i)
|
||||
.map((depName) => internalDeps[depName] || compDeps[depName])
|
||||
.map((depName) => getInternalDep(internalDeps, depName) || compDeps[depName])
|
||||
.filter(Boolean);
|
||||
// container.deps = Object.keys(compDeps).map((depName) => compDeps[depName]);
|
||||
});
|
||||
|
||||
@ -20,7 +20,7 @@ const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig
|
||||
|
||||
const codePrettier: PostProcessor = (content: string, fileType: string) => {
|
||||
let parser: prettier.BuiltInParserName | any;
|
||||
if (fileType === 'js' || fileType === 'jsx') {
|
||||
if (fileType === 'js' || fileType === 'jsx' || fileType === 'ts' || fileType === 'tsx') {
|
||||
parser = 'babel';
|
||||
} else if (fileType === 'json') {
|
||||
parser = 'json-stringify';
|
||||
|
||||
@ -167,7 +167,7 @@ export function parseExpressionGetKeywords(expr: string | null | undefined): str
|
||||
],
|
||||
});
|
||||
|
||||
const addIdentifierIfNeeded = (x: Record<string, unknown> | number | null | undefined) => {
|
||||
const addIdentifierIfNeeded = (x: Node | null | undefined) => {
|
||||
if (typeof x === 'object' && isIdentifier(x) && JS_KEYWORDS.includes(x.name)) {
|
||||
keywordVars.add(x.name);
|
||||
}
|
||||
@ -189,7 +189,7 @@ export function parseExpressionGetKeywords(expr: string | null | undefined): str
|
||||
addIdentifierIfNeeded(item);
|
||||
});
|
||||
} else {
|
||||
addIdentifierIfNeeded(fieldValue as Record<string, unknown> | null);
|
||||
addIdentifierIfNeeded(fieldValue as any);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -217,7 +217,7 @@ export function parseExpressionGetGlobalVariables(
|
||||
const ast = parser.parse(`!(${expr});`);
|
||||
|
||||
const addUndeclaredIdentifierIfNeeded = (
|
||||
x: Record<string, unknown> | number | null | undefined,
|
||||
x: Node | null | undefined,
|
||||
path: NodePath<Node>,
|
||||
) => {
|
||||
if (typeof x === 'object' && isIdentifier(x) && !path.scope.hasBinding(x.name)) {
|
||||
@ -241,7 +241,7 @@ export function parseExpressionGetGlobalVariables(
|
||||
addUndeclaredIdentifierIfNeeded(item, path);
|
||||
});
|
||||
} else {
|
||||
addUndeclaredIdentifierIfNeeded(fieldValue as Record<string, unknown> | null, path);
|
||||
addUndeclaredIdentifierIfNeeded(fieldValue as any, path);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -19,6 +19,7 @@ import { executeFunctionStack } from './aopHelper';
|
||||
import { encodeJsxStringNode } from './encodeJsxAttrString';
|
||||
import { unwrapJsExprQuoteInJsx } from './jsxHelpers';
|
||||
import { transformThis2Context } from '../core/jsx/handlers/transformThis2Context';
|
||||
import { isValidIdentifier } from './validate';
|
||||
|
||||
function mergeNodeGeneratorConfig(
|
||||
cfg1: NodeGeneratorConfig,
|
||||
@ -126,11 +127,13 @@ function generateAttrs(
|
||||
if (props) {
|
||||
if (!Array.isArray(props)) {
|
||||
Object.keys(props).forEach((propName: string) => {
|
||||
pieces = pieces.concat(generateAttr(propName, props[propName] as IPublicTypeCompositeValue, scope, config));
|
||||
if (isValidIdentifier(propName)) {
|
||||
pieces = pieces.concat(generateAttr(propName, props[propName] as IPublicTypeCompositeValue, scope, config));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
props.forEach((prop) => {
|
||||
if (prop.name && !prop.spread) {
|
||||
if (prop.name && isValidIdentifier(prop.name) && !prop.spread) {
|
||||
pieces = pieces.concat(generateAttr(prop.name, prop.value, scope, config));
|
||||
}
|
||||
|
||||
|
||||
@ -281,3 +281,75 @@ Object {
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`condition at root invalid attr name should not be generated 1`] = `
|
||||
Object {
|
||||
"chunks": Array [
|
||||
Object {
|
||||
"content": "
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return <Page><Text a={1}>Hello world!</Text></Page>;
|
||||
",
|
||||
"fileType": "jsx",
|
||||
"linkAfter": Array [
|
||||
"ReactComponentClassRenderStart",
|
||||
"ReactComponentClassRenderPre",
|
||||
],
|
||||
"name": "ReactComponentClassRenderJSX",
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"content": "
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
...ext,
|
||||
};
|
||||
childContext.__proto__ = oldContext;
|
||||
return childContext;
|
||||
}
|
||||
",
|
||||
"fileType": "jsx",
|
||||
"linkAfter": Array [
|
||||
"CommonFileExport",
|
||||
],
|
||||
"name": "CommonCustomContent",
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"contextData": Object {},
|
||||
"depNames": Array [],
|
||||
"ir": Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"children": "Hello world!",
|
||||
"componentName": "Text",
|
||||
"props": Object {
|
||||
"a": 1,
|
||||
"a.b": 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
"componentName": "Page",
|
||||
"condition": null,
|
||||
"containerType": "Page",
|
||||
"fileName": "test",
|
||||
"moduleName": "test",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
@ -83,4 +83,22 @@ describe('condition at root', () => {
|
||||
});
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('invalid attr name should not be generated', async () => {
|
||||
const containerIr: IContainerInfo = {
|
||||
containerType: 'Page',
|
||||
moduleName: 'test',
|
||||
componentName: 'Page',
|
||||
fileName: 'test',
|
||||
condition: null,
|
||||
children: [{ componentName: 'Text', children: 'Hello world!', props: { 'a': 1, 'a.b': 2 } }],
|
||||
};
|
||||
const result = await jsx()({
|
||||
ir: containerIr,
|
||||
contextData: {},
|
||||
chunks: [],
|
||||
depNames: [],
|
||||
});
|
||||
expect(result).toMatchSnapshot();
|
||||
})
|
||||
});
|
||||
|
||||
@ -19,6 +19,7 @@ const jestConfig = {
|
||||
// testMatch: ['**/setting-field.test.ts'],
|
||||
// testMatch: ['**/node.test.ts'],
|
||||
// testMatch: ['**/builtin-hotkey.test.ts'],
|
||||
// testMatch: ['**/selection.test.ts'],
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})/`,
|
||||
],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-designer",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Designer for Ali LowCode Engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,9 +15,10 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-editor-core": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/build-plugin-lce": "^0.0.4-beta.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.7",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
|
||||
@ -1,29 +1,7 @@
|
||||
import { Component } from '../simulator';
|
||||
import { IPublicTypeComponentInstance, IPublicTypeNodeInstance, Asset, IPublicTypeComponentSchema, IPublicTypeProjectSchema, IPublicTypeLowCodeComponent } from '@alilc/lowcode-types';
|
||||
import { IPublicTypeComponentInstance, IPublicTypeSimulatorRenderer } from '@alilc/lowcode-types';
|
||||
|
||||
export interface BuiltinSimulatorRenderer {
|
||||
readonly isSimulatorRenderer: true;
|
||||
autoRepaintNode?: boolean;
|
||||
components: Record<string, Component>;
|
||||
rerender: () => void;
|
||||
createComponent(schema: IPublicTypeProjectSchema<IPublicTypeComponentSchema>): Component | null;
|
||||
getComponent(componentName: string): Component;
|
||||
getClosestNodeInstance(
|
||||
from: IPublicTypeComponentInstance,
|
||||
nodeId?: string,
|
||||
): IPublicTypeNodeInstance<IPublicTypeComponentInstance> | null;
|
||||
findDOMNodes(instance: IPublicTypeComponentInstance): Array<Element | Text> | null;
|
||||
getClientRects(element: Element | Text): DOMRect[];
|
||||
setNativeSelection(enableFlag: boolean): void;
|
||||
setDraggingState(state: boolean): void;
|
||||
setCopyState(state: boolean): void;
|
||||
loadAsyncLibrary(asyncMap: { [index: string]: any }): void;
|
||||
clearState(): void;
|
||||
stopAutoRepaintNode(): void;
|
||||
enableAutoRepaintNode(): void;
|
||||
run(): void;
|
||||
load(asset: Asset): Promise<any>;
|
||||
}
|
||||
export type BuiltinSimulatorRenderer = IPublicTypeSimulatorRenderer<Component, IPublicTypeComponentInstance>;
|
||||
|
||||
export function isSimulatorRenderer(obj: any): obj is BuiltinSimulatorRenderer {
|
||||
return obj && obj.isSimulatorRenderer;
|
||||
|
||||
@ -839,13 +839,18 @@ export class DocumentModel implements IDocumentModel {
|
||||
}
|
||||
// 合并外界传入的自定义渲染的组件
|
||||
if (Array.isArray(extraComps)) {
|
||||
extraComps.forEach(c => {
|
||||
if (c && !exsitingMap[c]) {
|
||||
const m = this.getComponentMeta(c);
|
||||
if (m && m.npm?.package) {
|
||||
extraComps.forEach((componentName) => {
|
||||
if (componentName && !exsitingMap[componentName]) {
|
||||
const meta = this.getComponentMeta(componentName);
|
||||
if (meta?.npm?.package) {
|
||||
componentsMap.push({
|
||||
...m?.npm,
|
||||
componentName: c,
|
||||
...meta?.npm,
|
||||
componentName,
|
||||
});
|
||||
} else {
|
||||
componentsMap.push({
|
||||
devMode: 'lowCode',
|
||||
componentName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,6 +159,9 @@ export interface IBaseNode<Schema extends IPublicTypeNodeSchema = IPublicTypeNod
|
||||
setProps(props?: IPublicTypePropsMap | IPublicTypePropsList | Props | null): void;
|
||||
|
||||
mergeProps(props: IPublicTypePropsMap): void;
|
||||
|
||||
/** 是否可以选中 */
|
||||
canSelect(): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -644,6 +647,12 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
return !!this.getExtraProp('isLocked')?.getValue();
|
||||
}
|
||||
|
||||
canSelect(): boolean {
|
||||
const onSelectHook = this.componentMeta?.advanced?.callbacks?.onSelectHook;
|
||||
const canSelect = typeof onSelectHook === 'function' ? onSelectHook(this.internalToShellNode()!) : true;
|
||||
return canSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择当前节点
|
||||
*/
|
||||
|
||||
@ -148,15 +148,13 @@ export class Prop implements IProp, IPropParent {
|
||||
|
||||
@obx.shallow private _items: IProp[] | null = null;
|
||||
|
||||
@obx.shallow private _maps: Map<string | number, IProp> | null = null;
|
||||
|
||||
/**
|
||||
* 作为 _maps 的一层缓存机制,主要是复用部分已存在的 Prop,保持响应式关系,比如:
|
||||
* 作为一层缓存机制,主要是复用部分已存在的 Prop,保持响应式关系,比如:
|
||||
* 当前 Prop#_value 值为 { a: 1 },当调用 setValue({ a: 2 }) 时,所有原来的子 Prop 均被销毁,
|
||||
* 导致假如外部有 mobx reaction(常见于 observer),此时响应式链路会被打断,
|
||||
* 因为 reaction 监听的是原 Prop(a) 的 _value,而不是新 Prop(a) 的 _value。
|
||||
*/
|
||||
private _prevMaps: Map<string | number, IProp> | null = null;
|
||||
@obx.shallow private _maps: Map<string | number, IProp> | null = null;
|
||||
|
||||
/**
|
||||
* 构造 items 属性,同时构造 maps 属性
|
||||
@ -171,8 +169,8 @@ export class Prop implements IProp, IPropParent {
|
||||
data.forEach((item: any, idx: number) => {
|
||||
items = items || [];
|
||||
let prop;
|
||||
if (this._prevMaps?.has(idx.toString())) {
|
||||
prop = this._prevMaps.get(idx.toString())!;
|
||||
if (this._maps?.has(idx.toString())) {
|
||||
prop = this._maps.get(idx.toString())!;
|
||||
prop.setValue(item);
|
||||
} else {
|
||||
prop = new Prop(this, item, idx);
|
||||
@ -187,8 +185,8 @@ export class Prop implements IProp, IPropParent {
|
||||
const keys = Object.keys(data);
|
||||
for (const key of keys) {
|
||||
let prop: IProp;
|
||||
if (this._prevMaps?.has(key)) {
|
||||
prop = this._prevMaps.get(key)!;
|
||||
if (this._maps?.has(key)) {
|
||||
prop = this._maps.get(key)!;
|
||||
prop.setValue(data[key]);
|
||||
} else {
|
||||
prop = new Prop(this, data[key], key);
|
||||
@ -419,8 +417,6 @@ export class Prop implements IProp, IPropParent {
|
||||
items.forEach((prop) => prop.purge());
|
||||
}
|
||||
this._items = null;
|
||||
this._prevMaps = this._maps;
|
||||
this._maps = null;
|
||||
if (this._type !== 'slot' && this._slotNode) {
|
||||
this._slotNode.remove();
|
||||
this._slotNode = undefined;
|
||||
|
||||
@ -32,6 +32,12 @@ export class Selection implements ISelection {
|
||||
return;
|
||||
}
|
||||
|
||||
const node = this.doc.getNode(id);
|
||||
|
||||
if (!node?.canSelect()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._selected = [id];
|
||||
this.emitter.emit('selectionchange', this._selected);
|
||||
}
|
||||
@ -40,7 +46,18 @@ export class Selection implements ISelection {
|
||||
* 批量选中
|
||||
*/
|
||||
selectAll(ids: string[]) {
|
||||
this._selected = ids;
|
||||
const selectIds: string[] = [];
|
||||
|
||||
ids.forEach(d => {
|
||||
const node = this.doc.getNode(d);
|
||||
|
||||
if (node?.canSelect()) {
|
||||
selectIds.push(d);
|
||||
}
|
||||
});
|
||||
|
||||
this._selected = selectIds;
|
||||
|
||||
this.emitter.emit('selectionchange', this._selected);
|
||||
}
|
||||
|
||||
|
||||
@ -379,7 +379,6 @@ describe('Prop 类测试', () => {
|
||||
prop.dispose();
|
||||
|
||||
expect(prop._items).toBeNull();
|
||||
expect(prop._maps).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -122,7 +122,7 @@ describe('选择区测试', () => {
|
||||
selectionChangeHandler.mockClear();
|
||||
});
|
||||
|
||||
it('dispose 方法', () => {
|
||||
it('selectAll 包含不存在的 id', () => {
|
||||
const project = new Project(designer, {
|
||||
componentsTree: [
|
||||
formSchema,
|
||||
@ -135,14 +135,7 @@ describe('选择区测试', () => {
|
||||
|
||||
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 方法 - 选中的节点没有被删除的', () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-core",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Core Api for Ali lowCode engine",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -14,8 +14,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"intl-messageformat": "^9.3.1",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-skeleton",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "alibaba lowcode editor skeleton",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -19,10 +19,10 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.20.12",
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-editor-core": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-editor-core": "1.1.7",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, MouseEvent, Fragment, ReactNode } from 'react';
|
||||
import { shallowIntl, observer, obx, engineConfig, runInAction } from '@alilc/lowcode-editor-core';
|
||||
import { createContent, isJSSlot, isSetterConfig } from '@alilc/lowcode-utils';
|
||||
import { createContent, isJSSlot, isSetterConfig, shouldUseVariableSetter } from '@alilc/lowcode-utils';
|
||||
import { Skeleton, Stage } from '@alilc/lowcode-editor-skeleton';
|
||||
import { IPublicApiSetters, IPublicTypeCustomView, IPublicTypeDynamicProps } from '@alilc/lowcode-types';
|
||||
import { ISettingEntry, IComponentMeta, ISettingField, isSettingField, ISettingTopEntry } from '@alilc/lowcode-designer';
|
||||
@ -155,23 +155,29 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
|
||||
const supportVariable = this.field.extraProps?.supportVariable;
|
||||
// supportVariableGlobally 只对标准组件生效,vc 需要单独配置
|
||||
const supportVariableGlobally = engineConfig.get('supportVariableGlobally', false) && isStandardComponent(componentMeta);
|
||||
if (supportVariable || supportVariableGlobally) {
|
||||
if (setterType === 'MixedSetter') {
|
||||
// VariableSetter 不单独使用
|
||||
if (Array.isArray(setterProps.setters) && !setterProps.setters.includes('VariableSetter')) {
|
||||
setterProps.setters.push('VariableSetter');
|
||||
}
|
||||
} else {
|
||||
setterType = 'MixedSetter';
|
||||
setterProps = {
|
||||
setters: [
|
||||
setter,
|
||||
'VariableSetter',
|
||||
],
|
||||
};
|
||||
}
|
||||
const isUseVariableSetter = shouldUseVariableSetter(supportVariable, supportVariableGlobally);
|
||||
if (isUseVariableSetter === false) {
|
||||
return {
|
||||
setterProps,
|
||||
initialValue,
|
||||
setterType,
|
||||
};
|
||||
}
|
||||
|
||||
if (setterType === 'MixedSetter') {
|
||||
// VariableSetter 不单独使用
|
||||
if (Array.isArray(setterProps.setters) && !setterProps.setters.includes('VariableSetter')) {
|
||||
setterProps.setters.push('VariableSetter');
|
||||
}
|
||||
} else {
|
||||
setterType = 'MixedSetter';
|
||||
setterProps = {
|
||||
setters: [
|
||||
setter,
|
||||
'VariableSetter',
|
||||
],
|
||||
};
|
||||
}
|
||||
return {
|
||||
setterProps,
|
||||
initialValue,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-engine",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "An enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系",
|
||||
"main": "lib/engine-core.js",
|
||||
"module": "es/engine-core.js",
|
||||
@ -19,15 +19,15 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.12",
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-editor-core": "1.1.6",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-editor-core": "1.1.7",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.7",
|
||||
"@alilc/lowcode-engine-ext": "^1.0.0",
|
||||
"@alilc/lowcode-plugin-designer": "1.1.6",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.1.6",
|
||||
"@alilc/lowcode-shell": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-workspace": "1.1.6",
|
||||
"@alilc/lowcode-plugin-designer": "1.1.7",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.1.7",
|
||||
"@alilc/lowcode-shell": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"@alilc/lowcode-workspace": "1.1.7",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-ignitor",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "点火器,bootstrap lce project",
|
||||
"main": "lib/index.js",
|
||||
"private": true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-designer",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "alibaba lowcode editor designer plugin",
|
||||
"files": [
|
||||
"es",
|
||||
@ -18,9 +18,9 @@
|
||||
],
|
||||
"author": "xiayang.xy",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-editor-core": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-editor-core": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-outline-pane",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Outline pane for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
@ -13,8 +13,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
|
||||
@ -244,7 +244,9 @@ export default class TreeNode {
|
||||
if (this.node.conditionGroup) {
|
||||
return;
|
||||
}
|
||||
this.node.visible = !flag;
|
||||
if (this.node.visible !== !flag) {
|
||||
this.node.visible = !flag;
|
||||
}
|
||||
this.event.emit(EVENT_NAMES.hiddenChanged, flag);
|
||||
}
|
||||
|
||||
|
||||
@ -40,6 +40,11 @@ export class Tree {
|
||||
treeNode?.notifyConditionChanged();
|
||||
}
|
||||
});
|
||||
|
||||
doc?.onChangeNodeVisible((node: IPublicModelNode, visible: boolean) => {
|
||||
const treeNode = this.getTreeNodeById(node.id);
|
||||
treeNode?.setHidden(!visible);
|
||||
});
|
||||
}
|
||||
|
||||
setNodeSelected(nodeId: string): void {
|
||||
|
||||
@ -4,7 +4,7 @@ import { IPublicModelPluginContext, IPublicModelDocumentModel } from '@alilc/low
|
||||
import { MasterPaneName, BackupPaneName } from './helper/consts';
|
||||
import { TreeMaster } from './controllers/tree-master';
|
||||
import { PaneController } from './controllers/pane-controller';
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export function OutlinePaneContext(props: {
|
||||
treeMaster?: TreeMaster;
|
||||
@ -19,9 +19,11 @@ export function OutlinePaneContext(props: {
|
||||
}) {
|
||||
const treeMaster = props.treeMaster || new TreeMaster(props.pluginContext, props.options);
|
||||
const [masterPaneController, setMasterPaneController] = useState(new PaneController(props.paneName || MasterPaneName, treeMaster));
|
||||
treeMaster.onPluginContextChange(() => {
|
||||
setMasterPaneController(new PaneController(props.paneName || MasterPaneName, treeMaster));
|
||||
});
|
||||
useEffect(() => {
|
||||
return treeMaster.onPluginContextChange(() => {
|
||||
setMasterPaneController(new PaneController(props.paneName || MasterPaneName, treeMaster));
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Pane
|
||||
|
||||
@ -28,6 +28,7 @@ export default class TreeTitle extends PureComponent<{
|
||||
editing: boolean;
|
||||
title: string;
|
||||
condition?: boolean;
|
||||
visible?: boolean;
|
||||
} = {
|
||||
editing: false,
|
||||
title: '',
|
||||
@ -93,6 +94,11 @@ export default class TreeTitle extends PureComponent<{
|
||||
condition: treeNode.condition,
|
||||
});
|
||||
});
|
||||
treeNode.onHiddenChanged((hidden: boolean) => {
|
||||
this.setState({
|
||||
visible: !hidden,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -132,7 +138,7 @@ export default class TreeTitle extends PureComponent<{
|
||||
data-id={treeNode.id}
|
||||
onClick={() => {
|
||||
if (isModal) {
|
||||
if (node.visible) {
|
||||
if (this.state.visible) {
|
||||
node.document?.modalNodesManager?.setInvisible(node);
|
||||
} else {
|
||||
node.document?.modalNodesManager?.setVisible(node);
|
||||
@ -144,7 +150,7 @@ export default class TreeTitle extends PureComponent<{
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isModal && node.visible && (
|
||||
{isModal && this.state.visible && (
|
||||
<div onClick={() => {
|
||||
node.document?.modalNodesManager?.setInvisible(node);
|
||||
}}
|
||||
@ -152,7 +158,7 @@ export default class TreeTitle extends PureComponent<{
|
||||
<IconRadioActive className="tree-node-modal-radio-active" />
|
||||
</div>
|
||||
)}
|
||||
{isModal && !node.visible && (
|
||||
{isModal && !this.state.visible && (
|
||||
<div onClick={() => {
|
||||
node.document?.modalNodesManager?.setVisible(node);
|
||||
}}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-renderer",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Rax renderer for Ali lowCode engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -30,8 +30,8 @@
|
||||
"build": "build-scripts build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-renderer-core": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-renderer-core": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"rax-find-dom-node": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-simulator-renderer",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "rax simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -13,10 +13,10 @@
|
||||
"build:umd": "build-scripts build --config build.umd.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-rax-renderer": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-rax-renderer": "1.1.7",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"driver-universal": "^3.1.3",
|
||||
"history": "^5.0.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-renderer",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "react renderer for ali lowcode engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -22,7 +22,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.21.16",
|
||||
"@alilc/lowcode-renderer-core": "1.1.6"
|
||||
"@alilc/lowcode-renderer-core": "1.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-simulator-renderer",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "react simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -17,10 +17,10 @@
|
||||
"test:cov": "build-scripts test --config build.test.json --jest-coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-react-renderer": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-react-renderer": "1.1.7",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"mobx": "^6.3.0",
|
||||
"mobx-react": "^7.2.0",
|
||||
|
||||
@ -12,6 +12,7 @@ const jestConfig = {
|
||||
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
|
||||
// testMatch: ['**/*/base.test.tsx'],
|
||||
// testMatch: ['**/utils/common.test.ts'],
|
||||
// testMatch: ['**/*/leaf.test.tsx'],
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})/`,
|
||||
],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-renderer-core",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "renderer core",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -16,8 +16,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-datasource-engine": "^1.0.0",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
@ -32,7 +32,7 @@
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@alifd/next": "^1.26.0",
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@testing-library/react": "^11.2.2",
|
||||
"@types/classnames": "^2.2.11",
|
||||
|
||||
@ -521,16 +521,11 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
}
|
||||
|
||||
get hasChildren(): boolean {
|
||||
let { children } = this.props;
|
||||
if (this.state.childrenInState) {
|
||||
children = this.state.nodeChildren;
|
||||
if (!this.state.childrenInState) {
|
||||
return 'children' in this.props;
|
||||
}
|
||||
|
||||
if (Array.isArray(children)) {
|
||||
return Boolean(children && children.length);
|
||||
}
|
||||
|
||||
return Boolean(children);
|
||||
return true;
|
||||
}
|
||||
|
||||
get children(): any {
|
||||
@ -576,7 +571,11 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
|
||||
delete compProps.__inner__;
|
||||
|
||||
return engine.createElement(Comp, compProps, this.hasChildren ? this.children : null);
|
||||
if (this.hasChildren) {
|
||||
return engine.createElement(Comp, compProps, this.children);
|
||||
}
|
||||
|
||||
return engine.createElement(Comp, compProps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -504,6 +504,41 @@ describe('onChildrenChange', () => {
|
||||
DivNode.emitChildrenChange();
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('children is 0', () => {
|
||||
DivNode.schema.children = 0
|
||||
DivNode.emitChildrenChange();
|
||||
const componentInstance = component.root;
|
||||
expect(componentInstance.findByType(components.Div).props.children).toEqual(0);
|
||||
});
|
||||
|
||||
it('children is false', () => {
|
||||
DivNode.schema.children = false
|
||||
DivNode.emitChildrenChange();
|
||||
const componentInstance = component.root;
|
||||
expect(componentInstance.findByType(components.Div).props.children).toEqual(false);
|
||||
});
|
||||
|
||||
it('children is []', () => {
|
||||
DivNode.schema.children = []
|
||||
DivNode.emitChildrenChange();
|
||||
const componentInstance = component.root;
|
||||
expect(componentInstance.findByType(components.Div).props.children).toEqual([]);
|
||||
});
|
||||
|
||||
it('children is null', () => {
|
||||
DivNode.schema.children = null
|
||||
DivNode.emitChildrenChange();
|
||||
const componentInstance = component.root;
|
||||
expect(componentInstance.findByType(components.Div).props.children).toEqual(null);
|
||||
});
|
||||
|
||||
it('children is undefined', () => {
|
||||
DivNode.schema.children = undefined;
|
||||
DivNode.emitChildrenChange();
|
||||
const componentInstance = component.root;
|
||||
expect(componentInstance.findByType(components.Div).props.children).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('not render leaf', () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-shell",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Shell Layer for AliLowCodeEngine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -13,12 +13,12 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-editor-core": "1.1.6",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-workspace": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-editor-core": "1.1.7",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.7",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"@alilc/lowcode-workspace": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
|
||||
@ -47,11 +47,11 @@ export class Setters implements IPublicApiSetters {
|
||||
* 获取已注册的所有 settersMap
|
||||
* @returns
|
||||
*/
|
||||
getSettersMap(): Map<string, IPublicTypeRegisteredSetter & {
|
||||
getSettersMap = (): Map<string, IPublicTypeRegisteredSetter & {
|
||||
type: string;
|
||||
}> {
|
||||
}> => {
|
||||
return this[settersSymbol].getSettersMap();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 注册一个 setter
|
||||
|
||||
@ -13,7 +13,13 @@ export class ActiveTracker implements IPublicModelActiveTracker {
|
||||
}
|
||||
|
||||
get target() {
|
||||
const { node: innerNode, detail, instance } = this[activeTrackerSymbol]._target;
|
||||
const _target = this[activeTrackerSymbol]._target;
|
||||
|
||||
if (!_target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { node: innerNode, detail, instance } = _target;
|
||||
const publicNode = ShellNode.create(innerNode);
|
||||
return {
|
||||
node: publicNode!,
|
||||
|
||||
@ -43,6 +43,10 @@ export class Window implements IPublicModelWindow {
|
||||
return await this[windowSymbol].save();
|
||||
}
|
||||
|
||||
onSave(fn: () => void) {
|
||||
return this[windowSymbol].onSave(fn);
|
||||
}
|
||||
|
||||
get currentEditorView() {
|
||||
if (this[windowSymbol].editorView) {
|
||||
return new EditorView(this[windowSymbol].editorView).toProxy() as any;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-types",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Types for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
|
||||
@ -6,7 +6,7 @@ export interface IPublicModelActiveTracker {
|
||||
/**
|
||||
* @since 1.1.7
|
||||
*/
|
||||
target: IPublicTypeActiveTarget;
|
||||
target: IPublicTypeActiveTarget | null;
|
||||
|
||||
onChange(fn: (target: IPublicTypeActiveTarget) => void): () => void;
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import {
|
||||
IPublicApiWorkspace,
|
||||
} from '../api';
|
||||
import { IPublicEnumPluginRegisterLevel } from '../enum';
|
||||
import { IPublicModelEngineConfig, IPublicModelEditorView } from './';
|
||||
import { IPublicModelEngineConfig, IPublicModelWindow } from './';
|
||||
|
||||
export interface IPublicModelPluginContext {
|
||||
|
||||
@ -108,7 +108,7 @@ export interface IPublicModelPluginContext {
|
||||
*/
|
||||
get registerLevel(): IPublicEnumPluginRegisterLevel;
|
||||
|
||||
get editorWindow(): IPublicModelEditorView;
|
||||
get editorWindow(): IPublicModelWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -42,4 +42,10 @@ export interface IPublicModelWindow<
|
||||
|
||||
/** 窗口视图变更事件 */
|
||||
onChangeViewType(fn: (viewName: string) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 窗口视图保存事件
|
||||
* @since 1.1.7
|
||||
*/
|
||||
onSave(fn: () => void): IPublicTypeDisposable;
|
||||
}
|
||||
@ -90,3 +90,4 @@ export * from './editor-view-config';
|
||||
export * from './hotkey-callback-config';
|
||||
export * from './hotkey-callbacks';
|
||||
export * from './scrollable';
|
||||
export * from './simulator-renderer';
|
||||
|
||||
@ -195,6 +195,9 @@ export interface IPublicTypeCallbacks {
|
||||
onMoveHook?: (currentNode: IPublicModelNode) => boolean;
|
||||
// thinkof 限制性拖拽
|
||||
onHoverHook?: (currentNode: IPublicModelNode) => boolean;
|
||||
|
||||
/** 选中 hook,如果返回值是 false,可以控制组件不可被选中 */
|
||||
onSelectHook?: (currentNode: IPublicModelNode) => boolean;
|
||||
onChildMoveHook?: (childNode: IPublicModelNode, currentNode: IPublicModelNode) => boolean;
|
||||
|
||||
// events
|
||||
|
||||
32
packages/types/src/shell/type/simulator-renderer.ts
Normal file
32
packages/types/src/shell/type/simulator-renderer.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { Asset } from '../../assets';
|
||||
import {
|
||||
IPublicTypeNodeInstance,
|
||||
IPublicTypeProjectSchema,
|
||||
IPublicTypeComponentSchema,
|
||||
} from './';
|
||||
|
||||
export interface IPublicTypeSimulatorRenderer<Component, ComponentInstance> {
|
||||
readonly isSimulatorRenderer: true;
|
||||
autoRepaintNode?: boolean;
|
||||
components: Record<string, Component>;
|
||||
rerender: () => void;
|
||||
createComponent(
|
||||
schema: IPublicTypeProjectSchema<IPublicTypeComponentSchema>,
|
||||
): Component | null;
|
||||
getComponent(componentName: string): Component;
|
||||
getClosestNodeInstance(
|
||||
from: ComponentInstance,
|
||||
nodeId?: string,
|
||||
): IPublicTypeNodeInstance<ComponentInstance> | null;
|
||||
findDOMNodes(instance: ComponentInstance): Array<Element | Text> | null;
|
||||
getClientRects(element: Element | Text): DOMRect[];
|
||||
setNativeSelection(enableFlag: boolean): void;
|
||||
setDraggingState(state: boolean): void;
|
||||
setCopyState(state: boolean): void;
|
||||
loadAsyncLibrary(asyncMap: { [index: string]: any }): void;
|
||||
clearState(): void;
|
||||
stopAutoRepaintNode(): void;
|
||||
enableAutoRepaintNode(): void;
|
||||
run(): void;
|
||||
load(asset: Asset): Promise<any>;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-utils",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Utils for Ali lowCode engine",
|
||||
"files": [
|
||||
"lib",
|
||||
@ -14,7 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"lodash": "^4.17.21",
|
||||
"mobx": "^6.3.0",
|
||||
"react": "^16"
|
||||
|
||||
@ -81,6 +81,7 @@ const stageList = [
|
||||
'init',
|
||||
'upgrade',
|
||||
];
|
||||
|
||||
/**
|
||||
* 兼容原来的数字版本的枚举对象
|
||||
* @param stage
|
||||
@ -108,4 +109,18 @@ export function deprecate(fail: any, message: string, alterative?: string) {
|
||||
|
||||
export function isRegExp(obj: any): obj is RegExp {
|
||||
return obj && obj.test && obj.exec && obj.compile;
|
||||
}
|
||||
|
||||
/**
|
||||
* The prop supportVariable SHOULD take precedence over default global supportVariable.
|
||||
* @param propSupportVariable prop supportVariable
|
||||
* @param globalSupportVariable global supportVariable
|
||||
* @returns
|
||||
*/
|
||||
export function shouldUseVariableSetter(
|
||||
propSupportVariable: boolean | undefined,
|
||||
globalSupportVariable: boolean,
|
||||
) {
|
||||
if (propSupportVariable === false) return false;
|
||||
return propSupportVariable || globalSupportVariable;
|
||||
}
|
||||
9
packages/utils/test/src/misc.test.ts
Normal file
9
packages/utils/test/src/misc.test.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { shouldUseVariableSetter } from '../../src/misc';
|
||||
|
||||
it('shouldUseVariableSetter', () => {
|
||||
expect(shouldUseVariableSetter(false, true)).toBeFalsy();
|
||||
expect(shouldUseVariableSetter(true, true)).toBeTruthy();
|
||||
expect(shouldUseVariableSetter(true, false)).toBeTruthy();
|
||||
expect(shouldUseVariableSetter(undefined, false)).toBeFalsy();
|
||||
expect(shouldUseVariableSetter(undefined, true)).toBeTruthy();
|
||||
});
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-workspace",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"description": "Shell Layer for AliLowCodeEngine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,11 +15,11 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.6",
|
||||
"@alilc/lowcode-editor-core": "1.1.6",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.6",
|
||||
"@alilc/lowcode-types": "1.1.6",
|
||||
"@alilc/lowcode-utils": "1.1.6",
|
||||
"@alilc/lowcode-designer": "1.1.7",
|
||||
"@alilc/lowcode-editor-core": "1.1.7",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.7",
|
||||
"@alilc/lowcode-types": "1.1.7",
|
||||
"@alilc/lowcode-utils": "1.1.7",
|
||||
"classnames": "^2.2.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
|
||||
@ -77,7 +77,18 @@ export class EditorWindow implements IEditorWindow {
|
||||
const saveResult = await this.editorViews.get(name)?.save();
|
||||
value[name] = saveResult;
|
||||
}
|
||||
return await this.resource.save(value);
|
||||
const result = await this.resource.save(value);
|
||||
this.emitter.emit('handle.save');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
onSave(fn: () => void) {
|
||||
this.emitter.on('handle.save', fn);
|
||||
|
||||
return () => {
|
||||
this.emitter.off('handle.save', fn);
|
||||
};
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user