pict-section-flow 0.0.10 → 0.0.12
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/README.md +157 -0
- package/docs/.nojekyll +0 -0
- package/docs/Architecture.md +303 -0
- package/docs/Custom-Styling.md +275 -0
- package/docs/Getting_Started.md +237 -0
- package/docs/Implementation_Reference.md +528 -0
- package/docs/Layout_Persistence.md +117 -0
- package/docs/README.md +115 -52
- package/docs/_cover.md +11 -0
- package/docs/_sidebar.md +47 -0
- package/docs/_topbar.md +8 -0
- package/docs/api/PictFlowCard.md +216 -0
- package/docs/api/PictFlowCardPropertiesPanel.md +235 -0
- package/docs/api/addConnection.md +101 -0
- package/docs/api/addNode.md +137 -0
- package/docs/api/autoLayout.md +77 -0
- package/docs/api/getFlowData.md +112 -0
- package/docs/api/marshalToView.md +95 -0
- package/docs/api/openPanel.md +128 -0
- package/docs/api/registerHandler.md +174 -0
- package/docs/api/registerNodeType.md +142 -0
- package/docs/api/removeConnection.md +57 -0
- package/docs/api/removeNode.md +80 -0
- package/docs/api/saveLayout.md +152 -0
- package/docs/api/screenToSVGCoords.md +68 -0
- package/docs/api/selectNode.md +116 -0
- package/docs/api/setTheme.md +168 -0
- package/docs/api/setZoom.md +97 -0
- package/docs/api/toggleFullscreen.md +68 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/index.html +39 -0
- package/docs/retold-catalog.json +146 -0
- package/docs/retold-keyword-index.json +9536 -0
- package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +1 -0
- package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +1 -0
- package/package.json +8 -6
- package/source/Pict-Section-Flow.js +4 -0
- package/source/PictFlowCard.js +3 -1
- package/source/providers/PictProvider-Flow-CSS.js +247 -152
- package/source/providers/PictProvider-Flow-ConnectorShapes.js +24 -0
- package/source/providers/PictProvider-Flow-Geometry.js +195 -38
- package/source/providers/PictProvider-Flow-PanelChrome.js +14 -12
- package/source/services/PictService-Flow-ConnectionHandleManager.js +263 -0
- package/source/services/PictService-Flow-ConnectionRenderer.js +134 -183
- package/source/services/PictService-Flow-DataManager.js +338 -0
- package/source/services/PictService-Flow-InteractionManager.js +165 -7
- package/source/services/PictService-Flow-PathGenerator.js +282 -0
- package/source/services/PictService-Flow-PortRenderer.js +269 -0
- package/source/services/PictService-Flow-RenderManager.js +281 -0
- package/source/services/PictService-Flow-Tether.js +6 -42
- package/source/views/PictView-Flow-Node.js +2 -220
- package/source/views/PictView-Flow-PropertiesPanel.js +89 -44
- package/source/views/PictView-Flow.js +130 -882
- package/test/ConnectionHandleManager_tests.js +717 -0
- package/test/ConnectionRenderer_tests.js +591 -0
- package/test/DataManager_tests.js +859 -0
- package/test/Geometry_tests.js +767 -0
- package/test/PathGenerator_tests.js +978 -0
- package/test/PortRenderer_tests.js +367 -0
- package/test/RenderManager_tests.js +756 -0
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Pict-Section-Flow
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/pict-section-flow)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
An interactive flow diagram section view for the Pict application framework. Build node-based visual editors, workflow designers, and data pipeline tools with a declarative, configuration-driven API.
|
|
7
|
+
|
|
8
|
+
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.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Node-Based Graph Editor** — Drag-and-drop nodes with typed input/output ports and bezier or orthogonal connections
|
|
13
|
+
- **Custom Card Types** — Define reusable node types with the `PictFlowCard` base class; register categories, icons, port constraints, and body content
|
|
14
|
+
- **Properties Panels** — On-graph panels with four built-in types: Template, Markdown, Form, and View
|
|
15
|
+
- **Theming** — Six built-in themes plus a CSS custom properties API with 70+ design tokens
|
|
16
|
+
- **Layout Persistence** — Save and restore spatial arrangements to localStorage or any backend
|
|
17
|
+
- **Event System** — Hook into 20+ lifecycle events for custom behavior without modifying core code
|
|
18
|
+
- **Viewport Controls** — Pan, zoom, fullscreen, grid snap, zoom-to-fit, and auto-layout
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install pict-section-flow
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
const libPictSectionFlow = require('pict-section-flow');
|
|
30
|
+
const libPict = require('pict');
|
|
31
|
+
|
|
32
|
+
let _Pict = new libPict({ Product: 'MyFlowApp' });
|
|
33
|
+
|
|
34
|
+
// Register the flow view
|
|
35
|
+
_Pict.addView('MyFlow', {}, libPictSectionFlow);
|
|
36
|
+
|
|
37
|
+
// Add a node programmatically
|
|
38
|
+
let tmpFlowView = _Pict.views.MyFlow;
|
|
39
|
+
tmpFlowView.addNode('start', 50, 100, 'Begin');
|
|
40
|
+
tmpFlowView.addNode('end', 400, 100, 'Finish');
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Custom Card Types
|
|
44
|
+
|
|
45
|
+
Define reusable node types by extending `PictFlowCard`:
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
const libPictFlowCard = require('pict-section-flow').PictFlowCard;
|
|
49
|
+
|
|
50
|
+
class IfThenElseCard extends libPictFlowCard
|
|
51
|
+
{
|
|
52
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
53
|
+
{
|
|
54
|
+
super(pFable, Object.assign({},
|
|
55
|
+
{
|
|
56
|
+
Title: 'If-Then-Else',
|
|
57
|
+
Code: 'ITE',
|
|
58
|
+
Category: 'Control Flow',
|
|
59
|
+
TitleBarColor: '#e67e22',
|
|
60
|
+
Inputs: [{ Name: 'Condition', Side: 'left' }],
|
|
61
|
+
Outputs:
|
|
62
|
+
[
|
|
63
|
+
{ Name: 'Then', Side: 'right', PortType: 'event' },
|
|
64
|
+
{ Name: 'Else', Side: 'bottom', PortType: 'error' }
|
|
65
|
+
],
|
|
66
|
+
PropertiesPanel:
|
|
67
|
+
{
|
|
68
|
+
PanelType: 'Markdown',
|
|
69
|
+
Title: 'If-Then-Else',
|
|
70
|
+
Configuration:
|
|
71
|
+
{
|
|
72
|
+
Markdown: '## Conditional Branch\nRoutes flow based on a boolean condition.'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}, pOptions), pServiceHash);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Configuration Options
|
|
81
|
+
|
|
82
|
+
| Option | Type | Default | Description |
|
|
83
|
+
|--------|------|---------|-------------|
|
|
84
|
+
| `ViewIdentifier` | string | `'Pict-Flow'` | Unique view identifier |
|
|
85
|
+
| `FlowDataAddress` | string/false | `false` | AppData path for two-way binding |
|
|
86
|
+
| `EnableToolbar` | boolean | `true` | Show the toolbar UI |
|
|
87
|
+
| `EnablePanning` | boolean | `true` | Allow canvas panning |
|
|
88
|
+
| `EnableZooming` | boolean | `true` | Allow canvas zooming |
|
|
89
|
+
| `EnableNodeDragging` | boolean | `true` | Allow node repositioning |
|
|
90
|
+
| `EnableConnectionCreation` | boolean | `true` | Allow port-to-port connections |
|
|
91
|
+
| `EnableGridSnap` | boolean | `false` | Snap nodes to grid |
|
|
92
|
+
| `GridSnapSize` | number | `20` | Grid cell size in pixels |
|
|
93
|
+
| `MinZoom` | number | `0.1` | Minimum zoom level |
|
|
94
|
+
| `MaxZoom` | number | `5.0` | Maximum zoom level |
|
|
95
|
+
| `Theme` | string | `'default'` | Active theme key |
|
|
96
|
+
|
|
97
|
+
## Built-in Themes
|
|
98
|
+
|
|
99
|
+
| Theme | Style |
|
|
100
|
+
|-------|-------|
|
|
101
|
+
| `default` | Clean, modern, professional |
|
|
102
|
+
| `sketch` | Hand-drawn, informal |
|
|
103
|
+
| `blueprint` | Technical blueprint |
|
|
104
|
+
| `mono` | Monochrome |
|
|
105
|
+
| `retro-80s` | Neon retro |
|
|
106
|
+
| `retro-90s` | Vaporwave |
|
|
107
|
+
|
|
108
|
+
## Documentation
|
|
109
|
+
|
|
110
|
+
Full documentation is available at [https://stevenvelozo.github.io/pict-section-flow/](https://stevenvelozo.github.io/pict-section-flow/)
|
|
111
|
+
|
|
112
|
+
- [Getting Started](https://stevenvelozo.github.io/pict-section-flow/#/Getting_Started) — First flow diagram in five minutes
|
|
113
|
+
- [Architecture](https://stevenvelozo.github.io/pict-section-flow/#/Architecture) — Service/provider design and data flow
|
|
114
|
+
- [Implementation Reference](https://stevenvelozo.github.io/pict-section-flow/#/Implementation_Reference) — Complete API surface
|
|
115
|
+
- [Custom Styling](https://stevenvelozo.github.io/pict-section-flow/#/Custom-Styling) — CSS custom properties and theme API
|
|
116
|
+
- [Layout Persistence](https://stevenvelozo.github.io/pict-section-flow/#/Layout_Persistence) — Save/restore with localStorage or REST
|
|
117
|
+
|
|
118
|
+
## API Reference (Function Docs)
|
|
119
|
+
|
|
120
|
+
Detailed per-function documentation with code snippets:
|
|
121
|
+
|
|
122
|
+
| Function | Description |
|
|
123
|
+
|----------|-------------|
|
|
124
|
+
| [addNode](docs/api/addNode.md) | Create a node on the canvas |
|
|
125
|
+
| [removeNode](docs/api/removeNode.md) | Delete a node and its connections |
|
|
126
|
+
| [addConnection](docs/api/addConnection.md) | Connect two ports |
|
|
127
|
+
| [removeConnection](docs/api/removeConnection.md) | Delete a connection |
|
|
128
|
+
| [getFlowData / setFlowData](docs/api/getFlowData.md) | Get or load entire flow state |
|
|
129
|
+
| [selectNode / deselectAll](docs/api/selectNode.md) | Manage selection state |
|
|
130
|
+
| [openPanel / closePanel / togglePanel](docs/api/openPanel.md) | Properties panel lifecycle |
|
|
131
|
+
| [setZoom / zoomToFit](docs/api/setZoom.md) | Viewport zoom controls |
|
|
132
|
+
| [autoLayout](docs/api/autoLayout.md) | Automatic topological layout |
|
|
133
|
+
| [setTheme / registerTheme](docs/api/setTheme.md) | Theme management |
|
|
134
|
+
| [registerHandler / fireEvent](docs/api/registerHandler.md) | Event system |
|
|
135
|
+
| [saveLayout / restoreLayout](docs/api/saveLayout.md) | Layout persistence |
|
|
136
|
+
| [marshalToView / marshalFromView](docs/api/marshalToView.md) | AppData two-way binding |
|
|
137
|
+
| [PictFlowCard](docs/api/PictFlowCard.md) | Custom node type base class |
|
|
138
|
+
| [PictFlowCardPropertiesPanel](docs/api/PictFlowCardPropertiesPanel.md) | Custom panel base class |
|
|
139
|
+
| [registerNodeType](docs/api/registerNodeType.md) | Node type registry |
|
|
140
|
+
| [screenToSVGCoords](docs/api/screenToSVGCoords.md) | Coordinate conversion |
|
|
141
|
+
| [toggleFullscreen](docs/api/toggleFullscreen.md) | Fullscreen mode |
|
|
142
|
+
|
|
143
|
+
## Related Packages
|
|
144
|
+
|
|
145
|
+
- [pict](https://github.com/stevenvelozo/pict) — MVC application framework
|
|
146
|
+
- [pict-view](https://github.com/stevenvelozo/pict-view) — View base class
|
|
147
|
+
- [pict-provider](https://github.com/stevenvelozo/pict-provider) — Provider base class
|
|
148
|
+
- [pict-section-form](https://github.com/stevenvelozo/pict-section-form) — Form sections (used for Form panels)
|
|
149
|
+
- [fable](https://github.com/stevenvelozo/fable) — Service infrastructure
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT
|
|
154
|
+
|
|
155
|
+
## Contributing
|
|
156
|
+
|
|
157
|
+
Pull requests are welcome. For details on our code of conduct, contribution process, and testing requirements, see the [Retold Contributing Guide](https://github.com/stevenvelozo/retold/blob/main/docs/contributing.md).
|
package/docs/.nojekyll
ADDED
|
File without changes
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Pict-Section-Flow follows the standard Pict layered architecture — Views for rendering, Services for business logic, and Providers for configuration and stateless utilities. All components register with a Fable instance through the service provider pattern.
|
|
4
|
+
|
|
5
|
+
## High-Level Design
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TB
|
|
9
|
+
subgraph Application["Your Application"]
|
|
10
|
+
AppCode[Application Code]
|
|
11
|
+
AppData[Pict AppData Store]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
subgraph FlowView["PictViewFlow (Main Entry Point)"]
|
|
15
|
+
direction TB
|
|
16
|
+
FV[PictViewFlow]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
subgraph Views["Views (Rendering)"]
|
|
20
|
+
NodeView[Flow Node View]
|
|
21
|
+
ToolbarView[Toolbar View]
|
|
22
|
+
FloatingToolbar[Floating Toolbar View]
|
|
23
|
+
PanelView[Properties Panel View]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
subgraph Services["Services (Business Logic)"]
|
|
27
|
+
DM[DataManager]
|
|
28
|
+
RM[RenderManager]
|
|
29
|
+
SM[SelectionManager]
|
|
30
|
+
VM[ViewportManager]
|
|
31
|
+
PM[PanelManager]
|
|
32
|
+
IM[InteractionManager]
|
|
33
|
+
LS[Layout Service]
|
|
34
|
+
CR[ConnectionRenderer]
|
|
35
|
+
PG[PathGenerator]
|
|
36
|
+
PR[PortRenderer]
|
|
37
|
+
CHM[ConnectionHandleManager]
|
|
38
|
+
TM[Tether Service]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
subgraph Providers["Providers (Configuration)"]
|
|
42
|
+
NTP[NodeTypes Provider]
|
|
43
|
+
EHP[EventHandler Provider]
|
|
44
|
+
LP[Layouts Provider]
|
|
45
|
+
TP[Theme Provider]
|
|
46
|
+
CP[CSS Provider]
|
|
47
|
+
GP[Geometry Provider]
|
|
48
|
+
NP[Noise Provider]
|
|
49
|
+
SVG[SVGHelpers Provider]
|
|
50
|
+
CSP[ConnectorShapes Provider]
|
|
51
|
+
IP[Icons Provider]
|
|
52
|
+
PCP[PanelChrome Provider]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
subgraph Extension["Extension Points"]
|
|
56
|
+
FC[PictFlowCard]
|
|
57
|
+
FCP[PictFlowCardPropertiesPanel]
|
|
58
|
+
PT[Panel: Template]
|
|
59
|
+
PMD[Panel: Markdown]
|
|
60
|
+
PF[Panel: Form]
|
|
61
|
+
PVW[Panel: View]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
AppCode --> FV
|
|
65
|
+
FV <--> AppData
|
|
66
|
+
FV --> Views
|
|
67
|
+
FV --> Services
|
|
68
|
+
FV --> Providers
|
|
69
|
+
|
|
70
|
+
DM <--> AppData
|
|
71
|
+
RM --> NodeView
|
|
72
|
+
RM --> CR
|
|
73
|
+
PM --> PanelView
|
|
74
|
+
IM --> SM
|
|
75
|
+
IM --> VM
|
|
76
|
+
CR --> PG
|
|
77
|
+
CR --> PR
|
|
78
|
+
|
|
79
|
+
FC --> NTP
|
|
80
|
+
FCP --> PM
|
|
81
|
+
PT --> PanelView
|
|
82
|
+
PMD --> PanelView
|
|
83
|
+
PF --> PanelView
|
|
84
|
+
PVW --> PanelView
|
|
85
|
+
|
|
86
|
+
EHP --> AppCode
|
|
87
|
+
|
|
88
|
+
style Application fill:#e8f5e9,stroke:#42b983,color:#333
|
|
89
|
+
style FlowView fill:#e3f2fd,stroke:#42a5f5,color:#333
|
|
90
|
+
style Views fill:#fce4ec,stroke:#ef5350,color:#333
|
|
91
|
+
style Services fill:#fff3e0,stroke:#ffa726,color:#333
|
|
92
|
+
style Providers fill:#f3e5f5,stroke:#ab47bc,color:#333
|
|
93
|
+
style Extension fill:#e0f2f1,stroke:#26a69a,color:#333
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Data Flow
|
|
97
|
+
|
|
98
|
+
All mutations flow through a predictable pipeline:
|
|
99
|
+
|
|
100
|
+
```mermaid
|
|
101
|
+
sequenceDiagram
|
|
102
|
+
participant App as Application
|
|
103
|
+
participant FV as PictViewFlow
|
|
104
|
+
participant DM as DataManager
|
|
105
|
+
participant EH as EventHandler
|
|
106
|
+
participant RM as RenderManager
|
|
107
|
+
|
|
108
|
+
App->>FV: addNode('start', 50, 100, 'Begin')
|
|
109
|
+
FV->>DM: addNode(pType, pX, pY, pTitle, pData)
|
|
110
|
+
DM->>DM: Create node object with UUID hash
|
|
111
|
+
DM->>DM: Merge default ports from NodeType
|
|
112
|
+
DM->>EH: fireEvent('onNodeAdded', node)
|
|
113
|
+
DM->>EH: fireEvent('onFlowChanged', flowData)
|
|
114
|
+
DM->>RM: renderFlow()
|
|
115
|
+
RM->>RM: Render SVG nodes, connections, tethers, panels
|
|
116
|
+
DM-->>FV: Return node object
|
|
117
|
+
FV-->>App: Return node object
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## SVG Layer Structure
|
|
121
|
+
|
|
122
|
+
The rendering system uses SVG group elements in a specific z-order:
|
|
123
|
+
|
|
124
|
+
```mermaid
|
|
125
|
+
graph TB
|
|
126
|
+
subgraph SVG["SVG Canvas"]
|
|
127
|
+
Grid["Grid Background (pattern)"]
|
|
128
|
+
subgraph Viewport["Viewport Group (pan/zoom transform)"]
|
|
129
|
+
Connections["Connections Layer (bezier/orthogonal paths)"]
|
|
130
|
+
Nodes["Nodes Layer (rect + ports + labels)"]
|
|
131
|
+
Tethers["Tethers Layer (panel-to-node lines)"]
|
|
132
|
+
Panels["Panels Layer (foreignObject panels)"]
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
Grid --> Viewport
|
|
137
|
+
Connections --> Nodes
|
|
138
|
+
Nodes --> Tethers
|
|
139
|
+
Tethers --> Panels
|
|
140
|
+
|
|
141
|
+
style SVG fill:#f5f5f5,stroke:#bdbdbd,color:#333
|
|
142
|
+
style Viewport fill:#e3f2fd,stroke:#42a5f5,color:#333
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Connections render behind nodes so lines do not obscure node bodies. Tethers render above nodes so the connecting line from a panel to its node is always visible. Panels render last so they float above everything.
|
|
146
|
+
|
|
147
|
+
## Component Roles
|
|
148
|
+
|
|
149
|
+
### Views
|
|
150
|
+
|
|
151
|
+
| View | Role |
|
|
152
|
+
|------|------|
|
|
153
|
+
| `PictViewFlow` | Main entry point. Orchestrates services, providers, and child views. Exposes the public API. |
|
|
154
|
+
| `PictViewFlowNode` | Renders individual node SVG groups (title bar, body, ports, labels). |
|
|
155
|
+
| `PictViewFlowToolbar` | Renders the docked toolbar with palette cards, zoom controls, and layout buttons. |
|
|
156
|
+
| `PictViewFlowFloatingToolbar` | Renders context-sensitive floating toolbar on node selection. |
|
|
157
|
+
| `PictViewFlowPropertiesPanel` | Renders panel chrome and delegates content to panel type handlers. |
|
|
158
|
+
|
|
159
|
+
### Services
|
|
160
|
+
|
|
161
|
+
| Service | Role |
|
|
162
|
+
|---------|------|
|
|
163
|
+
| `DataManager` | CRUD for nodes and connections. Marshals to/from AppData. Fires data events. |
|
|
164
|
+
| `RenderManager` | Orchestrates full and partial re-renders. Delegates to node, connection, and panel renderers. |
|
|
165
|
+
| `SelectionManager` | Tracks selected node, connection, or tether. Fires selection events. |
|
|
166
|
+
| `ViewportManager` | Pan, zoom, fullscreen, coordinate transforms. |
|
|
167
|
+
| `PanelManager` | Open, close, toggle, and position properties panels. |
|
|
168
|
+
| `InteractionManager` | Pointer and keyboard event handling. State machine for drag modes. |
|
|
169
|
+
| `Layout Service` | Grid snap math and topological auto-layout algorithm. |
|
|
170
|
+
| `ConnectionRenderer` | Renders bezier and orthogonal paths with arrowheads. |
|
|
171
|
+
| `PathGenerator` | Pure math: bezier curves and orthogonal routing. |
|
|
172
|
+
| `PortRenderer` | Renders port circles on node boundaries. |
|
|
173
|
+
| `ConnectionHandleManager` | Manages bezier control point state for manual path adjustments. |
|
|
174
|
+
| `Tether` | Renders the connecting lines between panels and their parent nodes. |
|
|
175
|
+
|
|
176
|
+
### Providers
|
|
177
|
+
|
|
178
|
+
| Provider | Role |
|
|
179
|
+
|----------|------|
|
|
180
|
+
| `NodeTypes` | Registry of available node types. Cards register here. |
|
|
181
|
+
| `EventHandler` | Named event system with multi-handler support. |
|
|
182
|
+
| `Layouts` | Save/restore/delete layout snapshots. Pluggable storage backend. |
|
|
183
|
+
| `Theme` | Named theme registry. Applies CSS variable overrides. |
|
|
184
|
+
| `CSS` | Generates and injects all CSS into Pict's CSSMap service. |
|
|
185
|
+
| `Geometry` | Port positioning math: local coordinates, minimum node height, port counts by side. |
|
|
186
|
+
| `Noise` | Perlin-like noise for the hand-drawn rendering effect. |
|
|
187
|
+
| `SVGHelpers` | DOM utilities for creating and manipulating SVG elements. |
|
|
188
|
+
| `ConnectorShapes` | SVG marker definitions for arrowheads by port type. |
|
|
189
|
+
| `Icons` | Icon template library for toolbar and node UI. |
|
|
190
|
+
| `PanelChrome` | Panel title bar and tab bar template generation. |
|
|
191
|
+
|
|
192
|
+
## Flow Data Structure
|
|
193
|
+
|
|
194
|
+
The canonical flow state is a plain JavaScript object:
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
{
|
|
198
|
+
Nodes:
|
|
199
|
+
[
|
|
200
|
+
{
|
|
201
|
+
Hash: 'node-<UUID>',
|
|
202
|
+
Type: 'start',
|
|
203
|
+
X: 50, Y: 180,
|
|
204
|
+
Width: 140, Height: 80,
|
|
205
|
+
Title: 'Start',
|
|
206
|
+
Ports:
|
|
207
|
+
[
|
|
208
|
+
{
|
|
209
|
+
Hash: 'port-<UUID>',
|
|
210
|
+
Direction: 'output',
|
|
211
|
+
Side: 'right',
|
|
212
|
+
Label: 'Out',
|
|
213
|
+
PortType: 'event'
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
Data: {}
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
|
|
220
|
+
Connections:
|
|
221
|
+
[
|
|
222
|
+
{
|
|
223
|
+
Hash: 'conn-<UUID>',
|
|
224
|
+
SourceNodeHash: 'node-...',
|
|
225
|
+
SourcePortHash: 'port-...',
|
|
226
|
+
TargetNodeHash: 'node-...',
|
|
227
|
+
TargetPortHash: 'port-...',
|
|
228
|
+
Data:
|
|
229
|
+
{
|
|
230
|
+
LineMode: 'bezier',
|
|
231
|
+
HandleCustomized: false
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
|
|
236
|
+
OpenPanels:
|
|
237
|
+
[
|
|
238
|
+
{
|
|
239
|
+
Hash: 'panel-<UUID>',
|
|
240
|
+
NodeHash: 'node-...',
|
|
241
|
+
PanelType: 'Template',
|
|
242
|
+
Title: 'Properties',
|
|
243
|
+
X: 300, Y: 250,
|
|
244
|
+
Width: 300, Height: 200
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
|
|
248
|
+
SavedLayouts: [],
|
|
249
|
+
|
|
250
|
+
ViewState:
|
|
251
|
+
{
|
|
252
|
+
PanX: 0, PanY: 0,
|
|
253
|
+
Zoom: 1,
|
|
254
|
+
SelectedNodeHash: null,
|
|
255
|
+
SelectedConnectionHash: null,
|
|
256
|
+
SelectedTetherHash: null
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Service Initialization Sequence
|
|
262
|
+
|
|
263
|
+
When PictViewFlow initializes, it follows a declarative registry to instantiate all components:
|
|
264
|
+
|
|
265
|
+
```mermaid
|
|
266
|
+
sequenceDiagram
|
|
267
|
+
participant App as Application
|
|
268
|
+
participant FV as PictViewFlow
|
|
269
|
+
participant PR as Providers
|
|
270
|
+
participant SV as Services
|
|
271
|
+
participant VW as Child Views
|
|
272
|
+
|
|
273
|
+
App->>FV: new PictViewFlow(fable, options)
|
|
274
|
+
FV->>PR: Register & instantiate providers
|
|
275
|
+
Note over PR: SVGHelpers, Geometry, Noise (no FlowView ref)
|
|
276
|
+
Note over PR: Theme, CSS, Icons, NodeTypes, EventHandler, Layouts (with FlowView ref)
|
|
277
|
+
FV->>SV: Register & instantiate services
|
|
278
|
+
Note over SV: DataManager, RenderManager, SelectionManager, etc.
|
|
279
|
+
FV->>VW: Register & instantiate child views
|
|
280
|
+
Note over VW: Node, Toolbar, FloatingToolbar, PropertiesPanel
|
|
281
|
+
|
|
282
|
+
App->>FV: render()
|
|
283
|
+
FV->>SV: DataManager.marshalToView()
|
|
284
|
+
FV->>SV: RenderManager.renderFlow()
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Design Patterns
|
|
288
|
+
|
|
289
|
+
### Service Provider Pattern
|
|
290
|
+
|
|
291
|
+
Every service and provider extends `fable-serviceproviderbase` and registers with the Fable instance. This means any component can access any other through `this.fable` without explicit imports or singletons.
|
|
292
|
+
|
|
293
|
+
### Event-Driven Architecture
|
|
294
|
+
|
|
295
|
+
The `EventHandlerProvider` decouples application code from the flow internals. Services fire events; application code registers handlers. This avoids subclassing or monkey-patching to extend behavior.
|
|
296
|
+
|
|
297
|
+
### Data/View Separation
|
|
298
|
+
|
|
299
|
+
The flow data structure is completely separate from the SVG DOM. Mutations operate on the data model; the render manager regenerates the DOM from the model. This makes serialization, undo/redo, and server sync straightforward.
|
|
300
|
+
|
|
301
|
+
### Selective Re-rendering
|
|
302
|
+
|
|
303
|
+
Full re-renders are used when the graph topology changes (node added/removed, connection added/removed). During interactive operations like node dragging, only the affected elements (the dragged node and its connections) are updated for smooth performance.
|