pict-section-flow 1.0.0 → 1.0.1
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 +2 -2
- package/docs/index.html +0 -2
- package/package.json +3 -3
- package/source/PictFlowCard.js +2 -2
- package/source/providers/PictProvider-Flow-CSS.js +38 -12
- package/source/providers/PictProvider-Flow-ConnectorShapes.js +8 -8
- package/source/providers/PictProvider-Flow-Icons.js +33 -33
- package/source/providers/PictProvider-Flow-NodeTypes.js +9 -9
- package/source/providers/PictProvider-Flow-Renderer.js +516 -0
- package/source/providers/PictProvider-Flow-StylePresets.js +259 -0
- package/source/providers/PictProvider-Flow-Theme.js +97 -669
- package/source/services/PictService-Flow-ConnectionRenderer.js +6 -6
- package/source/services/PictService-Flow-PortRenderer.js +6 -6
- package/source/views/PictView-Flow-Node.js +1 -1
- package/source/views/PictView-Flow-PropertiesPanel.js +1 -1
- package/source/views/PictView-Flow-Toolbar.js +24 -16
- package/source/views/PictView-Flow.js +172 -47
- package/test/Renderer_tests.js +133 -0
- package/test/StylePresets_tests.js +153 -0
- package/docs/css/docuserve.css +0 -327
|
@@ -6,33 +6,39 @@ const _ProviderConfiguration =
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* PictProvider-Flow-Theme
|
|
9
|
+
* PictProvider-Flow-Theme — back-compat shim.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Flow's theming system was decomposed into three independent axes:
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* 1. **ColorTheme** — managed by pict-section-theme (the 7 `flow-*`
|
|
14
|
+
* bundled themes plus any other catalog entries).
|
|
15
|
+
* 2. **Renderer** — managed by PictProviderFlowRenderer (node body
|
|
16
|
+
* mode, bracket config, noise config, connection stroke,
|
|
17
|
+
* shape overrides, geometry CSS).
|
|
18
|
+
* 3. **EdgeTheme** — managed by PictService-Flow-Layout's edge themes
|
|
19
|
+
* (Bezier, Straight, Orthogonal, Perimeter…).
|
|
15
20
|
*
|
|
16
|
-
*
|
|
21
|
+
* The user-facing concept of "Theme" maps to a **StylePreset** —
|
|
22
|
+
* a curated triple `(ColorTheme, Renderer, EdgeTheme)` — registered
|
|
23
|
+
* with PictProviderFlowStylePresets.
|
|
17
24
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* ```
|
|
25
|
+
* This shim preserves the legacy API surface (`setTheme`, `getNoiseLevel`,
|
|
26
|
+
* `setNoiseLevel`, `processPathString`, `getNodeNoiseAmplitude`,
|
|
27
|
+
* `getActiveTheme`, `getActiveThemeKey`, `getThemeKeys`, `registerTheme`)
|
|
28
|
+
* so consumer code calling the old methods keeps working unmodified.
|
|
23
29
|
*
|
|
24
|
-
*
|
|
30
|
+
* Every method here delegates to the appropriate new provider — most
|
|
31
|
+
* commonly the Renderer provider (for noise + geometry) or the
|
|
32
|
+
* StylePresets provider (for `setTheme`/`getActiveThemeKey`).
|
|
25
33
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* flowView.setTheme('custom');
|
|
35
|
-
* ```
|
|
34
|
+
* New code should use the per-axis APIs directly:
|
|
35
|
+
*
|
|
36
|
+
* ```javascript
|
|
37
|
+
* flowView.setStylePreset('sketch'); // primary
|
|
38
|
+
* flowView.setColorTheme('flow-blueprint');
|
|
39
|
+
* flowView.setRenderer('bracket');
|
|
40
|
+
* flowView.setEdgeTheme('orthogonal');
|
|
41
|
+
* ```
|
|
36
42
|
*/
|
|
37
43
|
class PictProviderFlowTheme extends libFableServiceProviderBase
|
|
38
44
|
{
|
|
@@ -44,709 +50,131 @@ class PictProviderFlowTheme extends libFableServiceProviderBase
|
|
|
44
50
|
this.serviceType = 'PictProviderFlowTheme';
|
|
45
51
|
|
|
46
52
|
this._FlowView = (pOptions && pOptions.FlowView) ? pOptions.FlowView : null;
|
|
47
|
-
|
|
48
|
-
this._ActiveThemeKey = 'default';
|
|
49
|
-
this._NoiseLevel = 0;
|
|
50
|
-
this._Themes = {};
|
|
51
|
-
|
|
52
|
-
this._registerBuiltInThemes();
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// ──
|
|
55
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
_renderer()
|
|
58
58
|
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
Key: 'default',
|
|
63
|
-
Label: 'Modern',
|
|
64
|
-
CSSVariables: {},
|
|
65
|
-
AdditionalCSS: '',
|
|
66
|
-
NodeBodyMode: 'rect',
|
|
67
|
-
BracketConfig: null,
|
|
68
|
-
ConnectionConfig:
|
|
69
|
-
{
|
|
70
|
-
StrokeDashArray: null,
|
|
71
|
-
StrokeWidth: 2,
|
|
72
|
-
ArrowheadStyle: 'triangle'
|
|
73
|
-
},
|
|
74
|
-
NoiseConfig:
|
|
75
|
-
{
|
|
76
|
-
Enabled: false,
|
|
77
|
-
DefaultLevel: 0,
|
|
78
|
-
MaxJitterPx: 0,
|
|
79
|
-
AffectsNodes: false,
|
|
80
|
-
AffectsConnections: false
|
|
81
|
-
},
|
|
82
|
-
ShapeOverrides: {}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// ── 2. Sketch (Hand-drawn) ───────────────────────────────────
|
|
86
|
-
this._Themes['sketch'] =
|
|
87
|
-
{
|
|
88
|
-
Key: 'sketch',
|
|
89
|
-
Label: 'Sketch',
|
|
90
|
-
CSSVariables:
|
|
91
|
-
{
|
|
92
|
-
'--pf-node-body-fill': '#fffef5',
|
|
93
|
-
'--pf-node-body-stroke': '#444444',
|
|
94
|
-
'--pf-node-body-stroke-width': '1.5',
|
|
95
|
-
'--pf-node-body-radius': '0px',
|
|
96
|
-
'--pf-node-shadow': 'none',
|
|
97
|
-
'--pf-node-shadow-hover': 'none',
|
|
98
|
-
'--pf-node-shadow-selected': 'none',
|
|
99
|
-
'--pf-node-shadow-dragging': 'none',
|
|
100
|
-
'--pf-node-title-fill': '#333333',
|
|
101
|
-
'--pf-node-title-size': '12px',
|
|
102
|
-
'--pf-node-title-weight': '400',
|
|
103
|
-
'--pf-node-title-bar-color': '#f0ece0',
|
|
104
|
-
'--pf-node-type-label-fill': '#888888',
|
|
105
|
-
'--pf-node-selected-stroke': '#2255aa',
|
|
106
|
-
'--pf-port-input-fill': '#5577bb',
|
|
107
|
-
'--pf-port-output-fill': '#55aa77',
|
|
108
|
-
'--pf-port-stroke': '#fffef5',
|
|
109
|
-
'--pf-connection-stroke': '#555555',
|
|
110
|
-
'--pf-connection-selected-stroke': '#2255aa',
|
|
111
|
-
'--pf-canvas-bg': '#fffef5',
|
|
112
|
-
'--pf-grid-stroke': '#e8e4d8',
|
|
113
|
-
'--pf-panel-bg': '#fffef5',
|
|
114
|
-
'--pf-panel-border': '#ccccaa',
|
|
115
|
-
'--pf-panel-radius': '0px',
|
|
116
|
-
'--pf-panel-shadow': '2px 2px 0px rgba(0,0,0,0.08)',
|
|
117
|
-
'--pf-panel-titlebar-bg': '#f0ece0',
|
|
118
|
-
'--pf-panel-titlebar-border': '#ccccaa',
|
|
119
|
-
'--pf-panel-title-color': '#333333'
|
|
120
|
-
},
|
|
121
|
-
AdditionalCSS: `
|
|
122
|
-
.pict-flow-node-title,
|
|
123
|
-
.pict-flow-node-type-label,
|
|
124
|
-
.pict-flow-port-label,
|
|
125
|
-
.pict-flow-node-card-code {
|
|
126
|
-
font-family: "Courier New", "Courier", monospace !important;
|
|
127
|
-
}
|
|
128
|
-
.pict-flow-panel-title-text,
|
|
129
|
-
.pict-flow-panel-node-props-title,
|
|
130
|
-
.pict-flow-info-panel {
|
|
131
|
-
font-family: "Courier New", "Courier", monospace !important;
|
|
132
|
-
}
|
|
133
|
-
.pict-flow-node-title-icon {
|
|
134
|
-
filter: brightness(0) !important;
|
|
135
|
-
}
|
|
136
|
-
`,
|
|
137
|
-
NodeBodyMode: 'bracket',
|
|
138
|
-
BracketConfig:
|
|
139
|
-
{
|
|
140
|
-
SerifLength: 20,
|
|
141
|
-
TitleSeparator: true
|
|
142
|
-
},
|
|
143
|
-
ConnectionConfig:
|
|
144
|
-
{
|
|
145
|
-
StrokeDashArray: null,
|
|
146
|
-
StrokeWidth: 1.5,
|
|
147
|
-
ArrowheadStyle: 'triangle'
|
|
148
|
-
},
|
|
149
|
-
NoiseConfig:
|
|
150
|
-
{
|
|
151
|
-
Enabled: true,
|
|
152
|
-
DefaultLevel: 0.4,
|
|
153
|
-
MaxJitterPx: 4,
|
|
154
|
-
AffectsNodes: true,
|
|
155
|
-
AffectsConnections: true
|
|
156
|
-
},
|
|
157
|
-
ShapeOverrides:
|
|
158
|
-
{
|
|
159
|
-
'arrowhead-connection': { Fill: '#555555' },
|
|
160
|
-
'arrowhead-connection-selected': { Fill: '#2255aa' }
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
// ── 3. Blueprint (Technical) ─────────────────────────────────
|
|
165
|
-
this._Themes['blueprint'] =
|
|
166
|
-
{
|
|
167
|
-
Key: 'blueprint',
|
|
168
|
-
Label: 'Blueprint',
|
|
169
|
-
CSSVariables:
|
|
170
|
-
{
|
|
171
|
-
'--pf-node-body-fill': 'rgba(255,255,255,0.05)',
|
|
172
|
-
'--pf-node-body-stroke': '#ffffff',
|
|
173
|
-
'--pf-node-body-stroke-width': '1',
|
|
174
|
-
'--pf-node-body-radius': '0px',
|
|
175
|
-
'--pf-node-shadow': 'none',
|
|
176
|
-
'--pf-node-shadow-hover': 'none',
|
|
177
|
-
'--pf-node-shadow-selected': 'none',
|
|
178
|
-
'--pf-node-shadow-dragging': 'none',
|
|
179
|
-
'--pf-node-title-fill': '#ffffff',
|
|
180
|
-
'--pf-node-title-size': '11px',
|
|
181
|
-
'--pf-node-title-weight': '400',
|
|
182
|
-
'--pf-node-title-bar-color': 'rgba(255,255,255,0.1)',
|
|
183
|
-
'--pf-node-type-label-fill': 'rgba(255,255,255,0.5)',
|
|
184
|
-
'--pf-node-selected-stroke': '#ffdd44',
|
|
185
|
-
'--pf-port-input-fill': '#88bbff',
|
|
186
|
-
'--pf-port-output-fill': '#88ffbb',
|
|
187
|
-
'--pf-port-stroke': '#1a3a6a',
|
|
188
|
-
'--pf-connection-stroke': 'rgba(255,255,255,0.6)',
|
|
189
|
-
'--pf-connection-selected-stroke': '#ffdd44',
|
|
190
|
-
'--pf-canvas-bg': '#1a3a6a',
|
|
191
|
-
'--pf-grid-stroke': 'rgba(255,255,255,0.08)',
|
|
192
|
-
'--pf-panel-bg': '#1a3a6a',
|
|
193
|
-
'--pf-panel-border': 'rgba(255,255,255,0.3)',
|
|
194
|
-
'--pf-panel-radius': '0px',
|
|
195
|
-
'--pf-panel-shadow': 'none',
|
|
196
|
-
'--pf-panel-titlebar-bg': 'rgba(255,255,255,0.05)',
|
|
197
|
-
'--pf-panel-titlebar-border': 'rgba(255,255,255,0.15)',
|
|
198
|
-
'--pf-panel-title-color': '#ffffff'
|
|
199
|
-
},
|
|
200
|
-
AdditionalCSS: `
|
|
201
|
-
.pict-flow-node-title,
|
|
202
|
-
.pict-flow-node-type-label,
|
|
203
|
-
.pict-flow-port-label,
|
|
204
|
-
.pict-flow-node-card-code {
|
|
205
|
-
font-family: "Courier New", monospace !important;
|
|
206
|
-
text-transform: uppercase;
|
|
207
|
-
letter-spacing: 1px;
|
|
208
|
-
}
|
|
209
|
-
.pict-flow-container {
|
|
210
|
-
border-color: #0d2244;
|
|
211
|
-
}
|
|
212
|
-
.pict-flow-node-title-icon {
|
|
213
|
-
filter: brightness(0) invert(1) !important;
|
|
214
|
-
}
|
|
215
|
-
.pict-flow-toolbar {
|
|
216
|
-
background-color: #142e54;
|
|
217
|
-
border-bottom-color: rgba(255,255,255,0.15);
|
|
218
|
-
}
|
|
219
|
-
.pict-flow-toolbar-btn {
|
|
220
|
-
background-color: rgba(255,255,255,0.05);
|
|
221
|
-
border-color: rgba(255,255,255,0.2);
|
|
222
|
-
color: var(--theme-color-background-panel, #ffffff);
|
|
223
|
-
}
|
|
224
|
-
.pict-flow-toolbar-btn:hover {
|
|
225
|
-
background-color: rgba(255,255,255,0.1);
|
|
226
|
-
}
|
|
227
|
-
`,
|
|
228
|
-
NodeBodyMode: 'bracket',
|
|
229
|
-
BracketConfig:
|
|
230
|
-
{
|
|
231
|
-
SerifLength: 18,
|
|
232
|
-
TitleSeparator: true
|
|
233
|
-
},
|
|
234
|
-
ConnectionConfig:
|
|
235
|
-
{
|
|
236
|
-
StrokeDashArray: '8 4',
|
|
237
|
-
StrokeWidth: 1,
|
|
238
|
-
ArrowheadStyle: 'triangle'
|
|
239
|
-
},
|
|
240
|
-
NoiseConfig:
|
|
241
|
-
{
|
|
242
|
-
Enabled: false,
|
|
243
|
-
DefaultLevel: 0,
|
|
244
|
-
MaxJitterPx: 0,
|
|
245
|
-
AffectsNodes: false,
|
|
246
|
-
AffectsConnections: false
|
|
247
|
-
},
|
|
248
|
-
ShapeOverrides:
|
|
249
|
-
{
|
|
250
|
-
'arrowhead-connection': { Fill: 'rgba(255,255,255,0.6)' },
|
|
251
|
-
'arrowhead-connection-selected': { Fill: '#ffdd44' }
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
// ── 4. Mono (Black & White) ──────────────────────────────────
|
|
256
|
-
this._Themes['mono'] =
|
|
257
|
-
{
|
|
258
|
-
Key: 'mono',
|
|
259
|
-
Label: 'Monochrome',
|
|
260
|
-
CSSVariables:
|
|
261
|
-
{
|
|
262
|
-
'--pf-node-body-fill': '#ffffff',
|
|
263
|
-
'--pf-node-body-stroke': '#000000',
|
|
264
|
-
'--pf-node-body-stroke-width': '1',
|
|
265
|
-
'--pf-node-body-radius': '0px',
|
|
266
|
-
'--pf-node-shadow': 'none',
|
|
267
|
-
'--pf-node-shadow-hover': 'none',
|
|
268
|
-
'--pf-node-shadow-selected': 'none',
|
|
269
|
-
'--pf-node-shadow-dragging': 'none',
|
|
270
|
-
'--pf-node-title-fill': '#ffffff',
|
|
271
|
-
'--pf-node-title-size': '11px',
|
|
272
|
-
'--pf-node-title-weight': '600',
|
|
273
|
-
'--pf-node-title-bar-color': '#000000',
|
|
274
|
-
'--pf-node-type-label-fill': '#888888',
|
|
275
|
-
'--pf-node-selected-stroke': '#444444',
|
|
276
|
-
'--pf-port-input-fill': '#000000',
|
|
277
|
-
'--pf-port-output-fill': '#666666',
|
|
278
|
-
'--pf-port-stroke': '#ffffff',
|
|
279
|
-
'--pf-connection-stroke': '#000000',
|
|
280
|
-
'--pf-connection-selected-stroke': '#444444',
|
|
281
|
-
'--pf-canvas-bg': '#ffffff',
|
|
282
|
-
'--pf-grid-stroke': '#eeeeee',
|
|
283
|
-
'--pf-panel-bg': '#ffffff',
|
|
284
|
-
'--pf-panel-border': '#000000',
|
|
285
|
-
'--pf-panel-radius': '0px',
|
|
286
|
-
'--pf-panel-shadow': 'none',
|
|
287
|
-
'--pf-panel-titlebar-bg': '#f0f0f0',
|
|
288
|
-
'--pf-panel-titlebar-border': '#000000',
|
|
289
|
-
'--pf-panel-title-color': '#000000'
|
|
290
|
-
},
|
|
291
|
-
AdditionalCSS: `
|
|
292
|
-
.pict-flow-node-title {
|
|
293
|
-
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
|
294
|
-
}
|
|
295
|
-
.pict-flow-node-title-icon {
|
|
296
|
-
filter: brightness(0) invert(1) !important;
|
|
297
|
-
}
|
|
298
|
-
`,
|
|
299
|
-
NodeBodyMode: 'rect',
|
|
300
|
-
BracketConfig: null,
|
|
301
|
-
ConnectionConfig:
|
|
302
|
-
{
|
|
303
|
-
StrokeDashArray: null,
|
|
304
|
-
StrokeWidth: 1,
|
|
305
|
-
ArrowheadStyle: 'triangle'
|
|
306
|
-
},
|
|
307
|
-
NoiseConfig:
|
|
308
|
-
{
|
|
309
|
-
Enabled: false,
|
|
310
|
-
DefaultLevel: 0,
|
|
311
|
-
MaxJitterPx: 0,
|
|
312
|
-
AffectsNodes: false,
|
|
313
|
-
AffectsConnections: false
|
|
314
|
-
},
|
|
315
|
-
ShapeOverrides:
|
|
316
|
-
{
|
|
317
|
-
'arrowhead-connection': { Fill: '#000000' },
|
|
318
|
-
'arrowhead-connection-selected': { Fill: '#444444' }
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
// ── 5. Retro 80s (Neon) ──────────────────────────────────────
|
|
323
|
-
this._Themes['retro-80s'] =
|
|
324
|
-
{
|
|
325
|
-
Key: 'retro-80s',
|
|
326
|
-
Label: '80s Retro',
|
|
327
|
-
CSSVariables:
|
|
328
|
-
{
|
|
329
|
-
'--pf-node-body-fill': '#1a0a2e',
|
|
330
|
-
'--pf-node-body-stroke': '#ff00ff',
|
|
331
|
-
'--pf-node-body-stroke-width': '2',
|
|
332
|
-
'--pf-node-body-radius': '0px',
|
|
333
|
-
'--pf-node-shadow': 'drop-shadow(0 0 8px rgba(255,0,255,0.4))',
|
|
334
|
-
'--pf-node-shadow-hover': 'drop-shadow(0 0 12px rgba(255,0,255,0.6))',
|
|
335
|
-
'--pf-node-shadow-selected': 'drop-shadow(0 0 16px rgba(0,255,255,0.5))',
|
|
336
|
-
'--pf-node-shadow-dragging': 'drop-shadow(0 0 20px rgba(255,0,255,0.7))',
|
|
337
|
-
'--pf-node-title-fill': '#00ffff',
|
|
338
|
-
'--pf-node-title-size': '11px',
|
|
339
|
-
'--pf-node-title-weight': '700',
|
|
340
|
-
'--pf-node-title-bar-color': '#2a0a4e',
|
|
341
|
-
'--pf-node-type-label-fill': '#ff66ff',
|
|
342
|
-
'--pf-node-selected-stroke': '#00ffff',
|
|
343
|
-
'--pf-port-input-fill': '#ff00ff',
|
|
344
|
-
'--pf-port-output-fill': '#00ff66',
|
|
345
|
-
'--pf-port-stroke': '#1a0a2e',
|
|
346
|
-
'--pf-connection-stroke': '#ff00ff',
|
|
347
|
-
'--pf-connection-selected-stroke': '#00ffff',
|
|
348
|
-
'--pf-canvas-bg': '#0a0015',
|
|
349
|
-
'--pf-grid-stroke': '#1a0a2e',
|
|
350
|
-
'--pf-panel-bg': '#1a0a2e',
|
|
351
|
-
'--pf-panel-border': '#ff00ff',
|
|
352
|
-
'--pf-panel-radius': '0px',
|
|
353
|
-
'--pf-panel-shadow': '0 0 20px rgba(255,0,255,0.3)',
|
|
354
|
-
'--pf-panel-titlebar-bg': '#2a0a4e',
|
|
355
|
-
'--pf-panel-titlebar-border': '#ff00ff',
|
|
356
|
-
'--pf-panel-title-color': '#00ffff'
|
|
357
|
-
},
|
|
358
|
-
AdditionalCSS: `
|
|
359
|
-
.pict-flow-node-title,
|
|
360
|
-
.pict-flow-node-type-label,
|
|
361
|
-
.pict-flow-port-label,
|
|
362
|
-
.pict-flow-node-card-code {
|
|
363
|
-
font-family: "Courier New", monospace !important;
|
|
364
|
-
text-transform: uppercase;
|
|
365
|
-
letter-spacing: 0.5px;
|
|
366
|
-
}
|
|
367
|
-
.pict-flow-connection {
|
|
368
|
-
filter: drop-shadow(0 0 3px rgba(255,0,255,0.4));
|
|
369
|
-
}
|
|
370
|
-
.pict-flow-node-title-icon {
|
|
371
|
-
filter: brightness(0) invert(1) hue-rotate(180deg) !important;
|
|
372
|
-
}
|
|
373
|
-
.pict-flow-toolbar {
|
|
374
|
-
background-color: #1a0a2e;
|
|
375
|
-
border-bottom-color: #ff00ff;
|
|
376
|
-
}
|
|
377
|
-
.pict-flow-toolbar-btn {
|
|
378
|
-
background-color: #1a0a2e;
|
|
379
|
-
border-color: #ff00ff;
|
|
380
|
-
color: #00ffff;
|
|
381
|
-
}
|
|
382
|
-
.pict-flow-toolbar-btn:hover {
|
|
383
|
-
background-color: #2a0a4e;
|
|
384
|
-
}
|
|
385
|
-
.pict-flow-container {
|
|
386
|
-
border-color: #ff00ff;
|
|
387
|
-
}
|
|
388
|
-
`,
|
|
389
|
-
NodeBodyMode: 'rect',
|
|
390
|
-
BracketConfig: null,
|
|
391
|
-
ConnectionConfig:
|
|
392
|
-
{
|
|
393
|
-
StrokeDashArray: null,
|
|
394
|
-
StrokeWidth: 2,
|
|
395
|
-
ArrowheadStyle: 'triangle'
|
|
396
|
-
},
|
|
397
|
-
NoiseConfig:
|
|
398
|
-
{
|
|
399
|
-
Enabled: false,
|
|
400
|
-
DefaultLevel: 0,
|
|
401
|
-
MaxJitterPx: 0,
|
|
402
|
-
AffectsNodes: false,
|
|
403
|
-
AffectsConnections: false
|
|
404
|
-
},
|
|
405
|
-
ShapeOverrides:
|
|
406
|
-
{
|
|
407
|
-
'arrowhead-connection': { Fill: '#ff00ff' },
|
|
408
|
-
'arrowhead-connection-selected': { Fill: '#00ffff' }
|
|
409
|
-
}
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
// ── 6. Retro 90s (Windows) ───────────────────────────────────
|
|
413
|
-
this._Themes['retro-90s'] =
|
|
414
|
-
{
|
|
415
|
-
Key: 'retro-90s',
|
|
416
|
-
Label: '90s Retro',
|
|
417
|
-
CSSVariables:
|
|
418
|
-
{
|
|
419
|
-
'--pf-node-body-fill': '#c0c0c0',
|
|
420
|
-
'--pf-node-body-stroke': '#808080',
|
|
421
|
-
'--pf-node-body-stroke-width': '1',
|
|
422
|
-
'--pf-node-body-radius': '0px',
|
|
423
|
-
'--pf-node-shadow': 'drop-shadow(2px 2px 0px #404040)',
|
|
424
|
-
'--pf-node-shadow-hover': 'drop-shadow(3px 3px 0px #404040)',
|
|
425
|
-
'--pf-node-shadow-selected': 'drop-shadow(2px 2px 0px #008080)',
|
|
426
|
-
'--pf-node-shadow-dragging': 'drop-shadow(4px 4px 0px #404040)',
|
|
427
|
-
'--pf-node-title-fill': '#ffffff',
|
|
428
|
-
'--pf-node-title-size': '11px',
|
|
429
|
-
'--pf-node-title-weight': '700',
|
|
430
|
-
'--pf-node-title-bar-color': '#000080',
|
|
431
|
-
'--pf-node-type-label-fill': '#606060',
|
|
432
|
-
'--pf-node-selected-stroke': '#008080',
|
|
433
|
-
'--pf-port-input-fill': '#000080',
|
|
434
|
-
'--pf-port-output-fill': '#008000',
|
|
435
|
-
'--pf-port-stroke': '#c0c0c0',
|
|
436
|
-
'--pf-connection-stroke': '#808080',
|
|
437
|
-
'--pf-connection-selected-stroke': '#008080',
|
|
438
|
-
'--pf-canvas-bg': '#008080',
|
|
439
|
-
'--pf-grid-stroke': 'rgba(0,0,0,0.06)',
|
|
440
|
-
'--pf-panel-bg': '#c0c0c0',
|
|
441
|
-
'--pf-panel-border': '#808080',
|
|
442
|
-
'--pf-panel-radius': '0px',
|
|
443
|
-
'--pf-panel-shadow': '2px 2px 0px #404040',
|
|
444
|
-
'--pf-panel-titlebar-bg': '#000080',
|
|
445
|
-
'--pf-panel-titlebar-border': '#c0c0c0',
|
|
446
|
-
'--pf-panel-title-color': '#ffffff'
|
|
447
|
-
},
|
|
448
|
-
AdditionalCSS: `
|
|
449
|
-
.pict-flow-node-title,
|
|
450
|
-
.pict-flow-node-type-label,
|
|
451
|
-
.pict-flow-port-label,
|
|
452
|
-
.pict-flow-node-card-code {
|
|
453
|
-
font-family: "MS Sans Serif", "Arial", sans-serif !important;
|
|
454
|
-
}
|
|
455
|
-
.pict-flow-node-title-icon {
|
|
456
|
-
filter: brightness(0) invert(1) !important;
|
|
457
|
-
}
|
|
458
|
-
.pict-flow-toolbar {
|
|
459
|
-
background-color: #c0c0c0;
|
|
460
|
-
border-bottom: 2px solid #808080;
|
|
461
|
-
border-top: 1px solid var(--theme-color-background-panel, #ffffff);
|
|
462
|
-
}
|
|
463
|
-
.pict-flow-toolbar-btn {
|
|
464
|
-
background-color: #c0c0c0;
|
|
465
|
-
border: 2px outset #c0c0c0;
|
|
466
|
-
border-radius: 0;
|
|
467
|
-
color: var(--theme-color-text-primary, #000000);
|
|
468
|
-
}
|
|
469
|
-
.pict-flow-toolbar-btn:hover {
|
|
470
|
-
background-color: var(--theme-color-border-default, #d0d0d0);
|
|
471
|
-
}
|
|
472
|
-
.pict-flow-toolbar-btn:active {
|
|
473
|
-
border-style: inset;
|
|
474
|
-
}
|
|
475
|
-
.pict-flow-container {
|
|
476
|
-
border: 2px outset #c0c0c0;
|
|
477
|
-
border-radius: 0;
|
|
478
|
-
}
|
|
479
|
-
`,
|
|
480
|
-
NodeBodyMode: 'rect',
|
|
481
|
-
BracketConfig: null,
|
|
482
|
-
ConnectionConfig:
|
|
483
|
-
{
|
|
484
|
-
StrokeDashArray: null,
|
|
485
|
-
StrokeWidth: 2,
|
|
486
|
-
ArrowheadStyle: 'triangle'
|
|
487
|
-
},
|
|
488
|
-
NoiseConfig:
|
|
489
|
-
{
|
|
490
|
-
Enabled: false,
|
|
491
|
-
DefaultLevel: 0,
|
|
492
|
-
MaxJitterPx: 0,
|
|
493
|
-
AffectsNodes: false,
|
|
494
|
-
AffectsConnections: false
|
|
495
|
-
},
|
|
496
|
-
ShapeOverrides:
|
|
497
|
-
{
|
|
498
|
-
'arrowhead-connection': { Fill: '#808080' },
|
|
499
|
-
'arrowhead-connection-selected': { Fill: '#008080' }
|
|
500
|
-
}
|
|
501
|
-
};
|
|
59
|
+
return (this._FlowView && this._FlowView._RendererProvider) || null;
|
|
60
|
+
}
|
|
502
61
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
Key: 'whiteboard',
|
|
507
|
-
Label: 'Whiteboard',
|
|
508
|
-
CSSVariables:
|
|
509
|
-
{
|
|
510
|
-
'--pf-node-body-fill': 'transparent',
|
|
511
|
-
'--pf-node-body-stroke': '#555555',
|
|
512
|
-
'--pf-node-body-stroke-width': '2',
|
|
513
|
-
'--pf-node-body-radius': '0px',
|
|
514
|
-
'--pf-node-shadow': 'none',
|
|
515
|
-
'--pf-node-shadow-hover': 'none',
|
|
516
|
-
'--pf-node-shadow-selected': 'none',
|
|
517
|
-
'--pf-node-shadow-dragging': 'none',
|
|
518
|
-
'--pf-node-title-fill': '#333333',
|
|
519
|
-
'--pf-node-title-size': '12px',
|
|
520
|
-
'--pf-node-title-weight': '600',
|
|
521
|
-
'--pf-node-title-bar-color': 'transparent',
|
|
522
|
-
'--pf-node-type-label-fill': '#999999',
|
|
523
|
-
'--pf-node-selected-stroke': '#2255aa',
|
|
524
|
-
'--pf-port-input-fill': '#5577bb',
|
|
525
|
-
'--pf-port-output-fill': '#55aa77',
|
|
526
|
-
'--pf-port-stroke': '#ffffff',
|
|
527
|
-
'--pf-connection-stroke': '#888888',
|
|
528
|
-
'--pf-connection-selected-stroke': '#2255aa',
|
|
529
|
-
'--pf-canvas-bg': '#ffffff',
|
|
530
|
-
'--pf-grid-stroke': '#f0f0f0',
|
|
531
|
-
'--pf-panel-bg': '#ffffff',
|
|
532
|
-
'--pf-panel-border': '#cccccc',
|
|
533
|
-
'--pf-panel-radius': '0px',
|
|
534
|
-
'--pf-panel-shadow': '2px 2px 0px rgba(0,0,0,0.06)',
|
|
535
|
-
'--pf-panel-titlebar-bg': '#f8f8f8',
|
|
536
|
-
'--pf-panel-titlebar-border': '#e0e0e0',
|
|
537
|
-
'--pf-panel-title-color': '#333333'
|
|
538
|
-
},
|
|
539
|
-
AdditionalCSS: `
|
|
540
|
-
.pict-flow-node-title,
|
|
541
|
-
.pict-flow-node-type-label,
|
|
542
|
-
.pict-flow-port-label,
|
|
543
|
-
.pict-flow-node-card-code {
|
|
544
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
545
|
-
}
|
|
546
|
-
/* Node-type bracket colors — each type gets its own bracket color */
|
|
547
|
-
.pict-flow-node-start .pict-flow-node-bracket { stroke: var(--theme-color-status-success, #27ae60); }
|
|
548
|
-
.pict-flow-node-end .pict-flow-node-bracket { stroke: #1abc9c; }
|
|
549
|
-
.pict-flow-node-halt .pict-flow-node-bracket { stroke: var(--theme-color-status-error, #e74c3c); }
|
|
550
|
-
.pict-flow-node-decision .pict-flow-node-bracket { stroke: var(--theme-color-status-warning, #f39c12); }
|
|
551
|
-
.pict-flow-node-default .pict-flow-node-bracket { stroke: #3498db; }
|
|
552
|
-
.pict-flow-node-action .pict-flow-node-bracket { stroke: #2c3e50; }
|
|
553
|
-
/* Override variant rules: no fills/strokes on body rects in whiteboard */
|
|
554
|
-
.pict-flow-node-decision .pict-flow-node-body,
|
|
555
|
-
.pict-flow-node-start .pict-flow-node-body,
|
|
556
|
-
.pict-flow-node-end .pict-flow-node-body,
|
|
557
|
-
.pict-flow-node-halt .pict-flow-node-body {
|
|
558
|
-
fill: transparent;
|
|
559
|
-
stroke: transparent;
|
|
560
|
-
stroke-width: 0;
|
|
561
|
-
}
|
|
562
|
-
/* Title bar fills transparent too */
|
|
563
|
-
.pict-flow-node .pict-flow-node-bracket-title-fill {
|
|
564
|
-
fill: transparent !important;
|
|
565
|
-
}
|
|
566
|
-
.pict-flow-node-title-icon {
|
|
567
|
-
filter: none !important;
|
|
568
|
-
}
|
|
569
|
-
`,
|
|
570
|
-
NodeBodyMode: 'bracket',
|
|
571
|
-
BracketConfig:
|
|
572
|
-
{
|
|
573
|
-
SerifLength: 22,
|
|
574
|
-
TitleSeparator: false
|
|
575
|
-
},
|
|
576
|
-
ConnectionConfig:
|
|
577
|
-
{
|
|
578
|
-
StrokeDashArray: null,
|
|
579
|
-
StrokeWidth: 1.5,
|
|
580
|
-
ArrowheadStyle: 'triangle'
|
|
581
|
-
},
|
|
582
|
-
NoiseConfig:
|
|
583
|
-
{
|
|
584
|
-
Enabled: true,
|
|
585
|
-
DefaultLevel: 0.3,
|
|
586
|
-
MaxJitterPx: 3,
|
|
587
|
-
AffectsNodes: true,
|
|
588
|
-
AffectsConnections: true
|
|
589
|
-
},
|
|
590
|
-
ShapeOverrides:
|
|
591
|
-
{
|
|
592
|
-
'arrowhead-connection': { Fill: '#888888' },
|
|
593
|
-
'arrowhead-connection-selected': { Fill: '#2255aa' }
|
|
594
|
-
}
|
|
595
|
-
};
|
|
62
|
+
_presets()
|
|
63
|
+
{
|
|
64
|
+
return (this._FlowView && this._FlowView._StylePresetsProvider) || null;
|
|
596
65
|
}
|
|
597
66
|
|
|
598
|
-
// ──
|
|
67
|
+
// ── Compat API ────────────────────────────────────────────────────────
|
|
599
68
|
|
|
600
69
|
/**
|
|
601
|
-
*
|
|
70
|
+
* Compat: get the active style preset's "theme-shaped" view. Returns
|
|
71
|
+
* a synthetic object that exposes the legacy properties (NoiseConfig,
|
|
72
|
+
* NodeBodyMode, etc.) by pulling from the active renderer.
|
|
602
73
|
* @returns {Object}
|
|
603
74
|
*/
|
|
604
75
|
getActiveTheme()
|
|
605
76
|
{
|
|
606
|
-
|
|
77
|
+
let tmpRenderer = this._renderer();
|
|
78
|
+
let tmpPresets = this._presets();
|
|
79
|
+
let tmpPresetHash = tmpPresets ? tmpPresets.getActivePresetHash() : null;
|
|
80
|
+
let tmpR = tmpRenderer ? tmpRenderer.getActiveRenderer() : {};
|
|
81
|
+
return {
|
|
82
|
+
Key: tmpPresetHash || tmpR.Key || 'modern',
|
|
83
|
+
Label: tmpR.Label || 'Modern',
|
|
84
|
+
NodeBodyMode: tmpR.NodeBodyMode,
|
|
85
|
+
BracketConfig: tmpR.BracketConfig,
|
|
86
|
+
NoiseConfig: tmpR.NoiseConfig,
|
|
87
|
+
ConnectionConfig: tmpR.ConnectionConfig,
|
|
88
|
+
ShapeOverrides: tmpR.ShapeOverrides
|
|
89
|
+
};
|
|
607
90
|
}
|
|
608
91
|
|
|
609
92
|
/**
|
|
610
|
-
*
|
|
93
|
+
* Compat: active style preset hash (or, if customized, the active renderer key).
|
|
611
94
|
* @returns {string}
|
|
612
95
|
*/
|
|
613
96
|
getActiveThemeKey()
|
|
614
97
|
{
|
|
615
|
-
|
|
98
|
+
let tmpPresets = this._presets();
|
|
99
|
+
let tmpHash = tmpPresets ? tmpPresets.getActivePresetHash() : null;
|
|
100
|
+
if (tmpHash) return tmpHash;
|
|
101
|
+
let tmpRenderer = this._renderer();
|
|
102
|
+
return tmpRenderer ? tmpRenderer.getActiveRendererKey() : 'modern';
|
|
616
103
|
}
|
|
617
104
|
|
|
618
105
|
/**
|
|
619
|
-
*
|
|
620
|
-
* This updates the internal key and applies shape overrides.
|
|
621
|
-
* The caller (FlowView.setTheme) is responsible for re-registering
|
|
622
|
-
* CSS and triggering a full re-render.
|
|
623
|
-
*
|
|
106
|
+
* Compat: pass through to StylePresets.applyPreset.
|
|
624
107
|
* @param {string} pThemeKey
|
|
625
|
-
* @returns {boolean}
|
|
108
|
+
* @returns {boolean}
|
|
626
109
|
*/
|
|
627
110
|
setTheme(pThemeKey)
|
|
628
111
|
{
|
|
629
|
-
|
|
112
|
+
let tmpPresets = this._presets();
|
|
113
|
+
if (!tmpPresets)
|
|
630
114
|
{
|
|
631
|
-
this.log.warn(
|
|
115
|
+
this.log.warn('PictProviderFlowTheme: setTheme() called but StylePresets provider not available');
|
|
632
116
|
return false;
|
|
633
117
|
}
|
|
634
|
-
|
|
635
|
-
this._ActiveThemeKey = pThemeKey;
|
|
636
|
-
let tmpTheme = this._Themes[pThemeKey];
|
|
637
|
-
|
|
638
|
-
// Apply noise defaults from theme
|
|
639
|
-
if (tmpTheme.NoiseConfig && typeof tmpTheme.NoiseConfig.DefaultLevel === 'number')
|
|
640
|
-
{
|
|
641
|
-
this._NoiseLevel = tmpTheme.NoiseConfig.DefaultLevel;
|
|
642
|
-
}
|
|
643
|
-
else
|
|
644
|
-
{
|
|
645
|
-
this._NoiseLevel = 0;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// Apply shape overrides
|
|
649
|
-
if (this._FlowView && this._FlowView._ConnectorShapesProvider)
|
|
650
|
-
{
|
|
651
|
-
this._FlowView._ConnectorShapesProvider.resetToDefaults();
|
|
652
|
-
if (tmpTheme.ShapeOverrides && Object.keys(tmpTheme.ShapeOverrides).length > 0)
|
|
653
|
-
{
|
|
654
|
-
this._FlowView._ConnectorShapesProvider.applyThemeOverrides(tmpTheme.ShapeOverrides);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
this.log.trace(`PictProviderFlowTheme: switched to '${pThemeKey}'`);
|
|
659
|
-
return true;
|
|
118
|
+
return tmpPresets.applyPreset(pThemeKey);
|
|
660
119
|
}
|
|
661
120
|
|
|
662
121
|
/**
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
* Set the noise level (0 to 1).
|
|
673
|
-
* @param {number} pLevel
|
|
674
|
-
*/
|
|
675
|
-
setNoiseLevel(pLevel)
|
|
676
|
-
{
|
|
677
|
-
this._NoiseLevel = Math.max(0, Math.min(1, pLevel || 0));
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* Register a custom theme.
|
|
122
|
+
* Compat: register a "theme" — translates to a style preset registration.
|
|
123
|
+
* The legacy shape (CSSVariables / NodeBodyMode / NoiseConfig) is no
|
|
124
|
+
* longer supported wholesale; callers wanting full custom looks should
|
|
125
|
+
* register a Renderer and (optionally) a ColorTheme and StylePreset
|
|
126
|
+
* separately. This shim accepts a minimal preset-style payload:
|
|
127
|
+
* { Hash, Label?, ColorTheme, Renderer, EdgeTheme, NoiseLevel? }
|
|
682
128
|
* @param {string} pKey
|
|
683
|
-
* @param {Object}
|
|
129
|
+
* @param {Object} pDef
|
|
684
130
|
*/
|
|
685
|
-
registerTheme(pKey,
|
|
131
|
+
registerTheme(pKey, pDef)
|
|
686
132
|
{
|
|
687
|
-
|
|
133
|
+
let tmpPresets = this._presets();
|
|
134
|
+
if (!tmpPresets || !pKey || !pDef)
|
|
688
135
|
{
|
|
689
|
-
this.log.warn('PictProviderFlowTheme: registerTheme requires key and definition');
|
|
136
|
+
this.log.warn('PictProviderFlowTheme: registerTheme requires StylePresets provider, a key, and a definition');
|
|
690
137
|
return;
|
|
691
138
|
}
|
|
692
|
-
|
|
693
|
-
|
|
139
|
+
let tmpPreset = Object.assign({}, pDef, { Hash: pKey });
|
|
140
|
+
tmpPresets.register(tmpPreset);
|
|
694
141
|
}
|
|
695
142
|
|
|
696
143
|
/**
|
|
697
|
-
*
|
|
144
|
+
* Compat: list registered preset hashes.
|
|
698
145
|
* @returns {Array<string>}
|
|
699
146
|
*/
|
|
700
147
|
getThemeKeys()
|
|
701
148
|
{
|
|
702
|
-
|
|
149
|
+
let tmpPresets = this._presets();
|
|
150
|
+
return tmpPresets ? tmpPresets.getPresetHashes() : [];
|
|
703
151
|
}
|
|
704
152
|
|
|
705
|
-
// ──
|
|
153
|
+
// ── Noise + path delegations (preserved verbatim API) ─────────────────
|
|
706
154
|
|
|
707
|
-
|
|
708
|
-
* Post-process an SVG path string to apply noise/jitter if the
|
|
709
|
-
* active theme has noise enabled for connections.
|
|
710
|
-
*
|
|
711
|
-
* @param {string} pPathString - SVG path d attribute
|
|
712
|
-
* @param {string} pSeedString - Hash for deterministic noise
|
|
713
|
-
* @returns {string} Possibly-modified path string
|
|
714
|
-
*/
|
|
715
|
-
processPathString(pPathString, pSeedString)
|
|
155
|
+
getNoiseLevel()
|
|
716
156
|
{
|
|
717
|
-
let
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
return pPathString;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
let tmpAmplitude = this._NoiseLevel * (tmpTheme.NoiseConfig.MaxJitterPx || 3);
|
|
724
|
-
if (tmpAmplitude <= 0)
|
|
725
|
-
{
|
|
726
|
-
return pPathString;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
if (this._FlowView && this._FlowView._NoiseProvider)
|
|
730
|
-
{
|
|
731
|
-
return this._FlowView._NoiseProvider.jitterPath(pPathString, tmpAmplitude, pSeedString);
|
|
732
|
-
}
|
|
157
|
+
let tmpRenderer = this._renderer();
|
|
158
|
+
return tmpRenderer ? tmpRenderer.getNoiseLevel() : 0;
|
|
159
|
+
}
|
|
733
160
|
|
|
734
|
-
|
|
161
|
+
setNoiseLevel(pLevel)
|
|
162
|
+
{
|
|
163
|
+
let tmpRenderer = this._renderer();
|
|
164
|
+
if (tmpRenderer) tmpRenderer.setNoiseLevel(pLevel);
|
|
735
165
|
}
|
|
736
166
|
|
|
737
|
-
/**
|
|
738
|
-
* Get the noise amplitude for node bracket rendering.
|
|
739
|
-
* Returns 0 if noise is not enabled for nodes in the active theme.
|
|
740
|
-
* @returns {number}
|
|
741
|
-
*/
|
|
742
167
|
getNodeNoiseAmplitude()
|
|
743
168
|
{
|
|
744
|
-
let
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
169
|
+
let tmpRenderer = this._renderer();
|
|
170
|
+
return tmpRenderer ? tmpRenderer.getNodeNoiseAmplitude() : 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
processPathString(pPathString, pSeedString)
|
|
174
|
+
{
|
|
175
|
+
let tmpRenderer = this._renderer();
|
|
176
|
+
if (!tmpRenderer) return pPathString;
|
|
177
|
+
return tmpRenderer.processPathString(pPathString, pSeedString);
|
|
750
178
|
}
|
|
751
179
|
}
|
|
752
180
|
|