pict-section-flow 0.0.10 → 0.0.13

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.
Files changed (88) hide show
  1. package/.claude/launch.json +1 -1
  2. package/README.md +176 -0
  3. package/docs/.nojekyll +0 -0
  4. package/docs/Architecture.md +303 -0
  5. package/docs/Custom-Styling.md +275 -0
  6. package/docs/Data_Model.md +158 -0
  7. package/docs/Event_System.md +156 -0
  8. package/docs/Getting_Started.md +237 -0
  9. package/docs/Implementation_Reference.md +528 -0
  10. package/docs/Layout_Persistence.md +117 -0
  11. package/docs/README.md +115 -52
  12. package/docs/_cover.md +11 -0
  13. package/docs/_sidebar.md +52 -0
  14. package/docs/_topbar.md +8 -0
  15. package/docs/api/PictFlowCard.md +216 -0
  16. package/docs/api/PictFlowCardPropertiesPanel.md +235 -0
  17. package/docs/api/addConnection.md +101 -0
  18. package/docs/api/addNode.md +137 -0
  19. package/docs/api/autoLayout.md +77 -0
  20. package/docs/api/getFlowData.md +112 -0
  21. package/docs/api/marshalToView.md +95 -0
  22. package/docs/api/openPanel.md +128 -0
  23. package/docs/api/registerHandler.md +174 -0
  24. package/docs/api/registerNodeType.md +142 -0
  25. package/docs/api/removeConnection.md +57 -0
  26. package/docs/api/removeNode.md +80 -0
  27. package/docs/api/saveLayout.md +152 -0
  28. package/docs/api/screenToSVGCoords.md +68 -0
  29. package/docs/api/selectNode.md +116 -0
  30. package/docs/api/setTheme.md +168 -0
  31. package/docs/api/setZoom.md +97 -0
  32. package/docs/api/toggleFullscreen.md +68 -0
  33. package/docs/card-help/EACH.md +19 -0
  34. package/docs/card-help/FREAD.md +24 -0
  35. package/docs/card-help/FWRITE.md +24 -0
  36. package/docs/card-help/GET.md +22 -0
  37. package/docs/card-help/ITE.md +23 -0
  38. package/docs/card-help/LOG.md +23 -0
  39. package/docs/card-help/NOTE.md +17 -0
  40. package/docs/card-help/PREV.md +18 -0
  41. package/docs/card-help/SET.md +27 -0
  42. package/docs/card-help/SPKL.md +22 -0
  43. package/docs/card-help/STAT.md +23 -0
  44. package/docs/card-help/SW.md +25 -0
  45. package/docs/css/docuserve.css +73 -0
  46. package/docs/index.html +39 -0
  47. package/docs/retold-catalog.json +169 -0
  48. package/docs/retold-keyword-index.json +13942 -0
  49. package/example_applications/simple_cards/package.json +1 -0
  50. package/example_applications/simple_cards/source/card-help-content.js +16 -0
  51. package/example_applications/simple_cards/source/cards/FlowCard-Comment.js +2 -0
  52. package/example_applications/simple_cards/source/cards/FlowCard-DataPreview.js +2 -0
  53. package/example_applications/simple_cards/source/cards/FlowCard-Each.js +2 -0
  54. package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +2 -0
  55. package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +2 -0
  56. package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +2 -0
  57. package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +2 -0
  58. package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +2 -0
  59. package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +2 -0
  60. package/example_applications/simple_cards/source/cards/FlowCard-Sparkline.js +2 -0
  61. package/example_applications/simple_cards/source/cards/FlowCard-StatusMonitor.js +2 -0
  62. package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +2 -0
  63. package/package.json +11 -7
  64. package/scripts/generate-card-help.js +214 -0
  65. package/source/Pict-Section-Flow.js +4 -0
  66. package/source/PictFlowCard.js +3 -1
  67. package/source/providers/PictProvider-Flow-CSS.js +245 -152
  68. package/source/providers/PictProvider-Flow-ConnectorShapes.js +24 -0
  69. package/source/providers/PictProvider-Flow-Geometry.js +195 -38
  70. package/source/providers/PictProvider-Flow-PanelChrome.js +14 -12
  71. package/source/services/PictService-Flow-ConnectionHandleManager.js +263 -0
  72. package/source/services/PictService-Flow-ConnectionRenderer.js +134 -183
  73. package/source/services/PictService-Flow-DataManager.js +338 -0
  74. package/source/services/PictService-Flow-InteractionManager.js +165 -7
  75. package/source/services/PictService-Flow-PathGenerator.js +282 -0
  76. package/source/services/PictService-Flow-PortRenderer.js +269 -0
  77. package/source/services/PictService-Flow-RenderManager.js +281 -0
  78. package/source/services/PictService-Flow-Tether.js +6 -42
  79. package/source/views/PictView-Flow-Node.js +2 -220
  80. package/source/views/PictView-Flow-PropertiesPanel.js +89 -44
  81. package/source/views/PictView-Flow.js +130 -882
  82. package/test/ConnectionHandleManager_tests.js +717 -0
  83. package/test/ConnectionRenderer_tests.js +591 -0
  84. package/test/DataManager_tests.js +859 -0
  85. package/test/Geometry_tests.js +767 -0
  86. package/test/PathGenerator_tests.js +978 -0
  87. package/test/PortRenderer_tests.js +367 -0
  88. package/test/RenderManager_tests.js +756 -0
package/docs/README.md CHANGED
@@ -1,69 +1,132 @@
1
- # Pict Section Flow Diagram
1
+ # Pict-Section-Flow
2
+
3
+ An interactive flow diagram section view for the [Pict](https://github.com/stevenvelozo/pict) application framework. Build node-based visual editors, workflow designers, and data pipeline tools with a declarative, configuration-driven API.
4
+
5
+ Pict-Section-Flow provides a complete graph editing experience — nodes, ports, connections, properties panels, theming, and layout persistence — all composable through the Fable service provider pattern.
6
+
7
+ ## What It Does
8
+
9
+ Pict-Section-Flow renders an SVG-based canvas where users can:
10
+
11
+ - **Drag nodes** from a palette onto the canvas
12
+ - **Connect ports** between nodes with bezier or orthogonal paths
13
+ - **Open properties panels** on any node for editing, documentation, or custom views
14
+ - **Pan and zoom** the viewport with mouse or trackpad
15
+ - **Save and restore** spatial layouts to localStorage or a remote backend
16
+ - **Theme the entire diagram** with built-in themes or CSS custom properties
17
+
18
+ All interaction is driven by a JSON data structure that represents the flow graph. The view marshals data bidirectionally with Pict's `AppData` store, so the flow state integrates naturally with the rest of your application.
19
+
20
+ ## Architecture at a Glance
21
+
22
+ ```mermaid
23
+ graph TD
24
+ A[Your Application] --> B[PictViewFlow]
25
+ B --> C[Services]
26
+ B --> D[Providers]
27
+ B --> E[Views]
28
+
29
+ C --> C1[DataManager]
30
+ C --> C2[RenderManager]
31
+ C --> C3[SelectionManager]
32
+ C --> C4[ViewportManager]
33
+ C --> C5[PanelManager]
34
+ C --> C6[InteractionManager]
35
+ C --> C7[Layout Service]
36
+
37
+ D --> D1[NodeTypes]
38
+ D --> D2[EventHandler]
39
+ D --> D3[Layouts]
40
+ D --> D4[Theme]
41
+ D --> D5[CSS]
42
+ D --> D6[Geometry]
43
+
44
+ E --> E1[Flow Node View]
45
+ E --> E2[Toolbar View]
46
+ E --> E3[Properties Panel View]
47
+
48
+ style A fill:#e8f5e9,stroke:#42b983,color:#333
49
+ style B fill:#e3f2fd,stroke:#42a5f5,color:#333
50
+ style C fill:#fff3e0,stroke:#ffa726,color:#333
51
+ style D fill:#f3e5f5,stroke:#ab47bc,color:#333
52
+ style E fill:#fce4ec,stroke:#ef5350,color:#333
53
+ ```
2
54
 
3
- A Pict section view for rendering flow diagrams. Provides views, providers, and services for visual flow-based layouts within Pict applications.
55
+ The module follows the standard Pict layered architecture:
4
56
 
5
- ## Installation
57
+ - **Views** handle rendering and DOM interaction
58
+ - **Services** contain business logic (CRUD, selection, viewport math)
59
+ - **Providers** supply configuration and stateless utilities (themes, node types, geometry)
6
60
 
7
- ```bash
8
- npm install pict-section-flow
9
- ```
61
+ ## Key Concepts
10
62
 
11
- ## Building
63
+ ### Flow Data
12
64
 
13
- ```bash
14
- npx quack build
15
- ```
65
+ The entire graph state lives in a single JSON object with four collections: `Nodes`, `Connections`, `OpenPanels`, and `SavedLayouts`. Every mutation goes through the `DataManager` service and triggers a re-render.
66
+
67
+ ### Custom Card Types
68
+
69
+ Developers define reusable node types by extending `PictFlowCard`. Each card declares its title, ports, category, appearance, and optional properties panel. Cards register with the flow view's `NodeTypeProvider` and appear in the toolbar palette.
16
70
 
17
- ## Layout Persistence
71
+ ### Properties Panels
18
72
 
19
- Saved layouts are persisted to `localStorage` by default, keyed by the flow view identifier (e.g. `pict-flow-layouts-MyFlowDiagram`). Layouts survive page refreshes without any configuration.
73
+ Nodes can open floating panels tethered to them by a line. Four built-in panel types cover common needs — Template, Markdown, Form, and View or you can create custom panel types by extending `PictFlowCardPropertiesPanel`.
20
74
 
21
- ### Overriding Storage (e.g. REST API)
75
+ ### Theming
22
76
 
23
- The `LayoutProvider` exposes three hookable storage methods that follow the `fCallback(pError, pResult)` convention. Replace them on the instance to use any backend:
77
+ Six built-in themes ship with the module. The theme system is CSS-variable-based: override any of 70+ `--pf-*` design tokens on `.pict-flow-container` to customize colors, shadows, radii, and typography without touching source code.
78
+
79
+ ### Event Hooks
80
+
81
+ The `EventHandlerProvider` exposes 20+ named events (node selected, connection created, flow changed, theme changed, etc.). Register handlers to build integrations, undo/redo stacks, or server sync without modifying core code.
82
+
83
+ ## Quick Example
24
84
 
25
85
  ```javascript
26
- // After your flow view is initialized:
27
- let layoutProvider = myFlowView._LayoutProvider;
28
-
29
- // Persist layouts to a server
30
- layoutProvider.storageWrite = function(pLayouts, fCallback)
31
- {
32
- fetch('/api/my-flow/layouts',
33
- {
34
- method: 'PUT',
35
- headers: { 'Content-Type': 'application/json' },
36
- body: JSON.stringify(pLayouts)
37
- })
38
- .then(() => fCallback(null))
39
- .catch((pError) => fCallback(pError));
40
- };
41
-
42
- // Load layouts from a server
43
- layoutProvider.storageRead = function(fCallback)
44
- {
45
- fetch('/api/my-flow/layouts')
46
- .then((pResponse) => pResponse.json())
47
- .then((pLayouts) => fCallback(null, pLayouts))
48
- .catch((pError) => fCallback(pError, []));
49
- };
50
-
51
- // Delete all layouts on the server
52
- layoutProvider.storageDelete = function(fCallback)
53
- {
54
- fetch('/api/my-flow/layouts', { method: 'DELETE' })
55
- .then(() => fCallback(null))
56
- .catch((pError) => fCallback(pError));
57
- };
58
-
59
- // Load from the new backend now that hooks are set
60
- layoutProvider.loadPersistedLayouts();
86
+ const libPictSectionFlow = require('pict-section-flow');
87
+ const libPict = require('pict');
88
+
89
+ let _Pict = new libPict({ Product: 'FlowDemo' });
90
+
91
+ _Pict.addView('MyFlow', {}, libPictSectionFlow);
92
+
93
+ let tmpFlow = _Pict.views.MyFlow;
94
+
95
+ // Add two nodes
96
+ let tmpStart = tmpFlow.addNode('start', 50, 150, 'Begin');
97
+ let tmpEnd = tmpFlow.addNode('end', 400, 150, 'Done');
98
+
99
+ // Connect them
100
+ tmpFlow.addConnection(
101
+ tmpStart.Hash, tmpStart.Ports[0].Hash,
102
+ tmpEnd.Hash, tmpEnd.Ports[0].Hash
103
+ );
104
+
105
+ // Listen for changes
106
+ tmpFlow._EventHandlerProvider.registerHandler('onFlowChanged',
107
+ (pFlowData) =>
108
+ {
109
+ console.log('Flow updated:', pFlowData.Nodes.length, 'nodes');
110
+ });
61
111
  ```
62
112
 
63
- ### Configuration Options
113
+ ## Learn More
114
+
115
+ - **[Getting Started](Getting_Started.md)** — Build your first flow diagram in five minutes
116
+ - **[Architecture](Architecture.md)** — Detailed service/provider design with data flow diagrams
117
+ - **[Implementation Reference](Implementation_Reference.md)** — Complete API surface for every service and provider
118
+ - **[Custom Styling](Custom-Styling.md)** — CSS custom properties reference and theme API
119
+ - **[Layout Persistence](Layout_Persistence.md)** — Save and restore layouts with localStorage or REST
120
+
121
+ ## Ecosystem
122
+
123
+ Pict-Section-Flow is part of the [Retold](https://github.com/stevenvelozo/retold) module suite:
64
124
 
65
- - **`StorageKey`** (string) -- Override the localStorage key. Passed via options when instantiating the provider.
66
- - **`StorageKey: false`** -- Disable localStorage persistence entirely (useful when using only a remote backend).
125
+ - [pict](https://github.com/stevenvelozo/pict) Core MVC application framework
126
+ - [pict-view](https://github.com/stevenvelozo/pict-view) View base class
127
+ - [pict-provider](https://github.com/stevenvelozo/pict-provider) — Provider base class
128
+ - [pict-section-form](https://github.com/stevenvelozo/pict-section-form) — Form sections (used for Form panel type)
129
+ - [fable](https://github.com/stevenvelozo/fable) — Service infrastructure and dependency injection
67
130
 
68
131
  ## License
69
132
 
package/docs/_cover.md ADDED
@@ -0,0 +1,11 @@
1
+ # Pict-Section-Flow <small>0</small>
2
+
3
+ > Interactive flow diagram section view for the Pict application framework
4
+
5
+ - Node-based graph editor with typed ports and bezier connections
6
+ - Custom card types, properties panels, and event hooks
7
+ - Six built-in themes with 70+ CSS design tokens
8
+ - Layout persistence to localStorage or any backend
9
+
10
+ [GitHub](https://github.com/stevenvelozo/pict-section-flow)
11
+ [Get Started](#pict-section-flow)
@@ -0,0 +1,52 @@
1
+ - Getting Started
2
+
3
+ - [Overview](/)
4
+ - [Quick Start](Getting_Started.md)
5
+ - [Custom Styling](Custom-Styling.md)
6
+
7
+ - Architecture
8
+
9
+ - [Design Overview](Architecture.md)
10
+ - [Data Model](Data_Model.md)
11
+ - [Event System](Event_System.md)
12
+
13
+ - Reference
14
+
15
+ - [Implementation Reference](Implementation_Reference.md)
16
+ - [Layout Persistence](Layout_Persistence.md)
17
+
18
+ - API — Data Management
19
+
20
+ - [addNode](api/addNode.md)
21
+ - [removeNode](api/removeNode.md)
22
+ - [addConnection](api/addConnection.md)
23
+ - [removeConnection](api/removeConnection.md)
24
+ - [getFlowData / setFlowData](api/getFlowData.md)
25
+ - [marshalToView / marshalFromView](api/marshalToView.md)
26
+
27
+ - API — Selection & Viewport
28
+
29
+ - [selectNode / deselectAll](api/selectNode.md)
30
+ - [setZoom / zoomToFit](api/setZoom.md)
31
+ - [autoLayout](api/autoLayout.md)
32
+ - [screenToSVGCoords](api/screenToSVGCoords.md)
33
+ - [toggleFullscreen](api/toggleFullscreen.md)
34
+
35
+ - API — Panels
36
+
37
+ - [openPanel / closePanel / togglePanel](api/openPanel.md)
38
+
39
+ - API — Theming & Events
40
+
41
+ - [setTheme / registerTheme](api/setTheme.md)
42
+ - [registerHandler / fireEvent](api/registerHandler.md)
43
+
44
+ - API — Layout Persistence
45
+
46
+ - [saveLayout / restoreLayout](api/saveLayout.md)
47
+
48
+ - API — Extension Points
49
+
50
+ - [PictFlowCard](api/PictFlowCard.md)
51
+ - [PictFlowCardPropertiesPanel](api/PictFlowCardPropertiesPanel.md)
52
+ - [registerNodeType](api/registerNodeType.md)
@@ -0,0 +1,8 @@
1
+ # Pict Section Flow
2
+
3
+ - [Overview](README.md)
4
+ - [Getting Started](Getting_Started.md)
5
+ - [Architecture](Architecture.md)
6
+ - [API Reference](Implementation_Reference.md)
7
+ - [Custom Styling](Custom-Styling.md)
8
+ - [GitHub](https://github.com/stevenvelozo/pict-section-flow)
@@ -0,0 +1,216 @@
1
+ # PictFlowCard
2
+
3
+ Base class for defining reusable flow diagram node types. Extend this class to create custom cards that appear in the toolbar palette. Each card declares its title, ports, category, appearance, and optional properties panel.
4
+
5
+ ## Import
6
+
7
+ ```javascript
8
+ const libPictFlowCard = require('pict-section-flow').PictFlowCard;
9
+ ```
10
+
11
+ ## Constructor
12
+
13
+ ```javascript
14
+ class MyCard extends libPictFlowCard
15
+ {
16
+ constructor(pFable, pOptions, pServiceHash)
17
+ {
18
+ super(pFable, Object.assign({},
19
+ {
20
+ Title: 'My Card',
21
+ Code: 'MC',
22
+ // ... options
23
+ }, pOptions), pServiceHash);
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## Configuration Options
29
+
30
+ | Property | Type | Default | Description |
31
+ |----------|------|---------|-------------|
32
+ | `Title` | string | `'Card'` | Display name on the node title bar |
33
+ | `Name` | string | `false` | Longer descriptive name |
34
+ | `Code` | string | `''` | Short identifier used as the node type key |
35
+ | `Description` | string | `false` | Brief explanation of the card's purpose |
36
+ | `Icon` | string | `false` | Icon identifier or emoji |
37
+ | `PreviewImage` | string | `false` | URL to a preview thumbnail |
38
+ | `Documentation` | string | `false` | URL or inline documentation text |
39
+ | `Tooltip` | string | `false` | Hover tooltip text |
40
+ | `Help` | string | `false` | HTML help content for the Help tab |
41
+ | `Category` | string | `'General'` | Palette grouping category |
42
+ | `Enabled` | boolean | `true` | Whether the card appears in the palette |
43
+ | `TitleBarColor` | string | `'#2c3e50'` | Title bar background color |
44
+ | `BodyStyle` | object | `{}` | SVG style attributes for the node body |
45
+ | `Width` | number | `180` | Default node width in pixels |
46
+ | `Height` | number | `80` | Default node height in pixels |
47
+
48
+ ### Port Options
49
+
50
+ | Property | Type | Default | Description |
51
+ |----------|------|---------|-------------|
52
+ | `Inputs` | array | `[]` | Input port definitions |
53
+ | `Outputs` | array | `[]` | Output port definitions |
54
+
55
+ Each port object:
56
+
57
+ | Property | Type | Default | Description |
58
+ |----------|------|---------|-------------|
59
+ | `Name` | string | Required | Port label |
60
+ | `Side` | string | `'left'`/`'right'` | Port side: `'left'`, `'right'`, `'top'`, `'bottom'` |
61
+ | `MinimumInputCount` | number | `0` | Minimum required connections (inputs only) |
62
+ | `MaximumInputCount` | number | `-1` | Maximum allowed connections (-1 = unlimited, inputs only) |
63
+ | `PortType` | string | — | Type for styling: `'event'`, `'setting'`, `'value'`, `'error'` |
64
+ | `DataType` | string | — | Semantic data type (for validation/display) |
65
+
66
+ ### Label Display Options
67
+
68
+ | Property | Type | Default | Description |
69
+ |----------|------|---------|-------------|
70
+ | `ShowTypeLabel` | boolean | `true` | Show the type code badge on hover |
71
+ | `PortLabelsOnHover` | boolean | `false` | Only show port labels on hover |
72
+ | `PortLabelsVertical` | boolean | `false` | Render port labels vertically |
73
+ | `PortLabelPadding` | boolean | `false` | Extra spacing to avoid overlap |
74
+ | `PortLabelsOutside` | boolean | `false` | Render labels outside the node body |
75
+ | `LabelsInFront` | boolean | `true` | Labels render in front of body content |
76
+
77
+ ### Properties Panel Configuration
78
+
79
+ | Property | Type | Description |
80
+ |----------|------|-------------|
81
+ | `PropertiesPanel.PanelType` | string | `'Template'`, `'Markdown'`, `'Form'`, or `'View'` |
82
+ | `PropertiesPanel.DefaultWidth` | number | Panel width in pixels |
83
+ | `PropertiesPanel.DefaultHeight` | number | Panel height in pixels |
84
+ | `PropertiesPanel.Title` | string | Panel title bar text |
85
+ | `PropertiesPanel.Configuration` | object | Panel-type-specific config |
86
+
87
+ ### Body Content Configuration
88
+
89
+ | Property | Type | Description |
90
+ |----------|------|-------------|
91
+ | `BodyContent.ContentType` | string | `'svg'`, `'html'`, or `'canvas'` |
92
+ | `BodyContent.Template` | string | Pict template string |
93
+ | `BodyContent.TemplateHash` | string | Registered template hash (overrides Template) |
94
+ | `BodyContent.Templates` | array | Templates to auto-register: `[{ Hash, Template }]` |
95
+ | `BodyContent.RenderCallback` | function | Imperative render callback for canvas mode |
96
+ | `BodyContent.Padding` | number | Inner padding in pixels |
97
+
98
+ ## Methods
99
+
100
+ ### getNodeTypeConfiguration()
101
+
102
+ Generate the configuration object for the NodeTypes provider.
103
+
104
+ **Returns:** Node type configuration object.
105
+
106
+ ### registerWithFlowView(pFlowView)
107
+
108
+ Register this card with a flow view's node type provider.
109
+
110
+ | Parameter | Type | Description |
111
+ |-----------|------|-------------|
112
+ | `pFlowView` | PictViewFlow | The flow view instance |
113
+
114
+ **Returns:** `boolean` — whether registration succeeded.
115
+
116
+ ## Examples
117
+
118
+ ### Minimal card
119
+
120
+ ```javascript
121
+ class LogCard extends libPictFlowCard
122
+ {
123
+ constructor(pFable, pOptions, pServiceHash)
124
+ {
125
+ super(pFable, Object.assign({},
126
+ {
127
+ Title: 'Log',
128
+ Code: 'LOG',
129
+ Inputs: [{ Name: 'Data', Side: 'left' }],
130
+ Outputs: [{ Name: 'Pass', Side: 'right' }]
131
+ }, pOptions), pServiceHash);
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Card with typed ports and properties panel
137
+
138
+ ```javascript
139
+ class IfThenElseCard extends libPictFlowCard
140
+ {
141
+ constructor(pFable, pOptions, pServiceHash)
142
+ {
143
+ super(pFable, Object.assign({},
144
+ {
145
+ Title: 'If-Then-Else',
146
+ Code: 'ITE',
147
+ Category: 'Control Flow',
148
+ Description: 'Route flow based on a boolean condition',
149
+ TitleBarColor: '#e67e22',
150
+ Width: 160,
151
+ Height: 90,
152
+ Inputs:
153
+ [
154
+ { Name: 'Condition', Side: 'left', PortType: 'value' }
155
+ ],
156
+ Outputs:
157
+ [
158
+ { Name: 'Then', Side: 'right', PortType: 'event' },
159
+ { Name: 'Else', Side: 'bottom', PortType: 'error' }
160
+ ],
161
+ PropertiesPanel:
162
+ {
163
+ PanelType: 'Markdown',
164
+ Title: 'If-Then-Else',
165
+ DefaultWidth: 280,
166
+ DefaultHeight: 150,
167
+ Configuration:
168
+ {
169
+ Markdown: '## Conditional Branch\nRoutes flow based on a boolean condition.'
170
+ }
171
+ }
172
+ }, pOptions), pServiceHash);
173
+ }
174
+ }
175
+ ```
176
+
177
+ ### Card with custom SVG body content
178
+
179
+ ```javascript
180
+ class SparklineCard extends libPictFlowCard
181
+ {
182
+ constructor(pFable, pOptions, pServiceHash)
183
+ {
184
+ super(pFable, Object.assign({},
185
+ {
186
+ Title: 'Sparkline',
187
+ Code: 'SPARK',
188
+ Category: 'Visualization',
189
+ Width: 200,
190
+ Height: 100,
191
+ Inputs: [{ Name: 'Values', Side: 'left', PortType: 'value' }],
192
+ BodyContent:
193
+ {
194
+ ContentType: 'svg',
195
+ Template: '<polyline points="0,50 20,30 40,45 60,10 80,35 100,20" fill="none" stroke="#3498db" stroke-width="2" />'
196
+ }
197
+ }, pOptions), pServiceHash);
198
+ }
199
+ }
200
+ ```
201
+
202
+ ### Registration
203
+
204
+ ```javascript
205
+ let tmpCard = new IfThenElseCard(_Pict, {});
206
+ tmpCard.registerWithFlowView(flowView);
207
+
208
+ // The card now appears in the toolbar palette under "Control Flow"
209
+ // Users can drag it onto the canvas to create new ITE nodes
210
+ ```
211
+
212
+ ## See Also
213
+
214
+ - [registerNodeType](registerNodeType.md) — Register types directly without PictFlowCard
215
+ - [PictFlowCardPropertiesPanel](PictFlowCardPropertiesPanel.md) — Custom panel types
216
+ - [addNode](addNode.md) — Create nodes from registered types