@peter.prib/renderengine 0.14.0 → 0.15.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 (109) hide show
  1. package/README.md +45 -19
  2. package/bin/renderengine.mjs +157 -0
  3. package/dist/renderengine-workspace.umd.js +49391 -39748
  4. package/dist/renderengine.umd.js +25366 -15650
  5. package/documentation/REFERENCE.md +38 -0
  6. package/package.json +6 -1
  7. package/src/CanvasRenderer.js +225 -200
  8. package/src/SVGRenderer.js +476 -454
  9. package/src/archimate.js +22 -2
  10. package/src/archimateArchiFormat.js +1735 -1701
  11. package/src/archimateArchive.js +36 -7
  12. package/src/archimateCSV.js +93 -37
  13. package/src/archimateDrawio.js +2 -0
  14. package/src/archimateExchangeFormat.js +3 -1
  15. package/src/chartCatalog.js +219 -0
  16. package/src/charting/Annotations.js +169 -0
  17. package/src/charting/ArchimateDiagramEditor.js +54 -10
  18. package/src/charting/Axis.js +217 -5
  19. package/src/charting/Chart.js +99 -9
  20. package/src/charting/Chart3D.js +3 -0
  21. package/src/charting/ChartBox.js +8 -1
  22. package/src/charting/ColorPalette.js +42 -4
  23. package/src/charting/DiagramEditor.js +174 -39
  24. package/src/charting/DiagramEditorCommands.js +28 -0
  25. package/src/charting/Edge.js +7 -0
  26. package/src/charting/Hierarchy.js +114 -0
  27. package/src/charting/InteractionManager.js +4 -0
  28. package/src/charting/ModelFileFormat.js +5 -1
  29. package/src/charting/SettingsManager.js +35 -0
  30. package/src/charting/ShapePaths.js +82 -10
  31. package/src/charting/archimate/ArchimateCsvFileFormat.js +51 -12
  32. package/src/charting/archimate/ArchimateElementTemplate.js +235 -231
  33. package/src/charting/charts/AlluvialDiagram.js +311 -0
  34. package/src/charting/charts/AreaChart.js +52 -15
  35. package/src/charting/charts/BarChart.js +38 -3
  36. package/src/charting/charts/BarChart3D.js +5 -3
  37. package/src/charting/charts/BarChartBase.js +26 -6
  38. package/src/charting/charts/BeeswarmChart.js +164 -0
  39. package/src/charting/charts/BoxPlotChart.js +23 -1
  40. package/src/charting/charts/CalendarHeatmapChart.js +2 -1
  41. package/src/charting/charts/CandlestickChart.js +172 -4
  42. package/src/charting/charts/ChordDiagram.js +105 -2
  43. package/src/charting/charts/CirclePackChart.js +81 -0
  44. package/src/charting/charts/ComboChart.js +233 -0
  45. package/src/charting/charts/ContourChart.js +310 -0
  46. package/src/charting/charts/DonutChart3D.js +13 -0
  47. package/src/charting/charts/DumbbellChart.js +217 -0
  48. package/src/charting/charts/EcdfChart.js +150 -0
  49. package/src/charting/charts/FunnelChart.js +4 -1
  50. package/src/charting/charts/GeoMapChart.js +132 -11
  51. package/src/charting/charts/GroupedBarChart.js +44 -3
  52. package/src/charting/charts/GroupedDistributionChart.js +26 -1
  53. package/src/charting/charts/HeatmapChart.js +2 -2
  54. package/src/charting/charts/HexbinChart.js +137 -0
  55. package/src/charting/charts/HierarchyChart.js +77 -3
  56. package/src/charting/charts/HorizonChart.js +105 -0
  57. package/src/charting/charts/KagiChart.js +167 -0
  58. package/src/charting/charts/LineChart.js +74 -18
  59. package/src/charting/charts/OhlcChart.js +79 -0
  60. package/src/charting/charts/ParallelCoordinatesChart.js +9 -1
  61. package/src/charting/charts/PieChart.js +195 -17
  62. package/src/charting/charts/PieChart3D.js +137 -0
  63. package/src/charting/charts/PointAndFigureChart.js +198 -0
  64. package/src/charting/charts/PolarAreaChart.js +189 -0
  65. package/src/charting/charts/RadarChart.js +7 -1
  66. package/src/charting/charts/RadialBarChart.js +5 -2
  67. package/src/charting/charts/RenkoChart.js +178 -0
  68. package/src/charting/charts/RidgelineChart.js +113 -0
  69. package/src/charting/charts/SankeyDiagram.js +127 -4
  70. package/src/charting/charts/ScatterChart.js +13 -0
  71. package/src/charting/charts/ScatterMatrixChart.js +119 -0
  72. package/src/charting/charts/SlopegraphChart.js +205 -0
  73. package/src/charting/charts/SparklineTableChart.js +166 -0
  74. package/src/charting/charts/StackedBarChart.js +48 -5
  75. package/src/charting/charts/StackedBarChart3DOrbit.js +10 -5
  76. package/src/charting/charts/StreamGraphChart.js +10 -3
  77. package/src/charting/charts/SunburstChart.js +27 -7
  78. package/src/charting/charts/SurfaceChart3D.js +157 -0
  79. package/src/charting/charts/TreemapChart.js +28 -8
  80. package/src/charting/charts/ViolinChart.js +18 -0
  81. package/src/charting/datamodel/ArchimateDataLink.js +70 -0
  82. package/src/charting/datamodel/DataLineage.js +150 -0
  83. package/src/charting/datamodel/DataModel.js +83 -1
  84. package/src/charting/datamodel/ModelMapping.js +87 -0
  85. package/src/charting/datamodel/SqlDdl.js +110 -85
  86. package/src/charting/datamodel/index.js +3 -0
  87. package/src/charting/decision/DecisionWorkbench.js +295 -0
  88. package/src/charting/diagrams/ArchimateDiagram.js +25 -9
  89. package/src/charting/diagrams/ArchimateModel.js +1382 -1238
  90. package/src/charting/diagrams/GraphDiagram.js +1424 -1350
  91. package/src/charting/diagrams/SketchView.js +121 -0
  92. package/src/charting/diagrams/sketchBoxKinds.js +30 -0
  93. package/src/charting/modelTree/AnalysisPanel.js +101 -23
  94. package/src/charting/modelTree/NavigatorModel.js +410 -0
  95. package/src/charting/modelTree/NavigatorPanel.js +453 -0
  96. package/src/charting/pivot/PivotChart.js +109 -4
  97. package/src/charting/pivot/PivotGridChart.js +321 -33
  98. package/src/charting/pivot/PivotView.js +82 -0
  99. package/src/charting/report/TemplatedReport.js +547 -0
  100. package/src/charting/templates/BoxTemplate.js +28 -27
  101. package/src/charting/templates/PackageTemplate.js +26 -25
  102. package/src/charting/templates/SwimlaneTemplate.js +19 -18
  103. package/src/charting/templates/Template.js +219 -212
  104. package/src/cli.js +146 -0
  105. package/src/index.js +3370 -2995
  106. package/src/workspace/Workspace.js +126 -7
  107. package/src/workspace/archimateServices.js +4 -0
  108. package/src/workspace/parts/ArchimateCanvasPart.js +1 -1
  109. package/src/workspace/styles.js +36 -1
@@ -169,15 +169,134 @@ export class Workspace extends HTMLElement {
169
169
  }));
170
170
  }
171
171
 
172
+ /** Return every partId referenced by a registered perspective's layout. */
173
+ partIdsForPerspective(name) {
174
+ const layout = this.perspectives.get(name);
175
+ if (!layout) return [];
176
+ try {
177
+ return createLayout(layout).partIds();
178
+ } catch {
179
+ return [];
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Activate a perspective containing `partId` (if not already visible), scroll
185
+ * the part's pane into the center of the viewport, and pulse a highlight ring.
186
+ */
187
+ focusPart(partId, perspectiveName = null) {
188
+ if (!partId) return false;
189
+ const targetPerspective = perspectiveName
190
+ ?? (this.activePerspective && this.partIdsForPerspective(this.activePerspective).includes(partId)
191
+ ? this.activePerspective
192
+ : [...this.perspectives.keys()].find(p => this.partIdsForPerspective(p).includes(partId)));
193
+ if (targetPerspective && targetPerspective !== this.activePerspective) {
194
+ this.activatePerspective(targetPerspective);
195
+ }
196
+ const host = this._rootEl?.querySelector(`[data-part-id="${partId}"]`);
197
+ const pane = host?.closest('.ws-pane') ?? host;
198
+ if (!pane) return false;
199
+ pane.scrollIntoView?.({ behavior: 'smooth', block: 'center' });
200
+ pane.classList.remove('ws-pane-flash');
201
+ void pane.offsetWidth;
202
+ pane.classList.add('ws-pane-flash');
203
+ setTimeout(() => pane.classList.remove('ws-pane-flash'), 1500);
204
+ return true;
205
+ }
206
+
172
207
  _renderPerspectiveButtons() {
173
208
  if (!this._perspectivesEl) return;
174
- render(this._perspectivesEl, [...this.perspectives.keys()].map(name => ({
175
- tag: 'button',
176
- cls: ['ws-perspective-btn', name === this.activePerspective && 'ws-active'],
177
- text: name,
178
- attrs: { type: 'button' },
179
- on: { click: () => this.activatePerspective(name) },
180
- })));
209
+ render(this._perspectivesEl, [...this.perspectives.keys()].map(name => {
210
+ const parts = this.partIdsForPerspective(name)
211
+ .map(id => this.getPart(id))
212
+ .filter(Boolean);
213
+ const hasSubmenu = parts.length > 1;
214
+ let listEl = null;
215
+ let submenuEl = null;
216
+
217
+ const buildSubmenuRows = (filterText = '') => {
218
+ const q = filterText.trim().toLowerCase();
219
+ const filtered = q
220
+ ? parts.filter(p => (p.title ?? p.id).toLowerCase().includes(q))
221
+ : parts;
222
+ return filtered.map(part => ({
223
+ cls: 'ws-perspective-submenu-row',
224
+ children: [
225
+ {
226
+ tag: 'button',
227
+ cls: 'ws-perspective-submenu-item',
228
+ text: part.title ?? part.id,
229
+ attrs: { type: 'button', title: `Jump to ${part.title ?? part.id}` },
230
+ on: {
231
+ click: (e) => {
232
+ e.stopPropagation();
233
+ submenuEl?.classList.remove('ws-submenu-open');
234
+ this.focusPart(part.id, name);
235
+ },
236
+ },
237
+ },
238
+ ...(part.actions ?? []).filter(a => !a.separator).map(action => ({
239
+ tag: 'button',
240
+ cls: 'ws-perspective-submenu-action',
241
+ text: action.label,
242
+ attrs: { type: 'button', title: action.title ?? action.label },
243
+ on: {
244
+ click: (e) => {
245
+ e.stopPropagation();
246
+ submenuEl?.classList.remove('ws-submenu-open');
247
+ action.onClick?.(part, e);
248
+ },
249
+ },
250
+ })),
251
+ ],
252
+ }));
253
+ };
254
+
255
+ return {
256
+ cls: 'ws-perspective-item',
257
+ on: {
258
+ mouseenter: () => submenuEl?.classList.add('ws-submenu-open'),
259
+ mouseleave: () => submenuEl?.classList.remove('ws-submenu-open'),
260
+ },
261
+ children: [
262
+ {
263
+ tag: 'button',
264
+ cls: ['ws-perspective-btn', name === this.activePerspective && 'ws-active'],
265
+ attrs: { type: 'button' },
266
+ on: { click: () => this.activatePerspective(name) },
267
+ children: [
268
+ { tag: 'span', text: name },
269
+ hasSubmenu && { tag: 'span', cls: 'ws-perspective-caret', text: ' ▾' },
270
+ ],
271
+ },
272
+ hasSubmenu && {
273
+ cls: 'ws-perspective-submenu',
274
+ ref: n => { submenuEl = n; },
275
+ children: [
276
+ parts.length > 8 && {
277
+ cls: 'ws-perspective-submenu-search-wrap',
278
+ children: [{
279
+ tag: 'input',
280
+ cls: 'ws-perspective-submenu-search',
281
+ attrs: { type: 'search', placeholder: `Filter ${name} (${parts.length})…` },
282
+ on: {
283
+ click: e => e.stopPropagation(),
284
+ input: e => {
285
+ if (listEl) render(listEl, buildSubmenuRows(e.target.value));
286
+ },
287
+ },
288
+ }],
289
+ },
290
+ {
291
+ cls: 'ws-perspective-submenu-list',
292
+ ref: n => { listEl = n; },
293
+ children: buildSubmenuRows(),
294
+ },
295
+ ],
296
+ },
297
+ ],
298
+ };
299
+ }));
181
300
  }
182
301
 
183
302
  /* ── Theming ────────────────────────────────────────────────────────── */
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  RenderEngine, ArchimateModel, ArchimateSpecializationSelector, DerivedRelationships, DiagramTabs, ModelTree,
3
3
  SettingsManager, buildAnalysisPanel, buildModelTreePanel, fromArchimateView, parseArchiModel, toArchimateModel,
4
+ NavigatorModel, NavigatorPanel, buildNavigatorPanel,
4
5
  parseArchiFile, toArchiFile, toArchiExport, showGlobalSettingsDialog, showPropertiesDialog, showDiagramPropertiesDialog,
5
6
  } from '../index.js';
6
7
 
@@ -21,6 +22,9 @@ export const ARCHIMATE_SERVICES = Object.freeze({
21
22
  SettingsManager,
22
23
  buildAnalysisPanel,
23
24
  buildModelTreePanel,
25
+ NavigatorModel,
26
+ NavigatorPanel,
27
+ buildNavigatorPanel,
24
28
  fromArchimateView,
25
29
  parseArchiModel,
26
30
  parseArchiFile,
@@ -281,7 +281,7 @@ export class ArchimateCanvasPart extends EditorPart {
281
281
  if (!analysisHost) return;
282
282
  analysisHost.replaceChildren(buildAnalysisPanel(doc, {
283
283
  model, elementId: elementId && model.getElement(elementId) ? elementId : null,
284
- onSelectItem: (info) => this.modelTree.select(info.id, info.kind),
284
+ onSelectItem: (info) => this.modelTree.select(info.id, info.kind), onSelectView: (viewId) => { if (viewId !== this.model.currentViewId) this.model.switchTo(viewId); },
285
285
  }));
286
286
  };
287
287
  this.editor.onSelectionChange(({ templateId }) => {
@@ -57,7 +57,42 @@ export const WORKSPACE_CSS = `
57
57
  }
58
58
  .ws-toolbar-title { font-weight: 600; }
59
59
  .ws-toolbar-spacer { flex: 1; }
60
- .ws-perspectives { display: flex; gap: 2px; }
60
+ .ws-perspectives { display: flex; gap: 2px; }
61
+ .ws-perspective-item { position: relative; display: inline-flex; }
62
+ .ws-perspective-caret { font-size: 10px; opacity: .75; }
63
+ .ws-perspective-submenu {
64
+ display: none; position: absolute; top: 100%; right: 0; z-index: 1600;
65
+ min-width: 260px; max-width: 380px; background: var(--ws-panel-bg); color: var(--ws-fg);
66
+ border: 1px solid var(--ws-border); border-radius: 0 0 6px 6px;
67
+ box-shadow: 0 8px 24px rgba(0,0,0,.28); padding: 4px 0;
68
+ }
69
+ .ws-perspective-submenu.ws-submenu-open { display: flex; flex-direction: column; }
70
+ .ws-perspective-submenu-search-wrap { padding: 4px 8px 6px; border-bottom: 1px solid var(--ws-border); }
71
+ .ws-perspective-submenu-search {
72
+ width: 100%; padding: 4px 8px; font: inherit; font-size: 12px;
73
+ background: var(--ws-bg); color: var(--ws-fg); border: 1px solid var(--ws-border); border-radius: 4px;
74
+ }
75
+ .ws-perspective-submenu-list { max-height: 68vh; overflow-y: auto; }
76
+ .ws-perspective-submenu-row {
77
+ display: flex; align-items: center; gap: 4px; padding: 1px 6px;
78
+ }
79
+ .ws-perspective-submenu-row:hover { background: rgba(127,127,127,.15); }
80
+ .ws-perspective-submenu-item {
81
+ flex: 1 1 auto; text-align: left; padding: 5px 6px; font: inherit; font-size: 12px;
82
+ background: transparent; color: var(--ws-fg); border: none; cursor: pointer;
83
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
84
+ }
85
+ .ws-perspective-submenu-action {
86
+ flex: 0 0 auto; padding: 2px 6px; font: inherit; font-size: 10px; font-family: monospace;
87
+ background: rgba(127,127,127,.15); color: var(--ws-fg);
88
+ border: 1px solid var(--ws-border); border-radius: 3px; cursor: pointer; opacity: .8;
89
+ }
90
+ .ws-perspective-submenu-action:hover { opacity: 1; background: var(--ws-accent); color: #000; border-color: var(--ws-accent); }
91
+ @keyframes ws-pane-flash-anim {
92
+ 0%, 30% { box-shadow: 0 0 0 3px var(--ws-accent), 0 6px 20px rgba(0,0,0,.22); }
93
+ 100% { box-shadow: none; }
94
+ }
95
+ .ws-pane-flash { animation: ws-pane-flash-anim 1.4s ease-out; }
61
96
  .ws-perspective-btn {
62
97
  padding: 4px 12px; font: inherit; font-size: 12px; cursor: pointer;
63
98
  color: var(--ws-toolbar-fg); background: rgba(127,127,127,.12);