pict-section-flow 0.0.8 → 0.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pict-section-flow",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Pict Section Flow Diagram",
5
5
  "main": "source/Pict-Section-Flow.js",
6
6
  "scripts": {
@@ -137,6 +137,10 @@ class PictFlowCard extends libFableServiceProviderBase
137
137
  {
138
138
  tmpPort.PortType = tmpInput.PortType;
139
139
  }
140
+ if (tmpInput.DataType)
141
+ {
142
+ tmpPort.DataType = tmpInput.DataType;
143
+ }
140
144
  tmpPorts.push(tmpPort);
141
145
  }
142
146
 
@@ -155,6 +159,10 @@ class PictFlowCard extends libFableServiceProviderBase
155
159
  {
156
160
  tmpOutPort.PortType = tmpOutput.PortType;
157
161
  }
162
+ if (tmpOutput.DataType)
163
+ {
164
+ tmpOutPort.DataType = tmpOutput.DataType;
165
+ }
158
166
  tmpPorts.push(tmpOutPort);
159
167
  }
160
168
 
@@ -53,7 +53,7 @@ class FlowCardPropertiesPanelForm extends libPictFlowCardPropertiesPanel
53
53
  // Bind the node data to AppData.Record so the form descriptors
54
54
  // (which use addresses like Record.Data.SearchString) resolve against
55
55
  // the actual node object.
56
- this.pict.AppData.Record = pNodeData;
56
+ this.fable.AppData.Record = pNodeData;
57
57
 
58
58
  try
59
59
  {
@@ -60,6 +60,8 @@ class PictProviderFlowCSS extends libFableServiceProviderBase
60
60
  --pf-port-output-fill: #2ecc71;
61
61
  --pf-port-stroke: #ffffff;
62
62
  --pf-port-stroke-width: 2;
63
+ --pf-port-label-bg: rgba(255, 253, 240, 0.5);
64
+ --pf-port-label-text: #2c3e50;
63
65
 
64
66
  /* Port Type Colors */
65
67
  --pf-port-event-in-fill: #3498db;
@@ -663,6 +665,18 @@ class PictProviderFlowCSS extends libFableServiceProviderBase
663
665
  color: #8e99a4;
664
666
  font-size: 10px;
665
667
  }
668
+ /* Port summary section appended below form panels */
669
+ .pict-flow-port-summary {
670
+ margin-top: 12px;
671
+ padding-top: 8px;
672
+ border-top: 1px solid #e8eaed;
673
+ }
674
+ .pict-flow-info-panel-port.event {
675
+ border-left: 3px solid var(--pf-port-event-in-fill);
676
+ }
677
+ .pict-flow-info-panel-port.value {
678
+ border-left: 3px solid var(--pf-port-value-fill);
679
+ }
666
680
  `;
667
681
  }
668
682
 
@@ -265,7 +265,7 @@ class PictProviderFlowGeometry extends libFableServiceProviderBase
265
265
  // Need: lastPortY + badgeHalfHeight <= H - bottomPad
266
266
  // Solving for H:
267
267
  // H >= titleBar + bottomPad + (minSpacing * count + badgeHalfHeight) / (1 - zone.start)
268
- let tmpRequired = pTitleBarHeight + tmpBottomPad + (tmpMinSpacing * tmpCount + tmpBadgeHalfHeight) / (1 - tmpZone.start);
268
+ let tmpRequired = pTitleBarHeight + tmpBottomPad + (tmpMinSpacing * tmpCount + tmpBadgeHalfHeight) / (tmpZone.end - tmpZone.start);
269
269
 
270
270
  if (tmpRequired > tmpMinHeight)
271
271
  {
@@ -436,7 +436,7 @@ class PictViewFlowNode extends libPictView
436
436
  tmpBgRect.setAttribute('y', String(tmpBadgeY));
437
437
  tmpBgRect.setAttribute('width', String(tmpBadgeWidth));
438
438
  tmpBgRect.setAttribute('height', String(tmpBadgeHeight));
439
- tmpBgRect.setAttribute('fill', 'rgba(255, 253, 240, 0.5)');
439
+ tmpBgRect.setAttribute('fill', 'var(--pf-port-label-bg, rgba(255, 253, 240, 0.5))');
440
440
  pGroup.appendChild(tmpBgRect);
441
441
 
442
442
  // 3-sided border path (open on the edge-facing side)
@@ -461,7 +461,7 @@ class PictViewFlowNode extends libPictView
461
461
  // Text label — appended after circle for z-order
462
462
  tmpLabelElement = this._FlowView._SVGHelperProvider.createSVGElement('text');
463
463
  tmpLabelElement.setAttribute('class', 'pict-flow-port-label');
464
- tmpLabelElement.setAttribute('fill', '#2c3e50');
464
+ tmpLabelElement.setAttribute('fill', 'var(--pf-port-label-text, #2c3e50)');
465
465
  tmpLabelElement.textContent = tmpPort.Label;
466
466
  tmpLabelElement.setAttribute('x', String(tmpTextX));
467
467
  tmpLabelElement.setAttribute('y', String(tmpBadgeY + tmpBadgeHeight / 2));
@@ -56,6 +56,22 @@ const _DefaultConfiguration =
56
56
  Hash: 'Flow-InfoPanel-Port-Constraint',
57
57
  Template: ' <span class="pict-flow-info-panel-port-constraint">{~D:Record.ConstraintText~}</span>'
58
58
  },
59
+ {
60
+ Hash: 'Flow-InfoPanel-Section-Generic',
61
+ Template: '<div class="pict-flow-info-panel-section"><div class="pict-flow-info-panel-section-title">{~D:Record.SectionTitle~}</div>{~D:Record.PortsContent~}</div>'
62
+ },
63
+ {
64
+ Hash: 'Flow-InfoPanel-Port-Event',
65
+ Template: '<div class="pict-flow-info-panel-port event">{~D:Record.Label~}</div>'
66
+ },
67
+ {
68
+ Hash: 'Flow-InfoPanel-Port-Value',
69
+ Template: '<div class="pict-flow-info-panel-port value">{~D:Record.Label~}{~D:Record.DataType~}</div>'
70
+ },
71
+ {
72
+ Hash: 'Flow-InfoPanel-Port-DataType',
73
+ Template: ' <span class="pict-flow-info-panel-port-constraint">{~D:Record.DataTypeText~}</span>'
74
+ },
59
75
  {
60
76
  Hash: 'Flow-NodeProps-Editor',
61
77
  Template: '<div class="pict-flow-node-props-fields"><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Title</label><input type="text" class="pict-flow-node-props-input" data-prop="Title" value="{~D:Record.Title~}" /></div><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Width</label><input type="number" class="pict-flow-node-props-input" data-prop="Width" value="{~D:Record.Width~}" min="60" step="10" /></div><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Height</label><input type="number" class="pict-flow-node-props-input" data-prop="Height" value="{~D:Record.Height~}" min="40" step="10" /></div><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Body Fill</label><input type="color" class="pict-flow-node-props-input pict-flow-node-props-color" data-prop="Style.BodyFill" value="{~D:Record.BodyFillValue~}" /></div><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Body Stroke</label><input type="color" class="pict-flow-node-props-input pict-flow-node-props-color" data-prop="Style.BodyStroke" value="{~D:Record.BodyStrokeValue~}" /></div><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Stroke Width</label><input type="number" class="pict-flow-node-props-input" data-prop="Style.BodyStrokeWidth" value="{~D:Record.BodyStrokeWidthValue~}" min="0" max="10" step="0.5" /></div><div class="pict-flow-node-props-field"><label class="pict-flow-node-props-label">Title Bar</label><input type="color" class="pict-flow-node-props-input pict-flow-node-props-color" data-prop="Style.TitleBarColor" value="{~D:Record.TitleBarColorValue~}" /></div></div>'
@@ -262,6 +278,11 @@ class PictViewFlowPropertiesPanel extends libPictView
262
278
  {
263
279
  tmpInstance.render(pBodyContainer, tmpNodeData);
264
280
  }
281
+
282
+ // After the form renders, append port summary sections showing
283
+ // event inputs, event outputs, and state outputs.
284
+ // SettingsInputs are already visible as form fields above.
285
+ this._renderPortSummary(pBodyContainer, tmpNodeTypeConfig);
265
286
  }
266
287
 
267
288
  /**
@@ -362,6 +383,107 @@ class PictViewFlowPropertiesPanel extends libPictView
362
383
  pContainer.innerHTML = this.pict.parseTemplateByHash('Flow-InfoPanel-Wrapper', { PanelContent: tmpContentParts.join('') });
363
384
  }
364
385
 
386
+ /**
387
+ * Render port summary sections below the form panel content.
388
+ * Shows event inputs, event outputs, and state outputs — the ports
389
+ * that the form does not cover (since the form only shows SettingsInputs).
390
+ *
391
+ * @param {HTMLDivElement} pContainer
392
+ * @param {Object} pNodeTypeConfig
393
+ */
394
+ _renderPortSummary(pContainer, pNodeTypeConfig)
395
+ {
396
+ let tmpPorts = pNodeTypeConfig.DefaultPorts || [];
397
+ if (tmpPorts.length === 0) return;
398
+
399
+ // Categorize ports by type (settings are already shown as form fields)
400
+ let tmpEventInputs = [];
401
+ let tmpEventOutputs = [];
402
+ let tmpStateOutputs = [];
403
+
404
+ for (let i = 0; i < tmpPorts.length; i++)
405
+ {
406
+ let tmpPort = tmpPorts[i];
407
+ let tmpPortType = tmpPort.PortType || '';
408
+
409
+ if (tmpPortType === 'event-in')
410
+ {
411
+ tmpEventInputs.push(tmpPort);
412
+ }
413
+ else if (tmpPortType === 'event-out' || tmpPortType === 'error')
414
+ {
415
+ tmpEventOutputs.push(tmpPort);
416
+ }
417
+ else if (tmpPortType === 'value')
418
+ {
419
+ tmpStateOutputs.push(tmpPort);
420
+ }
421
+ }
422
+
423
+ // Only render if there are non-settings ports to show
424
+ if (tmpEventInputs.length === 0 && tmpEventOutputs.length === 0 && tmpStateOutputs.length === 0)
425
+ {
426
+ return;
427
+ }
428
+
429
+ let tmpSummaryParts = [];
430
+
431
+ // Event Inputs
432
+ if (tmpEventInputs.length > 0)
433
+ {
434
+ let tmpPortsContent = '';
435
+ for (let i = 0; i < tmpEventInputs.length; i++)
436
+ {
437
+ tmpPortsContent += this.pict.parseTemplateByHash('Flow-InfoPanel-Port-Event', { Label: tmpEventInputs[i].Label || tmpEventInputs[i].Name || 'Event In' });
438
+ }
439
+ tmpSummaryParts.push(this.pict.parseTemplateByHash('Flow-InfoPanel-Section-Generic', { SectionTitle: 'Event Inputs', PortsContent: tmpPortsContent }));
440
+ }
441
+
442
+ // Event Outputs
443
+ if (tmpEventOutputs.length > 0)
444
+ {
445
+ let tmpPortsContent = '';
446
+ for (let i = 0; i < tmpEventOutputs.length; i++)
447
+ {
448
+ let tmpPort = tmpEventOutputs[i];
449
+ let tmpLabel = tmpPort.Label || tmpPort.Name || 'Event Out';
450
+ if (tmpPort.PortType === 'error')
451
+ {
452
+ tmpLabel += ' ⚠';
453
+ }
454
+ tmpPortsContent += this.pict.parseTemplateByHash('Flow-InfoPanel-Port-Event', { Label: tmpLabel });
455
+ }
456
+ tmpSummaryParts.push(this.pict.parseTemplateByHash('Flow-InfoPanel-Section-Generic', { SectionTitle: 'Event Outputs', PortsContent: tmpPortsContent }));
457
+ }
458
+
459
+ // State Outputs
460
+ if (tmpStateOutputs.length > 0)
461
+ {
462
+ let tmpPortsContent = '';
463
+ for (let i = 0; i < tmpStateOutputs.length; i++)
464
+ {
465
+ let tmpPort = tmpStateOutputs[i];
466
+ let tmpLabel = tmpPort.Label || tmpPort.Name || 'Output';
467
+ let tmpDataType = '';
468
+ if (tmpPort.DataType)
469
+ {
470
+ tmpDataType = this.pict.parseTemplateByHash('Flow-InfoPanel-Port-DataType', { DataTypeText: tmpPort.DataType });
471
+ }
472
+ tmpPortsContent += this.pict.parseTemplateByHash('Flow-InfoPanel-Port-Value', { Label: tmpLabel, DataType: tmpDataType });
473
+ }
474
+ tmpSummaryParts.push(this.pict.parseTemplateByHash('Flow-InfoPanel-Section-Generic', { SectionTitle: 'State Outputs', PortsContent: tmpPortsContent }));
475
+ }
476
+
477
+ if (tmpSummaryParts.length > 0)
478
+ {
479
+ // Create a wrapper div for the port summary and append it to the container
480
+ let tmpSummaryDiv = document.createElement('div');
481
+ tmpSummaryDiv.className = 'pict-flow-info-panel pict-flow-port-summary';
482
+ tmpSummaryDiv.innerHTML = tmpSummaryParts.join('');
483
+ pContainer.appendChild(tmpSummaryDiv);
484
+ }
485
+ }
486
+
365
487
  /**
366
488
  * Build the constraint markup for a port using configuration templates.
367
489
  *