From 6bc3c1e9b8d9a23dc766c69872c31556935b3698 Mon Sep 17 00:00:00 2001 From: STEINNI Date: Wed, 25 Feb 2026 20:25:53 +0000 Subject: [PATCH] graflow: subflow polishing --- app/assets/html/bzGraflow/nodesEIC.html | 3 +- app/assets/html/bzGraflow/nodesTest1.html | 14 +++++++++- app/assets/html/test.html | 3 ++ app/assets/json/bzGraflow/testFlow1.json | 28 ++++++++++--------- app/assets/json/bzGraflow/testFlowEic.json | 17 +++++++++++- app/thirdparty/buildoz/bzGraflow.js | 32 ++++++++++++++++------ 6 files changed, 71 insertions(+), 26 deletions(-) diff --git a/app/assets/html/bzGraflow/nodesEIC.html b/app/assets/html/bzGraflow/nodesEIC.html index 0e6f91a..ea17fc3 100644 --- a/app/assets/html/bzGraflow/nodesEIC.html +++ b/app/assets/html/bzGraflow/nodesEIC.html @@ -61,8 +61,7 @@ align-items: center; justify-content: center; } - .bzgf-node[data-nodetype="refnodein"] .body{ background: #0F0; } - .bzgf-node[data-nodetype="refnodeout"] .body{ background: #FF0; } + .bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] .body{ background: var(--eicui-base-color-grey-25); } .bzgf-wire{ stroke: var(--eicui-base-color-info); stroke-width: 4px; stroke-dasharray: 10,5; } diff --git a/app/assets/html/bzGraflow/nodesTest1.html b/app/assets/html/bzGraflow/nodesTest1.html index be1d2aa..07533b6 100644 --- a/app/assets/html/bzGraflow/nodesTest1.html +++ b/app/assets/html/bzGraflow/nodesTest1.html @@ -96,8 +96,18 @@ .bzgf-node[data-nodetype="input"] .title, .bzgf-node[data-nodetype="console"] .title{ background: #555; } - .bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] body{ + .bzgf-node[data-nodetype="refnodein"], .bzgf-node[data-nodetype="refnodeout"] { + width:3em; + height:3em; + padding: 2px; + } + .bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] .body{ border-radius: 50%; + width: 3em; + height: 3em; + display: flex; + align-items: center; + justify-content: center; } .bzgf-node[data-nodetype="refnodein"] .body{ background: #0F0; } .bzgf-node[data-nodetype="refnodeout"] .body{ background: #FF0; } @@ -181,11 +191,13 @@ \ No newline at end of file diff --git a/app/assets/html/test.html b/app/assets/html/test.html index a4cd4e6..096f89f 100644 --- a/app/assets/html/test.html +++ b/app/assets/html/test.html @@ -58,6 +58,9 @@ grflw1.addEventListener('subflowLoaded', (evt) => { evt.target.querySelector('.demooptions').style.display = 'none'; } ) + grflw1.addEventListener('subflowExited', + (evt) => { evt.target.querySelector('.demooptions').style.display = 'block'; } + ) document.querySelector('[data-trigger="onAutoplace1H"]').addEventListener('click', (evt) => { grflw1.autoPlace('horizontal', 80, 30, 1000, document.querySelector('[data-id="compunet"]').value) } ) diff --git a/app/assets/json/bzGraflow/testFlow1.json b/app/assets/json/bzGraflow/testFlow1.json index 8e4e638..eb8c1fe 100644 --- a/app/assets/json/bzGraflow/testFlow1.json +++ b/app/assets/json/bzGraflow/testFlow1.json @@ -7,19 +7,21 @@ "coords": { "x": 220, "y": 120} }, { "nodeType": "inc", - "subflow": "/app/assets/json/bzGraflow/testFlowEic.json", - "portLinks": [ - { "refNodeType": "refnodein", "refnodePort": "out1", - "parentPort": "in1", - "subflowNode":"aze2", "subflowPort": "in1", - "direction": "in" - }, - { "refNodeType": "refnodeout", "refnodePort": "in1", - "parentPort": "out1", - "subflowNode":"aze5", "subflowPort": "out1", - "direction": "out" - } - ], + "subflow": { + "url": "/app/assets/json/bzGraflow/testFlowEic.json", + "portLinks": [ + { "refNodeType": "refnodein", "refnodePort": "out1", + "parentPort": "in1", + "subflowNode":"aze2", "subflowPort": "in1", + "direction": "in" + }, + { "refNodeType": "refnodeout", "refnodePort": "in1", + "parentPort": "out1", + "subflowNode":"aze5", "subflowPort": "out1", + "direction": "out" + } + ] + }, "id": "aze2", "coords": { "x": 220, "y": 10} }, diff --git a/app/assets/json/bzGraflow/testFlowEic.json b/app/assets/json/bzGraflow/testFlowEic.json index d80d441..3f5058c 100644 --- a/app/assets/json/bzGraflow/testFlowEic.json +++ b/app/assets/json/bzGraflow/testFlowEic.json @@ -27,7 +27,22 @@ "title": "Data mapping", "subtitle": "Associate content variables with attendees data" }, - "data": { "a": "a3", "b":"b3"} + "data": { "a": "a3", "b":"b3"}, + "subflow": { + "url": "/app/assets/json/bzGraflow/testFlowICMP.json", + "portLinks": [ + { "refNodeType": "refnodein", "refnodePort": "out1", + "parentPort": "in1", + "subflowNode":"cid", "subflowPort": "in3", + "direction": "in" + }, + { "refNodeType": "refnodeout", "refnodePort": "in1", + "parentPort": "out1", + "subflowNode":"signature", "subflowPort": "out2", + "direction": "out" + } + ] + } }, { "nodeType": "eicBasic", "id": "aze4", diff --git a/app/thirdparty/buildoz/bzGraflow.js b/app/thirdparty/buildoz/bzGraflow.js index 72f64a9..4c634f7 100644 --- a/app/thirdparty/buildoz/bzGraflow.js +++ b/app/thirdparty/buildoz/bzGraflow.js @@ -202,30 +202,25 @@ class BZgraflow extends Buildoz{ const parentBB = this.getBoundingClientRect() const flowNode = this.flow?.nodes?.find(n => n.id === id) - const flowUrl = flowNode?.subflow + const flowUrl = flowNode.subflow.url const childEl = document.createElement('bz-graflow') childEl.setAttribute('flow', flowUrl) childEl.setAttribute('tension', this.getBZAttribute('tension') || '60') // Remember which node we "came from" so exitSubflow() can animate back to it. childEl.dataset.enterNodeId = id - // Match the clicked node's border so the transition feels like we're "expanding" it. - const nodeStyle = getComputedStyle(nodeEl) - childEl.style.border = nodeStyle.border - childEl.style.borderRadius = nodeStyle.borderRadius - childEl.style.backgroundColor = nodeStyle.backgroundColor const btnExitSubflow = document.createElement('button') btnExitSubflow.classList.add('bzgf-zoom-out') this.addIcon(btnExitSubflow, 'zoomout') btnExitSubflow.addEventListener('click', () => { this.exitSubflow(childEl) }) - childEl.appendChild(btnExitSubflow) // Put the child in the exact same viewport rect as the parent (fixed overlay) this.invade(this, childEl) + childEl.hostContainer.appendChild(btnExitSubflow) childEl.addEventListener('flowLoaded', (e) => { - for(const portLink of flowNode.portLinks){ + for(const portLink of flowNode.subflow.portLinks){ const nid = crypto.randomUUID() childEl.addNode({ "nodeType": portLink.refNodeType, @@ -280,6 +275,12 @@ class BZgraflow extends Buildoz{ childEl.addEventListener('transitionend', (e) => { if(e.propertyName !== 'transform') return this.hostContainer.style.visibility = 'hidden' + // Important for nested subflows: + // A non-'none' transform on this element creates a containing block, which would make + // any nested `position:fixed` subflow overlay position relative to this element instead + // of the viewport (showing up as an extra offset like 8px). + childEl.style.transform = 'none' + childEl.style.willChange = '' this.dispatchEvent(new CustomEvent('subflowLoaded', { detail: { flowUrl }, bubbles: true, @@ -330,7 +331,14 @@ class BZgraflow extends Buildoz{ this.hostContainer.style.opacity = '0' this.hostContainer.style.transition = `opacity ${durMs}ms ease-in-out` - // Ensure child animates (it should already have the transform transition set) + // Ensure child animates (it may have had transform cleared after enter) + childEl.style.transformOrigin = 'top left' + childEl.style.willChange = 'transform' + childEl.style.transform = 'translate(var(--tx, 0px), var(--ty, 0px)) scale(var(--sx, 1), var(--sy, 1))' + childEl.style.setProperty('--tx', '0px') + childEl.style.setProperty('--ty', '0px') + childEl.style.setProperty('--sx', 1) + childEl.style.setProperty('--sy', 1) childEl.style.transition = `transform ${durMs}ms ease-in-out` childEl.getBoundingClientRect() // flush @@ -350,6 +358,12 @@ class BZgraflow extends Buildoz{ // Cleanup: ensure parent is fully visible and no longer hidden this.hostContainer.style.opacity = '1' this.hostContainer.style.visibility = 'visible' + childEl.style.willChange = '' + this.dispatchEvent(new CustomEvent('subflowExited', { + detail: { }, + bubbles: true, + composed: true, + })) }, { once:true }) }