@opendata-ai/openchart-engine 8.0.0-rc.1 → 8.0.0-rc.2

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": "8.0.0-rc.1",
3
+ "version": "8.0.0-rc.2",
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",
@@ -48,7 +48,7 @@
48
48
  "typecheck": "tsc --noEmit"
49
49
  },
50
50
  "dependencies": {
51
- "@opendata-ai/openchart-core": "8.0.0-rc.1",
51
+ "@opendata-ai/openchart-core": "8.0.0-rc.2",
52
52
  "d3-array": "^3.2.0",
53
53
  "d3-format": "^3.1.2",
54
54
  "d3-interpolate": "^3.0.0",
@@ -62,11 +62,11 @@ describe('dedupeKeys', () => {
62
62
  });
63
63
 
64
64
  it('suffixes duplicates with occurrence index', () => {
65
- expect(dedupeKeys(['a', 'a', 'a'])).toEqual(['a\x010', 'a\x011', 'a\x012']);
65
+ expect(dedupeKeys(['a', 'a', 'a'])).toEqual(['a⸱0', 'a⸱1', 'a⸱2']);
66
66
  });
67
67
 
68
68
  it('only suffixes keys that appear more than once', () => {
69
- expect(dedupeKeys(['a', 'b', 'a'])).toEqual(['a\x010', 'b', 'a\x011']);
69
+ expect(dedupeKeys(['a', 'b', 'a'])).toEqual(['a⸱0', 'b', 'a⸱1']);
70
70
  });
71
71
 
72
72
  it('handles empty array', () => {
@@ -78,12 +78,6 @@ describe('dedupeKeys', () => {
78
78
  });
79
79
 
80
80
  it('handles multiple duplicate groups', () => {
81
- expect(dedupeKeys(['x', 'y', 'x', 'y', 'z'])).toEqual([
82
- 'x\x010',
83
- 'y\x010',
84
- 'x\x011',
85
- 'y\x011',
86
- 'z',
87
- ]);
81
+ expect(dedupeKeys(['x', 'y', 'x', 'y', 'z'])).toEqual(['x⸱0', 'y⸱0', 'x⸱1', 'y⸱1', 'z']);
88
82
  });
89
83
  });
@@ -28,22 +28,23 @@ export function serializeKeyValue(v: unknown): string {
28
28
  *
29
29
  * Only keys that appear more than once get suffixed. Unique keys pass
30
30
  * through unchanged so keys remain human-readable when possible.
31
- * Uses SOH (\x01) as separator to avoid collisions with real data values.
31
+ * Uses U+2E31 (word separator middle dot) as separator - XML-safe and
32
+ * unlikely to appear in real data values.
32
33
  */
34
+ const KEY_DEDUP_SEP = '⸱';
35
+
33
36
  export function dedupeKeys(keys: string[]): string[] {
34
- // Count occurrences
35
37
  const counts = new Map<string, number>();
36
38
  for (const k of keys) {
37
39
  counts.set(k, (counts.get(k) ?? 0) + 1);
38
40
  }
39
41
 
40
- // Assign suffixes only to duplicates
41
42
  const seen = new Map<string, number>();
42
43
  const result: string[] = [];
43
44
  for (const k of keys) {
44
45
  if (counts.get(k)! > 1) {
45
46
  const idx = seen.get(k) ?? 0;
46
- result.push(`${k}\x01${idx}`);
47
+ result.push(`${k}${KEY_DEDUP_SEP}${idx}`);
47
48
  seen.set(k, idx + 1);
48
49
  } else {
49
50
  result.push(k);
@@ -25,6 +25,7 @@ import {
25
25
  estimateTextWidth,
26
26
  getAxisTitleOffset,
27
27
  truncateRotatedLabel,
28
+ X_AXIS_TITLE_BAND,
28
29
  X_AXIS_TITLE_BAND_ROTATED,
29
30
  } from '@opendata-ai/openchart-core';
30
31
  import type { ScaleBand } from 'd3-scale';
@@ -705,12 +706,12 @@ export function computeAxes(
705
706
  });
706
707
 
707
708
  if (result.x.label) {
708
- // Rotated: place the title just below the tick band (extent already
709
- // includes the rotated label height and the title band). Flat: fixed 35px.
710
- const rotatedBand = isRotated ? result.x.extent - X_AXIS_TITLE_BAND_ROTATED + 14 : 35;
709
+ const titleBand = isRotated ? X_AXIS_TITLE_BAND_ROTATED : X_AXIS_TITLE_BAND;
710
+ const tickBand = result.x.extent - titleBand;
711
+ const titleY = isRotated ? tickBand + 14 : tickBand + 9;
711
712
  result.x.titlePosition = {
712
713
  x: chartArea.x + chartArea.width / 2,
713
- y: chartArea.y + chartArea.height + rotatedBand,
714
+ y: chartArea.y + chartArea.height + titleY,
714
715
  };
715
716
  }
716
717
  }