@opendata-ai/openchart-engine 6.17.0 → 6.19.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/dist/index.d.ts +1 -0
- package/dist/index.js +37 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/compiler/normalize.ts +1 -0
- package/src/sankey/compile-sankey.ts +29 -1
- package/src/sankey/layout.ts +14 -0
- package/src/sankey/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendata-ai/openchart-engine",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.19.0",
|
|
4
4
|
"description": "Headless compiler for openchart: spec validation, data compilation, scales, and layout",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Riley Hilliard",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@opendata-ai/openchart-core": "6.
|
|
48
|
+
"@opendata-ai/openchart-core": "6.19.0",
|
|
49
49
|
"d3-array": "^3.2.0",
|
|
50
50
|
"d3-format": "^3.1.2",
|
|
51
51
|
"d3-interpolate": "^3.0.0",
|
|
@@ -249,6 +249,7 @@ function normalizeSankeySpec(spec: SankeySpec, _warnings: string[]): NormalizedS
|
|
|
249
249
|
iterations: spec.iterations ?? 6,
|
|
250
250
|
linkStyle: spec.linkStyle ?? 'gradient',
|
|
251
251
|
nodeLabelAlign: spec.nodeLabelAlign ?? 'auto',
|
|
252
|
+
nodeSort: spec.nodeSort,
|
|
252
253
|
chrome: normalizeChrome(spec.chrome),
|
|
253
254
|
legend: spec.legend,
|
|
254
255
|
theme: spec.theme ?? {},
|
|
@@ -140,6 +140,8 @@ function computeNodeLabel(
|
|
|
140
140
|
theme: ResolvedTheme,
|
|
141
141
|
nodeWidth: number,
|
|
142
142
|
nodeLabelAlign: 'auto' | 'left' | 'right' = 'auto',
|
|
143
|
+
containerWidth?: number,
|
|
144
|
+
padding?: number,
|
|
143
145
|
): SankeyNodeMark['label'] {
|
|
144
146
|
const depth = node.depth ?? 0;
|
|
145
147
|
|
|
@@ -168,6 +170,20 @@ function computeNodeLabel(
|
|
|
168
170
|
const y1 = node.y1 ?? 0;
|
|
169
171
|
const midY = (y0 + y1) / 2;
|
|
170
172
|
|
|
173
|
+
// Compute maxWidth: space from label position to the container edge
|
|
174
|
+
const pad = padding ?? 0;
|
|
175
|
+
let maxWidth: number | undefined;
|
|
176
|
+
if (containerWidth !== undefined) {
|
|
177
|
+
if (placeLeft) {
|
|
178
|
+
// Label goes left from x0: available space is from left padding to x0
|
|
179
|
+
maxWidth = x0 - LABEL_GAP - pad;
|
|
180
|
+
} else {
|
|
181
|
+
// Label goes right from x1: available space is from x1 to right edge
|
|
182
|
+
maxWidth = containerWidth - pad - (x1 + LABEL_GAP);
|
|
183
|
+
}
|
|
184
|
+
if (maxWidth !== undefined && maxWidth < 0) maxWidth = 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
171
187
|
if (placeLeft) {
|
|
172
188
|
return {
|
|
173
189
|
text: node.label ?? node.id,
|
|
@@ -175,6 +191,7 @@ function computeNodeLabel(
|
|
|
175
191
|
y: midY,
|
|
176
192
|
style: { ...style, textAnchor: 'end', dominantBaseline: 'central' },
|
|
177
193
|
visible: true,
|
|
194
|
+
maxWidth,
|
|
178
195
|
};
|
|
179
196
|
}
|
|
180
197
|
|
|
@@ -184,6 +201,7 @@ function computeNodeLabel(
|
|
|
184
201
|
y: midY,
|
|
185
202
|
style: { ...style, textAnchor: 'start', dominantBaseline: 'central' },
|
|
186
203
|
visible: true,
|
|
204
|
+
maxWidth,
|
|
187
205
|
};
|
|
188
206
|
}
|
|
189
207
|
|
|
@@ -324,6 +342,7 @@ export function compileSankey(spec: unknown, options: CompileOptions): SankeyLay
|
|
|
324
342
|
sankeySpec.nodePadding,
|
|
325
343
|
sankeySpec.nodeAlign,
|
|
326
344
|
sankeySpec.iterations,
|
|
345
|
+
sankeySpec.nodeSort,
|
|
327
346
|
);
|
|
328
347
|
|
|
329
348
|
// 6b. Check if any right-side node labels overflow the right edge.
|
|
@@ -363,6 +382,7 @@ export function compileSankey(spec: unknown, options: CompileOptions): SankeyLay
|
|
|
363
382
|
sankeySpec.nodePadding,
|
|
364
383
|
sankeySpec.nodeAlign,
|
|
365
384
|
sankeySpec.iterations,
|
|
385
|
+
sankeySpec.nodeSort,
|
|
366
386
|
));
|
|
367
387
|
}
|
|
368
388
|
|
|
@@ -392,7 +412,15 @@ export function compileSankey(spec: unknown, options: CompileOptions): SankeyLay
|
|
|
392
412
|
height: (node.y1 ?? 0) - (node.y0 ?? 0),
|
|
393
413
|
fill,
|
|
394
414
|
cornerRadius: NODE_CORNER_RADIUS,
|
|
395
|
-
label: computeNodeLabel(
|
|
415
|
+
label: computeNodeLabel(
|
|
416
|
+
node,
|
|
417
|
+
maxDepth,
|
|
418
|
+
theme,
|
|
419
|
+
sankeySpec.nodeWidth,
|
|
420
|
+
nodeLabelAlign,
|
|
421
|
+
options.width,
|
|
422
|
+
padding,
|
|
423
|
+
),
|
|
396
424
|
nodeId: node.id,
|
|
397
425
|
value: node.value ?? 0,
|
|
398
426
|
depth,
|
package/src/sankey/layout.ts
CHANGED
|
@@ -73,6 +73,7 @@ export function computeSankeyLayout(
|
|
|
73
73
|
nodePadding: number,
|
|
74
74
|
nodeAlign: SankeyNodeAlign,
|
|
75
75
|
iterations: number,
|
|
76
|
+
nodeSort?: string[],
|
|
76
77
|
): SankeyLayoutResult {
|
|
77
78
|
// Extract unique node IDs from source and target columns
|
|
78
79
|
const nodeSet = new Set<string>();
|
|
@@ -113,6 +114,19 @@ export function computeSankeyLayout(
|
|
|
113
114
|
])
|
|
114
115
|
.iterations(iterations);
|
|
115
116
|
|
|
117
|
+
// Apply explicit node ordering when provided.
|
|
118
|
+
// Builds a comparator from the ordered ID array so d3-sankey places nodes
|
|
119
|
+
// top-to-bottom within each column according to the spec's nodeSort.
|
|
120
|
+
if (nodeSort && nodeSort.length > 0) {
|
|
121
|
+
const orderMap = new Map(nodeSort.map((id, i) => [id, i]));
|
|
122
|
+
const fallback = nodeSort.length;
|
|
123
|
+
generator.nodeSort(
|
|
124
|
+
(a: SankeyNode<NodeExtra, LinkExtra>, b: SankeyNode<NodeExtra, LinkExtra>) =>
|
|
125
|
+
(orderMap.get((a as unknown as NodeExtra).id) ?? fallback) -
|
|
126
|
+
(orderMap.get((b as unknown as NodeExtra).id) ?? fallback),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
116
130
|
const graph = generator({
|
|
117
131
|
nodes: nodes as unknown as Array<SankeyNode<NodeExtra, LinkExtra>>,
|
|
118
132
|
links: links as unknown as Array<SankeyLink<NodeExtra, LinkExtra>>,
|
package/src/sankey/types.ts
CHANGED