@opendata-ai/openchart-engine 6.17.0 → 6.18.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opendata-ai/openchart-engine",
3
- "version": "6.17.0",
3
+ "version": "6.18.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.17.0",
48
+ "@opendata-ai/openchart-core": "6.18.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 ?? {},
@@ -324,6 +324,7 @@ export function compileSankey(spec: unknown, options: CompileOptions): SankeyLay
324
324
  sankeySpec.nodePadding,
325
325
  sankeySpec.nodeAlign,
326
326
  sankeySpec.iterations,
327
+ sankeySpec.nodeSort,
327
328
  );
328
329
 
329
330
  // 6b. Check if any right-side node labels overflow the right edge.
@@ -363,6 +364,7 @@ export function compileSankey(spec: unknown, options: CompileOptions): SankeyLay
363
364
  sankeySpec.nodePadding,
364
365
  sankeySpec.nodeAlign,
365
366
  sankeySpec.iterations,
367
+ sankeySpec.nodeSort,
366
368
  ));
367
369
  }
368
370
 
@@ -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>>,
@@ -29,6 +29,7 @@ export interface NormalizedSankeySpec {
29
29
  iterations: number;
30
30
  linkStyle: SankeyLinkColor;
31
31
  nodeLabelAlign: 'auto' | 'left' | 'right';
32
+ nodeSort?: string[];
32
33
  chrome: NormalizedChrome;
33
34
  legend?: LegendConfig;
34
35
  theme: ThemeConfig;