mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-13 23:31:17 +00:00
Merge branch 'release/1.1.3'
This commit is contained in:
commit
faa524e5e0
@ -20,7 +20,7 @@ module.exports = {
|
||||
'no-await-in-loop': 0,
|
||||
'no-plusplus': 0,
|
||||
'@typescript-eslint/no-parameter-properties': 0,
|
||||
'@typescript-eslint/no-unused-vars': 1,
|
||||
'no-restricted-exports': ['error'],
|
||||
'no-multi-assign': 1,
|
||||
'no-dupe-class-members': 1,
|
||||
'react/no-deprecated': 1,
|
||||
@ -48,6 +48,7 @@ module.exports = {
|
||||
"afterLineComment": false,
|
||||
"allowBlockStart": true,
|
||||
}],
|
||||
"no-unused-vars": ['error', { "destructuredArrayIgnorePattern": "^_" }],
|
||||
"@typescript-eslint/member-ordering": [
|
||||
"error",
|
||||
{ "default": ["signature", "field", "constructor", "method"] }
|
||||
|
||||
22
.github/workflows/cov packages.yml
vendored
22
.github/workflows/cov packages.yml
vendored
@ -71,4 +71,26 @@ jobs:
|
||||
working-directory: packages/react-simulator-renderer
|
||||
test-script: npm test -- --jest-ci --jest-json --jest-coverage --jest-testLocationInResults --jest-outputFile=report.json
|
||||
package-manager: yarn
|
||||
annotations: none
|
||||
|
||||
cov-utils:
|
||||
runs-on: ubuntu-latest
|
||||
# skip fork's PR, otherwise it fails while making a comment
|
||||
if: ${{ github.event.pull_request.head.repo.full_name == 'alibaba/lowcode-engine' }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
|
||||
- name: install
|
||||
run: npm i && npm run setup:skip-build
|
||||
|
||||
- uses: ArtiomTr/jest-coverage-report-action@v2
|
||||
with:
|
||||
working-directory: packages/utils
|
||||
test-script: npm test
|
||||
package-manager: yarn
|
||||
annotations: none
|
||||
@ -24,5 +24,6 @@
|
||||
- [Ychangqing](https://github.com/Ychangqing)
|
||||
- [yize](https://github.com/yize)
|
||||
- [youluna](https://github.com/youluna)
|
||||
- [ibreathebsb](https://github.com/ibreathebsb)
|
||||
|
||||
如果您贡献过低代码引擎,但是没有看到您的名字,为我们的疏忽感到抱歉。欢迎您通过 PR 补充上自己的名字。
|
||||
|
||||
113
docs/docs/api/model/config.md
Normal file
113
docs/docs/api/model/config.md
Normal file
@ -0,0 +1,113 @@
|
||||
---
|
||||
title: Config
|
||||
sidebar_position: 16
|
||||
---
|
||||
> **@types** [IPublicModelEngineConfig](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/engine-config.ts)<br/>
|
||||
> **@since** v1.1.3
|
||||
|
||||
## 方法
|
||||
### has
|
||||
|
||||
判断指定 key 是否有值
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 判断指定 key 是否有值
|
||||
* check if config has certain key configed
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
has(key: string): boolean;
|
||||
```
|
||||
|
||||
### get
|
||||
|
||||
获取指定 key 的值
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 获取指定 key 的值
|
||||
* get value by key
|
||||
* @param key
|
||||
* @param defaultValue
|
||||
* @returns
|
||||
*/
|
||||
get(key: string, defaultValue?: any): any;
|
||||
```
|
||||
|
||||
### set
|
||||
|
||||
设置指定 key 的值
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 设置指定 key 的值
|
||||
* set value for certain key
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
set(key: string, value: any): void;
|
||||
```
|
||||
|
||||
### setConfig
|
||||
批量设值,set 的对象版本
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 批量设值,set 的对象版本
|
||||
* set multiple config key-values
|
||||
* @param config
|
||||
*/
|
||||
setConfig(config: { [key: string]: any }): void;
|
||||
```
|
||||
|
||||
### getPreference
|
||||
获取全局 Preference, 用于管理全局浏览器侧用户 Preference,如 Panel 是否钉住
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 获取全局 Preference, 用于管理全局浏览器侧用户 Preference,如 Panel 是否钉住
|
||||
* get global user preference manager, which can be use to store
|
||||
* user`s preference in user localstorage, such as a panel is pinned or not.
|
||||
* @returns {IPublicModelPreference}
|
||||
* @since v1.1.0
|
||||
*/
|
||||
getPreference(): IPublicModelPreference;
|
||||
```
|
||||
|
||||
相关类型:[IPublicModelPreference](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/preference.ts)
|
||||
|
||||
## 事件
|
||||
|
||||
### onGot
|
||||
获取指定 key 的值,函数回调模式,若多次被赋值,回调会被多次调用
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 获取指定 key 的值,函数回调模式,若多次被赋值,回调会被多次调用
|
||||
* set callback for event of value set for some key
|
||||
* this will be called each time the value is set
|
||||
* @param key
|
||||
* @param fn
|
||||
* @returns
|
||||
*/
|
||||
onGot(key: string, fn: (data: any) => void): IPublicTypeDisposable;
|
||||
```
|
||||
|
||||
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
|
||||
|
||||
### onceGot
|
||||
获取指定 key 的值,若此时还未赋值,则等待,若已有值,则直接返回值
|
||||
> 注:此函数返回 Promise 实例,只会执行(fullfill)一次
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 获取指定 key 的值,若此时还未赋值,则等待,若已有值,则直接返回值
|
||||
* 注:此函数返回 Promise 实例,只会执行(fullfill)一次
|
||||
* wait until value of certain key is set, will only be
|
||||
* triggered once.
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
onceGot(key: string): Promise<any>;
|
||||
```
|
||||
@ -156,6 +156,21 @@ forEach(fn: (node: IPublicModelNode, index: number) => void): void;
|
||||
|
||||
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
|
||||
|
||||
### reverse
|
||||
|
||||
类似数组的 reverse
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 类似数组的 reverse
|
||||
* provide the same function with {Array.prototype.reverse}
|
||||
*/
|
||||
reverse(): IPublicModelNode[];
|
||||
|
||||
```
|
||||
|
||||
相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts)
|
||||
|
||||
|
||||
### map
|
||||
|
||||
|
||||
@ -645,3 +645,14 @@ setConditionalVisible(): void;
|
||||
```
|
||||
|
||||
**@since v1.1.0**
|
||||
|
||||
### getDOMNode
|
||||
获取节点实例对应的 dom 节点
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 获取节点实例对应的 dom 节点
|
||||
*/
|
||||
getDOMNode(): HTMLElement;
|
||||
|
||||
```
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"lerna": "4.0.0",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": [
|
||||
|
||||
@ -15,6 +15,7 @@ const jestConfig = {
|
||||
// testMatch: ['**/document-model.test.ts'],
|
||||
// testMatch: ['**/prop.test.ts'],
|
||||
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
|
||||
// testMatch: ['**/document/node/node.add.test.ts'],
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})/`,
|
||||
],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-designer",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "Designer for Ali LowCode Engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,9 +15,9 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-editor-core": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.3",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
|
||||
@ -236,17 +236,22 @@ export class BoxResizingInstance extends Component<{
|
||||
|
||||
render() {
|
||||
const { observed } = this.props;
|
||||
if (!observed.hasOffset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { node, offsetWidth, offsetHeight, offsetTop, offsetLeft } = observed;
|
||||
let triggerVisible: any = [];
|
||||
const { advanced } = node.componentMeta;
|
||||
if (advanced.getResizingHandlers) {
|
||||
triggerVisible = advanced.getResizingHandlers(node.internalToShellNode());
|
||||
let offsetWidth = 0;
|
||||
let offsetHeight = 0;
|
||||
let offsetTop = 0;
|
||||
let offsetLeft = 0;
|
||||
if (observed.hasOffset) {
|
||||
offsetWidth = observed.offsetWidth;
|
||||
offsetHeight = observed.offsetHeight;
|
||||
offsetTop = observed.offsetTop;
|
||||
offsetLeft = observed.offsetLeft;
|
||||
const { node } = observed;
|
||||
const metadata = node.componentMeta.getMetadata();
|
||||
if (metadata.configure?.advanced?.getResizingHandlers) {
|
||||
triggerVisible = metadata.configure.advanced.getResizingHandlers(node.internalToShellNode());
|
||||
}
|
||||
}
|
||||
|
||||
triggerVisible = normalizeTriggers(triggerVisible);
|
||||
|
||||
const baseSideClass = 'lc-borders lc-resize-side';
|
||||
@ -254,90 +259,100 @@ export class BoxResizingInstance extends Component<{
|
||||
|
||||
return (
|
||||
<div>
|
||||
{triggerVisible.includes('N') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineN = ref; }}
|
||||
className={classNames(baseSideClass, 'n')}
|
||||
style={{
|
||||
height: 20,
|
||||
transform: `translate(${offsetLeft}px, ${offsetTop - 10}px)`,
|
||||
width: offsetWidth,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('NE') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineNE = ref; }}
|
||||
className={classNames(baseCornerClass, 'ne')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft + offsetWidth - 5}px, ${offsetTop - 3}px)`,
|
||||
cursor: 'nesw-resize',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('E') && (
|
||||
<div
|
||||
className={classNames(baseSideClass, 'e')}
|
||||
ref={(ref) => { this.outlineE = ref; }}
|
||||
style={{
|
||||
height: offsetHeight,
|
||||
transform: `translate(${offsetLeft + offsetWidth - 10}px, ${offsetTop}px)`,
|
||||
width: 20,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('SE') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineSE = ref; }}
|
||||
className={classNames(baseCornerClass, 'se')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft + offsetWidth - 5}px, ${offsetTop + offsetHeight - 5}px)`,
|
||||
cursor: 'nwse-resize',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('S') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineS = ref; }}
|
||||
className={classNames(baseSideClass, 's')}
|
||||
style={{
|
||||
height: 20,
|
||||
transform: `translate(${offsetLeft}px, ${offsetTop + offsetHeight - 10}px)`,
|
||||
width: offsetWidth,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('SW') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineSW = ref; }}
|
||||
className={classNames(baseCornerClass, 'sw')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft - 3}px, ${offsetTop + offsetHeight - 5}px)`,
|
||||
cursor: 'nesw-resize',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('W') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineW = ref; }}
|
||||
className={classNames(baseSideClass, 'w')}
|
||||
style={{
|
||||
height: offsetHeight,
|
||||
transform: `translate(${offsetLeft - 10}px, ${offsetTop}px)`,
|
||||
width: 20,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{triggerVisible.includes('NW') && (
|
||||
<div
|
||||
ref={(ref) => { this.outlineNW = ref; }}
|
||||
className={classNames(baseCornerClass, 'nw')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft - 3}px, ${offsetTop - 3}px)`,
|
||||
cursor: 'nwse-resize',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineN = ref;
|
||||
}}
|
||||
className={classNames(baseSideClass, 'n')}
|
||||
style={{
|
||||
height: 20,
|
||||
transform: `translate(${offsetLeft}px, ${offsetTop - 10}px)`,
|
||||
width: offsetWidth,
|
||||
display: triggerVisible.includes('N') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineNE = ref;
|
||||
}}
|
||||
className={classNames(baseCornerClass, 'ne')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft + offsetWidth - 5}px, ${offsetTop - 3}px)`,
|
||||
cursor: 'nesw-resize',
|
||||
display: triggerVisible.includes('NE') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={classNames(baseSideClass, 'e')}
|
||||
ref={(ref) => {
|
||||
this.outlineE = ref;
|
||||
}}
|
||||
style={{
|
||||
height: offsetHeight,
|
||||
transform: `translate(${offsetLeft + offsetWidth - 10}px, ${offsetTop}px)`,
|
||||
width: 20,
|
||||
display: triggerVisible.includes('E') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineSE = ref;
|
||||
}}
|
||||
className={classNames(baseCornerClass, 'se')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft + offsetWidth - 5}px, ${
|
||||
offsetTop + offsetHeight - 5
|
||||
}px)`,
|
||||
cursor: 'nwse-resize',
|
||||
display: triggerVisible.includes('SE') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineS = ref;
|
||||
}}
|
||||
className={classNames(baseSideClass, 's')}
|
||||
style={{
|
||||
height: 20,
|
||||
transform: `translate(${offsetLeft}px, ${offsetTop + offsetHeight - 10}px)`,
|
||||
width: offsetWidth,
|
||||
display: triggerVisible.includes('S') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineSW = ref;
|
||||
}}
|
||||
className={classNames(baseCornerClass, 'sw')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft - 3}px, ${offsetTop + offsetHeight - 5}px)`,
|
||||
cursor: 'nesw-resize',
|
||||
display: triggerVisible.includes('SW') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineW = ref;
|
||||
}}
|
||||
className={classNames(baseSideClass, 'w')}
|
||||
style={{
|
||||
height: offsetHeight,
|
||||
transform: `translate(${offsetLeft - 10}px, ${offsetTop}px)`,
|
||||
width: 20,
|
||||
display: triggerVisible.includes('W') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.outlineNW = ref;
|
||||
}}
|
||||
className={classNames(baseCornerClass, 'nw')}
|
||||
style={{
|
||||
transform: `translate(${offsetLeft - 3}px, ${offsetTop - 3}px)`,
|
||||
cursor: 'nwse-resize',
|
||||
display: triggerVisible.includes('NW') ? 'flex' : 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -56,7 +56,8 @@ export function buildFilter(rule?: string | string[] | RegExp | IPublicTypeNesti
|
||||
return (testNode: Node | IPublicTypeNodeSchema) => list.includes(testNode.componentName);
|
||||
}
|
||||
|
||||
export interface IComponentMeta extends IPublicModelComponentMeta {
|
||||
export interface IComponentMeta extends IPublicModelComponentMeta<INode> {
|
||||
prototype?: any;
|
||||
}
|
||||
|
||||
export class ComponentMeta implements IComponentMeta {
|
||||
|
||||
@ -30,7 +30,7 @@ import { ActiveTracker, IActiveTracker } from './active-tracker';
|
||||
import { Detecting } from './detecting';
|
||||
import { DropLocation } from './location';
|
||||
import { OffsetObserver, createOffsetObserver } from './offset-observer';
|
||||
import { SettingTopEntry } from './setting';
|
||||
import { ISettingTopEntry, SettingTopEntry } from './setting';
|
||||
import { BemToolsManager } from '../builtin-simulator/bem-tools/manager';
|
||||
import { ComponentActions } from '../component-actions';
|
||||
|
||||
@ -61,6 +61,7 @@ export interface DesignerProps {
|
||||
}
|
||||
|
||||
export interface IDesigner {
|
||||
readonly shellModelFactory: IShellModelFactory;
|
||||
|
||||
get dragon(): IPublicModelDragon;
|
||||
|
||||
@ -70,6 +71,8 @@ export interface IDesigner {
|
||||
|
||||
get editor(): IPublicModelEditor;
|
||||
|
||||
get detecting(): Detecting;
|
||||
|
||||
createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller;
|
||||
|
||||
/**
|
||||
@ -91,6 +94,12 @@ export interface IDesigner {
|
||||
getComponentMetasMap(): Map<string, IComponentMeta>;
|
||||
|
||||
addPropsReducer(reducer: IPublicTypePropsTransducer, stage: IPublicEnumTransformStage): void;
|
||||
|
||||
postEvent(event: string, ...args: any[]): void;
|
||||
|
||||
transformProps(props: IPublicTypeCompositeObject | IPublicTypePropsList, node: Node, stage: IPublicEnumTransformStage): IPublicTypeCompositeObject | IPublicTypePropsList;
|
||||
|
||||
createSettingEntry(nodes: INode[]): ISettingTopEntry;
|
||||
}
|
||||
|
||||
export class Designer implements IDesigner {
|
||||
@ -331,7 +340,7 @@ export class Designer implements IDesigner {
|
||||
this.oobxList.forEach((item) => item.compute());
|
||||
}
|
||||
|
||||
createSettingEntry(nodes: Node[]) {
|
||||
createSettingEntry(nodes: INode[]): ISettingTopEntry {
|
||||
return new SettingTopEntry(this.editor, nodes);
|
||||
}
|
||||
|
||||
|
||||
@ -4,8 +4,11 @@ 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' > {
|
||||
|
||||
export interface IDetecting extends Omit< IPublicModelDetecting<INode>,
|
||||
'capture' |
|
||||
'release' |
|
||||
'leave'
|
||||
> {
|
||||
capture(node: INode | null): void;
|
||||
|
||||
release(node: INode | null): void;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { INode } from '../document';
|
||||
import { IDocumentModel, INode } from '../document';
|
||||
import { ILocateEvent } from './dragon';
|
||||
import {
|
||||
IPublicModelDocumentModel,
|
||||
IPublicModelDropLocation,
|
||||
IPublicTypeLocationDetailType,
|
||||
IPublicTypeRect,
|
||||
@ -105,7 +104,7 @@ export interface IDropLocation extends Omit< IPublicModelDropLocation, 'target'
|
||||
|
||||
get target(): INode;
|
||||
|
||||
get document(): IPublicModelDocumentModel;
|
||||
get document(): IDocumentModel | null;
|
||||
|
||||
clone(event: IPublicModelLocateEvent): IDropLocation;
|
||||
}
|
||||
@ -119,7 +118,7 @@ export class DropLocation implements IDropLocation {
|
||||
|
||||
readonly source: string;
|
||||
|
||||
get document(): IPublicModelDocumentModel {
|
||||
get document(): IDocumentModel | null {
|
||||
return this.target.document;
|
||||
}
|
||||
|
||||
@ -159,7 +158,7 @@ export class DropLocation implements IDropLocation {
|
||||
if (this.detail.index <= 0) {
|
||||
return null;
|
||||
}
|
||||
return this.target.children.get(this.detail.index - 1);
|
||||
return this.target.children?.get(this.detail.index - 1);
|
||||
}
|
||||
return (this.detail as any)?.near?.node;
|
||||
}
|
||||
|
||||
@ -3,15 +3,15 @@ import { IComponentMeta } from '../../component-meta';
|
||||
import { Designer } from '../designer';
|
||||
import { INode } from '../../document';
|
||||
|
||||
export interface SettingEntry extends IPublicModelSettingTarget {
|
||||
export interface ISettingEntry extends IPublicModelSettingTarget {
|
||||
readonly nodes: INode[];
|
||||
readonly componentMeta: IComponentMeta | null;
|
||||
readonly designer: Designer;
|
||||
|
||||
// 顶端
|
||||
readonly top: SettingEntry;
|
||||
readonly top: ISettingEntry;
|
||||
// 父级
|
||||
readonly parent: SettingEntry;
|
||||
readonly parent: ISettingEntry;
|
||||
|
||||
get: (propName: string | number) => SettingEntry | null;
|
||||
get: (propName: string | number) => ISettingEntry | null;
|
||||
}
|
||||
|
||||
@ -9,11 +9,11 @@ import {
|
||||
} from '@alilc/lowcode-types';
|
||||
import { Transducer } from './utils';
|
||||
import { SettingPropEntry } from './setting-prop-entry';
|
||||
import { SettingEntry } from './setting-entry';
|
||||
import { ISettingEntry } from './setting-entry';
|
||||
import { computed, obx, makeObservable, action, untracked, intl } from '@alilc/lowcode-editor-core';
|
||||
import { cloneDeep, isCustomView, isDynamicSetter } from '@alilc/lowcode-utils';
|
||||
|
||||
function getSettingFieldCollectorKey(parent: SettingEntry, config: IPublicTypeFieldConfig) {
|
||||
function getSettingFieldCollectorKey(parent: ISettingEntry, config: IPublicTypeFieldConfig) {
|
||||
let cur = parent;
|
||||
const path = [config.name];
|
||||
while (cur !== parent.top) {
|
||||
@ -25,7 +25,11 @@ function getSettingFieldCollectorKey(parent: SettingEntry, config: IPublicTypeFi
|
||||
return path.join('.');
|
||||
}
|
||||
|
||||
export class SettingField extends SettingPropEntry implements SettingEntry {
|
||||
export interface ISettingField extends ISettingEntry {
|
||||
|
||||
}
|
||||
|
||||
export class SettingField extends SettingPropEntry implements ISettingField {
|
||||
readonly isSettingField = true;
|
||||
|
||||
readonly isRequired: boolean;
|
||||
@ -36,7 +40,7 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
|
||||
|
||||
private hotValue: any;
|
||||
|
||||
parent: SettingEntry;
|
||||
parent: ISettingEntry;
|
||||
|
||||
extraProps: IPublicTypeFieldExtraProps;
|
||||
|
||||
@ -56,9 +60,9 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
|
||||
private _items: Array<SettingField | IPublicTypeCustomView> = [];
|
||||
|
||||
constructor(
|
||||
parent: SettingEntry,
|
||||
parent: ISettingEntry,
|
||||
config: IPublicTypeFieldConfig,
|
||||
settingFieldCollector?: (name: string | number, field: SettingField) => void,
|
||||
private settingFieldCollector?: (name: string | number, field: SettingField) => void,
|
||||
) {
|
||||
super(parent, config.name, config.type);
|
||||
makeObservable(this);
|
||||
@ -137,7 +141,8 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
|
||||
|
||||
// 创建子配置项,通常用于 object/array 类型数据
|
||||
createField(config: IPublicTypeFieldConfig): SettingField {
|
||||
return new SettingField(this, config);
|
||||
this.settingFieldCollector?.(getSettingFieldCollectorKey(this.parent, config), this);
|
||||
return new SettingField(this, config, this.settingFieldCollector);
|
||||
}
|
||||
|
||||
purge() {
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { obx, computed, makeObservable, runInAction, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
|
||||
import { GlobalEvent, IPublicModelEditor, IPublicTypeSetValueOptions } from '@alilc/lowcode-types';
|
||||
import { uniqueId, isJSExpression, isSettingField } from '@alilc/lowcode-utils';
|
||||
import { SettingEntry } from './setting-entry';
|
||||
import { Setters } from '@alilc/lowcode-shell';
|
||||
import { ISettingEntry } from './setting-entry';
|
||||
import { INode } from '../../document';
|
||||
import { IComponentMeta } from '../../component-meta';
|
||||
import { Designer } from '../designer';
|
||||
import { Setters } from '@alilc/lowcode-shell';
|
||||
import { ISettingField } from './setting-field';
|
||||
|
||||
export class SettingPropEntry implements SettingEntry {
|
||||
export class SettingPropEntry implements ISettingEntry {
|
||||
// === static properties ===
|
||||
readonly editor: IPublicModelEditor;
|
||||
|
||||
@ -25,7 +26,7 @@ export class SettingPropEntry implements SettingEntry {
|
||||
|
||||
readonly designer: Designer;
|
||||
|
||||
readonly top: SettingEntry;
|
||||
readonly top: ISettingEntry;
|
||||
|
||||
readonly isGroup: boolean;
|
||||
|
||||
@ -52,7 +53,7 @@ export class SettingPropEntry implements SettingEntry {
|
||||
|
||||
extraProps: any = {};
|
||||
|
||||
constructor(readonly parent: SettingEntry, name: string | number, type?: 'field' | 'group') {
|
||||
constructor(readonly parent: ISettingEntry | ISettingField, name: string | number, type?: 'field' | 'group') {
|
||||
makeObservable(this);
|
||||
if (type == null) {
|
||||
const c = typeof name === 'string' ? name.slice(0, 1) : '';
|
||||
|
||||
@ -1,22 +1,26 @@
|
||||
import { IPublicTypeCustomView, IPublicModelEditor } from '@alilc/lowcode-types';
|
||||
import { isCustomView } from '@alilc/lowcode-utils';
|
||||
import { computed, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
|
||||
import { SettingEntry } from './setting-entry';
|
||||
import { ISettingEntry } from './setting-entry';
|
||||
import { SettingField } from './setting-field';
|
||||
import { SettingPropEntry } from './setting-prop-entry';
|
||||
import { Node } from '../../document';
|
||||
import { INode } from '../../document';
|
||||
import { ComponentMeta } from '../../component-meta';
|
||||
import { Designer } from '../designer';
|
||||
import { IDesigner } from '../designer';
|
||||
import { Setters } from '@alilc/lowcode-shell';
|
||||
|
||||
function generateSessionId(nodes: Node[]) {
|
||||
function generateSessionId(nodes: INode[]) {
|
||||
return nodes
|
||||
.map((node) => node.id)
|
||||
.sort()
|
||||
.join(',');
|
||||
}
|
||||
|
||||
export class SettingTopEntry implements SettingEntry {
|
||||
export interface ISettingTopEntry extends ISettingEntry {
|
||||
purge(): void;
|
||||
}
|
||||
|
||||
export class SettingTopEntry implements ISettingTopEntry {
|
||||
private emitter: IEventBus = createModuleEventBus('SettingTopEntry');
|
||||
|
||||
private _items: Array<SettingField | IPublicTypeCustomView> = [];
|
||||
@ -68,21 +72,21 @@ export class SettingTopEntry implements SettingEntry {
|
||||
|
||||
readonly id: string;
|
||||
|
||||
readonly first: Node;
|
||||
readonly first: INode;
|
||||
|
||||
readonly designer: Designer;
|
||||
readonly designer: IDesigner | undefined;
|
||||
|
||||
readonly setters: Setters;
|
||||
|
||||
disposeFunctions: any[] = [];
|
||||
|
||||
constructor(readonly editor: IPublicModelEditor, readonly nodes: Node[]) {
|
||||
constructor(readonly editor: IPublicModelEditor, readonly nodes: INode[]) {
|
||||
if (!Array.isArray(nodes) || nodes.length < 1) {
|
||||
throw new ReferenceError('nodes should not be empty');
|
||||
}
|
||||
this.id = generateSessionId(nodes);
|
||||
this.first = nodes[0];
|
||||
this.designer = this.first.document.designer;
|
||||
this.designer = this.first.document?.designer;
|
||||
this.setters = editor.get('setters') as Setters;
|
||||
|
||||
// setups
|
||||
@ -229,7 +233,6 @@ export class SettingTopEntry implements SettingEntry {
|
||||
this.disposeFunctions = [];
|
||||
}
|
||||
|
||||
|
||||
getProp(propName: string | number) {
|
||||
return this.get(propName);
|
||||
}
|
||||
|
||||
@ -1,4 +1,13 @@
|
||||
import { makeObservable, obx, engineConfig, action, runWithGlobalEventOff, wrapWithEventSwitch, createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core';
|
||||
import {
|
||||
makeObservable,
|
||||
obx,
|
||||
engineConfig,
|
||||
action,
|
||||
runWithGlobalEventOff,
|
||||
wrapWithEventSwitch,
|
||||
createModuleEventBus,
|
||||
IEventBus,
|
||||
} from '@alilc/lowcode-editor-core';
|
||||
import {
|
||||
IPublicTypeNodeData,
|
||||
IPublicTypeNodeSchema,
|
||||
@ -8,20 +17,32 @@ import {
|
||||
IPublicTypeDragNodeObject,
|
||||
IPublicTypeDragNodeDataObject,
|
||||
IPublicModelDocumentModel,
|
||||
IPublicModelHistory,
|
||||
IPublicModelNode,
|
||||
IPublicEnumTransformStage,
|
||||
IPublicTypeOnChangeOptions,
|
||||
IPublicTypeDisposable,
|
||||
} from '@alilc/lowcode-types';
|
||||
import {
|
||||
IDropLocation,
|
||||
} from '@alilc/lowcode-designer';
|
||||
import {
|
||||
uniqueId,
|
||||
isPlainObject,
|
||||
compatStage,
|
||||
isJSExpression,
|
||||
isDOMText,
|
||||
isNodeSchema,
|
||||
isDragNodeObject,
|
||||
isDragNodeDataObject,
|
||||
isNode,
|
||||
} from '@alilc/lowcode-utils';
|
||||
import { IProject, Project } from '../project';
|
||||
import { ISimulatorHost } from '../simulator';
|
||||
import { ComponentMeta } from '../component-meta';
|
||||
import { IDropLocation, Designer, IHistory } from '../designer';
|
||||
import { Node, insertChildren, insertChild, RootNode, INode } from './node/node';
|
||||
import { IComponentMeta } from '../component-meta';
|
||||
import { IDesigner, IHistory } from '../designer';
|
||||
import { insertChildren, insertChild, RootNode, INode } from './node/node';
|
||||
import { Selection, ISelection } from './selection';
|
||||
import { History } from './history';
|
||||
import { IModalNodesManager, ModalNodesManager } from './node';
|
||||
import { uniqueId, isPlainObject, compatStage, isJSExpression, isDOMText, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isNode } from '@alilc/lowcode-utils';
|
||||
import { IModalNodesManager, ModalNodesManager, Node } from './node';
|
||||
import { EDITOR_EVENT } from '../types';
|
||||
|
||||
export type GetDataType<T, NodeType> = T extends undefined
|
||||
@ -32,21 +53,41 @@ export type GetDataType<T, NodeType> = T extends undefined
|
||||
: any
|
||||
: T;
|
||||
|
||||
export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'selection' | 'checkNesting' > {
|
||||
export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
|
||||
ISelection,
|
||||
IHistory,
|
||||
INode | RootNode,
|
||||
IDropLocation,
|
||||
IModalNodesManager,
|
||||
IProject
|
||||
>,
|
||||
'detecting' |
|
||||
'checkNesting' |
|
||||
'getNodeById' |
|
||||
// 以下属性在内部的 document 中不存在
|
||||
'exportSchema' |
|
||||
'importSchema' |
|
||||
'onAddNode' |
|
||||
'onRemoveNode' |
|
||||
'onChangeDetecting' |
|
||||
'onChangeSelection' |
|
||||
'onMountNode' |
|
||||
'onChangeNodeProp' |
|
||||
'onImportSchema' |
|
||||
'isDetectingNode' |
|
||||
'onFocusNodeChanged' |
|
||||
'onDropLocationChanged'
|
||||
> {
|
||||
|
||||
readonly designer: Designer;
|
||||
readonly designer: IDesigner;
|
||||
|
||||
/**
|
||||
* 选区控制
|
||||
*/
|
||||
readonly selection: ISelection;
|
||||
get rootNode(): INode | null;
|
||||
|
||||
readonly project: IProject;
|
||||
get simulator(): ISimulatorHost | null;
|
||||
|
||||
/**
|
||||
* 模态节点管理
|
||||
*/
|
||||
readonly modalNodesManager: IModalNodesManager;
|
||||
get active(): boolean;
|
||||
|
||||
get nodesMap(): Map<string, INode>;
|
||||
|
||||
/**
|
||||
* 根据 id 获取节点
|
||||
@ -55,16 +96,32 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'select
|
||||
|
||||
getHistory(): IHistory;
|
||||
|
||||
get focusNode(): INode | null;
|
||||
|
||||
get rootNode(): INode | null;
|
||||
|
||||
checkNesting(
|
||||
dropTarget: INode,
|
||||
dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject,
|
||||
): boolean;
|
||||
|
||||
getNodeCount(): number;
|
||||
|
||||
nextId(possibleId: string | undefined): string;
|
||||
|
||||
import(schema: IPublicTypeRootSchema, checkId?: boolean): void;
|
||||
|
||||
export(stage: IPublicEnumTransformStage): IPublicTypeRootSchema | undefined;
|
||||
|
||||
onNodeCreate(func: (node: INode) => void): IPublicTypeDisposable;
|
||||
|
||||
onNodeDestroy(func: (node: INode) => void): IPublicTypeDisposable;
|
||||
|
||||
onChangeNodeVisible(fn: (node: INode, visible: boolean) => void): IPublicTypeDisposable;
|
||||
|
||||
addWillPurge(node: INode): void;
|
||||
|
||||
removeWillPurge(node: INode): void;
|
||||
|
||||
getComponentMeta(componentName: string): IComponentMeta;
|
||||
|
||||
insertNodes(parent: INode, thing: INode[] | IPublicTypeNodeData[], at?: number | null, copy?: boolean): INode[];
|
||||
}
|
||||
|
||||
export class DocumentModel implements IDocumentModel {
|
||||
@ -86,20 +143,20 @@ export class DocumentModel implements IDocumentModel {
|
||||
/**
|
||||
* 操作记录控制
|
||||
*/
|
||||
readonly history: IPublicModelHistory;
|
||||
readonly history: IHistory;
|
||||
|
||||
/**
|
||||
* 模态节点管理
|
||||
*/
|
||||
readonly modalNodesManager: IModalNodesManager;
|
||||
modalNodesManager: IModalNodesManager;
|
||||
|
||||
private _nodesMap = new Map<string, IPublicModelNode>();
|
||||
private _nodesMap = new Map<string, INode>();
|
||||
|
||||
readonly project: IProject;
|
||||
|
||||
readonly designer: Designer;
|
||||
readonly designer: IDesigner;
|
||||
|
||||
@obx.shallow private nodes = new Set<IPublicModelNode>();
|
||||
@obx.shallow private nodes = new Set<INode>();
|
||||
|
||||
private seqId = 0;
|
||||
|
||||
@ -119,7 +176,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
return this.project.simulator;
|
||||
}
|
||||
|
||||
get nodesMap(): Map<string, Node> {
|
||||
get nodesMap(): Map<string, INode> {
|
||||
return this._nodesMap;
|
||||
}
|
||||
|
||||
@ -131,7 +188,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
this.rootNode?.getExtraProp('fileName', true)?.setValue(fileName);
|
||||
}
|
||||
|
||||
get focusNode(): INode {
|
||||
get focusNode(): INode | null {
|
||||
if (this._drillDownNode) {
|
||||
return this._drillDownNode;
|
||||
}
|
||||
@ -142,7 +199,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
return this.rootNode;
|
||||
}
|
||||
|
||||
@obx.ref private _drillDownNode: Node | null = null;
|
||||
@obx.ref private _drillDownNode: INode | null = null;
|
||||
|
||||
private _modalNode?: INode;
|
||||
|
||||
@ -150,7 +207,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
|
||||
private inited = false;
|
||||
|
||||
@obx.shallow private willPurgeSpace: Node[] = [];
|
||||
@obx.shallow private willPurgeSpace: INode[] = [];
|
||||
|
||||
get modalNode() {
|
||||
return this._modalNode;
|
||||
@ -160,7 +217,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
return this.modalNode || this.focusNode;
|
||||
}
|
||||
|
||||
@obx.shallow private activeNodes?: Node[];
|
||||
@obx.shallow private activeNodes?: INode[];
|
||||
|
||||
@obx.ref private _dropLocation: IDropLocation | null = null;
|
||||
|
||||
@ -236,7 +293,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
// 兼容 vision
|
||||
this.id = project.getSchema()?.id || this.id;
|
||||
|
||||
this.rootNode = this.createNode<RootNode>(
|
||||
this.rootNode = this.createNode(
|
||||
schema || {
|
||||
componentName: 'Page',
|
||||
id: 'root',
|
||||
@ -257,11 +314,11 @@ export class DocumentModel implements IDocumentModel {
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
drillDown(node: Node | null) {
|
||||
drillDown(node: INode | null) {
|
||||
this._drillDownNode = node;
|
||||
}
|
||||
|
||||
onChangeNodeVisible(fn: (node: IPublicModelNode, visible: boolean) => void): () => void {
|
||||
onChangeNodeVisible(fn: (node: INode, visible: boolean) => void): IPublicTypeDisposable {
|
||||
this.designer.editor?.eventBus.on(EDITOR_EVENT.NODE_CHILDREN_CHANGE, fn);
|
||||
|
||||
return () => {
|
||||
@ -269,7 +326,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
};
|
||||
}
|
||||
|
||||
onChangeNodeChildren(fn: (info: IPublicTypeOnChangeOptions) => void): () => void {
|
||||
onChangeNodeChildren(fn: (info: IPublicTypeOnChangeOptions<INode>) => void): IPublicTypeDisposable {
|
||||
this.designer.editor?.eventBus.on(EDITOR_EVENT.NODE_VISIBLE_CHANGE, fn);
|
||||
|
||||
return () => {
|
||||
@ -277,11 +334,11 @@ export class DocumentModel implements IDocumentModel {
|
||||
};
|
||||
}
|
||||
|
||||
addWillPurge(node: Node) {
|
||||
addWillPurge(node: INode) {
|
||||
this.willPurgeSpace.push(node);
|
||||
}
|
||||
|
||||
removeWillPurge(node: Node) {
|
||||
removeWillPurge(node: INode) {
|
||||
const i = this.willPurgeSpace.indexOf(node);
|
||||
if (i > -1) {
|
||||
this.willPurgeSpace.splice(i, 1);
|
||||
@ -295,7 +352,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
/**
|
||||
* 生成唯一 id
|
||||
*/
|
||||
nextId(possibleId: string | undefined) {
|
||||
nextId(possibleId: string | undefined): string {
|
||||
let id = possibleId;
|
||||
while (!id || this.nodesMap.get(id)) {
|
||||
id = `node_${(String(this.id).slice(-10) + (++this.seqId).toString(36)).toLocaleLowerCase()}`;
|
||||
@ -330,7 +387,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
* 根据 schema 创建一个节点
|
||||
*/
|
||||
@action
|
||||
createNode<T extends Node = Node, C = undefined>(data: GetDataType<C, T>, checkId: boolean = true): T {
|
||||
createNode<T extends INode = INode, C = undefined>(data: GetDataType<C, T>): T {
|
||||
let schema: any;
|
||||
if (isDOMText(data) || isJSExpression(data)) {
|
||||
schema = {
|
||||
@ -341,7 +398,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
schema = data;
|
||||
}
|
||||
|
||||
let node: Node | null = null;
|
||||
let node: INode | null = null;
|
||||
if (this.hasNode(schema?.id)) {
|
||||
schema.id = null;
|
||||
}
|
||||
@ -361,7 +418,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
node = new Node(this, schema, { checkId });
|
||||
node = new Node(this, schema);
|
||||
// will add
|
||||
// todo: this.activeNodes?.push(node);
|
||||
}
|
||||
@ -373,30 +430,30 @@ export class DocumentModel implements IDocumentModel {
|
||||
return node as any;
|
||||
}
|
||||
|
||||
public destroyNode(node: Node) {
|
||||
public destroyNode(node: INode) {
|
||||
this.emitter.emit('nodedestroy', node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入一个节点
|
||||
*/
|
||||
insertNode(parent: INode, thing: Node | IPublicTypeNodeData, at?: number | null, copy?: boolean): Node {
|
||||
insertNode(parent: INode, thing: INode | IPublicTypeNodeData, at?: number | null, copy?: boolean): INode | null {
|
||||
return insertChild(parent, thing, at, copy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入多个节点
|
||||
*/
|
||||
insertNodes(parent: INode, thing: Node[] | IPublicTypeNodeData[], at?: number | null, copy?: boolean) {
|
||||
insertNodes(parent: INode, thing: INode[] | IPublicTypeNodeData[], at?: number | null, copy?: boolean) {
|
||||
return insertChildren(parent, thing, at, copy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除一个节点
|
||||
*/
|
||||
removeNode(idOrNode: string | Node) {
|
||||
removeNode(idOrNode: string | INode) {
|
||||
let id: string;
|
||||
let node: Node | null;
|
||||
let node: INode | null = null;
|
||||
if (typeof idOrNode === 'string') {
|
||||
id = idOrNode;
|
||||
node = this.getNode(id);
|
||||
@ -413,14 +470,14 @@ export class DocumentModel implements IDocumentModel {
|
||||
/**
|
||||
* 内部方法,请勿调用
|
||||
*/
|
||||
internalRemoveAndPurgeNode(node: Node, useMutator = false) {
|
||||
internalRemoveAndPurgeNode(node: INode, useMutator = false) {
|
||||
if (!this.nodes.has(node)) {
|
||||
return;
|
||||
}
|
||||
node.remove(useMutator);
|
||||
}
|
||||
|
||||
unlinkNode(node: Node) {
|
||||
unlinkNode(node: INode) {
|
||||
this.nodes.delete(node);
|
||||
this._nodesMap.delete(node.id);
|
||||
}
|
||||
@ -428,7 +485,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
/**
|
||||
* 包裹当前选区中的节点
|
||||
*/
|
||||
wrapWith(schema: IPublicTypeNodeSchema): Node | null {
|
||||
wrapWith(schema: IPublicTypeNodeSchema): INode | null {
|
||||
const nodes = this.selection.getTopNodes();
|
||||
if (nodes.length < 1) {
|
||||
return null;
|
||||
@ -465,17 +522,17 @@ export class DocumentModel implements IDocumentModel {
|
||||
});
|
||||
}
|
||||
|
||||
export(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Serilize) {
|
||||
export(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Serilize): IPublicTypeRootSchema | undefined {
|
||||
stage = compatStage(stage);
|
||||
// 置顶只作用于 Page 的第一级子节点,目前还用不到里层的置顶;如果后面有需要可以考虑将这段写到 node-children 中的 export
|
||||
const currentSchema = this.rootNode?.export(stage);
|
||||
if (Array.isArray(currentSchema?.children) && currentSchema?.children.length > 0) {
|
||||
const FixedTopNodeIndex = currentSchema.children
|
||||
const currentSchema = this.rootNode?.export<IPublicTypeRootSchema>(stage);
|
||||
if (Array.isArray(currentSchema?.children) && currentSchema?.children?.length && currentSchema?.children?.length > 0) {
|
||||
const FixedTopNodeIndex = currentSchema?.children
|
||||
.filter(i => isPlainObject(i))
|
||||
.findIndex((i => (i as IPublicTypeNodeSchema).props?.__isTopFixed__));
|
||||
if (FixedTopNodeIndex > 0) {
|
||||
const FixedTopNode = currentSchema.children.splice(FixedTopNodeIndex, 1);
|
||||
currentSchema.children.unshift(FixedTopNode[0]);
|
||||
const FixedTopNode = currentSchema?.children.splice(FixedTopNodeIndex, 1);
|
||||
currentSchema?.children.unshift(FixedTopNode[0]);
|
||||
}
|
||||
}
|
||||
return currentSchema;
|
||||
@ -504,7 +561,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
return this.simulator!.getComponent(componentName);
|
||||
}
|
||||
|
||||
getComponentMeta(componentName: string): ComponentMeta {
|
||||
getComponentMeta(componentName: string): IComponentMeta {
|
||||
return this.designer.getComponentMeta(
|
||||
componentName,
|
||||
() => this.simulator?.generateComponentMetadata(componentName) || null,
|
||||
@ -579,10 +636,10 @@ export class DocumentModel implements IDocumentModel {
|
||||
dropTarget: INode,
|
||||
dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject,
|
||||
): boolean {
|
||||
let items: Array<Node | IPublicTypeNodeSchema>;
|
||||
let items: Array<INode | IPublicTypeNodeSchema>;
|
||||
if (isDragNodeDataObject(dragObject)) {
|
||||
items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
|
||||
} else if (isDragNodeObject(dragObject)) {
|
||||
} else if (isDragNodeObject<INode>(dragObject)) {
|
||||
items = dragObject.nodes;
|
||||
} else if (isNode(dragObject) || isNodeSchema(dragObject)) {
|
||||
items = [dragObject];
|
||||
@ -599,11 +656,13 @@ export class DocumentModel implements IDocumentModel {
|
||||
* Use checkNesting method instead.
|
||||
*/
|
||||
checkDropTarget(dropTarget: INode, dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject): boolean {
|
||||
let items: Array<Node | IPublicTypeNodeSchema>;
|
||||
let items: Array<INode | IPublicTypeNodeSchema>;
|
||||
if (isDragNodeDataObject(dragObject)) {
|
||||
items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
|
||||
} else {
|
||||
} else if (isDragNodeObject<INode>(dragObject)) {
|
||||
items = dragObject.nodes;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return items.every((item) => this.checkNestingUp(dropTarget, item));
|
||||
}
|
||||
@ -611,7 +670,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
/**
|
||||
* 检查对象对父级的要求,涉及配置 parentWhitelist
|
||||
*/
|
||||
checkNestingUp(parent: INode, obj: IPublicTypeNodeSchema | Node): boolean {
|
||||
checkNestingUp(parent: INode, obj: IPublicTypeNodeSchema | INode): boolean {
|
||||
if (isNode(obj) || isNodeSchema(obj)) {
|
||||
const config = isNode(obj) ? obj.componentMeta : this.getComponentMeta(obj.componentName);
|
||||
if (config) {
|
||||
@ -625,7 +684,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
/**
|
||||
* 检查投放位置对子级的要求,涉及配置 childWhitelist
|
||||
*/
|
||||
checkNestingDown(parent: INode, obj: IPublicTypeNodeSchema | Node): boolean {
|
||||
checkNestingDown(parent: INode, obj: IPublicTypeNodeSchema | INode): boolean {
|
||||
const config = parent.componentMeta;
|
||||
return config.checkNestingDown(parent, obj);
|
||||
}
|
||||
@ -666,7 +725,9 @@ export class DocumentModel implements IDocumentModel {
|
||||
*/
|
||||
/* istanbul ignore next */
|
||||
exportAddonData() {
|
||||
const addons = {};
|
||||
const addons: {
|
||||
[key: string]: any;
|
||||
} = {};
|
||||
this._addons.forEach((addon) => {
|
||||
const data = addon.exportData();
|
||||
if (data === null) {
|
||||
@ -806,7 +867,7 @@ export class DocumentModel implements IDocumentModel {
|
||||
onReady(fn: Function) {
|
||||
this.designer.editor.eventBus.on('document-open', fn);
|
||||
return () => {
|
||||
this.designer.editor.removeListener('document-open', fn);
|
||||
this.designer.editor.eventBus.off('document-open', fn);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,30 @@
|
||||
import { obx, computed, makeObservable } from '@alilc/lowcode-editor-core';
|
||||
import { uniqueId } from '@alilc/lowcode-utils';
|
||||
import { IPublicTypeTitleContent, IPublicModelExclusiveGroup } from '@alilc/lowcode-types';
|
||||
import { Node } from './node';
|
||||
import { INode } from './node';
|
||||
import { intl } from '../../locale';
|
||||
|
||||
export interface IExclusiveGroup extends IPublicModelExclusiveGroup<INode> {
|
||||
readonly name: string;
|
||||
|
||||
remove(node: INode): void;
|
||||
|
||||
add(node: INode): void;
|
||||
|
||||
isVisible(node: INode): boolean;
|
||||
}
|
||||
|
||||
// modals assoc x-hide value, initial: check is Modal, yes will put it in modals, cross levels
|
||||
// if-else-if assoc conditionGroup value, should be the same level,
|
||||
// and siblings, need renderEngine support
|
||||
export class ExclusiveGroup implements IPublicModelExclusiveGroup {
|
||||
export class ExclusiveGroup implements IExclusiveGroup {
|
||||
readonly isExclusiveGroup = true;
|
||||
|
||||
readonly id = uniqueId('exclusive');
|
||||
|
||||
@obx.shallow readonly children: Node[] = [];
|
||||
readonly title: IPublicTypeTitleContent;
|
||||
|
||||
@obx.shallow readonly children: INode[] = [];
|
||||
|
||||
@obx private visibleIndex = 0;
|
||||
|
||||
@ -28,11 +40,11 @@ export class ExclusiveGroup implements IPublicModelExclusiveGroup {
|
||||
return this.children.length;
|
||||
}
|
||||
|
||||
@computed get visibleNode(): Node {
|
||||
@computed get visibleNode(): INode {
|
||||
return this.children[this.visibleIndex];
|
||||
}
|
||||
|
||||
@computed get firstNode(): Node {
|
||||
@computed get firstNode(): INode {
|
||||
return this.children[0]!;
|
||||
}
|
||||
|
||||
@ -40,8 +52,16 @@ export class ExclusiveGroup implements IPublicModelExclusiveGroup {
|
||||
return this.firstNode.index;
|
||||
}
|
||||
|
||||
add(node: Node) {
|
||||
if (node.nextSibling && node.nextSibling.conditionGroup === this) {
|
||||
constructor(readonly name: string, title?: IPublicTypeTitleContent) {
|
||||
makeObservable(this);
|
||||
this.title = title || {
|
||||
type: 'i18n',
|
||||
intl: intl('Condition Group'),
|
||||
};
|
||||
}
|
||||
|
||||
add(node: INode) {
|
||||
if (node.nextSibling && node.nextSibling.conditionGroup?.id === this.id) {
|
||||
const i = this.children.indexOf(node.nextSibling);
|
||||
this.children.splice(i, 0, node);
|
||||
} else {
|
||||
@ -49,7 +69,7 @@ export class ExclusiveGroup implements IPublicModelExclusiveGroup {
|
||||
}
|
||||
}
|
||||
|
||||
remove(node: Node) {
|
||||
remove(node: INode) {
|
||||
const i = this.children.indexOf(node);
|
||||
if (i > -1) {
|
||||
this.children.splice(i, 1);
|
||||
@ -61,27 +81,17 @@ export class ExclusiveGroup implements IPublicModelExclusiveGroup {
|
||||
}
|
||||
}
|
||||
|
||||
setVisible(node: Node) {
|
||||
setVisible(node: INode) {
|
||||
const i = this.children.indexOf(node);
|
||||
if (i > -1) {
|
||||
this.visibleIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
isVisible(node: Node) {
|
||||
isVisible(node: INode) {
|
||||
const i = this.children.indexOf(node);
|
||||
return i === this.visibleIndex;
|
||||
}
|
||||
|
||||
readonly title: IPublicTypeTitleContent;
|
||||
|
||||
constructor(readonly name: string, title?: IPublicTypeTitleContent) {
|
||||
makeObservable(this);
|
||||
this.title = title || {
|
||||
type: 'i18n',
|
||||
intl: intl('Condition Group'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function isExclusiveGroup(obj: any): obj is ExclusiveGroup {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { INode, Node } from './node';
|
||||
import { INode } 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: INode | Node) {
|
||||
export function getModalNodes(node: INode) {
|
||||
if (!node) return [];
|
||||
let nodes: any = [];
|
||||
if (node.componentMeta.isModal) {
|
||||
@ -18,11 +18,7 @@ export function getModalNodes(node: INode | Node) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
export interface IModalNodesManager extends IPublicModelModalNodesManager {
|
||||
|
||||
getModalNodes(): INode[];
|
||||
|
||||
getVisibleModalNode(): INode | null;
|
||||
export interface IModalNodesManager extends IPublicModelModalNodesManager<INode> {
|
||||
}
|
||||
|
||||
export class ModalNodesManager implements IModalNodesManager {
|
||||
@ -87,7 +83,7 @@ export class ModalNodesManager implements IModalNodesManager {
|
||||
}
|
||||
|
||||
private addNode(node: INode) {
|
||||
if (node.componentMeta.isModal) {
|
||||
if (node?.componentMeta.isModal) {
|
||||
this.hideModalNodes();
|
||||
this.modalNodes.push(node);
|
||||
this.addNodeEvent(node);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { obx, computed, globalContext, makeObservable, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
|
||||
import { Node, INode } from './node';
|
||||
import { IPublicTypeNodeData, IPublicModelNodeChildren, IPublicEnumTransformStage } from '@alilc/lowcode-types';
|
||||
import { IPublicTypeNodeData, IPublicModelNodeChildren, IPublicEnumTransformStage, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
||||
import { shallowEqual, compatStage, isNodeSchema } from '@alilc/lowcode-utils';
|
||||
import { foreachReverse } from '../../utils/tree';
|
||||
import { NodeRemoveOptions } from '../../types';
|
||||
@ -10,9 +10,16 @@ export interface IOnChangeOptions {
|
||||
node: Node;
|
||||
}
|
||||
|
||||
export interface INodeChildren extends Omit<IPublicModelNodeChildren, 'forEach' | 'map' | 'every' | 'some' | 'filter' | 'find' | 'reduce' | 'mergeChildren' > {
|
||||
export interface INodeChildren extends Omit<IPublicModelNodeChildren<INode>,
|
||||
'importSchema' |
|
||||
'exportSchema' |
|
||||
'isEmpty' |
|
||||
'notEmpty'
|
||||
> {
|
||||
get owner(): INode;
|
||||
|
||||
get length(): number;
|
||||
|
||||
unlinkChild(node: INode): void;
|
||||
|
||||
/**
|
||||
@ -42,29 +49,19 @@ export interface INodeChildren extends Omit<IPublicModelNodeChildren, 'forEach'
|
||||
|
||||
forEach(fn: (item: INode, index: number) => void): void;
|
||||
|
||||
map<T>(fn: (item: INode, index: number) => T): T[] | null;
|
||||
|
||||
every(fn: (item: INode, index: number) => any): boolean;
|
||||
|
||||
some(fn: (item: INode, index: number) => any): boolean;
|
||||
|
||||
filter(fn: (item: INode, index: number) => any): any;
|
||||
|
||||
find(fn: (item: INode, index: number) => boolean): any;
|
||||
|
||||
reduce(fn: (acc: any, cur: INode) => any, initialValue: any): void;
|
||||
|
||||
mergeChildren(
|
||||
remover: (node: INode, idx: number) => boolean,
|
||||
adder: (children: INode[]) => IPublicTypeNodeData[] | null,
|
||||
sorter: (firstNode: INode, secondNode: INode) => number,
|
||||
): any;
|
||||
|
||||
/**
|
||||
* 根据索引获得节点
|
||||
*/
|
||||
get(index: number): INode | null;
|
||||
|
||||
isEmpty(): boolean;
|
||||
|
||||
notEmpty(): boolean;
|
||||
|
||||
internalInitParent(): void;
|
||||
|
||||
onChange(fn: (info?: IOnChangeOptions) => void): IPublicTypeDisposable;
|
||||
|
||||
/** overriding methods end */
|
||||
}
|
||||
export class NodeChildren implements INodeChildren {
|
||||
@ -138,12 +135,12 @@ export class NodeChildren implements INodeChildren {
|
||||
const child = originChildren[i];
|
||||
const item = data[i];
|
||||
|
||||
let node: Node | undefined;
|
||||
let node: INode | undefined | null;
|
||||
if (isNodeSchema(item) && !checkId && child && child.componentName === item.componentName) {
|
||||
node = child;
|
||||
node.import(item);
|
||||
} else {
|
||||
node = this.owner.document.createNode(item, checkId);
|
||||
node = this.owner.document?.createNode(item, checkId);
|
||||
}
|
||||
children[i] = node;
|
||||
}
|
||||
@ -434,7 +431,7 @@ export class NodeChildren implements INodeChildren {
|
||||
return this.children.filter(fn);
|
||||
}
|
||||
|
||||
find(fn: (item: INode, index: number) => boolean) {
|
||||
find(fn: (item: INode, index: number) => boolean): INode | undefined {
|
||||
return this.children.find(fn);
|
||||
}
|
||||
|
||||
@ -442,6 +439,10 @@ export class NodeChildren implements INodeChildren {
|
||||
return this.children.reduce(fn, initialValue);
|
||||
}
|
||||
|
||||
reverse() {
|
||||
return this.children.reverse();
|
||||
}
|
||||
|
||||
mergeChildren(
|
||||
remover: (node: INode, idx: number) => boolean,
|
||||
adder: (children: INode[]) => IPublicTypeNodeData[] | null,
|
||||
@ -465,7 +466,7 @@ export class NodeChildren implements INodeChildren {
|
||||
const items = adder(this.children);
|
||||
if (items && items.length > 0) {
|
||||
items.forEach((child: IPublicTypeNodeData) => {
|
||||
const node = this.owner.document?.createNode(child);
|
||||
const node: INode = this.owner.document?.createNode(child);
|
||||
this.children.push(node);
|
||||
node.internalSetParent(this.owner);
|
||||
});
|
||||
@ -481,7 +482,7 @@ export class NodeChildren implements INodeChildren {
|
||||
}
|
||||
}
|
||||
|
||||
onChange(fn: (info?: IOnChangeOptions) => void): () => void {
|
||||
onChange(fn: (info?: IOnChangeOptions) => void): IPublicTypeDisposable {
|
||||
this.emitter.on('change', fn);
|
||||
return () => {
|
||||
this.emitter.removeListener('change', fn);
|
||||
|
||||
@ -16,15 +16,16 @@ import {
|
||||
IPublicModelExclusiveGroup,
|
||||
IPublicEnumTransformStage,
|
||||
IPublicTypeDisposable,
|
||||
IBaseModelNode,
|
||||
} from '@alilc/lowcode-types';
|
||||
import { compatStage, isDOMText, isJSExpression, isNode } from '@alilc/lowcode-utils';
|
||||
import { SettingTopEntry } from '@alilc/lowcode-designer';
|
||||
import { compatStage, isDOMText, isJSExpression, isNode, isNodeSchema } from '@alilc/lowcode-utils';
|
||||
import { ISettingTopEntry } from '@alilc/lowcode-designer';
|
||||
import { Props, getConvertedExtraKey, IProps } from './props/props';
|
||||
import { DocumentModel, IDocumentModel } from '../document-model';
|
||||
import { IDocumentModel } from '../document-model';
|
||||
import { NodeChildren, INodeChildren } from './node-children';
|
||||
import { IProp, Prop } from './props/prop';
|
||||
import { ComponentMeta, IComponentMeta } from '../../component-meta';
|
||||
import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
|
||||
import { IComponentMeta } from '../../component-meta';
|
||||
import { ExclusiveGroup, IExclusiveGroup, isExclusiveGroup } from './exclusive-group';
|
||||
import { includeSlot, removeSlot } from '../../utils/slot';
|
||||
import { foreachReverse } from '../../utils/tree';
|
||||
import { NodeRemoveOptions, EDITOR_EVENT } from '../../types';
|
||||
@ -36,50 +37,51 @@ export interface NodeStatus {
|
||||
inPlaceEditing: boolean;
|
||||
}
|
||||
|
||||
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;
|
||||
export interface INode extends Omit<IBaseModelNode<
|
||||
IDocumentModel,
|
||||
INode,
|
||||
INodeChildren,
|
||||
IComponentMeta,
|
||||
ISettingTopEntry,
|
||||
IProps,
|
||||
IProp,
|
||||
IExclusiveGroup
|
||||
>,
|
||||
'isRoot' |
|
||||
'isPage' |
|
||||
'isComponent' |
|
||||
'isModal' |
|
||||
'isSlot' |
|
||||
'isParental' |
|
||||
'isLeaf' |
|
||||
'settingEntry' |
|
||||
// 在内部的 node 模型中不存在
|
||||
'getExtraPropValue' |
|
||||
'setExtraPropValue' |
|
||||
'exportSchema' |
|
||||
'visible' |
|
||||
'importSchema' |
|
||||
// 内外实现有差异
|
||||
'isContainer' |
|
||||
'isEmpty'
|
||||
> {
|
||||
isNode: boolean;
|
||||
|
||||
get componentMeta(): IComponentMeta;
|
||||
|
||||
get document(): IDocumentModel;
|
||||
get settingEntry(): ISettingTopEntry;
|
||||
|
||||
setVisible(flag: boolean): void;
|
||||
get isPurged(): boolean;
|
||||
|
||||
getVisible(): boolean;
|
||||
get index(): number | undefined;
|
||||
|
||||
get isPurging(): boolean;
|
||||
|
||||
/**
|
||||
* 内部方法,请勿使用
|
||||
* @param useMutator 是否触发联动逻辑
|
||||
*/
|
||||
internalSetParent(parent: INode | null, useMutator: boolean): void;
|
||||
internalSetParent(parent: INode | null, useMutator?: boolean): void;
|
||||
|
||||
setConditionGroup(grp: IPublicModelExclusiveGroup | string | null): void;
|
||||
|
||||
@ -87,14 +89,12 @@ export interface INode extends IPublicModelNode {
|
||||
|
||||
internalPurgeStart(): void;
|
||||
|
||||
unlinkSlot(slotNode: Node): void;
|
||||
|
||||
didDropOut(dragment: Node): void;
|
||||
unlinkSlot(slotNode: INode): void;
|
||||
|
||||
/**
|
||||
* 导出 schema
|
||||
*/
|
||||
export(stage: IPublicEnumTransformStage, options?: any): IPublicTypeNodeSchema;
|
||||
export<T = IPublicTypeNodeSchema>(stage: IPublicEnumTransformStage, options?: any): T;
|
||||
|
||||
emitPropChange(val: IPublicTypePropChangeOptions): void;
|
||||
|
||||
@ -106,17 +106,47 @@ export interface INode extends IPublicModelNode {
|
||||
|
||||
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;
|
||||
|
||||
getSuitablePlace(node: INode, ref: any): any;
|
||||
|
||||
onChildrenChange(fn: (param?: { type: string; node: INode }) => void): IPublicTypeDisposable;
|
||||
onChildrenChange(fn: (param?: { type: string; node: INode }) => void): IPublicTypeDisposable | undefined;
|
||||
|
||||
onPropChange(func: (info: IPublicTypePropChangeOptions) => void): IPublicTypeDisposable;
|
||||
|
||||
isModal(): boolean;
|
||||
|
||||
isRoot(): boolean;
|
||||
|
||||
isPage(): boolean;
|
||||
|
||||
isComponent(): boolean;
|
||||
|
||||
isSlot(): boolean;
|
||||
|
||||
isParental(): boolean;
|
||||
|
||||
isLeaf(): boolean;
|
||||
|
||||
isContainer(): boolean;
|
||||
|
||||
isEmpty(): boolean;
|
||||
|
||||
remove(
|
||||
useMutator?: boolean,
|
||||
purge?: boolean,
|
||||
options?: NodeRemoveOptions,
|
||||
): void;
|
||||
|
||||
didDropIn(dragment: INode): void;
|
||||
|
||||
didDropOut(dragment: INode): void;
|
||||
|
||||
purge(): void;
|
||||
|
||||
removeSlot(slotNode: INode): boolean;
|
||||
|
||||
setVisible(flag: boolean): void;
|
||||
|
||||
getVisible(): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,9 +281,9 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
|
||||
isInited = false;
|
||||
|
||||
_settingEntry: SettingTopEntry;
|
||||
_settingEntry: ISettingTopEntry;
|
||||
|
||||
get settingEntry(): SettingTopEntry {
|
||||
get settingEntry(): ISettingTopEntry {
|
||||
if (this._settingEntry) return this._settingEntry;
|
||||
this._settingEntry = this.document.designer.createSettingEntry([this]);
|
||||
return this._settingEntry;
|
||||
@ -279,7 +309,11 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
return !!this._isRGLContainer;
|
||||
}
|
||||
|
||||
private _slotFor?: IProp | null = null;
|
||||
get isEmptyNode() {
|
||||
return this.isEmpty();
|
||||
}
|
||||
|
||||
private _slotFor?: IProp | null | undefined = null;
|
||||
|
||||
@obx.shallow _slots: INode[] = [];
|
||||
|
||||
@ -288,10 +322,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
@obx.ref private _conditionGroup: IPublicModelExclusiveGroup | null = null;
|
||||
@obx.ref private _conditionGroup: IExclusiveGroup | null = null;
|
||||
|
||||
/* istanbul ignore next */
|
||||
get conditionGroup(): IPublicModelExclusiveGroup | null {
|
||||
get conditionGroup(): IExclusiveGroup | null {
|
||||
return this._conditionGroup;
|
||||
}
|
||||
|
||||
@ -319,7 +353,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
pseudo: false,
|
||||
};
|
||||
|
||||
constructor(readonly document: IDocumentModel, nodeSchema: Schema, options: any = {}) {
|
||||
constructor(readonly document: IDocumentModel, nodeSchema: Schema) {
|
||||
makeObservable(this);
|
||||
const { componentName, id, children, props, ...extras } = nodeSchema;
|
||||
this.id = document.nextId(id);
|
||||
@ -347,7 +381,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
this.onVisibleChange((visible: boolean) => {
|
||||
editor?.eventBus.emit(EDITOR_EVENT.NODE_VISIBLE_CHANGE, this, visible);
|
||||
});
|
||||
this.onChildrenChange((info?: { type: string; node: Node }) => {
|
||||
this.onChildrenChange((info?: { type: string; node: INode }) => {
|
||||
editor?.eventBus.emit(EDITOR_EVENT.NODE_VISIBLE_CHANGE, info);
|
||||
});
|
||||
}
|
||||
@ -475,7 +509,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
this.document.addWillPurge(this);
|
||||
}
|
||||
|
||||
private didDropIn(dragment: Node) {
|
||||
didDropIn(dragment: INode) {
|
||||
const { callbacks } = this.componentMeta.advanced;
|
||||
if (callbacks?.onNodeAdd) {
|
||||
const cbThis = this.internalToShellNode();
|
||||
@ -486,7 +520,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
}
|
||||
}
|
||||
|
||||
private didDropOut(dragment: Node) {
|
||||
didDropOut(dragment: INode) {
|
||||
const { callbacks } = this.componentMeta.advanced;
|
||||
if (callbacks?.onNodeRemove) {
|
||||
const cbThis = this.internalToShellNode();
|
||||
@ -547,7 +581,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
/**
|
||||
* 关联属性
|
||||
*/
|
||||
get slotFor(): IProp | null {
|
||||
get slotFor(): IProp | null | undefined {
|
||||
return this._slotFor;
|
||||
}
|
||||
|
||||
@ -567,10 +601,10 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
});
|
||||
}
|
||||
if (this.isSlot()) {
|
||||
this.parent.removeSlot(this, purge);
|
||||
this.parent.children.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true });
|
||||
this.parent.removeSlot(this);
|
||||
this.parent.children?.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true });
|
||||
} else {
|
||||
this.parent.children.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true });
|
||||
this.parent.children?.internalDelete(this, purge, useMutator, { suppressRemoveEvent: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -610,7 +644,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
/**
|
||||
* 节点组件描述
|
||||
*/
|
||||
@computed get componentMeta(): ComponentMeta {
|
||||
@computed get componentMeta(): IComponentMeta {
|
||||
return this.document.getComponentMeta(this.componentName);
|
||||
}
|
||||
|
||||
@ -627,6 +661,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
|
||||
/* istanbul ignore next */
|
||||
setConditionGroup(grp: IPublicModelExclusiveGroup | string | null) {
|
||||
let _grp: IExclusiveGroup | null = null;
|
||||
if (!grp) {
|
||||
this.getExtraProp('conditionGroup', false)?.remove();
|
||||
if (this._conditionGroup) {
|
||||
@ -637,20 +672,20 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
}
|
||||
if (!isExclusiveGroup(grp)) {
|
||||
if (this.prevSibling?.conditionGroup?.name === grp) {
|
||||
grp = this.prevSibling.conditionGroup;
|
||||
_grp = this.prevSibling.conditionGroup;
|
||||
} else if (this.nextSibling?.conditionGroup?.name === grp) {
|
||||
grp = this.nextSibling.conditionGroup;
|
||||
} else {
|
||||
grp = new ExclusiveGroup(grp);
|
||||
_grp = this.nextSibling.conditionGroup;
|
||||
} else if (typeof grp === 'string') {
|
||||
_grp = new ExclusiveGroup(grp);
|
||||
}
|
||||
}
|
||||
if (this._conditionGroup !== grp) {
|
||||
this.getExtraProp('conditionGroup', true)?.setValue(grp.name);
|
||||
if (_grp && this._conditionGroup !== _grp) {
|
||||
this.getExtraProp('conditionGroup', true)?.setValue(_grp.name);
|
||||
if (this._conditionGroup) {
|
||||
this._conditionGroup.remove(this);
|
||||
}
|
||||
this._conditionGroup = grp;
|
||||
grp.add(this);
|
||||
this._conditionGroup = _grp;
|
||||
_grp?.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,13 +741,17 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
* @param {INode} node
|
||||
* @param {object} data
|
||||
*/
|
||||
replaceChild(node: INode, data: any): INode {
|
||||
replaceChild(node: INode, data: any): INode | null {
|
||||
if (this.children?.has(node)) {
|
||||
const selected = this.document.selection.has(node.id);
|
||||
|
||||
delete data.id;
|
||||
const newNode = this.document.createNode(data);
|
||||
|
||||
if (!isNode(newNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.insertBefore(newNode, node, false);
|
||||
node.remove(false);
|
||||
|
||||
@ -795,39 +834,45 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
/**
|
||||
* 获取节点在父容器中的索引
|
||||
*/
|
||||
@computed get index(): number {
|
||||
@computed get index(): number | undefined {
|
||||
if (!this.parent) {
|
||||
return -1;
|
||||
}
|
||||
return this.parent.children.indexOf(this);
|
||||
return this.parent.children?.indexOf(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个兄弟节点
|
||||
*/
|
||||
get nextSibling(): INode | null {
|
||||
get nextSibling(): INode | null | undefined {
|
||||
if (!this.parent) {
|
||||
return null;
|
||||
}
|
||||
const { index } = this;
|
||||
if (typeof index !== 'number') {
|
||||
return null;
|
||||
}
|
||||
if (index < 0) {
|
||||
return null;
|
||||
}
|
||||
return this.parent.children.get(index + 1);
|
||||
return this.parent.children?.get(index + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上一个兄弟节点
|
||||
*/
|
||||
get prevSibling(): INode | null {
|
||||
get prevSibling(): INode | null | undefined {
|
||||
if (!this.parent) {
|
||||
return null;
|
||||
}
|
||||
const { index } = this;
|
||||
if (typeof index !== 'number') {
|
||||
return null;
|
||||
}
|
||||
if (index < 1) {
|
||||
return null;
|
||||
}
|
||||
return this.parent.children.get(index - 1);
|
||||
return this.parent.children?.get(index - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -846,7 +891,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
if (this.isSlot()) {
|
||||
foreachReverse(
|
||||
this.children!,
|
||||
(subNode: Node) => {
|
||||
(subNode: INode) => {
|
||||
subNode.remove(true, true);
|
||||
},
|
||||
(iterable, idx) => (iterable as NodeChildren).get(idx),
|
||||
@ -869,7 +914,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
/**
|
||||
* 导出 schema
|
||||
*/
|
||||
export(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Save, options: any = {}): Schema {
|
||||
export<T = IPublicTypeNodeSchema>(stage: IPublicEnumTransformStage = IPublicEnumTransformStage.Save, options: any = {}): T {
|
||||
stage = compatStage(stage);
|
||||
const baseSchema: any = {
|
||||
componentName: this.componentName,
|
||||
@ -911,7 +956,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
...this.document.designer.transformProps(_extras_, this, stage),
|
||||
};
|
||||
|
||||
if (this.isParental() && this.children.size > 0 && !options.bypassChildren) {
|
||||
if (this.isParental() && this.children && this.children.size > 0 && !options.bypassChildren) {
|
||||
schema.children = this.children.export(stage);
|
||||
}
|
||||
|
||||
@ -928,7 +973,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
/**
|
||||
* 获取特定深度的父亲节点
|
||||
*/
|
||||
getZLevelTop(zLevel: number): Node | null {
|
||||
getZLevelTop(zLevel: number): INode | null {
|
||||
return getZLevelTop(this, zLevel);
|
||||
}
|
||||
|
||||
@ -940,11 +985,11 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
* 2 thisNode before or after otherNode
|
||||
* 0 thisNode same as otherNode
|
||||
*/
|
||||
comparePosition(otherNode: Node): PositionNO {
|
||||
comparePosition(otherNode: INode): PositionNO {
|
||||
return comparePosition(this, otherNode);
|
||||
}
|
||||
|
||||
unlinkSlot(slotNode: Node) {
|
||||
unlinkSlot(slotNode: INode) {
|
||||
const i = this._slots.indexOf(slotNode);
|
||||
if (i < 0) {
|
||||
return false;
|
||||
@ -955,7 +1000,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
/**
|
||||
* 删除一个Slot节点
|
||||
*/
|
||||
removeSlot(slotNode: Node, purge = false): boolean {
|
||||
removeSlot(slotNode: INode): boolean {
|
||||
// if (purge) {
|
||||
// // should set parent null
|
||||
// slotNode?.internalSetParent(null, false);
|
||||
@ -996,7 +1041,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
* 删除一个节点
|
||||
* @param node
|
||||
*/
|
||||
removeChild(node: Node) {
|
||||
removeChild(node: INode) {
|
||||
this.children?.delete(node);
|
||||
}
|
||||
|
||||
@ -1047,18 +1092,18 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
return this.componentName;
|
||||
}
|
||||
|
||||
insert(node: Node, ref?: Node, useMutator = true) {
|
||||
insert(node: INode, ref?: INode, useMutator = true) {
|
||||
this.insertAfter(node, ref, useMutator);
|
||||
}
|
||||
|
||||
insertBefore(node: Node, ref?: Node, useMutator = true) {
|
||||
insertBefore(node: INode, ref?: INode, useMutator = true) {
|
||||
const nodeInstance = ensureNode(node, this.document);
|
||||
this.children?.internalInsert(nodeInstance, ref ? ref.index : null, useMutator);
|
||||
}
|
||||
|
||||
insertAfter(node: any, ref?: Node, useMutator = true) {
|
||||
insertAfter(node: any, ref?: INode, useMutator = true) {
|
||||
const nodeInstance = ensureNode(node, this.document);
|
||||
this.children?.internalInsert(nodeInstance, ref ? ref.index + 1 : null, useMutator);
|
||||
this.children?.internalInsert(nodeInstance, ref ? (ref.index || 0) + 1 : null, useMutator);
|
||||
}
|
||||
|
||||
getParent() {
|
||||
@ -1085,15 +1130,15 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
return this.props;
|
||||
}
|
||||
|
||||
onChildrenChange(fn: (param?: { type: string; node: Node }) => void): IPublicTypeDisposable {
|
||||
onChildrenChange(fn: (param?: { type: string; node: INode }) => void): IPublicTypeDisposable | undefined {
|
||||
const wrappedFunc = wrapWithEventSwitch(fn);
|
||||
return this.children?.onChange(wrappedFunc);
|
||||
}
|
||||
|
||||
mergeChildren(
|
||||
remover: () => any,
|
||||
adder: (children: Node[]) => IPublicTypeNodeData[] | null,
|
||||
sorter: () => any,
|
||||
remover: (node: INode, idx: number) => any,
|
||||
adder: (children: INode[]) => IPublicTypeNodeData[] | null,
|
||||
sorter: (firstNode: INode, secondNode: INode) => any,
|
||||
) {
|
||||
this.children?.mergeChildren(remover, adder, sorter);
|
||||
}
|
||||
@ -1287,7 +1332,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
}
|
||||
}
|
||||
|
||||
function ensureNode(node: any, document: DocumentModel): Node {
|
||||
function ensureNode(node: any, document: IDocumentModel): INode {
|
||||
let nodeInstance = node;
|
||||
if (!isNode(node)) {
|
||||
if (node.getComponentName) {
|
||||
@ -1400,20 +1445,24 @@ export function insertChild(
|
||||
thing: INode | IPublicTypeNodeData,
|
||||
at?: number | null,
|
||||
copy?: boolean,
|
||||
): INode {
|
||||
let node: INode;
|
||||
if (isNode(thing) && (copy || thing.isSlot())) {
|
||||
thing = thing.export(IPublicEnumTransformStage.Clone);
|
||||
}
|
||||
if (isNode(thing)) {
|
||||
): INode | null {
|
||||
let node: INode | null | RootNode | undefined;
|
||||
let nodeSchema: IPublicTypeNodeSchema;
|
||||
if (isNode<INode>(thing) && (copy || thing.isSlot())) {
|
||||
nodeSchema = thing.export(IPublicEnumTransformStage.Clone);
|
||||
node = container.document?.createNode(nodeSchema);
|
||||
} else if (isNode<INode>(thing)) {
|
||||
node = thing;
|
||||
} else {
|
||||
node = container.document.createNode(thing);
|
||||
} else if (isNodeSchema(thing)) {
|
||||
node = container.document?.createNode(thing);
|
||||
}
|
||||
|
||||
container.children.insert(node, at);
|
||||
if (isNode<INode>(node)) {
|
||||
container.children?.insert(node, at);
|
||||
return node;
|
||||
}
|
||||
|
||||
return node;
|
||||
return null;
|
||||
}
|
||||
|
||||
export function insertChildren(
|
||||
|
||||
@ -2,7 +2,7 @@ import { untracked, computed, obx, engineConfig, action, makeObservable, mobx, r
|
||||
import { IPublicTypeCompositeValue, GlobalEvent, IPublicTypeJSSlot, IPublicTypeSlotSchema, IPublicEnumTransformStage, IPublicModelProp } from '@alilc/lowcode-types';
|
||||
import { uniqueId, isPlainObject, hasOwnProperty, compatStage, isJSExpression, isJSSlot } from '@alilc/lowcode-utils';
|
||||
import { valueToSource } from './value-to-source';
|
||||
import { Props, IProps, IPropParent } from './props';
|
||||
import { IProps, IPropParent } from './props';
|
||||
import { SlotNode, INode } from '../node';
|
||||
// import { TransformStage } from '../transform-stage';
|
||||
|
||||
@ -11,19 +11,25 @@ export const UNSET = Symbol.for('unset');
|
||||
// eslint-disable-next-line no-redeclare
|
||||
export type UNSET = typeof UNSET;
|
||||
|
||||
export interface IProp extends Omit<IPublicModelProp, 'exportSchema' | 'node' | 'slotNode' > {
|
||||
export interface IProp extends Omit<IPublicModelProp<
|
||||
INode
|
||||
>, 'exportSchema' | 'node' > {
|
||||
|
||||
readonly props: Props;
|
||||
readonly props: IProps;
|
||||
|
||||
readonly owner: INode;
|
||||
|
||||
get slotNode(): INode | null;
|
||||
|
||||
delete(prop: Prop): void;
|
||||
|
||||
export(stage: IPublicEnumTransformStage): IPublicTypeCompositeValue;
|
||||
|
||||
getNode(): INode;
|
||||
|
||||
getAsString(): string;
|
||||
|
||||
unset(): void;
|
||||
|
||||
get value(): IPublicTypeCompositeValue | UNSET;
|
||||
}
|
||||
|
||||
export type ValueTypes = 'unset' | 'literal' | 'map' | 'list' | 'expression' | 'slot';
|
||||
@ -43,7 +49,7 @@ export class Prop implements IProp, IPropParent {
|
||||
*/
|
||||
@obx spread: boolean;
|
||||
|
||||
readonly props: Props;
|
||||
readonly props: IProps;
|
||||
|
||||
readonly options: any;
|
||||
|
||||
@ -303,7 +309,7 @@ export class Prop implements IProp, IPropParent {
|
||||
return this._value;
|
||||
}
|
||||
const values = this.items!.map((prop) => {
|
||||
return prop.export(stage);
|
||||
return prop?.export(stage);
|
||||
});
|
||||
if (values.every((val) => val === undefined)) {
|
||||
return undefined;
|
||||
@ -401,7 +407,7 @@ export class Prop implements IProp, IPropParent {
|
||||
slotSchema = {
|
||||
componentName: 'Slot',
|
||||
title: value.title || value.props?.slotTitle,
|
||||
id: data.id,
|
||||
id: value.id,
|
||||
name: value.name || value.props?.slotName,
|
||||
params: value.params || value.props?.slotParams,
|
||||
children: value.children,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { computed, makeObservable, obx, action } from '@alilc/lowcode-editor-core';
|
||||
import { IPublicTypePropsMap, IPublicTypePropsList, IPublicTypeCompositeValue, IPublicEnumTransformStage, IPublicModelProps } from '@alilc/lowcode-types';
|
||||
import { IPublicTypePropsMap, IPublicTypePropsList, IPublicTypeCompositeValue, IPublicEnumTransformStage, IBaseModelProps } from '@alilc/lowcode-types';
|
||||
import { uniqueId, compatStage } from '@alilc/lowcode-utils';
|
||||
import { Prop, IProp, UNSET } from './prop';
|
||||
import { INode, Node } from '../node';
|
||||
import { INode } from '../node';
|
||||
// import { TransformStage } from '../transform-stage';
|
||||
|
||||
interface ExtrasObject {
|
||||
@ -33,19 +33,29 @@ export interface IPropParent {
|
||||
get path(): string[];
|
||||
|
||||
delete(prop: Prop): void;
|
||||
|
||||
}
|
||||
|
||||
export interface IProps extends Omit<IPublicModelProps, 'getProp' | 'getExtraProp' | 'getExtraPropValue' | 'setExtraPropValue' | 'node'> {
|
||||
export interface IProps extends Omit<IBaseModelProps<IProp>, | 'getExtraProp' | 'getExtraPropValue' | 'setExtraPropValue' | 'node'> {
|
||||
|
||||
/**
|
||||
* 获取 props 对应的 node
|
||||
*/
|
||||
getNode(): INode;
|
||||
|
||||
getProp(path: string): IProp | null;
|
||||
get(path: string, createIfNone?: boolean): Prop | null;
|
||||
|
||||
get(path: string, createIfNone: boolean): Prop;
|
||||
export(stage?: IPublicEnumTransformStage): {
|
||||
props?: IPublicTypePropsMap | IPublicTypePropsList;
|
||||
extras?: ExtrasObject;
|
||||
};
|
||||
|
||||
merge(value: IPublicTypePropsMap, extras?: IPublicTypePropsMap): void;
|
||||
|
||||
purge(): void;
|
||||
|
||||
query(path: string, createIfNone: boolean): Prop | null;
|
||||
|
||||
import(value?: IPublicTypePropsMap | IPublicTypePropsList | null, extras?: ExtrasObject): void;
|
||||
}
|
||||
|
||||
export class Props implements IProps, IPropParent {
|
||||
|
||||
@ -1,20 +1,10 @@
|
||||
import { obx, makeObservable, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
|
||||
import { Node, INode, comparePosition, PositionNO } from './node/node';
|
||||
import { INode, comparePosition, PositionNO } from './node/node';
|
||||
import { DocumentModel } from './document-model';
|
||||
import { IPublicModelSelection } from '@alilc/lowcode-types';
|
||||
|
||||
export interface ISelection extends Omit< IPublicModelSelection, 'getNodes' | 'getTopNodes' > {
|
||||
export interface ISelection extends Omit<IPublicModelSelection<INode>, 'node'> {
|
||||
|
||||
/**
|
||||
* 获取选中的节点实例
|
||||
* @returns
|
||||
*/
|
||||
getNodes(): INode[];
|
||||
|
||||
/**
|
||||
* 获取顶层选区节点,场景:拖拽时,建立蒙层,只蒙在最上层
|
||||
*/
|
||||
getTopNodes(includeRoot?: boolean): INode[];
|
||||
}
|
||||
|
||||
export class Selection implements ISelection {
|
||||
@ -115,7 +105,7 @@ export class Selection implements ISelection {
|
||||
/**
|
||||
* 选区是否包含节点
|
||||
*/
|
||||
containsNode(node: Node, excludeRoot = false) {
|
||||
containsNode(node: INode, excludeRoot = false) {
|
||||
for (const id of this._selected) {
|
||||
const parent = this.doc.getNode(id);
|
||||
if (excludeRoot && parent?.contains(this.doc.focusNode)) {
|
||||
@ -131,8 +121,8 @@ export class Selection implements ISelection {
|
||||
/**
|
||||
* 获取选中的节点
|
||||
*/
|
||||
getNodes(): Node[] {
|
||||
const nodes = [];
|
||||
getNodes(): INode[] {
|
||||
const nodes: INode[] = [];
|
||||
for (const id of this._selected) {
|
||||
const node = this.doc.getNode(id);
|
||||
if (node) {
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
IPublicApiPlugins,
|
||||
IPublicTypePluginDeclaration,
|
||||
IPublicApiCanvas,
|
||||
IPublicApiWorkspace,
|
||||
} from '@alilc/lowcode-types';
|
||||
import {
|
||||
IPluginContextOptions,
|
||||
@ -24,8 +25,8 @@ import {
|
||||
} from './plugin-types';
|
||||
import { isValidPreferenceKey } from './plugin-utils';
|
||||
|
||||
|
||||
export default class PluginContext implements IPublicModelPluginContext, ILowCodePluginContextPrivate {
|
||||
export default class PluginContext implements
|
||||
IPublicModelPluginContext, ILowCodePluginContextPrivate {
|
||||
hotkey: IPublicApiHotkey;
|
||||
project: IPublicApiProject;
|
||||
skeleton: IPublicApiSkeleton;
|
||||
@ -39,6 +40,7 @@ export default class PluginContext implements IPublicModelPluginContext, ILowCod
|
||||
preference: IPluginPreferenceMananger;
|
||||
pluginEvent: IPublicApiEvent;
|
||||
canvas: IPublicApiCanvas;
|
||||
workspace: IPublicApiWorkspace;
|
||||
|
||||
constructor(
|
||||
options: IPluginContextOptions,
|
||||
|
||||
@ -12,13 +12,31 @@ import {
|
||||
import { isLowCodeComponentType, isProCodeComponentType } from '@alilc/lowcode-utils';
|
||||
import { ISimulatorHost } from '../simulator';
|
||||
|
||||
export interface IProject extends Omit< IPublicApiProject, 'simulatorHost' | 'importSchema' | 'exportSchema' | 'openDocument' | 'getDocumentById' | 'getCurrentDocument' | 'addPropsTransducer' | 'onRemoveDocument' | 'onChangeDocument' | 'onSimulatorHostReady' | 'onSimulatorRendererReady' | 'setI18n' > {
|
||||
export interface IProject extends Omit< IPublicApiProject,
|
||||
'simulatorHost' |
|
||||
'importSchema' |
|
||||
'exportSchema' |
|
||||
'openDocument' |
|
||||
'getDocumentById' |
|
||||
'getCurrentDocument' |
|
||||
'addPropsTransducer' |
|
||||
'onRemoveDocument' |
|
||||
'onChangeDocument' |
|
||||
'onSimulatorHostReady' |
|
||||
'onSimulatorRendererReady' |
|
||||
'setI18n' |
|
||||
'currentDocument' |
|
||||
'selection' |
|
||||
'documents' |
|
||||
'createDocument' |
|
||||
'getDocumentByFileName'
|
||||
> {
|
||||
|
||||
get designer(): IDesigner;
|
||||
|
||||
get simulator(): ISimulatorHost | null;
|
||||
|
||||
get currentDocument(): IDocumentModel | null;
|
||||
get currentDocument(): IDocumentModel | null | undefined;
|
||||
|
||||
get documents(): IDocumentModel[];
|
||||
|
||||
@ -60,6 +78,8 @@ export interface IProject extends Omit< IPublicApiProject, 'simulatorHost' | 'im
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
value: any,
|
||||
): void;
|
||||
|
||||
checkExclusive(activeDoc: DocumentModel): void;
|
||||
}
|
||||
|
||||
export class Project implements IProject {
|
||||
@ -85,7 +105,7 @@ export class Project implements IProject {
|
||||
return this._simulator || null;
|
||||
}
|
||||
|
||||
@computed get currentDocument(): IDocumentModel | null {
|
||||
@computed get currentDocument(): IDocumentModel | null | undefined {
|
||||
return this.documents.find((doc) => doc.active);
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { ComponentType } from 'react';
|
||||
import { IPublicTypeComponentMetadata, IPublicTypeNodeSchema, IPublicTypeScrollable, IPublicTypeComponentInstance, IPublicModelSensor, IPublicTypeNodeInstance } from '@alilc/lowcode-types';
|
||||
import { Point, ScrollTarget, ILocateEvent } from './designer';
|
||||
import { BuiltinSimulatorRenderer } from './builtin-simulator/renderer';
|
||||
import { Node, INode } from './document';
|
||||
import { INode } from './document';
|
||||
|
||||
export type AutoFit = '100%';
|
||||
// eslint-disable-next-line no-redeclare
|
||||
@ -132,7 +132,7 @@ export interface ISimulatorHost<P = object> extends IPublicModelSensor {
|
||||
/**
|
||||
* 滚动视口到节点
|
||||
*/
|
||||
scrollToNode(node: Node, detail?: any): void;
|
||||
scrollToNode(node: INode, detail?: any): void;
|
||||
|
||||
/**
|
||||
* 描述组件
|
||||
@ -147,7 +147,7 @@ export interface ISimulatorHost<P = object> extends IPublicModelSensor {
|
||||
/**
|
||||
* 根据节点获取节点的组件实例
|
||||
*/
|
||||
getComponentInstances(node: Node): IPublicTypeComponentInstance[] | null;
|
||||
getComponentInstances(node: INode): IPublicTypeComponentInstance[] | null;
|
||||
|
||||
/**
|
||||
* 根据 schema 创建组件类
|
||||
@ -157,11 +157,11 @@ export interface ISimulatorHost<P = object> extends IPublicModelSensor {
|
||||
/**
|
||||
* 根据节点获取节点的组件运行上下文
|
||||
*/
|
||||
getComponentContext(node: Node): object | null;
|
||||
getComponentContext(node: INode): object | null;
|
||||
|
||||
getClosestNodeInstance(from: IPublicTypeComponentInstance, specId?: string): IPublicTypeNodeInstance | null;
|
||||
|
||||
computeRect(node: Node): DOMRect | null;
|
||||
computeRect(node: INode): DOMRect | null;
|
||||
|
||||
computeComponentInstanceRect(instance: IPublicTypeComponentInstance, selector?: string): DOMRect | null;
|
||||
|
||||
@ -189,6 +189,6 @@ export function isSimulatorHost(obj: any): obj is ISimulatorHost {
|
||||
export type Component = ComponentType<any> | object;
|
||||
|
||||
export interface INodeSelector {
|
||||
node: Node;
|
||||
node: INode;
|
||||
instance?: IPublicTypeComponentInstance;
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ describe('document-model 测试', () => {
|
||||
|
||||
it('empty schema', () => {
|
||||
const doc = new DocumentModel(project);
|
||||
expect(doc.rootNode.id).toBe('root');
|
||||
expect(doc.rootNode?.id).toBe('root');
|
||||
expect(doc.currentRoot).toBe(doc.rootNode);
|
||||
expect(doc.root).toBe(doc.rootNode);
|
||||
expect(doc.modalNode).toBeUndefined();
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import set from 'lodash/set';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import '../../fixtures/window';
|
||||
import { Project } from '../../../src/project/project';
|
||||
import { Node } from '../../../src/document/node/node';
|
||||
import { Project, IProject } from '../../../src/project/project';
|
||||
import { Node, INode } from '../../../src/document/node/node';
|
||||
import { Designer } from '../../../src/designer/designer';
|
||||
import formSchema from '../../fixtures/schema/form';
|
||||
import { getIdsFromSchema, getNodeFromSchemaById } from '../../utils';
|
||||
@ -37,7 +37,7 @@ beforeAll(() => {
|
||||
|
||||
describe('schema 生成节点模型测试', () => {
|
||||
describe('block ❌ | component ❌ | slot ❌', () => {
|
||||
let project: Project;
|
||||
let project: IProject;
|
||||
beforeEach(() => {
|
||||
project = new Project(designer, {
|
||||
componentsTree: [
|
||||
@ -52,12 +52,12 @@ describe('schema 生成节点模型测试', () => {
|
||||
it('基本的节点模型初始化,模型导出', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const expectedNodeCnt = ids.length;
|
||||
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||
expect(nodesMap?.size).toBe(expectedNodeCnt);
|
||||
ids.forEach(id => {
|
||||
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||
expect(nodesMap?.get(id)?.componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||
});
|
||||
|
||||
const pageNode = currentDocument?.getNode('page');
|
||||
@ -76,18 +76,18 @@ describe('schema 生成节点模型测试', () => {
|
||||
it('基本的节点模型初始化,节点深度', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const { currentDocument } = project;
|
||||
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||
const getNode = currentDocument?.getNode.bind(currentDocument);
|
||||
|
||||
const pageNode = getNode('page');
|
||||
const rootHeaderNode = getNode('node_k1ow3cba');
|
||||
const rootContentNode = getNode('node_k1ow3cbb');
|
||||
const rootFooterNode = getNode('node_k1ow3cbc');
|
||||
const formNode = getNode('form');
|
||||
const cardNode = getNode('node_k1ow3cbj');
|
||||
const cardContentNode = getNode('node_k1ow3cbk');
|
||||
const columnsLayoutNode = getNode('node_k1ow3cbw');
|
||||
const columnNode = getNode('node_k1ow3cbx');
|
||||
const textFieldNode = getNode('node_k1ow3cbz');
|
||||
const pageNode = getNode?.('page');
|
||||
const rootHeaderNode = getNode?.('node_k1ow3cba');
|
||||
const rootContentNode = getNode?.('node_k1ow3cbb');
|
||||
const rootFooterNode = getNode?.('node_k1ow3cbc');
|
||||
const formNode = getNode?.('form');
|
||||
const cardNode = getNode?.('node_k1ow3cbj');
|
||||
const cardContentNode = getNode?.('node_k1ow3cbk');
|
||||
const columnsLayoutNode = getNode?.('node_k1ow3cbw');
|
||||
const columnNode = getNode?.('node_k1ow3cbx');
|
||||
const textFieldNode = getNode?.('node_k1ow3cbz');
|
||||
|
||||
expect(pageNode?.zLevel).toBe(0);
|
||||
expect(rootHeaderNode?.zLevel).toBe(1);
|
||||
@ -131,7 +131,7 @@ describe('schema 生成节点模型测试', () => {
|
||||
const textFieldNode = getNode('node_k1ow3cbz');
|
||||
|
||||
expect(pageNode?.index).toBe(-1);
|
||||
expect(pageNode?.children.toString()).toBe('[object Array]');
|
||||
expect(pageNode?.children?.toString()).toBe('[object Array]');
|
||||
expect(pageNode?.children?.get(1)).toBe(rootContentNode);
|
||||
expect(pageNode?.getChildren()?.get(1)).toBe(rootContentNode);
|
||||
expect(pageNode?.getNode()).toBe(pageNode);
|
||||
@ -162,20 +162,20 @@ describe('schema 生成节点模型测试', () => {
|
||||
it('基本的节点模型初始化,节点新建、删除等事件', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const { currentDocument } = project;
|
||||
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||
const createNode = currentDocument.createNode.bind(currentDocument);
|
||||
const getNode = currentDocument?.getNode.bind(currentDocument);
|
||||
const createNode = currentDocument?.createNode.bind(currentDocument);
|
||||
|
||||
const pageNode = getNode('page');
|
||||
const pageNode = getNode?.('page');
|
||||
const nodeCreateHandler = jest.fn();
|
||||
const offCreate = currentDocument?.onNodeCreate(nodeCreateHandler);
|
||||
|
||||
const node = createNode({
|
||||
const node = createNode?.({
|
||||
componentName: 'TextInput',
|
||||
props: {
|
||||
propA: 'haha',
|
||||
},
|
||||
});
|
||||
currentDocument?.insertNode(pageNode, node);
|
||||
pageNode && node && currentDocument?.insertNode(pageNode, node);
|
||||
|
||||
expect(nodeCreateHandler).toHaveBeenCalledTimes(1);
|
||||
expect(nodeCreateHandler.mock.calls[0][0]).toBe(node);
|
||||
@ -184,7 +184,7 @@ describe('schema 生成节点模型测试', () => {
|
||||
|
||||
const nodeDestroyHandler = jest.fn();
|
||||
const offDestroy = currentDocument?.onNodeDestroy(nodeDestroyHandler);
|
||||
node.remove();
|
||||
node?.remove();
|
||||
expect(nodeDestroyHandler).toHaveBeenCalledTimes(1);
|
||||
expect(nodeDestroyHandler.mock.calls[0][0]).toBe(node);
|
||||
expect(nodeDestroyHandler.mock.calls[0][0].componentName).toBe('TextInput');
|
||||
@ -290,9 +290,9 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form');
|
||||
currentDocument?.insertNode(formNode, {
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form');
|
||||
formNode && currentDocument?.insertNode(formNode, {
|
||||
componentName: 'TextInput',
|
||||
id: 'nodeschema-id1',
|
||||
props: {
|
||||
@ -300,11 +300,11 @@ describe('schema 生成节点模型测试', () => {
|
||||
propB: 3,
|
||||
},
|
||||
}, 0);
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
expect(formNode.children.length).toBe(4);
|
||||
const insertedNode = formNode.children.get(0);
|
||||
expect(insertedNode.componentName).toBe('TextInput');
|
||||
expect(insertedNode.propsData).toEqual({
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
expect(formNode?.children?.length).toBe(4);
|
||||
const insertedNode = formNode?.children?.get(0);
|
||||
expect(insertedNode?.componentName).toBe('TextInput');
|
||||
expect(insertedNode?.propsData).toEqual({
|
||||
propA: 'haha',
|
||||
propB: 3,
|
||||
});
|
||||
@ -316,9 +316,9 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form');
|
||||
currentDocument?.insertNode(formNode, {
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form');
|
||||
formNode && currentDocument?.insertNode(formNode, {
|
||||
componentName: 'TextInput',
|
||||
id: 'nodeschema-id1',
|
||||
props: {
|
||||
@ -326,11 +326,11 @@ describe('schema 生成节点模型测试', () => {
|
||||
propB: 3,
|
||||
},
|
||||
}, 1);
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
expect(formNode.children.length).toBe(4);
|
||||
const insertedNode = formNode.children.get(1);
|
||||
expect(insertedNode.componentName).toBe('TextInput');
|
||||
expect(insertedNode.propsData).toEqual({
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
expect(formNode?.children?.length).toBe(4);
|
||||
const insertedNode = formNode?.children?.get(1);
|
||||
expect(insertedNode?.componentName).toBe('TextInput');
|
||||
expect(insertedNode?.propsData).toEqual({
|
||||
propA: 'haha',
|
||||
propB: 3,
|
||||
});
|
||||
@ -342,8 +342,8 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form') as Node;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form') as INode;
|
||||
currentDocument?.insertNode(formNode, {
|
||||
componentName: 'ParentNode',
|
||||
props: {
|
||||
@ -367,8 +367,8 @@ describe('schema 生成节点模型测试', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(nodesMap.size).toBe(ids.length + 3);
|
||||
expect(formNode.children.length).toBe(4);
|
||||
expect(nodesMap?.size).toBe(ids.length + 3);
|
||||
expect(formNode.children?.length).toBe(4);
|
||||
expect(formNode.children?.get(3)?.componentName).toBe('ParentNode');
|
||||
expect(formNode.children?.get(3)?.children?.get(0)?.componentName).toBe('SubNode');
|
||||
expect(formNode.children?.get(3)?.children?.get(1)?.componentName).toBe('SubNode2');
|
||||
@ -378,9 +378,9 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form');
|
||||
currentDocument?.insertNode(formNode, {
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form');
|
||||
formNode && currentDocument?.insertNode(formNode, {
|
||||
componentName: 'TextInput',
|
||||
id: 'nodeschema-id1',
|
||||
props: {
|
||||
@ -388,17 +388,17 @@ describe('schema 生成节点模型测试', () => {
|
||||
propB: 3,
|
||||
},
|
||||
});
|
||||
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput');
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
});
|
||||
|
||||
it.skip('场景一:插入 NodeSchema,id 与现有 schema 里的 id 重复,但关闭了 id 检测器', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form');
|
||||
currentDocument?.insertNode(formNode, {
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form');
|
||||
formNode && currentDocument?.insertNode(formNode, {
|
||||
componentName: 'TextInput',
|
||||
id: 'nodeschema-id1',
|
||||
props: {
|
||||
@ -406,16 +406,16 @@ describe('schema 生成节点模型测试', () => {
|
||||
propB: 3,
|
||||
},
|
||||
});
|
||||
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput');
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
});
|
||||
|
||||
it('场景二:插入 Node 实例', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form');
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form');
|
||||
const inputNode = currentDocument?.createNode({
|
||||
componentName: 'TextInput',
|
||||
id: 'nodeschema-id2',
|
||||
@ -424,22 +424,22 @@ describe('schema 生成节点模型测试', () => {
|
||||
propB: 3,
|
||||
},
|
||||
});
|
||||
currentDocument?.insertNode(formNode, inputNode);
|
||||
expect(formNode.children?.get(3)?.componentName).toBe('TextInput');
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
formNode && currentDocument?.insertNode(formNode, inputNode);
|
||||
expect(formNode?.children?.get(3)?.componentName).toBe('TextInput');
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
});
|
||||
|
||||
it('场景三:插入 JSExpression', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form') as Node;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form') as Node;
|
||||
currentDocument?.insertNode(formNode, {
|
||||
type: 'JSExpression',
|
||||
value: 'just a expression',
|
||||
});
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
|
||||
// expect(formNode.children?.get(3)?.children).toEqual({
|
||||
// type: 'JSExpression',
|
||||
@ -450,10 +450,10 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form') as Node;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form') as Node;
|
||||
currentDocument?.insertNode(formNode, 'just a string');
|
||||
expect(nodesMap.size).toBe(ids.length + 1);
|
||||
expect(nodesMap?.size).toBe(ids.length + 1);
|
||||
expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
|
||||
// expect(formNode.children?.get(3)?.children).toBe('just a string');
|
||||
});
|
||||
@ -473,8 +473,8 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form') as Node;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form') as Node;
|
||||
const formNode2 = currentDocument?.getNode('form');
|
||||
expect(formNode).toEqual(formNode2);
|
||||
currentDocument?.insertNodes(formNode, [
|
||||
@ -493,17 +493,17 @@ describe('schema 生成节点模型测试', () => {
|
||||
},
|
||||
},
|
||||
], 1);
|
||||
expect(nodesMap.size).toBe(ids.length + 2);
|
||||
expect(nodesMap?.size).toBe(ids.length + 2);
|
||||
expect(formNode.children?.length).toBe(5);
|
||||
const insertedNode1 = formNode.children.get(1);
|
||||
const insertedNode2 = formNode.children.get(2);
|
||||
expect(insertedNode1.componentName).toBe('TextInput');
|
||||
expect(insertedNode1.propsData).toEqual({
|
||||
const insertedNode1 = formNode.children?.get(1);
|
||||
const insertedNode2 = formNode.children?.get(2);
|
||||
expect(insertedNode1?.componentName).toBe('TextInput');
|
||||
expect(insertedNode1?.propsData).toEqual({
|
||||
propA: 'haha2',
|
||||
propB: 3,
|
||||
});
|
||||
expect(insertedNode2.componentName).toBe('TextInput2');
|
||||
expect(insertedNode2.propsData).toEqual({
|
||||
expect(insertedNode2?.componentName).toBe('TextInput2');
|
||||
expect(insertedNode2?.propsData).toEqual({
|
||||
propA: 'haha',
|
||||
propB: 3,
|
||||
});
|
||||
@ -513,8 +513,8 @@ describe('schema 生成节点模型测试', () => {
|
||||
expect(project).toBeTruthy();
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const formNode = nodesMap.get('form') as Node;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const formNode = nodesMap?.get('form') as INode;
|
||||
const formNode2 = currentDocument?.getNode('form');
|
||||
expect(formNode).toEqual(formNode2);
|
||||
const createdNode1 = currentDocument?.createNode({
|
||||
@ -532,17 +532,17 @@ describe('schema 生成节点模型测试', () => {
|
||||
},
|
||||
});
|
||||
currentDocument?.insertNodes(formNode, [createdNode1, createdNode2], 1);
|
||||
expect(nodesMap.size).toBe(ids.length + 2);
|
||||
expect(nodesMap?.size).toBe(ids.length + 2);
|
||||
expect(formNode.children?.length).toBe(5);
|
||||
const insertedNode1 = formNode.children.get(1);
|
||||
const insertedNode2 = formNode.children.get(2);
|
||||
expect(insertedNode1.componentName).toBe('TextInput');
|
||||
expect(insertedNode1.propsData).toEqual({
|
||||
const insertedNode1 = formNode.children?.get(1);
|
||||
const insertedNode2 = formNode.children?.get(2);
|
||||
expect(insertedNode1?.componentName).toBe('TextInput');
|
||||
expect(insertedNode1?.propsData).toEqual({
|
||||
propA: 'haha2',
|
||||
propB: 3,
|
||||
});
|
||||
expect(insertedNode2.componentName).toBe('TextInput2');
|
||||
expect(insertedNode2.propsData).toEqual({
|
||||
expect(insertedNode2?.componentName).toBe('TextInput2');
|
||||
expect(insertedNode2?.propsData).toEqual({
|
||||
propA: 'haha',
|
||||
propB: 3,
|
||||
});
|
||||
@ -561,13 +561,13 @@ describe('schema 生成节点模型测试', () => {
|
||||
project.open();
|
||||
expect(project).toBeTruthy();
|
||||
const { currentDocument } = project;
|
||||
const { nodesMap } = currentDocument;
|
||||
const nodesMap = currentDocument?.nodesMap;
|
||||
const ids = getIdsFromSchema(formSchema);
|
||||
// 目前每个 slot 会新增(1 + children.length)个节点
|
||||
const expectedNodeCnt = ids.length + 2;
|
||||
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||
expect(nodesMap?.size).toBe(expectedNodeCnt);
|
||||
// PageHeader
|
||||
expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
|
||||
expect(nodesMap?.get('node_k1ow3cbd')?.slots).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -499,6 +499,59 @@ describe('Prop 类测试', () => {
|
||||
expect(slotProp.purged).toBeTruthy();
|
||||
slotProp.dispose();
|
||||
});
|
||||
|
||||
describe('slotNode-value / setAsSlot', () => {
|
||||
const editor = new Editor();
|
||||
const designer = new Designer({ editor, shellModelFactory });
|
||||
const doc = new DocumentModel(designer.project, {
|
||||
componentName: 'Page',
|
||||
children: [
|
||||
{
|
||||
id: 'div',
|
||||
componentName: 'Div',
|
||||
},
|
||||
],
|
||||
});
|
||||
const div = doc.getNode('div');
|
||||
|
||||
const slotProp = new Prop(div?.getProps(), {
|
||||
type: 'JSSlot',
|
||||
value: {
|
||||
componentName: 'Slot',
|
||||
id: 'node_oclei5rv2e2',
|
||||
props: {
|
||||
slotName: "content",
|
||||
slotTitle: "主内容"
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Button',
|
||||
}
|
||||
]
|
||||
},
|
||||
});
|
||||
|
||||
expect(slotProp.slotNode?.componentName).toBe('Slot');
|
||||
|
||||
expect(slotProp.slotNode?.title).toBe('主内容');
|
||||
expect(slotProp.slotNode?.getExtraProp('name')?.getValue()).toBe('content');
|
||||
expect(slotProp.slotNode?.export()?.id).toBe('node_oclei5rv2e2');
|
||||
|
||||
slotProp.export();
|
||||
|
||||
// Save
|
||||
expect(slotProp.export()?.value[0].componentName).toBe('Button');
|
||||
expect(slotProp.export()?.title).toBe('主内容');
|
||||
expect(slotProp.export()?.name).toBe('content');
|
||||
|
||||
// Render
|
||||
expect(slotProp.export(IPublicEnumTransformStage.Render)?.value.children[0].componentName).toBe('Button');
|
||||
expect(slotProp.export(IPublicEnumTransformStage.Render)?.value.componentName).toBe('Slot');
|
||||
|
||||
slotProp.purge();
|
||||
expect(slotProp.purged).toBeTruthy();
|
||||
slotProp.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('其他导出函数', () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-core",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "Core Api for Ali lowCode engine",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -14,8 +14,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"intl-messageformat": "^9.3.1",
|
||||
|
||||
@ -124,9 +124,7 @@ const VALID_ENGINE_OPTIONS = {
|
||||
type: 'array',
|
||||
description: '自定义 simulatorUrl 的地址',
|
||||
},
|
||||
/**
|
||||
* 与 react-renderer 的 appHelper 一致,https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper
|
||||
*/
|
||||
// 与 react-renderer 的 appHelper 一致,https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper
|
||||
appHelper: {
|
||||
type: 'object',
|
||||
description: '定义 utils 和 constants 等对象',
|
||||
@ -149,7 +147,6 @@ const VALID_ENGINE_OPTIONS = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const getStrictModeValue = (engineOptions: IPublicTypeEngineOptions, defaultValue: boolean): boolean => {
|
||||
if (!engineOptions || !isPlainObject(engineOptions)) {
|
||||
return defaultValue;
|
||||
@ -161,7 +158,8 @@ const getStrictModeValue = (engineOptions: IPublicTypeEngineOptions, defaultValu
|
||||
return engineOptions.enableStrictPluginMode;
|
||||
};
|
||||
|
||||
export interface IEngineConfigPrivate {
|
||||
export interface IEngineConfig extends IPublicModelEngineConfig {
|
||||
|
||||
/**
|
||||
* if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions.
|
||||
*
|
||||
@ -176,8 +174,7 @@ export interface IEngineConfigPrivate {
|
||||
delWait(key: string, fn: any): void;
|
||||
}
|
||||
|
||||
|
||||
export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPrivate {
|
||||
export class EngineConfig implements IEngineConfig {
|
||||
private config: { [key: string]: any } = {};
|
||||
|
||||
private waits = new Map<
|
||||
@ -291,13 +288,11 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv
|
||||
const val = this.config?.[key];
|
||||
if (val !== undefined) {
|
||||
fn(val);
|
||||
return () => {};
|
||||
} else {
|
||||
this.setWait(key, fn);
|
||||
return () => {
|
||||
this.delWait(key, fn);
|
||||
};
|
||||
}
|
||||
this.setWait(key, fn);
|
||||
return () => {
|
||||
this.delWait(key, fn);
|
||||
};
|
||||
}
|
||||
|
||||
notifyGot(key: string): void {
|
||||
@ -350,4 +345,4 @@ export class EngineConfig implements IPublicModelEngineConfig, IEngineConfigPriv
|
||||
}
|
||||
}
|
||||
|
||||
export const engineConfig = new EngineConfig();
|
||||
export const engineConfig = new EngineConfig();
|
||||
|
||||
@ -123,6 +123,7 @@ export class Editor extends (EventEmitter as any) implements IPublicModelEditor
|
||||
await (new AssetLoader()).load(url);
|
||||
function setAssetsComponent(component: any, extraNpmInfo: any = {}) {
|
||||
const components = component.components;
|
||||
assets.componentList = assets.componentList?.concat(component.componentList || []);
|
||||
if (Array.isArray(components)) {
|
||||
components.forEach(d => {
|
||||
assets.components = assets.components.concat({
|
||||
@ -144,7 +145,6 @@ export class Editor extends (EventEmitter as any) implements IPublicModelEditor
|
||||
...component.components,
|
||||
} || []);
|
||||
}
|
||||
// assets.componentList = assets.componentList.concat(component.componentList || []);
|
||||
}
|
||||
function setArrayAssets(value: any[], preExportName: string = '', preSubName: string = '') {
|
||||
value.forEach((d: any, i: number) => {
|
||||
@ -190,13 +190,11 @@ export class Editor extends (EventEmitter as any) implements IPublicModelEditor
|
||||
const x = this.context.get(keyOrType);
|
||||
if (x !== undefined) {
|
||||
fn(x);
|
||||
return () => { };
|
||||
} else {
|
||||
this.setWait(keyOrType, fn);
|
||||
return () => {
|
||||
this.delWait(keyOrType, fn);
|
||||
};
|
||||
}
|
||||
this.setWait(keyOrType, fn);
|
||||
return () => {
|
||||
this.delWait(keyOrType, fn);
|
||||
};
|
||||
}
|
||||
|
||||
register(data: any, key?: IPublicTypeEditorValueKey): void {
|
||||
@ -328,4 +326,4 @@ export class Editor extends (EventEmitter as any) implements IPublicModelEditor
|
||||
}
|
||||
}
|
||||
|
||||
export const commonEvent = new EventBus(new EventEmitter());
|
||||
export const commonEvent = new EventBus(new EventEmitter());
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-skeleton",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "alibaba lowcode editor skeleton",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -18,10 +18,10 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.20.12",
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-editor-core": "1.1.3",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
|
||||
@ -3,7 +3,7 @@ import { shallowIntl, observer, obx, engineConfig, runInAction, globalContext }
|
||||
import { createContent, isJSSlot, isSetterConfig, isSettingField } from '@alilc/lowcode-utils';
|
||||
import { Skeleton } from '@alilc/lowcode-editor-skeleton';
|
||||
import { IPublicTypeCustomView } from '@alilc/lowcode-types';
|
||||
import { SettingField, SettingTopEntry, SettingEntry, ComponentMeta } from '@alilc/lowcode-designer';
|
||||
import { SettingField, SettingTopEntry, ISettingEntry, ComponentMeta } from '@alilc/lowcode-designer';
|
||||
import { createField } from '../field';
|
||||
import PopupService, { PopupPipe } from '../popup';
|
||||
import { SkeletonContext } from '../../context';
|
||||
@ -58,7 +58,7 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
|
||||
stageName = `${field.getNode().id}_${field.name.toString()}`;
|
||||
// 清除原 stage,不然 content 引用的一直是老的 field,导致数据无法得到更新
|
||||
stages.container.remove(stageName);
|
||||
const stage = stages.add({
|
||||
stages.add({
|
||||
type: 'Widget',
|
||||
name: stageName,
|
||||
content: <Fragment>{field.items.map((item, index) => createSettingFieldView(item, field, index))}</Fragment>,
|
||||
@ -324,7 +324,7 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export function createSettingFieldView(item: SettingField | IPublicTypeCustomView, field: SettingEntry, index?: number) {
|
||||
export function createSettingFieldView(item: SettingField | IPublicTypeCustomView, field: ISettingEntry, index?: number) {
|
||||
if (isSettingField(item)) {
|
||||
if (item.isGroup) {
|
||||
return <SettingGroupView field={item} key={item.id} />;
|
||||
|
||||
@ -71,7 +71,7 @@ skeleton.add({
|
||||
area: 'topArea',
|
||||
type: 'Widget',
|
||||
name: 'logo',
|
||||
content: YourFantaticLogo,
|
||||
content: YourFantasticLogo,
|
||||
contentProps: {
|
||||
logo:
|
||||
'https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png',
|
||||
|
||||
@ -71,7 +71,7 @@ skeleton.add({
|
||||
area: 'topArea',
|
||||
type: 'Widget',
|
||||
name: 'logo',
|
||||
content: YourFantaticLogo,
|
||||
content: YourFantasticLogo,
|
||||
contentProps: {
|
||||
logo:
|
||||
'https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-engine",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "An enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系",
|
||||
"main": "lib/engine-core.js",
|
||||
"module": "es/engine-core.js",
|
||||
@ -19,15 +19,15 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.12",
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.2",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-editor-core": "1.1.3",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.3",
|
||||
"@alilc/lowcode-engine-ext": "^1.0.0",
|
||||
"@alilc/lowcode-plugin-designer": "1.1.2",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.1.2",
|
||||
"@alilc/lowcode-shell": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-workspace": "1.1.2",
|
||||
"@alilc/lowcode-plugin-designer": "1.1.3",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.1.3",
|
||||
"@alilc/lowcode-shell": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"@alilc/lowcode-workspace": "1.1.3",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -43,6 +43,7 @@ import {
|
||||
Logger,
|
||||
Canvas,
|
||||
Workspace,
|
||||
Config,
|
||||
} from '@alilc/lowcode-shell';
|
||||
import { isPlainObject } from '@alilc/lowcode-utils';
|
||||
import './modules/live-editing';
|
||||
@ -96,7 +97,7 @@ editor.set('project', project);
|
||||
editor.set('setters' as any, setters);
|
||||
editor.set('material', material);
|
||||
editor.set('innerHotkey', innerHotkey);
|
||||
const config = engineConfig;
|
||||
const config = new Config(engineConfig);
|
||||
const event = new Event(commonEvent, { prefix: 'common' });
|
||||
const logger = new Logger({ level: 'warn', bizName: 'common' });
|
||||
const common = new Common(editor, innerSkeleton);
|
||||
@ -118,6 +119,7 @@ const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
||||
context.canvas = canvas;
|
||||
context.plugins = plugins;
|
||||
context.logger = new Logger({ level: 'warn', bizName: `plugin:${pluginName}` });
|
||||
context.workspace = workspace;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {
|
||||
Node as InnerNode,
|
||||
INode,
|
||||
SettingField as InnerSettingField,
|
||||
} from '@alilc/lowcode-designer';
|
||||
import { IShellModelFactory, IPublicModelNode, IPublicModelSettingPropEntry } from '@alilc/lowcode-types';
|
||||
@ -8,7 +8,7 @@ import {
|
||||
SettingPropEntry,
|
||||
} from '@alilc/lowcode-shell';
|
||||
class ShellModelFactory implements IShellModelFactory {
|
||||
createNode(node: InnerNode | null | undefined): IPublicModelNode | null {
|
||||
createNode(node: INode | null | undefined): IPublicModelNode | null {
|
||||
return Node.create(node);
|
||||
}
|
||||
createSettingPropEntry(prop: InnerSettingField): IPublicModelSettingPropEntry {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-ignitor",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "点火器,bootstrap lce project",
|
||||
"main": "lib/index.js",
|
||||
"private": true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-designer",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "alibaba lowcode editor designer plugin",
|
||||
"files": [
|
||||
"es",
|
||||
@ -18,9 +18,9 @@
|
||||
],
|
||||
"author": "xiayang.xy",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-editor-core": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-outline-pane",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "Outline pane for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
@ -13,10 +13,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-editor-core": "1.1.3",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
|
||||
@ -3,8 +3,10 @@ import {
|
||||
IPublicTypeLocationChildrenDetail,
|
||||
IPublicModelNode,
|
||||
IPublicModelPluginContext,
|
||||
IPublicTypeDisposable,
|
||||
} from '@alilc/lowcode-types';
|
||||
import { isI18nData, isLocationChildrenDetail } from '@alilc/lowcode-utils';
|
||||
import EventEmitter from 'events';
|
||||
import { Tree } from './tree';
|
||||
|
||||
/**
|
||||
@ -21,14 +23,61 @@ export interface FilterResult {
|
||||
keywords: string;
|
||||
}
|
||||
|
||||
enum EVENT_NAMES {
|
||||
filterResultChanged = 'filterResultChanged',
|
||||
|
||||
expandedChanged = 'expandedChanged',
|
||||
|
||||
hiddenChanged = 'hiddenChanged',
|
||||
|
||||
lockedChanged = 'lockedChanged',
|
||||
|
||||
titleLabelChanged = 'titleLabelChanged',
|
||||
|
||||
expandableChanged = 'expandableChanged',
|
||||
}
|
||||
|
||||
export default class TreeNode {
|
||||
readonly pluginContext: IPublicModelPluginContext;
|
||||
onFilterResultChanged: () => void;
|
||||
onExpandedChanged: (expanded: boolean) => void;
|
||||
onHiddenChanged: (hidden: boolean) => void;
|
||||
onLockedChanged: (locked: boolean) => void;
|
||||
onTitleLabelChanged: (treeNode: TreeNode) => void;
|
||||
onExpandableChanged: (expandable: boolean) => void;
|
||||
event = new EventEmitter();
|
||||
|
||||
onFilterResultChanged(fn: () => void): IPublicTypeDisposable {
|
||||
this.event.on(EVENT_NAMES.filterResultChanged, fn);
|
||||
return () => {
|
||||
this.event.off(EVENT_NAMES.filterResultChanged, fn);
|
||||
}
|
||||
};
|
||||
onExpandedChanged(fn: (expanded: boolean) => void): IPublicTypeDisposable {
|
||||
this.event.on(EVENT_NAMES.expandedChanged, fn);
|
||||
return () => {
|
||||
this.event.off(EVENT_NAMES.expandedChanged, fn);
|
||||
}
|
||||
};
|
||||
onHiddenChanged(fn: (hidden: boolean) => void): IPublicTypeDisposable {
|
||||
this.event.on(EVENT_NAMES.hiddenChanged, fn);
|
||||
return () => {
|
||||
this.event.off(EVENT_NAMES.hiddenChanged, fn);
|
||||
}
|
||||
};
|
||||
onLockedChanged(fn: (locked: boolean) => void): IPublicTypeDisposable {
|
||||
this.event.on(EVENT_NAMES.lockedChanged, fn);
|
||||
return () => {
|
||||
this.event.off(EVENT_NAMES.lockedChanged, fn);
|
||||
}
|
||||
};
|
||||
onTitleLabelChanged(fn: (treeNode: TreeNode) => void): IPublicTypeDisposable {
|
||||
this.event.on(EVENT_NAMES.titleLabelChanged, fn);
|
||||
|
||||
return () => {
|
||||
this.event.off(EVENT_NAMES.titleLabelChanged, fn);
|
||||
}
|
||||
};
|
||||
onExpandableChanged(fn: (expandable: boolean) => void): IPublicTypeDisposable {
|
||||
this.event.on(EVENT_NAMES.expandableChanged, fn);
|
||||
return () => {
|
||||
this.event.off(EVENT_NAMES.expandableChanged, fn);
|
||||
}
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this.node.id;
|
||||
@ -46,7 +95,7 @@ export default class TreeNode {
|
||||
* 触发 onExpandableChanged 回调
|
||||
*/
|
||||
notifyExpandableChanged(): void {
|
||||
this.onExpandableChanged && this.onExpandableChanged(this.expandable);
|
||||
this.event.emit(EVENT_NAMES.expandableChanged, this.expandable);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,7 +148,7 @@ export default class TreeNode {
|
||||
|
||||
setExpanded(value: boolean) {
|
||||
this._expanded = value;
|
||||
this.onExpandedChanged && this.onExpandedChanged(value);
|
||||
this.event.emit(EVENT_NAMES.expandedChanged, value);
|
||||
}
|
||||
|
||||
get detecting() {
|
||||
@ -120,7 +169,7 @@ export default class TreeNode {
|
||||
return;
|
||||
}
|
||||
this.node.visible = !flag;
|
||||
this.onHiddenChanged && this.onHiddenChanged(flag);
|
||||
this.event.emit(EVENT_NAMES.hiddenChanged, flag);
|
||||
}
|
||||
|
||||
get locked(): boolean {
|
||||
@ -129,7 +178,7 @@ export default class TreeNode {
|
||||
|
||||
setLocked(flag: boolean) {
|
||||
this.node.lock(flag);
|
||||
this.onLockedChanged && this.onLockedChanged(flag);
|
||||
this.event.emit(EVENT_NAMES.lockedChanged, flag);
|
||||
}
|
||||
|
||||
get selected(): boolean {
|
||||
@ -174,11 +223,11 @@ export default class TreeNode {
|
||||
} else {
|
||||
this.node.getExtraProp('title', true)?.setValue(label);
|
||||
}
|
||||
this.onTitleLabelChanged && this.onTitleLabelChanged(this);
|
||||
this.event.emit(EVENT_NAMES.titleLabelChanged, this);
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this.node.componentMeta.icon;
|
||||
return this.node.componentMeta?.icon;
|
||||
}
|
||||
|
||||
get parent(): TreeNode | null {
|
||||
@ -282,8 +331,6 @@ export default class TreeNode {
|
||||
|
||||
setFilterReult(val: FilterResult) {
|
||||
this._filterResult = val;
|
||||
if (this.onFilterResultChanged) {
|
||||
this.onFilterResultChanged();
|
||||
}
|
||||
this.event.emit(EVENT_NAMES.filterResultChanged)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { Component } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import TreeNode from '../controllers/tree-node';
|
||||
import TreeNodeView from './tree-node';
|
||||
import { IPublicModelPluginContext, IPublicModelExclusiveGroup } from '@alilc/lowcode-types';
|
||||
import { IPublicModelPluginContext, IPublicModelExclusiveGroup, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
||||
|
||||
export default class TreeBranches extends Component<{
|
||||
treeNode: TreeNode;
|
||||
@ -25,10 +25,10 @@ export default class TreeBranches extends Component<{
|
||||
|
||||
componentDidMount() {
|
||||
const { treeNode } = this.props;
|
||||
treeNode.onFilterResultChanged = () => {
|
||||
treeNode.onFilterResultChanged(() => {
|
||||
const { filterWorking: newFilterWorking, matchChild: newMatchChild } = treeNode.filterReult;
|
||||
this.setState({ filterWorking: newFilterWorking, matchChild: newMatchChild });
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
@ -73,7 +73,7 @@ class TreeNodeChildren extends Component<{
|
||||
keywords: null,
|
||||
dropDetail: null,
|
||||
};
|
||||
offLocationChanged: () => void;
|
||||
offLocationChanged: IPublicTypeDisposable | undefined;
|
||||
componentDidMount() {
|
||||
const { treeNode, pluginContext } = this.props;
|
||||
const { project } = pluginContext;
|
||||
@ -85,7 +85,7 @@ class TreeNodeChildren extends Component<{
|
||||
keywords,
|
||||
dropDetail,
|
||||
});
|
||||
treeNode.onFilterResultChanged = () => {
|
||||
treeNode.onFilterResultChanged(() => {
|
||||
const {
|
||||
filterWorking: newFilterWorking,
|
||||
matchSelf: newMatchChild,
|
||||
@ -96,7 +96,7 @@ class TreeNodeChildren extends Component<{
|
||||
matchSelf: newMatchChild,
|
||||
keywords: newKeywords,
|
||||
});
|
||||
};
|
||||
});
|
||||
this.offLocationChanged = project.currentDocument?.onDropLocationChanged(
|
||||
() => {
|
||||
this.setState({ dropDetail: treeNode.dropDetail });
|
||||
@ -118,7 +118,7 @@ class TreeNodeChildren extends Component<{
|
||||
const endGroup = () => {
|
||||
if (groupContents.length > 0) {
|
||||
children.push(
|
||||
<div key={currentGrp.id} className="condition-group-container" data-id={currentGrp.firstNode.id}>
|
||||
<div key={currentGrp.id} className="condition-group-container" data-id={currentGrp.firstNode?.id}>
|
||||
<div className="condition-group-title">
|
||||
<Title
|
||||
title={currentGrp.title}
|
||||
|
||||
@ -4,7 +4,7 @@ import TreeNode from '../controllers/tree-node';
|
||||
import TreeTitle from './tree-title';
|
||||
import TreeBranches from './tree-branches';
|
||||
import { IconEyeClose } from '../icons/eye-close';
|
||||
import { IPublicModelPluginContext, IPublicModelModalNodesManager, IPublicModelDocumentModel } from '@alilc/lowcode-types';
|
||||
import { IPublicModelPluginContext, IPublicModelModalNodesManager, IPublicModelDocumentModel, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
||||
|
||||
class ModalTreeNodeView extends Component<{
|
||||
treeNode: TreeNode;
|
||||
@ -78,7 +78,7 @@ export default class TreeNodeView extends Component<{
|
||||
expandable: false,
|
||||
};
|
||||
|
||||
eventOffCallbacks: Array<() => void> = [];
|
||||
eventOffCallbacks: Array<IPublicTypeDisposable | undefined> = [];
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
@ -104,18 +104,18 @@ export default class TreeNodeView extends Component<{
|
||||
|
||||
const doc = project.currentDocument;
|
||||
|
||||
treeNode.onExpandedChanged = ((expanded: boolean) => {
|
||||
treeNode.onExpandedChanged(((expanded: boolean) => {
|
||||
this.setState({ expanded });
|
||||
});
|
||||
treeNode.onHiddenChanged = (hidden: boolean) => {
|
||||
}));
|
||||
treeNode.onHiddenChanged((hidden: boolean) => {
|
||||
this.setState({ hidden });
|
||||
};
|
||||
treeNode.onLockedChanged = (locked: boolean) => {
|
||||
});
|
||||
treeNode.onLockedChanged((locked: boolean) => {
|
||||
this.setState({ locked });
|
||||
};
|
||||
treeNode.onExpandableChanged = (expandable: boolean) => {
|
||||
});
|
||||
treeNode.onExpandableChanged((expandable: boolean) => {
|
||||
this.setState({ expandable });
|
||||
};
|
||||
});
|
||||
|
||||
this.eventOffCallbacks.push(
|
||||
doc?.onDropLocationChanged((document: IPublicModelDocumentModel) => {
|
||||
@ -135,8 +135,8 @@ export default class TreeNodeView extends Component<{
|
||||
this.eventOffCallbacks.push(offDetectingChange!);
|
||||
}
|
||||
componentWillUnmount(): void {
|
||||
this.eventOffCallbacks?.forEach((offFun: () => void) => {
|
||||
offFun();
|
||||
this.eventOffCallbacks?.forEach((offFun: IPublicTypeDisposable | undefined) => {
|
||||
offFun && offFun();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ import { IPublicModelPluginContext, IPublicApiEvent } from '@alilc/lowcode-types
|
||||
import TreeNode from '../controllers/tree-node';
|
||||
import { IconLock, IconUnlock, IconArrowRight, IconEyeClose, IconEye, IconCond, IconLoop, IconRadioActive, IconRadio, IconSetting } from '../icons';
|
||||
|
||||
|
||||
function emitOutlineEvent(event: IPublicApiEvent, type: string, treeNode: TreeNode, rest?: Record<string, unknown>) {
|
||||
const node = treeNode?.node;
|
||||
const npm = node?.componentMeta?.npm;
|
||||
@ -35,6 +34,8 @@ export default class TreeTitle extends Component<{
|
||||
title: '',
|
||||
};
|
||||
|
||||
private lastInput?: HTMLInputElement;
|
||||
|
||||
private enableEdit = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
@ -66,8 +67,6 @@ export default class TreeTitle extends Component<{
|
||||
}
|
||||
};
|
||||
|
||||
private lastInput?: HTMLInputElement;
|
||||
|
||||
private setCaret = (input: HTMLInputElement | null) => {
|
||||
if (!input || this.lastInput === input) {
|
||||
return;
|
||||
@ -84,11 +83,11 @@ export default class TreeTitle extends Component<{
|
||||
editing: false,
|
||||
title: treeNode.titleLabel,
|
||||
});
|
||||
treeNode.onTitleLabelChanged = () => {
|
||||
treeNode.onTitleLabelChanged(() => {
|
||||
this.setState({
|
||||
title: treeNode.titleLabel,
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -96,6 +95,8 @@ export default class TreeTitle extends Component<{
|
||||
const { editing } = this.state;
|
||||
const isCNode = !treeNode.isRoot();
|
||||
const { node } = treeNode;
|
||||
const { componentMeta } = node;
|
||||
const availableActions = componentMeta ? componentMeta.availableActions.map((availableAction) => availableAction.name) : [];
|
||||
const isNodeParent = node.isParentalNode;
|
||||
const isContainer = node.isContainerNode;
|
||||
let style: any;
|
||||
@ -112,8 +113,11 @@ export default class TreeTitle extends Component<{
|
||||
const { intlNode, common, config } = pluginContext;
|
||||
const Tip = common.editorCabin.Tip;
|
||||
const Title = common.editorCabin.Title;
|
||||
const shouldShowHideBtn = isCNode && isNodeParent && !isModal;
|
||||
const shouldShowLockBtn = config.get('enableCanvasLock', false) && isContainer && isCNode && isNodeParent;
|
||||
const couldHide = availableActions.includes('hide');
|
||||
const couldLock = availableActions.includes('lock');
|
||||
const couldUnlock = availableActions.includes('unlock');
|
||||
const shouldShowHideBtn = isCNode && isNodeParent && !isModal && couldHide;
|
||||
const shouldShowLockBtn = config.get('enableCanvasLock', false) && isContainer && isCNode && isNodeParent && ((couldLock && !node.isLocked) || (couldUnlock && node.isLocked));
|
||||
const shouldEditBtn = isCNode && isNodeParent;
|
||||
return (
|
||||
<div
|
||||
@ -221,7 +225,6 @@ class RenameBtn extends Component<{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LockBtn extends Component<{
|
||||
treeNode: TreeNode;
|
||||
pluginContext: IPublicModelPluginContext;
|
||||
@ -273,7 +276,6 @@ class HideBtn extends Component<{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ExpandBtn extends Component<{
|
||||
treeNode: TreeNode;
|
||||
pluginContext: IPublicModelPluginContext;
|
||||
@ -301,4 +303,4 @@ class ExpandBtn extends Component<{
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-renderer",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "Rax renderer for Ali lowCode engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -30,8 +30,8 @@
|
||||
"build": "build-scripts build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-renderer-core": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-renderer-core": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"rax-find-dom-node": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-simulator-renderer",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "rax simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -13,10 +13,10 @@
|
||||
"build:umd": "build-scripts build --config build.umd.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-rax-renderer": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-rax-renderer": "1.1.3",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"driver-universal": "^3.1.3",
|
||||
"history": "^5.0.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-renderer",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "react renderer for ali lowcode engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -22,7 +22,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.21.16",
|
||||
"@alilc/lowcode-renderer-core": "1.1.2"
|
||||
"@alilc/lowcode-renderer-core": "1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-simulator-renderer",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "react simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -17,10 +17,10 @@
|
||||
"test:cov": "build-scripts test --config build.test.json --jest-coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-react-renderer": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-react-renderer": "1.1.3",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"mobx": "^6.3.0",
|
||||
"mobx-react": "^7.2.0",
|
||||
|
||||
@ -170,7 +170,9 @@ class Renderer extends Component<{
|
||||
this.startTime = Date.now();
|
||||
this.schemaChangedSymbol = false;
|
||||
|
||||
if (!container.autoRender || isRendererDetached()) return null;
|
||||
if (!container.autoRender || isRendererDetached()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { intl } = createIntl(locale);
|
||||
|
||||
|
||||
@ -39,10 +39,6 @@ export class DocumentInstance {
|
||||
|
||||
private disposeFunctions: Array<() => void> = [];
|
||||
|
||||
constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@obx.ref private _components: any = {};
|
||||
|
||||
@computed get components(): object {
|
||||
@ -98,6 +94,10 @@ export class DocumentInstance {
|
||||
return this.document.id;
|
||||
}
|
||||
|
||||
constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
private unmountInstance(id: string, instance: ReactInstance) {
|
||||
const instances = this.instancesMap.get(id);
|
||||
if (instances) {
|
||||
@ -170,8 +170,7 @@ export class DocumentInstance {
|
||||
host.setInstance(this.document.id, id, instances);
|
||||
}
|
||||
|
||||
mountContext(docId: string, id: string, ctx: object) {
|
||||
// this.ctxMap.set(id, ctx);
|
||||
mountContext() {
|
||||
}
|
||||
|
||||
getNode(id: string): Node | null {
|
||||
@ -195,6 +194,60 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
||||
return this._documentInstances;
|
||||
}
|
||||
|
||||
@obx private _layout: any = null;
|
||||
|
||||
@computed get layout(): any {
|
||||
// TODO: parse layout Component
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
set layout(value: any) {
|
||||
this._layout = value;
|
||||
}
|
||||
|
||||
private _libraryMap: { [key: string]: string } = {};
|
||||
|
||||
private _components: any = {};
|
||||
|
||||
get components(): object {
|
||||
// 根据 device 选择不同组件,进行响应式
|
||||
// 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl
|
||||
return this._components;
|
||||
}
|
||||
// context from: utils、constants、history、location、match
|
||||
@obx.ref private _appContext: any = {};
|
||||
@computed get context(): any {
|
||||
return this._appContext;
|
||||
}
|
||||
@obx.ref private _designMode: string = 'design';
|
||||
@computed get designMode(): any {
|
||||
return this._designMode;
|
||||
}
|
||||
@obx.ref private _device: string = 'default';
|
||||
@computed get device() {
|
||||
return this._device;
|
||||
}
|
||||
@obx.ref private _locale: string | undefined = undefined;
|
||||
@computed get locale() {
|
||||
return this._locale;
|
||||
}
|
||||
@obx.ref private _componentsMap = {};
|
||||
@computed get componentsMap(): any {
|
||||
return this._componentsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为画布自动渲染
|
||||
*/
|
||||
autoRender = true;
|
||||
|
||||
/**
|
||||
* 画布是否自动监听事件来重绘节点
|
||||
*/
|
||||
autoRepaintNode = true;
|
||||
|
||||
private _running = false;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this);
|
||||
this.autoRender = host.autoRender;
|
||||
@ -306,19 +359,6 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
||||
});
|
||||
}
|
||||
|
||||
@obx private _layout: any = null;
|
||||
|
||||
@computed get layout(): any {
|
||||
// TODO: parse layout Component
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
set layout(value: any) {
|
||||
this._layout = value;
|
||||
}
|
||||
|
||||
private _libraryMap: { [key: string]: string } = {};
|
||||
|
||||
private buildComponents() {
|
||||
this._components = buildComponents(
|
||||
this._libraryMap,
|
||||
@ -330,44 +370,6 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
||||
...this._components,
|
||||
};
|
||||
}
|
||||
private _components: any = {};
|
||||
|
||||
get components(): object {
|
||||
// 根据 device 选择不同组件,进行响应式
|
||||
// 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl
|
||||
return this._components;
|
||||
}
|
||||
// context from: utils、constants、history、location、match
|
||||
@obx.ref private _appContext: any = {};
|
||||
@computed get context(): any {
|
||||
return this._appContext;
|
||||
}
|
||||
@obx.ref private _designMode: string = 'design';
|
||||
@computed get designMode(): any {
|
||||
return this._designMode;
|
||||
}
|
||||
@obx.ref private _device: string = 'default';
|
||||
@computed get device() {
|
||||
return this._device;
|
||||
}
|
||||
@obx.ref private _locale: string | undefined = undefined;
|
||||
@computed get locale() {
|
||||
return this._locale;
|
||||
}
|
||||
@obx.ref private _componentsMap = {};
|
||||
@computed get componentsMap(): any {
|
||||
return this._componentsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为画布自动渲染
|
||||
*/
|
||||
autoRender = true;
|
||||
|
||||
/**
|
||||
* 画布是否自动监听事件来重绘节点
|
||||
*/
|
||||
autoRepaintNode = true;
|
||||
|
||||
/**
|
||||
* 加载资源
|
||||
@ -457,6 +459,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
||||
appHelper: renderer.context,
|
||||
rendererName: 'LowCodeRenderer',
|
||||
thisRequiredInJSE: host.thisRequiredInJSE,
|
||||
faultComponent: host.faultComponent,
|
||||
customCreateElement: (Comp: any, props: any, children: any) => {
|
||||
const componentMeta = host.currentDocument?.getComponentMeta(Comp.displayName);
|
||||
if (componentMeta?.isModal) {
|
||||
@ -479,8 +482,6 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
||||
return LowCodeComp;
|
||||
}
|
||||
|
||||
private _running = false;
|
||||
|
||||
run() {
|
||||
if (this._running) {
|
||||
return;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-renderer-core",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "renderer core",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -16,8 +16,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-datasource-engine": "^1.0.0",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
@ -32,7 +32,7 @@
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@alifd/next": "^1.26.0",
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@testing-library/react": "^11.2.2",
|
||||
"@types/classnames": "^2.2.11",
|
||||
|
||||
@ -45,7 +45,7 @@ export default function addonRendererFactory(): IBaseRenderComponent {
|
||||
this.__initDataSource(props);
|
||||
this.open = this.open || (() => { });
|
||||
this.close = this.close || (() => { });
|
||||
this.__excuteLifeCycleMethod('constructor', [...arguments]);
|
||||
this.__executeLifeCycleMethod('constructor', [...arguments]);
|
||||
}
|
||||
|
||||
async componentWillUnmount() {
|
||||
|
||||
@ -40,7 +40,7 @@ import isUseLoop from '../utils/is-use-loop';
|
||||
* execute method in schema.lifeCycles with context
|
||||
* @PRIVATE
|
||||
*/
|
||||
export function excuteLifeCycleMethod(context: any, schema: IPublicTypeNodeSchema, method: string, args: any, thisRequiredInJSE: boolean | undefined): any {
|
||||
export function executeLifeCycleMethod(context: any, schema: IPublicTypeNodeSchema, method: string, args: any, thisRequiredInJSE: boolean | undefined): any {
|
||||
if (!context || !isSchema(schema) || !method) {
|
||||
return;
|
||||
}
|
||||
@ -183,32 +183,32 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
__afterInit(_props: IBaseRendererProps) { }
|
||||
|
||||
static getDerivedStateFromProps(props: IBaseRendererProps, state: any) {
|
||||
return excuteLifeCycleMethod(this, props?.__schema, 'getDerivedStateFromProps', [props, state], props.thisRequiredInJSE);
|
||||
return executeLifeCycleMethod(this, props?.__schema, 'getDerivedStateFromProps', [props, state], props.thisRequiredInJSE);
|
||||
}
|
||||
|
||||
async getSnapshotBeforeUpdate(...args: any[]) {
|
||||
this.__excuteLifeCycleMethod('getSnapshotBeforeUpdate', args);
|
||||
this.__executeLifeCycleMethod('getSnapshotBeforeUpdate', args);
|
||||
this.__debug(`getSnapshotBeforeUpdate - ${this.props?.__schema?.fileName}`);
|
||||
}
|
||||
|
||||
async componentDidMount(...args: any[]) {
|
||||
this.reloadDataSource();
|
||||
this.__excuteLifeCycleMethod('componentDidMount', args);
|
||||
this.__executeLifeCycleMethod('componentDidMount', args);
|
||||
this.__debug(`componentDidMount - ${this.props?.__schema?.fileName}`);
|
||||
}
|
||||
|
||||
async componentDidUpdate(...args: any[]) {
|
||||
this.__excuteLifeCycleMethod('componentDidUpdate', args);
|
||||
this.__executeLifeCycleMethod('componentDidUpdate', args);
|
||||
this.__debug(`componentDidUpdate - ${this.props.__schema.fileName}`);
|
||||
}
|
||||
|
||||
async componentWillUnmount(...args: any[]) {
|
||||
this.__excuteLifeCycleMethod('componentWillUnmount', args);
|
||||
this.__executeLifeCycleMethod('componentWillUnmount', args);
|
||||
this.__debug(`componentWillUnmount - ${this.props?.__schema?.fileName}`);
|
||||
}
|
||||
|
||||
async componentDidCatch(...args: any[]) {
|
||||
this.__excuteLifeCycleMethod('componentDidCatch', args);
|
||||
this.__executeLifeCycleMethod('componentDidCatch', args);
|
||||
console.warn(args);
|
||||
}
|
||||
|
||||
@ -248,8 +248,8 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
* execute method in schema.lifeCycles
|
||||
* @PRIVATE
|
||||
*/
|
||||
__excuteLifeCycleMethod = (method: string, args?: any) => {
|
||||
excuteLifeCycleMethod(this, this.props.__schema, method, args, this.props.thisRequiredInJSE);
|
||||
__executeLifeCycleMethod = (method: string, args?: any) => {
|
||||
executeLifeCycleMethod(this, this.props.__schema, method, args, this.props.thisRequiredInJSE);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -406,7 +406,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
__render = () => {
|
||||
const schema = this.props.__schema;
|
||||
this.__excuteLifeCycleMethod('render');
|
||||
this.__executeLifeCycleMethod('render');
|
||||
this.__writeCss(this.props);
|
||||
|
||||
const { engine } = this.context;
|
||||
@ -774,6 +774,11 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
{
|
||||
...schema,
|
||||
loop: undefined,
|
||||
props: {
|
||||
...schema.props,
|
||||
// 循环下 key 不能为常量,这样会造成 key 值重复,渲染异常
|
||||
key: isJSExpression(schema.props?.key) ? schema.props?.key : null,
|
||||
},
|
||||
},
|
||||
loopSelf,
|
||||
parentInfo,
|
||||
|
||||
@ -13,7 +13,7 @@ export default function blockRendererFactory(): IBaseRenderComponent {
|
||||
const schema = props.__schema || {};
|
||||
this.state = this.__parseData(schema.state || {});
|
||||
this.__initDataSource(props);
|
||||
this.__excuteLifeCycleMethod('constructor', [...arguments]);
|
||||
this.__executeLifeCycleMethod('constructor', [...arguments]);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@ -15,7 +15,7 @@ export default function componentRendererFactory(): IBaseRenderComponent {
|
||||
const schema = props.__schema || {};
|
||||
this.state = this.__parseData(schema.state || {});
|
||||
this.__initDataSource(props);
|
||||
this.__excuteLifeCycleMethod('constructor', arguments as any);
|
||||
this.__executeLifeCycleMethod('constructor', arguments as any);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@ -15,7 +15,7 @@ export default function pageRendererFactory(): IBaseRenderComponent {
|
||||
const schema = props.__schema || {};
|
||||
this.state = this.__parseData(schema.state || {});
|
||||
this.__initDataSource(props);
|
||||
this.__excuteLifeCycleMethod('constructor', [props, ...rest]);
|
||||
this.__executeLifeCycleMethod('constructor', [props, ...rest]);
|
||||
}
|
||||
|
||||
async componentDidUpdate(prevProps: IBaseRendererProps, _prevState: {}, snapshot: unknown) {
|
||||
@ -44,7 +44,6 @@ export default function pageRendererFactory(): IBaseRenderComponent {
|
||||
});
|
||||
this.__render();
|
||||
|
||||
|
||||
const { Page } = __components;
|
||||
if (Page) {
|
||||
return this.__renderComp(Page, { pageContext: this });
|
||||
|
||||
@ -19,10 +19,9 @@ export default function rendererFactory(): IRenderComponent {
|
||||
|
||||
const debug = Debug('renderer:entry');
|
||||
|
||||
class FaultComponent extends PureComponent<IPublicTypeNodeSchema> {
|
||||
class FaultComponent extends PureComponent<IPublicTypeNodeSchema | any> {
|
||||
render() {
|
||||
// FIXME: errorlog
|
||||
console.error('render error', this.props);
|
||||
logger.error(`%c组件渲染异常, 异常原因: ${this.props.error?.message || this.props.error || '未知'}`, 'color: #ff0000;');
|
||||
return createElement(Div, {
|
||||
style: {
|
||||
width: '100%',
|
||||
@ -86,8 +85,9 @@ export default function rendererFactory(): IRenderComponent {
|
||||
debug(`entry.componentWillUnmount - ${this.props?.schema?.componentName}`);
|
||||
}
|
||||
|
||||
async componentDidCatch(e: any) {
|
||||
console.warn(e);
|
||||
componentDidCatch(error: Error) {
|
||||
this.state.engineRenderError = true;
|
||||
this.state.error = error;
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: IRendererProps) {
|
||||
@ -182,6 +182,13 @@ export default function rendererFactory(): IRenderComponent {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.state && this.state.engineRenderError) {
|
||||
return createElement(this.getFaultComponent(), {
|
||||
...this.props,
|
||||
error: this.state.error,
|
||||
});
|
||||
}
|
||||
|
||||
if (Comp) {
|
||||
return createElement(AppContext.Provider, { value: {
|
||||
appHelper,
|
||||
|
||||
@ -281,7 +281,7 @@ export type IBaseRendererInstance = IGeneralComponent<
|
||||
__beforeInit(props: IBaseRendererProps): void;
|
||||
__init(props: IBaseRendererProps): void;
|
||||
__afterInit(props: IBaseRendererProps): void;
|
||||
__excuteLifeCycleMethod(method: string, args?: any[]): void;
|
||||
__executeLifeCycleMethod(method: string, args?: any[]): void;
|
||||
__bindCustomMethods(props: IBaseRendererProps): void;
|
||||
__generateCtx(ctx: Record<string, any>): void;
|
||||
__parseData(data: any, ctx?: any): any;
|
||||
@ -323,10 +323,10 @@ export interface IRenderComponent {
|
||||
new(props: IRendererProps, context: any): IGeneralComponent<IRendererProps, IRendererState> & {
|
||||
[x: string]: any;
|
||||
__getRef: (ref: any) => void;
|
||||
componentDidMount(): Promise<void>;
|
||||
componentDidUpdate(): Promise<void>;
|
||||
componentWillUnmount(): Promise<void>;
|
||||
componentDidCatch(e: any): Promise<void>;
|
||||
componentDidMount(): Promise<void> | void;
|
||||
componentDidUpdate(): Promise<void> | void;
|
||||
componentWillUnmount(): Promise<void> | void;
|
||||
componentDidCatch(e: any): Promise<void> | void;
|
||||
shouldComponentUpdate(nextProps: IRendererProps): boolean;
|
||||
isValidComponent(SetComponent: any): any;
|
||||
patchDidCatch(SetComponent: any): void;
|
||||
|
||||
@ -121,7 +121,7 @@ describe('Base Render methods', () => {
|
||||
// it('should excute lifecycle.componentDidCatch when defined', () => {
|
||||
// });
|
||||
|
||||
// it('__excuteLifeCycleMethod should work', () => {
|
||||
// it('__executeLifeCycleMethod should work', () => {
|
||||
// });
|
||||
|
||||
// it('reloadDataSource should work', () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-shell",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "Shell Layer for AliLowCodeEngine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,12 +15,12 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.1.2",
|
||||
"@alilc/lowcode-editor-core": "1.1.2",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.2",
|
||||
"@alilc/lowcode-types": "1.1.2",
|
||||
"@alilc/lowcode-utils": "1.1.2",
|
||||
"@alilc/lowcode-workspace": "1.1.2",
|
||||
"@alilc/lowcode-designer": "1.1.3",
|
||||
"@alilc/lowcode-editor-core": "1.1.3",
|
||||
"@alilc/lowcode-editor-skeleton": "1.1.3",
|
||||
"@alilc/lowcode-types": "1.1.3",
|
||||
"@alilc/lowcode-utils": "1.1.3",
|
||||
"@alilc/lowcode-workspace": "1.1.3",
|
||||
"classnames": "^2.2.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
SettingPropEntry,
|
||||
SettingTopEntry,
|
||||
Clipboard,
|
||||
Config,
|
||||
} from './model';
|
||||
import {
|
||||
Project,
|
||||
@ -61,4 +62,5 @@ export {
|
||||
Workspace,
|
||||
Clipboard,
|
||||
SimulatorHost,
|
||||
};
|
||||
Config,
|
||||
};
|
||||
|
||||
42
packages/shell/src/model/condition-group.ts
Normal file
42
packages/shell/src/model/condition-group.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { IExclusiveGroup } from '@alilc/lowcode-designer';
|
||||
import { IPublicModelExclusiveGroup, IPublicModelNode } from '@alilc/lowcode-types';
|
||||
import { conditionGroupSymbol, nodeSymbol } from '../symbols';
|
||||
import { Node } from './node';
|
||||
|
||||
export class ConditionGroup implements IPublicModelExclusiveGroup {
|
||||
private [conditionGroupSymbol]: IExclusiveGroup | null;
|
||||
|
||||
constructor(conditionGroup: IExclusiveGroup | null) {
|
||||
this[conditionGroupSymbol] = conditionGroup;
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this[conditionGroupSymbol]?.id;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this[conditionGroupSymbol]?.title;
|
||||
}
|
||||
|
||||
get firstNode() {
|
||||
return Node.create(this[conditionGroupSymbol]?.firstNode);
|
||||
}
|
||||
|
||||
setVisible(node: IPublicModelNode) {
|
||||
this[conditionGroupSymbol]?.setVisible((node as any)[nodeSymbol] ? (node as any)[nodeSymbol] : node);
|
||||
}
|
||||
|
||||
static create(conditionGroup: IExclusiveGroup | null) {
|
||||
if (!conditionGroup) {
|
||||
return null;
|
||||
}
|
||||
// @ts-ignore
|
||||
if (conditionGroup[conditionGroupSymbol]) {
|
||||
return (conditionGroup as any)[conditionGroupSymbol];
|
||||
}
|
||||
const shellConditionGroup = new ConditionGroup(conditionGroup);
|
||||
// @ts-ignore
|
||||
shellConditionGroup[conditionGroupSymbol] = shellConditionGroup;
|
||||
return shellConditionGroup;
|
||||
}
|
||||
}
|
||||
39
packages/shell/src/model/config.ts
Normal file
39
packages/shell/src/model/config.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { IPublicModelEngineConfig, IPublicModelPreference, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
||||
import { configSymbol } from '../symbols';
|
||||
import { IEngineConfig } from '@alilc/lowcode-editor-core';
|
||||
|
||||
export class Config implements IPublicModelEngineConfig {
|
||||
private readonly [configSymbol]: IEngineConfig;
|
||||
|
||||
constructor(innerEngineConfig: IEngineConfig) {
|
||||
this[configSymbol] = innerEngineConfig;
|
||||
}
|
||||
|
||||
has(key: string): boolean {
|
||||
return this[configSymbol].has(key);
|
||||
}
|
||||
|
||||
get(key: string, defaultValue?: any): any {
|
||||
return this[configSymbol].get(key, defaultValue);
|
||||
}
|
||||
|
||||
set(key: string, value: any): void {
|
||||
this[configSymbol].set(key, value);
|
||||
}
|
||||
|
||||
setConfig(config: { [key: string]: any }): void {
|
||||
this[configSymbol].setConfig(config);
|
||||
}
|
||||
|
||||
onceGot(key: string): Promise<any> {
|
||||
return this[configSymbol].onceGot(key);
|
||||
}
|
||||
|
||||
onGot(key: string, fn: (data: any) => void): IPublicTypeDisposable {
|
||||
return this[configSymbol].onGot(key, fn);
|
||||
}
|
||||
|
||||
getPreference(): IPublicModelPreference {
|
||||
return this[configSymbol].getPreference();
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,7 @@ import {
|
||||
IPublicApiCanvas,
|
||||
IPublicTypeDisposable,
|
||||
IPublicModelEditor,
|
||||
IPublicTypeNodeSchema,
|
||||
} from '@alilc/lowcode-types';
|
||||
import { isDragNodeObject } from '@alilc/lowcode-utils';
|
||||
import { Node as ShellNode } from './node';
|
||||
@ -195,7 +196,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
createNode(data: any): IPublicModelNode | null {
|
||||
createNode(data: IPublicTypeNodeSchema): IPublicModelNode | null {
|
||||
return ShellNode.create(this[documentSymbol].createNode(data));
|
||||
}
|
||||
|
||||
@ -289,7 +290,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
|
||||
* @param fn
|
||||
*/
|
||||
onChangeNodeVisible(fn: (node: IPublicModelNode, visible: boolean) => void): IPublicTypeDisposable {
|
||||
return this[documentSymbol].onChangeNodeVisible((node: IPublicModelNode, visible: boolean) => {
|
||||
return this[documentSymbol].onChangeNodeVisible((node: InnerNode, visible: boolean) => {
|
||||
fn(ShellNode.create(node)!, visible);
|
||||
});
|
||||
}
|
||||
|
||||
@ -18,4 +18,5 @@ export * from './resource';
|
||||
export * from './active-tracker';
|
||||
export * from './plugin-instance';
|
||||
export * from './window';
|
||||
export * from './clipboard';
|
||||
export * from './clipboard';
|
||||
export * from './config';
|
||||
|
||||
@ -129,6 +129,15 @@ export class NodeChildren implements IPublicModelNodeChildren {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 类似数组的 reverse
|
||||
*/
|
||||
reverse(): IPublicModelNode[] {
|
||||
return this[nodeChildrenSymbol].reverse().map(d => {
|
||||
return ShellNode.create(d)!;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 类似数组的 map
|
||||
* @param fn
|
||||
|
||||
@ -27,6 +27,7 @@ import { ComponentMeta as ShellComponentMeta } from './component-meta';
|
||||
import { SettingTopEntry as ShellSettingTopEntry } from './setting-top-entry';
|
||||
import { documentSymbol, nodeSymbol } from '../symbols';
|
||||
import { ReactElement } from 'react';
|
||||
import { ConditionGroup } from './condition-group';
|
||||
|
||||
const shellNodeSymbol = Symbol('shellNodeSymbol');
|
||||
|
||||
@ -289,7 +290,7 @@ export class Node implements IPublicModelNode {
|
||||
/**
|
||||
* 当前节点为插槽节点时,返回节点对应的属性实例
|
||||
*/
|
||||
get slotFor(): IPublicModelProp | null {
|
||||
get slotFor(): IPublicModelProp | null | undefined {
|
||||
return ShellProp.create(this[nodeSymbol].slotFor);
|
||||
}
|
||||
|
||||
@ -349,7 +350,6 @@ export class Node implements IPublicModelNode {
|
||||
|
||||
/**
|
||||
* 获取节点实例对应的 dom 节点
|
||||
* @deprecated
|
||||
*/
|
||||
getDOMNode() {
|
||||
return (this[nodeSymbol] as any).getDOMNode();
|
||||
@ -641,7 +641,7 @@ export class Node implements IPublicModelNode {
|
||||
* @since v1.1.0
|
||||
*/
|
||||
get conditionGroup(): IPublicModelExclusiveGroup | null {
|
||||
return this[nodeSymbol].conditionGroup;
|
||||
return ConditionGroup.create(this[nodeSymbol].conditionGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -37,7 +37,7 @@ export class Resource implements IPublicModelResource {
|
||||
return this[resourceSymbol].children.map((child) => new Resource(child));
|
||||
}
|
||||
|
||||
get viewType() {
|
||||
return this[resourceSymbol].viewType;
|
||||
get viewName() {
|
||||
return this[resourceSymbol].viewName;
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,14 @@
|
||||
import {
|
||||
IDocumentModel as InnerDocumentModel,
|
||||
INode as InnerNode,
|
||||
ISelection as InnerSelection,
|
||||
ISelection,
|
||||
} from '@alilc/lowcode-designer';
|
||||
import { Node as ShellNode } from './node';
|
||||
import { selectionSymbol } from '../symbols';
|
||||
import { IPublicModelSelection, IPublicModelNode, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
||||
|
||||
export class Selection implements IPublicModelSelection {
|
||||
private readonly [selectionSymbol]: InnerSelection;
|
||||
private readonly [selectionSymbol]: ISelection;
|
||||
|
||||
constructor(document: InnerDocumentModel) {
|
||||
this[selectionSymbol] = document.selection;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SettingField, SettingEntry } from '@alilc/lowcode-designer';
|
||||
import { SettingField, ISettingEntry } from '@alilc/lowcode-designer';
|
||||
import {
|
||||
IPublicTypeCompositeValue,
|
||||
IPublicTypeFieldConfig,
|
||||
@ -233,7 +233,7 @@ export class SettingPropEntry implements IPublicModelSettingPropEntry {
|
||||
* @returns
|
||||
*/
|
||||
getProps(): IPublicModelSettingTopEntry {
|
||||
return ShellSettingTopEntry.create(this[settingPropEntrySymbol].getProps() as SettingEntry);
|
||||
return ShellSettingTopEntry.create(this[settingPropEntrySymbol].getProps() as ISettingEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import { SettingEntry } from '@alilc/lowcode-designer';
|
||||
import { ISettingEntry } from '@alilc/lowcode-designer';
|
||||
import { settingTopEntrySymbol } from '../symbols';
|
||||
import { Node as ShellNode } from './node';
|
||||
import { SettingPropEntry as ShellSettingPropEntry } from './setting-prop-entry';
|
||||
import { IPublicModelSettingTopEntry, IPublicModelNode, IPublicModelSettingPropEntry } from '@alilc/lowcode-types';
|
||||
|
||||
export class SettingTopEntry implements IPublicModelSettingTopEntry {
|
||||
private readonly [settingTopEntrySymbol]: SettingEntry;
|
||||
private readonly [settingTopEntrySymbol]: ISettingEntry;
|
||||
|
||||
constructor(prop: SettingEntry) {
|
||||
constructor(prop: ISettingEntry) {
|
||||
this[settingTopEntrySymbol] = prop;
|
||||
}
|
||||
|
||||
static create(prop: SettingEntry): IPublicModelSettingTopEntry {
|
||||
static create(prop: ISettingEntry): IPublicModelSettingTopEntry {
|
||||
return new SettingTopEntry(prop);
|
||||
}
|
||||
|
||||
|
||||
@ -31,4 +31,6 @@ export const windowSymbol = Symbol('window');
|
||||
export const pluginInstanceSymbol = Symbol('plugin-instance');
|
||||
export const resourceTypeSymbol = Symbol('resourceType');
|
||||
export const resourceSymbol = Symbol('resource');
|
||||
export const clipboardSymbol = Symbol('clipboard');
|
||||
export const clipboardSymbol = Symbol('clipboard');
|
||||
export const configSymbol = Symbol('configSymbol');
|
||||
export const conditionGroupSymbol = Symbol('conditionGroup');
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-types",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "Types for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
|
||||
@ -2,12 +2,14 @@ import { IPublicModelDragon, IPublicModelDropLocation, IPublicModelScrollTarget,
|
||||
import { IPublicTypeLocationData, IPublicTypeScrollable } from '../type';
|
||||
|
||||
/**
|
||||
* canvas - 画布 API
|
||||
* @since v1.1.0
|
||||
*/
|
||||
export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 创一个滚动控制器 Scroller,赋予一个视图滚动的基本能力,
|
||||
*
|
||||
* a Scroller is a controller that gives a view (IPublicTypeScrollable) the ability scrolling
|
||||
* to some cordination by api scrollTo.
|
||||
*
|
||||
@ -20,6 +22,7 @@ export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 创建一个 ScrollTarget,与 Scroller 一起发挥作用,详见 createScroller 中的描述
|
||||
*
|
||||
* this works with Scroller, refer to createScroller`s description
|
||||
* @since v1.1.0
|
||||
*/
|
||||
@ -27,6 +30,7 @@ export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 创建一个文档插入位置对象,该对象用来描述一个即将插入的节点在文档中的位置
|
||||
*
|
||||
* create a drop location for document, drop location describes a location in document
|
||||
* @since v1.1.0
|
||||
*/
|
||||
@ -34,6 +38,7 @@ export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 获取拖拽操作对象的实例
|
||||
*
|
||||
* get dragon instance, you can use this to obtain draging related abilities and lifecycle hooks
|
||||
* @since v1.1.0
|
||||
*/
|
||||
@ -41,6 +46,7 @@ export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 获取活动追踪器实例
|
||||
*
|
||||
* get activeTracker instance, which is a singleton running in engine.
|
||||
* it tracks document`s current focusing node/node[], and notify it`s subscribers that when
|
||||
* focusing node/node[] changed.
|
||||
@ -50,6 +56,7 @@ export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 是否处于 LiveEditing 状态
|
||||
*
|
||||
* check if canvas is in liveEditing state
|
||||
* @since v1.1.0
|
||||
*/
|
||||
@ -57,6 +64,7 @@ export interface IPublicApiCanvas {
|
||||
|
||||
/**
|
||||
* 获取全局剪贴板实例
|
||||
*
|
||||
* get clipboard instance
|
||||
*
|
||||
* @since v1.1.0
|
||||
|
||||
@ -76,8 +76,25 @@ export interface IPublicApiMaterial {
|
||||
|
||||
/**
|
||||
* 在设计器辅助层增加一个扩展 action
|
||||
*
|
||||
* add an action button in canvas context menu area
|
||||
* @param action
|
||||
* @example
|
||||
* ```ts
|
||||
* import { plugins } from '@alilc/lowcode-engine';
|
||||
* import { IPublicModelPluginContext } from '@alilc/lowcode-types';
|
||||
*
|
||||
* const removeCopyAction = (ctx: IPublicModelPluginContext) => {
|
||||
* return {
|
||||
* async init() {
|
||||
* const { removeBuiltinComponentAction } = ctx.material;
|
||||
* removeBuiltinComponentAction('copy');
|
||||
* }
|
||||
* }
|
||||
* };
|
||||
* removeCopyAction.pluginName = 'removeCopyAction';
|
||||
* await plugins.register(removeCopyAction);
|
||||
* ```
|
||||
*/
|
||||
addBuiltinComponentAction(action: IPublicTypeComponentAction): void;
|
||||
|
||||
|
||||
@ -13,6 +13,11 @@ export interface IPluginPreferenceMananger {
|
||||
export type PluginOptionsType = string | number | boolean | object;
|
||||
|
||||
export interface IPublicApiPlugins {
|
||||
/**
|
||||
* 可以通过 plugin api 获取其他插件 export 导出的内容
|
||||
*/
|
||||
[key: string]: any;
|
||||
|
||||
register(
|
||||
pluginModel: IPublicTypePlugin,
|
||||
options?: Record<string, PluginOptionsType>,
|
||||
@ -21,6 +26,7 @@ export interface IPublicApiPlugins {
|
||||
|
||||
/**
|
||||
* 引擎初始化时可以提供全局配置给到各插件,通过这个方法可以获得本插件对应的配置
|
||||
*
|
||||
* use this to get preference config for this plugin when engine.init() called
|
||||
*/
|
||||
getPluginPreference(
|
||||
@ -29,24 +35,28 @@ export interface IPublicApiPlugins {
|
||||
|
||||
/**
|
||||
* 获取指定插件
|
||||
*
|
||||
* get plugin instance by name
|
||||
*/
|
||||
get(pluginName: string): IPublicModelPluginInstance | null;
|
||||
|
||||
/**
|
||||
* 获取所有的插件实例
|
||||
*
|
||||
* get all plugin instances
|
||||
*/
|
||||
getAll(): IPublicModelPluginInstance[];
|
||||
|
||||
/**
|
||||
* 判断是否有指定插件
|
||||
*
|
||||
* check if plugin with certain name exists
|
||||
*/
|
||||
has(pluginName: string): boolean;
|
||||
|
||||
/**
|
||||
* 删除指定插件
|
||||
*
|
||||
* delete plugin instance by name
|
||||
*/
|
||||
delete(pluginName: string): void;
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { IPublicModelWindow } from '../model';
|
||||
import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
|
||||
|
||||
export interface IPublicApiWorkspace {
|
||||
export interface IPublicApiWorkspace<
|
||||
Plugins = IPublicApiPlugins
|
||||
> {
|
||||
|
||||
/** 是否启用 workspace 模式 */
|
||||
isActive: boolean;
|
||||
@ -9,7 +11,7 @@ export interface IPublicApiWorkspace {
|
||||
/** 当前设计器窗口 */
|
||||
window: IPublicModelWindow;
|
||||
|
||||
plugins: IPublicApiPlugins;
|
||||
plugins: Plugins;
|
||||
|
||||
/** 当前设计器的编辑窗口 */
|
||||
windows: IPublicModelWindow[];
|
||||
|
||||
@ -2,7 +2,9 @@ import { IPublicTypeNodeSchema, IPublicTypeNodeData, IPublicTypeIconType, IPubli
|
||||
import { ReactElement } from 'react';
|
||||
import { IPublicModelNode } from './node';
|
||||
|
||||
export interface IPublicModelComponentMeta {
|
||||
export interface IPublicModelComponentMeta<
|
||||
Node = IPublicModelNode
|
||||
> {
|
||||
|
||||
/**
|
||||
* 组件名
|
||||
@ -92,7 +94,7 @@ export interface IPublicModelComponentMeta {
|
||||
* @param my 当前节点
|
||||
* @param parent 父节点
|
||||
*/
|
||||
checkNestingUp(my: IPublicModelNode | IPublicTypeNodeData, parent: any): boolean;
|
||||
checkNestingUp(my: Node | IPublicTypeNodeData, parent: any): boolean;
|
||||
|
||||
/**
|
||||
* 检测目标节点是否可被放置在父节点中
|
||||
@ -101,8 +103,8 @@ export interface IPublicModelComponentMeta {
|
||||
* @param parent 父节点
|
||||
*/
|
||||
checkNestingDown(
|
||||
my: IPublicModelNode | IPublicTypeNodeData,
|
||||
target: IPublicTypeNodeSchema | IPublicModelNode | IPublicTypeNodeSchema[],
|
||||
my: Node | IPublicTypeNodeData,
|
||||
target: IPublicTypeNodeSchema | Node | IPublicTypeNodeSchema[],
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { IPublicModelNode } from './';
|
||||
import { IPublicTypeDisposable } from '../type';
|
||||
|
||||
export interface IPublicModelDetecting {
|
||||
export interface IPublicModelDetecting<Node = IPublicModelNode> {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
@ -15,7 +15,7 @@ export interface IPublicModelDetecting {
|
||||
* get current hovering node
|
||||
* @since v1.0.16
|
||||
*/
|
||||
get current(): IPublicModelNode | null;
|
||||
get current(): Node | null;
|
||||
|
||||
/**
|
||||
* hover 指定节点
|
||||
@ -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 | null) => void): IPublicTypeDisposable;
|
||||
onDetectingChange(fn: (node: Node | null) => void): IPublicTypeDisposable;
|
||||
}
|
||||
|
||||
@ -2,15 +2,22 @@ import { IPublicTypeRootSchema, IPublicTypeDragNodeDataObject, IPublicTypeDragNo
|
||||
import { IPublicEnumTransformStage } from '../enum';
|
||||
import { IPublicApiProject } from '../api';
|
||||
import { IPublicModelDropLocation, IPublicModelDetecting, IPublicModelNode, IPublicModelSelection, IPublicModelHistory, IPublicModelModalNodesManager } from './';
|
||||
import { IPublicTypeOnChangeOptions } from '@alilc/lowcode-types';
|
||||
import { IPublicTypeNodeData, IPublicTypeNodeSchema, IPublicTypeOnChangeOptions } from '@alilc/lowcode-types';
|
||||
|
||||
export interface IPublicModelDocumentModel {
|
||||
export interface IPublicModelDocumentModel<
|
||||
Selection = IPublicModelSelection,
|
||||
History = IPublicModelHistory,
|
||||
Node = IPublicModelNode,
|
||||
DropLocation = IPublicModelDropLocation,
|
||||
ModalNodesManager = IPublicModelModalNodesManager,
|
||||
Project = IPublicApiProject
|
||||
> {
|
||||
|
||||
/**
|
||||
* 节点选中区模型实例
|
||||
* instance of selection
|
||||
*/
|
||||
selection: IPublicModelSelection;
|
||||
selection: Selection;
|
||||
|
||||
/**
|
||||
* 画布节点 hover 区模型实例
|
||||
@ -22,7 +29,7 @@ export interface IPublicModelDocumentModel {
|
||||
* 操作历史模型实例
|
||||
* instance of history
|
||||
*/
|
||||
history: IPublicModelHistory;
|
||||
history: History;
|
||||
|
||||
/**
|
||||
* id
|
||||
@ -36,30 +43,30 @@ export interface IPublicModelDocumentModel {
|
||||
* get project which this documentModel belongs to
|
||||
* @returns
|
||||
*/
|
||||
get project(): IPublicApiProject;
|
||||
get project(): Project;
|
||||
|
||||
/**
|
||||
* 获取文档的根节点
|
||||
* root node of this documentModel
|
||||
* @returns
|
||||
*/
|
||||
get root(): IPublicModelNode | null;
|
||||
get root(): Node | null;
|
||||
|
||||
get focusNode(): IPublicModelNode | null;
|
||||
get focusNode(): Node | null;
|
||||
|
||||
set focusNode(node: IPublicModelNode | null);
|
||||
set focusNode(node: Node | null);
|
||||
|
||||
/**
|
||||
* 获取文档下所有节点
|
||||
* @returns
|
||||
*/
|
||||
get nodesMap(): Map<string, IPublicModelNode>;
|
||||
get nodesMap(): Map<string, Node>;
|
||||
|
||||
/**
|
||||
* 模态节点管理
|
||||
* get instance of modalNodesManager
|
||||
*/
|
||||
get modalNodesManager(): IPublicModelModalNodesManager | null;
|
||||
get modalNodesManager(): ModalNodesManager | null;
|
||||
|
||||
/**
|
||||
* 根据 nodeId 返回 Node 实例
|
||||
@ -67,7 +74,7 @@ export interface IPublicModelDocumentModel {
|
||||
* @param nodeId
|
||||
* @returns
|
||||
*/
|
||||
getNodeById(nodeId: string): IPublicModelNode | null;
|
||||
getNodeById(nodeId: string): Node | null;
|
||||
|
||||
/**
|
||||
* 导入 schema
|
||||
@ -89,11 +96,11 @@ export interface IPublicModelDocumentModel {
|
||||
* insert a node
|
||||
*/
|
||||
insertNode(
|
||||
parent: IPublicModelNode,
|
||||
thing: IPublicModelNode,
|
||||
parent: Node,
|
||||
thing: Node | IPublicTypeNodeData,
|
||||
at?: number | null | undefined,
|
||||
copy?: boolean | undefined
|
||||
): IPublicModelNode | null;
|
||||
): Node | null;
|
||||
|
||||
/**
|
||||
* 创建一个节点
|
||||
@ -101,14 +108,14 @@ export interface IPublicModelDocumentModel {
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
createNode(data: any): IPublicModelNode | null;
|
||||
createNode(data: IPublicTypeNodeSchema): Node | null;
|
||||
|
||||
/**
|
||||
* 移除指定节点/节点id
|
||||
* remove a node by node instance or nodeId
|
||||
* @param idOrNode
|
||||
*/
|
||||
removeNode(idOrNode: string | IPublicModelNode): void;
|
||||
removeNode(idOrNode: string | Node): void;
|
||||
|
||||
/**
|
||||
* componentsMap of documentModel
|
||||
@ -126,7 +133,7 @@ export interface IPublicModelDocumentModel {
|
||||
* @since v1.0.16
|
||||
*/
|
||||
checkNesting(
|
||||
dropTarget: IPublicModelNode,
|
||||
dropTarget: Node,
|
||||
dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject
|
||||
): boolean;
|
||||
|
||||
@ -134,26 +141,26 @@ export interface IPublicModelDocumentModel {
|
||||
* 当前 document 新增节点事件
|
||||
* set callback for event on node is created for a document
|
||||
*/
|
||||
onAddNode(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable;
|
||||
onAddNode(fn: (node: Node) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 当前 document 新增节点事件,此时节点已经挂载到 document 上
|
||||
* set callback for event on node is mounted to canvas
|
||||
*/
|
||||
onMountNode(fn: (payload: { node: IPublicModelNode }) => void): IPublicTypeDisposable;
|
||||
onMountNode(fn: (payload: { node: Node }) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 当前 document 删除节点事件
|
||||
* set callback for event on node is removed
|
||||
*/
|
||||
onRemoveNode(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable;
|
||||
onRemoveNode(fn: (node: Node) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 当前 document 的 hover 变更事件
|
||||
*
|
||||
* set callback for event on detecting changed
|
||||
*/
|
||||
onChangeDetecting(fn: (node: IPublicModelNode) => void): IPublicTypeDisposable;
|
||||
onChangeDetecting(fn: (node: Node) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 当前 document 的选中变更事件
|
||||
@ -166,19 +173,19 @@ export interface IPublicModelDocumentModel {
|
||||
* set callback for event on visibility changed for certain node
|
||||
* @param fn
|
||||
*/
|
||||
onChangeNodeVisible(fn: (node: IPublicModelNode, visible: boolean) => void): IPublicTypeDisposable;
|
||||
onChangeNodeVisible(fn: (node: Node, visible: boolean) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 当前 document 的节点 children 变更事件
|
||||
* @param fn
|
||||
*/
|
||||
onChangeNodeChildren(fn: (info: IPublicTypeOnChangeOptions) => void): IPublicTypeDisposable;
|
||||
onChangeNodeChildren(fn: (info: IPublicTypeOnChangeOptions<Node>) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 当前 document 节点属性修改事件
|
||||
* @param fn
|
||||
*/
|
||||
onChangeNodeProp(fn: (info: IPublicTypePropChangeOptions) => void): IPublicTypeDisposable;
|
||||
onChangeNodeProp(fn: (info: IPublicTypePropChangeOptions<Node>) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* import schema event
|
||||
@ -193,21 +200,21 @@ export interface IPublicModelDocumentModel {
|
||||
* @param node
|
||||
* @since v1.1.0
|
||||
*/
|
||||
isDetectingNode(node: IPublicModelNode): boolean;
|
||||
isDetectingNode(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* 获取当前的 DropLocation 信息
|
||||
* get current drop location
|
||||
* @since v1.1.0
|
||||
*/
|
||||
get dropLocation(): IPublicModelDropLocation | null;
|
||||
get dropLocation(): DropLocation | null;
|
||||
|
||||
/**
|
||||
* 设置当前的 DropLocation 信息
|
||||
* set current drop location
|
||||
* @since v1.1.0
|
||||
*/
|
||||
set dropLocation(loc: IPublicModelDropLocation | null);
|
||||
set dropLocation(loc: DropLocation | null);
|
||||
|
||||
/**
|
||||
* 设置聚焦节点变化的回调
|
||||
@ -216,7 +223,7 @@ export interface IPublicModelDocumentModel {
|
||||
* @since v1.1.0
|
||||
*/
|
||||
onFocusNodeChanged(
|
||||
fn: (doc: IPublicModelDocumentModel, focusNode: IPublicModelNode) => void,
|
||||
fn: (doc: IPublicModelDocumentModel, focusNode: Node) => void,
|
||||
): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { IPublicTypeDisposable } from '../type';
|
||||
import { IPublicModelPreference } from './';
|
||||
|
||||
export interface IPublicModelEngineConfig {
|
||||
@ -52,7 +53,7 @@ export interface IPublicModelEngineConfig {
|
||||
* @param fn
|
||||
* @returns
|
||||
*/
|
||||
onGot(key: string, fn: (data: any) => void): () => void;
|
||||
onGot(key: string, fn: (data: any) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 获取全局 Preference, 用于管理全局浏览器侧用户 Preference,如 Panel 是否钉住
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { IPublicModelNode } from '..';
|
||||
import { IPublicModelNode, IPublicTypeTitleContent } from '..';
|
||||
|
||||
export interface IPublicModelExclusiveGroup {
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
get firstNode(): IPublicModelNode;
|
||||
export interface IPublicModelExclusiveGroup<
|
||||
Node = IPublicModelNode,
|
||||
> {
|
||||
readonly id: string | undefined;
|
||||
readonly title: IPublicTypeTitleContent | undefined;
|
||||
get firstNode(): Node | null;
|
||||
setVisible(node: Node): void;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { IPublicModelNode } from './';
|
||||
|
||||
export interface IPublicModelModalNodesManager {
|
||||
export interface IPublicModelModalNodesManager<Node = IPublicModelNode> {
|
||||
|
||||
/**
|
||||
* 设置模态节点,触发内部事件
|
||||
@ -12,13 +12,13 @@ export interface IPublicModelModalNodesManager {
|
||||
* 获取模态节点(们)
|
||||
* get modal nodes
|
||||
*/
|
||||
getModalNodes(): IPublicModelNode[];
|
||||
getModalNodes(): Node[];
|
||||
|
||||
/**
|
||||
* 获取当前可见的模态节点
|
||||
* get current visible modal node
|
||||
*/
|
||||
getVisibleModalNode(): IPublicModelNode | null;
|
||||
getVisibleModalNode(): Node | null;
|
||||
|
||||
/**
|
||||
* 隐藏模态节点(们)
|
||||
@ -31,12 +31,12 @@ export interface IPublicModelModalNodesManager {
|
||||
* set specfic model node as visible
|
||||
* @param node Node
|
||||
*/
|
||||
setVisible(node: IPublicModelNode): void;
|
||||
setVisible(node: Node): void;
|
||||
|
||||
/**
|
||||
* 设置指定节点为不可见态
|
||||
* set specfic model node as invisible
|
||||
* @param node Node
|
||||
*/
|
||||
setInvisible(node: IPublicModelNode): void;
|
||||
setInvisible(node: Node): void;
|
||||
}
|
||||
|
||||
@ -2,13 +2,15 @@ import { IPublicTypeNodeSchema, IPublicTypeNodeData } from '../type';
|
||||
import { IPublicEnumTransformStage } from '../enum';
|
||||
import { IPublicModelNode } from './';
|
||||
|
||||
export interface IPublicModelNodeChildren {
|
||||
export interface IPublicModelNodeChildren<
|
||||
Node = IPublicModelNode
|
||||
> {
|
||||
|
||||
/**
|
||||
* 返回当前 children 实例所属的节点实例
|
||||
* get owner node of this nodeChildren
|
||||
*/
|
||||
get owner(): IPublicModelNode | null;
|
||||
get owner(): Node | null;
|
||||
|
||||
/**
|
||||
* children 内的节点实例数
|
||||
@ -25,6 +27,7 @@ export interface IPublicModelNodeChildren {
|
||||
|
||||
/**
|
||||
* 是否为空
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
get isEmptyNode(): boolean;
|
||||
@ -42,104 +45,121 @@ export interface IPublicModelNodeChildren {
|
||||
|
||||
/**
|
||||
* 删除指定节点
|
||||
*
|
||||
* delete the node
|
||||
* @param node
|
||||
*/
|
||||
delete(node: IPublicModelNode): boolean;
|
||||
delete(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* 插入一个节点
|
||||
*
|
||||
* insert a node at specific position
|
||||
* @param node 待插入节点
|
||||
* @param at 插入下标
|
||||
* @returns
|
||||
*/
|
||||
insert(node: IPublicModelNode, at?: number | null): void;
|
||||
insert(node: Node, at?: number | null): void;
|
||||
|
||||
/**
|
||||
* 返回指定节点的下标
|
||||
*
|
||||
* get index of node in current children
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
indexOf(node: IPublicModelNode): number;
|
||||
indexOf(node: Node): number;
|
||||
|
||||
/**
|
||||
* 类似数组 splice 操作
|
||||
*
|
||||
* provide the same function with {Array.prototype.splice}
|
||||
* @param start
|
||||
* @param deleteCount
|
||||
* @param node
|
||||
*/
|
||||
splice(start: number, deleteCount: number, node?: IPublicModelNode): any;
|
||||
splice(start: number, deleteCount: number, node?: Node): any;
|
||||
|
||||
/**
|
||||
* 返回指定下标的节点
|
||||
*
|
||||
* get node with index
|
||||
* @param index
|
||||
* @returns
|
||||
*/
|
||||
get(index: number): IPublicModelNode | null;
|
||||
get(index: number): Node | null;
|
||||
|
||||
/**
|
||||
* 是否包含指定节点
|
||||
*
|
||||
* check if node exists in current children
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
has(node: IPublicModelNode): boolean;
|
||||
has(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* 类似数组的 forEach
|
||||
*
|
||||
* provide the same function with {Array.prototype.forEach}
|
||||
* @param fn
|
||||
*/
|
||||
forEach(fn: (node: IPublicModelNode, index: number) => void): void;
|
||||
forEach(fn: (node: Node, index: number) => void): void;
|
||||
|
||||
/**
|
||||
* 类似数组的 reverse
|
||||
*
|
||||
* provide the same function with {Array.prototype.reverse}
|
||||
*/
|
||||
reverse(): Node[];
|
||||
|
||||
/**
|
||||
* 类似数组的 map
|
||||
*
|
||||
* provide the same function with {Array.prototype.map}
|
||||
* @param fn
|
||||
*/
|
||||
map<T>(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null;
|
||||
map<T = any>(fn: (node: Node, index: number) => T): T[] | null;
|
||||
|
||||
/**
|
||||
* 类似数组的 every
|
||||
* provide the same function with {Array.prototype.every}
|
||||
* @param fn
|
||||
*/
|
||||
every(fn: (node: IPublicModelNode, index: number) => boolean): boolean;
|
||||
every(fn: (node: Node, index: number) => boolean): boolean;
|
||||
|
||||
/**
|
||||
* 类似数组的 some
|
||||
* provide the same function with {Array.prototype.some}
|
||||
* @param fn
|
||||
*/
|
||||
some(fn: (node: IPublicModelNode, index: number) => boolean): boolean;
|
||||
some(fn: (node: Node, index: number) => boolean): boolean;
|
||||
|
||||
/**
|
||||
* 类似数组的 filter
|
||||
* provide the same function with {Array.prototype.filter}
|
||||
* @param fn
|
||||
*/
|
||||
filter(fn: (node: IPublicModelNode, index: number) => boolean): any;
|
||||
filter(fn: (node: Node, index: number) => boolean): any;
|
||||
|
||||
/**
|
||||
* 类似数组的 find
|
||||
* provide the same function with {Array.prototype.find}
|
||||
* @param fn
|
||||
*/
|
||||
find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null;
|
||||
find(fn: (node: Node, index: number) => boolean): Node | null | undefined;
|
||||
|
||||
/**
|
||||
* 类似数组的 reduce
|
||||
*
|
||||
* provide the same function with {Array.prototype.reduce}
|
||||
* @param fn
|
||||
*/
|
||||
reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void;
|
||||
reduce(fn: (acc: any, cur: Node) => any, initialValue: any): void;
|
||||
|
||||
/**
|
||||
* 导入 schema
|
||||
*
|
||||
* import schema
|
||||
* @param data
|
||||
*/
|
||||
@ -147,6 +167,7 @@ export interface IPublicModelNodeChildren {
|
||||
|
||||
/**
|
||||
* 导出 schema
|
||||
*
|
||||
* export schema
|
||||
* @param stage
|
||||
*/
|
||||
@ -154,15 +175,16 @@ export interface IPublicModelNodeChildren {
|
||||
|
||||
/**
|
||||
* 执行新增、删除、排序等操作
|
||||
*
|
||||
* excute remove/add/sort operations
|
||||
* @param remover
|
||||
* @param adder
|
||||
* @param sorter
|
||||
*/
|
||||
mergeChildren(
|
||||
remover: (node: IPublicModelNode, idx: number) => boolean,
|
||||
adder: (children: IPublicModelNode[]) => IPublicTypeNodeData[] | null,
|
||||
sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number
|
||||
remover: (node: Node, idx: number) => boolean,
|
||||
adder: (children: Node[]) => IPublicTypeNodeData[] | null,
|
||||
sorter: (firstNode: Node, secondNode: Node) => number
|
||||
): any;
|
||||
|
||||
}
|
||||
|
||||
@ -3,7 +3,16 @@ import { IPublicTypeNodeSchema, IPublicTypeIconType, IPublicTypeI18nData, IPubli
|
||||
import { IPublicEnumTransformStage } from '../enum';
|
||||
import { IPublicModelNodeChildren, IPublicModelComponentMeta, IPublicModelProp, IPublicModelProps, IPublicModelSettingTopEntry, IPublicModelDocumentModel, IPublicModelExclusiveGroup } from './';
|
||||
|
||||
export interface IPublicModelNode {
|
||||
export interface IBaseModelNode<
|
||||
Document = IPublicModelDocumentModel,
|
||||
Node = IPublicModelNode,
|
||||
NodeChildren = IPublicModelNodeChildren,
|
||||
ComponentMeta = IPublicModelComponentMeta,
|
||||
SettingTopEntry = IPublicModelSettingTopEntry,
|
||||
Props = IPublicModelProps,
|
||||
Prop = IPublicModelProp,
|
||||
ExclusiveGroup = IPublicModelExclusiveGroup
|
||||
> {
|
||||
|
||||
/**
|
||||
* 节点 id
|
||||
@ -161,7 +170,7 @@ export interface IPublicModelNode {
|
||||
* 下标
|
||||
* index
|
||||
*/
|
||||
get index(): number;
|
||||
get index(): number | undefined;
|
||||
|
||||
/**
|
||||
* 图标
|
||||
@ -185,55 +194,55 @@ export interface IPublicModelNode {
|
||||
* 节点的物料元数据
|
||||
* get component meta of this node
|
||||
*/
|
||||
get componentMeta(): IPublicModelComponentMeta | null;
|
||||
get componentMeta(): ComponentMeta | null;
|
||||
|
||||
/**
|
||||
* 获取节点所属的文档模型对象
|
||||
* get documentModel of this node
|
||||
*/
|
||||
get document(): IPublicModelDocumentModel | null;
|
||||
get document(): Document | null;
|
||||
|
||||
/**
|
||||
* 获取当前节点的前一个兄弟节点
|
||||
* get previous sibling of this node
|
||||
*/
|
||||
get prevSibling(): IPublicModelNode | null;
|
||||
get prevSibling(): Node | null | undefined;
|
||||
|
||||
/**
|
||||
* 获取当前节点的后一个兄弟节点
|
||||
* get next sibling of this node
|
||||
*/
|
||||
get nextSibling(): IPublicModelNode | null;
|
||||
get nextSibling(): Node | null | undefined;
|
||||
|
||||
/**
|
||||
* 获取当前节点的父亲节点
|
||||
* get parent of this node
|
||||
*/
|
||||
get parent(): IPublicModelNode | null;
|
||||
get parent(): Node | null;
|
||||
|
||||
/**
|
||||
* 获取当前节点的孩子节点模型
|
||||
* get children of this node
|
||||
*/
|
||||
get children(): IPublicModelNodeChildren | null;
|
||||
get children(): NodeChildren | null;
|
||||
|
||||
/**
|
||||
* 节点上挂载的插槽节点们
|
||||
* get slots of this node
|
||||
*/
|
||||
get slots(): IPublicModelNode[];
|
||||
get slots(): Node[];
|
||||
|
||||
/**
|
||||
* 当前节点为插槽节点时,返回节点对应的属性实例
|
||||
* return coresponding prop when this node is a slot node
|
||||
*/
|
||||
get slotFor(): IPublicModelProp | null;
|
||||
get slotFor(): Prop | null | undefined;
|
||||
|
||||
/**
|
||||
* 返回节点的属性集
|
||||
* get props
|
||||
*/
|
||||
get props(): IPublicModelProps | null;
|
||||
get props(): Props | null;
|
||||
|
||||
/**
|
||||
* 返回节点的属性集
|
||||
@ -244,7 +253,7 @@ export interface IPublicModelNode {
|
||||
/**
|
||||
* get conditionGroup
|
||||
*/
|
||||
get conditionGroup(): IPublicModelExclusiveGroup | null;
|
||||
get conditionGroup(): ExclusiveGroup | null;
|
||||
|
||||
/**
|
||||
* 获取符合搭建协议 - 节点 schema 结构
|
||||
@ -258,7 +267,7 @@ export interface IPublicModelNode {
|
||||
* get setting entry of this node
|
||||
* @since v1.1.0
|
||||
*/
|
||||
get settingEntry(): IPublicModelSettingTopEntry;
|
||||
get settingEntry(): SettingTopEntry;
|
||||
|
||||
/**
|
||||
* 返回节点的尺寸、位置信息
|
||||
@ -289,7 +298,7 @@ export interface IPublicModelNode {
|
||||
* get prop by path
|
||||
* @param path 属性路径,支持 a / a.b / a.0 等格式
|
||||
*/
|
||||
getProp(path: string, createIfNone: boolean): IPublicModelProp | null;
|
||||
getProp(path: string, createIfNone: boolean): Prop | null;
|
||||
|
||||
/**
|
||||
* 获取指定 path 的属性模型实例值
|
||||
@ -307,7 +316,7 @@ export interface IPublicModelNode {
|
||||
* @param path 属性路径,支持 a / a.b / a.0 等格式
|
||||
* @param createIfNone 当没有属性的时候,是否创建一个属性
|
||||
*/
|
||||
getExtraProp(path: string, createIfNone?: boolean): IPublicModelProp | null;
|
||||
getExtraProp(path: string, createIfNone?: boolean): Prop | null;
|
||||
|
||||
/**
|
||||
* 获取指定 path 的属性模型实例,
|
||||
@ -359,8 +368,8 @@ export interface IPublicModelNode {
|
||||
* @param useMutator
|
||||
*/
|
||||
insertBefore(
|
||||
node: IPublicModelNode,
|
||||
ref?: IPublicModelNode | undefined,
|
||||
node: Node,
|
||||
ref?: Node | undefined,
|
||||
useMutator?: boolean,
|
||||
): void;
|
||||
|
||||
@ -372,8 +381,8 @@ export interface IPublicModelNode {
|
||||
* @param useMutator
|
||||
*/
|
||||
insertAfter(
|
||||
node: IPublicModelNode,
|
||||
ref?: IPublicModelNode | undefined,
|
||||
node: Node,
|
||||
ref?: Node | undefined,
|
||||
useMutator?: boolean,
|
||||
): void;
|
||||
|
||||
@ -384,7 +393,7 @@ export interface IPublicModelNode {
|
||||
* @param data 用作替换的节点对象或者节点描述
|
||||
* @returns
|
||||
*/
|
||||
replaceChild(node: IPublicModelNode, data: any): IPublicModelNode | null;
|
||||
replaceChild(node: Node, data: any): Node | null;
|
||||
|
||||
/**
|
||||
* 将当前节点替换成指定节点描述
|
||||
@ -427,9 +436,9 @@ export interface IPublicModelNode {
|
||||
* @since v1.1.0
|
||||
*/
|
||||
mergeChildren(
|
||||
remover: (node: IPublicModelNode, idx: number) => boolean,
|
||||
adder: (children: IPublicModelNode[]) => any,
|
||||
sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number
|
||||
remover: (node: Node, idx: number) => boolean,
|
||||
adder: (children: Node[]) => any,
|
||||
sorter: (firstNode: Node, secondNode: Node) => number
|
||||
): any;
|
||||
|
||||
/**
|
||||
@ -438,7 +447,7 @@ export interface IPublicModelNode {
|
||||
* @param node
|
||||
* @since v1.1.0
|
||||
*/
|
||||
contains(node: IPublicModelNode): boolean;
|
||||
contains(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* 是否可执行某 action
|
||||
@ -475,4 +484,11 @@ export interface IPublicModelNode {
|
||||
* @since v1.1.0
|
||||
*/
|
||||
setConditionalVisible(): void;
|
||||
|
||||
/**
|
||||
* 获取节点实例对应的 dom 节点
|
||||
*/
|
||||
getDOMNode(): HTMLElement;
|
||||
}
|
||||
|
||||
export interface IPublicModelNode extends IBaseModelNode<IPublicModelDocumentModel, IPublicModelNode> {}
|
||||
@ -10,6 +10,7 @@ import {
|
||||
IPublicApiCanvas,
|
||||
IPluginPreferenceMananger,
|
||||
IPublicApiPlugins,
|
||||
IPublicApiWorkspace,
|
||||
} from '../api';
|
||||
import { IPublicModelEngineConfig } from './';
|
||||
|
||||
@ -28,31 +29,88 @@ export interface IPublicModelPluginContext {
|
||||
* by using this, init options can be accessed from inside plugin
|
||||
*/
|
||||
preference: IPluginPreferenceMananger;
|
||||
|
||||
/**
|
||||
* skeleton API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/skeleton
|
||||
*/
|
||||
get skeleton(): IPublicApiSkeleton;
|
||||
|
||||
/**
|
||||
* hotkey API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/hotkey
|
||||
*/
|
||||
get hotkey(): IPublicApiHotkey;
|
||||
|
||||
/**
|
||||
* setter API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/setters
|
||||
*/
|
||||
get setters(): IPublicApiSetters;
|
||||
|
||||
/**
|
||||
* config API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/config
|
||||
*/
|
||||
get config(): IPublicModelEngineConfig;
|
||||
|
||||
/**
|
||||
* material API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/material
|
||||
*/
|
||||
get material(): IPublicApiMaterial;
|
||||
|
||||
/**
|
||||
* event API
|
||||
* this event works globally, can be used between plugins and engine.
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/event
|
||||
*/
|
||||
get event(): IPublicApiEvent;
|
||||
|
||||
/**
|
||||
* project API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/project
|
||||
*/
|
||||
get project(): IPublicApiProject;
|
||||
|
||||
/**
|
||||
* common API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/common
|
||||
*/
|
||||
get common(): IPublicApiCommon;
|
||||
|
||||
/**
|
||||
* plugins API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/plugins
|
||||
*/
|
||||
get plugins(): IPublicApiPlugins;
|
||||
|
||||
/**
|
||||
* logger API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/logger
|
||||
*/
|
||||
get logger(): IPublicApiLogger;
|
||||
|
||||
/**
|
||||
* this event works within current plugin, on an emit locally.
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/event
|
||||
*/
|
||||
get pluginEvent(): IPublicApiEvent;
|
||||
|
||||
/**
|
||||
* canvas API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/canvas
|
||||
*/
|
||||
get canvas(): IPublicApiCanvas;
|
||||
|
||||
/**
|
||||
* workspace API
|
||||
* @tutorial https://lowcode-engine.cn/site/docs/api/workspace
|
||||
*/
|
||||
get workspace(): IPublicApiWorkspace;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @deprecated please use IPublicModelPluginContext instead
|
||||
*/
|
||||
export interface ILowCodePluginContext extends IPublicModelPluginContext {
|
||||
|
||||
@ -2,7 +2,9 @@ import { IPublicEnumTransformStage } from '../enum';
|
||||
import { IPublicTypeCompositeValue } from '../type';
|
||||
import { IPublicModelNode } from './';
|
||||
|
||||
export interface IPublicModelProp {
|
||||
export interface IPublicModelProp<
|
||||
Node = IPublicModelNode
|
||||
> {
|
||||
|
||||
/**
|
||||
* id
|
||||
@ -25,14 +27,14 @@ export interface IPublicModelProp {
|
||||
* 返回所属的节点实例
|
||||
* get node instance, which this prop belongs to
|
||||
*/
|
||||
get node(): IPublicModelNode | null;
|
||||
get node(): Node | null;
|
||||
|
||||
/**
|
||||
* 当本 prop 代表一个 Slot 时,返回对应的 slotNode
|
||||
* return the slot node (only if the current prop represents a slot)
|
||||
* @since v1.1.0
|
||||
*/
|
||||
get slotNode(): IPublicModelNode | undefined | null;
|
||||
get slotNode(): Node | undefined | null;
|
||||
|
||||
/**
|
||||
* 是否是 Prop , 固定返回 true
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { IPublicTypeCompositeValue } from '../type';
|
||||
import { IPublicModelNode, IPublicModelProp } from './';
|
||||
import { IPublicModelNode } from './';
|
||||
|
||||
export interface IPublicModelProps {
|
||||
export interface IBaseModelProps<
|
||||
Prop
|
||||
> {
|
||||
|
||||
/**
|
||||
* id
|
||||
@ -24,7 +26,7 @@ export interface IPublicModelProps {
|
||||
* get prop by path
|
||||
* @param path 属性路径,支持 a / a.b / a.0 等格式
|
||||
*/
|
||||
getProp(path: string): IPublicModelProp | null;
|
||||
getProp(path: string): Prop | null;
|
||||
|
||||
/**
|
||||
* 获取指定 path 的属性模型实例值
|
||||
@ -39,7 +41,7 @@ export interface IPublicModelProps {
|
||||
* get extra prop by path
|
||||
* @param path 属性路径,支持 a / a.b / a.0 等格式
|
||||
*/
|
||||
getExtraProp(path: string): IPublicModelProp | null;
|
||||
getExtraProp(path: string): Prop | null;
|
||||
|
||||
/**
|
||||
* 获取指定 path 的属性模型实例值
|
||||
@ -83,3 +85,5 @@ export interface IPublicModelProps {
|
||||
add(value: IPublicTypeCompositeValue, key?: string | number | undefined): any;
|
||||
|
||||
}
|
||||
|
||||
export type IPublicModelProps = IBaseModelProps<IPublicModelProps>;
|
||||
@ -5,11 +5,15 @@ export interface IPublicModelResource {
|
||||
|
||||
get icon(): ReactElement | undefined;
|
||||
|
||||
get options(): Object;
|
||||
get options(): Record<string, any>;
|
||||
|
||||
get name(): string | undefined;
|
||||
|
||||
get type(): string | undefined;
|
||||
|
||||
get category(): string | undefined;
|
||||
|
||||
get children(): IPublicModelResource[];
|
||||
|
||||
get viewName(): string | undefined;
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
import { IPublicModelNode } from './';
|
||||
import { IPublicTypeDisposable } from '../type';
|
||||
|
||||
export interface IPublicModelSelection {
|
||||
export interface IPublicModelSelection<
|
||||
Node = IPublicModelNode
|
||||
> {
|
||||
|
||||
/**
|
||||
* 返回选中的节点 id
|
||||
@ -14,7 +16,7 @@ export interface IPublicModelSelection {
|
||||
* return selected Node instance,return the first one if multiple nodes are selected
|
||||
* @since v1.1.0
|
||||
*/
|
||||
get node(): IPublicModelNode | null;
|
||||
get node(): Node | null;
|
||||
|
||||
/**
|
||||
* 选中指定节点(覆盖方式)
|
||||
@ -62,7 +64,7 @@ export interface IPublicModelSelection {
|
||||
* 获取选中的节点实例
|
||||
* get selected nodes
|
||||
*/
|
||||
getNodes(): IPublicModelNode[];
|
||||
getNodes(): Node[];
|
||||
|
||||
/**
|
||||
* 获取选区的顶层节点
|
||||
@ -72,7 +74,7 @@ export interface IPublicModelSelection {
|
||||
* getTopNodes() will return [A, B], subA will be removed
|
||||
* @since v1.0.16
|
||||
*/
|
||||
getTopNodes(includeRoot?: boolean): IPublicModelNode[];
|
||||
getTopNodes(includeRoot?: boolean): Node[];
|
||||
|
||||
/**
|
||||
* 注册 selection 变化事件回调
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { IPublicModelNode } from '..';
|
||||
import { IPublicEnumDragObjectType } from '../enum';
|
||||
|
||||
export interface IPublicTypeDragNodeObject {
|
||||
export interface IPublicTypeDragNodeObject<Node = IPublicModelNode> {
|
||||
type: IPublicEnumDragObjectType.Node;
|
||||
nodes: IPublicModelNode[];
|
||||
nodes: Node[];
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ export interface IPublicTypeFieldConfig extends IPublicTypeFieldExtraProps {
|
||||
/**
|
||||
* the name of this setting field, which used in quickEditor
|
||||
*/
|
||||
name: string | number;
|
||||
name?: string | number;
|
||||
|
||||
/**
|
||||
* the field title
|
||||
|
||||
@ -1,59 +1,72 @@
|
||||
import { IPublicModelSettingTarget } from '../model';
|
||||
import { IPublicModelSettingPropEntry, IPublicModelSettingTarget } from '../model';
|
||||
import { IPublicTypeLiveTextEditingConfig } from './';
|
||||
|
||||
/**
|
||||
* extra props for field
|
||||
*/
|
||||
export interface IPublicTypeFieldExtraProps {
|
||||
|
||||
/**
|
||||
* 是否必填参数
|
||||
*/
|
||||
isRequired?: boolean;
|
||||
|
||||
/**
|
||||
* default value of target prop for setter use
|
||||
*/
|
||||
defaultValue?: any;
|
||||
|
||||
/**
|
||||
* get value for field
|
||||
*/
|
||||
getValue?: (target: IPublicModelSettingTarget, fieldValue: any) => any;
|
||||
getValue?: (target: IPublicModelSettingPropEntry, fieldValue: any) => any;
|
||||
|
||||
/**
|
||||
* set value for field
|
||||
*/
|
||||
setValue?: (target: IPublicModelSettingTarget, value: any) => void;
|
||||
setValue?: (target: IPublicModelSettingPropEntry, value: any) => void;
|
||||
|
||||
/**
|
||||
* the field conditional show, is not set always true
|
||||
* @default undefined
|
||||
*/
|
||||
condition?: (target: IPublicModelSettingTarget) => boolean;
|
||||
condition?: (target: IPublicModelSettingPropEntry) => boolean;
|
||||
|
||||
/**
|
||||
* autorun when something change
|
||||
*/
|
||||
autorun?: (target: IPublicModelSettingTarget) => void;
|
||||
|
||||
/**
|
||||
* is this field is a virtual field that not save to schema
|
||||
*/
|
||||
virtual?: (target: IPublicModelSettingTarget) => boolean;
|
||||
|
||||
/**
|
||||
* default collapsed when display accordion
|
||||
*/
|
||||
defaultCollapsed?: boolean;
|
||||
|
||||
/**
|
||||
* important field
|
||||
*/
|
||||
important?: boolean;
|
||||
|
||||
/**
|
||||
* internal use
|
||||
*/
|
||||
forceInline?: number;
|
||||
|
||||
/**
|
||||
* 是否支持变量配置
|
||||
*/
|
||||
supportVariable?: boolean;
|
||||
|
||||
/**
|
||||
* compatiable vision display
|
||||
*/
|
||||
display?: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry';
|
||||
|
||||
// @todo 这个 omit 是否合理?
|
||||
/**
|
||||
* @todo 待补充文档
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { IPublicTypePropType, IPublicTypeComponentAction } from './';
|
||||
import { IPublicModelProp, IPublicModelSettingTarget } from '../model';
|
||||
import { IPublicModelNode, IPublicModelProp, IPublicModelSettingTarget } from '../model';
|
||||
|
||||
/**
|
||||
* 嵌套控制函数
|
||||
@ -184,20 +184,20 @@ export interface ConfigureSupport {
|
||||
*/
|
||||
export interface IPublicTypeCallbacks {
|
||||
// hooks
|
||||
onMouseDownHook?: (e: MouseEvent, currentNode: any) => any;
|
||||
onDblClickHook?: (e: MouseEvent, currentNode: any) => any;
|
||||
onClickHook?: (e: MouseEvent, currentNode: any) => any;
|
||||
onMouseDownHook?: (e: MouseEvent, currentNode: IPublicModelNode) => any;
|
||||
onDblClickHook?: (e: MouseEvent, currentNode: IPublicModelNode) => any;
|
||||
onClickHook?: (e: MouseEvent, currentNode: IPublicModelNode) => any;
|
||||
// onLocateHook?: (e: any, currentNode: any) => any;
|
||||
// onAcceptHook?: (currentNode: any, locationData: any) => any;
|
||||
onMoveHook?: (currentNode: any) => boolean;
|
||||
onMoveHook?: (currentNode: IPublicModelNode) => boolean;
|
||||
// thinkof 限制性拖拽
|
||||
onHoverHook?: (currentNode: any) => boolean;
|
||||
onChildMoveHook?: (childNode: any, currentNode: any) => boolean;
|
||||
onHoverHook?: (currentNode: IPublicModelNode) => boolean;
|
||||
onChildMoveHook?: (childNode: IPublicModelNode, currentNode: IPublicModelNode) => boolean;
|
||||
|
||||
// events
|
||||
onNodeRemove?: (removedNode: any, currentNode: any) => void;
|
||||
onNodeAdd?: (addedNode: any, currentNode: any) => void;
|
||||
onSubtreeModified?: (currentNode: any, options: any) => void;
|
||||
onNodeRemove?: (removedNode: IPublicModelNode | null, currentNode: IPublicModelNode | null) => void;
|
||||
onNodeAdd?: (addedNode: IPublicModelNode | null, currentNode: IPublicModelNode | null) => void;
|
||||
onSubtreeModified?: (currentNode: IPublicModelNode, options: any) => void;
|
||||
onResize?: (
|
||||
e: MouseEvent & {
|
||||
trigger: string;
|
||||
@ -220,6 +220,6 @@ export interface IPublicTypeCallbacks {
|
||||
deltaX?: number;
|
||||
deltaY?: number;
|
||||
},
|
||||
currentNode: any,
|
||||
currentNode: IPublicModelNode,
|
||||
) => void;
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { IPublicModelNode } from '..';
|
||||
|
||||
export interface IPublicTypeOnChangeOptions {
|
||||
export interface IPublicTypeOnChangeOptions<
|
||||
Node = IPublicModelNode
|
||||
> {
|
||||
type: string;
|
||||
node: IPublicModelNode;
|
||||
node: Node;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user