From dbc958c6bc608a4f6bb3e1f93bc249a58d3251d9 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Thu, 30 Jul 2020 23:16:54 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E5=AF=BC=E5=87=BA=E7=9A=84schema?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0componentsMap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../designer/src/document/document-model.ts | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts index 903312e29..6609e25c8 100644 --- a/packages/designer/src/document/document-model.ts +++ b/packages/designer/src/document/document-model.ts @@ -20,6 +20,15 @@ export type GetDataType = T extends undefined : any : T; + export interface ComponentMap { + componentName: string; + package: string; + version?: string; + destructuring?: boolean; + exportName?: string; + subName?: string; + } + export class DocumentModel { /** * 根节点 类型有:Page/Component/Block @@ -493,9 +502,13 @@ export class DocumentModel { } // add toData - toData() { + toData(extraComps?: string[]) { const node = this.project?.currentDocument?.export(TransformStage.Save); - return { componentsTree: [node] }; + const data = { + componentsMap: this.getComponentsMap(extraComps), + componentsTree: [node], + }; + return data; } getHistory(): History { @@ -564,6 +577,37 @@ export class DocumentModel { return this.rootNodeVisitorMap[name]; } + getComponentsMap(extraComps?: string[]) { + const componentsMap: ComponentMap[] = []; + // 组件去重 + const map: any = {}; + for (let node of this.nodesMap.values()) { + const { componentName } = node || {}; + if (!map[componentName] && node?.componentMeta?.npm?.package) { + map[componentName] = true; + componentsMap.push({ + componentName, + package: node?.componentMeta?.npm?.package, + }); + } + } + // 合并外界传入的自定义渲染的组件 + if (Array.isArray(extraComps)) { + extraComps.forEach(c => { + if (c && !map[c]) { + const m = this.getComponentMeta(c); + if (m && m.npm?.package) { + componentsMap.push({ + componentName: c, + package: m.npm?.package, + }); + } + } + }); + } + return componentsMap; + } + onNodeCreate(func: (node: Node) => void) { this.emitter.on('nodecreate', func); return () => { From bfc63db78dd3cd4325893b360d4d015ec4b83283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E7=9A=93?= Date: Wed, 12 Aug 2020 17:14:33 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86=E9=80=89=E5=8C=BA?= =?UTF-8?q?=E7=9A=84=20toolkit=20=E4=BD=8D=E7=BD=AE=E4=B8=8D=E5=AF=B9?= =?UTF-8?q?=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/builtin-simulator/bem-tools/border-selecting.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx index 4562c9ffd..7341fc056 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx @@ -66,7 +66,9 @@ class Toolbar extends Component<{ observed: OffsetObserver }> { const MARGIN = 1; const BORDER = 2; const SPACE_HEIGHT = BAR_HEIGHT + MARGIN + BORDER; + const SPACE_MINIMUM_WIDTH = 140; // magic number let style: any; + // 计算 toolbar 的上/下位置 if (observed.top > SPACE_HEIGHT) { style = { top: -SPACE_HEIGHT, @@ -83,10 +85,12 @@ class Toolbar extends Component<{ observed: OffsetObserver }> { top: Math.max(MARGIN, MARGIN - observed.top), }; } - if (observed.width < 140) { + // 计算 toolbar 的左/右位置 + if (SPACE_MINIMUM_WIDTH > observed.left + observed.width) { style.left = Math.max(-BORDER, observed.left - width - BORDER); } else { style.right = Math.max(-BORDER, observed.right - width - BORDER); + style.justifyContent = 'flex-start'; } const { node } = observed; const actions: ReactNodeArray = []; From e18a2311d89cf80b0603f44b5fa94f1373e2e474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E7=86=A0?= Date: Wed, 12 Aug 2020 22:41:06 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=E5=BF=AB=E6=8D=B7=E9=94=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/designer/src/designer/builtin-hotkey.ts | 13 ++++++++++--- packages/designer/src/document/node/node.ts | 8 ++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/designer/src/designer/builtin-hotkey.ts b/packages/designer/src/designer/builtin-hotkey.ts index a30ee0ad4..13bea87f4 100644 --- a/packages/designer/src/designer/builtin-hotkey.ts +++ b/packages/designer/src/designer/builtin-hotkey.ts @@ -77,7 +77,9 @@ hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => { const topItems = sel.getTopNodes(); // TODO: check can remove topItems.forEach((node) => { - doc.removeNode(node); + if (node.canPerformAction('remove')) { + doc.removeNode(node); + } }); sel.clear(); }); @@ -102,8 +104,13 @@ hotkey.bind(['command+c', 'ctrl+c', 'command+x', 'ctrl+x'], (e, action) => { } e.preventDefault(); - const selected = doc.selection.getTopNodes(true); - if (!selected || selected.length < 1) return; + let selected = doc.selection.getTopNodes(true); + selected = selected.filter((node) => { + return node.canPerformAction('copy'); + }) + if (!selected || selected.length < 1) { + return; + } const componentsMap = {}; const componentsTree = selected.map((item) => item.export(TransformStage.Clone)); diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 003d6f109..9ec5e8069 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -703,6 +703,14 @@ export class Node { this.document.destroyNode(this); } + /** + * 是否可执行某action + */ + canPerformAction(action: string): boolean { + const availableActions = this.componentMeta?.availableActions?.map((action) => action.name); + return availableActions.indexOf(action) >= 0; + } + // ======= compatible apis ==== isEmpty(): boolean { return this.children ? this.children.isEmpty() : true; From 0f64829826c9806979e2857b5260ecc6af04985c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E7=86=A0?= Date: Wed, 12 Aug 2020 22:44:06 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E5=BF=AB=E6=8D=B7=E9=94=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/designer/src/document/node/node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 9ec5e8069..e786a46d0 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -707,7 +707,7 @@ export class Node { * 是否可执行某action */ canPerformAction(action: string): boolean { - const availableActions = this.componentMeta?.availableActions?.map((action) => action.name); + const availableActions = this.componentMeta?.availableActions?.map((action) => action.name) || []; return availableActions.indexOf(action) >= 0; } From 6a85c43468cf2db93e1c9fea000b388af1e6a6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E7=86=A0?= Date: Thu, 13 Aug 2020 12:07:20 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=E5=8D=A1=E7=89=87=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E4=B8=8D=E5=8F=AF=E7=94=A8=E6=8B=96=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../designer/src/builtin-simulator/host.ts | 23 +++++++++++++++---- packages/designer/src/component-meta.ts | 6 ++--- packages/plugin-outline-pane/src/main.ts | 18 ++++++++++++--- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index 045a5bae5..5259a31f4 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -839,22 +839,35 @@ export class BuiltinSimulatorHost implements ISimulatorHost { + const onMoveHook = node.componentMeta?.getMetadata()?.experimental?.callbacks?.onMoveHook; + const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook() : true; + + return canMove; + }); + + if (!operationalNodes || operationalNodes.length === 0) { + return; + } this.sensing = true; this.scroller.scrolling(e); const dropContainer = this.getDropContainer(e); - const canDropIn = dropContainer.container?.componentMeta?.prototype?.options?.canDropIn; + const canDropIn = dropContainer?.container?.componentMeta?.prototype?.options?.canDropIn; + if ( !dropContainer || canDropIn === false || // too dirty - (typeof canDropIn === 'function' && - !canDropIn(e.dragObject.nodes[0])) + (typeof canDropIn === 'function' && !canDropIn(operationalNodes[0])) ) { return null; } @@ -886,7 +899,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost { + const onMoveHook = node.componentMeta?.getMetadata()?.experimental?.callbacks?.onMoveHook; + const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook() : true; + + return canMove; + }); + + if (!operationalNodes || operationalNodes.length === 0) { + return; + } + const document = tree.document; const designer = document.designer; - const { globalY, dragObject } = e; const pos = getPosFromEvent(e, this._shell); const irect = this.getInsertionRect(); const originLoc = document.dropLocation; - if (e.dragObject.type === 'node' && e.dragObject.nodes[0].getPrototype().isModal()) { + if (dragObject.type === 'node' && operationalNodes[0].getPrototype().isModal()) { return designer.createLocation({ target: document.rootNode, detail: { @@ -195,7 +207,7 @@ export class OutlineMain implements ISensor, ITreeBoard, IScrollable { let focusSlots = pos.focusSlots; let { node } = treeNode; if (isDragNodeObject(dragObject)) { - const nodes = dragObject.nodes; + const nodes = operationalNodes; let i = nodes.length; let p: any = node; while (i-- > 0) {