From 93a3c68f438a3b086292c55d9112e21c26878e9f Mon Sep 17 00:00:00 2001 From: kangwei Date: Sun, 3 May 2020 02:12:24 +0800 Subject: [PATCH] fix variables --- packages/demo/src/vision/index.ts | 9 +++-- packages/demo/src/vision/module.d.ts | 4 ++ packages/designer/src/designer/designer.ts | 10 +++-- .../src/document/node/node-children.ts | 32 ++++++++++++---- packages/designer/src/document/node/node.ts | 8 ++++ packages/editor-core/src/di/setter.ts | 15 ++++++++ .../src/components/mixed-setter/index.tsx | 19 +++++----- .../src/components/mixed-setter/style.less | 10 ++++- .../src/components/widget-views.tsx | 2 +- .../src/layouts/workbench.less | 31 ++++++--------- .../src/transducers/addon-combine.ts | 8 ++-- .../editor-skeleton/src/widget/panel-dock.ts | 3 +- packages/editor-skeleton/src/widget/panel.ts | 15 ++++++++ .../src/renderer-view.tsx | 30 +++++++++++++++ .../src/bundle/upgrade-metadata.ts | 38 +++++++++++++++++-- packages/vision-preset/src/context.ts | 1 - 16 files changed, 179 insertions(+), 56 deletions(-) diff --git a/packages/demo/src/vision/index.ts b/packages/demo/src/vision/index.ts index 36e8e4267..3761dee2c 100644 --- a/packages/demo/src/vision/index.ts +++ b/packages/demo/src/vision/index.ts @@ -25,9 +25,6 @@ Trunk.registerSetter('I18nSetter', { 'zh-CN': '国际化输入', 'en-US': 'International Input' }, - // TODO: below - // condition?: (field: any) => boolean; - // initialValue?: any | ((field: any) => any); recommend: true, }); context.use(HOOKS.VE_SETTING_FIELD_VARIABLE_SETTER, VariableSetter); @@ -112,7 +109,7 @@ function initDemoPanes() { description: '帮助', }, }); - + skeleton.add({ area: 'topArea', type: 'Dock', @@ -289,6 +286,10 @@ function initActionPane() { async function init() { Engine.Env.setEnv('RE_VERSION', '7.2.0'); + Engine.Env.setSupportFeatures({ + subview: true, + i18nPane: true, + }); await loadAssets(); await loadSchema(); await initTrunkPane(); diff --git a/packages/demo/src/vision/module.d.ts b/packages/demo/src/vision/module.d.ts index 21aab4290..2217b3e06 100644 --- a/packages/demo/src/vision/module.d.ts +++ b/packages/demo/src/vision/module.d.ts @@ -2,3 +2,7 @@ declare module "@ali/visualengine"; declare module "@ali/visualengine-utils"; declare module "@ali/ve-trunk-pane"; declare module "@ali/vs-variable-setter"; +declare module "@ali/ve-datapool-pane"; +declare module "@ali/ve-i18n-manage-pane"; +declare module "@ali/ve-action-pane"; +declare module "@ali/vu-legao-design-fetch-context"; diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts index f5c08b888..f5881b262 100644 --- a/packages/designer/src/designer/designer.ts +++ b/packages/designer/src/designer/designer.ts @@ -71,9 +71,13 @@ export class Designer { this.hovering.enable = false; const { dragObject } = e; if (isDragNodeObject(dragObject)) { - if (dragObject.nodes.length === 1 && dragObject.nodes[0].parent) { - // ensure current selecting - dragObject.nodes[0].select(); + if (dragObject.nodes.length === 1) { + if (dragObject.nodes[0].parent) { + // ensure current selecting + dragObject.nodes[0].select(); + } else { + this.currentSelection?.clear(); + } } } else { this.currentSelection?.clear(); diff --git a/packages/designer/src/document/node/node-children.ts b/packages/designer/src/document/node/node-children.ts index a8a4a364e..43701b4ba 100644 --- a/packages/designer/src/document/node/node-children.ts +++ b/packages/designer/src/document/node/node-children.ts @@ -2,9 +2,13 @@ import { obx, computed } from '@ali/lowcode-editor-core'; import { Node, ParentalNode } from './node'; import { TransformStage } from './transform-stage'; import { NodeData, isNodeSchema } from '@ali/lowcode-types'; +import { shallowEqual } from '@ali/lowcode-utils'; +import { EventEmitter } from 'events'; export class NodeChildren { @obx.val private children: Node[]; + private emitter = new EventEmitter(); + constructor(readonly owner: ParentalNode, data: NodeData | NodeData[]) { this.children = (Array.isArray(data) ? data : [data]).map(child => { return this.owner.document.createNode(child); @@ -52,6 +56,9 @@ export class NodeChildren { this.children = children; this.interalInitParent(); + if (!shallowEqual(children, originChildren)) { + this.emitter.emit('change'); + } } /** @@ -86,6 +93,7 @@ export class NodeChildren { deleted.internalSetParent(null); deleted.purge(); } + this.emitter.emit('change'); return false; } @@ -118,6 +126,8 @@ export class NodeChildren { children.splice(index, 0, node); } + this.emitter.emit('change'); + // check condition group if (node.conditionGroup) { if ( @@ -208,14 +218,7 @@ export class NodeChildren { } mergeChildren(remover: () => any, adder: (children: Node[]) => NodeData[] | null, sorter: () => any) { - /* - const children = this.children.slice(); - children.forEach(child => child.internalSetParent(null)); - - this.children = children; - this.interalInitParent(); - */ - + let changed = false; if (remover) { const willRemove = this.children.filter(remover); if (willRemove.length > 0) { @@ -226,6 +229,7 @@ export class NodeChildren { node.remove(); } }); + changed = true; } } if (adder) { @@ -236,11 +240,23 @@ export class NodeChildren { this.children.push(node); node.internalSetParent(this.owner); }); + changed = true; } } if (sorter) { this.children = this.children.sort(sorter); + changed = true; } + if (changed) { + this.emitter.emit('change'); + } + } + + onChange(fn: () => void) { + this.emitter.on('change', fn); + return () => { + this.emitter.removeListener('change', fn); + }; } private purged = false; diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index cd4d1db5b..f70a737c1 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -593,6 +593,10 @@ export class Node { return this.props; } + onChildrenChange(fn: () => void) { + return this.children?.onChange(fn); + } + mergeChildren(remover: () => any, adder: (children: Node[]) => NodeData[] | null, sorter: () => any) { this.children?.mergeChildren(remover, adder, sorter); } @@ -654,6 +658,10 @@ export class Node { this._addons[key] = exportData; } + getRect(): DOMRect | null { + return this.document.simulator?.computeRect(this) || null; + } + toString() { return this.id; } diff --git a/packages/editor-core/src/di/setter.ts b/packages/editor-core/src/di/setter.ts index b66bfc06c..428b0a7ea 100644 --- a/packages/editor-core/src/di/setter.ts +++ b/packages/editor-core/src/di/setter.ts @@ -39,9 +39,24 @@ export function registerSetter( title: (setter as any).displayName || (setter as any).name || 'CustomSetter', }; } + if (!setter.initialValue) { + const initial = getInitialFromSetter(setter.component); + if (initial) { + setter.initialValue = (field: any) => { + return initial.call(field, field.getValue()); + }; + } + } settersMap.set(typeOrMaps, { type: typeOrMaps, ...setter }); } +function getInitialFromSetter(setter: any) { + return setter && ( + setter.initial || setter.Initial + || (setter.type && (setter.type.initial || setter.type.Initial)) + ) || null; // eslint-disable-line +} + export function getSetter(type: string): RegisteredSetter | null { return settersMap.get(type) || null; } diff --git a/packages/editor-skeleton/src/components/mixed-setter/index.tsx b/packages/editor-skeleton/src/components/mixed-setter/index.tsx index 4e1ed2e2a..67e020925 100644 --- a/packages/editor-skeleton/src/components/mixed-setter/index.tsx +++ b/packages/editor-skeleton/src/components/mixed-setter/index.tsx @@ -26,7 +26,7 @@ import { intlNode } from '../../locale'; import './style.less'; import { SettingField } from '@ali/lowcode-designer'; -import { IconVariable } from 'editor-skeleton/src/icons/variable'; +import { IconVariable } from '../../icons/variable'; export interface SetterItem { name: string; @@ -120,14 +120,12 @@ export default class MixedSetter extends Component<{ const { field } = this.props; let firstMatched: SetterItem | undefined; for (const setter of this.setters) { + if (setter.name === this.used) { + return setter; + } const matched = !setter.condition || setter.condition(field); - if (matched) { - if (setter.name === this.used) { - return setter; - } - if (!firstMatched) { - firstMatched = setter; - } + if (matched && !firstMatched) { + firstMatched = setter; } } return firstMatched; @@ -234,6 +232,7 @@ export default class MixedSetter extends Component<{ ); } else { // =2: 另外一个 Setter 原地展示,icon 高亮,点击弹出调用 VariableSetter.show + // FIXME! use variable placeholder setter const otherSetter = this.setters.find((item) => item.name !== 'VariableSetter')!; setterContent = this.renderCurrentSetter(otherSetter, { value: field.getMockOrValue(), @@ -243,7 +242,7 @@ export default class MixedSetter extends Component<{ , tip: tipContent, }} onClick={() => { @@ -314,7 +313,7 @@ export default class MixedSetter extends Component<{ actions: ReactNode, } | undefined; if (this.hasVariableSetter) { - // FIXME: polyfill vision variable setter logic + // polyfill vision variable setter logic const setterComponent = getSetter('VariableSetter')?.component as any; if (setterComponent && setterComponent.isPopup) { contents = this.contentsFromPolyfill(setterComponent); diff --git a/packages/editor-skeleton/src/components/mixed-setter/style.less b/packages/editor-skeleton/src/components/mixed-setter/style.less index bc4fa76a2..d277ae322 100644 --- a/packages/editor-skeleton/src/components/mixed-setter/style.less +++ b/packages/editor-skeleton/src/components/mixed-setter/style.less @@ -16,6 +16,14 @@ opacity: 1; } } + .lc-title { + cursor: pointer; + } + .variable-binded { + background: var(--color-brand, #006cff); + color: #fff!important; + border-radius: 3px; + } } .next-input,.next-date-picker { width: 100%; @@ -39,4 +47,4 @@ height: 32px; transform: none; } -} \ No newline at end of file +} diff --git a/packages/editor-skeleton/src/components/widget-views.tsx b/packages/editor-skeleton/src/components/widget-views.tsx index e097c3407..cdd646be7 100644 --- a/packages/editor-skeleton/src/components/widget-views.tsx +++ b/packages/editor-skeleton/src/components/widget-views.tsx @@ -95,7 +95,7 @@ export class TitledPanelView extends Component<{ panel: Panel }> { hidden: !panel.visible, })}> <PanelTitle panel={panel} /> - <div className="lc-pane-body">{panel.body}</div> + <div className="lc-panel-body">{panel.body}</div> </div> ); } diff --git a/packages/editor-skeleton/src/layouts/workbench.less b/packages/editor-skeleton/src/layouts/workbench.less index c4019db63..94d335a90 100644 --- a/packages/editor-skeleton/src/layouts/workbench.less +++ b/packages/editor-skeleton/src/layouts/workbench.less @@ -50,24 +50,28 @@ body { width: 100%; height: 100%; position: relative; - .pane-title { - // height: var(--pane-title-height); + &.hidden { + display: none; + } + .lc-panel-title { + height: 32px; background-color: var(--pane-title-bg-color); display: flex; align-items: center; padding: 0 15px; - .my-help-tip { + .lc-help-tip { margin-left: 4px; } } - .pane-body { + .lc-panel-body { position: absolute; - top: 0; + top: 32px; bottom: 0; left: 0; right: 0; overflow: auto; + /* .my-tabs { width: 100%; height: 100%; @@ -99,10 +103,7 @@ body { overflow: hidden; } } - } - - &.titled > .pane-body { - top: var(--pane-title-height); + */ } } .lc-panel { @@ -112,16 +113,7 @@ body { &.hidden { display: none; } - .pane-title { - height: var(--pane-title-height); - background-color: var(--pane-title-bg-color); - display: flex; - align-items: center; - padding: 0 15px; - .my-help-tip { - margin-left: 4px; - } - } + /* .my-tabs { width: 100%; height: 100%; @@ -154,6 +146,7 @@ body { overflow: hidden; } } + */ } .my-dock { diff --git a/packages/editor-skeleton/src/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts index c3072df54..c0ee2a480 100644 --- a/packages/editor-skeleton/src/transducers/addon-combine.ts +++ b/packages/editor-skeleton/src/transducers/addon-combine.ts @@ -181,7 +181,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' }, items: [ { - name: '__condition', + name: '___condition', title: { type: 'i18n', 'zh-CN': '条件显示', 'en-US': 'Condition' }, setter: 'ExpressionSetter', }, @@ -190,7 +190,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp title: { type: 'i18n', 'zh-CN': '循环', 'en-US': 'Loop' }, items: [ { - name: '__loop', + name: '___loop', title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' }, setter: { componentName: 'MixinSetter', @@ -215,7 +215,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }, }, { - name: '__loopArgs.0', + name: '___loopArgs.0', title: { type: 'i18n', 'zh-CN': '迭代变量名', 'en-US': 'Loop Item' }, setter: { componentName: 'StringSetter', @@ -225,7 +225,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }, }, { - name: '__loopArgs.1', + name: '___loopArgs.1', title: { type: 'i18n', 'zh-CN': '索引变量名', 'en-US': 'Loop Index' }, setter: { componentName: 'StringSetter', diff --git a/packages/editor-skeleton/src/widget/panel-dock.ts b/packages/editor-skeleton/src/widget/panel-dock.ts index 7b06882fe..e83bbddde 100644 --- a/packages/editor-skeleton/src/widget/panel-dock.ts +++ b/packages/editor-skeleton/src/widget/panel-dock.ts @@ -6,6 +6,7 @@ import { PanelDockConfig } from '../types'; import Panel from './panel'; import { PanelDockView, WidgetView } from '../components/widget-views'; import { IWidget } from './widget'; +import { composeTitle } from './utils'; export default class PanelDock implements IWidget { readonly isWidget = true; @@ -63,7 +64,7 @@ export default class PanelDock implements IWidget { name: this.panelName, props: { // FIXME! give default title for panel - // title: props ? composeTitle(props?.title, props?.icon, props?.description, true) : '', + title: props ? composeTitle(props?.title, props?.icon, props?.description, true) : '', ...panelProps, }, contentProps, diff --git a/packages/editor-skeleton/src/widget/panel.ts b/packages/editor-skeleton/src/widget/panel.ts index f75e69a3d..019309370 100644 --- a/packages/editor-skeleton/src/widget/panel.ts +++ b/packages/editor-skeleton/src/widget/panel.ts @@ -74,6 +74,8 @@ export default class Panel implements IWidget { ); content.forEach((item) => this.add(item)); } + // compatiable for vision, init at first + this.initBody(); // todo: process shortcut } @@ -93,6 +95,7 @@ export default class Panel implements IWidget { editor: this.skeleton.editor, config: this.config, panel: this, + pane: this, }); } } @@ -159,6 +162,18 @@ export default class Panel implements IWidget { show() { this.setActive(true); } + + + getSupportedPositions() { + return ['default']; + } + + getCurrentPosition() { + return 'default'; + } + + setPosition(position: string) { + } } export function isPanel(obj: any): obj is Panel { diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx index 8036d21c7..7b41312c8 100644 --- a/packages/react-simulator-renderer/src/renderer-view.tsx +++ b/packages/react-simulator-renderer/src/renderer-view.tsx @@ -5,6 +5,36 @@ import { SimulatorRenderer } from './renderer'; import { host } from './host'; import './renderer.less'; +// patch cloneElement avoid lost keyProps +const originCloneElement = window.React.cloneElement; +(window as any).React.cloneElement = (child: any, { _leaf, ...props}: any = {}) => { + if (child.ref && props.ref) { + const dRef = props.ref; + const cRef = child.ref; + props.ref = (x: any) => { + if (cRef) { + if (typeof cRef === 'function') { + cRef(x); + } else { + try { + cRef.current = x; + } catch (e) { } + } + } + if (dRef) { + if (typeof dRef === 'function') { + dRef(x); + } else { + try { + dRef.current = x; + } catch (e) { } + } + } + } + }; + return originCloneElement(child, props); +} + export default class SimulatorRendererView extends Component<{ renderer: SimulatorRenderer }> { render() { const { renderer } = this.props; diff --git a/packages/vision-preset/src/bundle/upgrade-metadata.ts b/packages/vision-preset/src/bundle/upgrade-metadata.ts index 0df3e1ad4..3ea38d90e 100644 --- a/packages/vision-preset/src/bundle/upgrade-metadata.ts +++ b/packages/vision-preset/src/bundle/upgrade-metadata.ts @@ -284,6 +284,17 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) } let initialFn = (slotName ? null : initial) || initialValue; + if (slotName && initialValue === true) { + initialFn = (field: any, value: any) => { + if (isJSSlot(value)) { + return value; + } + return { + type: 'JSSlot', + value: initialChildren, + }; + }; + } if (accessor && !slotName) { extraProps.getValue = (field: Field, fieldValue: any) => { @@ -294,17 +305,25 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) } } + const setterInitial = getInitialFromSetter(setter); + addInitial({ name: slotName || name, initial: (field: Field, currentValue: any) => { // FIXME! read from prototype.defaultProps const defaults = extraProps.defaultValue; - if (typeof initialFn === 'function') { - return initialFn.call(field, currentValue, defaults); + if (typeof initialFn !== 'function') { + initialFn = defaultInitial; } - return currentValue == null ? defaults : currentValue; + const v = initialFn.call(field, currentValue, defaults); + + if (setterInitial) { + return setterInitial.call(field, v, defaults); + } + + return v; }, }); @@ -343,7 +362,6 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) ]; if (allowTextInput !== false) { setters.unshift('I18nSetter'); - // FIXME: use I18nSetter } if (supportVariable) { setters.push('VariableSetter'); @@ -429,6 +447,18 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) type AddIntial = (initialItem: InitialItem) => void; +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[], addInitial: AddIntial) { const configure: any[] = []; let ignoreSlotName: any = null; diff --git a/packages/vision-preset/src/context.ts b/packages/vision-preset/src/context.ts index 39322a971..47a6917a4 100644 --- a/packages/vision-preset/src/context.ts +++ b/packages/vision-preset/src/context.ts @@ -25,7 +25,6 @@ export class VisualEngineContext { component: plugin, title: { type: 'i18n', 'zh-CN': '变量绑定', 'en-US': 'Variable Binding' }, // TODO: add logic below - // condition?: (field: any) => boolean; // initialValue?: any | ((field: any) => any); }); }