@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/dist/index.d.ts +0 -7
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/compiler/__tests__/keys.test.ts +3 -9
- package/src/compiler/keys.ts +5 -4
- package/src/layout/axes.ts +5 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendata-ai/openchart-engine",
|
|
3
|
-
"version": "8.0.0-rc.
|
|
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.
|
|
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
|
|
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
|
|
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
|
});
|
package/src/compiler/keys.ts
CHANGED
|
@@ -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
|
|
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}
|
|
47
|
+
result.push(`${k}${KEY_DEDUP_SEP}${idx}`);
|
|
47
48
|
seen.set(k, idx + 1);
|
|
48
49
|
} else {
|
|
49
50
|
result.push(k);
|
package/src/layout/axes.ts
CHANGED
|
@@ -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
|
-
|
|
709
|
-
|
|
710
|
-
const
|
|
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 +
|
|
714
|
+
y: chartArea.y + chartArea.height + titleY,
|
|
714
715
|
};
|
|
715
716
|
}
|
|
716
717
|
}
|