Merge branch 'develop' into release/1.1.0-beta

This commit is contained in:
JackLian 2023-01-12 18:56:32 +08:00
commit 2220988fdc
83 changed files with 1101 additions and 485 deletions

View File

@ -39,7 +39,7 @@ module.exports = {
type: 'category',
label: '扩展编辑器',
collapsed: false,
items: getDocsFromDir('guide/expand/editor'),
items: getDocsFromDir('guide/expand/editor', [{ dir: 'guide/expand/editor/parts', label: 'Parts·造物' }]),
},
{
type: 'category',

View File

@ -42,7 +42,7 @@ get dragon(): IPublicModelDragon | null;
get activeTracker(): IPublicModelActiveTracker | null;
```
## 方法签名
## 方法
### createLocation
创建一个文档插入位置对象,该对象用来描述一个即将插入的节点在文档中的位置

View File

@ -20,7 +20,7 @@ sidebar_position: 11
#### skeletonCabin
面板扩展相关,详见下方方法签名
## 方法签名
## 方法
### utils
#### isNodeSchema
是否为合法的 schema 结构

View File

@ -10,7 +10,7 @@ sidebar_position: 8
## 模块简介
配置模块,负责配置的读、写等操作。
## 方法签名
## 方法
### get
获取指定 key 的值

View File

@ -10,7 +10,7 @@ sidebar_position: 7
## 模块简介
负责事件处理 API支持自定义监听事件、触发事件。
## 方法签名
## 方法
### on
监听事件

View File

@ -9,7 +9,7 @@ sidebar_position: 5
## 模块简介
绑定快捷键 API可以自定义项目快捷键使用。
## 方法签名
## 方法
### bind
绑定快捷键

View File

@ -8,7 +8,7 @@ sidebar_position: 10
## 模块简介
提供 init 等方法
## 方法签名
## 方法
#### 1. init
初始化引擎

View File

@ -12,7 +12,7 @@ sidebar_position: 9
> 注:日志级别可以通过 url query 动态调整,详见下方[查看示例](#查看示例)。<br/>
> 参考 [zen-logger](https://web.npm.alibaba-inc.com/package/zen-logger) 实现进行封装
## 方法签名
## 方法
日志记录方法

View File

@ -22,7 +22,7 @@ get componentsMap(): { [key: string]: IPublicTypeNpmInfo | ComponentType<any> |
```
相关类型:[IPublicTypeNpmInfo](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/npm-info.ts)
## 方法签名
## 方法
### 资产包
#### setAssets

View File

@ -9,7 +9,7 @@ sidebar_position: 6
画布节点悬停模型
## 变量
## 属性
### current
@ -28,7 +28,7 @@ sidebar_position: 6
`@type {boolean}`
## 方法签名
## 方法
### capture
hover 指定节点
@ -77,7 +77,7 @@ hover 节点变化事件
* set callback which will be called when hovering object changed.
* @since v1.1.0
*/
onDetectingChange(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable;
onDetectingChange(fn: (node: IPublicModelNode | null) => void): IPublicTypeDisposable;
```
相关类型:

View File

@ -9,7 +9,7 @@ sidebar_position: 0
文档模型
## 变量
## 属性
### id
@ -95,7 +95,7 @@ sidebar_position: 0
**@since v1.1.0**
## 方法签名
## 方法
### getNodeById
根据 nodeId 返回 [Node](./node) 实例

View File

@ -18,7 +18,7 @@ import { IPublicModelDragon } from '@alilc/lowcode-types';
**@since** v1.1.0
## 变量
## 属性
### dragging
@ -31,7 +31,7 @@ import { IPublicModelDragon } from '@alilc/lowcode-types';
get dragging(): boolean;
```
## 方法签名
## 方法
### onDragstart

View File

@ -11,7 +11,7 @@ sidebar_position: 13
拖拽放置位置模型
## 变量
## 属性
### target
@ -37,7 +37,7 @@ sidebar_position: 13
相关类型:[IPublicModelLocateEvent](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/location-event.ts)
## 方法签名
## 方法
### clone

View File

@ -9,7 +9,7 @@ sidebar_position: 5
操作历史记录模型
## 方法签名
## 方法
### go
历史记录跳转到指定位置

View File

@ -9,40 +9,86 @@ sidebar_position: 7
模态节点管理器模型
## 方法签名
## 方法
### setNodes
setNodes()
设置模态节点,触发内部事件
```typescript
/**
* 设置模态节点,触发内部事件
* set modal nodes, trigger internal events
*/
setNodes(): void;
```
### getModalNodes
getModalNodes()
获取模态节点(们)
```typescript
/**
* 获取模态节点(们)
* get modal nodes
*/
getModalNodes(): IPublicModelNode[];
```
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
### getVisibleModalNode
getVisibleModalNode()
获取当前可见的模态节点
```typescript
/**
* 获取当前可见的模态节点
* get current visible modal node
*/
getVisibleModalNode(): IPublicModelNode | null;
```
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
### hideModalNodes
hideModalNodes()
隐藏模态节点(们)
```typescript
/**
* 隐藏模态节点(们)
* hide modal nodes
*/
hideModalNodes(): void;
```
### setVisible
setVisible(node: Node)
设置指定节点为可见态
```typescript
/**
* 设置指定节点为可见态
* set specfic model node as visible
* @param node Node
*/
setVisible(node: IPublicModelNode): void;
```
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
### setInvisible
setInvisible(node: Node)
设置指定节点为不可见态
```typescript
/**
* 设置指定节点为不可见态
* set specfic model node as invisible
* @param node Node
*/
setInvisible(node: IPublicModelNode): void;
```
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)

View File

@ -8,7 +8,7 @@ sidebar_position: 2
## 基本介绍
节点孩子模型
## 变量
## 属性
### owner
返回当前 children 实例所属的节点实例
@ -41,7 +41,7 @@ children 内的节点实例数
**@since v1.1.0**
## 方法签名
## 方法
### delete
删除指定节点

View File

@ -9,7 +9,7 @@ sidebar_position: 1
节点模型
## 变量
## 属性
### id
节点 id
@ -263,7 +263,7 @@ sidebar_position: 1
**@since v1.1.0**
## 方法签名
## 方法
### getRect

View File

@ -17,38 +17,24 @@ sidebar_position: 12
插件名字
```typescript
get name(): string;
```
`@type {string}`
### dep
插件依赖
```typescript
get dep(): string[];
```
`@type {string[]}`
### disabled
插件是否禁用
```typescript
get disabled(): boolean
set disabled(disabled: boolean): void;
```
`@type {boolean}`
### meta
插件 meta 信息
```typescript
get meta(): IPublicTypePluginMeta
```
- [IPublicTypePluginMeta](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/plugin-meta.ts)
`@type {IPublicTypePluginMeta}`
相关类型:[IPublicTypePluginMeta](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/plugin-meta.ts)

View File

@ -9,7 +9,7 @@ sidebar_position: 3
属性模型
## 变量
## 属性
### id
@ -46,7 +46,7 @@ key 值
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
## 方法签名
## 方法
### setValue

View File

@ -9,7 +9,7 @@ sidebar_position: 4
属性集模型
## 变量
## 属性
### id
id
@ -32,7 +32,7 @@ id
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
## 方法签名
## 方法
### getProp
获取指定 path 的属性模型实例

View File

@ -7,7 +7,7 @@ sidebar_position: 12
> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/resource.ts)<br/>
> **@since** v1.1.0
## 变量
## 属性
### title

View File

@ -9,7 +9,7 @@ sidebar_position: 6
画布节点选中模型
## 变量
## 属性
### selected
返回选中的节点 id
@ -25,7 +25,7 @@ sidebar_position: 6
**@since v1.1.0**
## 方法签名
## 方法
### select
选中指定节点(覆盖方式)

View File

@ -12,7 +12,7 @@ sidebar_position: 12
低代码设计器窗口模型
## 变量
## 属性
### id
@ -38,7 +38,7 @@ sidebar_position: 12
关联模型 [IPublicModelResource](./resource)
## 方法签名
## 方法
### importSchema
当前窗口导入 schema, 会调用当前窗口对应资源的 import 钩子

View File

@ -8,7 +8,7 @@ sidebar_position: 4
## 模块简介
插件管理器,提供编排模块中管理插件的能力。
## 方法签名
## 方法
### register
注册插件

View File

@ -69,7 +69,7 @@ get simulatorHost(): IPublicApiSimulatorHost | null;
相关类型:[IPublicApiSimulatorHost](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/simulator-host.ts)
## 方法签名
## 方法
### openDocument
打开一个 document

View File

@ -8,7 +8,7 @@ sidebar_position: 6
## 模块简介
负责注册设置器、管理设置器的 API。注册自定义设置器之后可以在物料中进行使用。
## 方法签名
## 方法
### getSetter
获取指定 setter

View File

@ -135,7 +135,7 @@ skeleton.add({
});
```
## 方法签名
## 方法
### add

View File

@ -57,7 +57,7 @@ get resourceList(): IPublicModelResource;
关联模型 [IPublicModelResource](./model/resource)
## 方法签名
## 方法
### registerResourceType
注册资源

View File

@ -4,4 +4,4 @@ sidebar_position: 15
tags: [FAQ]
---
你可以通过在线工具「Parts 造物」生产物料描述协议,然后使用到你的项目中去。
文档地址:[利用 Parts 造物快速使用 react 组件](/site/docs/guide/expand/editor/partsIntro)
文档地址:[利用 Parts 造物快速使用 react 组件](/site/docs/guide/expand/editor/parts/partsIntro)

View File

@ -1,6 +1,6 @@
---
title: 低代码生态脚手架 & 调试机制
sidebar_position: 7
sidebar_position: 8
---
## 脚手架简述

View File

@ -10,7 +10,7 @@ sidebar_position: 2
## 可视化生成物料描述
使用 Parts 造物平台:[使用文档](/site/docs/guide/expand/editor/partsIntro)
使用 Parts 造物平台:[使用文档](/site/docs/guide/expand/editor/parts/partsIntro)
## 自动生成物料描述

View File

@ -0,0 +1,4 @@
{
"label": "Parts 造物",
"position": 1
}

View File

@ -0,0 +1,18 @@
---
title: 介绍
sidebar_position: 1
---
## 介绍
![](https://gw.alicdn.com/imgextra/i2/O1CN01Gyq6AZ1nOENPTVXX7_!!6000000005079-2-tps-256-104.png)
「Parts·造物」是基于开源低代码引擎打造的次时代物料研发和集成工具一方面作为低代码引擎搭建低代码平台的一个样板展示开源生态下的各个组件如何集合在一起形成生产力另一方面也可以生产低代码平台所需的物料。
目前「Parts·造物」主要提供两大产品功能
1. React 组件导入低代码引擎:通过在线可视化的「物料描述」配置,任意工具开发的 React 组件都可以快速完成对低代码引擎的适配,导入到低代码引擎项目中进行使用。不必额外开发新的组件。
2. 低代码生产组件:通过低代码的形式生产组件,极低上手门槛,提供丰富的原子组件用于组合,完善的调试预览和组件生命周期控制。生产的组件既可以在低代码引擎项目中使用,也可以出码后在普通源码项目中使用。
## 联系我们
<img src="https://img.alicdn.com/imgextra/i2/O1CN01UF88Xi1jC5SZ6m4wt_!!6000000004511-2-tps-750-967.png" width="300" />

View File

@ -0,0 +1,267 @@
---
title: 资产包管理
sidebar_position: 4
---
## 介绍
通过前述介绍,相信大家已经了解如何使用「[Parts·造物](https://parts.lowcode-engine.cn/)」来将已有的 React 组件快速接入低代码引擎,以及生产低代码组件。
大家在使用的过程中,可能会希望构建出来的资产包可以后续随时访问下载,或者希望构建资产包时各个组件的版本等信息可以持久化起来并且能够多人维护。
通过「[Parts·造物](https://parts.lowcode-engine.cn/)」的 `资产包` 管理功能帮助大家解决这个问题
![image.png](https://img.alicdn.com/imgextra/i3/O1CN01Fkaznh1zWj9wYKpcH_!!6000000006722-2-tps-1702-628.png)
## 新建资产包
首先,我们在 我的资产包 tab 中点击 `新建资产包`
![image.png](https://img.alicdn.com/imgextra/i1/O1CN01qe8zfO1ilysebSfD5_!!6000000004454-2-tps-3064-1432.png)
- 填写资产包名称
- 配置资产包管理员,管理员拥有该资产包的所有权限,初始默认为资产包的创建者,还可以添加其他人作为管理员,
- 配置资产包描述 (可选)
- 点击 `确定`, 即可完成资产包的创建
接下来需要为资产包添加一个或者多个组件。
## 添加组件
第二步:新建完资产包以后,我们就可以为其添加组件了,如果是新建资产包流程,新建完成之后会自动弹出组件配置的弹窗,当然,你可可以通过点击资产包卡片的方式打开组件配置的弹窗。
![image.png](https://img.alicdn.com/imgextra/i3/O1CN01kqymdB1nkDQclPk7F_!!6000000005127-2-tps-965-261.png)
- 点击弹窗中 `添加组件` 按钮,在弹出的组件选择面板中,选中需要添加的组件并点击 `下一步`
![image.png](https://img.alicdn.com/imgextra/i1/O1CN014Baihf1r742Qi1Wel_!!6000000005583-2-tps-1856-1520.png)
- 进入组件版本以及描述协议版本选择界面,选择所需要的正确版本,点击 `安装` 即可完成一个组件的添加。
![image.png](https://img.alicdn.com/imgextra/i2/O1CN01Y7aWWi1MMPDVlidgz_!!6000000001420-2-tps-1668-1462.png)
## 构建资产包
添加完组件以后就点击 `保存并构建资产包` 进入资产包构建配置弹窗
![image.png](https://img.alicdn.com/imgextra/i4/O1CN01iZf4Ue1PlXnyKYxnK_!!6000000001881-2-tps-1288-670.png)
- `开启缓存` : 可充分利用之前的构建结果缓存来加速资产包的生成,我们会将每个组件的构建结果以 包名和版本号为 key 进行缓存。
- `任务描述` : 当前构建任务的一些描述信息。
点击 `确认` 按钮 会自动跳转到当前资产包的构建历史界面:
![image.png](https://img.alicdn.com/imgextra/i2/O1CN01krDaFc1TuTztMPssI_!!6000000002442-2-tps-1726-696.png)
构建历史界面会显示当前资产包所有的构建历史记录,表格状态栏展示了构建的状态:`成功`,`失败`,`正在运行` 三种状态,操作列可以在构建成功时复制或者下载资产包结果
## 使用资产包
你可以在 [lowcode-demo](https://github.com/alibaba/lowcode-demo) 中直接引用,可直接替换 demo 中原来的资产包文件:
例如,在 [demo-lowcode-component](https://github.com/alibaba/lowcode-demo/tree/main/demo-lowcode-component) 中,直接用你的资产包文件替换文件[assets.json](https://github.com/alibaba/lowcode-demo/blob/main/demo-lowcode-component/src/services/assets.json),即可快速使用自己的物料了。
### 在编辑器中使用资产包
在使用含有低代码组件的资产包注意 注意引擎版本必须大于等于 `1.1.0-beta.9`
然后直接替换 [lowcode-demo](https://github.com/alibaba/lowcode-demo) demo 中的 `assets.json` 文件即可。
### 在预览中使用资产包
在预览中使用资产包的整体思路是从 `资产包` 中提取并转换出 `ReactRenderer` 渲染所需要的 react 组件列表 (`components` 参数),然后将 `schema` 以及 `components` 传入到 `ReactRenderer` 中进行渲染,需要注意的是,在 `资产包` 的转换过程中,我们也需要将 `低代码组件` 转换成 react 组件,具体逻辑可以参考下 [demo-lowcode-component](https://github.com/alibaba/lowcode-demo/tree/main/demo-lowcode-component) 中 `src/parse-assets.ts` 文件的实现。
基于资产包进行预览的整体逻辑如下: [详见](https://github.com/alibaba/lowcode-demo/blob/main/demo-lowcode-component/src/preview.tsx)
```ts
import ReactDOM from 'react-dom';
import React, { useState } from 'react';
import { Loading } from '@alifd/next';
import ReactRenderer from '@alilc/lowcode-react-renderer';
import { createFetchHandler } from '@alilc/lowcode-datasource-fetch-handler';
import {
getProjectSchemaFromLocalStorage,
} from './services/mockService';
import assets from './services/assets.json';
import { parseAssets } from './parse-assets';
const getScenarioName = function () {
if (location.search) {
return new URLSearchParams(location.search.slice(1)).get('scenarioName') || 'index';
}
return 'index';
};
const SamplePreview = () => {
const [data, setData] = useState({});
async function init() {
const scenarioName = getScenarioName();
const projectSchema = getProjectSchemaFromLocalStorage(scenarioName);
const { componentsMap: componentsMapArray, componentsTree } = projectSchema;
const schema = componentsTree[0];
const componentsMap: any = {};
componentsMapArray.forEach((component: any) => {
componentsMap[component.componentName] = component;
});
// 特别提醒重点注意!!!:从资产包中解析出所有的 react 组件列表
const { components } = await parseAssets(assets);
setData({
schema,
components,
});
}
const { schema, components } = data;
if (!schema || !components) {
init();
return <Loading fullScreen />;
}
return (
<div className="lowcode-plugin-sample-preview">
<ReactRenderer
className="lowcode-plugin-sample-preview-content"
schema={schema}
// // 将 react 组件列表传入 ReactRenderer 进行渲染
components={components}
appHelper={{
requestHandlersMap: {
fetch: createFetchHandler(),
},
}}
/>
</div>
);
};
ReactDOM.render(<SamplePreview />, document.getElementById('ice-container'));
```
从资产包中解析 react 组件列表的逻辑如下,[详见](https://github.com/alibaba/lowcode-demo/blob/main/demo-lowcode-component/src/parse-assets.ts)
```ts
import { ComponentDescription, ComponentSchema, RemoteComponentDescription } from '@alilc/lowcode-types';
import { buildComponents, AssetsJson, AssetLoader } from '@alilc/lowcode-utils';
import ReactRenderer from '@alilc/lowcode-react-renderer';
import { injectComponents } from '@alilc/lowcode-plugin-inject';
import React, { createElement } from 'react';
export async function parseAssets(assets: AssetsJson) {
const { components: rawComponents, packages } = assets;
const libraryAsset = [];
const libraryMap = {};
const packagesMap = {};
packages.forEach(pkg => {
const { package: _package, library, urls, renderUrls, id } = pkg;
if (_package) {
libraryMap[id || _package] = library;
}
packagesMap[id || _package] = pkg;
if (renderUrls) {
libraryAsset.push(renderUrls);
} else if (urls) {
libraryAsset.push(urls);
}
});
const assetLoader = new AssetLoader();
await assetLoader.load(libraryAsset);
let newComponents = rawComponents;
if (rawComponents && rawComponents.length) {
const componentDescriptions: ComponentDescription[] = [];
const remoteComponentDescriptions: RemoteComponentDescription[] = [];
rawComponents.forEach((component: any) => {
if (!component) {
return;
}
if (component.exportName && component.url) {
remoteComponentDescriptions.push(component);
} else {
componentDescriptions.push(component);
}
});
newComponents = [...componentDescriptions];
// 如果有远程组件描述协议,则自动加载并补充到资产包中,同时出发 designer.incrementalAssetsReady 通知组件面板更新数据
if (remoteComponentDescriptions && remoteComponentDescriptions.length) {
await Promise.all(
remoteComponentDescriptions.map(async (component: any) => {
const { exportName, url, npm } = component;
await (new AssetLoader()).load(url);
function setAssetsComponent(component: any, extraNpmInfo: any = {}) {
const components = component.components;
if (Array.isArray(components)) {
components.forEach(d => {
newComponents = newComponents.concat({
npm: {
...npm,
...extraNpmInfo,
},
...d,
} || []);
});
return;
}
newComponents = newComponents.concat({
npm: {
...npm,
...extraNpmInfo,
},
...component.components,
} || []);
}
function setArrayAssets(value: any[], preExportName: string = '', preSubName: string = '') {
value.forEach((d: any, i: number) => {
const exportName = [preExportName, i.toString()].filter(d => !!d).join('.');
const subName = [preSubName, i.toString()].filter(d => !!d).join('.');
Array.isArray(d) ? setArrayAssets(d, exportName, subName) : setAssetsComponent(d, {
exportName,
subName,
});
});
}
if (window[exportName]) {
if (Array.isArray(window[exportName])) {
setArrayAssets(window[exportName] as any);
} else {
setAssetsComponent(window[exportName] as any);
}
}
return window[exportName];
}),
);
}
}
const lowcodeComponentsArray = [];
const proCodeComponentsMap = newComponents.reduce((acc, cur) => {
if ((cur.devMode || '').toLowerCase() === 'lowcode') {
lowcodeComponentsArray.push(cur);
} else {
acc[cur.componentName] = {
...(cur.reference || cur.npm),
componentName: cur.componentName,
};
}
return acc;
}, {})
function genLowCodeComponentsMap(components) {
const lowcodeComponentsMap = {};
lowcodeComponentsArray.forEach((lowcode) => {
const id = lowcode.reference?.id;
const schema = packagesMap[id]?.schema;
const comp = genLowcodeComp(schema, {...components, ...lowcodeComponentsMap});
lowcodeComponentsMap[lowcode.componentName] = comp;
});
return lowcodeComponentsMap;
}
let components = await injectComponents(buildComponents(libraryMap, proCodeComponentsMap));
const lowCodeComponents = genLowCodeComponentsMap(components);
return {
components: { ...components, ...lowCodeComponents }
}
}
function genLowcodeComp(schema: ComponentSchema, components: any) {
return class LowcodeComp extends React.Component {
render(): React.ReactNode {
return createElement(ReactRenderer, {
...this.props,
schema,
components,
designMode: '',
});
}
};
}
```
## 联系我们
<img src="https://img.alicdn.com/imgextra/i2/O1CN01UF88Xi1jC5SZ6m4wt_!!6000000004511-2-tps-750-967.png" width="300" />

View File

@ -0,0 +1,92 @@
---
title: 低代码组件
sidebar_position: 2
---
## 什么是低代码组件
我们先了解一下什么是低代码组件,为什么要用低代码组件。
低代码组件是通过可视化的方式生产的组件,这些组件既可以用于低代码搭建体系,也可以用于 ProCode 开发体系(后续迭代)。
那么为什么我们要使用低代码的形式来开发组件:
* <font color="red"><b>首先</b></font><b>轻快</b>,低代码组件只需通过浏览器秒级完成初始化工作,不需要 ProCode 繁重的环境准备;<b>环境一致(低代码环境)</b>,同时能够保证物料的开发环境和真实的运行环境是一致的,不会存在开发和运行环境不一致的问题。
* <font color="red"><b>其次</b></font><b>通用能力可视化方式抽象,提升研发效能</b>,比如获取远程数据、视图开发、依赖管理、生命周期、事件绑定等功能。
<font color="red">低代码组件不是用来替代 ProCode 的开发方式</font>,而是让开发者可以从 ProCode 中重复的工作脱离出来,抽象更多业务垂直的能力,从而起到提效的作用。
## 创建组件
环境准备:我们可以通过 Parts 提供的通用[低代码组件开发环境](https://parts.lowcode-engine.cn/material#/)开发。
点击开发新组件 --> 填写组件标题 --> 填写组件名称 --> 点击确定,完成组件创建工作。
![](https://img.alicdn.com/imgextra/i2/O1CN01OTQRew25y6WxuONIx_!!6000000007594-2-tps-3396-1696.png)
## 组件开发
一张图速览低代码组件开发的功能模块,其中大部分功能可以参考[低代码引擎文档](https://lowcode-engine.cn/site/docs/guide/quickStart/intro)。
![](https://img.alicdn.com/imgextra/i1/O1CN01gx96E121qzv4smV2v_!!6000000007037-2-tps-3456-1930.png)
### 依赖管理
依赖管理用于管理低代码组件本身的依赖(类似于 dependencies。步骤点击添加组件 --> 选择安装的组件 --> 保存并构建 (需要等待几分钟构建)。
![](https://img.alicdn.com/imgextra/i4/O1CN01wC9JPK1J9dKLca9wK_!!6000000000986-2-tps-1438-819.png)
### 属性定义
用于定义组件接收外部传入的 propTypes组件内部可以通过<font color="red">this.props.${属性名称}</font>的方式获取属性值。
属性定义前建议先阅读 [物料描述详解](https://lowcode-engine.cn/site/docs/guide/expand/editor/metaSpec)、[预置设置器](https://lowcode-engine.cn/site/docs/guide/appendix/setters)。
![](https://img.alicdn.com/imgextra/i2/O1CN01wesIJA1nL1eSPrk7U_!!6000000005072-2-tps-1438-821.png)
![](https://img.alicdn.com/imgextra/i3/O1CN01FZIRwv1es9lGplgIB_!!6000000003926-2-tps-1438-821.png)
### 生命周期
低代码组件的开发支持 componentDidMount、componentDidUpdate、componentDidCatch、componentWillUnmount 几个生命周期
![](https://img.alicdn.com/imgextra/i4/O1CN010bnrxJ1oLlujlfFqj_!!6000000005209-2-tps-1438-819.png)
### 组件调试
我们提供了一套线上实时调试的方案,只需点击右上角的调试按钮,就能自动创建一个低代码应用,在这个应用中可以实时调试当前的低代码组件。
![](https://img.alicdn.com/imgextra/i2/O1CN01Tk96vp1xrDeNeIUJD_!!6000000006496-2-tps-1438-820.png)
在低代码应用中使用,组件面板 --> 低代码组件,找到对应的低代码组件拖入画布即可。
![](https://img.alicdn.com/imgextra/i2/O1CN01oGHLea1lzDAhZQQVO_!!6000000004889-2-tps-1438-819.png)
### 组件发布
同时我们提供了组件发布的功能,用于组件版本管理,点击右上角的发布按钮即可发布组件
![](https://img.alicdn.com/imgextra/i2/O1CN017suVAD1NXEC8zQgO1_!!6000000001579-2-tps-1438-821.png)
## 组件使用
组件的消费是通过资产包来管理的,详情请参考 [资产包管理](./partsassets)。
## 组件导出
开发好的低代码组件可以导出成为 React 组件,脱离低代码引擎独立使用。同时导出功能也为您的组件留出一份备份,您可以放心使用本产品的服务,而不用担心万一出现的不能服务的场景。
在物料列表页面,低代码组件会有一个导出的动作。
![](https://img.alicdn.com/imgextra/i2/O1CN016oUByO21spVHZvvw2_!!6000000007041-2-tps-1395-413.png)
点击导出后,就会开启导出低代码组件的过程。这个过程持续 10s+,导出完成后会为您自动下载对应的 zip 包。
![](https://img.alicdn.com/imgextra/i1/O1CN01lctpIo1aDcEvu75Mo_!!6000000003296-2-tps-1399-512.png)
zip 包解压后可以看到一个完整的组件脚手架工程,您可以在这个工程里继续开发调试,或者发布到合适的 npm 源中。
![](https://img.alicdn.com/imgextra/i1/O1CN010aAjsf1xYRPZBAh7d_!!6000000006455-2-tps-2154-1072.png)
注意:目前导出功能暂不支持 低代码组件嵌套。
## 联系我们
<img src="https://img.alicdn.com/imgextra/i2/O1CN01UF88Xi1jC5SZ6m4wt_!!6000000004511-2-tps-750-967.png" width="300" />

View File

@ -1,5 +1,5 @@
---
title: 利用 Parts 造物快速使用 react 组件
title: React 组件导入
sidebar_position: 3
---
## 介绍
@ -50,8 +50,6 @@ sidebar_position: 3
![image.png](https://img.alicdn.com/imgextra/i3/O1CN01klci7y1IUPflKpeVB_!!6000000000896-2-tps-1193-704.png)
#### 给组件增加物料描述
选中刚刚新增的 BlockPicker 组件,然后给它增加描述:
- 打开左侧 Setter 面板
- 按照组件的属性拖入需要 Setter 类型(如图中组件的 width 属性,拖入数字 Setter
- 各种 Setter 的介绍可以参看这篇文档:[预置设置器列表](/site/docs/guide/appendix/setters)
@ -102,31 +100,22 @@ sidebar_position: 3
- 点击确定发布完成
![image.png](https://img.alicdn.com/imgextra/i4/O1CN01uwa8RH1QDwM7FN31k_!!6000000001943-2-tps-1431-734.png)
## 资产包构建
## 资产包
第三步:物料描述发布完成后,接下来我们就需要构建出可用的资产包用于低代码应用中。
#### 资产包构建
有两种方式可以构建资产包:
- 一种是通过 [`我的资产包`] 资产包管理模块进行整个资产包生命周期的管理,当然也包括资产包的构建,可参考 [资产包管理](./partsassets)
- 一种是通过 [`我的物料`] 组件物料管理模块的 `资产包构建` 进行构建, 具体操作如下:
- 选择需要构建的组件
- 点击构建资产包按钮
- 选择刚刚的物料描述配置
- 开始构建,构建完成后你将得到一份 json 文件(里面包含了物料描述和 umd 包),就可以到项目中使用了
![image.png](https://img.alicdn.com/imgextra/i3/O1CN01Oc73aw1TH5vlJx9oj_!!6000000002356-2-tps-1431-770.png)
- 选择需要构建的组件
- 点击构建资产包按钮
- 选择刚刚的物料描述配置
- 开始构建,构建完成后你将得到一份 json 文件(里面包含了物料描述和 umd 包),就可以到项目中使用了
#### 资产包使用
详情请参考 [资产包管理](./partsassets#使用资产包)
**方式一、在 **[**lowcode-demo**](https://github.com/alibaba/lowcode-demo)**中直接引用,可直接替换 demo 中原来的资产包文件:**
## 联系我们
例如,在 basic-fusion demo 中,直接用你的资产包文件替换文件[assets.json](https://github.com/alibaba/lowcode-demo/blob/main/demo-basic-fusion/src/services/assets.json),即可快速使用自己的物料了。
**方式二、将新的资产包内容和现有的资产包内容融合:**
将上面构建完成的资产包与你项目中的[assets.json 文件](https://github.com/alibaba/lowcode-demo/blob/main/demo-basic-fusion/src/services/assets.json)合并,主要合并 packages 和 components。
- packages 中是构建好的 umd 包;
- components 中是上面配置好的[物料描述](https://lowcode-engine.cn/material),你也可以在基础上二次加工;
![image.png](https://img.alicdn.com/imgextra/i3/O1CN01m7QkDN1P7hL86mjyH_!!6000000001794-2-tps-1140-744.png)
<img src="https://img.alicdn.com/imgextra/i2/O1CN01UF88Xi1jC5SZ6m4wt_!!6000000004511-2-tps-750-967.png" width="300" />

View File

@ -2,7 +2,9 @@
title: 插件扩展 - 编排扩展
sidebar_position: 6
---
## 场景一:扩展选中节点操作项
### 增加节点操作项
![image.png](https://img.alicdn.com/imgextra/i2/O1CN01J7PrJc1S86XNDBIFQ_!!6000000002201-2-tps-1240-292.png)
@ -31,7 +33,7 @@ const addHelloAction = (ctx: IPublicModelPluginContext) => {
},
important: true,
});
}
},
};
};
addHelloAction.pluginName = 'addHelloAction';
@ -68,6 +70,7 @@ await plugins.register(removeCopyAction);
具体 API 参考:[API 文档](/site/docs/api/material#removebuiltincomponentaction)
## 实际案例
### 区块管理
- 仓库地址:[https://github.com/alibaba/lowcode-plugins](https://github.com/alibaba/lowcode-plugins)

View File

@ -2,6 +2,7 @@
title: 插件扩展 - 面板扩展
sidebar_position: 5
---
## 插件简述
插件功能赋予低代码引擎更高的灵活性,低代码引擎的生态提供了一些官方的插件,但是无法满足所有人的需求,所以提供了强大的插件定制功能。
@ -23,7 +24,7 @@ import { IPublicModelPluginContext } from '@alilc/lowcode-types';
const pluginA = (ctx: IPublicModelPluginContext, options: any) => {
return {
init() {
console.log(options.key);
console.log(options.key);
// 往引擎增加面板
ctx.skeleton.add({
// area 配置见下方说明
@ -36,9 +37,9 @@ const pluginA = (ctx: IPublicModelPluginContext, options: any) => {
},
destroy() {
console.log('我被销毁了~');
}
}
}
},
};
};
pluginA.pluginName = 'pluginA';
@ -56,6 +57,7 @@ plugins.register(pluginA, { key: 'test' });
![image.png](https://img.alicdn.com/imgextra/i3/O1CN01y05ZHC1Gix0p4nXxH_!!6000000000657-2-tps-3068-1648.png)
### 展示区域 area
#### topArea
展示在设计器的顶部区域,常见的相关区域的插件主要是:、
@ -76,6 +78,7 @@ plugins.register(pluginA, { key: 'test' });
4. JS 等代码面板。
可以发现,这个区域的面板大多数操作时是不需要同时并存的,且交互比较复杂的,需要一个更整块的区域来进行操作。
#### centerArea
画布区域,由于画布大多数是展示作用,所以一般扩展的种类比较少。常见的扩展有:
@ -106,12 +109,12 @@ PanelDock 是以面板的形式展示在设计器的左侧区域的。其中主
接入可以参考代码
```javascript
import { skeleton } from "@alilc/lowcode-engine";
import { skeleton } from '@alilc/lowcode-engine';
skeleton.add({
area: "leftArea", // 插件区域
type: "PanelDock", // 插件类型,弹出面板
name: "sourceEditor",
area: 'leftArea', // 插件区域
type: 'PanelDock', // 插件类型,弹出面板
name: 'sourceEditor',
content: SourceEditor, // 插件组件实例
props: {
align: "left",
@ -139,12 +142,12 @@ Widget 形式是直接渲染在当前编辑器的对应位置上。如 demo 中
接入可以参考代码:
```javascript
import {skeleton} from "@alilc/lowcode-engine";
import { skeleton } from '@alilc/lowcode-engine';
// 注册 logo 面板
skeleton.add({
area: "topArea",
type: "Widget",
name: "logo",
area: 'topArea',
type: 'Widget',
name: 'logo',
content: Logo, // Widget 组件实例
contentProps: { // Widget 插件 props
logo:
@ -152,7 +155,7 @@ skeleton.add({
href: "/",
},
props: {
align: "left",
align: 'left',
width: 100,
},
});
@ -163,7 +166,7 @@ skeleton.add({
一个图标的表现形式,可以用于语言切换、跳转到外部链接、打开一个 widget 等场景。
```javascript
import { skeleton } from "@alilc/lowcode-engine";
import { skeleton } from '@alilc/lowcode-engine';
skeleton.add({
area: 'leftArea',
@ -176,12 +179,12 @@ skeleton.add({
props: {
align: 'bottom',
},
onClick: function() {
onClick: function () {
// 打开外部链接
window.open('https://lowcode-engine.cn');
// 显示 widget
skeleton.showWidget('xxx');
}
},
});
```
@ -211,4 +214,4 @@ skeleton.add({
- [阿里巴巴低代码引擎项目实战 (11)-区块管理 - ICON 优化](https://www.bilibili.com/video/BV1zr4y1H7Km/)
- [阿里巴巴低代码引擎项目实战 (11)-区块管理 - 自动截图](https://www.bilibili.com/video/BV1GZ4y117VH/)
- [阿里巴巴低代码引擎项目实战 (11)-区块管理 - 样式优化](https://www.bilibili.com/video/BV1Pi4y1S7ZT/)
- [阿里低代码引擎项目实战 (12)-区块管理 (完结)-给引擎插件提个 PR](https://www.bilibili.com/video/BV1hB4y1277o/)
- [阿里低代码引擎项目实战 (12)-区块管理 (完结)-给引擎插件提个 PR](https://www.bilibili.com/video/BV1hB4y1277o/)

View File

@ -1,6 +1,6 @@
---
title: 设置器扩展
sidebar_position: 4
sidebar_position: 5
---
## 设置器简述

View File

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

View File

@ -8,9 +8,14 @@ module.exports = function getDocsFromDir(dir, cateList) {
const baseDir = path.join(__dirname, '../docs/');
const docsDir = path.join(baseDir, dir);
function isNil(value) {
return value === undefined || value === null;
}
function getMarkdownOrder(filepath) {
const data = matter(fs.readFileSync(filepath, 'utf-8')).data;
return (data || {}).sidebar_position || 100;
const { data } = matter(fs.readFileSync(filepath, 'utf-8'));
const { sidebar_position } = data || {};
return isNil(sidebar_position) ? 100 : sidebar_position;
}
const docs = glob.sync('*.md?(x)', {
@ -19,17 +24,17 @@ module.exports = function getDocsFromDir(dir, cateList) {
});
const result = docs
.filter(doc => !/^index.md(x)?$/.test(doc))
.map(doc => {
.filter((doc) => !/^index.md(x)?$/.test(doc))
.map((doc) => {
return path.join(docsDir, doc);
})
.sort((a, b) => {
const orderA = getMarkdownOrder(a);
const orderB = getMarkdownOrder(b);
return orderB - orderA;
return orderA - orderB;
})
.map(filepath => {
.map((filepath) => {
// /Users/xxx/site/docs/guide/basic/router.md => guide/basic/router
const id = path
.relative(baseDir, filepath)
@ -38,7 +43,7 @@ module.exports = function getDocsFromDir(dir, cateList) {
return id;
});
(cateList || []).forEach(item => {
(cateList || []).forEach((item) => {
const { dir, subCategory, ...otherConfig } = item;
const indexList = glob.sync('index.md?(x)', {
cwd: path.join(baseDir, dir),

View File

@ -6,7 +6,7 @@ import {
} from '@alilc/lowcode-types';
import { isNode } from '@alilc/lowcode-utils';
export interface IActiveTracker extends IPublicModelActiveTracker {
export interface IActiveTracker extends Omit< IPublicModelActiveTracker, 'track' > {
track(originalTarget: IPublicTypeActiveTarget | INode): void;
}

View File

@ -17,17 +17,16 @@ import {
IPublicTypeLocationData,
IPublicEnumTransformStage,
IPublicModelDragon,
IPublicModelActiveTracker,
IPublicModelDropLocation,
} from '@alilc/lowcode-types';
import { megreAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils';
import { Project } from '../project';
import { Node, DocumentModel, insertChildren, INode } from '../document';
import { ComponentMeta } from '../component-meta';
import { ComponentMeta, IComponentMeta } from '../component-meta';
import { INodeSelector, Component } from '../simulator';
import { Scroller } from './scroller';
import { Dragon, ILocateEvent } from './dragon';
import { ActiveTracker } from './active-tracker';
import { Dragon, IDragon, ILocateEvent } from './dragon';
import { ActiveTracker, IActiveTracker } from './active-tracker';
import { Detecting } from './detecting';
import { DropLocation } from './location';
import { OffsetObserver, createOffsetObserver } from './offset-observer';
@ -56,24 +55,49 @@ export interface DesignerProps {
onMount?: (designer: Designer) => void;
onDragstart?: (e: ILocateEvent) => void;
onDrag?: (e: ILocateEvent) => void;
onDragend?: (e: { dragObject: IPublicModelDragObject; copy: boolean }, loc?: DropLocation) => void;
onDragend?: (
e: { dragObject: IPublicModelDragObject; copy: boolean },
loc?: DropLocation,
) => void;
}
export interface IDesigner {
get dragon(): IPublicModelDragon;
get activeTracker(): IPublicModelActiveTracker;
get activeTracker(): IActiveTracker;
get componentActions(): ComponentActions;
get editor(): IPublicModelEditor;
createScroller(scrollable: IPublicModelScrollable): IPublicModelScroller;
/**
* dragon
*/
createLocation(locationData: IPublicTypeLocationData): IPublicModelDropLocation;
get componentsMap(): { [key: string]: IPublicTypeNpmInfo | Component };
loadIncrementalAssets(incrementalAssets: IPublicTypeAssetsJson): Promise<void>;
getComponentMeta(
componentName: string,
generateMetadata?: () => IPublicTypeComponentMetadata | null,
): IComponentMeta;
createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null;
getComponentMetasMap(): Map<string, IComponentMeta>;
addPropsReducer(reducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage): void;
}
export class Designer implements IDesigner {
public dragon: Dragon;
dragon: IDragon;
public viewName: string | undefined;
viewName: string | undefined;
readonly componentActions = new ComponentActions();
@ -99,7 +123,7 @@ export class Designer implements IDesigner {
private oobxList: OffsetObserver[] = [];
@obx.ref private _componentMetasMap = new Map<string, ComponentMeta>();
@obx.ref private _componentMetasMap = new Map<string, IComponentMeta>();
@obx.ref private _simulatorComponent?: ComponentType<any>;
@ -483,7 +507,7 @@ export class Designer implements IDesigner {
metas.forEach((data) => this.createComponentMeta(data));
}
createComponentMeta(data: IPublicTypeComponentMetadata): ComponentMeta | null {
createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null {
const key = data.componentName;
if (!key) {
return null;
@ -515,7 +539,7 @@ export class Designer implements IDesigner {
getComponentMeta(
componentName: string,
generateMetadata?: () => IPublicTypeComponentMetadata | null,
) {
): IComponentMeta {
if (this._componentMetasMap.has(componentName)) {
return this._componentMetasMap.get(componentName)!;
}

View File

@ -1,14 +1,18 @@
import { makeObservable, obx, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
import { IPublicModelDetecting, IPublicModelNode, IPublicModelDocumentModel } from '@alilc/lowcode-types';
import { IPublicModelDetecting } from '@alilc/lowcode-types';
import { IDocumentModel } from '../document/document-model';
import { INode } from '../document/node/node';
const DETECTING_CHANGE_EVENT = 'detectingChange';
export interface IDetecting extends Omit< IPublicModelDetecting, 'capture' | 'release' | 'leave' > {
capture(node: IPublicModelNode | null): void;
capture(node: INode | null): void;
release(node: IPublicModelNode | null): void;
release(node: INode | null): void;
leave(document: IPublicModelDocumentModel | undefined): void;
leave(document: IDocumentModel | undefined): void;
get current(): INode | null;
}
export class Detecting implements IDetecting {
@ -31,7 +35,7 @@ export class Detecting implements IDetecting {
@obx.ref xRayMode = false;
@obx.ref private _current: IPublicModelNode | null = null;
@obx.ref private _current: INode | null = null;
private emitter: IEventBus = createModuleEventBus('Detecting');
@ -43,27 +47,27 @@ export class Detecting implements IDetecting {
return this._current;
}
capture(node: IPublicModelNode | null) {
capture(node: INode | null) {
if (this._current !== node) {
this._current = node;
this.emitter.emit(DETECTING_CHANGE_EVENT, this.current);
}
}
release(node: IPublicModelNode | null) {
release(node: INode | null) {
if (this._current === node) {
this._current = null;
this.emitter.emit(DETECTING_CHANGE_EVENT, this.current);
}
}
leave(document: IPublicModelDocumentModel | undefined) {
leave(document: IDocumentModel | undefined) {
if (this.current && this.current.document === document) {
this._current = null;
}
}
onDetectingChange(fn: (node: IPublicModelNode) => void) {
onDetectingChange(fn: (node: INode) => void) {
this.emitter.on(DETECTING_CHANGE_EVENT, fn);
return () => {
this.emitter.off(DETECTING_CHANGE_EVENT, fn);

View File

@ -9,21 +9,18 @@ import {
IPublicTypeDragNodeDataObject,
IPublicModelDocumentModel,
IPublicModelHistory,
IPublicModelModalNodesManager,
IPublicModelNode,
IPublicApiProject,
IPublicModelDropLocation,
IPublicEnumTransformStage,
IPublicTypeOnChangeOptions,
} from '@alilc/lowcode-types';
import { Project } from '../project';
import { IProject, Project } from '../project';
import { ISimulatorHost } from '../simulator';
import { ComponentMeta } from '../component-meta';
import { IDropLocation, Designer } from '../designer';
import { IDropLocation, Designer, IHistory } from '../designer';
import { Node, insertChildren, insertChild, isNode, RootNode, INode } from './node/node';
import { Selection, ISelection } from './selection';
import { History } from './history';
import { ModalNodesManager } from './node';
import { IModalNodesManager, ModalNodesManager } from './node';
import { uniqueId, isPlainObject, compatStage, isJSExpression, isDOMText, isNodeSchema, isDragNodeObject, isDragNodeDataObject } from '@alilc/lowcode-utils';
import { EDITOR_EVENT } from '../types';
@ -44,17 +41,31 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'select
*/
readonly selection: ISelection;
readonly project: IProject;
/**
*
*/
readonly modalNodesManager: IModalNodesManager;
/**
* id
*/
getNode(id: string): INode | null;
getHistory(): IHistory;
get focusNode(): INode | null;
get rootNode(): INode | null;
}
export class DocumentModel implements IDocumentModel {
/**
* Page/Component/Block
*/
rootNode: RootNode | null;
rootNode: INode | null;
/**
*
@ -74,11 +85,11 @@ export class DocumentModel implements IDocumentModel {
/**
*
*/
readonly modalNodesManager: IPublicModelModalNodesManager;
readonly modalNodesManager: IModalNodesManager;
private _nodesMap = new Map<string, IPublicModelNode>();
readonly project: IPublicApiProject;
readonly project: IProject;
readonly designer: Designer;
@ -114,7 +125,7 @@ export class DocumentModel implements IDocumentModel {
this.rootNode?.getExtraProp('fileName', true)?.setValue(fileName);
}
get focusNode() {
get focusNode(): INode {
if (this._drillDownNode) {
return this._drillDownNode;
}
@ -147,7 +158,7 @@ export class DocumentModel implements IDocumentModel {
@obx.ref private _dropLocation: IDropLocation | null = null;
set dropLocation(loc: IPublicModelDropLocation | null) {
set dropLocation(loc: IDropLocation | null) {
this._dropLocation = loc;
// pub event
this.designer.editor.eventBus.emit(
@ -626,7 +637,7 @@ export class DocumentModel implements IDocumentModel {
return data;
}
getHistory(): History {
getHistory(): IHistory {
return this.history;
}
@ -753,7 +764,7 @@ export class DocumentModel implements IDocumentModel {
}));
}
onNodeCreate(func: (node: Node) => void) {
onNodeCreate(func: (node: INode) => void) {
const wrappedFunc = wrapWithEventSwitch(func);
this.emitter.on('nodecreate', wrappedFunc);
return () => {
@ -761,7 +772,7 @@ export class DocumentModel implements IDocumentModel {
};
}
onNodeDestroy(func: (node: Node) => void) {
onNodeDestroy(func: (node: INode) => void) {
const wrappedFunc = wrapWithEventSwitch(func);
this.emitter.on('nodedestroy', wrappedFunc);
return () => {

View File

@ -193,7 +193,7 @@ export class History<T = IPublicTypeNodeSchema> implements IHistory {
return this.onStateChange(func);
}
onStateChange(func: () => any) {
onStateChange(func: () => any): () => void {
this.emitter.on('statechange', func);
return () => {
this.emitter.removeListener('statechange', func);
@ -208,7 +208,8 @@ export class History<T = IPublicTypeNodeSchema> implements IHistory {
onChangeCursor(func: () => any): () => void {
return this.onCursor(func);
}
onCursor(func: () => any) {
onCursor(func: () => any): () => void {
this.emitter.on('cursor', func);
return () => {
this.emitter.removeListener('cursor', func);

View File

@ -1,15 +1,15 @@
import { Node } from './node';
import { INode, Node } from './node';
import { DocumentModel } from '../document-model';
import { IPublicModelModalNodesManager } from '@alilc/lowcode-types';
import { createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core';
export function getModalNodes(node: Node) {
export function getModalNodes(node: INode | Node) {
if (!node) return [];
let nodes: any = [];
if (node.componentMeta.isModal) {
nodes.push(node);
}
const children = node.getChildren();
const { children } = node;
if (children) {
children.forEach((child) => {
nodes = nodes.concat(getModalNodes(child));
@ -20,14 +20,17 @@ export function getModalNodes(node: Node) {
export interface IModalNodesManager extends IPublicModelModalNodesManager {
getModalNodes(): INode[];
getVisibleModalNode(): INode | null;
}
export class ModalNodesManager implements IModalNodesManager {
public willDestroy: any;
willDestroy: any;
private page: DocumentModel;
private modalNodes: Node[];
private modalNodes: INode[];
private nodeRemoveEvents: any;
@ -45,26 +48,27 @@ export class ModalNodesManager implements IModalNodesManager {
];
}
getModalNodes() {
getModalNodes(): INode[] {
return this.modalNodes;
}
getVisibleModalNode() {
return this.getModalNodes().find((node: Node) => node.getVisible());
getVisibleModalNode(): INode | null {
const visibleNode = this.getModalNodes().find((node: INode) => node.getVisible());
return visibleNode || null;
}
hideModalNodes() {
this.modalNodes.forEach((node: Node) => {
this.modalNodes.forEach((node: INode) => {
node.setVisible(false);
});
}
setVisible(node: Node) {
setVisible(node: INode) {
this.hideModalNodes();
node.setVisible(true);
}
setInvisible(node: Node) {
setInvisible(node: INode) {
node.setVisible(false);
}
@ -82,7 +86,7 @@ export class ModalNodesManager implements IModalNodesManager {
};
}
private addNode(node: Node) {
private addNode(node: INode) {
if (node.componentMeta.isModal) {
this.hideModalNodes();
this.modalNodes.push(node);
@ -92,7 +96,7 @@ export class ModalNodesManager implements IModalNodesManager {
}
}
private removeNode(node: Node) {
private removeNode(node: INode) {
if (node.componentMeta.isModal) {
const index = this.modalNodes.indexOf(node);
if (index >= 0) {
@ -106,24 +110,24 @@ export class ModalNodesManager implements IModalNodesManager {
}
}
private addNodeEvent(node: Node) {
this.nodeRemoveEvents[node.getId()] =
private addNodeEvent(node: INode) {
this.nodeRemoveEvents[node.id] =
node.onVisibleChange(() => {
this.emitter.emit('visibleChange');
});
}
private removeNodeEvent(node: Node) {
if (this.nodeRemoveEvents[node.getId()]) {
this.nodeRemoveEvents[node.getId()]();
delete this.nodeRemoveEvents[node.getId()];
private removeNodeEvent(node: INode) {
if (this.nodeRemoveEvents[node.id]) {
this.nodeRemoveEvents[node.id]();
delete this.nodeRemoveEvents[node.id];
}
}
setNodes() {
const nodes = getModalNodes(this.page.getRoot()!);
const nodes = getModalNodes(this.page.rootNode!);
this.modalNodes = nodes;
this.modalNodes.forEach((node: Node) => {
this.modalNodes.forEach((node: INode) => {
this.addNodeEvent(node);
});

View File

@ -11,7 +11,10 @@ export interface IOnChangeOptions {
}
export interface INodeChildren extends Omit<IPublicModelNodeChildren, 'forEach' | 'map' | 'every' | 'some' | 'filter' | 'find' | 'reduce' | 'mergeChildren' > {
get owner(): INode;
unlinkChild(node: INode): void;
/**
*
*/
@ -57,6 +60,11 @@ export interface INodeChildren extends Omit<IPublicModelNodeChildren, 'forEach'
sorter: (firstNode: INode, secondNode: INode) => number,
): any;
/**
*
*/
get(index: number): INode | null;
/** overriding methods end */
}
export class NodeChildren implements INodeChildren {
@ -64,6 +72,31 @@ export class NodeChildren implements INodeChildren {
private emitter: IEventBus = createModuleEventBus('NodeChildren');
/**
*
*/
@computed get size(): number {
return this.children.length;
}
get isEmptyNode(): boolean {
return this.size < 1;
}
get notEmptyNode(): boolean {
return this.size > 0;
}
@computed get length(): number {
return this.children.length;
}
private purged = false;
get [Symbol.toStringTag]() {
// 保证向前兼容性
return 'Array';
}
constructor(
readonly owner: INode,
data: IPublicTypeNodeData | IPublicTypeNodeData[],
@ -130,13 +163,6 @@ export class NodeChildren implements INodeChildren {
return this.children.concat(nodes);
}
/**
*
*/
@computed get size(): number {
return this.children.length;
}
/**
*
*/
@ -144,24 +170,10 @@ export class NodeChildren implements INodeChildren {
return this.isEmptyNode;
}
get isEmptyNode(): boolean {
return this.size < 1;
}
notEmpty() {
return this.notEmptyNode;
}
get notEmptyNode(): boolean {
return this.size > 0;
}
@computed get length(): number {
return this.children.length;
}
private purged = false;
/**
*
*/
@ -483,11 +495,6 @@ export class NodeChildren implements INodeChildren {
};
}
get [Symbol.toStringTag]() {
// 保证向前兼容性
return 'Array';
}
private reportModified(node: INode, owner: INode, options = {}) {
if (!node) {
return;

View File

@ -18,11 +18,11 @@ import {
} from '@alilc/lowcode-types';
import { compatStage, isDOMText, isJSExpression } from '@alilc/lowcode-utils';
import { SettingTopEntry } from '@alilc/lowcode-designer';
import { Props, getConvertedExtraKey } from './props/props';
import { Props, getConvertedExtraKey, IProps } from './props/props';
import { DocumentModel, IDocumentModel } from '../document-model';
import { NodeChildren, INodeChildren } from './node-children';
import { Prop } from './props/prop';
import { ComponentMeta } from '../../component-meta';
import { IProp, Prop } from './props/prop';
import { ComponentMeta, IComponentMeta } from '../../component-meta';
import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
import { includeSlot, removeSlot } from '../../utils/slot';
import { foreachReverse } from '../../utils/tree';
@ -36,6 +36,39 @@ export interface NodeStatus {
export interface INode extends IPublicModelNode {
/**
*
*/
get children(): INodeChildren | null;
/**
*
*/
get prevSibling(): INode | null;
/**
*
*/
get nextSibling(): INode | null;
/**
*
*/
get parent(): INode | null;
get slots(): INode[];
/**
*
*/
get slotFor(): IProp | null;
get props(): IProps;
get componentMeta(): IComponentMeta;
get document(): IDocumentModel;
setVisible(flag: boolean): void;
getVisible(): boolean;
@ -61,8 +94,6 @@ export interface INode extends IPublicModelNode {
*/
export(stage: IPublicEnumTransformStage, options?: any): IPublicTypeNodeSchema;
get document(): IDocumentModel;
emitPropChange(val: IPublicTypePropChangeOptions): void;
import(data: IPublicTypeNodeSchema, checkId?: boolean): void;
@ -70,6 +101,14 @@ export interface INode extends IPublicModelNode {
internalSetSlotFor(slotFor: Prop | null | undefined): void;
addSlot(slotNode: INode): void;
onVisibleChange(func: (flag: boolean) => any): () => void;
getProp(path: string, createIfNone?: boolean): IProp | null;
getExtraProp(key: string, createIfNone?: boolean): IProp | null;
replaceChild(node: INode, data: any): INode;
}
/**
@ -148,7 +187,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/**
*
*/
props: Props;
props: IProps;
protected _children?: INodeChildren;
@ -204,6 +243,74 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
isInited = false;
_settingEntry: SettingTopEntry;
get settingEntry(): SettingTopEntry {
if (this._settingEntry) return this._settingEntry;
this._settingEntry = this.document.designer.createSettingEntry([this]);
return this._settingEntry;
}
private autoruns?: Array<() => void>;
private _isRGLContainer = false;
set isRGLContainer(status: boolean) {
this._isRGLContainer = status;
}
get isRGLContainer(): boolean {
return !!this._isRGLContainer;
}
set isRGLContainerNode(status: boolean) {
this._isRGLContainer = status;
}
get isRGLContainerNode(): boolean {
return !!this._isRGLContainer;
}
private _slotFor?: IProp | null = null;
@obx.shallow _slots: INode[] = [];
get slots(): INode[] {
return this._slots;
}
/* istanbul ignore next */
@obx.ref private _conditionGroup: IPublicModelExclusiveGroup | null = null;
/* istanbul ignore next */
get conditionGroup(): IPublicModelExclusiveGroup | null {
return this._conditionGroup;
}
private purged = false;
/**
*
*/
get isPurged() {
return this.purged;
}
private purging: boolean = false;
/**
*
*/
get isPurging() {
return this.purging;
}
@obx.shallow status: NodeStatus = {
inPlaceEditing: false,
locking: false,
pseudo: false,
};
constructor(readonly document: IDocumentModel, nodeSchema: Schema, options: any = {}) {
makeObservable(this);
const { componentName, id, children, props, ...extras } = nodeSchema;
@ -237,14 +344,6 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
});
}
_settingEntry: SettingTopEntry;
get settingEntry(): SettingTopEntry {
if (this._settingEntry) return this._settingEntry;
this._settingEntry = this.document.designer.createSettingEntry([this]);
return this._settingEntry;
}
/**
* prop reaction
*/
@ -268,8 +367,6 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
return this.document.designer.transformProps(props, this, IPublicEnumTransformStage.Upgrade);
}
private autoruns?: Array<() => void>;
private setupAutoruns() {
const autoruns = this.componentMeta.getMetadata().configure.advanced?.autoruns;
if (!autoruns || autoruns.length < 1) {
@ -296,24 +393,6 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
return children || [];
}
private _isRGLContainer = false;
set isRGLContainer(status: boolean) {
this._isRGLContainer = status;
}
get isRGLContainer(): boolean {
return !!this._isRGLContainer;
}
set isRGLContainerNode(status: boolean) {
this._isRGLContainer = status;
}
get isRGLContainerNode(): boolean {
return !!this._isRGLContainer;
}
isContainer(): boolean {
return this.isContainerNode;
}
@ -449,8 +528,6 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
}
}
private _slotFor?: Prop | null = null;
internalSetSlotFor(slotFor: Prop | null | undefined) {
this._slotFor = slotFor;
}
@ -462,7 +539,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/**
*
*/
get slotFor() {
get slotFor(): IProp | null {
return this._slotFor;
}
@ -536,24 +613,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
return this.props.export(IPublicEnumTransformStage.Serilize).props || null;
}
@obx.shallow _slots: INode[] = [];
hasSlots() {
return this._slots.length > 0;
}
get slots() {
return this._slots;
}
/* istanbul ignore next */
@obx.ref private _conditionGroup: IPublicModelExclusiveGroup | null = null;
/* istanbul ignore next */
get conditionGroup(): IPublicModelExclusiveGroup | null {
return this._conditionGroup;
}
/* istanbul ignore next */
setConditionGroup(grp: IPublicModelExclusiveGroup | string | null) {
if (!grp) {
@ -632,10 +695,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/**
*
*
* @param {Node} node
* @param {INode} node
* @param {object} data
*/
replaceChild(node: Node, data: any): Node {
replaceChild(node: INode, data: any): INode {
if (this.children?.has(node)) {
const selected = this.document.selection.has(node.id);
@ -670,11 +733,11 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
};
}
getProp(path: string, createIfNone = true): Prop | null {
getProp(path: string, createIfNone = true): IProp | null {
return this.props.query(path, createIfNone) || null;
}
getExtraProp(key: string, createIfNone = true): Prop | null {
getExtraProp(key: string, createIfNone = true): IProp | null {
return this.props.get(getConvertedExtraKey(key), createIfNone) || null;
}
@ -734,7 +797,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/**
*
*/
get nextSibling(): Node | null {
get nextSibling(): INode | null {
if (!this.parent) {
return null;
}
@ -748,7 +811,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/**
*
*/
get prevSibling(): Node | null {
get prevSibling(): INode | null {
if (!this.parent) {
return null;
}
@ -929,15 +992,6 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
this.children?.delete(node);
}
private purged = false;
/**
*
*/
get isPurged() {
return this.purged;
}
/**
*
*/
@ -952,18 +1006,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
// this.document.destroyNode(this);
}
private purging: boolean = false;
internalPurgeStart() {
this.purging = true;
}
/**
*
*/
get isPurging() {
return this.purging;
}
/**
* action
*/
@ -1044,12 +1090,6 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
this.children?.mergeChildren(remover, adder, sorter);
}
@obx.shallow status: NodeStatus = {
inPlaceEditing: false,
locking: false,
pseudo: false,
};
/**
* @deprecated
*/

View File

@ -1,6 +1,6 @@
import { obx, computed, makeObservable, action, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
import { Designer } from '../designer';
import { DocumentModel, isDocumentModel } from '../document';
import { IDesigner } from '../designer';
import { DocumentModel, IDocumentModel, isDocumentModel } from '../document';
import {
IPublicTypeProjectSchema,
IPublicTypeRootSchema,
@ -12,14 +12,60 @@ import {
import { isLowCodeComponentType, isProCodeComponentType } from '@alilc/lowcode-utils';
import { ISimulatorHost } from '../simulator';
export interface IProject extends IPublicApiProject {
export interface IProject extends Omit< IPublicApiProject, 'simulatorHost' | 'importSchema' | 'exportSchema' | 'openDocument' | 'getDocumentById' | 'getCurrentDocument' | 'addPropsTransducer' | 'onRemoveDocument' | 'onChangeDocument' | 'onSimulatorHostReady' | 'onSimulatorRendererReady' | 'setI18n' > {
get designer(): IDesigner;
get simulator(): ISimulatorHost | null;
get currentDocument(): IDocumentModel | null;
get documents(): IDocumentModel[];
open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null;
getDocumentByFileName(fileName: string): IDocumentModel | null;
createDocument(data?: IPublicTypeRootSchema): IDocumentModel;
load(schema?: IPublicTypeProjectSchema, autoOpen?: boolean | string): void;
getSchema(
stage: IPublicEnumTransformStage,
): IPublicTypeProjectSchema;
getDocument(id: string): IDocumentModel | null;
onCurrentDocumentChange(fn: (doc: IDocumentModel) => void): () => void;
onSimulatorReady(fn: (args: any) => void): () => void;
onRendererReady(fn: () => void): () => void;
/**
*
*/
set(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
key:
| 'version'
| 'componentsTree'
| 'componentsMap'
| 'utils'
| 'constants'
| 'i18n'
| 'css'
| 'dataSource'
| string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
value: any,
): void;
}
export class Project implements IProject {
private emitter: IEventBus = createModuleEventBus('Project');
@obx.shallow readonly documents: IPublicModelDocumentModel[] = [];
@obx.shallow readonly documents: IDocumentModel[] = [];
private data: IPublicTypeProjectSchema = {
version: '1.0.0',
@ -41,14 +87,7 @@ export class Project implements IProject {
key = Math.random();
// TODO: 考虑项目级别 History
constructor(readonly designer: Designer, schema?: IPublicTypeProjectSchema, readonly viewName = 'global') {
makeObservable(this);
this.load(schema);
}
@computed get currentDocument() {
@computed get currentDocument(): IDocumentModel | null {
return this.documents.find((doc) => doc.active);
}
@ -69,6 +108,13 @@ export class Project implements IProject {
this._i18n = value || {};
}
private documentsMap = new Map<string, DocumentModel>();
constructor(readonly designer: IDesigner, schema?: IPublicTypeProjectSchema, readonly viewName = 'global') {
makeObservable(this);
this.load(schema);
}
private getComponentsMap(): IPublicTypeComponentsMap {
return this.documents.reduce((
compomentsMap: IPublicTypeComponentsMap,
@ -104,7 +150,9 @@ export class Project implements IProject {
/**
* schema
*/
getSchema(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Save): IPublicTypeProjectSchema {
getSchema(
stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Save,
): IPublicTypeProjectSchema {
return {
...this.data,
componentsMap: this.getComponentsMap(),
@ -240,26 +288,24 @@ export class Project implements IProject {
return Reflect.get(this.data, key);
}
private documentsMap = new Map<string, DocumentModel>();
getDocument(id: string): DocumentModel | null {
getDocument(id: string): IDocumentModel | null {
// 此处不能使用 this.documentsMap.get(id),因为在乐高 rollback 场景document.id 会被改成其他值
return this.documents.find((doc) => doc.id === id) || null;
}
getDocumentByFileName(fileName: string): DocumentModel | null {
getDocumentByFileName(fileName: string): IDocumentModel | null {
return this.documents.find((doc) => doc.fileName === fileName) || null;
}
@action
createDocument(data?: IPublicTypeRootSchema): DocumentModel {
createDocument(data?: IPublicTypeRootSchema): IDocumentModel {
const doc = new DocumentModel(this, data || this?.data?.componentsTree?.[0]);
this.documents.push(doc);
this.documentsMap.set(doc.id, doc);
return doc;
}
open(doc?: string | DocumentModel | IPublicTypeRootSchema): DocumentModel | null {
open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null {
if (!doc) {
const got = this.documents.find((item) => item.isBlank());
if (got) {
@ -341,7 +387,7 @@ export class Project implements IProject {
};
}
onCurrentDocumentChange(fn: (doc: DocumentModel) => void): () => void {
onCurrentDocumentChange(fn: (doc: IDocumentModel) => void): () => void {
this.emitter.on('current-document.change', fn);
return () => {
this.emitter.removeListener('current-document.change', fn);

View File

@ -1,6 +1,6 @@
import { isEqual } from 'lodash';
import { globalContext } from './di';
import { IPublicTypeHotkeyCallback, IPublicApiHotkey } from '@alilc/lowcode-types';
import { IPublicTypeHotkeyCallback, IPublicTypeHotkeyCallbackConfig, IPublicTypeHotkeyCallbacks, IPublicApiHotkey } from '@alilc/lowcode-types';
interface KeyMap {
[key: number]: string;
@ -14,23 +14,10 @@ interface ActionEvent {
type: string;
}
interface IPublicTypeHotkeyCallbacks {
[key: string]: IPublicTypeHotkeyCallbackCfg[];
}
interface HotkeyDirectMap {
[key: string]: IPublicTypeHotkeyCallback;
}
interface IPublicTypeHotkeyCallbackCfg {
callback: IPublicTypeHotkeyCallback;
modifiers: string[];
action: string;
seq?: string;
level?: number;
combo?: string;
}
interface KeyInfo {
key: string;
modifiers: string[];
@ -444,10 +431,10 @@ export class Hotkey implements IHotKey {
sequenceName?: string,
combination?: string,
level?: number,
): IPublicTypeHotkeyCallbackCfg[] {
): IPublicTypeHotkeyCallbackConfig[] {
let i: number;
let callback: IPublicTypeHotkeyCallbackCfg;
const matches: IPublicTypeHotkeyCallbackCfg[] = [];
let callback: IPublicTypeHotkeyCallbackConfig;
const matches: IPublicTypeHotkeyCallbackConfig[] = [];
const action: string = e.type;
// if there are no events related to this keycode
@ -498,7 +485,7 @@ export class Hotkey implements IHotKey {
}
private handleKey(character: string, modifiers: string[], e: KeyboardEvent): void {
const callbacks: IPublicTypeHotkeyCallbackCfg[] = this.getMatches(character, modifiers, e);
const callbacks: IPublicTypeHotkeyCallbackConfig[] = this.getMatches(character, modifiers, e);
let i: number;
const doNotReset: SequenceLevels = {};
let maxLevel = 0;

View File

@ -14,9 +14,11 @@ import {
IDesigner,
} from '@alilc/lowcode-designer';
import { editorSymbol, designerSymbol, nodeSymbol } from '../symbols';
import { Dragon } from '../model';
import { DropLocation } from '../model/drop-location';
import { ActiveTracker } from '../model/active-tracker';
import {
Dragon as ShellDragon,
DropLocation as ShellDropLocation,
ActiveTracker as ShellActiveTracker,
} from '../model';
export class Canvas implements IPublicApiCanvas {
private readonly [editorSymbol]: IPublicModelEditor;
@ -25,6 +27,15 @@ export class Canvas implements IPublicApiCanvas {
return this[editorSymbol].get('designer') as IDesigner;
}
get dragon(): IPublicModelDragon | null {
return ShellDragon.create(this[designerSymbol].dragon, this.workspaceMode);
}
get activeTracker(): IPublicModelActiveTracker | null {
const activeTracker = new ShellActiveTracker(this[designerSymbol].activeTracker);
return activeTracker;
}
constructor(editor: IPublicModelEditor, readonly workspaceMode: boolean = false) {
this[editorSymbol] = editor;
}
@ -47,19 +58,10 @@ export class Canvas implements IPublicApiCanvas {
});
}
get dragon(): IPublicModelDragon | null {
return Dragon.create(this[designerSymbol].dragon, this.workspaceMode);
}
get activeTracker(): IPublicModelActiveTracker | null {
const activeTracker = new ActiveTracker(this[designerSymbol].activeTracker);
return activeTracker;
}
/**
* @deprecated
*/
get dropLocation() {
return DropLocation.create((this[designerSymbol] as any).dropLocation || null);
return ShellDropLocation.create((this[designerSymbol] as any).dropLocation || null);
}
}

View File

@ -58,7 +58,7 @@ import {
computed as innerComputed,
observer as innerObserver,
} from '@alilc/lowcode-editor-core';
import { Dragon } from '../model';
import { Dragon as ShellDragon } from '../model';
import { ReactNode, Component } from 'react';
class DesignerCabin implements IPublicApiCommonDesignerCabin {
@ -149,7 +149,7 @@ class DesignerCabin implements IPublicApiCommonDesignerCabin {
* @deprecated please use canvas.dragon
*/
get dragon(): IPublicModelDragon | null {
return Dragon.create(this[designerSymbol].dragon);
return ShellDragon.create(this[designerSymbol].dragon, false);
}
}

View File

@ -14,12 +14,6 @@ export class Event implements IPublicApiEvent {
private readonly [eventBusSymbol]: EventBus;
private readonly options: EventOptions;
// TODO:
/**
*
*/
readonly names = [];
constructor(eventBus: EventBus, options: EventOptions, public workspaceMode = false) {
this[eventBusSymbol] = eventBus;
this.options = options;

View File

@ -1,6 +1,6 @@
import { globalContext, Hotkey as InnerHotkey } from '@alilc/lowcode-editor-core';
import { hotkeySymbol } from '../symbols';
import { IPublicTypeDisposable, IPublicTypeHotkeyCallback, IPublicApiHotkey } from '@alilc/lowcode-types';
import { IPublicTypeDisposable, IPublicTypeHotkeyCallback, IPublicTypeHotkeyCallbacks, IPublicApiHotkey } from '@alilc/lowcode-types';
const innerHotkeySymbol = Symbol('innerHotkey');
@ -22,15 +22,17 @@ export class Hotkey implements IPublicApiHotkey {
this[innerHotkeySymbol] = hotkey;
}
get callbacks(): any {
get callbacks(): IPublicTypeHotkeyCallbacks {
return this[hotkeySymbol].callBacks;
}
/**
* @deprecated
*/
get callBacks() {
return this.callbacks;
}
/**
*
* @param combos ['command + s'] ['ctrl + shift + s']
@ -38,7 +40,11 @@ export class Hotkey implements IPublicApiHotkey {
* @param action
* @returns
*/
bind(combos: string[] | string, callback: IPublicTypeHotkeyCallback, action?: string): IPublicTypeDisposable {
bind(
combos: string[] | string,
callback: IPublicTypeHotkeyCallback,
action?: string,
): IPublicTypeDisposable {
this[hotkeySymbol].bind(combos, callback, action);
return () => {
this[hotkeySymbol].unbind(combos, callback, action);

View File

@ -1,6 +1,6 @@
import { Editor, globalContext } from '@alilc/lowcode-editor-core';
import { globalContext } from '@alilc/lowcode-editor-core';
import {
Designer,
IDesigner,
isComponentMeta,
} from '@alilc/lowcode-designer';
import { IPublicTypeAssetsJson } from '@alilc/lowcode-utils';
@ -11,21 +11,22 @@ import {
IPublicTypeMetadataTransducer,
IPublicModelComponentMeta,
IPublicTypeNpmInfo,
IPublicModelEditor,
} from '@alilc/lowcode-types';
import { Workspace } from '@alilc/lowcode-workspace';
import { Workspace as InnerWorkspace } from '@alilc/lowcode-workspace';
import { editorSymbol, designerSymbol } from '../symbols';
import { ComponentMeta } from '../model/component-meta';
import { ComponentMeta as ShellComponentMeta } from '../model';
import { ComponentType } from 'react';
const innerEditorSymbol = Symbol('editor');
export class Material implements IPublicApiMaterial {
private readonly [innerEditorSymbol]: Editor;
private readonly [innerEditorSymbol]: IPublicModelEditor;
get [editorSymbol](): Editor {
get [editorSymbol](): IPublicModelEditor {
if (this.workspaceMode) {
return this[innerEditorSymbol];
}
const workspace: Workspace = globalContext.get('workspace');
const workspace: InnerWorkspace = globalContext.get('workspace');
if (workspace.isActive) {
return workspace.window.editor;
}
@ -33,11 +34,11 @@ export class Material implements IPublicApiMaterial {
return this[innerEditorSymbol];
}
get [designerSymbol](): Designer {
get [designerSymbol](): IDesigner {
return this[editorSymbol].get('designer')!;
}
constructor(editor: Editor, readonly workspaceMode: boolean = false) {
constructor(editor: IPublicModelEditor, readonly workspaceMode: boolean = false) {
this[innerEditorSymbol] = editor;
}
@ -103,7 +104,7 @@ export class Material implements IPublicApiMaterial {
*/
getComponentMeta(componentName: string): IPublicModelComponentMeta | null {
const innerMeta = this[designerSymbol].getComponentMeta(componentName);
return ComponentMeta.create(innerMeta);
return ShellComponentMeta.create(innerMeta);
}
/**
@ -112,7 +113,7 @@ export class Material implements IPublicApiMaterial {
* @returns
*/
createComponentMeta(metadata: IPublicTypeComponentMetadata) {
return ComponentMeta.create(this[designerSymbol].createComponentMeta(metadata));
return ShellComponentMeta.create(this[designerSymbol].createComponentMeta(metadata));
}
/**
@ -158,7 +159,10 @@ export class Material implements IPublicApiMaterial {
* @param actionName
* @param handle
*/
modifyBuiltinComponentAction(actionName: string, handle: (action: IPublicTypeComponentAction) => void) {
modifyBuiltinComponentAction(
actionName: string,
handle: (action: IPublicTypeComponentAction) => void,
) {
this[designerSymbol].componentActions.modifyBuiltinComponentAction(actionName, handle);
}

View File

@ -9,7 +9,7 @@ import {
IPublicTypePluginRegisterOptions,
IPublicTypePreferenceValueType,
} from '@alilc/lowcode-types';
import { PluginInstance } from '../model/plugin-instance';
import { PluginInstance as ShellPluginInstance } from '../model';
import { pluginsSymbol } from '../symbols';
const innerPluginsSymbol = Symbol('plugin');
@ -43,21 +43,23 @@ export class Plugins implements IPublicApiPlugins {
await this[pluginsSymbol].init(registerOptions);
}
getPluginPreference(pluginName: string): Record<string, IPublicTypePreferenceValueType> | null | undefined {
getPluginPreference(
pluginName: string,
): Record<string, IPublicTypePreferenceValueType> | null | undefined {
return this[pluginsSymbol].getPluginPreference(pluginName);
}
get(pluginName: string): IPublicModelPluginInstance | null {
const instance = this[pluginsSymbol].get(pluginName);
if (instance) {
return new PluginInstance(instance);
return new ShellPluginInstance(instance);
}
return null;
}
getAll() {
return this[pluginsSymbol].getAll()?.map(d => new PluginInstance(d));
return this[pluginsSymbol].getAll()?.map((d) => new ShellPluginInstance(d));
}
has(pluginName: string) {

View File

@ -1,6 +1,6 @@
import {
BuiltinSimulatorHost,
Project as InnerProject,
IProject as InnerProject,
} from '@alilc/lowcode-designer';
import { globalContext } from '@alilc/lowcode-editor-core';
import {
@ -14,9 +14,7 @@ import {
IPublicEnumTransformStage,
IPublicTypeDisposable,
} from '@alilc/lowcode-types';
import { DocumentModel } from '../model/document-model';
import { DocumentModel as ShellDocumentModel } from '../model';
import { SimulatorHost } from './simulator-host';
import { editorSymbol, projectSymbol, simulatorHostSymbol, documentSymbol } from '../symbols';
@ -61,7 +59,7 @@ export class Project implements IPublicApiProject {
* @returns
*/
get documents(): IPublicModelDocumentModel[] {
return this[projectSymbol].documents.map((doc) => DocumentModel.create(doc)!);
return this[projectSymbol].documents.map((doc) => ShellDocumentModel.create(doc)!);
}
/**
@ -85,8 +83,10 @@ export class Project implements IPublicApiProject {
*/
openDocument(doc?: string | IPublicTypeRootSchema | undefined) {
const documentModel = this[projectSymbol].open(doc);
if (!documentModel) return null;
return DocumentModel.create(documentModel);
if (!documentModel) {
return null;
}
return ShellDocumentModel.create(documentModel);
}
/**
@ -96,7 +96,7 @@ export class Project implements IPublicApiProject {
*/
createDocument(data?: IPublicTypeRootSchema): IPublicModelDocumentModel | null {
const doc = this[projectSymbol].createDocument(data);
return DocumentModel.create(doc);
return ShellDocumentModel.create(doc);
}
/**
@ -113,7 +113,8 @@ export class Project implements IPublicApiProject {
* @returns
*/
getDocumentByFileName(fileName: string): IPublicModelDocumentModel | null {
return DocumentModel.create(this[projectSymbol].getDocumentByFileName(fileName));
const innerDocumentModel = this[projectSymbol].getDocumentByFileName(fileName);
return ShellDocumentModel.create(innerDocumentModel);
}
/**
@ -122,7 +123,7 @@ export class Project implements IPublicApiProject {
* @returns
*/
getDocumentById(id: string): IPublicModelDocumentModel | null {
return DocumentModel.create(this[projectSymbol].getDocument(id));
return ShellDocumentModel.create(this[projectSymbol].getDocument(id));
}
/**
@ -146,7 +147,7 @@ export class Project implements IPublicApiProject {
* @returns
*/
getCurrentDocument(): IPublicModelDocumentModel | null {
return DocumentModel.create(this[projectSymbol].currentDocument);
return ShellDocumentModel.create(this[projectSymbol].currentDocument);
}
/**
@ -154,7 +155,10 @@ export class Project implements IPublicApiProject {
* @param transducer
* @param stage
*/
addPropsTransducer(transducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage): void {
addPropsTransducer(
transducer: IPublicTypePropsTransducer,
stage: IPublicEnumTransformStage,
): void {
this[projectSymbol].designer.addPropsReducer(transducer, stage);
}
@ -175,10 +179,10 @@ export class Project implements IPublicApiProject {
*/
onChangeDocument(fn: (doc: IPublicModelDocumentModel) => void): IPublicTypeDisposable {
const offFn = this[projectSymbol].onCurrentDocumentChange((originalDoc) => {
fn(DocumentModel.create(originalDoc)!);
fn(ShellDocumentModel.create(originalDoc)!);
});
if (this[projectSymbol].currentDocument) {
fn(DocumentModel.create(this[projectSymbol].currentDocument)!);
fn(ShellDocumentModel.create(this[projectSymbol].currentDocument)!);
}
return offFn;
}

View File

@ -23,7 +23,11 @@ export class Skeleton implements IPublicApiSkeleton {
return this[innerSkeletonSymbol];
}
constructor(skeleton: InnerSkeleton, pluginName: string, readonly workspaceMode: boolean = false) {
constructor(
skeleton: InnerSkeleton,
pluginName: string,
readonly workspaceMode: boolean = false,
) {
this[innerSkeletonSymbol] = skeleton;
this.pluginName = pluginName;
}

View File

@ -1,9 +1,8 @@
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType } from '@alilc/lowcode-types';
import { Workspace as InnerWorkSpace } from '@alilc/lowcode-workspace';
import { Plugins } from '@alilc/lowcode-shell';
import { Window } from '../model/window';
import { workspaceSymbol } from '../symbols';
import { Resource } from '../model';
import { Resource as ShellResource, Window as ShellWindow } from '../model';
export class Workspace implements IPublicApiWorkspace {
readonly [workspaceSymbol]: InnerWorkSpace;
@ -13,7 +12,7 @@ export class Workspace implements IPublicApiWorkspace {
}
get resourceList() {
return this[workspaceSymbol].getResourceList().map(d => new Resource(d));
return this[workspaceSymbol].getResourceList().map((d) => new ShellResource(d));
}
setResourceList(resourceList: IPublicResourceList) {
@ -29,14 +28,14 @@ export class Workspace implements IPublicApiWorkspace {
}
get window() {
return new Window(this[workspaceSymbol].window);
return new ShellWindow(this[workspaceSymbol].window);
}
registerResourceType(resourceTypeModel: IPublicTypeResourceType): void {
this[workspaceSymbol].registerResourceType(resourceTypeModel);
}
openEditorWindow(resourceName: string, title: string, extra: Object, viewName?: string) {
openEditorWindow(resourceName: string, title: string, extra: object, viewName?: string) {
this[workspaceSymbol].openEditorWindow(resourceName, title, extra, viewName);
}
@ -57,7 +56,7 @@ export class Workspace implements IPublicApiWorkspace {
}
get windows() {
return this[workspaceSymbol].windows.map(d => new Window(d));
return this[workspaceSymbol].windows.map((d) => new ShellWindow(d));
}
onChangeWindows(fn: () => void) {

View File

@ -1,16 +1,14 @@
import { IPublicModelActiveTracker, IPublicModelNode, IPublicTypeActiveTarget } from '@alilc/lowcode-types';
import { IActiveTracker } from '@alilc/lowcode-designer';
import { Node } from './node';
import { IActiveTracker as InnerActiveTracker, INode as InnerNode } from '@alilc/lowcode-designer';
import { Node as ShellNode } from './node';
import { nodeSymbol } from '../symbols';
const activeTrackerSymbol = Symbol('activeTracker');
export class ActiveTracker implements IPublicModelActiveTracker {
private readonly [activeTrackerSymbol]: IActiveTracker;
private readonly [activeTrackerSymbol]: InnerActiveTracker;
constructor(innerTracker: IActiveTracker) {
constructor(innerTracker: InnerActiveTracker) {
this[activeTrackerSymbol] = innerTracker;
}
@ -20,7 +18,7 @@ export class ActiveTracker implements IPublicModelActiveTracker {
}
return this[activeTrackerSymbol].onChange((t: IPublicTypeActiveTarget) => {
const { node: innerNode, detail, instance } = t;
const publicNode = Node.create(innerNode);
const publicNode = ShellNode.create(innerNode as InnerNode);
const publicActiveTarget = {
node: publicNode!,
detail,

View File

@ -1,5 +1,5 @@
import {
ComponentMeta as InnerComponentMeta,
IComponentMeta as InnerComponentMeta,
INode,
} from '@alilc/lowcode-designer';
import { IPublicTypeNodeData, IPublicTypeNodeSchema, IPublicModelComponentMeta, IPublicTypeI18nData, IPublicTypeIconType, IPublicTypeNpmInfo, IPublicTypeTransformedComponentMetadata, IPublicModelNode } from '@alilc/lowcode-types';
@ -9,6 +9,8 @@ import { ReactElement } from 'react';
export class ComponentMeta implements IPublicModelComponentMeta {
private readonly [componentMetaSymbol]: InnerComponentMeta;
isComponentMeta = true;
constructor(componentMeta: InnerComponentMeta) {
this[componentMetaSymbol] = componentMeta;
}
@ -83,7 +85,7 @@ export class ComponentMeta implements IPublicModelComponentMeta {
* @deprecated
*/
get prototype() {
return this[componentMetaSymbol].prototype;
return (this[componentMetaSymbol] as any).prototype;
}
get availableActions(): any {
@ -106,7 +108,6 @@ export class ComponentMeta implements IPublicModelComponentMeta {
return this[componentMetaSymbol].getMetadata();
}
isComponentMeta = true;
/**
* check if the current node could be placed in parent node
* @param my
@ -124,9 +125,15 @@ export class ComponentMeta implements IPublicModelComponentMeta {
* @param parent
* @returns
*/
checkNestingDown(my: IPublicModelNode | IPublicTypeNodeData, target: IPublicTypeNodeSchema | IPublicModelNode | IPublicTypeNodeSchema[]) {
checkNestingDown(
my: IPublicModelNode | IPublicTypeNodeData,
target: IPublicTypeNodeSchema | IPublicModelNode | IPublicTypeNodeSchema[],
) {
const curNode = (my as any)?.isNode ? (my as any)[nodeSymbol] : my;
return this[componentMetaSymbol].checkNestingDown(curNode as any, (target as any)[nodeSymbol] || target);
return this[componentMetaSymbol].checkNestingDown(
curNode as any,
(target as any)[nodeSymbol] || target,
);
}
refreshMetadata(): void {

View File

@ -2,6 +2,7 @@ import { Node as ShellNode } from './node';
import {
Detecting as InnerDetecting,
IDocumentModel as InnerDocumentModel,
INode as InnerNode,
} from '@alilc/lowcode-designer';
import { documentSymbol, detectingSymbol } from '../symbols';
import { IPublicModelDetecting, IPublicModelNode, IPublicTypeDisposable } from '@alilc/lowcode-types';
@ -52,7 +53,11 @@ export class Detecting implements IPublicModelDetecting {
this[detectingSymbol].leave(this[documentSymbol]);
}
onDetectingChange(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable {
return this[detectingSymbol].onDetectingChange(fn);
onDetectingChange(fn: (node: IPublicModelNode | null) => void): IPublicTypeDisposable {
const innerFn = (innerNode: InnerNode) => {
const shellNode = ShellNode.create(innerNode);
fn(shellNode);
};
return this[detectingSymbol].onDetectingChange(innerFn);
}
}

View File

@ -1,8 +1,6 @@
import { Editor } from '@alilc/lowcode-editor-core';
import {
DocumentModel as InnerDocumentModel,
Node as InnerNode,
isDragNodeObject,
IDocumentModel as InnerDocumentModel,
INode as InnerNode,
} from '@alilc/lowcode-designer';
import {
IPublicEnumTransformStage,
@ -23,23 +21,24 @@ import {
IPublicModelDropLocation,
IPublicApiCanvas,
IPublicTypeDisposable,
IPublicModelEditor,
} from '@alilc/lowcode-types';
import { Node } from './node';
import { Selection } from './selection';
import { Detecting } from './detecting';
import { History } from './history';
import { DropLocation } from './drop-location';
import { Project } from '../api/project';
import { Prop } from './prop';
import { isDragNodeObject } from '@alilc/lowcode-utils';
import { Node as ShellNode } from './node';
import { Selection as ShellSelection } from './selection';
import { Detecting as ShellDetecting } from './detecting';
import { History as ShellHistory } from './history';
import { DropLocation as ShellDropLocation } from './drop-location';
import { Project as ShellProject, Canvas as ShellCanvas } from '../api';
import { Prop as ShellProp } from './prop';
import { ModalNodesManager } from './modal-nodes-manager';
import { documentSymbol, editorSymbol, nodeSymbol } from '../symbols';
import { Canvas } from '../api';
const shellDocSymbol = Symbol('shellDocSymbol');
export class DocumentModel implements IPublicModelDocumentModel {
private readonly [documentSymbol]: InnerDocumentModel;
private readonly [editorSymbol]: Editor;
private readonly [editorSymbol]: IPublicModelEditor;
private _focusNode: IPublicModelNode | null;
selection: IPublicModelSelection;
detecting: IPublicModelDetecting;
@ -52,13 +51,13 @@ export class DocumentModel implements IPublicModelDocumentModel {
constructor(document: InnerDocumentModel) {
this[documentSymbol] = document;
this[editorSymbol] = document.designer?.editor as Editor;
this.selection = new Selection(document);
this.detecting = new Detecting(document);
this.history = new History(document);
this.canvas = new Canvas(this[editorSymbol]);
this[editorSymbol] = document.designer?.editor as IPublicModelEditor;
this.selection = new ShellSelection(document);
this.detecting = new ShellDetecting(document);
this.history = new ShellHistory(document);
this.canvas = new ShellCanvas(this[editorSymbol]);
this._focusNode = Node.create(this[documentSymbol].focusNode);
this._focusNode = ShellNode.create(this[documentSymbol].focusNode);
}
static create(document: InnerDocumentModel | undefined | null): IPublicModelDocumentModel | null {
@ -91,7 +90,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
* @returns
*/
get project(): IPublicApiProject {
return Project.create(this[documentSymbol].project);
return ShellProject.create(this[documentSymbol].project);
}
/**
@ -100,7 +99,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
* @returns
*/
get root(): IPublicModelNode | null {
return Node.create(this[documentSymbol].getRoot());
return ShellNode.create(this[documentSymbol].rootNode);
}
get focusNode(): IPublicModelNode | null {
@ -135,7 +134,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
}
get dropLocation(): IPublicModelDropLocation | null {
return DropLocation.create(this[documentSymbol].dropLocation);
return ShellDropLocation.create(this[documentSymbol].dropLocation);
}
set dropLocation(loc: IPublicModelDropLocation | null) {
@ -148,7 +147,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
* @param {string} nodeId
*/
getNodeById(nodeId: string): IPublicModelNode | null {
return Node.create(this[documentSymbol].getNode(nodeId));
return ShellNode.create(this[documentSymbol].getNode(nodeId));
}
/**
@ -189,7 +188,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
at,
copy,
);
return Node.create(node);
return ShellNode.create(node);
}
/**
@ -198,7 +197,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
* @returns
*/
createNode(data: any): IPublicModelNode | null {
return Node.create(this[documentSymbol].createNode(data));
return ShellNode.create(this[documentSymbol].createNode(data));
}
/**
@ -243,7 +242,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
*/
onAddNode(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable {
return this[documentSymbol].onNodeCreate((node: InnerNode) => {
fn(Node.create(node)!);
fn(ShellNode.create(node)!);
});
}
@ -262,7 +261,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
*/
onRemoveNode(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable {
return this[documentSymbol].onNodeDestroy((node: InnerNode) => {
fn(Node.create(node)!);
fn(ShellNode.create(node)!);
});
}
@ -271,7 +270,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
*/
onChangeDetecting(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable {
return this[documentSymbol].designer.detecting.onDetectingChange((node: InnerNode) => {
fn(Node.create(node)!);
fn(ShellNode.create(node)!);
});
}
@ -290,7 +289,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
*/
onChangeNodeVisible(fn: (node: IPublicModelNode, visible: boolean) => void): void {
this[documentSymbol].onChangeNodeVisible((node: IPublicModelNode, visible: boolean) => {
fn(Node.create(node)!, visible);
fn(ShellNode.create(node)!, visible);
});
}
@ -305,7 +304,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
}
fn({
type: info.type,
node: Node.create(info.node)!,
node: ShellNode.create(info.node)!,
});
});
}
@ -322,8 +321,8 @@ export class DocumentModel implements IPublicModelDocumentModel {
key: info.key,
oldValue: info.oldValue,
newValue: info.newValue,
prop: Prop.create(info.prop)!,
node: Node.create(info.node as any)!,
prop: ShellProp.create(info.prop)!,
node: ShellNode.create(info.node as any)!,
});
},
);

View File

@ -9,7 +9,7 @@ export class DragObject implements IPublicModelDragObject {
this[dragObjectSymbol] = dragObject;
}
static create(dragObject: InnerDragObject): IPublicModelDragObject | null {
static create(dragObject: InnerDragObject | null): IPublicModelDragObject | null {
if (!dragObject) {
return null;
}

View File

@ -15,7 +15,6 @@ import {
export const innerDragonSymbol = Symbol('innerDragonSymbol');
export class Dragon implements IPublicModelDragon {
private readonly [innerDragonSymbol]: IPublicModelDragon;
@ -38,7 +37,10 @@ export class Dragon implements IPublicModelDragon {
return designer.dragon;
}
static create(dragon: IPublicModelDragon | null, workspaceMode: boolean): IPublicModelDragon | null {
static create(
dragon: IPublicModelDragon | null,
workspaceMode: boolean,
): IPublicModelDragon | null {
if (!dragon) {
return null;
}

View File

@ -1,5 +1,5 @@
import {
DropLocation as InnerDropLocation,
IDropLocation as InnerDropLocation,
} from '@alilc/lowcode-designer';
import { dropLocationSymbol } from '../symbols';
import { Node } from './node';

View File

@ -1,11 +1,11 @@
import { DocumentModel as InnerDocumentModel } from '@alilc/lowcode-designer';
import { IDocumentModel as InnerDocumentModel, IHistory as InnerHistory } from '@alilc/lowcode-designer';
import { historySymbol, documentSymbol } from '../symbols';
import { IPublicModelHistory, IPublicTypeDisposable } from '@alilc/lowcode-types';
export class History implements IPublicModelHistory {
private readonly [documentSymbol]: InnerDocumentModel;
private get [historySymbol]() {
private get [historySymbol](): InnerHistory {
return this[documentSymbol].getHistory();
}
@ -64,7 +64,7 @@ export class History implements IPublicModelHistory {
* @returns
*/
onChangeState(func: () => any): IPublicTypeDisposable {
return this[historySymbol].onStateChange(func);
return this[historySymbol].onChangeState(func);
}
/**
@ -73,6 +73,6 @@ export class History implements IPublicModelHistory {
* @returns
*/
onChangeCursor(func: () => any): IPublicTypeDisposable {
return this[historySymbol].onCursor(func);
return this[historySymbol].onChangeCursor(func);
}
}

View File

@ -14,4 +14,7 @@ export * from './props';
export * from './selection';
export * from './setting-prop-entry';
export * from './setting-top-entry';
export * from './resource';
export * from './resource';
export * from './active-tracker';
export * from './plugin-instance';
export * from './window';

View File

@ -1,6 +1,9 @@
import { ModalNodesManager as InnerModalNodesManager } from '@alilc/lowcode-designer';
import {
IModalNodesManager as InnerModalNodesManager,
INode as InnerNode,
} from '@alilc/lowcode-designer';
import { IPublicModelModalNodesManager, IPublicModelNode } from '@alilc/lowcode-types';
import { Node } from './node';
import { Node as ShellNode } from './node';
import { nodeSymbol, modalNodesManagerSymbol } from '../symbols';
export class ModalNodesManager implements IPublicModelModalNodesManager {
@ -28,18 +31,24 @@ export class ModalNodesManager implements IPublicModelModalNodesManager {
/**
*
* @returns
*/
getModalNodes(): any {
return this[modalNodesManagerSymbol].getModalNodes().map((node) => Node.create(node));
getModalNodes(): IPublicModelNode[] {
const innerNodes = this[modalNodesManagerSymbol].getModalNodes();
const shellNodes: IPublicModelNode[] = [];
innerNodes?.forEach((node: InnerNode) => {
const shellNode = ShellNode.create(node);
if (shellNode) {
shellNodes.push(shellNode);
}
});
return shellNodes;
}
/**
*
* @returns
*/
getVisibleModalNode(): any {
return Node.create(this[modalNodesManagerSymbol].getVisibleModalNode());
getVisibleModalNode(): IPublicModelNode | null {
return ShellNode.create(this[modalNodesManagerSymbol].getVisibleModalNode());
}
/**
@ -54,7 +63,7 @@ export class ModalNodesManager implements IPublicModelModalNodesManager {
* @param node Node
*/
setVisible(node: IPublicModelNode): void {
this[modalNodesManagerSymbol].setVisible(node[nodeSymbol]);
this[modalNodesManagerSymbol].setVisible((node as any)[nodeSymbol]);
}
/**
@ -62,6 +71,6 @@ export class ModalNodesManager implements IPublicModelModalNodesManager {
* @param node Node
*/
setInvisible(node: IPublicModelNode): void {
this[modalNodesManagerSymbol].setInvisible(node[nodeSymbol]);
this[modalNodesManagerSymbol].setInvisible((node as any)[nodeSymbol]);
}
}

View File

@ -1,6 +1,6 @@
import { INode as InnerNode, INodeChildren } from '@alilc/lowcode-designer';
import { IPublicTypeNodeData, IPublicEnumTransformStage, IPublicModelNodeChildren, IPublicModelNode } from '@alilc/lowcode-types';
import { Node } from './node';
import { Node as ShellNode } from './node';
import { nodeSymbol, nodeChildrenSymbol } from '../symbols';
export class NodeChildren implements IPublicModelNodeChildren {
@ -21,7 +21,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* children
*/
get owner(): IPublicModelNode | null {
return Node.create(this[nodeChildrenSymbol].owner);
return ShellNode.create(this[nodeChildrenSymbol].owner);
}
/**
@ -107,7 +107,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @returns
*/
get(index: number): IPublicModelNode | null {
return Node.create(this[nodeChildrenSymbol].get(index));
return ShellNode.create(this[nodeChildrenSymbol].get(index));
}
/**
@ -125,7 +125,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
*/
forEach(fn: (node: IPublicModelNode, index: number) => void): void {
this[nodeChildrenSymbol].forEach((item: InnerNode, index: number) => {
fn(Node.create(item)!, index);
fn(ShellNode.create(item)!, index);
});
}
@ -135,7 +135,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
*/
map<T>(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null {
return this[nodeChildrenSymbol].map((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index);
return fn(ShellNode.create(item)!, index);
});
}
@ -145,7 +145,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
*/
every(fn: (node: IPublicModelNode, index: number) => boolean): boolean {
return this[nodeChildrenSymbol].every((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index);
return fn(ShellNode.create(item)!, index);
});
}
@ -155,7 +155,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
*/
some(fn: (node: IPublicModelNode, index: number) => boolean): boolean {
return this[nodeChildrenSymbol].some((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index);
return fn(ShellNode.create(item)!, index);
});
}
@ -166,9 +166,9 @@ export class NodeChildren implements IPublicModelNodeChildren {
filter(fn: (node: IPublicModelNode, index: number) => boolean): any {
return this[nodeChildrenSymbol]
.filter((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index);
return fn(ShellNode.create(item)!, index);
})
.map((item: InnerNode) => Node.create(item)!);
.map((item: InnerNode) => ShellNode.create(item)!);
}
/**
@ -176,9 +176,9 @@ export class NodeChildren implements IPublicModelNodeChildren {
* @param fn
*/
find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null {
return Node.create(
return ShellNode.create(
this[nodeChildrenSymbol].find((item: InnerNode, index: number) => {
return fn(Node.create(item)!, index);
return fn(ShellNode.create(item)!, index);
}),
);
}
@ -189,7 +189,7 @@ export class NodeChildren implements IPublicModelNodeChildren {
*/
reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void {
return this[nodeChildrenSymbol].reduce((acc: any, cur: InnerNode) => {
return fn(acc, Node.create(cur)!);
return fn(acc, ShellNode.create(cur)!);
}, initialValue);
}
@ -226,10 +226,11 @@ export class NodeChildren implements IPublicModelNodeChildren {
sorter = () => 0;
}
this[nodeChildrenSymbol].mergeChildren(
(node: InnerNode, idx: number) => remover(Node.create(node)!, idx),
(children: InnerNode[]) => adder(children.map((node) => Node.create(node)!)),
(firstNode: InnerNode, secondNode: InnerNode) =>
sorter(Node.create(firstNode)!, Node.create(secondNode)!),
(node: InnerNode, idx: number) => remover(ShellNode.create(node)!, idx),
(children: InnerNode[]) => adder(children.map((node) => ShellNode.create(node)!)),
(firstNode: InnerNode, secondNode: InnerNode) => {
return sorter(ShellNode.create(firstNode)!, ShellNode.create(secondNode)!);
},
);
}
}

View File

@ -283,7 +283,7 @@ export class Node implements IPublicModelNode {
*
*/
get slots(): IPublicModelNode[] {
return this[nodeSymbol].slots.map((node: IPublicModelNode) => Node.create(node)!);
return this[nodeSymbol].slots.map((node: InnerNode) => Node.create(node)!);
}
/**
@ -318,7 +318,7 @@ export class Node implements IPublicModelNode {
return ShellSettingTopEntry.create(this[nodeSymbol].settingEntry as any);
}
constructor(node: IPublicModelNode) {
constructor(node: InnerNode) {
this[nodeSymbol] = node;
this[documentSymbol] = node.document;
@ -351,7 +351,7 @@ export class Node implements IPublicModelNode {
* @deprecated
*/
getDOMNode() {
return this[nodeSymbol].getDOMNode();
return (this[nodeSymbol] as any).getDOMNode();
}
/**
@ -512,7 +512,10 @@ export class Node implements IPublicModelNode {
* @param options
* @returns
*/
exportSchema(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Render, options?: any): IPublicTypeNodeSchema {
exportSchema(
stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Render,
options?: any,
): IPublicTypeNodeSchema {
return this[nodeSymbol].export(stage, options);
}

View File

@ -1,7 +1,14 @@
import { IPublicTypeDisposable, IPublicTypeHotkeyCallback } from '../type';
import { IPublicTypeDisposable, IPublicTypeHotkeyCallback, IPublicTypeHotkeyCallbacks } from '../type';
export interface IPublicApiHotkey {
get callbacks(): any;
/**
*
*
* @experimental
* @since v1.1.0
*/
get callbacks(): IPublicTypeHotkeyCallbacks;
/**
*
@ -9,7 +16,6 @@ export interface IPublicApiHotkey {
* @param combos ['command + s'] ['ctrl + shift + s']
* @param callback
* @param action
* @returns
*/
bind(
combos: string[] | string,

View File

@ -3,8 +3,8 @@ import { IPublicEnumTransformStage } from '../enum';
import { IPublicApiSimulatorHost } from './';
import { IPublicModelDocumentModel } from '../model';
export interface IPublicApiProject {
/**
* document
* get current document
@ -40,7 +40,6 @@ export interface IPublicApiProject {
*/
createDocument(data?: IPublicTypeRootSchema): IPublicModelDocumentModel | null;
/**
* document
* remove a document

View File

@ -3,6 +3,7 @@ import { ReactElement } from 'react';
import { IPublicModelNode } from './node';
export interface IPublicModelComponentMeta {
/**
*
*/
@ -79,6 +80,5 @@ export interface IPublicModelComponentMeta {
target: IPublicTypeNodeSchema | IPublicModelNode | IPublicTypeNodeSchema[],
): boolean;
refreshMetadata(): void;
}

View File

@ -42,5 +42,5 @@ export interface IPublicModelDetecting {
* set callback which will be called when hovering object changed.
* @since v1.1.0
*/
onDetectingChange(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable;
onDetectingChange(fn: (node: IPublicModelNode | null) => void): IPublicTypeDisposable;
}

View File

@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
import StrictEventEmitter from 'strict-event-emitter-types';
import * as GlobalEvent from '../../event';
import { IPublicApiEvent } from '../api';
import { IPublicTypeEditorValueKey, IPublicTypeEditorGetOptions, IPublicTypeEditorGetResult, IPublicTypeEditorRegisterOptions } from '../type';
import { IPublicTypeEditorValueKey, IPublicTypeEditorGetOptions, IPublicTypeEditorGetResult, IPublicTypeEditorRegisterOptions, IPublicTypeAssetsJson } from '../type';
export interface IPublicModelEditor extends StrictEventEmitter<EventEmitter, GlobalEvent.EventConfig> {
get: <T = undefined, KeyOrType = any>(
@ -25,4 +25,6 @@ export interface IPublicModelEditor extends StrictEventEmitter<EventEmitter, Glo
register: (data: any, key?: IPublicTypeEditorValueKey, options?: IPublicTypeEditorRegisterOptions) => void;
get eventBus(): IPublicApiEvent;
setAssets(assets: IPublicTypeAssetsJson): void;
}

View File

@ -1,36 +1,41 @@
import { IPublicModelNode } from './';
export interface IPublicModelModalNodesManager {
/**
*
* set modal nodes, trigger internal events
*/
setNodes(): void;
/**
*
* @returns
* get modal nodes
*/
getModalNodes(): any;
getModalNodes(): IPublicModelNode[];
/**
*
* @returns
* get current visible modal node
*/
getVisibleModalNode(): any;
getVisibleModalNode(): IPublicModelNode | null;
/**
*
* hide modal nodes
*/
hideModalNodes(): void;
/**
*
* set specfic model node as visible
* @param node Node
*/
setVisible(node: IPublicModelNode): void;
/**
*
* set specfic model node as invisible
* @param node Node
*/
setInvisible(node: IPublicModelNode): void;

View File

@ -1,5 +1,4 @@
import { ReactElement } from 'react';
import { IPublicModelResourceType } from './resource-type';
export interface IPublicModelResource {
get title(): string | undefined;

View File

@ -0,0 +1,10 @@
import { IPublicTypeHotkeyCallback } from './';
export interface IPublicTypeHotkeyCallbackConfig {
callback: IPublicTypeHotkeyCallback;
modifiers: string[];
action: string;
seq?: string;
level?: number;
combo?: string;
}

View File

@ -0,0 +1,5 @@
import { IPublicTypeHotkeyCallbackConfig } from './';
export interface IPublicTypeHotkeyCallbacks {
[key: string]: IPublicTypeHotkeyCallbackConfig[];
}

View File

@ -86,4 +86,6 @@ export * from './editor-register-options';
export * from './editor-view';
export * from './resource-type';
export * from './resource-type-config';
export * from './editor-view-config';
export * from './editor-view-config';
export * from './hotkey-callback-config';
export * from './hotkey-callbacks';

View File

@ -7,12 +7,16 @@ import { Workspace as InnerWorkSpace } from './workspace';
const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' });
export class Resource implements IPublicModelResource {
private context: BasicContext;
resourceTypeInstance: IPublicResourceTypeConfig;
editorViewMap: Map<string, IPublicTypeEditorView> = new Map<string, IPublicTypeEditorView>();
constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, workspace: InnerWorkSpace) {
this.resourceTypeInstance = resourceType.resourceTypeModel(new BasicContext(workspace, ''), {});
this.context = new BasicContext(workspace, '');
this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, {});
this.init();
if (this.resourceTypeInstance.editorViews) {
this.resourceTypeInstance.editorViews.forEach((d: any) => {
this.editorViewMap.set(d.viewName, d);
@ -51,6 +55,11 @@ export class Resource implements IPublicModelResource {
return this.resourceData?.category;
}
async init() {
await this.resourceTypeInstance.init?.();
await this.context.innerPlugins.init();
}
async import(schema: any) {
return await this.resourceTypeInstance.import?.(schema);
}