mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-05 17:57:13 +00:00
feat: 补充一波 callbacks / hooks shell 模型转换
This commit is contained in:
parent
ece6c76b46
commit
3f041b592b
@ -19,7 +19,16 @@ import EventEmitter from 'events';
|
||||
import { isNode, Node, ParentalNode } from './document';
|
||||
import { Designer } from './designer';
|
||||
import { intlNode } from './locale';
|
||||
import { IconLock, IconUnlock, IconContainer, IconPage, IconComponent, IconRemove, IconClone, IconHidden } from './icons';
|
||||
import {
|
||||
IconLock,
|
||||
IconUnlock,
|
||||
IconContainer,
|
||||
IconPage,
|
||||
IconComponent,
|
||||
IconRemove,
|
||||
IconClone,
|
||||
IconHidden,
|
||||
} from './icons';
|
||||
|
||||
function ensureAList(list?: string | string[]): string[] | null {
|
||||
if (!list) {
|
||||
@ -183,10 +192,10 @@ export class ComponentMeta {
|
||||
this._title =
|
||||
typeof title === 'string'
|
||||
? {
|
||||
type: 'i18n',
|
||||
'en-US': this.componentName,
|
||||
'zh-CN': title,
|
||||
}
|
||||
type: 'i18n',
|
||||
'en-US': this.componentName,
|
||||
'zh-CN': title,
|
||||
}
|
||||
: title;
|
||||
}
|
||||
|
||||
@ -265,7 +274,8 @@ export class ComponentMeta {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { disableBehaviors, actions } = this._transformedMetadata?.configure.component || {};
|
||||
const disabled =
|
||||
ensureAList(disableBehaviors) || (this.isRootComponent(false) ? ['copy', 'remove', 'lock', 'unlock'] : null);
|
||||
ensureAList(disableBehaviors) ||
|
||||
(this.isRootComponent(false) ? ['copy', 'remove', 'lock', 'unlock'] : null);
|
||||
actions = builtinComponentActions.concat(
|
||||
this.designer.getGlobalComponentActions() || [],
|
||||
actions || [],
|
||||
@ -291,7 +301,10 @@ export class ComponentMeta {
|
||||
checkNestingUp(my: Node | NodeData, parent: ParentalNode) {
|
||||
// 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器
|
||||
if (this.parentWhitelist) {
|
||||
return this.parentWhitelist(parent, my);
|
||||
return this.parentWhitelist(
|
||||
parent.internalToShellNode(),
|
||||
isNode(my) ? my.internalToShellNode() : my,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -302,7 +315,10 @@ export class ComponentMeta {
|
||||
const _target: any = !Array.isArray(target) ? [target] : target;
|
||||
return _target.every((item: Node | NodeSchema) => {
|
||||
const _item = !isNode(item) ? new Node(my.document, item) : item;
|
||||
return this.childWhitelist && this.childWhitelist(_item, my);
|
||||
return (
|
||||
this.childWhitelist &&
|
||||
this.childWhitelist(_item.internalToShellNode(), my.internalToShellNode())
|
||||
);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
@ -484,7 +500,7 @@ const builtinComponentActions: ComponentAction[] = [
|
||||
},
|
||||
},
|
||||
condition: (node: Node) => {
|
||||
return (engineConfig.get('enableCanvasLock', false) && node.isContainer() && !node.isLocked);
|
||||
return engineConfig.get('enableCanvasLock', false) && node.isContainer() && !node.isLocked;
|
||||
},
|
||||
important: true,
|
||||
},
|
||||
@ -498,7 +514,7 @@ const builtinComponentActions: ComponentAction[] = [
|
||||
},
|
||||
},
|
||||
condition: (node: Node) => {
|
||||
return (engineConfig.get('enableCanvasLock', false) && node.isContainer() && node.isLocked);
|
||||
return engineConfig.get('enableCanvasLock', false) && node.isContainer() && node.isLocked;
|
||||
},
|
||||
important: true,
|
||||
},
|
||||
|
||||
@ -44,7 +44,8 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
|
||||
return null;
|
||||
}
|
||||
if (isDynamicSetter(this._setter)) {
|
||||
return this._setter.call(this, this);
|
||||
const shellThis = this.internalToShellPropEntry();
|
||||
return this._setter.call(shellThis, shellThis);
|
||||
}
|
||||
return this._setter;
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { obx, computed, makeObservable, runInAction } from '@ali/lowcode-editor-core';
|
||||
import { GlobalEvent, IEditor, isJSExpression } from '@ali/lowcode-types';
|
||||
import { uniqueId } from '@ali/lowcode-utils';
|
||||
import { SettingPropEntry as ShellSettingPropEntry } from '@ali/lowcode-shell';
|
||||
import { SettingEntry } from './setting-entry';
|
||||
import { Node } from '../../document';
|
||||
import { ComponentMeta } from '../../component-meta';
|
||||
@ -124,7 +125,11 @@ export class SettingPropEntry implements SettingEntry {
|
||||
return runInAction(() => {
|
||||
if (this.type !== 'field') {
|
||||
const { getValue } = this.extraProps;
|
||||
return getValue ? (getValue(this, undefined) === undefined ? 0 : 1) : 0;
|
||||
return getValue
|
||||
? getValue(this.internalToShellPropEntry(), undefined) === undefined
|
||||
? 0
|
||||
: 1
|
||||
: 0;
|
||||
}
|
||||
if (this.nodes.length === 1) {
|
||||
return 2;
|
||||
@ -160,7 +165,7 @@ export class SettingPropEntry implements SettingEntry {
|
||||
}
|
||||
const { getValue } = this.extraProps;
|
||||
try {
|
||||
return getValue ? getValue(this, val) : val;
|
||||
return getValue ? getValue(this.internalToShellPropEntry(), val) : val;
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return val;
|
||||
@ -179,7 +184,7 @@ export class SettingPropEntry implements SettingEntry {
|
||||
const { setValue } = this.extraProps;
|
||||
if (setValue && !extraOptions?.disableMutator) {
|
||||
try {
|
||||
setValue(this, val);
|
||||
setValue(this.internalToShellPropEntry(), val);
|
||||
} catch (e) {
|
||||
/* istanbul ignore next */
|
||||
console.warn(e);
|
||||
@ -202,7 +207,7 @@ export class SettingPropEntry implements SettingEntry {
|
||||
const { setValue } = this.extraProps;
|
||||
if (setValue) {
|
||||
try {
|
||||
setValue(this, undefined);
|
||||
setValue(this.internalToShellPropEntry(), undefined);
|
||||
} catch (e) {
|
||||
/* istanbul ignore next */
|
||||
console.warn(e);
|
||||
@ -293,7 +298,12 @@ export class SettingPropEntry implements SettingEntry {
|
||||
}
|
||||
|
||||
notifyValueChange(oldValue: any, newValue: any) {
|
||||
this.editor.emit(GlobalEvent.Node.Prop.Change, { node: this.getNode(), prop: this, oldValue, newValue });
|
||||
this.editor.emit(GlobalEvent.Node.Prop.Change, {
|
||||
node: this.getNode(),
|
||||
prop: this,
|
||||
oldValue,
|
||||
newValue,
|
||||
});
|
||||
}
|
||||
|
||||
getDefaultValue() {
|
||||
@ -352,4 +362,8 @@ export class SettingPropEntry implements SettingEntry {
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
internalToShellPropEntry() {
|
||||
return ShellSettingPropEntry.create(this) as any;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
||||
let stageName;
|
||||
if (display === 'entry') {
|
||||
runInAction(() => {
|
||||
stageName = `${field.getNode().id }_${field.name.toString()}`;
|
||||
stageName = `${field.getNode().id}_${field.name.toString()}`;
|
||||
// 清除原 stage,不然 content 引用的一直是老的 field,导致数据无法得到更新
|
||||
stages.container.remove(stageName);
|
||||
const stage = stages.add({
|
||||
@ -62,7 +62,7 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
||||
const { condition, defaultValue } = extraProps;
|
||||
let visible;
|
||||
try {
|
||||
visible = typeof condition === 'function' ? condition(field) !== false : true;
|
||||
visible = typeof condition === 'function' ? condition(field.internalToShellPropEntry()) !== false : true;
|
||||
} catch (error) {
|
||||
console.error('exception when condition (hidden) is excuted', error);
|
||||
}
|
||||
@ -86,7 +86,7 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
||||
if (setter.props) {
|
||||
setterProps = setter.props;
|
||||
if (typeof setterProps === 'function') {
|
||||
setterProps = setterProps(field);
|
||||
setterProps = setterProps(field.internalToShellPropEntry());
|
||||
}
|
||||
}
|
||||
if (setter.initialValue != null) {
|
||||
@ -150,40 +150,40 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
||||
...extraProps,
|
||||
},
|
||||
!stageName &&
|
||||
createSetterContent(setterType, {
|
||||
...shallowIntl(setterProps),
|
||||
forceInline: extraProps.forceInline,
|
||||
key: field.id,
|
||||
// === injection
|
||||
prop: field, // for compatible vision
|
||||
selected: field.top?.getNode(),
|
||||
field,
|
||||
// === IO
|
||||
value, // reaction point
|
||||
onChange: (value: any) => {
|
||||
this.setState({
|
||||
// eslint-disable-next-line react/no-unused-state
|
||||
value,
|
||||
});
|
||||
field.setValue(value);
|
||||
if (_onChange) _onChange(value, field);
|
||||
},
|
||||
onInitial: () => {
|
||||
if (initialValue == null) {
|
||||
return;
|
||||
}
|
||||
const value = typeof initialValue === 'function' ? initialValue(field) : initialValue;
|
||||
this.setState({
|
||||
// eslint-disable-next-line react/no-unused-state
|
||||
value,
|
||||
});
|
||||
field.setValue(value);
|
||||
},
|
||||
createSetterContent(setterType, {
|
||||
...shallowIntl(setterProps),
|
||||
forceInline: extraProps.forceInline,
|
||||
key: field.id,
|
||||
// === injection
|
||||
prop: field.internalToShellPropEntry(), // for compatible vision
|
||||
selected: field.top?.getNode()?.internalToShellNode(),
|
||||
field: field.internalToShellPropEntry(),
|
||||
// === IO
|
||||
value, // reaction point
|
||||
onChange: (value: any) => {
|
||||
this.setState({
|
||||
// eslint-disable-next-line react/no-unused-state
|
||||
value,
|
||||
});
|
||||
field.setValue(value);
|
||||
if (_onChange) _onChange(value, field);
|
||||
},
|
||||
onInitial: () => {
|
||||
if (initialValue == null) {
|
||||
return;
|
||||
}
|
||||
const value = typeof initialValue === 'function' ? initialValue(field.internalToShellPropEntry()) : initialValue;
|
||||
this.setState({
|
||||
// eslint-disable-next-line react/no-unused-state
|
||||
value,
|
||||
});
|
||||
field.setValue(value);
|
||||
},
|
||||
|
||||
removeProp: () => {
|
||||
field.parent.clearPropValue(field.name);
|
||||
},
|
||||
}),
|
||||
removeProp: () => {
|
||||
field.parent.clearPropValue(field.name);
|
||||
},
|
||||
}),
|
||||
extraProps.forceInline ? 'plain' : extraProps.display,
|
||||
);
|
||||
}
|
||||
@ -200,7 +200,7 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
|
||||
super(props);
|
||||
const { field } = this.props;
|
||||
const { extraProps } = field;
|
||||
const { condition, display } = extraProps;
|
||||
const { display } = extraProps;
|
||||
|
||||
const { stages } = field.editor.get('skeleton') as Skeleton;
|
||||
// const items = field.items;
|
||||
@ -208,7 +208,7 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
|
||||
let stageName;
|
||||
if (display === 'entry') {
|
||||
runInAction(() => {
|
||||
stageName = `${field.getNode().id }_${field.name.toString()}`;
|
||||
stageName = `${field.getNode().id}_${field.name.toString()}`;
|
||||
// 清除原 stage,不然 content 引用的一直是老的 field,导致数据无法得到更新
|
||||
stages.container.remove(stageName);
|
||||
stages.add({
|
||||
@ -228,7 +228,7 @@ class SettingGroupView extends Component<SettingGroupViewProps> {
|
||||
const { field } = this.props;
|
||||
const { extraProps } = field;
|
||||
const { condition, display } = extraProps;
|
||||
const visible = field.isSingle && typeof condition === 'function' ? condition(field) !== false : true;
|
||||
const visible = field.isSingle && typeof condition === 'function' ? condition(field.internalToShellPropEntry()) !== false : true;
|
||||
|
||||
if (!visible) {
|
||||
return null;
|
||||
|
||||
@ -24,12 +24,10 @@ import {
|
||||
designerSymbol,
|
||||
skeletonSymbol,
|
||||
} from '@ali/lowcode-shell';
|
||||
import { getLogger, Logger } from '@ali/lowcode-utils';
|
||||
import { getLogger, Logger, isPlainObject } from '@ali/lowcode-utils';
|
||||
import './modules/live-editing';
|
||||
import { isPlainObject } from '@ali/lowcode-utils';
|
||||
import utils from './modules/utils';
|
||||
|
||||
|
||||
export * from './modules/editor-types';
|
||||
export * from './modules/skeleton-types';
|
||||
export * from './modules/designer-types';
|
||||
@ -71,12 +69,12 @@ const event = new Event(editor, { prefix: 'common' });
|
||||
const logger = getLogger({ level: 'warn', bizName: 'common' });
|
||||
|
||||
export {
|
||||
editor,
|
||||
editorCabin,
|
||||
// editor,
|
||||
// editorCabin,
|
||||
// skeleton,
|
||||
skeletonCabin,
|
||||
designer,
|
||||
designerCabin,
|
||||
// skeletonCabin,
|
||||
// designer,
|
||||
// designerCabin,
|
||||
plugins,
|
||||
// setters,
|
||||
project,
|
||||
|
||||
@ -11,6 +11,7 @@ import Selection from './selection';
|
||||
import Setters from './setters';
|
||||
import Hotkey from './hotkey';
|
||||
import Skeleton from './skeleton';
|
||||
import SettingPropEntry from './setting-prop-entry';
|
||||
export * from './symbols';
|
||||
|
||||
/**
|
||||
@ -33,4 +34,5 @@ export {
|
||||
Setters,
|
||||
Hotkey,
|
||||
Skeleton,
|
||||
SettingPropEntry,
|
||||
};
|
||||
@ -1,5 +1,5 @@
|
||||
import { NodeChildren as InnerNodeChildren, Node as InnerNode } from '@ali/lowcode-designer';
|
||||
import { NodeSchema } from '@ali/lowcode-types';
|
||||
import { NodeSchema, NodeData, TransformStage } from '@ali/lowcode-types';
|
||||
import Node from './node';
|
||||
import { nodeSymbol, nodeChildrenSymbol } from './symbols';
|
||||
|
||||
@ -97,6 +97,14 @@ export default class NodeChildren {
|
||||
}, initialValue);
|
||||
}
|
||||
|
||||
importSchema(data?: NodeData | NodeData[]) {
|
||||
this[nodeChildrenSymbol].import(data);
|
||||
}
|
||||
|
||||
exportSchema(stage?: TransformStage) {
|
||||
return this[nodeChildrenSymbol].export(stage);
|
||||
}
|
||||
|
||||
mergeChildren(
|
||||
remover: (node: Node, idx: number) => boolean,
|
||||
adder: (children: Node[]) => any,
|
||||
|
||||
@ -146,6 +146,17 @@ export default class Node {
|
||||
return this.children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
getDOMNode() {
|
||||
return this[nodeSymbol].getDOMNode();
|
||||
}
|
||||
|
||||
getRect() {
|
||||
return this[nodeSymbol].getRect();
|
||||
}
|
||||
|
||||
hasSlots() {
|
||||
return this[nodeSymbol].hasSlots();
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ export default class Project {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use simulatorHost instead.
|
||||
* @deprecated use .simulatorHost instead.
|
||||
*/
|
||||
get simulator() {
|
||||
return this.simulatorHost;
|
||||
|
||||
40
packages/shell/src/setting-prop-entry.ts
Normal file
40
packages/shell/src/setting-prop-entry.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { SettingEntry } from '@ali/lowcode-designer';
|
||||
import { CompositeValue, SettingTarget } from '@ali/lowcode-types';
|
||||
import { settingPropEntrySymbol } from './symbols';
|
||||
import Node from './node';
|
||||
import SettingTopEntry from './setting-top-entry';
|
||||
|
||||
export default class SettingPropEntry {
|
||||
private readonly [settingPropEntrySymbol]: SettingEntry;
|
||||
|
||||
constructor(prop: SettingEntry) {
|
||||
this[settingPropEntrySymbol] = prop;
|
||||
}
|
||||
|
||||
static create(prop: SettingEntry) {
|
||||
return new SettingPropEntry(prop);
|
||||
}
|
||||
|
||||
get node(): Node | null {
|
||||
return Node.create(this[settingPropEntrySymbol].getNode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use .node instead
|
||||
*/
|
||||
getNode() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
setValue(val: CompositeValue) {
|
||||
this[settingPropEntrySymbol].setValue(val);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this[settingPropEntrySymbol].getValue();
|
||||
}
|
||||
|
||||
getProps() {
|
||||
return SettingTopEntry.create(this[settingPropEntrySymbol].getProps() as SettingEntry) as any;
|
||||
}
|
||||
}
|
||||
34
packages/shell/src/setting-top-entry.ts
Normal file
34
packages/shell/src/setting-top-entry.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { SettingEntry } from '@ali/lowcode-designer';
|
||||
import { settingTopEntrySymbol } from './symbols';
|
||||
import Node from './node';
|
||||
|
||||
export default class SettingTopEntry {
|
||||
private readonly [settingTopEntrySymbol]: SettingEntry;
|
||||
|
||||
constructor(prop: SettingEntry) {
|
||||
this[settingTopEntrySymbol] = prop;
|
||||
}
|
||||
|
||||
static create(prop: SettingEntry) {
|
||||
return new SettingTopEntry(prop);
|
||||
}
|
||||
|
||||
get node(): Node | null {
|
||||
return Node.create(this[settingTopEntrySymbol].getNode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use .node instead
|
||||
*/
|
||||
getNode() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
getPropValue(propName: string | number) {
|
||||
return this[settingTopEntrySymbol].getPropValue(propName);
|
||||
}
|
||||
|
||||
setPropValue(propName: string | number, value: any) {
|
||||
this[settingTopEntrySymbol].setPropValue(propName, value);
|
||||
}
|
||||
}
|
||||
@ -8,8 +8,10 @@ export const documentSymbol = Symbol('document');
|
||||
export const editorSymbol = Symbol('editor');
|
||||
export const nodeSymbol = Symbol('node');
|
||||
export const nodeChildrenSymbol = Symbol('nodeChildren');
|
||||
export const propsSymbol = Symbol('props');
|
||||
export const propSymbol = Symbol('prop');
|
||||
export const settingPropEntrySymbol = Symbol('settingPropEntry');
|
||||
export const settingTopEntrySymbol = Symbol('settingTopEntry');
|
||||
export const propsSymbol = Symbol('props');
|
||||
export const detectingSymbol = Symbol('detecting');
|
||||
export const selectionSymbol = Symbol('selection');
|
||||
export const historySymbol = Symbol('history');
|
||||
|
||||
@ -52,6 +52,11 @@ export interface SettingTarget {
|
||||
*/
|
||||
get: (propName: string | number) => SettingTarget | null;
|
||||
|
||||
/**
|
||||
* 取得子项
|
||||
*/
|
||||
getProps?: () => SettingTarget;
|
||||
|
||||
/**
|
||||
* 获取子项属性值
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user