@opendata-ai/openchart-core 2.9.1 → 2.11.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 +53 -14
- package/dist/index.js +119 -31
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -0
- package/package.json +1 -1
- package/src/index.ts +5 -1
- package/src/labels/collision.ts +26 -0
- package/src/labels/index.ts +1 -1
- package/src/layout/__tests__/chrome.test.ts +17 -0
- package/src/layout/chrome.ts +90 -30
- package/src/layout/index.ts +6 -1
- package/src/layout/text-measure.ts +18 -2
- package/src/responsive/__tests__/breakpoints.test.ts +89 -1
- package/src/responsive/breakpoints.ts +89 -9
- package/src/responsive/index.ts +5 -0
- package/src/styles/viz.css +2 -0
- package/src/theme/__tests__/resolve.test.ts +57 -0
- package/src/types/layout.ts +2 -0
package/src/styles/viz.css
CHANGED
|
@@ -74,3 +74,60 @@ describe('resolveTheme', () => {
|
|
|
74
74
|
expect(resolved.spacing.padding).toBe(DEFAULT_THEME.spacing.padding);
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Deep merge behavior hardening
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
describe('resolveTheme deep merge edge cases', () => {
|
|
83
|
+
it('replaces categorical array entirely, does not concatenate', () => {
|
|
84
|
+
const custom = ['#aaa', '#bbb'];
|
|
85
|
+
const resolved = resolveTheme({ colors: { categorical: custom } });
|
|
86
|
+
expect(resolved.colors.categorical).toEqual(custom);
|
|
87
|
+
expect(resolved.colors.categorical).toHaveLength(2);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('skips undefined values, preserving defaults', () => {
|
|
91
|
+
const resolved = resolveTheme({ borderRadius: undefined });
|
|
92
|
+
expect(resolved.borderRadius).toBe(DEFAULT_THEME.borderRadius);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('applies multiple overrides at different depths in one call', () => {
|
|
96
|
+
const resolved = resolveTheme({
|
|
97
|
+
colors: { background: '#222222', text: '#eeeeee' },
|
|
98
|
+
fonts: { family: 'Georgia' },
|
|
99
|
+
spacing: { padding: 32 },
|
|
100
|
+
borderRadius: 4,
|
|
101
|
+
});
|
|
102
|
+
expect(resolved.colors.background).toBe('#222222');
|
|
103
|
+
expect(resolved.colors.text).toBe('#eeeeee');
|
|
104
|
+
expect(resolved.fonts.family).toBe('Georgia');
|
|
105
|
+
expect(resolved.spacing.padding).toBe(32);
|
|
106
|
+
expect(resolved.borderRadius).toBe(4);
|
|
107
|
+
// Non-overridden values preserved
|
|
108
|
+
expect(resolved.fonts.mono).toBe(DEFAULT_THEME.fonts.mono);
|
|
109
|
+
expect(resolved.spacing.chromeGap).toBe(DEFAULT_THEME.spacing.chromeGap);
|
|
110
|
+
expect(resolved.colors.categorical).toEqual(DEFAULT_THEME.colors.categorical);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('empty object override returns defaults unchanged', () => {
|
|
114
|
+
const resolved = resolveTheme({});
|
|
115
|
+
expect(resolved.colors).toEqual(expect.objectContaining(DEFAULT_THEME.colors));
|
|
116
|
+
expect(resolved.fonts).toEqual(DEFAULT_THEME.fonts);
|
|
117
|
+
expect(resolved.spacing).toEqual(DEFAULT_THEME.spacing);
|
|
118
|
+
expect(resolved.borderRadius).toBe(DEFAULT_THEME.borderRadius);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('dark background adapts chrome colors without losing chrome structure', () => {
|
|
122
|
+
const resolved = resolveTheme({ colors: { background: '#111111', text: '#ffffff' } });
|
|
123
|
+
expect(resolved.isDark).toBe(true);
|
|
124
|
+
// Chrome structure should still be fully populated
|
|
125
|
+
expect(resolved.chrome.title).toBeDefined();
|
|
126
|
+
expect(resolved.chrome.subtitle).toBeDefined();
|
|
127
|
+
expect(resolved.chrome.source).toBeDefined();
|
|
128
|
+
expect(resolved.chrome.byline).toBeDefined();
|
|
129
|
+
expect(resolved.chrome.footer).toBeDefined();
|
|
130
|
+
// Title color should be adapted (not the light-mode default)
|
|
131
|
+
expect(resolved.chrome.title.color).not.toBe(DEFAULT_THEME.chrome.title.color);
|
|
132
|
+
});
|
|
133
|
+
});
|
package/src/types/layout.ts
CHANGED
|
@@ -394,6 +394,8 @@ export interface LegendEntry {
|
|
|
394
394
|
shape: 'circle' | 'square' | 'line';
|
|
395
395
|
/** Whether this entry is currently highlighted/active. */
|
|
396
396
|
active?: boolean;
|
|
397
|
+
/** True for overflow indicator entries ("+N more"). Not interactive. */
|
|
398
|
+
overflow?: boolean;
|
|
397
399
|
}
|
|
398
400
|
|
|
399
401
|
/** Resolved legend layout with position and entries. */
|