pict-section-flow 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/Theme_Integration.md +150 -0
- package/docs/_sidebar.md +1 -0
- package/package.json +8 -8
- package/source/providers/PictProvider-Flow-CSS.js +197 -47
- package/source/providers/PictProvider-Flow-ConnectorShapes.js +9 -5
- package/source/providers/PictProvider-Flow-NodeTypes.js +10 -0
- package/source/providers/PictProvider-Flow-PanelChrome.js +7 -17
- package/source/services/PictService-Flow-InteractionManager.js +39 -42
- package/source/services/PictService-Flow-PortRenderer.js +10 -24
- package/source/views/PictView-Flow-FloatingToolbar.js +69 -61
- package/source/views/PictView-Flow-Node.js +19 -6
- package/source/views/PictView-Flow-PropertiesPanel.js +46 -53
- package/source/views/PictView-Flow-Toolbar.js +664 -789
- package/source/views/PictView-Flow.js +183 -2
|
@@ -85,10 +85,13 @@ const _DefaultConfiguration =
|
|
|
85
85
|
[
|
|
86
86
|
{
|
|
87
87
|
Hash: 'Flow-PanelChrome-Template',
|
|
88
|
-
Template: /*html*/`<div class="pict-flow-panel" xmlns="http://www.w3.org/1999/xhtml"><div class="pict-flow-panel-titlebar" data-element-type="panel-titlebar" data-panel-hash="{~D:Record.Hash~}"><span class="pict-flow-panel-title-text">{~D:Record.Title~}</span><span class="pict-flow-panel-close-btn" data-element-type="panel-close" data-panel-hash="{~D:Record.Hash~}"><span class="pict-flow-panel-close-icon"></span></span></div><div class="pict-flow-panel-content" data-panel-hash="{~D:Record.Hash~}"><div class="pict-flow-panel-tab-pane active" data-tab="properties" data-panel-hash="{~D:Record.Hash~}"></div><div class="pict-flow-panel-tab-pane" data-tab="help" data-panel-hash="{~D:Record.Hash~}" style="display:none;"></div><div class="pict-flow-panel-tab-pane" data-tab="appearance" data-panel-hash="{~D:Record.Hash~}" style="display:none;"></div></div><div class="pict-flow-panel-resize-handle" data-element-type="panel-resize" data-panel-hash="{~D:Record.Hash~}"></div><div class="pict-flow-panel-tabbar" data-panel-hash="{~D:Record.Hash~}"><div class="pict-flow-panel-tab active" data-tab-target="properties" data-panel-hash="{~D:Record.Hash~}">Properties</div><div class="pict-flow-panel-tab" data-tab-target="help" data-panel-hash="{~D:Record.Hash~}" style="display:none;">Help</div><div class="pict-flow-panel-tab" data-tab-target="appearance" data-panel-hash="{~D:Record.Hash~}">Appearance</div></div></div>`
|
|
88
|
+
Template: /*html*/`<div class="pict-flow-panel" xmlns="http://www.w3.org/1999/xhtml"><div class="pict-flow-panel-titlebar" data-element-type="panel-titlebar" data-panel-hash="{~D:Record.Hash~}"><span class="pict-flow-panel-title-text">{~D:Record.Title~}</span><span class="pict-flow-panel-close-btn" data-element-type="panel-close" data-panel-hash="{~D:Record.Hash~}"><span class="pict-flow-panel-close-icon"></span></span></div><div class="pict-flow-panel-content" data-panel-hash="{~D:Record.Hash~}" onpointerdown="event.stopPropagation()" onwheel="event.stopPropagation()"><div class="pict-flow-panel-tab-pane active" data-tab="properties" data-panel-hash="{~D:Record.Hash~}"></div><div class="pict-flow-panel-tab-pane" data-tab="help" data-panel-hash="{~D:Record.Hash~}" style="display:none;"></div><div class="pict-flow-panel-tab-pane" data-tab="appearance" data-panel-hash="{~D:Record.Hash~}" style="display:none;"></div></div><div class="pict-flow-panel-resize-handle" data-element-type="panel-resize" data-panel-hash="{~D:Record.Hash~}"></div><div class="pict-flow-panel-tabbar" data-panel-hash="{~D:Record.Hash~}" onpointerdown="event.stopPropagation()" onwheel="event.stopPropagation()"><div class="pict-flow-panel-tab active" data-tab-target="properties" data-panel-hash="{~D:Record.Hash~}" onclick="_Pict.views['{~D:Record.FlowViewIdentifier~}']._handlePanelTabClick(this, event)">Properties</div><div class="pict-flow-panel-tab" data-tab-target="help" data-panel-hash="{~D:Record.Hash~}" style="display:none;" onclick="_Pict.views['{~D:Record.FlowViewIdentifier~}']._handlePanelTabClick(this, event)">Help</div><div class="pict-flow-panel-tab" data-tab-target="appearance" data-panel-hash="{~D:Record.Hash~}" onclick="_Pict.views['{~D:Record.FlowViewIdentifier~}']._handlePanelTabClick(this, event)">Appearance</div></div></div>`
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
Hash: 'Flow-Container-Template',
|
|
92
|
+
// Inline pointer/wheel/contextmenu handlers route to the
|
|
93
|
+
// InteractionManager via the FlowView. Keyboard events stay
|
|
94
|
+
// document-level (no element-level inline equivalent).
|
|
92
95
|
Template: /*html*/`
|
|
93
96
|
<div class="pict-flow-container" id="Flow-Wrapper-{~D:Record.ViewIdentifier~}">
|
|
94
97
|
<div id="Flow-Toolbar-{~D:Record.ViewIdentifier~}"></div>
|
|
@@ -96,7 +99,13 @@ const _DefaultConfiguration =
|
|
|
96
99
|
<div class="pict-flow-svg-container" id="Flow-SVG-Container-{~D:Record.ViewIdentifier~}">
|
|
97
100
|
<svg class="pict-flow-svg"
|
|
98
101
|
id="Flow-SVG-{~D:Record.ViewIdentifier~}"
|
|
99
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
102
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
103
|
+
onpointerdown="_Pict.views['{~D:Record.ViewIdentifier~}']._handleSVGPointerDown(event)"
|
|
104
|
+
onpointermove="_Pict.views['{~D:Record.ViewIdentifier~}']._handleSVGPointerMove(event)"
|
|
105
|
+
onpointerup="_Pict.views['{~D:Record.ViewIdentifier~}']._handleSVGPointerUp(event)"
|
|
106
|
+
onpointerleave="_Pict.views['{~D:Record.ViewIdentifier~}']._handleSVGPointerUp(event)"
|
|
107
|
+
onwheel="_Pict.views['{~D:Record.ViewIdentifier~}']._handleSVGWheel(event)"
|
|
108
|
+
oncontextmenu="_Pict.views['{~D:Record.ViewIdentifier~}']._handleSVGContextMenu(event)">
|
|
100
109
|
<defs>
|
|
101
110
|
<pattern id="flow-grid-{~D:Record.ViewIdentifier~}"
|
|
102
111
|
width="20" height="20" patternUnits="userSpaceOnUse">
|
|
@@ -351,9 +360,65 @@ class PictViewFlow extends libPictView
|
|
|
351
360
|
// Instantiate all remaining services (skips Theme + Noise since already set)
|
|
352
361
|
this._instantiateServices();
|
|
353
362
|
|
|
363
|
+
// Subscribe to the host application's pict-provider-theme so the flow
|
|
364
|
+
// editor's marker arrowhead colors and shape overrides update when the
|
|
365
|
+
// host swaps light/dark or palette themes. CSS variables (--theme-*)
|
|
366
|
+
// re-resolve automatically — only the SVG <marker> defs (which inline
|
|
367
|
+
// fill colors at build time) and ConnectorShapesProvider state need a
|
|
368
|
+
// manual refresh.
|
|
369
|
+
this._subscribeToHostTheme();
|
|
370
|
+
|
|
354
371
|
return super.onBeforeInitialize();
|
|
355
372
|
}
|
|
356
373
|
|
|
374
|
+
/**
|
|
375
|
+
* If the host application has registered pict-provider-theme, subscribe
|
|
376
|
+
* to its onApply hook so we can refresh anything that doesn't pick up
|
|
377
|
+
* the new --theme-* CSS variables automatically (SVG marker fills,
|
|
378
|
+
* connector shape overrides). No-op when no host theme provider is
|
|
379
|
+
* available — the flow editor still functions with its built-in themes.
|
|
380
|
+
*/
|
|
381
|
+
_subscribeToHostTheme()
|
|
382
|
+
{
|
|
383
|
+
let tmpHostTheme = this._resolveHostThemeProvider();
|
|
384
|
+
if (!tmpHostTheme || typeof tmpHostTheme.onApply !== 'function') return;
|
|
385
|
+
|
|
386
|
+
this._HostThemeUnsubscribe = tmpHostTheme.onApply(() =>
|
|
387
|
+
{
|
|
388
|
+
if (this._CSSProvider) this._CSSProvider.registerCSS();
|
|
389
|
+
this._reinjectMarkerDefs();
|
|
390
|
+
if (this.initialRenderComplete) this.renderFlow();
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Locate the host's pict-provider-theme instance. It is normally
|
|
396
|
+
* registered under a stable service hash by the host app; we check
|
|
397
|
+
* common locations so consumers don't have to wire it manually.
|
|
398
|
+
* @returns {Object|null}
|
|
399
|
+
*/
|
|
400
|
+
_resolveHostThemeProvider()
|
|
401
|
+
{
|
|
402
|
+
let tmpPict = this.pict;
|
|
403
|
+
if (!tmpPict) return null;
|
|
404
|
+
if (tmpPict.providers)
|
|
405
|
+
{
|
|
406
|
+
let tmpKeys = Object.keys(tmpPict.providers);
|
|
407
|
+
for (let i = 0; i < tmpKeys.length; i++)
|
|
408
|
+
{
|
|
409
|
+
let tmpProvider = tmpPict.providers[tmpKeys[i]];
|
|
410
|
+
if (tmpProvider
|
|
411
|
+
&& typeof tmpProvider.onApply === 'function'
|
|
412
|
+
&& typeof tmpProvider.applyTheme === 'function'
|
|
413
|
+
&& typeof tmpProvider.listThemes === 'function')
|
|
414
|
+
{
|
|
415
|
+
return tmpProvider;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
|
|
357
422
|
onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
|
|
358
423
|
{
|
|
359
424
|
if (!this.initialRenderComplete)
|
|
@@ -1148,6 +1213,122 @@ class PictViewFlow extends libPictView
|
|
|
1148
1213
|
{
|
|
1149
1214
|
return this._PanelManager.updatePanelPosition(pPanelHash, pX, pY);
|
|
1150
1215
|
}
|
|
1216
|
+
|
|
1217
|
+
// ── Inline-handler bridges (called from template onclick/oninput attrs)
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Handle a click on a panel tab button. Stops propagation so the
|
|
1221
|
+
* underlying SVG doesn't see it, then delegates to the properties
|
|
1222
|
+
* panel view for the actual visibility toggle.
|
|
1223
|
+
*
|
|
1224
|
+
* @param {Element} pTabElement
|
|
1225
|
+
* @param {Event} pEvent
|
|
1226
|
+
*/
|
|
1227
|
+
_handlePanelTabClick(pTabElement, pEvent)
|
|
1228
|
+
{
|
|
1229
|
+
if (pEvent && typeof pEvent.stopPropagation === 'function')
|
|
1230
|
+
{
|
|
1231
|
+
pEvent.stopPropagation();
|
|
1232
|
+
}
|
|
1233
|
+
if (this._PropertiesPanelView)
|
|
1234
|
+
{
|
|
1235
|
+
this._PropertiesPanelView.switchPanelTab(pTabElement);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Apply a node property change driven from the appearance editor's
|
|
1241
|
+
* inline `oninput` handler. Stops propagation, then delegates to the
|
|
1242
|
+
* properties panel view.
|
|
1243
|
+
*
|
|
1244
|
+
* @param {string} pNodeHash
|
|
1245
|
+
* @param {string} pPropPath
|
|
1246
|
+
* @param {string} pValue
|
|
1247
|
+
* @param {string} pInputType - 'text' | 'number' | 'color'
|
|
1248
|
+
* @param {Event} [pEvent]
|
|
1249
|
+
*/
|
|
1250
|
+
_applyNodePropChange(pNodeHash, pPropPath, pValue, pInputType, pEvent)
|
|
1251
|
+
{
|
|
1252
|
+
if (pEvent && typeof pEvent.stopPropagation === 'function')
|
|
1253
|
+
{
|
|
1254
|
+
pEvent.stopPropagation();
|
|
1255
|
+
}
|
|
1256
|
+
if (this._PropertiesPanelView)
|
|
1257
|
+
{
|
|
1258
|
+
this._PropertiesPanelView._applyNodePropChange(pNodeHash, pPropPath, pValue, pInputType);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* Inline-handler bridge — light up port-hint paths matching the given
|
|
1264
|
+
* port (and optionally node) hash. Called from inline `onmouseenter`
|
|
1265
|
+
* on port badges; see PictService-Flow-PortRenderer._wirePortHintHover.
|
|
1266
|
+
*
|
|
1267
|
+
* @param {string|null} pPortHash
|
|
1268
|
+
* @param {string|null} pNodeHash
|
|
1269
|
+
*/
|
|
1270
|
+
_activatePortHints(pPortHash, pNodeHash)
|
|
1271
|
+
{
|
|
1272
|
+
this._togglePortHints(pPortHash, pNodeHash, true);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* Inline-handler bridge — clear port-hint highlights.
|
|
1277
|
+
*
|
|
1278
|
+
* @param {string|null} pPortHash
|
|
1279
|
+
* @param {string|null} pNodeHash
|
|
1280
|
+
*/
|
|
1281
|
+
_deactivatePortHints(pPortHash, pNodeHash)
|
|
1282
|
+
{
|
|
1283
|
+
this._togglePortHints(pPortHash, pNodeHash, false);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
_togglePortHints(pPortHash, pNodeHash, pActive)
|
|
1287
|
+
{
|
|
1288
|
+
let tmpScope = this._SVGElement || document;
|
|
1289
|
+
let tmpSelector = pPortHash
|
|
1290
|
+
? '.pict-flow-port-hint[data-port-hash="' + pPortHash + '"]'
|
|
1291
|
+
: '.pict-flow-port-hint[data-node-hash="' + pNodeHash + '"]';
|
|
1292
|
+
let tmpHints = tmpScope.querySelectorAll(tmpSelector);
|
|
1293
|
+
for (let i = 0; i < tmpHints.length; i++)
|
|
1294
|
+
{
|
|
1295
|
+
if (pActive)
|
|
1296
|
+
{
|
|
1297
|
+
tmpHints[i].setAttribute('data-active', 'true');
|
|
1298
|
+
}
|
|
1299
|
+
else
|
|
1300
|
+
{
|
|
1301
|
+
tmpHints[i].removeAttribute('data-active');
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// ── SVG inline pointer/wheel bridges ─────────────────────────────────
|
|
1307
|
+
|
|
1308
|
+
_handleSVGPointerDown(pEvent)
|
|
1309
|
+
{
|
|
1310
|
+
if (this._InteractionManager) this._InteractionManager._onPointerDown(pEvent);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
_handleSVGPointerMove(pEvent)
|
|
1314
|
+
{
|
|
1315
|
+
if (this._InteractionManager) this._InteractionManager._onPointerMove(pEvent);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
_handleSVGPointerUp(pEvent)
|
|
1319
|
+
{
|
|
1320
|
+
if (this._InteractionManager) this._InteractionManager._onPointerUp(pEvent);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
_handleSVGWheel(pEvent)
|
|
1324
|
+
{
|
|
1325
|
+
if (this._InteractionManager) this._InteractionManager._onWheel(pEvent);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
_handleSVGContextMenu(pEvent)
|
|
1329
|
+
{
|
|
1330
|
+
if (this._InteractionManager) this._InteractionManager.handleContextMenu(pEvent);
|
|
1331
|
+
}
|
|
1151
1332
|
}
|
|
1152
1333
|
|
|
1153
1334
|
module.exports = PictViewFlow;
|