@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.
- package/README.md +45 -19
- package/bin/renderengine.mjs +157 -0
- package/dist/renderengine-workspace.umd.js +49391 -39748
- package/dist/renderengine.umd.js +25366 -15650
- package/documentation/REFERENCE.md +38 -0
- package/package.json +6 -1
- package/src/CanvasRenderer.js +225 -200
- package/src/SVGRenderer.js +476 -454
- package/src/archimate.js +22 -2
- package/src/archimateArchiFormat.js +1735 -1701
- package/src/archimateArchive.js +36 -7
- package/src/archimateCSV.js +93 -37
- package/src/archimateDrawio.js +2 -0
- package/src/archimateExchangeFormat.js +3 -1
- package/src/chartCatalog.js +219 -0
- package/src/charting/Annotations.js +169 -0
- package/src/charting/ArchimateDiagramEditor.js +54 -10
- package/src/charting/Axis.js +217 -5
- package/src/charting/Chart.js +99 -9
- package/src/charting/Chart3D.js +3 -0
- package/src/charting/ChartBox.js +8 -1
- package/src/charting/ColorPalette.js +42 -4
- package/src/charting/DiagramEditor.js +174 -39
- package/src/charting/DiagramEditorCommands.js +28 -0
- package/src/charting/Edge.js +7 -0
- package/src/charting/Hierarchy.js +114 -0
- package/src/charting/InteractionManager.js +4 -0
- package/src/charting/ModelFileFormat.js +5 -1
- package/src/charting/SettingsManager.js +35 -0
- package/src/charting/ShapePaths.js +82 -10
- package/src/charting/archimate/ArchimateCsvFileFormat.js +51 -12
- package/src/charting/archimate/ArchimateElementTemplate.js +235 -231
- package/src/charting/charts/AlluvialDiagram.js +311 -0
- package/src/charting/charts/AreaChart.js +52 -15
- package/src/charting/charts/BarChart.js +38 -3
- package/src/charting/charts/BarChart3D.js +5 -3
- package/src/charting/charts/BarChartBase.js +26 -6
- package/src/charting/charts/BeeswarmChart.js +164 -0
- package/src/charting/charts/BoxPlotChart.js +23 -1
- package/src/charting/charts/CalendarHeatmapChart.js +2 -1
- package/src/charting/charts/CandlestickChart.js +172 -4
- package/src/charting/charts/ChordDiagram.js +105 -2
- package/src/charting/charts/CirclePackChart.js +81 -0
- package/src/charting/charts/ComboChart.js +233 -0
- package/src/charting/charts/ContourChart.js +310 -0
- package/src/charting/charts/DonutChart3D.js +13 -0
- package/src/charting/charts/DumbbellChart.js +217 -0
- package/src/charting/charts/EcdfChart.js +150 -0
- package/src/charting/charts/FunnelChart.js +4 -1
- package/src/charting/charts/GeoMapChart.js +132 -11
- package/src/charting/charts/GroupedBarChart.js +44 -3
- package/src/charting/charts/GroupedDistributionChart.js +26 -1
- package/src/charting/charts/HeatmapChart.js +2 -2
- package/src/charting/charts/HexbinChart.js +137 -0
- package/src/charting/charts/HierarchyChart.js +77 -3
- package/src/charting/charts/HorizonChart.js +105 -0
- package/src/charting/charts/KagiChart.js +167 -0
- package/src/charting/charts/LineChart.js +74 -18
- package/src/charting/charts/OhlcChart.js +79 -0
- package/src/charting/charts/ParallelCoordinatesChart.js +9 -1
- package/src/charting/charts/PieChart.js +195 -17
- package/src/charting/charts/PieChart3D.js +137 -0
- package/src/charting/charts/PointAndFigureChart.js +198 -0
- package/src/charting/charts/PolarAreaChart.js +189 -0
- package/src/charting/charts/RadarChart.js +7 -1
- package/src/charting/charts/RadialBarChart.js +5 -2
- package/src/charting/charts/RenkoChart.js +178 -0
- package/src/charting/charts/RidgelineChart.js +113 -0
- package/src/charting/charts/SankeyDiagram.js +127 -4
- package/src/charting/charts/ScatterChart.js +13 -0
- package/src/charting/charts/ScatterMatrixChart.js +119 -0
- package/src/charting/charts/SlopegraphChart.js +205 -0
- package/src/charting/charts/SparklineTableChart.js +166 -0
- package/src/charting/charts/StackedBarChart.js +48 -5
- package/src/charting/charts/StackedBarChart3DOrbit.js +10 -5
- package/src/charting/charts/StreamGraphChart.js +10 -3
- package/src/charting/charts/SunburstChart.js +27 -7
- package/src/charting/charts/SurfaceChart3D.js +157 -0
- package/src/charting/charts/TreemapChart.js +28 -8
- package/src/charting/charts/ViolinChart.js +18 -0
- package/src/charting/datamodel/ArchimateDataLink.js +70 -0
- package/src/charting/datamodel/DataLineage.js +150 -0
- package/src/charting/datamodel/DataModel.js +83 -1
- package/src/charting/datamodel/ModelMapping.js +87 -0
- package/src/charting/datamodel/SqlDdl.js +110 -85
- package/src/charting/datamodel/index.js +3 -0
- package/src/charting/decision/DecisionWorkbench.js +295 -0
- package/src/charting/diagrams/ArchimateDiagram.js +25 -9
- package/src/charting/diagrams/ArchimateModel.js +1382 -1238
- package/src/charting/diagrams/GraphDiagram.js +1424 -1350
- package/src/charting/diagrams/SketchView.js +121 -0
- package/src/charting/diagrams/sketchBoxKinds.js +30 -0
- package/src/charting/modelTree/AnalysisPanel.js +101 -23
- package/src/charting/modelTree/NavigatorModel.js +410 -0
- package/src/charting/modelTree/NavigatorPanel.js +453 -0
- package/src/charting/pivot/PivotChart.js +109 -4
- package/src/charting/pivot/PivotGridChart.js +321 -33
- package/src/charting/pivot/PivotView.js +82 -0
- package/src/charting/report/TemplatedReport.js +547 -0
- package/src/charting/templates/BoxTemplate.js +28 -27
- package/src/charting/templates/PackageTemplate.js +26 -25
- package/src/charting/templates/SwimlaneTemplate.js +19 -18
- package/src/charting/templates/Template.js +219 -212
- package/src/cli.js +146 -0
- package/src/index.js +3370 -2995
- package/src/workspace/Workspace.js +126 -7
- package/src/workspace/archimateServices.js +4 -0
- package/src/workspace/parts/ArchimateCanvasPart.js +1 -1
- package/src/workspace/styles.js +36 -1
package/src/archimateArchive.js
CHANGED
|
@@ -53,6 +53,15 @@ export function parseArchiFile(input) {
|
|
|
53
53
|
visual.imagePath = url;
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
|
+
for (const el of model.archi?.elements || []) {
|
|
57
|
+
if (el.attributes?.imagePath) {
|
|
58
|
+
const url = resolve(el.attributes.imagePath);
|
|
59
|
+
if (url) {
|
|
60
|
+
el.attributes.archiImagePath = el.attributes.imagePath;
|
|
61
|
+
el.attributes.imagePath = url;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
56
65
|
return model;
|
|
57
66
|
}
|
|
58
67
|
|
|
@@ -66,21 +75,41 @@ export function parseArchiFile(input) {
|
|
|
66
75
|
export function toArchiFile(model, views) {
|
|
67
76
|
const copies = _copyTrees(views);
|
|
68
77
|
const pictures = new Map(); // data: URL -> archive path
|
|
69
|
-
|
|
70
|
-
const url =
|
|
78
|
+
const registerPicture = (target, pathKey = 'imagePath', archiKey = 'archiImagePath') => {
|
|
79
|
+
const url = target[pathKey];
|
|
71
80
|
if (!url?.startsWith('data:')) return;
|
|
72
81
|
if (!pictures.has(url)) {
|
|
73
82
|
// Its own archive path when it came from one (and no other picture took it), else a new one.
|
|
74
83
|
const taken = new Set(pictures.values());
|
|
75
|
-
const own =
|
|
84
|
+
const own = target[archiKey] && !taken.has(target[archiKey]) ? target[archiKey] : null;
|
|
76
85
|
const { mime } = _parseDataUrl(url);
|
|
77
86
|
let path = own;
|
|
78
|
-
for (let n = pictures.size + 1; !path || (path !== own && taken.has(path)); n++)
|
|
87
|
+
for (let n = pictures.size + 1; !path || (path !== own && taken.has(path)); n++) {
|
|
88
|
+
path = `${IMAGE_FOLDER}image-${n}.${EXTENSION_BY_MIME[mime] ?? 'bin'}`;
|
|
89
|
+
}
|
|
79
90
|
pictures.set(url, path);
|
|
80
91
|
}
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
92
|
+
target[pathKey] = pictures.get(url);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
_eachVisual(copies, (visual) => registerPicture(visual));
|
|
96
|
+
|
|
97
|
+
let modelForXml = model;
|
|
98
|
+
if (model?.archi?.elements?.some(e => e.attributes?.imagePath?.startsWith('data:'))) {
|
|
99
|
+
modelForXml = {
|
|
100
|
+
...model,
|
|
101
|
+
archi: {
|
|
102
|
+
...model.archi,
|
|
103
|
+
elements: model.archi.elements.map(e => {
|
|
104
|
+
if (!e.attributes?.imagePath?.startsWith('data:')) return e;
|
|
105
|
+
const clonedAttr = { ...e.attributes };
|
|
106
|
+
registerPicture(clonedAttr);
|
|
107
|
+
return { ...e, attributes: clonedAttr };
|
|
108
|
+
}),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const xml = toArchiXML(modelForXml, copies);
|
|
84
113
|
if (!pictures.size) return { data: xml, archive: false, mimeType: 'application/xml' };
|
|
85
114
|
|
|
86
115
|
const zip = new ZipArchive().add(ARCHI_MODEL_ENTRY, xml);
|
package/src/archimateCSV.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { parseCsvTable } from './csvTable.js';
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
|
-
* archimateCSV —
|
|
4
|
-
* models
|
|
5
|
-
* for the two shapes we need.
|
|
6
|
-
*
|
|
7
|
-
* Two files are used:
|
|
8
|
-
* - elements.csv: id, name, type, layer, documentation, properties
|
|
9
|
-
* - relationships.csv: id, source, target, kind, label, documentation, properties
|
|
4
|
+
* archimateCSV — CSV import/export for renderengine element/relationship
|
|
5
|
+
* models and Archi interchange.
|
|
10
6
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* Supports three files / tables:
|
|
8
|
+
* - elements.csv: id, name, type, layer, documentation, properties (or Archi ID, Type, Name, Documentation)
|
|
9
|
+
* - relations.csv / relationships.csv: id, source, target, kind, label, documentation, properties (or Archi ID, Type, Name, Documentation, Source, Target)
|
|
10
|
+
* - properties.csv: ID, Key, Value (or id, key, value)
|
|
13
11
|
*/
|
|
14
12
|
|
|
15
13
|
function escapeCsvCell(value) {
|
|
@@ -66,8 +64,8 @@ export function exportRelationshipsCSV(relationships = []) {
|
|
|
66
64
|
escapeCsvCell(rel.id),
|
|
67
65
|
escapeCsvCell(rel.source),
|
|
68
66
|
escapeCsvCell(rel.target),
|
|
69
|
-
escapeCsvCell(rel.kind),
|
|
70
|
-
escapeCsvCell(rel.label),
|
|
67
|
+
escapeCsvCell(rel.kind || rel.type),
|
|
68
|
+
escapeCsvCell(rel.label || rel.name),
|
|
71
69
|
escapeCsvCell(rel.documentation),
|
|
72
70
|
escapeCsvCell(stringifyProperties(rel.properties)),
|
|
73
71
|
].join(','));
|
|
@@ -75,18 +73,55 @@ export function exportRelationshipsCSV(relationships = []) {
|
|
|
75
73
|
return lines.join('\n');
|
|
76
74
|
}
|
|
77
75
|
|
|
76
|
+
/** Export properties of elements and relationships to properties.csv format (ID, Key, Value). */
|
|
77
|
+
export function exportPropertiesCSV(elements = [], relationships = []) {
|
|
78
|
+
const header = ['ID', 'Key', 'Value'];
|
|
79
|
+
const lines = [header.join(',')];
|
|
80
|
+
const exportItemProps = (item) => {
|
|
81
|
+
if (!item || !Array.isArray(item.properties)) return;
|
|
82
|
+
for (const p of item.properties) {
|
|
83
|
+
const k = p.key ?? p.name;
|
|
84
|
+
const v = p.value;
|
|
85
|
+
if (k != null) {
|
|
86
|
+
lines.push([escapeCsvCell(item.id), escapeCsvCell(k), escapeCsvCell(v)].join(','));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
for (const el of elements) exportItemProps(el);
|
|
91
|
+
for (const rel of relationships) exportItemProps(rel);
|
|
92
|
+
return lines.join('\n');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Parse a properties CSV string into a Map of itemId -> Array<{name, value}>. */
|
|
96
|
+
export function importPropertiesCSV(csv) {
|
|
97
|
+
const rows = parseCsv(csv);
|
|
98
|
+
const byId = new Map();
|
|
99
|
+
for (const row of rows) {
|
|
100
|
+
const id = row.ID ?? row.id;
|
|
101
|
+
const key = row.Key ?? row.key ?? row.Name ?? row.name;
|
|
102
|
+
const val = row.Value ?? row.value ?? '';
|
|
103
|
+
if (id && key) {
|
|
104
|
+
if (!byId.has(id)) byId.set(id, []);
|
|
105
|
+
byId.get(id).push({ name: key, value: val });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return byId;
|
|
109
|
+
}
|
|
110
|
+
|
|
78
111
|
/** Parse an elements CSV string into element objects. */
|
|
79
112
|
export function importElementsCSV(csv) {
|
|
80
113
|
const rows = parseCsv(csv);
|
|
81
114
|
return rows.map(row => {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
115
|
+
const id = row.id ?? row.ID;
|
|
116
|
+
const name = row.name ?? row.Name;
|
|
117
|
+
const type = row.type ?? row.Type;
|
|
118
|
+
const layer = row.layer ?? row.Layer;
|
|
119
|
+
const doc = row.documentation ?? row.Documentation;
|
|
120
|
+
|
|
121
|
+
const el = { id, name, type };
|
|
122
|
+
if (layer) el.layer = layer;
|
|
123
|
+
if (doc) el.documentation = doc;
|
|
124
|
+
const props = parseProperties(row.properties ?? row.Properties);
|
|
90
125
|
if (props) el.properties = props;
|
|
91
126
|
return el;
|
|
92
127
|
});
|
|
@@ -96,32 +131,53 @@ export function importElementsCSV(csv) {
|
|
|
96
131
|
export function importRelationshipsCSV(csv) {
|
|
97
132
|
const rows = parseCsv(csv);
|
|
98
133
|
return rows.map(row => {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
134
|
+
const id = row.id ?? row.ID;
|
|
135
|
+
const source = row.source ?? row.Source;
|
|
136
|
+
const target = row.target ?? row.Target;
|
|
137
|
+
const kind = row.kind ?? row.Kind ?? row.type ?? row.Type;
|
|
138
|
+
const label = row.label ?? row.Label ?? row.name ?? row.Name;
|
|
139
|
+
const doc = row.documentation ?? row.Documentation;
|
|
140
|
+
|
|
141
|
+
const rel = { id, source, target, kind };
|
|
142
|
+
if (label) rel.label = label;
|
|
143
|
+
if (doc) rel.documentation = doc;
|
|
144
|
+
const props = parseProperties(row.properties ?? row.Properties);
|
|
108
145
|
if (props) rel.properties = props;
|
|
109
146
|
return rel;
|
|
110
147
|
});
|
|
111
148
|
}
|
|
112
149
|
|
|
113
|
-
/** Convenience: export
|
|
150
|
+
/** Convenience: export all three tables in one call. Returns { elementsCSV, relationshipsCSV, propertiesCSV }. */
|
|
114
151
|
export function exportModelCSV(model = {}) {
|
|
152
|
+
const elements = model.elements || [];
|
|
153
|
+
const relationships = model.relationships || [];
|
|
115
154
|
return {
|
|
116
|
-
elementsCSV: exportElementsCSV(
|
|
117
|
-
relationshipsCSV: exportRelationshipsCSV(
|
|
155
|
+
elementsCSV: exportElementsCSV(elements),
|
|
156
|
+
relationshipsCSV: exportRelationshipsCSV(relationships),
|
|
157
|
+
propertiesCSV: exportPropertiesCSV(elements, relationships),
|
|
118
158
|
};
|
|
119
159
|
}
|
|
120
160
|
|
|
121
|
-
/** Convenience: import
|
|
122
|
-
export function importModelCSV(elementsCSV = '', relationshipsCSV = '') {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
161
|
+
/** Convenience: import all three tables in one call. Attaches parsed properties to items. */
|
|
162
|
+
export function importModelCSV(elementsCSV = '', relationshipsCSV = '', propertiesCSV = '') {
|
|
163
|
+
const elements = importElementsCSV(elementsCSV);
|
|
164
|
+
const relationships = importRelationshipsCSV(relationshipsCSV);
|
|
165
|
+
|
|
166
|
+
if (propertiesCSV && propertiesCSV.trim()) {
|
|
167
|
+
const propsById = importPropertiesCSV(propertiesCSV);
|
|
168
|
+
for (const el of elements) {
|
|
169
|
+
const props = propsById.get(el.id);
|
|
170
|
+
if (props?.length) {
|
|
171
|
+
el.properties = [...(el.properties || []), ...props];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
for (const rel of relationships) {
|
|
175
|
+
const props = propsById.get(rel.id);
|
|
176
|
+
if (props?.length) {
|
|
177
|
+
rel.properties = [...(rel.properties || []), ...props];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return { elements, relationships };
|
|
127
183
|
}
|
package/src/archimateDrawio.js
CHANGED
|
@@ -53,6 +53,8 @@ export const DRAWIO_ELEMENT_STYLES = Object.freeze({
|
|
|
53
53
|
location: app('location', 'square'),
|
|
54
54
|
grouping: box({ shape: 'folder', spacingTop: 10, tabWidth: 100, tabHeight: 25, tabPosition: 'left', dashed: 1, outlineConnect: undefined }),
|
|
55
55
|
junction: box({ verticalLabelPosition: 'bottom', verticalAlign: 'top', outlineConnect: undefined }, 'ellipse;'),
|
|
56
|
+
'and-junction': box({ verticalLabelPosition: 'bottom', verticalAlign: 'top', outlineConnect: undefined }, 'ellipse;fillColor=#000000;'),
|
|
57
|
+
'or-junction': box({ verticalLabelPosition: 'bottom', verticalAlign: 'top', outlineConnect: undefined }, 'ellipse;fillColor=#ffffff;'),
|
|
56
58
|
});
|
|
57
59
|
|
|
58
60
|
/** The other boxes a view draws: notes, groups (folders), pictures, canvas boxes; and a type with no shape of its own. */
|
|
@@ -353,7 +353,9 @@ export function toExchangeXML(model, views = []) {
|
|
|
353
353
|
] : [];
|
|
354
354
|
const textLines = (tag, text, indent) => text ? [`${indent}<${tag}>${escapeXml(text)}</${tag}>`] : [];
|
|
355
355
|
const conceptPairs = (concept, extra = []) => [
|
|
356
|
-
...
|
|
356
|
+
...(Array.isArray(concept.properties)
|
|
357
|
+
? concept.properties.map(p => ({ key: p.name ?? p.key ?? '', value: p.value == null ? '' : String(p.value) }))
|
|
358
|
+
: Object.entries(typedArrayToProperties(concept.properties)).map(([key, value]) => ({ key, value }))),
|
|
357
359
|
...extra,
|
|
358
360
|
];
|
|
359
361
|
|
package/src/chartCatalog.js
CHANGED
|
@@ -242,6 +242,16 @@ export const CHART_CATALOG = [
|
|
|
242
242
|
dataShape: 'Array<{label, value}> — angular categories with radial bar length',
|
|
243
243
|
streamShape: 'flat',
|
|
244
244
|
},
|
|
245
|
+
{
|
|
246
|
+
key: 'polarArea', label: 'Polar Area (Nightingale Rose)', method: 'polarAreaChart', category: '2d',
|
|
247
|
+
coordSystem: COORD_SYSTEM.RADIAL, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.ISOMETRIC,
|
|
248
|
+
axes: [
|
|
249
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.RADIAL_AXIS, required: true },
|
|
250
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.RADIAL_DISTANCE, required: true },
|
|
251
|
+
],
|
|
252
|
+
dataShape: 'Array<{label, value, exploded?}> — equal-angle wedges whose radius (or area) encodes value; supports 3D extrusion ({extrude3D:true}) and hover pull-out',
|
|
253
|
+
streamShape: 'flat',
|
|
254
|
+
},
|
|
245
255
|
{
|
|
246
256
|
key: 'populationPyramid', label: 'Population Pyramid', method: 'populationPyramid', category: '2d',
|
|
247
257
|
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.SEMANTIC, camera: CAMERA_MODE.NONE,
|
|
@@ -554,6 +564,26 @@ export const CHART_CATALOG = [
|
|
|
554
564
|
dataShape: 'Array<{label, value, depth?}> — a single fixed-angle isometric shadow per bar, not a real camera (see bar3DOrbit for that)',
|
|
555
565
|
streamShape: 'flat',
|
|
556
566
|
},
|
|
567
|
+
{
|
|
568
|
+
key: 'pie3D', label: 'Pie (3D)', method: 'pieChart3D', category: '3d',
|
|
569
|
+
coordSystem: COORD_SYSTEM.RADIAL, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.ISOMETRIC,
|
|
570
|
+
axes: [
|
|
571
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.ANGLE_OR_AREA, required: true },
|
|
572
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.ANGLE_OR_AREA, required: true },
|
|
573
|
+
],
|
|
574
|
+
dataShape: 'Array<{label, value, exploded?}> — extruded 3D tilted pie with cylinder skirt, radial cut walls, exploded slices, and hover slice pull-out',
|
|
575
|
+
streamShape: 'flat',
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
key: 'donut3D', label: 'Donut (3D)', method: 'donutChart3D', category: '3d',
|
|
579
|
+
coordSystem: COORD_SYSTEM.RADIAL, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.ISOMETRIC,
|
|
580
|
+
axes: [
|
|
581
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.ANGLE_OR_AREA, required: true },
|
|
582
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.ANGLE_OR_AREA, required: true },
|
|
583
|
+
],
|
|
584
|
+
dataShape: 'Array<{label, value, exploded?}> — extruded 3D tilted doughnut (innerRadiusRatio=0.5) with inner/outer cylinder skirts, exploded slices, and hover slice pull-out',
|
|
585
|
+
streamShape: 'flat',
|
|
586
|
+
},
|
|
557
587
|
{
|
|
558
588
|
key: 'bubble3D', label: 'Bubble (3D)', method: 'bubbleChart3D', category: '3d',
|
|
559
589
|
coordSystem: COORD_SYSTEM.ORBIT_3D, title: true, legend: false, colorMode: COLOR_MODE.GROUPED_FIELD, camera: CAMERA_MODE.ORBIT,
|
|
@@ -633,6 +663,195 @@ export const CHART_CATALOG = [
|
|
|
633
663
|
dataShape: 'Array<{x, z, values:number[]}> — same grid as bar3DOrbit, each cell a stack of segments; colors indexed by segment position, not z-group',
|
|
634
664
|
streamShape: 'none', // fixed x*z grid
|
|
635
665
|
},
|
|
666
|
+
{
|
|
667
|
+
key: 'surface3D', label: 'Surface Mesh (3D Orbit)', method: 'surfaceChart3D', category: '3d',
|
|
668
|
+
coordSystem: COORD_SYSTEM.ORBIT_3D, title: true, legend: false, colorMode: COLOR_MODE.SCALE, camera: CAMERA_MODE.ORBIT,
|
|
669
|
+
axes: [
|
|
670
|
+
{ role: 'x', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
671
|
+
{ role: 'z', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_Z, required: true },
|
|
672
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y_HEIGHT, required: true },
|
|
673
|
+
],
|
|
674
|
+
dataShape: 'Array<{x, z, value}> or {xLabels, zLabels, values:number[][]} — continuous 3D surface mesh with gradient shading, wireframe, and real orbit camera',
|
|
675
|
+
streamShape: 'none',
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
key: 'dumbbell', label: 'Dumbbell / Gap Chart', method: 'dumbbellChart', category: '2d',
|
|
679
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
680
|
+
axes: [
|
|
681
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
682
|
+
{ role: 'start', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
683
|
+
{ role: 'end', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
684
|
+
],
|
|
685
|
+
dataShape: 'Array<{label, start, end}> or multi-series Array<{name, values}> — connected pair of dots showing before/after or target/actual change across categories',
|
|
686
|
+
streamShape: 'flat',
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
key: 'slopegraph', label: 'Slopegraph', method: 'slopegraph', category: '2d',
|
|
690
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
691
|
+
axes: [
|
|
692
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_ORDER, required: true },
|
|
693
|
+
{ role: 'values', kind: AXIS_KIND.NUMERIC_LIST, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
694
|
+
],
|
|
695
|
+
dataShape: 'Array<{label, values: number[]}>, Array<{label, start, end}>, or multi-series — connects categories across stages with direct labels and hover highlighting',
|
|
696
|
+
streamShape: 'flat',
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
key: 'circlePack', label: 'Circle Packing', method: 'circlePackChart', category: '2d',
|
|
700
|
+
coordSystem: COORD_SYSTEM.RADIAL, title: true, legend: false, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
701
|
+
axes: [
|
|
702
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.ANGLE_OR_AREA, required: true },
|
|
703
|
+
{ role: 'group', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_ORDER, required: false },
|
|
704
|
+
],
|
|
705
|
+
dataShape: 'Array<{label, value?, children?}> — nested tangent circles sized by value with translucent branch containment and hover elevation',
|
|
706
|
+
streamShape: 'flat',
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
key: 'ridgeline', label: 'Ridgeline / Joy Plot', method: 'ridgelineChart', category: 'statistical',
|
|
710
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
711
|
+
axes: [
|
|
712
|
+
{ role: 'group', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_ORDER, required: true },
|
|
713
|
+
{ role: 'sample', kind: AXIS_KIND.RAW_SAMPLE, channel: ENCODING_CHANNEL.DERIVED, required: true },
|
|
714
|
+
],
|
|
715
|
+
dataShape: 'Array<{label, values: number[]}> — vertically staggered, partially overlapping Gaussian-KDE density curves (Joy plot) with median lines',
|
|
716
|
+
streamShape: 'grouped-sample',
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
key: 'beeswarm', label: 'Beeswarm / Raincloud Plot', method: 'beeswarmChart', category: 'statistical',
|
|
720
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
721
|
+
axes: [
|
|
722
|
+
{ role: 'group', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
723
|
+
{ role: 'sample', kind: AXIS_KIND.RAW_SAMPLE, channel: ENCODING_CHANNEL.DERIVED, required: true },
|
|
724
|
+
],
|
|
725
|
+
dataShape: 'Array<{label, values: number[]}> — individual sample points circle-packed along each group slot; Raincloud mode pairs half-KDE cloud, mini-box, and packed dots',
|
|
726
|
+
streamShape: 'grouped-sample',
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
key: 'combo', label: 'Combo (Bars & Lines)', method: 'comboChart', category: '2d',
|
|
730
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
731
|
+
axes: [
|
|
732
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
733
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
734
|
+
{ role: 'series', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.COLOR, required: true },
|
|
735
|
+
],
|
|
736
|
+
dataShape: 'Array<{name, type?:"bar"|"line"|"area", yAxis?:"left"|"right", values}> — pairs bar series with lines/areas and optional secondary right Y-axis',
|
|
737
|
+
streamShape: 'series',
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
key: 'hexbin', label: 'Hexbin (2D Density)', method: 'hexbinChart', category: 'statistical',
|
|
741
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.SCALE, camera: CAMERA_MODE.NONE,
|
|
742
|
+
axes: [
|
|
743
|
+
{ role: 'x', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
744
|
+
{ role: 'y', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
745
|
+
],
|
|
746
|
+
dataShape: 'Array<{x, y, value?}> or Array<[x, y]> — 2D hexagonal binning and density plot for dense point clouds, eliminating overplotting',
|
|
747
|
+
streamShape: 'flat',
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
key: 'ecdf', label: 'Empirical CDF (Step Plot)', method: 'ecdfChart', category: 'statistical',
|
|
751
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
752
|
+
axes: [
|
|
753
|
+
{ role: 'sample', kind: AXIS_KIND.RAW_SAMPLE, channel: ENCODING_CHANNEL.DERIVED, required: true },
|
|
754
|
+
],
|
|
755
|
+
dataShape: 'number[] or Array<{label, values: number[]}> — cumulative distribution step function (0..1) with median and Kolmogorov-Smirnov distance comparison',
|
|
756
|
+
streamShape: 'grouped-sample',
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
key: 'splom', label: 'Scatter Plot Matrix (SPLOM)', method: 'scatterMatrix', category: 'statistical',
|
|
760
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: true, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
761
|
+
axes: [
|
|
762
|
+
{ role: 'dimensions', kind: AXIS_KIND.NUMERIC_LIST, channel: ENCODING_CHANNEL.POSITION_ORDER, required: true },
|
|
763
|
+
],
|
|
764
|
+
dataShape: 'Array<object> with options.dimensions — N x N grid of pairwise scatter plots with univariate KDE curves on the diagonal',
|
|
765
|
+
streamShape: 'flat',
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
key: 'sparklineTable', label: 'Sparkline Table', method: 'sparklineTable', category: '2d',
|
|
769
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.NONE, camera: CAMERA_MODE.NONE,
|
|
770
|
+
axes: [
|
|
771
|
+
{ role: 'row', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_ORDER, required: true },
|
|
772
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.TEXT_VALUE, required: true },
|
|
773
|
+
],
|
|
774
|
+
dataShape: 'Array<{label, value, target?, sparkline?: number[], delta?: number, status?}> — multi-metric table embedding inline sparklines and bullet KPI bars',
|
|
775
|
+
streamShape: 'flat',
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
key: 'horizon', label: 'Horizon Chart', method: 'horizonChart', category: '2d',
|
|
779
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
780
|
+
axes: [
|
|
781
|
+
{ role: 'series', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_ORDER, required: true },
|
|
782
|
+
{ role: 'values', kind: AXIS_KIND.NUMERIC_LIST, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
783
|
+
],
|
|
784
|
+
dataShape: 'Array<{label, values: number[]}> — compact layered area strips folding positive and negative magnitude bands into narrow viewports',
|
|
785
|
+
streamShape: 'flat',
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
key: 'ohlc', label: 'OHLC Bar Chart', method: 'ohlcChart', category: '2d',
|
|
789
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.SEMANTIC, camera: CAMERA_MODE.NONE,
|
|
790
|
+
axes: [
|
|
791
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
792
|
+
{ role: 'open', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
793
|
+
{ role: 'high', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
794
|
+
{ role: 'low', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
795
|
+
{ role: 'close', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
796
|
+
],
|
|
797
|
+
dataShape: 'Array<{label, open, high, low, close}> — financial price bar chart with high-low spine, left open tick, and right close tick',
|
|
798
|
+
streamShape: 'flat',
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
key: 'alluvial', label: 'Alluvial Diagram', method: 'alluvialDiagram', category: '2d',
|
|
802
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.PALETTE, camera: CAMERA_MODE.NONE,
|
|
803
|
+
axes: [
|
|
804
|
+
{ role: 'dimensions', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_ORDER, required: true },
|
|
805
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.SHAPE_WIDTH, required: true },
|
|
806
|
+
],
|
|
807
|
+
dataShape: '{dimensions: string[], rows: Array<object>} or Array<{steps: string[], value: number}> — multi-stage categorical flow diagram across 3+ ordered dimensions',
|
|
808
|
+
streamShape: 'none',
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
key: 'renko', label: 'Renko / Heikin-Ashi', method: 'renkoChart', category: '2d',
|
|
812
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.SEMANTIC, camera: CAMERA_MODE.NONE,
|
|
813
|
+
axes: [
|
|
814
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
815
|
+
{ role: 'open', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
816
|
+
{ role: 'high', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
817
|
+
{ role: 'low', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
818
|
+
{ role: 'close', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
819
|
+
],
|
|
820
|
+
dataShape: 'Array<{label, open, high, low, close}> — price trend brick chart filtering out time noise (renko), or modified smoothed momentum candles (mode: "heikinAshi")',
|
|
821
|
+
streamShape: 'flat',
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
key: 'contour', label: 'Contour Plot', method: 'contourChart', category: '2d',
|
|
825
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: true, colorMode: COLOR_MODE.SCALE, camera: CAMERA_MODE.NONE,
|
|
826
|
+
axes: [
|
|
827
|
+
{ role: 'x', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
828
|
+
{ role: 'y', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
829
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.COLOR_SCALE, required: true },
|
|
830
|
+
],
|
|
831
|
+
dataShape: 'number[][] (2D scalar grid) or Array<{x, y, value}> — marching-squares isolines and filled isoband contours with numeric level labels',
|
|
832
|
+
streamShape: 'none',
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
key: 'kagi', label: 'Kagi Chart', method: 'kagiChart', category: '2d',
|
|
836
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.SEMANTIC, camera: CAMERA_MODE.NONE,
|
|
837
|
+
axes: [
|
|
838
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
839
|
+
{ role: 'value', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
840
|
+
],
|
|
841
|
+
dataShape: 'Array<{label, value}> or Array<number> — time-independent price action tracking reversals with Yang and Yin inflection lines',
|
|
842
|
+
streamShape: 'flat',
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
key: 'pointAndFigure', label: 'Point and Figure', method: 'pointAndFigure', category: '2d',
|
|
846
|
+
coordSystem: COORD_SYSTEM.CARTESIAN, title: true, legend: false, colorMode: COLOR_MODE.SEMANTIC, camera: CAMERA_MODE.NONE,
|
|
847
|
+
axes: [
|
|
848
|
+
{ role: 'category', kind: AXIS_KIND.CATEGORICAL, channel: ENCODING_CHANNEL.POSITION_X, required: true },
|
|
849
|
+
{ role: 'high', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
850
|
+
{ role: 'low', kind: AXIS_KIND.NUMERIC, channel: ENCODING_CHANNEL.POSITION_Y, required: true },
|
|
851
|
+
],
|
|
852
|
+
dataShape: 'Array<{label, high, low}> or Array<number> — classical supply/demand chart with columns of rising X and falling O boxes and 45-degree support trendlines',
|
|
853
|
+
streamShape: 'flat',
|
|
854
|
+
},
|
|
636
855
|
];
|
|
637
856
|
|
|
638
857
|
import { ChartRegistry } from './charting/ChartRegistry.js';
|