pict-section-flow 1.4.0 → 2.0.0

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 (164) hide show
  1. package/package.json +7 -2
  2. package/source/Pict-Section-Flow.js +20 -14
  3. package/source/providers/PictProvider-Flow-Background.js +303 -0
  4. package/source/providers/PictProvider-Flow-CSS.js +73 -7
  5. package/source/providers/PictProvider-Flow-Geometry.js +11 -421
  6. package/source/providers/PictProvider-Flow-Icons.js +12 -0
  7. package/source/providers/PictProvider-Flow-Layouts.js +107 -0
  8. package/source/services/PictService-Flow-ConnectionRenderer.js +1 -1
  9. package/source/services/PictService-Flow-CursorManager.js +113 -0
  10. package/source/services/PictService-Flow-InteractionManager.js +439 -59
  11. package/source/services/PictService-Flow-Layout.js +21 -16
  12. package/source/services/PictService-Flow-PathGenerator.js +30 -417
  13. package/source/services/PictService-Flow-RenderManager.js +9 -1
  14. package/source/services/PictService-Flow-ViewportManager.js +102 -0
  15. package/source/views/PictView-Flow-FloatingToolbar.js +5 -1
  16. package/source/views/PictView-Flow-Node.js +29 -0
  17. package/source/views/PictView-Flow-Toolbar.js +50 -3
  18. package/source/views/PictView-Flow.js +591 -2
  19. package/.claude/launch.json +0 -11
  20. package/docs/.nojekyll +0 -0
  21. package/docs/Architecture.md +0 -163
  22. package/docs/Custom-Styling.md +0 -275
  23. package/docs/Data_Model.md +0 -149
  24. package/docs/Event_System.md +0 -156
  25. package/docs/Getting_Started.md +0 -237
  26. package/docs/Implementation_Reference.md +0 -528
  27. package/docs/Layout_Persistence.md +0 -117
  28. package/docs/README.md +0 -103
  29. package/docs/Theme_Integration.md +0 -150
  30. package/docs/_brand.json +0 -18
  31. package/docs/_cover.md +0 -17
  32. package/docs/_playground.json +0 -24
  33. package/docs/_sidebar.md +0 -57
  34. package/docs/_topbar.md +0 -8
  35. package/docs/_version.json +0 -7
  36. package/docs/api/PictFlowCard.md +0 -216
  37. package/docs/api/PictFlowCardPropertiesPanel.md +0 -235
  38. package/docs/api/addConnection.md +0 -101
  39. package/docs/api/addNode.md +0 -137
  40. package/docs/api/autoLayout.md +0 -77
  41. package/docs/api/getFlowData.md +0 -112
  42. package/docs/api/marshalToView.md +0 -95
  43. package/docs/api/openPanel.md +0 -128
  44. package/docs/api/registerHandler.md +0 -174
  45. package/docs/api/registerNodeType.md +0 -142
  46. package/docs/api/removeConnection.md +0 -57
  47. package/docs/api/removeNode.md +0 -80
  48. package/docs/api/saveLayout.md +0 -152
  49. package/docs/api/screenToSVGCoords.md +0 -68
  50. package/docs/api/selectNode.md +0 -116
  51. package/docs/api/setTheme.md +0 -168
  52. package/docs/api/setZoom.md +0 -97
  53. package/docs/api/toggleFullscreen.md +0 -68
  54. package/docs/card-help/EACH.md +0 -19
  55. package/docs/card-help/FREAD.md +0 -24
  56. package/docs/card-help/FWRITE.md +0 -24
  57. package/docs/card-help/GET.md +0 -22
  58. package/docs/card-help/ITE.md +0 -23
  59. package/docs/card-help/LOG.md +0 -23
  60. package/docs/card-help/NOTE.md +0 -17
  61. package/docs/card-help/PREV.md +0 -18
  62. package/docs/card-help/SET.md +0 -27
  63. package/docs/card-help/SPKL.md +0 -22
  64. package/docs/card-help/STAT.md +0 -23
  65. package/docs/card-help/SW.md +0 -25
  66. package/docs/diagrams/architecture-at-a-glance.excalidraw +0 -4270
  67. package/docs/diagrams/architecture-at-a-glance.mmd +0 -30
  68. package/docs/diagrams/architecture-at-a-glance.svg +0 -2
  69. package/docs/diagrams/data-flow.excalidraw +0 -1451
  70. package/docs/diagrams/data-flow.mmd +0 -17
  71. package/docs/diagrams/data-flow.svg +0 -2
  72. package/docs/diagrams/high-level-design.excalidraw +0 -5767
  73. package/docs/diagrams/high-level-design.mmd +0 -86
  74. package/docs/diagrams/high-level-design.svg +0 -2
  75. package/docs/diagrams/relationships.excalidraw +0 -3852
  76. package/docs/diagrams/relationships.mmd +0 -9
  77. package/docs/diagrams/relationships.svg +0 -2
  78. package/docs/diagrams/service-initialization-sequence.excalidraw +0 -1466
  79. package/docs/diagrams/service-initialization-sequence.mmd +0 -19
  80. package/docs/diagrams/service-initialization-sequence.svg +0 -2
  81. package/docs/diagrams/svg-layer-structure.excalidraw +0 -1060
  82. package/docs/diagrams/svg-layer-structure.mmd +0 -18
  83. package/docs/diagrams/svg-layer-structure.svg +0 -2
  84. package/docs/examples/README.md +0 -9
  85. package/docs/examples/simple_cards/README.md +0 -677
  86. package/docs/examples/simple_cards/css/flowexample.css +0 -65
  87. package/docs/examples/simple_cards/index.html +0 -32
  88. package/docs/examples/simple_cards/js/pict.min.js +0 -12
  89. package/docs/examples/simple_cards/pict-section-flow-example-simple-cards.compatible.min.js +0 -1
  90. package/docs/index.html +0 -38
  91. package/docs/playground/app.json +0 -6
  92. package/docs/playground/appdata.json +0 -85
  93. package/docs/playground/application.js +0 -23
  94. package/docs/playground/pict.json +0 -17
  95. package/docs/playground/runtime/pict-application.min.js +0 -2
  96. package/docs/playground/runtime/pict-section-flow.min.js +0 -2
  97. package/docs/playground/runtime/pict-section-modal.min.js +0 -2
  98. package/docs/playground/runtime/pict.min.js +0 -12
  99. package/docs/retold-catalog.json +0 -244
  100. package/docs/retold-keyword-index.json +0 -26028
  101. package/example_applications/simple_cards/css/flowexample.css +0 -65
  102. package/example_applications/simple_cards/html/index.html +0 -32
  103. package/example_applications/simple_cards/package.json +0 -52
  104. package/example_applications/simple_cards/source/Pict-Application-FlowExample-Configuration.json +0 -15
  105. package/example_applications/simple_cards/source/Pict-Application-FlowExample.js +0 -539
  106. package/example_applications/simple_cards/source/card-help-content.js +0 -16
  107. package/example_applications/simple_cards/source/cards/FlowCard-Comment.js +0 -38
  108. package/example_applications/simple_cards/source/cards/FlowCard-DataPreview.js +0 -44
  109. package/example_applications/simple_cards/source/cards/FlowCard-Each.js +0 -38
  110. package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +0 -56
  111. package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +0 -50
  112. package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +0 -37
  113. package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +0 -49
  114. package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +0 -55
  115. package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +0 -97
  116. package/example_applications/simple_cards/source/cards/FlowCard-Sparkline.js +0 -100
  117. package/example_applications/simple_cards/source/cards/FlowCard-StatusMonitor.js +0 -46
  118. package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +0 -39
  119. package/example_applications/simple_cards/source/providers/PictRouter-FlowExample-Configuration.json +0 -22
  120. package/example_applications/simple_cards/source/sample-flows.js +0 -410
  121. package/example_applications/simple_cards/source/views/PictView-FlowExample-About.js +0 -184
  122. package/example_applications/simple_cards/source/views/PictView-FlowExample-BottomBar.js +0 -77
  123. package/example_applications/simple_cards/source/views/PictView-FlowExample-Documentation.js +0 -325
  124. package/example_applications/simple_cards/source/views/PictView-FlowExample-FileWriteInfo.js +0 -59
  125. package/example_applications/simple_cards/source/views/PictView-FlowExample-Layout.js +0 -90
  126. package/example_applications/simple_cards/source/views/PictView-FlowExample-MainWorkspace.js +0 -453
  127. package/example_applications/simple_cards/source/views/PictView-FlowExample-TopBar.js +0 -95
  128. package/scripts/generate-card-help.js +0 -214
  129. package/source/providers/edges/Edge-Bezier.js +0 -41
  130. package/source/providers/edges/Edge-Orthogonal.js +0 -37
  131. package/source/providers/edges/Edge-OrthogonalSnap.js +0 -72
  132. package/source/providers/edges/Edge-Perimeter-Linear.js +0 -31
  133. package/source/providers/edges/Edge-Perimeter-Orthogonal.js +0 -39
  134. package/source/providers/edges/Edge-Perimeter.js +0 -48
  135. package/source/providers/edges/Edge-PerimeterMath.js +0 -92
  136. package/source/providers/edges/Edge-Straight.js +0 -24
  137. package/source/providers/layouts/Layout-Circular.js +0 -203
  138. package/source/providers/layouts/Layout-Coerce.js +0 -40
  139. package/source/providers/layouts/Layout-Columnar.js +0 -134
  140. package/source/providers/layouts/Layout-Custom.js +0 -27
  141. package/source/providers/layouts/Layout-ForcedFromCenter.js +0 -256
  142. package/source/providers/layouts/Layout-Grid.js +0 -134
  143. package/source/providers/layouts/Layout-Layered.js +0 -155
  144. package/source/providers/layouts/Layout-Rank.js +0 -141
  145. package/source/providers/layouts/Layout-Staggered.js +0 -131
  146. package/source/providers/layouts/Layout-Tabular.js +0 -94
  147. package/test/CardPalette_tests.js +0 -43
  148. package/test/ConnectionHandleManager_tests.js +0 -717
  149. package/test/ConnectionRenderer_tests.js +0 -591
  150. package/test/ConnectionStyle_tests.js +0 -90
  151. package/test/DataManager_tests.js +0 -859
  152. package/test/Geometry_tests.js +0 -767
  153. package/test/InteractionManager_tests.js +0 -279
  154. package/test/Layout_tests.js +0 -1604
  155. package/test/NodeView_tests.js +0 -66
  156. package/test/PanelManager_tests.js +0 -172
  157. package/test/PathGenerator_tests.js +0 -978
  158. package/test/PortRenderer_tests.js +0 -376
  159. package/test/RenderManager_tests.js +0 -756
  160. package/test/Renderer_tests.js +0 -133
  161. package/test/SelectionManager_tests.js +0 -185
  162. package/test/StylePresets_tests.js +0 -153
  163. package/test/ToolbarExtraButtons_tests.js +0 -138
  164. package/test/UndirectedConnections_tests.js +0 -70
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pict-section-flow",
3
- "version": "1.4.0",
3
+ "version": "2.0.0",
4
4
  "description": "Pict Section Flow Diagram",
5
5
  "main": "source/Pict-Section-Flow.js",
6
6
  "scripts": {
@@ -15,6 +15,8 @@
15
15
  "dependencies": {
16
16
  "fable-serviceproviderbase": "^3.0.19",
17
17
  "pict-provider": "^1.0.13",
18
+ "pict-provider-graphgeometry": "^1.0.0",
19
+ "pict-provider-graphlayout": "^1.0.0",
18
20
  "pict-section-form": "^1.0.199",
19
21
  "pict-view": "^1.0.68"
20
22
  },
@@ -25,5 +27,8 @@
25
27
  "pict-docuserve": "^1.4.4",
26
28
  "pict-router": "^1.0.10",
27
29
  "quackage": "^1.3.0"
28
- }
30
+ },
31
+ "files": [
32
+ "source"
33
+ ]
29
34
  }
@@ -35,30 +35,36 @@ module.exports.PictProviderFlowCSS = require('./providers/PictProvider-Flow-CSS.
35
35
  module.exports.PictProviderFlowIcons = require('./providers/PictProvider-Flow-Icons.js');
36
36
  module.exports.PictProviderFlowConnectorShapes = require('./providers/PictProvider-Flow-ConnectorShapes.js');
37
37
 
38
+ // Layout algorithm and edge-theme descriptors now live in the standalone
39
+ // pict-provider-graphlayout module. They are re-exported here unchanged so the
40
+ // historical pict-section-flow export surface (LayoutAlgorithms / EdgeThemes) is
41
+ // preserved for consumers.
42
+ const libPictProviderGraphLayout = require('pict-provider-graphlayout');
43
+
38
44
  // Layout algorithm descriptors (consumers can register custom algorithms via
39
45
  // _LayoutService.registerAlgorithm({ Name, Apply, DefaultParameters, ParameterSchema }))
40
46
  module.exports.LayoutAlgorithms =
41
47
  {
42
- Custom: require('./providers/layouts/Layout-Custom.js'),
43
- Layered: require('./providers/layouts/Layout-Layered.js'),
44
- ForcedFromCenter: require('./providers/layouts/Layout-ForcedFromCenter.js'),
45
- Grid: require('./providers/layouts/Layout-Grid.js'),
46
- Circular: require('./providers/layouts/Layout-Circular.js'),
47
- Tabular: require('./providers/layouts/Layout-Tabular.js'),
48
- Columnar: require('./providers/layouts/Layout-Columnar.js')
48
+ Custom: libPictProviderGraphLayout.Layouts.Custom,
49
+ Layered: libPictProviderGraphLayout.Layouts.Layered,
50
+ ForcedFromCenter: libPictProviderGraphLayout.Layouts.ForcedFromCenter,
51
+ Grid: libPictProviderGraphLayout.Layouts.Grid,
52
+ Circular: libPictProviderGraphLayout.Layouts.Circular,
53
+ Tabular: libPictProviderGraphLayout.Layouts.Tabular,
54
+ Columnar: libPictProviderGraphLayout.Layouts.Columnar
49
55
  };
50
56
 
51
57
  // Edge-theme descriptors (consumers can register custom edge themes via
52
58
  // _LayoutService.registerEdgeTheme({ Name, GeneratePath, AdjustLayout?, ResolveAttachment?, ... }))
53
59
  module.exports.EdgeThemes =
54
60
  {
55
- Bezier: require('./providers/edges/Edge-Bezier.js'),
56
- Orthogonal: require('./providers/edges/Edge-Orthogonal.js'),
57
- Straight: require('./providers/edges/Edge-Straight.js'),
58
- OrthogonalSnap: require('./providers/edges/Edge-OrthogonalSnap.js'),
59
- Perimeter: require('./providers/edges/Edge-Perimeter.js'),
60
- PerimeterLinear: require('./providers/edges/Edge-Perimeter-Linear.js'),
61
- PerimeterOrthogonal: require('./providers/edges/Edge-Perimeter-Orthogonal.js')
61
+ Bezier: libPictProviderGraphLayout.Edges.Bezier,
62
+ Orthogonal: libPictProviderGraphLayout.Edges.Orthogonal,
63
+ Straight: libPictProviderGraphLayout.Edges.Straight,
64
+ OrthogonalSnap: libPictProviderGraphLayout.Edges.OrthogonalSnap,
65
+ Perimeter: libPictProviderGraphLayout.Edges.Perimeter,
66
+ PerimeterLinear: libPictProviderGraphLayout.Edges.PerimeterLinear,
67
+ PerimeterOrthogonal: libPictProviderGraphLayout.Edges.PerimeterOrthogonal
62
68
  };
63
69
 
64
70
  // FlowCard base class
@@ -0,0 +1,303 @@
1
+ const libPictProvider = require('pict-provider');
2
+
3
+ /**
4
+ * PictProvider-Flow-Background
5
+ *
6
+ * Native canvas background for the flow diagram. The container template ships a
7
+ * default grid; this provider lets a host pick a background through config or
8
+ * ViewState instead of hand-painting the SVG from outside (which moodboard used
9
+ * to do). When no background is configured the provider is a no-op and the
10
+ * template grid stands, so existing diagrams are unchanged.
11
+ *
12
+ * Background shape:
13
+ * { Style: 'grid' | 'dots' | 'graph' | 'solid' | 'image' | 'none',
14
+ * Color?: string, // line / dot color (minor lines for 'graph')
15
+ * MajorColor?: string, // 'graph' only: the heavier every-Nth line color
16
+ * Paper?: string, // grid/dots/graph: solid fill painted behind the pattern
17
+ * Image?: string,
18
+ * GridSize?: number, // cell spacing (minor cell for 'graph')
19
+ * MajorEvery?: number, // 'graph' only: heavier line every N cells (default 10)
20
+ * DotSize?: number,
21
+ * LineWidth?: number, // grid/graph minor line width
22
+ * MajorLineWidth?: number } // 'graph' major line width
23
+ *
24
+ * Named presets (smaller / lighter / darker dots, grids, blue graph paper,
25
+ * blueprint, ...) live in PRESETS and are fetched with preset(name).
26
+ *
27
+ * The markup generators are pure (string in, string out) and unit tested; only
28
+ * apply() touches the DOM.
29
+ */
30
+ const _ProviderConfiguration =
31
+ {
32
+ ProviderIdentifier: 'PictProviderFlowBackground'
33
+ };
34
+
35
+ const _DEFAULT_GRID_SIZE = 20;
36
+ const _DEFAULT_DOT_SIZE = 2;
37
+ const _DEFAULT_DOT_FILL = 'var(--theme-color-text-secondary, #b0b0b0)';
38
+ const _DEFAULT_MAJOR_EVERY = 10;
39
+ // Concrete fallback line color for 'graph' (var() does not resolve in an SVG
40
+ // presentation attribute, and graph lines are drawn with stroke="...").
41
+ const _DEFAULT_GRID_LINE = '#cbd5e1';
42
+
43
+ // Named, ready-to-use backgrounds. preset(name) returns a fresh clone so callers
44
+ // can tweak one without mutating the catalog.
45
+ const _PRESETS =
46
+ {
47
+ 'dots': { Style: 'dots', GridSize: 20, DotSize: 2 },
48
+ 'dots-small': { Style: 'dots', GridSize: 14, DotSize: 1 },
49
+ 'dots-light': { Style: 'dots', GridSize: 20, DotSize: 2, Color: '#dcdcdc' },
50
+ 'dots-dark': { Style: 'dots', GridSize: 22, DotSize: 2.4, Color: '#64748b' },
51
+ 'grid': { Style: 'grid', GridSize: 20 },
52
+ 'grid-fine': { Style: 'grid', GridSize: 12, Color: '#e2e8f0' },
53
+ // "10-square grid with light and more-light-blue lines": minor light-blue lines
54
+ // every 16px, a heavier sky-blue line every 10 cells, on white paper.
55
+ 'graph-blue': { Style: 'graph', GridSize: 16, MajorEvery: 10, Color: '#dbeafe', MajorColor: '#93c5fd', LineWidth: 1, MajorLineWidth: 1.5, Paper: '#ffffff' },
56
+ // Classic dark blueprint: light-blue lines on deep navy paper.
57
+ 'blueprint': { Style: 'graph', GridSize: 16, MajorEvery: 10, Color: '#3b6ea5', MajorColor: '#6fa8dc', LineWidth: 1, MajorLineWidth: 1.5, Paper: '#0f2a4a' },
58
+ 'solid': { Style: 'solid', Color: '#faf7f2' },
59
+ 'none': { Style: 'none' }
60
+ };
61
+
62
+ class PictProviderFlowBackground extends libPictProvider
63
+ {
64
+ constructor(pFable, pOptions, pServiceHash)
65
+ {
66
+ let tmpOptions = Object.assign({}, _ProviderConfiguration, pOptions);
67
+ super(pFable, tmpOptions, pServiceHash);
68
+
69
+ this.serviceType = 'PictProviderFlowBackground';
70
+
71
+ this._FlowView = (pOptions && pOptions.FlowView) ? pOptions.FlowView : null;
72
+ }
73
+
74
+ /**
75
+ * The pattern element id for a view + style.
76
+ * @param {string} pViewIdentifier
77
+ * @param {string} pStyle
78
+ * @returns {string}
79
+ */
80
+ patternId(pViewIdentifier, pStyle)
81
+ {
82
+ return `flow-bg-${pStyle}-${pViewIdentifier}`;
83
+ }
84
+
85
+ /**
86
+ * Generate the <pattern> markup for grid/dots backgrounds. Returns '' for
87
+ * styles that need no pattern (solid, image, none) or when nothing is set.
88
+ * Pure.
89
+ * @param {string} pViewIdentifier
90
+ * @param {Object} pBackground
91
+ * @returns {string}
92
+ */
93
+ generatePatternMarkup(pViewIdentifier, pBackground)
94
+ {
95
+ if (!pBackground || !pBackground.Style)
96
+ {
97
+ return '';
98
+ }
99
+
100
+ // Optional solid fill painted behind the pattern (paper color). Empty unless set.
101
+ let tmpPaper = function (pW, pH)
102
+ {
103
+ return pBackground.Paper ? `<rect width="${pW}" height="${pH}" fill="${pBackground.Paper}" />` : '';
104
+ };
105
+
106
+ if (pBackground.Style === 'grid')
107
+ {
108
+ let tmpSize = (typeof pBackground.GridSize === 'number') ? pBackground.GridSize : _DEFAULT_GRID_SIZE;
109
+ // With no explicit Color the lines inherit the theme via the existing
110
+ // CSS class, matching the template grid; a Color overrides inline.
111
+ let tmpStroke = pBackground.Color ? ` style="stroke:${pBackground.Color}"` : '';
112
+ let tmpWidth = (typeof pBackground.LineWidth === 'number') ? ` stroke-width="${pBackground.LineWidth}"` : '';
113
+ let tmpId = this.patternId(pViewIdentifier, 'grid');
114
+ return `<pattern id="${tmpId}" width="${tmpSize}" height="${tmpSize}" patternUnits="userSpaceOnUse">`
115
+ + tmpPaper(tmpSize, tmpSize)
116
+ + `<line x1="${tmpSize}" y1="0" x2="${tmpSize}" y2="${tmpSize}" class="pict-flow-grid-pattern"${tmpStroke}${tmpWidth} />`
117
+ + `<line x1="0" y1="${tmpSize}" x2="${tmpSize}" y2="${tmpSize}" class="pict-flow-grid-pattern"${tmpStroke}${tmpWidth} />`
118
+ + `</pattern>`;
119
+ }
120
+
121
+ if (pBackground.Style === 'dots')
122
+ {
123
+ let tmpSize = (typeof pBackground.GridSize === 'number') ? pBackground.GridSize : _DEFAULT_GRID_SIZE;
124
+ let tmpDot = (typeof pBackground.DotSize === 'number') ? pBackground.DotSize : _DEFAULT_DOT_SIZE;
125
+ let tmpFill = pBackground.Color ? pBackground.Color : _DEFAULT_DOT_FILL;
126
+ let tmpId = this.patternId(pViewIdentifier, 'dots');
127
+ return `<pattern id="${tmpId}" width="${tmpSize}" height="${tmpSize}" patternUnits="userSpaceOnUse">`
128
+ + tmpPaper(tmpSize, tmpSize)
129
+ + `<circle cx="${tmpSize / 2}" cy="${tmpSize / 2}" r="${tmpDot}" fill="${tmpFill}" />`
130
+ + `</pattern>`;
131
+ }
132
+
133
+ if (pBackground.Style === 'graph')
134
+ {
135
+ // Graph paper: a fine minor grid tiled inside a heavier major grid drawn
136
+ // every MajorEvery cells. Two patterns — the major one fills itself with the
137
+ // minor pattern, then strokes the heavier lines on top.
138
+ let tmpMinor = (typeof pBackground.GridSize === 'number') ? pBackground.GridSize : _DEFAULT_GRID_SIZE;
139
+ let tmpMajorEvery = (typeof pBackground.MajorEvery === 'number') ? pBackground.MajorEvery : _DEFAULT_MAJOR_EVERY;
140
+ let tmpMajor = tmpMinor * tmpMajorEvery;
141
+ let tmpMinorColor = pBackground.Color || _DEFAULT_GRID_LINE;
142
+ let tmpMajorColor = pBackground.MajorColor || tmpMinorColor;
143
+ let tmpMinorWidth = (typeof pBackground.LineWidth === 'number') ? pBackground.LineWidth : 1;
144
+ let tmpMajorWidth = (typeof pBackground.MajorLineWidth === 'number') ? pBackground.MajorLineWidth : 1.5;
145
+ let tmpMinorId = this.patternId(pViewIdentifier, 'graph-minor');
146
+ let tmpId = this.patternId(pViewIdentifier, 'graph');
147
+
148
+ let tmpMinorPattern = `<pattern id="${tmpMinorId}" width="${tmpMinor}" height="${tmpMinor}" patternUnits="userSpaceOnUse">`
149
+ + `<line x1="${tmpMinor}" y1="0" x2="${tmpMinor}" y2="${tmpMinor}" stroke="${tmpMinorColor}" stroke-width="${tmpMinorWidth}" />`
150
+ + `<line x1="0" y1="${tmpMinor}" x2="${tmpMinor}" y2="${tmpMinor}" stroke="${tmpMinorColor}" stroke-width="${tmpMinorWidth}" />`
151
+ + `</pattern>`;
152
+ let tmpMajorPattern = `<pattern id="${tmpId}" width="${tmpMajor}" height="${tmpMajor}" patternUnits="userSpaceOnUse">`
153
+ + tmpPaper(tmpMajor, tmpMajor)
154
+ + `<rect width="${tmpMajor}" height="${tmpMajor}" fill="url(#${tmpMinorId})" />`
155
+ + `<line x1="${tmpMajor}" y1="0" x2="${tmpMajor}" y2="${tmpMajor}" stroke="${tmpMajorColor}" stroke-width="${tmpMajorWidth}" />`
156
+ + `<line x1="0" y1="${tmpMajor}" x2="${tmpMajor}" y2="${tmpMajor}" stroke="${tmpMajorColor}" stroke-width="${tmpMajorWidth}" />`
157
+ + `</pattern>`;
158
+ return tmpMinorPattern + tmpMajorPattern;
159
+ }
160
+
161
+ return '';
162
+ }
163
+
164
+ /**
165
+ * Resolve the fill value for the background rect. Pure.
166
+ * grid/dots -> url(#pattern); solid -> Color; image -> url(Image);
167
+ * none -> 'none'. Returns null when nothing is configured.
168
+ * @param {string} pViewIdentifier
169
+ * @param {Object} pBackground
170
+ * @returns {string|null}
171
+ */
172
+ resolveFill(pViewIdentifier, pBackground)
173
+ {
174
+ if (!pBackground || !pBackground.Style)
175
+ {
176
+ return null;
177
+ }
178
+
179
+ switch (pBackground.Style)
180
+ {
181
+ case 'grid': return `url(#${this.patternId(pViewIdentifier, 'grid')})`;
182
+ case 'dots': return `url(#${this.patternId(pViewIdentifier, 'dots')})`;
183
+ case 'graph': return `url(#${this.patternId(pViewIdentifier, 'graph')})`;
184
+ case 'solid': return pBackground.Color || 'transparent';
185
+ case 'image': return pBackground.Image ? `url(${pBackground.Image})` : 'none';
186
+ case 'none': return 'none';
187
+ default: return null;
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Resolve the effective background for a flow view: ViewState wins, then the
193
+ * static option. Returns null/false when none is configured.
194
+ * @param {Object} pFlowView
195
+ */
196
+ resolveBackground(pFlowView)
197
+ {
198
+ if (!pFlowView)
199
+ {
200
+ return null;
201
+ }
202
+ let tmpViewStateBackground = (pFlowView._FlowData && pFlowView._FlowData.ViewState)
203
+ ? pFlowView._FlowData.ViewState.Background
204
+ : null;
205
+ if (tmpViewStateBackground)
206
+ {
207
+ return tmpViewStateBackground;
208
+ }
209
+ return (pFlowView.options && pFlowView.options.Background) ? pFlowView.options.Background : null;
210
+ }
211
+
212
+ /**
213
+ * Fetch a named background preset as a fresh object (safe to tweak / store on
214
+ * ViewState). Unknown names return null.
215
+ * @param {string} pName
216
+ * @returns {Object|null}
217
+ */
218
+ preset(pName)
219
+ {
220
+ let tmpPreset = _PRESETS[pName];
221
+ return tmpPreset ? JSON.parse(JSON.stringify(tmpPreset)) : null;
222
+ }
223
+
224
+ /**
225
+ * The available preset names, in catalog order.
226
+ * @returns {string[]}
227
+ */
228
+ presetNames()
229
+ {
230
+ return Object.keys(_PRESETS);
231
+ }
232
+
233
+ /**
234
+ * Apply the configured background to the live SVG. No-op when nothing is
235
+ * configured (the template grid stands). DOM-touching; verified in browser.
236
+ * @param {Object} [pFlowView]
237
+ * @returns {boolean} true when a background was applied
238
+ */
239
+ apply(pFlowView)
240
+ {
241
+ let tmpFlowView = pFlowView || this._FlowView;
242
+ if (!tmpFlowView || !tmpFlowView._SVGElement)
243
+ {
244
+ return false;
245
+ }
246
+
247
+ let tmpBackground = this.resolveBackground(tmpFlowView);
248
+ if (!tmpBackground || !tmpBackground.Style)
249
+ {
250
+ return false;
251
+ }
252
+
253
+ let tmpViewIdentifier = tmpFlowView.options.ViewIdentifier;
254
+ let tmpSVG = tmpFlowView._SVGElement;
255
+
256
+ // Replace any pattern we previously injected, then add the new one.
257
+ let tmpDefs = tmpSVG.querySelector('defs');
258
+ if (tmpDefs)
259
+ {
260
+ let tmpOld = tmpDefs.querySelectorAll('[data-flow-bg-pattern]');
261
+ for (let i = 0; i < tmpOld.length; i++)
262
+ {
263
+ tmpOld[i].remove();
264
+ }
265
+ let tmpMarkup = this.generatePatternMarkup(tmpViewIdentifier, tmpBackground);
266
+ if (tmpMarkup)
267
+ {
268
+ let tmpScratch = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
269
+ tmpScratch.innerHTML = tmpMarkup;
270
+ while (tmpScratch.firstChild)
271
+ {
272
+ let tmpChild = tmpScratch.firstChild;
273
+ if (tmpChild.setAttribute)
274
+ {
275
+ tmpChild.setAttribute('data-flow-bg-pattern', 'true');
276
+ }
277
+ tmpDefs.appendChild(tmpChild);
278
+ }
279
+ }
280
+ }
281
+
282
+ let tmpFill = this.resolveFill(tmpViewIdentifier, tmpBackground);
283
+ let tmpRect = tmpSVG.querySelector('.pict-flow-grid-background');
284
+ if (tmpRect && tmpFill !== null)
285
+ {
286
+ tmpRect.setAttribute('fill', tmpFill);
287
+ }
288
+
289
+ // A solid color also tints the container behind the (transparent) rect.
290
+ let tmpContainer = (typeof tmpSVG.closest === 'function') ? tmpSVG.closest('.pict-flow-svg-container') : null;
291
+ if (tmpContainer)
292
+ {
293
+ tmpContainer.style.backgroundColor = (tmpBackground.Style === 'solid' && tmpBackground.Color) ? tmpBackground.Color : '';
294
+ }
295
+
296
+ return true;
297
+ }
298
+ }
299
+
300
+ module.exports = PictProviderFlowBackground;
301
+
302
+ module.exports.default_configuration = _ProviderConfiguration;
303
+ module.exports.PRESETS = _PRESETS;
@@ -205,16 +205,19 @@ class PictProviderFlowCSS extends libFableServiceProviderBase
205
205
  .pict-flow-svg {
206
206
  width: 100%;
207
207
  height: 100%;
208
- cursor: grab;
208
+ cursor: default;
209
209
  user-select: none;
210
210
  -webkit-user-select: none;
211
211
  }
212
- .pict-flow-svg.panning {
213
- cursor: grabbing;
214
- }
215
- .pict-flow-svg.connecting {
216
- cursor: crosshair;
217
- }
212
+ /* The canvas cursor is owned by the CursorManager: it sets data-flow-cursor
213
+ on the SVG from the interaction state + view mode, and these map the
214
+ tokens to real cursors. Element-scoped hover cursors (ports, handles,
215
+ panel chrome, toolbar buttons) still win for their own elements. */
216
+ .pict-flow-svg[data-flow-cursor="grab"] { cursor: grab; }
217
+ .pict-flow-svg[data-flow-cursor="grabbing"] { cursor: grabbing; }
218
+ .pict-flow-svg[data-flow-cursor="crosshair"] { cursor: crosshair; }
219
+ .pict-flow-svg[data-flow-cursor="resize"] { cursor: nwse-resize; }
220
+ .pict-flow-svg[data-flow-cursor="default"] { cursor: default; }
218
221
  .pict-flow-grid-pattern line {
219
222
  stroke: var(--pf-grid-stroke);
220
223
  stroke-width: 0.5;
@@ -1307,6 +1310,33 @@ class PictProviderFlowCSS extends libFableServiceProviderBase
1307
1310
  background-color: var(--pf-button-active-bg);
1308
1311
  border-color: var(--pf-button-hover-border);
1309
1312
  }
1313
+ /* Toggle-state LED: a status dot in the corner of a toggle button (one marked
1314
+ Toggle:true). Action buttons render no LED; a toggle shows an empty outline
1315
+ when off and a filled green dot when on (the .active class). Works on the
1316
+ docked and floating toolbars. */
1317
+ .pict-flow-toolbar-btn, .pict-flow-floating-btn {
1318
+ position: relative;
1319
+ }
1320
+ .pict-flow-toolbar-btn-led {
1321
+ display: none;
1322
+ position: absolute;
1323
+ right: 2px;
1324
+ bottom: 2px;
1325
+ width: 7px;
1326
+ height: 7px;
1327
+ box-sizing: border-box;
1328
+ border-radius: 50%;
1329
+ border: 1.5px solid var(--pf-button-border, #c2cad6);
1330
+ background: transparent;
1331
+ pointer-events: none;
1332
+ }
1333
+ .pict-flow-toolbar-btn-toggle .pict-flow-toolbar-btn-led {
1334
+ display: block;
1335
+ }
1336
+ .pict-flow-toolbar-btn-toggle.pict-flow-toolbar-btn-active .pict-flow-toolbar-btn-led {
1337
+ background: var(--theme-color-status-success, #27ae60);
1338
+ border-color: var(--theme-color-status-success, #27ae60);
1339
+ }
1310
1340
  /* An icon-only host button (ToolbarExtraButtons with no Label) renders an empty text span. */
1311
1341
  .pict-flow-toolbar-btn-text:empty {
1312
1342
  display: none;
@@ -2019,6 +2049,12 @@ class PictProviderFlowCSS extends libFableServiceProviderBase
2019
2049
  // Remove existing CSS first so we can re-register with updated theme overrides
2020
2050
  this.fable.CSSMap.removeCSS('PictSectionFlow-CSS');
2021
2051
  this.fable.CSSMap.addCSS('PictSectionFlow-CSS', this.generateCSS(), 500, 'PictProviderFlowCSS');
2052
+
2053
+ // Supplemental CSS (read-only chrome hiding + content frame), at a
2054
+ // priority above the base so the hides win.
2055
+ this.fable.CSSMap.removeCSS('PictSectionFlow-Supplemental-CSS');
2056
+ this.fable.CSSMap.addCSS('PictSectionFlow-Supplemental-CSS', this._supplementalCSS(), 502, 'PictProviderFlowCSS');
2057
+
2022
2058
  // Re-inject into the DOM to apply the updated CSS
2023
2059
  this.fable.CSSMap.injectCSS();
2024
2060
  }
@@ -2053,6 +2089,36 @@ class PictProviderFlowCSS extends libFableServiceProviderBase
2053
2089
  this.fable.CSSMap.addCSS('PictSectionFlow-Renderer-CSS', tmpCSS, 501, 'PictProviderFlowCSS');
2054
2090
  this.fable.CSSMap.injectCSS();
2055
2091
  }
2092
+
2093
+ /**
2094
+ * Supplemental CSS: hides editing chrome when the container carries the
2095
+ * 'pict-flow-readonly' class (set by PictView-Flow.setReadOnly), and styles
2096
+ * the content-frame rectangle. Replaces the ad-hoc CSS consumers (e.g.
2097
+ * moodboard) used to inject for a read-only look or a board frame.
2098
+ * @returns {string}
2099
+ */
2100
+ _supplementalCSS()
2101
+ {
2102
+ return /*css*/`
2103
+ .pict-flow-readonly .pict-flow-port,
2104
+ .pict-flow-readonly .pict-flow-port-hint,
2105
+ .pict-flow-readonly .pict-flow-node-resize-handle { display: none; }
2106
+ .pict-flow-readonly [data-flow-action="add-node"],
2107
+ .pict-flow-readonly [data-flow-action="delete-selected"],
2108
+ .pict-flow-readonly [data-flow-action="cards-popup"] { display: none; }
2109
+ .pict-flow-frame { fill: none; stroke: var(--theme-color-border, #9aa3ab); stroke-width: 1.5; stroke-dasharray: 8 6; pointer-events: none; }
2110
+ .pict-flow-frame-handle { fill: var(--theme-color-background-panel, #ffffff); stroke: var(--theme-color-brand-primary, #2e7d74); stroke-width: 1.5; }
2111
+ .pict-flow-frame-handle:hover { fill: var(--theme-color-brand-primary, #2e7d74); }
2112
+ .pict-flow-frame-handle-n, .pict-flow-frame-handle-s { cursor: ns-resize; }
2113
+ .pict-flow-frame-handle-e, .pict-flow-frame-handle-w { cursor: ew-resize; }
2114
+ .pict-flow-frame-move-handle { cursor: move; rx: 6; }
2115
+ .pict-flow-node-rotate-arm { stroke: var(--theme-color-brand-primary, #2e7d74); stroke-width: 1.5; }
2116
+ .pict-flow-node-rotate-handle { fill: var(--theme-color-background-panel, #ffffff); stroke: var(--theme-color-brand-primary, #2e7d74); stroke-width: 1.5; cursor: grab; }
2117
+ .pict-flow-node-rotate-handle:hover { fill: var(--theme-color-brand-primary, #2e7d74); }
2118
+ .pict-flow-readonly .pict-flow-node-rotate-arm,
2119
+ .pict-flow-readonly .pict-flow-node-rotate-handle { display: none; }
2120
+ `;
2121
+ }
2056
2122
  }
2057
2123
 
2058
2124
  module.exports = PictProviderFlowCSS;