@peter.prib/renderengine 0.0.0-stage → 0.2.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 (451) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -2
  3. package/REFERENCE.md +2198 -0
  4. package/dist/renderengine-workspace.umd.js +46905 -0
  5. package/dist/renderengine.umd.js +42223 -0
  6. package/examples/archimate.html +66 -0
  7. package/examples/diagram-editor.html +51 -0
  8. package/package.json +65 -4
  9. package/src/BaseRenderer.js +57 -0
  10. package/src/CanvasRenderer.js +194 -0
  11. package/src/Mat4.js +111 -0
  12. package/src/OrbitCamera.js +57 -0
  13. package/src/RendererFactory.js +50 -0
  14. package/src/SVGRenderer.js +439 -0
  15. package/src/archimate.js +723 -0
  16. package/src/archimateArchiFormat.js +1693 -0
  17. package/src/archimateArchiTypes.js +72 -0
  18. package/src/archimateArchive.js +140 -0
  19. package/src/archimateCSV.js +127 -0
  20. package/src/archimateDrawio.js +182 -0
  21. package/src/archimateExchangeFormat.js +546 -0
  22. package/src/archimateRelationshipTable.js +93 -0
  23. package/src/archimateSpecializations.js +161 -0
  24. package/src/chartCatalog.js +589 -0
  25. package/src/charting/ArchimateDiagramEditor.js +1624 -0
  26. package/src/charting/ArchimateSpecializationSelector.js +134 -0
  27. package/src/charting/Axis.js +68 -0
  28. package/src/charting/CameraSeeder.js +30 -0
  29. package/src/charting/CatalogDialog.js +92 -0
  30. package/src/charting/Chart.js +37 -0
  31. package/src/charting/Chart3D.js +99 -0
  32. package/src/charting/ChartBox.js +80 -0
  33. package/src/charting/ChartData.js +27 -0
  34. package/src/charting/ChartRegistry.js +76 -0
  35. package/src/charting/CheckboxTreeSelector.js +304 -0
  36. package/src/charting/ColorField.js +107 -0
  37. package/src/charting/ColorPalette.js +88 -0
  38. package/src/charting/CommandHistory.js +176 -0
  39. package/src/charting/DataFilter.js +52 -0
  40. package/src/charting/Diagram.js +36 -0
  41. package/src/charting/Diagram3D.js +29 -0
  42. package/src/charting/DiagramClipboard.js +31 -0
  43. package/src/charting/DiagramEditor.js +3330 -0
  44. package/src/charting/DiagramEditorCommand.js +110 -0
  45. package/src/charting/DiagramEditorCommands.js +237 -0
  46. package/src/charting/DiagramEditorEdgeCommands.js +142 -0
  47. package/src/charting/DiagramEditorState.js +98 -0
  48. package/src/charting/DiagramRegistry.js +86 -0
  49. package/src/charting/DiagramTypeRegistry.js +326 -0
  50. package/src/charting/DiagramViewPropertiesDialog.js +46 -0
  51. package/src/charting/Edge.js +113 -0
  52. package/src/charting/ErrorBars.js +37 -0
  53. package/src/charting/FilterSystem.js +285 -0
  54. package/src/charting/FindReplaceDialog.js +139 -0
  55. package/src/charting/FormDialog.js +385 -0
  56. package/src/charting/Gauge.js +58 -0
  57. package/src/charting/Hierarchy.js +175 -0
  58. package/src/charting/HintPanel.js +86 -0
  59. package/src/charting/ImageSelector.js +148 -0
  60. package/src/charting/InteractionManager.js +725 -0
  61. package/src/charting/Legend.js +58 -0
  62. package/src/charting/MenuBar.js +62 -0
  63. package/src/charting/ModelFileFormat.js +115 -0
  64. package/src/charting/OrbitControls.js +77 -0
  65. package/src/charting/Palette.js +119 -0
  66. package/src/charting/PopupMenu.js +117 -0
  67. package/src/charting/PropertiesPanel.js +155 -0
  68. package/src/charting/PropertyListEditor.js +96 -0
  69. package/src/charting/PropertyLog.js +92 -0
  70. package/src/charting/SettingsCascade.js +93 -0
  71. package/src/charting/SettingsDialog.js +53 -0
  72. package/src/charting/SettingsManager.js +179 -0
  73. package/src/charting/SettingsViewPropertiesDialog.js +58 -0
  74. package/src/charting/ShapePaths.js +27 -0
  75. package/src/charting/Statistics.js +134 -0
  76. package/src/charting/TemplateCatalog.js +59 -0
  77. package/src/charting/TemplateLibrary.js +103 -0
  78. package/src/charting/TextStyle.js +168 -0
  79. package/src/charting/ViewFit.js +55 -0
  80. package/src/charting/ViewMenu.js +70 -0
  81. package/src/charting/ViewPropertiesDialog.js +77 -0
  82. package/src/charting/ViewTabStrip.js +81 -0
  83. package/src/charting/archimate/ArchiFileFormat.js +32 -0
  84. package/src/charting/archimate/ArchimateCanvasEditor.js +815 -0
  85. package/src/charting/archimate/ArchimateCsvFileFormat.js +35 -0
  86. package/src/charting/archimate/ArchimateEdge.js +137 -0
  87. package/src/charting/archimate/ArchimateElementTemplate.js +195 -0
  88. package/src/charting/archimate/ArchimatePalette.js +102 -0
  89. package/src/charting/archimate/CsvImportDialog.js +105 -0
  90. package/src/charting/archimate/CustomViewpoints.js +74 -0
  91. package/src/charting/archimate/DerivedEdge.js +29 -0
  92. package/src/charting/archimate/DrawioFileFormat.js +24 -0
  93. package/src/charting/archimate/ElementFilterRule.js +21 -0
  94. package/src/charting/archimate/ExchangeFileFormat.js +28 -0
  95. package/src/charting/archimate/ViewGroupTemplate.js +137 -0
  96. package/src/charting/archimate/ViewLineEdge.js +84 -0
  97. package/src/charting/archimate/ViewpointRule.js +45 -0
  98. package/src/charting/archimate/archimateFileFormats.js +12 -0
  99. package/src/charting/archimate/archimateNames.js +5 -0
  100. package/src/charting/archimate/csvMapping.js +122 -0
  101. package/src/charting/archimate/elementMenuItems.js +32 -0
  102. package/src/charting/archimate/elementProperties.js +146 -0
  103. package/src/charting/archimate/elementTypeChoices.js +7 -0
  104. package/src/charting/archimate/elementTypeGroups.js +19 -0
  105. package/src/charting/archimate/index.js +17 -0
  106. package/src/charting/archimate/specializationCatalogDialog.js +64 -0
  107. package/src/charting/archimate/typeGlyph.js +29 -0
  108. package/src/charting/arrangement/Arrangement.js +112 -0
  109. package/src/charting/arrangement/ArrangementCommand.js +29 -0
  110. package/src/charting/arrangement/BackgroundCommand.js +41 -0
  111. package/src/charting/arrangement/BackgroundGroup.js +18 -0
  112. package/src/charting/arrangement/GroupCommand.js +46 -0
  113. package/src/charting/arrangement/ItemGroup.js +62 -0
  114. package/src/charting/arrangement/LockCommand.js +32 -0
  115. package/src/charting/arrangement/UngroupCommand.js +27 -0
  116. package/src/charting/arrangement/alignment.js +88 -0
  117. package/src/charting/arrangement/arrangeMenuItems.js +25 -0
  118. package/src/charting/arrangement/index.js +11 -0
  119. package/src/charting/arrangement/layouts.js +233 -0
  120. package/src/charting/canvas/ArchiHint.js +78 -0
  121. package/src/charting/canvas/CanvasBoxKind.js +39 -0
  122. package/src/charting/canvas/CanvasPalette.js +49 -0
  123. package/src/charting/canvas/CanvasTemplateLibrary.js +61 -0
  124. package/src/charting/canvas/CanvasTemplateMenu.js +151 -0
  125. package/src/charting/canvas/EditHintCommand.js +28 -0
  126. package/src/charting/canvas/canvasBoxKinds.js +27 -0
  127. package/src/charting/canvas/canvasBoxMenuItems.js +40 -0
  128. package/src/charting/canvas/defaultCanvasTemplates.js +186 -0
  129. package/src/charting/canvas/diagramBoxKinds.js +12 -0
  130. package/src/charting/canvas/hintMenuItems.js +49 -0
  131. package/src/charting/charts/ArcGauge.js +55 -0
  132. package/src/charting/charts/AreaChart.js +71 -0
  133. package/src/charting/charts/BarChart.js +80 -0
  134. package/src/charting/charts/BarChart3D.js +56 -0
  135. package/src/charting/charts/BarChart3DOrbit.js +53 -0
  136. package/src/charting/charts/BarChartBase.js +70 -0
  137. package/src/charting/charts/BarGauge.js +42 -0
  138. package/src/charting/charts/BoxPlotChart.js +41 -0
  139. package/src/charting/charts/BubbleChart.js +99 -0
  140. package/src/charting/charts/BubbleChart3D.js +78 -0
  141. package/src/charting/charts/BulletGauge.js +87 -0
  142. package/src/charting/charts/CalendarHeatmapChart.js +204 -0
  143. package/src/charting/charts/CandlestickChart.js +54 -0
  144. package/src/charting/charts/ChordDiagram.js +130 -0
  145. package/src/charting/charts/DensityChart.js +73 -0
  146. package/src/charting/charts/DialGauge.js +65 -0
  147. package/src/charting/charts/DonutChart.js +15 -0
  148. package/src/charting/charts/FunnelChart.js +47 -0
  149. package/src/charting/charts/GanttChart.js +201 -0
  150. package/src/charting/charts/GaugeChart.js +175 -0
  151. package/src/charting/charts/GeoMapChart.js +146 -0
  152. package/src/charting/charts/GroupedBarChart.js +88 -0
  153. package/src/charting/charts/GroupedDistributionChart.js +70 -0
  154. package/src/charting/charts/HeatmapChart.js +80 -0
  155. package/src/charting/charts/HierarchyChart.js +39 -0
  156. package/src/charting/charts/HistogramChart.js +45 -0
  157. package/src/charting/charts/KpiTile.js +72 -0
  158. package/src/charting/charts/LagPlotChart.js +41 -0
  159. package/src/charting/charts/LineChart.js +124 -0
  160. package/src/charting/charts/MultiRingGauge.js +54 -0
  161. package/src/charting/charts/OutlineChart.js +95 -0
  162. package/src/charting/charts/ParallelCoordinatesChart.js +130 -0
  163. package/src/charting/charts/PieChart.js +56 -0
  164. package/src/charting/charts/PipeChart.js +88 -0
  165. package/src/charting/charts/PopulationPyramidChart.js +106 -0
  166. package/src/charting/charts/QQPlotChart.js +64 -0
  167. package/src/charting/charts/RadarChart.js +76 -0
  168. package/src/charting/charts/RadialBarChart.js +96 -0
  169. package/src/charting/charts/RingGauge.js +23 -0
  170. package/src/charting/charts/SankeyDiagram.js +174 -0
  171. package/src/charting/charts/ScatterChart.js +104 -0
  172. package/src/charting/charts/StackedAreaChart.js +15 -0
  173. package/src/charting/charts/StackedBarChart.js +33 -0
  174. package/src/charting/charts/StackedBarChart3DOrbit.js +58 -0
  175. package/src/charting/charts/StreamGraphChart.js +131 -0
  176. package/src/charting/charts/SunburstChart.js +57 -0
  177. package/src/charting/charts/ThermometerGauge.js +43 -0
  178. package/src/charting/charts/TreemapChart.js +54 -0
  179. package/src/charting/charts/ViolinChart.js +37 -0
  180. package/src/charting/charts/WaterfallChart.js +66 -0
  181. package/src/charting/charts/WordCloudChart.js +104 -0
  182. package/src/charting/diagramModel/AddViewCommand.js +33 -0
  183. package/src/charting/diagramModel/DiagramModel.js +39 -0
  184. package/src/charting/diagramModel/DiagramModelSearch.js +22 -0
  185. package/src/charting/diagramModel/DiagramView.js +50 -0
  186. package/src/charting/diagramModel/ModelHistory.js +43 -0
  187. package/src/charting/diagramModel/ModelReport.js +153 -0
  188. package/src/charting/diagramModel/ModelSearch.js +223 -0
  189. package/src/charting/diagramModel/RemoveViewCommand.js +25 -0
  190. package/src/charting/diagramModel/RenameViewCommand.js +21 -0
  191. package/src/charting/diagramModel/ReplaceTextCommand.js +25 -0
  192. package/src/charting/diagramModel/ViewSetChecker.js +34 -0
  193. package/src/charting/diagramModel/ViewSetModel.js +243 -0
  194. package/src/charting/diagramModel/index.js +6 -0
  195. package/src/charting/diagramModel/nameTransforms.js +29 -0
  196. package/src/charting/diagrams/ArchimateCommands.js +141 -0
  197. package/src/charting/diagrams/ArchimateDiagram.js +263 -0
  198. package/src/charting/diagrams/ArchimateModel.js +1155 -0
  199. package/src/charting/diagrams/ArchimateModelChecker.js +125 -0
  200. package/src/charting/diagrams/ArchimateModelReport.js +128 -0
  201. package/src/charting/diagrams/ArchimateModelSearch.js +41 -0
  202. package/src/charting/diagrams/ArchimateValidator.js +357 -0
  203. package/src/charting/diagrams/CanvasView.js +112 -0
  204. package/src/charting/diagrams/ContextMenu.js +37 -0
  205. package/src/charting/diagrams/DataModelDiagram.js +86 -0
  206. package/src/charting/diagrams/DataModelRelationshipStrategy.js +38 -0
  207. package/src/charting/diagrams/DerivedRelationships.js +102 -0
  208. package/src/charting/diagrams/EbnfDiagram.js +39 -0
  209. package/src/charting/diagrams/EdgeGeometry.js +553 -0
  210. package/src/charting/diagrams/EditViewItemCommand.js +128 -0
  211. package/src/charting/diagrams/ElementInstance.js +157 -0
  212. package/src/charting/diagrams/GraphDiagram.js +1340 -0
  213. package/src/charting/diagrams/GraphDiagram3D.js +152 -0
  214. package/src/charting/diagrams/GraphMetrics.js +81 -0
  215. package/src/charting/diagrams/GridOverlay.js +137 -0
  216. package/src/charting/diagrams/ImportRowsCommand.js +62 -0
  217. package/src/charting/diagrams/LabelHelper.js +108 -0
  218. package/src/charting/diagrams/MergeElementsCommand.js +101 -0
  219. package/src/charting/diagrams/NestInstanceCommand.js +34 -0
  220. package/src/charting/diagrams/NodeGeometry.js +158 -0
  221. package/src/charting/diagrams/PlaceItemsCommand.js +77 -0
  222. package/src/charting/diagrams/RadialLayout.js +101 -0
  223. package/src/charting/diagrams/RelationshipInstance.js +93 -0
  224. package/src/charting/diagrams/RemoveGroupFromViewCommand.js +28 -0
  225. package/src/charting/diagrams/RemoveLineCommand.js +27 -0
  226. package/src/charting/diagrams/ShowElementCommand.js +43 -0
  227. package/src/charting/diagrams/SvgCoordinate.js +17 -0
  228. package/src/charting/diagrams/SvgZoom.js +127 -0
  229. package/src/charting/diagrams/Tooltip.js +62 -0
  230. package/src/charting/diagrams/ViewConnectionInstance.js +102 -0
  231. package/src/charting/diagrams/ViewObjectInstance.js +56 -0
  232. package/src/charting/diagrams/commands/AddEdgeCommand.js +34 -0
  233. package/src/charting/diagrams/commands/AddNodeCommand.js +28 -0
  234. package/src/charting/diagrams/commands/AddWaypointCommand.js +27 -0
  235. package/src/charting/diagrams/commands/CreateFolderCommand.js +27 -0
  236. package/src/charting/diagrams/commands/DeleteEdgeCommand.js +30 -0
  237. package/src/charting/diagrams/commands/DeleteFolderCommand.js +47 -0
  238. package/src/charting/diagrams/commands/DeleteNodeCommand.js +35 -0
  239. package/src/charting/diagrams/commands/DeleteWaypointCommand.js +24 -0
  240. package/src/charting/diagrams/commands/GraphCommand.js +65 -0
  241. package/src/charting/diagrams/commands/InvertEdgeCommand.js +24 -0
  242. package/src/charting/diagrams/commands/MoveNodeCommand.js +44 -0
  243. package/src/charting/diagrams/commands/MoveWaypointCommand.js +27 -0
  244. package/src/charting/diagrams/commands/RenameEdgeCommand.js +23 -0
  245. package/src/charting/diagrams/commands/RenameFolderCommand.js +31 -0
  246. package/src/charting/diagrams/commands/RenameNodeCommand.js +27 -0
  247. package/src/charting/diagrams/commands/ResizeNodeCommand.js +46 -0
  248. package/src/charting/diagrams/commands/UpdateEdgeSideCommand.js +40 -0
  249. package/src/charting/diagrams/commands/index.js +17 -0
  250. package/src/charting/diagrams/duplicates.js +49 -0
  251. package/src/charting/diagrams/nesting.js +30 -0
  252. package/src/charting/diagrams/roadmap.js +77 -0
  253. package/src/charting/edgeMarkers/ArrowMarker.js +15 -0
  254. package/src/charting/edgeMarkers/CircleMarker.js +13 -0
  255. package/src/charting/edgeMarkers/CrowsFootMarker.js +16 -0
  256. package/src/charting/edgeMarkers/DiamondMarker.js +15 -0
  257. package/src/charting/edgeMarkers/EdgeMarker.js +34 -0
  258. package/src/charting/edgeMarkers/HalfArrowMarker.js +8 -0
  259. package/src/charting/edgeMarkers/HollowDiamondMarker.js +18 -0
  260. package/src/charting/edgeMarkers/HollowTriangleMarker.js +18 -0
  261. package/src/charting/edgeMarkers/OpenArrowMarker.js +17 -0
  262. package/src/charting/edgeMarkers/index.js +27 -0
  263. package/src/charting/edgeStyle/EdgeStyleCascade.js +22 -0
  264. package/src/charting/edgeStyle/EdgeStyleDialog.js +51 -0
  265. package/src/charting/edgeStyle/EdgeStyleSchema.js +43 -0
  266. package/src/charting/edgeStyle/SetStyleCommand.js +12 -0
  267. package/src/charting/edgeStyle/index.js +4 -0
  268. package/src/charting/emphasis/EmphasisRule.js +42 -0
  269. package/src/charting/emphasis/HighlightRule.js +24 -0
  270. package/src/charting/gauges/ArcTrack.js +51 -0
  271. package/src/charting/gauges/GaugeAnimation.js +51 -0
  272. package/src/charting/gauges/GaugeBands.js +48 -0
  273. package/src/charting/gauges/GaugeScale.js +87 -0
  274. package/src/charting/gauges/GaugeTrack.js +44 -0
  275. package/src/charting/gauges/GaugeValue.js +61 -0
  276. package/src/charting/gauges/HorizontalTrack.js +14 -0
  277. package/src/charting/gauges/LinearTrack.js +29 -0
  278. package/src/charting/gauges/Sparkline.js +42 -0
  279. package/src/charting/gauges/VerticalTrack.js +17 -0
  280. package/src/charting/glyphs/ArrowGlyph.js +21 -0
  281. package/src/charting/glyphs/BatteryGlyph.js +18 -0
  282. package/src/charting/glyphs/ChevronGlyph.js +18 -0
  283. package/src/charting/glyphs/CircleGlyph.js +15 -0
  284. package/src/charting/glyphs/CloudGlyph.js +19 -0
  285. package/src/charting/glyphs/ComponentGlyph.js +18 -0
  286. package/src/charting/glyphs/ConstraintGlyph.js +24 -0
  287. package/src/charting/glyphs/ContractBoxGlyph.js +10 -0
  288. package/src/charting/glyphs/CubeGlyph.js +19 -0
  289. package/src/charting/glyphs/CylinderGlyph.js +19 -0
  290. package/src/charting/glyphs/DashedDoubleArrowGlyph.js +11 -0
  291. package/src/charting/glyphs/DeviceGlyph.js +17 -0
  292. package/src/charting/glyphs/DiamondGlyph.js +17 -0
  293. package/src/charting/glyphs/DocumentGlyph.js +17 -0
  294. package/src/charting/glyphs/DoubleArrowGlyph.js +23 -0
  295. package/src/charting/glyphs/DoubleCircleGlyph.js +24 -0
  296. package/src/charting/glyphs/EllipseGlyph.js +18 -0
  297. package/src/charting/glyphs/FactoryGlyph.js +20 -0
  298. package/src/charting/glyphs/FlagGlyph.js +16 -0
  299. package/src/charting/glyphs/GapCircleGlyph.js +17 -0
  300. package/src/charting/glyphs/GearGlyph.js +37 -0
  301. package/src/charting/glyphs/Glyph.js +98 -0
  302. package/src/charting/glyphs/GroupingBoxGlyph.js +13 -0
  303. package/src/charting/glyphs/HalfCircleGlyph.js +22 -0
  304. package/src/charting/glyphs/HexagonGlyph.js +28 -0
  305. package/src/charting/glyphs/IconGlyph.js +22 -0
  306. package/src/charting/glyphs/ImageGlyph.js +16 -0
  307. package/src/charting/glyphs/JunctionGlyph.js +17 -0
  308. package/src/charting/glyphs/LollipopGlyph.js +22 -0
  309. package/src/charting/glyphs/MagnifierGlyph.js +17 -0
  310. package/src/charting/glyphs/NoteGlyph.js +33 -0
  311. package/src/charting/glyphs/ObjectBoxGlyph.js +21 -0
  312. package/src/charting/glyphs/OrJunctionGlyph.js +17 -0
  313. package/src/charting/glyphs/ParallelogramGlyph.js +20 -0
  314. package/src/charting/glyphs/PersonGlyph.js +23 -0
  315. package/src/charting/glyphs/PillGlyph.js +23 -0
  316. package/src/charting/glyphs/PinGlyph.js +18 -0
  317. package/src/charting/glyphs/PrincipleGlyph.js +23 -0
  318. package/src/charting/glyphs/ProductBoxGlyph.js +16 -0
  319. package/src/charting/glyphs/RectGlyph.js +15 -0
  320. package/src/charting/glyphs/RoundedBoxGlyph.js +13 -0
  321. package/src/charting/glyphs/StackGlyph.js +14 -0
  322. package/src/charting/glyphs/StepsGlyph.js +20 -0
  323. package/src/charting/glyphs/StickFigureGlyph.js +32 -0
  324. package/src/charting/glyphs/SystemSoftwareBoxGlyph.js +16 -0
  325. package/src/charting/glyphs/TabbedBoxGlyph.js +37 -0
  326. package/src/charting/glyphs/TargetGlyph.js +23 -0
  327. package/src/charting/glyphs/WavyBoxGlyph.js +17 -0
  328. package/src/charting/glyphs/WheelGlyph.js +28 -0
  329. package/src/charting/glyphs/drawGlyph.js +28 -0
  330. package/src/charting/glyphs/glyphSvg.js +55 -0
  331. package/src/charting/glyphs/index.js +109 -0
  332. package/src/charting/modelTree/AnalysisPanel.js +159 -0
  333. package/src/charting/modelTree/DiagramTabs.js +217 -0
  334. package/src/charting/modelTree/ModelTree.js +164 -0
  335. package/src/charting/modelTree/ModelTreePanel.js +914 -0
  336. package/src/charting/modelTree/TreeBuilder.js +238 -0
  337. package/src/charting/modelTree/TreeModeRegistry.js +51 -0
  338. package/src/charting/modelTree/TreeViewMode.js +110 -0
  339. package/src/charting/modelTree/buildFilterTrees.js +138 -0
  340. package/src/charting/modelTree/modes/FlatTreeMode.js +46 -0
  341. package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +62 -0
  342. package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +60 -0
  343. package/src/charting/modelTree/treeLayers.js +11 -0
  344. package/src/charting/report/reportHtml.js +82 -0
  345. package/src/charting/report/reportViewer.js +118 -0
  346. package/src/charting/shapes/CircleShape.js +19 -0
  347. package/src/charting/shapes/PathShape.js +17 -0
  348. package/src/charting/shapes/RectShape.js +20 -0
  349. package/src/charting/shapes/Shape.js +20 -0
  350. package/src/charting/shapes/ShapeFactory.js +23 -0
  351. package/src/charting/storage/LocalJsonStore.js +43 -0
  352. package/src/charting/templates/ActorTemplate.js +36 -0
  353. package/src/charting/templates/BoxTemplate.js +27 -0
  354. package/src/charting/templates/CircleTemplate.js +18 -0
  355. package/src/charting/templates/ClassTemplate.js +20 -0
  356. package/src/charting/templates/CloudTemplate.js +43 -0
  357. package/src/charting/templates/ComponentTemplate.js +19 -0
  358. package/src/charting/templates/CylinderTemplate.js +30 -0
  359. package/src/charting/templates/DataStoreTemplate.js +16 -0
  360. package/src/charting/templates/DiamondTemplate.js +10 -0
  361. package/src/charting/templates/DocumentTemplate.js +32 -0
  362. package/src/charting/templates/EllipseTemplate.js +15 -0
  363. package/src/charting/templates/FinalStateTemplate.js +12 -0
  364. package/src/charting/templates/GlyphTemplate.js +47 -0
  365. package/src/charting/templates/HexagonTemplate.js +17 -0
  366. package/src/charting/templates/LifelineTemplate.js +20 -0
  367. package/src/charting/templates/ManualInputTemplate.js +12 -0
  368. package/src/charting/templates/NoteTemplate.js +23 -0
  369. package/src/charting/templates/OctagonTemplate.js +7 -0
  370. package/src/charting/templates/PackageTemplate.js +25 -0
  371. package/src/charting/templates/ParallelogramTemplate.js +11 -0
  372. package/src/charting/templates/PentagonTemplate.js +5 -0
  373. package/src/charting/templates/PolygonTemplate.js +18 -0
  374. package/src/charting/templates/PredefinedProcessTemplate.js +13 -0
  375. package/src/charting/templates/RectangleTemplate.js +28 -0
  376. package/src/charting/templates/RegularPolygonTemplate.js +21 -0
  377. package/src/charting/templates/RoundedRectangleTemplate.js +5 -0
  378. package/src/charting/templates/StadiumTemplate.js +8 -0
  379. package/src/charting/templates/StarTemplate.js +17 -0
  380. package/src/charting/templates/SwimlaneTemplate.js +18 -0
  381. package/src/charting/templates/Template.js +208 -0
  382. package/src/charting/templates/TrapezoidTemplate.js +11 -0
  383. package/src/charting/templates/TriangleTemplate.js +12 -0
  384. package/src/charting/templates/index.js +31 -0
  385. package/src/charting/templates/outline.js +59 -0
  386. package/src/charting/templates/svg.js +19 -0
  387. package/src/charting/textToShapes.js +61 -0
  388. package/src/charting/toolbar/ToolbarButton.js +38 -0
  389. package/src/charting/toolbar/ToolbarCheckbox.js +31 -0
  390. package/src/charting/toolbar/ToolbarItem.js +19 -0
  391. package/src/charting/toolbar/ToolbarMenu.js +36 -0
  392. package/src/charting/toolbar/ToolbarSelect.js +38 -0
  393. package/src/charting/toolbar/ToolbarSeparator.js +7 -0
  394. package/src/charting/toolbar/ToolbarText.js +22 -0
  395. package/src/charting/toolbar/index.js +8 -0
  396. package/src/charting/toolbar/pickFile.js +14 -0
  397. package/src/charting/viewDecorations.js +85 -0
  398. package/src/charting/zOrder.js +57 -0
  399. package/src/csvTable.js +61 -0
  400. package/src/datamodel.js +122 -0
  401. package/src/datawindow/BoundedWindow.js +36 -0
  402. package/src/datawindow/FlatDataWindow.js +34 -0
  403. package/src/datawindow/GraphDataWindow.js +40 -0
  404. package/src/datawindow/GroupedSampleDataWindow.js +16 -0
  405. package/src/datawindow/SeriesDataWindow.js +42 -0
  406. package/src/datawindow/index.js +31 -0
  407. package/src/diagramCatalog.js +30 -0
  408. package/src/ebnfDiagram.js +57 -0
  409. package/src/ebnfParser.js +129 -0
  410. package/src/exportImage.js +233 -0
  411. package/src/index.js +2636 -0
  412. package/src/itIcons.js +84 -0
  413. package/src/kernelExpr.js +243 -0
  414. package/src/propertiesDialog.js +463 -0
  415. package/src/railroadDiagram.js +571 -0
  416. package/src/treeModeCatalog.js +16 -0
  417. package/src/workspace/ContextBus.js +79 -0
  418. package/src/workspace/EditorShell.js +67 -0
  419. package/src/workspace/Part.js +163 -0
  420. package/src/workspace/PartFactory.js +49 -0
  421. package/src/workspace/PartRegistry.js +86 -0
  422. package/src/workspace/Workspace.js +321 -0
  423. package/src/workspace/archimateServices.js +33 -0
  424. package/src/workspace/dom.js +120 -0
  425. package/src/workspace/index.js +75 -0
  426. package/src/workspace/layout/GridNode.js +280 -0
  427. package/src/workspace/layout/LayoutNode.js +89 -0
  428. package/src/workspace/layout/PartNode.js +77 -0
  429. package/src/workspace/layout/SplitNode.js +114 -0
  430. package/src/workspace/layout/TabsNode.js +191 -0
  431. package/src/workspace/layout/index.js +24 -0
  432. package/src/workspace/parts/AdapterPart.js +33 -0
  433. package/src/workspace/parts/ArchimateCanvasPart.js +345 -0
  434. package/src/workspace/parts/ArchimateEditorPart.js +79 -0
  435. package/src/workspace/parts/ChartPart.js +115 -0
  436. package/src/workspace/parts/ContentPart.js +34 -0
  437. package/src/workspace/parts/DetailPart.js +46 -0
  438. package/src/workspace/parts/DiagramEditorPart.js +135 -0
  439. package/src/workspace/parts/EditorPart.js +388 -0
  440. package/src/workspace/parts/HtmlPart.js +25 -0
  441. package/src/workspace/parts/ListPart.js +57 -0
  442. package/src/workspace/parts/ModelFile.js +187 -0
  443. package/src/workspace/parts/ModelsPart.js +135 -0
  444. package/src/workspace/styles.js +258 -0
  445. package/src/workspace/themes.js +96 -0
  446. package/src/workspace/workArea.js +413 -0
  447. package/src/workspace/workAreaModel.js +197 -0
  448. package/src/workspace.js +16 -0
  449. package/src/zip/ZipArchive.js +160 -0
  450. package/src/zip/crc32.js +25 -0
  451. package/src/zip/inflate.js +159 -0
@@ -0,0 +1,385 @@
1
+ import { el } from '../workspace/dom.js';
2
+ import { ColorField } from './ColorField.js';
3
+
4
+ const INHERIT = '__inherit__';
5
+
6
+ /**
7
+ * FormDialog — the one modal form, built from field descriptions, so every
8
+ * editor dialog shares one layout, keyboard handling and value reading.
9
+ *
10
+ * Field: `{ key, label, type, value?, choices?, min?, max?, step?, rows?, placeholder?,
11
+ * suggestions?, accept?, hint?, readOnly?, allowEmpty?, inherit?, element?, read? }`
12
+ * - type: 'text' | 'textarea' | 'number' | 'color' | 'select' | 'checkbox' | 'checklist' | 'file' | 'custom'
13
+ * | 'heading' (a section title; no value)
14
+ * - checklist: a box per choice, `choices` `[[value, text, group?], ...]` (grouped under their group's
15
+ * name), `value` the chosen values; reads as the chosen values, in choice order
16
+ * - choices (select): `[[value, text], ...]`. A current value that is not a
17
+ * choice is kept as its own option (never silently blanked); `allowEmpty`
18
+ * adds a "(none)" option for an empty value.
19
+ * - suggestions (text): values offered as you type (a datalist). The box empties
20
+ * on focus so every suggestion shows, and restores its value if left empty.
21
+ * - readOnly: shown but not editable, and not read back
22
+ * - accept (file): file types; reads as the chosen File or null
23
+ * - custom: `element` (a Node to place) and `read()` (its value)
24
+ * - color: a ColorField (the value as text, `#rrggbb` or `none`, a picker and preset
25
+ * swatches); `presets` (`[{value, name}]`) replaces ColorField.PRESETS, and
26
+ * `allowNone: false` leaves out "No colour"
27
+ * - hint: small explanatory text under the field
28
+ * - inherit: `{ text, short?, value }` — the field may be left unset. Selects get
29
+ * a first option labelled `text`; other types (checkboxes too) get an "Inherit"
30
+ * checkbox (`short` renames it) that greys the control out showing `value`. An
31
+ * inherited field reads as `undefined`. `FormDialog.many` uses it for a form
32
+ * that edits several items at once.
33
+ *
34
+ * The dialog fits the window: its fields scroll between the title and the
35
+ * buttons, which stay in view, and it moves by dragging its title. A textarea
36
+ * scrolls inside its own box and can be resized taller.
37
+ *
38
+ * `validate(values)` may return a message to show inline instead of closing.
39
+ * After open(), `controls[key]` is each field's control, for wiring fields that
40
+ * depend on one another.
41
+ */
42
+ export class FormDialog {
43
+ /**
44
+ * @param {Object} options
45
+ * @param {string} options.title
46
+ * @param {string} [options.description] - Text under the title
47
+ * @param {Array<Object>} options.fields
48
+ * @param {(values: Object) => void} options.onApply
49
+ * @param {(values: Object) => (string|null|undefined)} [options.validate]
50
+ * @param {string} [options.submitLabel]
51
+ * @param {string} [options.cancelLabel]
52
+ * @param {string} [options.idPrefix] - Field element ids are `${idPrefix}${key}`
53
+ * @param {Document} [options.document]
54
+ * @param {(applied: boolean) => void} [options.onClose] - Once, when the dialog closes: whether it was
55
+ * applied (false for Cancel, Escape or a click outside)
56
+ */
57
+ constructor({ title, description, fields, onApply, validate, submitLabel = 'Apply', cancelLabel = 'Cancel', idPrefix = 'form-dialog-', document: doc = document, onClose = null }) {
58
+ this.title = title;
59
+ this.description = description;
60
+ this.fields = fields;
61
+ this.onApply = onApply;
62
+ this.validate = validate;
63
+ this.submitLabel = submitLabel;
64
+ this.cancelLabel = cancelLabel;
65
+ this.idPrefix = idPrefix;
66
+ this.doc = doc;
67
+ this.onClose = onClose;
68
+ this._applied = false;
69
+ this.overlay = null;
70
+ /** @type {Object<string, HTMLElement>} */
71
+ this.controls = {};
72
+ this._readers = [];
73
+ this._error = null;
74
+ }
75
+
76
+ open() {
77
+ this._readers = [];
78
+ this.controls = {};
79
+ const rows = this.fields.map(f => this._row(f));
80
+ this.overlay = el({
81
+ style: {
82
+ position: 'fixed', inset: '0', background: 'rgba(0,0,0,0.25)', zIndex: '10001',
83
+ display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'sans-serif',
84
+ },
85
+ on: { mousedown: (e) => { if (e.target === this.overlay) this.close(); } },
86
+ children: [{
87
+ tag: 'form',
88
+ attrs: { role: 'dialog', 'aria-label': this.title },
89
+ style: {
90
+ background: '#fff', color: '#222', border: '1px solid #bbb', borderRadius: '6px', padding: '16px 18px',
91
+ minWidth: '360px', maxWidth: '90vw', maxHeight: '90vh', boxSizing: 'border-box',
92
+ display: 'flex', flexDirection: 'column',
93
+ boxShadow: '0 6px 24px rgba(0,0,0,0.2)', fontSize: '12px',
94
+ },
95
+ ref: (n) => { this.form = n; },
96
+ on: {
97
+ submit: (e) => { e.preventDefault(); this._apply(); },
98
+ keydown: (e) => { if (e.key === 'Escape') this.close(); },
99
+ },
100
+ children: [
101
+ {
102
+ // The title is the handle that moves the dialog.
103
+ tag: 'h3', text: this.title, attrs: { title: 'Drag to move' },
104
+ style: { margin: '0 0 8px', fontSize: '14px', cursor: 'move', userSelect: 'none', flex: '0 0 auto' },
105
+ on: { mousedown: (e) => this._startMove(e) },
106
+ },
107
+ {
108
+ // The fields scroll; the title and the buttons stay in view.
109
+ style: { overflowY: 'auto', flex: '1 1 auto', minHeight: '0', paddingRight: '4px' },
110
+ ref: (n) => { this.body = n; },
111
+ children: [
112
+ this.description && { text: this.description, style: { fontSize: '11px', color: '#666', margin: '0 0 10px' } },
113
+ { style: { display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '8px 12px', alignItems: 'center' }, children: rows.flat() },
114
+ { attrs: { role: 'alert' }, style: { color: '#c0392b', fontSize: '12px', marginTop: '8px', display: 'none' }, ref: (n) => { this._error = n; } },
115
+ ].filter(Boolean),
116
+ },
117
+ {
118
+ style: { display: 'flex', justifyContent: 'flex-end', gap: '8px', marginTop: '16px', flex: '0 0 auto' },
119
+ children: [
120
+ { tag: 'button', attrs: { type: 'button' }, text: this.cancelLabel, on: { click: () => this.close() } },
121
+ {
122
+ tag: 'button', attrs: { type: 'submit' }, text: this.submitLabel,
123
+ style: { background: '#0066cc', color: '#fff', border: '1px solid #0066cc', borderRadius: '3px', padding: '4px 14px' },
124
+ },
125
+ ],
126
+ },
127
+ ].filter(Boolean),
128
+ }],
129
+ }, this.doc);
130
+ this.doc.body.appendChild(this.overlay);
131
+ this.overlay.querySelector('input:not([type=checkbox]), select, textarea')?.focus();
132
+ return this;
133
+ }
134
+
135
+ /**
136
+ * Move the dialog by its title: from then on it sits where it was dropped
137
+ * (fixed position), kept inside the window.
138
+ * @protected
139
+ */
140
+ _startMove(e) {
141
+ if (e.button !== 0 || !this.form) return;
142
+ e.preventDefault();
143
+ const view = this.doc.defaultView;
144
+ const box = this.form.getBoundingClientRect();
145
+ const grab = { x: e.clientX - box.left, y: e.clientY - box.top };
146
+ Object.assign(this.form.style, { position: 'fixed', margin: '0', left: `${box.left}px`, top: `${box.top}px` });
147
+ const move = (ev) => {
148
+ const width = view?.innerWidth ?? Infinity, height = view?.innerHeight ?? Infinity;
149
+ const left = Math.min(Math.max(0, ev.clientX - grab.x), Math.max(0, width - box.width));
150
+ const top = Math.min(Math.max(0, ev.clientY - grab.y), Math.max(0, height - 40));
151
+ this.form.style.left = `${left}px`;
152
+ this.form.style.top = `${top}px`;
153
+ };
154
+ const end = () => {
155
+ this.doc.removeEventListener('mousemove', move);
156
+ this.doc.removeEventListener('mouseup', end);
157
+ };
158
+ this.doc.addEventListener('mousemove', move);
159
+ this.doc.addEventListener('mouseup', end);
160
+ }
161
+
162
+ close() {
163
+ if (!this.overlay) return;
164
+ this.overlay.remove();
165
+ this.overlay = null;
166
+ this.onClose?.(this._applied);
167
+ }
168
+
169
+ values() {
170
+ return Object.fromEntries(this._readers.map(read => read()));
171
+ }
172
+
173
+ _apply() {
174
+ const values = this.values();
175
+ const problem = this.validate?.(values);
176
+ if (problem) {
177
+ this._error.textContent = problem;
178
+ this._error.style.display = 'block';
179
+ return;
180
+ }
181
+ this._applied = true;
182
+ this.close();
183
+ this.onApply(values);
184
+ }
185
+
186
+ _id(f) {
187
+ return `${this.idPrefix}${f.key}`;
188
+ }
189
+
190
+ _keep(f) {
191
+ return (n) => { this.controls[f.key] = n; };
192
+ }
193
+
194
+ _row(f) {
195
+ if (f.type === 'heading') {
196
+ return [{
197
+ text: f.label, style: {
198
+ gridColumn: '1 / -1', fontSize: '11px', fontWeight: 'bold', textTransform: 'uppercase',
199
+ color: '#999', letterSpacing: '0.04em', marginTop: '6px',
200
+ },
201
+ }];
202
+ }
203
+ const label = { tag: 'label', text: f.label, attrs: { for: this._id(f) }, style: { color: '#333' } };
204
+ let control;
205
+ if (f.type === 'select') control = this._select(f);
206
+ else if (f.type === 'checkbox') control = this._checkbox(f);
207
+ else if (f.type === 'checklist') control = this._checklist(f);
208
+ else if (f.type === 'custom') control = this._custom(f);
209
+ else control = f.inherit ? this._inheritableInput(f) : this._input(f);
210
+ // No label: the control takes the whole row (e.g. an editable list).
211
+ const row = f.label ? [label, control] : [{ style: { gridColumn: '1 / -1' }, children: [control] }];
212
+ if (f.hint) row.push({}, { text: f.hint, style: { fontSize: '11px', color: '#888', marginTop: '-4px' } });
213
+ return row;
214
+ }
215
+
216
+ _select(f) {
217
+ let select;
218
+ if (!f.readOnly) this._readers.push(() => [f.key, select.value === INHERIT ? undefined : select.value]);
219
+ const unset = f.inherit && f.value === undefined;
220
+ const current = f.value == null ? '' : String(f.value);
221
+ const known = f.choices.some(([v]) => v === current);
222
+ const extra = unset ? []
223
+ : current && !known ? [[current, current]]
224
+ : !current && f.allowEmpty ? [['', '(none)']]
225
+ : [];
226
+ return {
227
+ tag: 'select', attrs: { id: this._id(f), disabled: !!f.readOnly }, ref: (n) => { select = n; this._keep(f)(n); },
228
+ children: [
229
+ ...(f.inherit ? [{ tag: 'option', attrs: { value: INHERIT, selected: unset }, text: f.inherit.text }] : []),
230
+ ...[...extra, ...f.choices].map(([v, text]) => ({ tag: 'option', attrs: { value: v, selected: !unset && v === current }, text })),
231
+ ],
232
+ };
233
+ }
234
+
235
+ _checkbox(f) {
236
+ if (f.inherit) return this._inheritableInput(f);
237
+ let box;
238
+ if (!f.readOnly) this._readers.push(() => [f.key, box.checked]);
239
+ return {
240
+ tag: 'input', attrs: { id: this._id(f), type: 'checkbox', checked: !!f.value, disabled: !!f.readOnly }, style: { justifySelf: 'start' },
241
+ ref: (n) => { box = n; this._keep(f)(n); },
242
+ };
243
+ }
244
+
245
+ _checklist(f) {
246
+ const boxes = [];
247
+ const chosen = new Set(f.value ?? []);
248
+ if (!f.readOnly) this._readers.push(() => [f.key, boxes.filter(b => b.checked).map(b => b.value)]);
249
+ const groups = new Map();
250
+ for (const [value, text, group = ''] of f.choices) {
251
+ if (!groups.has(group)) groups.set(group, []);
252
+ groups.get(group).push([value, text]);
253
+ }
254
+ return {
255
+ attrs: { id: this._id(f) }, ref: this._keep(f),
256
+ style: { maxHeight: '220px', overflowY: 'auto', border: '1px solid #ccc', borderRadius: '3px', padding: '4px 8px', background: '#fff' },
257
+ children: [...groups].map(([group, items]) => ({
258
+ children: [
259
+ ...(group ? [{ text: group, style: { fontSize: '11px', fontWeight: 'bold', color: '#777', marginTop: '4px' } }] : []),
260
+ ...items.map(([value, text]) => ({
261
+ tag: 'label', style: { display: 'block', whiteSpace: 'nowrap' },
262
+ children: [
263
+ { tag: 'input', attrs: { type: 'checkbox', value, checked: chosen.has(value), disabled: !!f.readOnly }, ref: (n) => boxes.push(n) },
264
+ ` ${text}`,
265
+ ],
266
+ })),
267
+ ],
268
+ })),
269
+ };
270
+ }
271
+
272
+ _custom(f) {
273
+ this._readers.push(() => [f.key, f.read()]);
274
+ if (f.element && !f.element.id) f.element.id = this._id(f);
275
+ this.controls[f.key] = f.element;
276
+ return f.element;
277
+ }
278
+
279
+ _controlSpec(f, ref) {
280
+ const keep = (n) => { ref(n); this._keep(f)(n); };
281
+ const readOnlyStyle = f.readOnly ? { background: '#f2f2f2', color: '#888' } : {};
282
+ if (f.type === 'textarea') {
283
+ return {
284
+ tag: 'textarea', attrs: { id: this._id(f), rows: f.rows ?? 4, placeholder: f.placeholder, readonly: !!f.readOnly },
285
+ text: f.value ?? '',
286
+ // Long text scrolls inside the box, which can be dragged taller.
287
+ style: { width: '100%', minWidth: '260px', boxSizing: 'border-box', maxHeight: '40vh', overflowY: 'auto', resize: 'vertical', ...readOnlyStyle },
288
+ ref: keep,
289
+ };
290
+ }
291
+ // A colour: its value as text (#rrggbb or none), a picker and preset swatches.
292
+ if (f.type === 'color') return ColorField.spec(f, { id: this._id(f), ref: keep, style: readOnlyStyle });
293
+ const value = f.type === 'file' ? null : (f.value == null ? '' : (Array.isArray(f.value) ? JSON.stringify(f.value) : String(f.value)));
294
+ const listId = f.suggestions ? `${this._id(f)}-suggestions` : null;
295
+ const input = {
296
+ tag: 'input',
297
+ attrs: {
298
+ id: this._id(f), type: f.type ?? 'text', value,
299
+ min: f.min, max: f.max, step: f.step, placeholder: f.placeholder, accept: f.accept, list: listId,
300
+ readonly: !!f.readOnly,
301
+ },
302
+ style: { ...(f.type === 'number' ? { width: '70px' } : { width: '100%', boxSizing: 'border-box' }), ...readOnlyStyle },
303
+ on: f.suggestions ? {
304
+ // A datalist filters against the text already typed, so an existing
305
+ // value can look like the only option. Emptying on focus shows them all.
306
+ focus: (e) => { e.target.dataset.prevValue = e.target.value; e.target.value = ''; },
307
+ blur: (e) => { if (e.target.value === '' && e.target.dataset.prevValue) e.target.value = e.target.dataset.prevValue; },
308
+ } : undefined,
309
+ ref: keep,
310
+ };
311
+ if (!listId) return input;
312
+ return {
313
+ children: [input, { tag: 'datalist', attrs: { id: listId }, children: f.suggestions.map(v => ({ tag: 'option', attrs: { value: v } })) }],
314
+ };
315
+ }
316
+
317
+ _read(f, input) {
318
+ if (f.type === 'file') return input.files?.[0] ?? null;
319
+ if (f.type === 'checkbox') return input.checked;
320
+ return f.type === 'number' ? Number(input.value) : input.value;
321
+ }
322
+
323
+ _input(f) {
324
+ let input;
325
+ if (!f.readOnly) this._readers.push(() => [f.key, this._read(f, input)]);
326
+ return this._controlSpec(f, (n) => { input = n; });
327
+ }
328
+
329
+ /** The control plus an "Inherit" checkbox that greys it out showing the inherited value. */
330
+ _inheritableInput(f) {
331
+ let input, inherit;
332
+ const sync = () => {
333
+ input.disabled = inherit.checked;
334
+ if (inherit.checked && f.type === 'checkbox') input.checked = !!f.inherit.value;
335
+ else if (inherit.checked) input.value = f.inherit.value;
336
+ };
337
+ this._readers.push(() => [f.key, inherit.checked ? undefined : this._read(f, input)]);
338
+ return {
339
+ style: { display: 'flex', alignItems: 'center', gap: '10px' },
340
+ children: [
341
+ f.type === 'checkbox'
342
+ ? { tag: 'input', attrs: { id: this._id(f), type: 'checkbox', checked: !!(f.value ?? f.inherit.value) }, ref: (n) => { input = n; this._keep(f)(n); } }
343
+ : this._controlSpec({ ...f, value: f.value ?? f.inherit.value }, (n) => { input = n; }),
344
+ {
345
+ tag: 'label', style: { display: 'flex', alignItems: 'center', gap: '4px', color: '#555' },
346
+ attrs: { title: f.inherit.text },
347
+ children: [
348
+ { tag: 'input', attrs: { type: 'checkbox', checked: f.value === undefined }, on: { change: sync }, ref: (n) => { inherit = n; } },
349
+ f.inherit.short ?? 'Inherit',
350
+ ],
351
+ },
352
+ ],
353
+ // el() runs a parent's ref after its children's, so input/inherit are bound here.
354
+ ref: () => sync(),
355
+ };
356
+ }
357
+
358
+ /**
359
+ * One form for several items: each item's fields (the same keys, in the
360
+ * same order) merged into one list in which every field starts as "keep
361
+ * each item's own" (`inherit`, reading as undefined) showing the value
362
+ * they share, or empty with a hint when they differ. Set a field and it
363
+ * applies to them all; read-only fields are left out.
364
+ * @param {Array<Array<Object>>} fieldLists - One list of fields per item
365
+ * @param {Object} [options]
366
+ * @param {string} [options.short] - The keep checkbox's label
367
+ * @param {string} [options.text] - Its tooltip (and a select's first option)
368
+ * @returns {Array<Object>} fields
369
+ */
370
+ static many(fieldLists, { short = 'Keep', text = 'As each one is' } = {}) {
371
+ const [first = [], ...rest] = fieldLists;
372
+ const same = (a, b) => JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
373
+ return first.filter(f => !f.readOnly).map((f, i) => {
374
+ if (f.type === 'heading' || !f.key) return f;
375
+ const values = [f.value, ...rest.map(list => list.find(g => g.key === f.key)?.value)];
376
+ const shared = values.every(v => same(v, values[0]));
377
+ const blank = f.type === 'checkbox' ? false : '';
378
+ return {
379
+ ...f, value: undefined,
380
+ inherit: { short, text, value: shared ? (values[0] ?? blank) : blank },
381
+ ...(!shared && { hint: [f.hint, 'Differs between them'].filter(Boolean).join('. ') }),
382
+ };
383
+ });
384
+ }
385
+ }
@@ -0,0 +1,58 @@
1
+ import { ColorPalette } from './ColorPalette.js';
2
+
3
+ /**
4
+ * Gauge — pure helpers shared by barGauge and dialGauge.
5
+ */
6
+ export class Gauge {
7
+ /**
8
+ * Resolves a gauge `color` option to a single hex color for the given
9
+ * 0-100 value. A plain string or function passes through unchanged. An
10
+ * array is treated as a heat-map gradient, either plain hex strings evenly
11
+ * spaced across 0-100 or `{stop, color}` pairs at explicit percentages.
12
+ */
13
+ static resolveColor(color, percent) {
14
+ if (typeof color === 'function') return color(percent);
15
+ if (!Array.isArray(color)) return color;
16
+ if (color.length === 0) return '#5352ed';
17
+ if (color.length === 1) return typeof color[0] === 'string' ? color[0] : color[0].color;
18
+
19
+ const stops = typeof color[0] === 'string'
20
+ ? color.map((c, i) => ({ stop: (i / (color.length - 1)) * 100, color: c }))
21
+ : [...color].sort((a, b) => a.stop - b.stop);
22
+
23
+ const p = Math.min(100, Math.max(0, percent));
24
+ if (p <= stops[0].stop) return stops[0].color;
25
+ if (p >= stops[stops.length - 1].stop) return stops[stops.length - 1].color;
26
+ for (let i = 0; i < stops.length - 1; i++) {
27
+ const a = stops[i], b = stops[i + 1];
28
+ if (p >= a.stop && p <= b.stop) {
29
+ const t = b.stop === a.stop ? 0 : (p - a.stop) / (b.stop - a.stop);
30
+ return ColorPalette.interpolate(a.color, b.color, t);
31
+ }
32
+ }
33
+ return stops[stops.length - 1].color;
34
+ }
35
+
36
+ /**
37
+ * Builds an SVG arc path `d` string for a gauge background or progress arc.
38
+ * Angles are in radians.
39
+ */
40
+ static arcPath(cx, cy, r, startAngle, endAngle) {
41
+ // A whole circle starts and ends on one point, which an SVG arc draws as nothing: two halves.
42
+ if (endAngle - startAngle >= 2 * Math.PI - 1e-9) {
43
+ const mid = startAngle + Math.PI;
44
+ const at = (a) => `${cx + r * Math.cos(a)} ${cy + r * Math.sin(a)}`;
45
+ return `M ${at(startAngle)} A ${r} ${r} 0 0 1 ${at(mid)} A ${r} ${r} 0 0 1 ${at(startAngle)}`;
46
+ }
47
+ const largeArcFlag = endAngle - startAngle <= Math.PI ? '0' : '1';
48
+ const start = {
49
+ x: cx + r * Math.cos(startAngle),
50
+ y: cy + r * Math.sin(startAngle),
51
+ };
52
+ const end = {
53
+ x: cx + r * Math.cos(endAngle),
54
+ y: cy + r * Math.sin(endAngle),
55
+ };
56
+ return `M ${start.x} ${start.y} A ${r} ${r} 0 ${largeArcFlag} 1 ${end.x} ${end.y}`;
57
+ }
58
+ }
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Hierarchy — pure, DOM-free helpers for hierarchical charts.
3
+ *
4
+ * Value computation, tree depth, squarified treemap layout, and sunburst
5
+ * angular layout used to be private methods on RenderEngine. Moving them here
6
+ * lets TreemapChart, SunburstChart, and OutlineChart stay focused on rendering.
7
+ */
8
+ export class Hierarchy {
9
+ /**
10
+ * A leaf's own value, or a branch's value computed as the sum of its
11
+ * children (recursively). Non-finite or non-positive values are treated as 0.
12
+ */
13
+ static value(node) {
14
+ if (node.children?.length) return node.children.reduce((sum, c) => sum + Hierarchy.value(c), 0);
15
+ return Number.isFinite(node.value) && node.value > 0 ? node.value : 0;
16
+ }
17
+
18
+ /** Tree depth: 1 for a leaf, 1 + the deepest child for a branch. */
19
+ static depth(node) {
20
+ if (!node.children?.length) return 1;
21
+ return 1 + Math.max(...node.children.map(c => Hierarchy.depth(c)));
22
+ }
23
+
24
+ /**
25
+ * The worst (largest) width:height aspect ratio among `row`'s rectangles
26
+ * if laid out along a strip of the given `side` length. Assumes every
27
+ * item's `.area` is already computed.
28
+ */
29
+ static squarifyWorstRatio(row, side) {
30
+ const sum = row.reduce((s, item) => s + item.area, 0);
31
+ if (sum <= 0 || side <= 0) return Infinity;
32
+ const thickness = sum / side;
33
+ let worst = 1;
34
+ for (const item of row) {
35
+ const length = item.area / thickness;
36
+ if (length <= 0) return Infinity;
37
+ worst = Math.max(worst, Math.max(thickness / length, length / thickness));
38
+ }
39
+ return worst;
40
+ }
41
+
42
+ /**
43
+ * Squarified treemap layout. Lays `items` (each `{value, ref}`, pre-sorted
44
+ * descending by value) into the rect `x,y,width,height`, area-proportional
45
+ * to value.
46
+ * @returns {Array<{ref: *, x: number, y: number, width: number, height: number}>}
47
+ */
48
+ static squarify(items, x, y, width, height) {
49
+ const total = items.reduce((s, it) => s + it.value, 0);
50
+ if (!items.length || total <= 0 || width <= 0 || height <= 0) return [];
51
+ const scale = (width * height) / total;
52
+ const scaled = items.map(it => ({ ref: it.ref, area: it.value * scale }));
53
+
54
+ const result = [];
55
+ let rectX = x, rectY = y, rectW = width, rectH = height;
56
+ let i = 0;
57
+ while (i < scaled.length) {
58
+ const isWide = rectW >= rectH;
59
+ const side = isWide ? rectH : rectW;
60
+ let row = [scaled[i]];
61
+ let bestRatio = Hierarchy.squarifyWorstRatio(row, side);
62
+ let j = i + 1;
63
+ while (j < scaled.length) {
64
+ const testRow = [...row, scaled[j]];
65
+ const testRatio = Hierarchy.squarifyWorstRatio(testRow, side);
66
+ if (testRatio > bestRatio) break;
67
+ row = testRow;
68
+ bestRatio = testRatio;
69
+ j++;
70
+ }
71
+
72
+ const rowSum = row.reduce((s, it) => s + it.area, 0);
73
+ const thickness = rowSum / side;
74
+ let offset = 0;
75
+ for (const item of row) {
76
+ const length = item.area / thickness;
77
+ if (isWide) result.push({ ref: item.ref, x: rectX, y: rectY + offset, width: thickness, height: length });
78
+ else result.push({ ref: item.ref, x: rectX + offset, y: rectY, width: length, height: thickness });
79
+ offset += length;
80
+ }
81
+
82
+ if (isWide) { rectX += thickness; rectW -= thickness; }
83
+ else { rectY += thickness; rectH -= thickness; }
84
+ i += row.length;
85
+ }
86
+ return result;
87
+ }
88
+
89
+ /**
90
+ * Recursive layout over a treemap node tree. Computes each node's value,
91
+ * squarifies this level, and for a branch reserves a fixed-height header
92
+ * band before recursing into the remaining content rect.
93
+ * @param {number} [headerH=16]
94
+ * @returns {Array<{node: object, x: number, y: number, width: number, height: number, depth: number, isLeaf: boolean, topAncestor: object}>}
95
+ */
96
+ static treemapLayout(nodes, x, y, width, height, depth = 0, topAncestors = null, headerH = 16) {
97
+ const items = nodes
98
+ .map(node => ({ ref: node, value: Hierarchy.value(node) }))
99
+ .filter(it => it.value > 0)
100
+ .sort((a, b) => b.value - a.value);
101
+ const rects = Hierarchy.squarify(items, x, y, width, height);
102
+
103
+ const result = [];
104
+ for (const r of rects) {
105
+ const node = r.ref;
106
+ const isLeaf = !node.children?.length;
107
+ const topAncestor = topAncestors ? topAncestors.get(node) : node;
108
+ result.push({ node, x: r.x, y: r.y, width: r.width, height: r.height, depth, isLeaf, topAncestor });
109
+ if (!isLeaf) {
110
+ const bandH = Math.min(r.height, headerH);
111
+ const childTopAncestors = new Map(node.children.map(c => [c, topAncestor]));
112
+ result.push(...Hierarchy.treemapLayout(node.children, r.x, r.y + bandH, r.width, r.height - bandH, depth + 1, childTopAncestors, headerH));
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * Recursive angular layout over a node tree. Partitions angle instead of
120
+ * area, one ring per depth. Input order is preserved.
121
+ * @returns {Array<{node: object, cx: number, cy: number, rInner: number, rOuter: number, startAngle: number, endAngle: number, depth: number, isLeaf: boolean, topAncestor: object}>}
122
+ */
123
+ static sunburstLayout(nodes, cx, cy, innerRadius, ringWidth, startAngle, endAngle, depth = 0, topAncestors = null) {
124
+ const items = nodes
125
+ .map(node => ({ node, value: Hierarchy.value(node) }))
126
+ .filter(it => it.value > 0);
127
+ const total = items.reduce((s, it) => s + it.value, 0) || 1;
128
+ const rOuter = innerRadius + ringWidth;
129
+
130
+ const result = [];
131
+ let angle = startAngle;
132
+ for (const it of items) {
133
+ const { node } = it;
134
+ const sliceAngle = (it.value / total) * (endAngle - startAngle);
135
+ const isLeaf = !node.children?.length;
136
+ const topAncestor = topAncestors ? topAncestors.get(node) : node;
137
+ const sliceStart = angle, sliceEnd = angle + sliceAngle;
138
+ result.push({ node, cx, cy, rInner: innerRadius, rOuter, startAngle: sliceStart, endAngle: sliceEnd, depth, isLeaf, topAncestor });
139
+ if (!isLeaf) {
140
+ const childTopAncestors = new Map(node.children.map(c => [c, topAncestor]));
141
+ result.push(...Hierarchy.sunburstLayout(node.children, cx, cy, rOuter, ringWidth, sliceStart, sliceEnd, depth + 1, childTopAncestors));
142
+ }
143
+ angle = sliceEnd;
144
+ }
145
+ return result;
146
+ }
147
+
148
+ /**
149
+ * Flat, pre-order list of *visible* rows for an outline view. A branch
150
+ * present in `collapsed` contributes its own row but none of its
151
+ * descendants'.
152
+ * @returns {Array<{node: object, depth: number, hasChildren: boolean, topAncestor: object}>}
153
+ */
154
+ static outlineLayout(nodes, depth, collapsed, topAncestors = null) {
155
+ const rows = [];
156
+ for (const node of nodes) {
157
+ const hasChildren = !!node.children?.length;
158
+ const topAncestor = topAncestors ? topAncestors.get(node) : node;
159
+ rows.push({ node, depth, hasChildren, topAncestor });
160
+ if (hasChildren && !collapsed.has(node)) {
161
+ const childTopAncestors = new Map(node.children.map(c => [c, topAncestor]));
162
+ rows.push(...Hierarchy.outlineLayout(node.children, depth + 1, collapsed, childTopAncestors));
163
+ }
164
+ }
165
+ return rows;
166
+ }
167
+
168
+ /** Extracts descriptive extra fields from an outline row node. */
169
+ static outlineExtraText(node, structuralKeys) {
170
+ return Object.entries(node)
171
+ .filter(([k, v]) => !structuralKeys.has(k) && v !== undefined && typeof v !== 'function')
172
+ .map(([, v]) => Array.isArray(v) ? v.join(', ') : v)
173
+ .join(' · ');
174
+ }
175
+ }