mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-04 17:27:09 +00:00
817 lines
21 KiB
TypeScript
817 lines
21 KiB
TypeScript
import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react';
|
|
import { isPlainObject, uniqueId } from '@ali/lowcode-utils';
|
|
import { isI18nData, SettingTarget, InitialItem, FilterItem, isJSSlot, ProjectSchema, AutorunItem, isJSBlock } from '@ali/lowcode-types';
|
|
import { untracked } from '@ali/lowcode-editor-core';
|
|
import { editor, designer } from '../editor';
|
|
import { SettingField } from '@ali/lowcode-designer';
|
|
|
|
type Field = SettingTarget;
|
|
|
|
export enum DISPLAY_TYPE {
|
|
NONE = 'none', // => condition'plain'
|
|
PLAIN = 'plain',
|
|
INLINE = 'inline',
|
|
BLOCK = 'block',
|
|
ACCORDION = 'accordion',
|
|
TAB = 'tab', // => 'accordion'
|
|
ENTRY = 'entry',
|
|
}
|
|
|
|
// from vision 5.4
|
|
export interface OldPropConfig {
|
|
/**
|
|
* composite share the namespace
|
|
* group just be tie up together
|
|
*/
|
|
type?: 'composite' | 'group'; // => composite as objectSetter
|
|
/**
|
|
* when type is composite or group
|
|
*/
|
|
items?: OldPropConfig[]; // => items
|
|
/**
|
|
* property name: the field key in props of schema
|
|
*/
|
|
name: string; // =>
|
|
title?: string; // =>
|
|
tip?: {
|
|
content?: string;
|
|
url?: string;
|
|
};
|
|
defaultValue?: any; // => extraProps.defaultValue
|
|
initialValue?: any | ((value: any, defaultValue: any) => any); // => initials.initialValue
|
|
initial?: (value: any, defaultValue: any) => any; // => initials.initialValue
|
|
|
|
display?: DISPLAY_TYPE; // => fieldExtraProps
|
|
fieldStyle?: DISPLAY_TYPE; // => fieldExtraProps
|
|
setter?: ComponentClass | ISetterConfig[] | string | SetterGetter; // =>
|
|
supportVariable?: boolean; // => use MixedSetter
|
|
/**
|
|
* the prop should be collapsed while display value is accordion
|
|
*/
|
|
collapse?: boolean; // => extraProps.defaultCollapsed
|
|
/**
|
|
* alias to collapse
|
|
*/
|
|
collapsed?: boolean; // => extraProps.defaultCollapsed
|
|
fieldCollapsed?: boolean; // => extraProps.defaultCollapsed
|
|
/**
|
|
* if a prop is declared as disabled, it will not be saved into
|
|
* schema
|
|
*/
|
|
disabled?: boolean | ReturnBooleanFunction; // => hide & virtual ? thinkof global transform
|
|
/**
|
|
* will not export data to schema
|
|
*/
|
|
ignore?: boolean | ReturnBooleanFunction; // => ?virtualProp ? thinkof global transform
|
|
hidden?: boolean | ReturnBooleanFunction; // => condition
|
|
|
|
/**
|
|
* when use getValue(), accessor shall be called as initializer
|
|
*/
|
|
accessor?(this: Field, value: any): any; // => getValue
|
|
/**
|
|
* when current prop value mutate, the mutator function shall be called
|
|
*/
|
|
mutator?( // => setValue
|
|
this: Field,
|
|
value: any,
|
|
hotValue: any,
|
|
): /*
|
|
preValue: any, // => x
|
|
preHotValue: any, // => x
|
|
*/
|
|
void;
|
|
/**
|
|
* other values' change will trigger sync function here
|
|
*/
|
|
sync?(this: Field, value: any): void; // => autorun
|
|
/**
|
|
* user click var to change current field to
|
|
* variable setting field
|
|
*/
|
|
useVariableChange?(this: Field, data: { isUseVariable: boolean }): any; // => as MixinSetter param
|
|
|
|
slotName?: string;
|
|
slotTitle?: string;
|
|
initialChildren?: any; // schema
|
|
allowTextInput: boolean;
|
|
liveTextEditing?: any;
|
|
}
|
|
|
|
// from vision 5.4
|
|
export interface OldPrototypeConfig {
|
|
packageName: string; // => npm.package
|
|
/**
|
|
* category display in the component pane
|
|
* component will be hidden while the value is: null
|
|
*/
|
|
category: string; // => tags
|
|
componentName: string; // =>
|
|
docUrl?: string; // =>
|
|
defaultProps?: any; // => ?
|
|
/**
|
|
* extra actions on the outline of current selected node
|
|
* by default we have: remove / clone
|
|
*/
|
|
extraActions?: Array<ComponentType<any> | ReactElement> | (() => ReactElement); // => configure.component.actions
|
|
title?: string; // =>
|
|
icon?: ComponentType<any> | ReactElement; // =>
|
|
view: ComponentType; // => ?
|
|
initialChildren?: (props: any) => any[]; // => snippets
|
|
|
|
/**
|
|
* Props configurations of node
|
|
*/
|
|
configure: OldPropConfig[]; // => configure.props
|
|
snippets?: any[]; // => snippets
|
|
transducers?: any; // => ?
|
|
/**
|
|
* Selector expression rectangle of a node, it is usually a querySelector string
|
|
* @example '.classname > div'
|
|
*/
|
|
rectSelector?: string; // => configure.component.rectSelector
|
|
context?: {
|
|
// => ?
|
|
[contextInfoName: string]: any;
|
|
};
|
|
|
|
isContainer?: boolean; // => configure.component.isContainer
|
|
isModal?: boolean; // => configure.component.isModal
|
|
isFloating?: boolean; // => configure.component.isFloating
|
|
descriptor?: string; // => configure.component.descriptor
|
|
|
|
// alias to canDragging
|
|
canDraging?: boolean; // => onDrag
|
|
canDragging?: boolean; // => ?
|
|
|
|
canOperating?: boolean; // => disabledActions
|
|
canUseCondition?: boolean;
|
|
canLoop?: boolean;
|
|
canContain?: (dragment: Node) => boolean; // => nestingRule
|
|
|
|
canDropTo?: ((container: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
|
canDropto?: ((container: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
|
|
|
canDropIn?: ((dragment: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
|
canDroping?: ((dragment: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
|
|
|
didDropOut?: (dragment: any, container: any) => void; // => hooks
|
|
didDropIn?: (dragment: any, container: any) => void; // => hooks
|
|
|
|
/**
|
|
* when sub-node of the current node changed
|
|
* including: sub-node insert / remove
|
|
*/
|
|
subtreeModified?(this: Node): any; // => ? hooks
|
|
|
|
// => ?
|
|
canResizing?: ((dragment: any, triggerDirection: string) => boolean) | boolean;
|
|
onResizeStart?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
|
|
onResize?: (e: MouseEvent, triggerDirection: string, dragment: Node, moveX: number, moveY: number) => void;
|
|
onResizeEnd?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
|
|
devMode?: string;
|
|
schema?: ProjectSchema;
|
|
}
|
|
|
|
export interface ISetterConfig {
|
|
setter?: ComponentClass;
|
|
// use value to decide whether this setter is available
|
|
condition?: (value: any) => boolean;
|
|
}
|
|
|
|
type SetterGetter = (this: Field, value: any) => ComponentClass;
|
|
|
|
type ReturnBooleanFunction = (this: Field, value: any) => boolean;
|
|
|
|
export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollector) {
|
|
const {
|
|
type,
|
|
name,
|
|
title,
|
|
tip,
|
|
slotName,
|
|
slotTitle,
|
|
initialChildren,
|
|
allowTextInput,
|
|
initialValue,
|
|
defaultValue,
|
|
display,
|
|
fieldStyle,
|
|
collapse,
|
|
collapsed,
|
|
fieldCollapsed,
|
|
hidden,
|
|
disabled,
|
|
items,
|
|
ignore,
|
|
initial,
|
|
sync,
|
|
accessor,
|
|
mutator,
|
|
setter,
|
|
useVariableChange,
|
|
supportVariable,
|
|
liveTextEditing,
|
|
} = config;
|
|
|
|
const extraProps: any = {
|
|
display: DISPLAY_TYPE.BLOCK,
|
|
};
|
|
const newConfig: any = {
|
|
type: type === 'group' ? 'group' : 'field',
|
|
name: type === 'group' && !name ? uniqueId('group') : name,
|
|
title,
|
|
extraProps,
|
|
};
|
|
|
|
if (tip) {
|
|
if (typeof title !== 'object' || isI18nData(title) || isValidElement(title)) {
|
|
newConfig.title = {
|
|
label: title,
|
|
tip: tip.content,
|
|
docUrl: tip.url,
|
|
};
|
|
} else {
|
|
newConfig.title = {
|
|
...(title as any),
|
|
tip: tip.content,
|
|
docUrl: tip.url,
|
|
};
|
|
}
|
|
}
|
|
|
|
if (display || fieldStyle) {
|
|
extraProps.display = display || fieldStyle;
|
|
if (extraProps.display === DISPLAY_TYPE.TAB) {
|
|
extraProps.display = DISPLAY_TYPE.ACCORDION;
|
|
}
|
|
}
|
|
|
|
if (collapse || collapsed || fieldCollapsed || extraProps.display === DISPLAY_TYPE.ENTRY) {
|
|
extraProps.defaultCollapsed = true;
|
|
}
|
|
function isDisabled(field: Field) {
|
|
if (typeof disabled === 'function') {
|
|
return disabled.call(field, field.getValue()) === true;
|
|
}
|
|
return disabled === true;
|
|
}
|
|
function isHidden(field: Field) {
|
|
if (typeof hidden === 'function') {
|
|
return hidden.call(field, field.getValue()) === true;
|
|
}
|
|
return hidden === true;
|
|
}
|
|
if (extraProps.display === DISPLAY_TYPE.NONE) {
|
|
extraProps.display = undefined;
|
|
extraProps.condition = () => false;
|
|
} else if (hidden != null || disabled != null) {
|
|
extraProps.condition = (field: Field) => !(isHidden(field) || isDisabled(field));
|
|
}
|
|
|
|
if (type === 'group') {
|
|
newConfig.items = items ? upgradeConfigure(items, collector) : [];
|
|
return newConfig;
|
|
}
|
|
|
|
if (defaultValue !== undefined) {
|
|
extraProps.defaultValue = defaultValue;
|
|
} else if (typeof initialValue !== 'function') {
|
|
extraProps.defaultValue = initialValue;
|
|
}
|
|
|
|
let initialFn = (slotName ? null : initial) || initialValue;
|
|
if (slotName && initialValue === true) {
|
|
initialFn = (value: any, defaultValue: any) => {
|
|
if (isJSBlock(value)) {
|
|
return value;
|
|
}
|
|
return {
|
|
type: 'JSSlot',
|
|
title: slotTitle || title,
|
|
name: slotName,
|
|
value: initialChildren,
|
|
};
|
|
};
|
|
}
|
|
|
|
if (!slotName) {
|
|
if (accessor) {
|
|
extraProps.getValue = (field: Field, fieldValue: any) => {
|
|
return accessor.call(field, fieldValue);
|
|
};
|
|
}
|
|
|
|
if (sync || accessor) {
|
|
collector.addAutorun({
|
|
name,
|
|
autorun: (field: Field) => {
|
|
let fieldValue = untracked(() => field.getValue());
|
|
if (accessor) {
|
|
fieldValue = accessor.call(field, fieldValue)
|
|
}
|
|
if (sync) {
|
|
fieldValue = sync.call(field, fieldValue);
|
|
if (fieldValue !== undefined) {
|
|
field.setValue(fieldValue);
|
|
}
|
|
} else {
|
|
field.setValue(fieldValue);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
if (mutator) {
|
|
extraProps.setValue = (field: Field, value: any) => {
|
|
// TODO: 兼容代码,不触发查询组件的 Mutator
|
|
if (field instanceof SettingField && field.componentMeta?.componentName === 'Filter') {
|
|
return;
|
|
}
|
|
mutator.call(field, value, value);
|
|
};
|
|
}
|
|
}
|
|
|
|
const setterInitial = getInitialFromSetter(setter);
|
|
|
|
if (type !== 'composite') {
|
|
collector.addInitial({
|
|
// FIXME! name could be "xxx.xxx"
|
|
name: slotName || name,
|
|
initial: (field: Field, currentValue: any) => {
|
|
// FIXME! read from prototype.defaultProps
|
|
const defaults = extraProps.defaultValue;
|
|
|
|
if (typeof initialFn !== 'function') {
|
|
initialFn = defaultInitial;
|
|
}
|
|
|
|
const v = initialFn.call(field, currentValue, defaults);
|
|
|
|
if (setterInitial) {
|
|
return setterInitial.call(field, v, defaults);
|
|
}
|
|
|
|
return v;
|
|
},
|
|
});
|
|
}
|
|
|
|
if (ignore != null || disabled != null) {
|
|
collector.addFilter({
|
|
// FIXME! name should be "xxx.xxx"
|
|
name: slotName || name,
|
|
filter: (field: Field, currentValue: any) => {
|
|
let disabledValue: boolean;
|
|
if (typeof disabled === 'function') {
|
|
disabledValue = disabled.call(field, currentValue) === true;
|
|
}
|
|
else {
|
|
disabledValue = disabled === true;
|
|
}
|
|
if (disabledValue) {
|
|
return false;
|
|
}
|
|
if (typeof ignore === 'function') {
|
|
return ignore.call(field, currentValue) !== true;
|
|
}
|
|
return ignore !== true;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (slotName) {
|
|
newConfig.name = slotName;
|
|
if (!newConfig.title && slotTitle) {
|
|
newConfig.title = slotTitle;
|
|
}
|
|
const setters: any[] = [
|
|
{
|
|
componentName: 'SlotSetter',
|
|
initialValue: (field: any, value: any) => {
|
|
if (isJSSlot(value)) {
|
|
return {
|
|
title: slotTitle || title,
|
|
...value,
|
|
};
|
|
}
|
|
return {
|
|
type: 'JSSlot',
|
|
title: slotTitle || title,
|
|
name: slotName,
|
|
value: value == null ? initialChildren : value,
|
|
};
|
|
},
|
|
},
|
|
];
|
|
if (allowTextInput) {
|
|
setters.unshift('I18nSetter');
|
|
}
|
|
if (supportVariable) {
|
|
setters.push('VariableSetter');
|
|
}
|
|
newConfig.setter = setters.length > 1 ? setters : setters[0];
|
|
|
|
return newConfig;
|
|
}
|
|
|
|
let primarySetter: any;
|
|
if (type === 'composite') {
|
|
const initials: InitialItem[] = [];
|
|
const objItems = items
|
|
? upgradeConfigure(items,
|
|
{
|
|
addInitial: (item) => {
|
|
initials.push(item);
|
|
},
|
|
addFilter: (item) => {
|
|
collector.addFilter({
|
|
name: `${name}.${item.name}`,
|
|
filter: item.filter,
|
|
});
|
|
},
|
|
addAutorun: (item) => {
|
|
collector.addAutorun({
|
|
name: `${name}.${item.name}`,
|
|
autorun: item.autorun,
|
|
});
|
|
},
|
|
},
|
|
)
|
|
: [];
|
|
newConfig.items = objItems;
|
|
|
|
const initial = (target: SettingTarget, value?: any) => {
|
|
// TODO:
|
|
const defaults = extraProps.defaultValue;
|
|
const data: any = {};
|
|
initials.forEach((item) => {
|
|
// FIXME! Target may be a wrong
|
|
data[item.name] = item.initial(target, isPlainObject(value) ? value[item.name] : null);
|
|
});
|
|
return data;
|
|
};
|
|
collector.addInitial({
|
|
name,
|
|
initial,
|
|
});
|
|
primarySetter = {
|
|
componentName: 'ObjectSetter',
|
|
props: {
|
|
config: {
|
|
items: objItems,
|
|
},
|
|
},
|
|
initialValue: (field: Field) => {
|
|
return initial(field, field.getValue());
|
|
},
|
|
};
|
|
} else if (setter) {
|
|
if (Array.isArray(setter)) {
|
|
// FIXME! read initial from setter
|
|
primarySetter = setter.map(({ setter, condition }) => {
|
|
return {
|
|
componentName: setter,
|
|
condition: condition
|
|
? (field: Field) => {
|
|
return condition.call(field, field.getValue());
|
|
}
|
|
: null,
|
|
};
|
|
});
|
|
} else {
|
|
primarySetter = setter;
|
|
}
|
|
}
|
|
if (!primarySetter) {
|
|
primarySetter = 'I18nSetter';
|
|
}
|
|
if (supportVariable) {
|
|
const setters = Array.isArray(primarySetter)
|
|
? primarySetter.concat('VariableSetter')
|
|
: [primarySetter, 'VariableSetter'];
|
|
primarySetter = {
|
|
componentName: 'MixedSetter',
|
|
props: {
|
|
setters,
|
|
onSetterChange: (field: Field, name: string) => {
|
|
if (useVariableChange) {
|
|
useVariableChange.call(field, { isUseVariable: name === 'VariableSetter' });
|
|
}
|
|
},
|
|
},
|
|
};
|
|
}
|
|
newConfig.setter = primarySetter;
|
|
|
|
if (liveTextEditing) {
|
|
extraProps.liveTextEditing = liveTextEditing;
|
|
}
|
|
|
|
return newConfig;
|
|
}
|
|
|
|
type AddInitial = (initialItem: InitialItem) => void;
|
|
type AddFilter = (filterItem: FilterItem) => void;
|
|
type AddAutorun = (autorunItem: AutorunItem) => void;
|
|
|
|
type ConfigCollector = {
|
|
addInitial: AddInitial;
|
|
addFilter: AddFilter;
|
|
addAutorun: AddAutorun;
|
|
}
|
|
|
|
function getInitialFromSetter(setter: any) {
|
|
return setter && (
|
|
setter.initial || setter.Initial
|
|
|| (setter.type && (setter.type.initial || setter.type.Initial))
|
|
) || null; // eslint-disable-line
|
|
}
|
|
|
|
function defaultInitial(value: any, defaultValue: any) {
|
|
return value == null ? defaultValue : value;
|
|
}
|
|
|
|
|
|
export function upgradeConfigure(items: OldPropConfig[], collector: ConfigCollector) {
|
|
const configure: any[] = [];
|
|
let ignoreSlotName: any = null;
|
|
items.forEach((config) => {
|
|
if (config.slotName) {
|
|
ignoreSlotName = config.slotName;
|
|
} else if (ignoreSlotName) {
|
|
if (config.name === ignoreSlotName) {
|
|
ignoreSlotName = null;
|
|
return;
|
|
}
|
|
ignoreSlotName = null;
|
|
}
|
|
configure.push(upgradePropConfig(config, collector));
|
|
});
|
|
return configure;
|
|
}
|
|
|
|
export function upgradeActions(actions?: Array<ComponentType<any> | ReactElement> | (() => ReactElement)) {
|
|
if (!actions) {
|
|
return null;
|
|
}
|
|
if (!Array.isArray(actions)) {
|
|
actions = [actions];
|
|
}
|
|
return actions.map((content) => {
|
|
const type: any = isValidElement(content) ? content.type : content;
|
|
if (typeof content === 'function') {
|
|
const fn = content as () => ReactElement;
|
|
content = (({ node }: any) => {
|
|
return fn.call(node);
|
|
}) as any;
|
|
}
|
|
return {
|
|
name: type.displayName || type.name || 'anonymous',
|
|
content,
|
|
important: true,
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 升级
|
|
*/
|
|
export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
|
|
const {
|
|
componentName,
|
|
docUrl,
|
|
title,
|
|
icon,
|
|
packageName,
|
|
category,
|
|
extraActions,
|
|
defaultProps,
|
|
initialChildren,
|
|
snippets,
|
|
view,
|
|
configure,
|
|
transducers,
|
|
isContainer,
|
|
rectSelector,
|
|
isModal,
|
|
isFloating,
|
|
descriptor,
|
|
context,
|
|
canOperating,
|
|
canContain,
|
|
canDropTo,
|
|
canDropto,
|
|
canDropIn,
|
|
canDroping,
|
|
canUseCondition,
|
|
canLoop,
|
|
|
|
// hooks
|
|
canDraging,
|
|
canDragging, // handleDragging
|
|
// events
|
|
didDropOut, // onNodeRemove
|
|
didDropIn, // onNodeAdd
|
|
subtreeModified, // onSubtreeModified
|
|
|
|
canResizing, // resizing
|
|
onResizeStart, // onResizeStart
|
|
onResize, // onResize
|
|
onResizeEnd, // onResizeEnd
|
|
devMode,
|
|
schema,
|
|
} = oldConfig;
|
|
|
|
const meta: any = {
|
|
componentName,
|
|
title,
|
|
icon,
|
|
docUrl,
|
|
devMode: devMode || 'procode',
|
|
schema: schema?.componentsTree[0],
|
|
};
|
|
|
|
if (category) {
|
|
meta.tags = [category];
|
|
}
|
|
if (packageName) {
|
|
meta.npm = {
|
|
componentName,
|
|
package: packageName,
|
|
};
|
|
}
|
|
|
|
const component: any = {
|
|
isContainer,
|
|
rootSelector: rectSelector,
|
|
isModal,
|
|
isFloating,
|
|
descriptor,
|
|
};
|
|
|
|
if (canOperating === false) {
|
|
component.disableBehaviors = '*';
|
|
}
|
|
if (extraActions) {
|
|
component.actions = upgradeActions(extraActions);
|
|
}
|
|
const nestingRule: any = {};
|
|
if (canContain) {
|
|
nestingRule.descendantWhitelist = canContain;
|
|
}
|
|
if (canDropTo != null || canDropto != null) {
|
|
if (canDropTo === false || canDropto === false) {
|
|
nestingRule.parentWhitelist = () => false;
|
|
}
|
|
if (canDropTo !== true && canDropto !== true) {
|
|
nestingRule.parentWhitelist = canDropTo || canDropto;
|
|
}
|
|
}
|
|
if (canDropIn != null || canDroping != null) {
|
|
if (canDropIn === false || canDroping === false) {
|
|
nestingRule.childWhitelist = () => false;
|
|
}
|
|
if (canDropIn !== true && canDroping !== true) {
|
|
nestingRule.childWhitelist = canDropIn || canDroping;
|
|
}
|
|
}
|
|
component.nestingRule = nestingRule;
|
|
|
|
// 未考虑清楚的,放在实验性段落
|
|
const experimental: any = {};
|
|
if (context) {
|
|
// for prototype.getContextInfo
|
|
experimental.context = context;
|
|
}
|
|
if (snippets) {
|
|
experimental.snippets = snippets.map((data) => {
|
|
const { schema = {} } = data;
|
|
if (!schema.children && initialChildren && typeof initialChildren !== 'function') {
|
|
schema.children = initialChildren;
|
|
}
|
|
return {
|
|
...data,
|
|
schema,
|
|
};
|
|
});
|
|
}
|
|
// FIXME! defaultProps for initial input
|
|
// initialChildren maybe a function
|
|
else if (defaultProps || initialChildren) {
|
|
const snippet = {
|
|
screenshot: icon,
|
|
label: title,
|
|
schema: {
|
|
componentName,
|
|
props: defaultProps,
|
|
children: initialChildren,
|
|
},
|
|
};
|
|
if (experimental.snippets) {
|
|
experimental.snippets.push(snippet);
|
|
} else {
|
|
experimental.snippets = [snippet];
|
|
}
|
|
}
|
|
if (initialChildren) {
|
|
experimental.initialChildren =
|
|
typeof initialChildren === 'function'
|
|
? (node: any) => {
|
|
return initialChildren.call(node, node.settingEntry);
|
|
}
|
|
: initialChildren;
|
|
}
|
|
if (view) {
|
|
experimental.view = view;
|
|
}
|
|
if (transducers) {
|
|
// Array<{ toStatic, toNative }>
|
|
// ? only twice
|
|
experimental.transducers = transducers;
|
|
}
|
|
if (canResizing) {
|
|
// TODO: enhance
|
|
experimental.getResizingHandlers = (currentNode: any) => {
|
|
const directs = ['n', 'w', 's', 'e'];
|
|
if (canResizing === true) {
|
|
return directs;
|
|
}
|
|
return directs.filter((d) => canResizing(currentNode, d));
|
|
};
|
|
}
|
|
|
|
const callbacks: any = {};
|
|
if (canDragging != null || canDraging != null) {
|
|
let v = true;
|
|
if (canDragging === false || canDraging === false) {
|
|
v = false;
|
|
}
|
|
callbacks.onMoveHook = () => v;
|
|
}
|
|
if (didDropIn) {
|
|
callbacks.onNodeAdd = didDropIn;
|
|
}
|
|
if (didDropOut) {
|
|
callbacks.onNodeRemove = didDropOut;
|
|
}
|
|
if (subtreeModified) {
|
|
callbacks.onSubtreeModified = subtreeModified;
|
|
}
|
|
if (onResize) {
|
|
callbacks.onResize = (e: any, currentNode: any) => {
|
|
// todo: what is trigger?
|
|
const { trigger, deltaX, deltaY } = e;
|
|
onResize(e, trigger, currentNode, deltaX, deltaY);
|
|
};
|
|
}
|
|
if (onResizeStart) {
|
|
callbacks.onResizeStart = (e: any, currentNode: any) => {
|
|
// todo: what is trigger?
|
|
const { trigger } = e;
|
|
onResizeStart(e, trigger, currentNode);
|
|
};
|
|
}
|
|
if (onResizeEnd) {
|
|
callbacks.onResizeEnd = (e: any, currentNode: any) => {
|
|
// todo: what is trigger?
|
|
const { trigger } = e;
|
|
onResizeEnd(e, trigger, currentNode);
|
|
};
|
|
}
|
|
|
|
experimental.callbacks = callbacks;
|
|
|
|
const initials: InitialItem[] = [];
|
|
const filters: FilterItem[] = [];
|
|
const autoruns: AutorunItem[] = [];
|
|
const props = upgradeConfigure(configure || [],
|
|
{
|
|
addInitial: (item) => {
|
|
initials.push(item);
|
|
},
|
|
addFilter: (item) => {
|
|
filters.push(item);
|
|
},
|
|
addAutorun: (item) => {
|
|
autoruns.push(item);
|
|
}
|
|
}
|
|
);
|
|
experimental.initials = initials;
|
|
experimental.filters = filters;
|
|
experimental.autoruns = autoruns;
|
|
|
|
const supports: any = {};
|
|
if (canUseCondition != null) {
|
|
supports.condition = canUseCondition;
|
|
}
|
|
if (canLoop != null) {
|
|
supports.loop = canLoop;
|
|
}
|
|
meta.configure = { props, component, supports };
|
|
meta.experimental = experimental;
|
|
return meta;
|
|
}
|