chart-factory 0.1.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/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/chart-factory-table.js +1400 -0
- package/dist/chart-factory.css +2368 -0
- package/dist/chart-factory.js +11398 -0
- package/dist/chart-factory.min.js +7 -0
- package/docs/API.md +1815 -0
- package/docs/chart-guide.md +872 -0
- package/docs/color-guide.md +134 -0
- package/docs/conformance-matrix.md +864 -0
- package/docs/theming.md +107 -0
- package/index.d.ts +10453 -0
- package/package.json +83 -0
- package/src/core/base.css +508 -0
- package/src/core/builder-metadata.generated.mjs +406 -0
- package/src/core/d3-base.js +249 -0
- package/src/core/d3-chart-factory.js +18547 -0
- package/src/core/d3-data.js +0 -0
- package/src/core/d3-suggest.js +565 -0
- package/src/core/example-nav.css +62 -0
- package/src/core/example-nav.js +249 -0
- package/src/core/palettes.js +310 -0
- package/src/core/theme-toggle.js +126 -0
- package/src/core/tokens.css +792 -0
- package/src/table/d3-table.js +1570 -0
- package/src/table/table.css +899 -0
- package/src/table/tokens.css +157 -0
|
@@ -0,0 +1,792 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chart Factory - Shared Design Tokens
|
|
3
|
+
*
|
|
4
|
+
* These CSS custom properties define the visual foundation for all D3 components.
|
|
5
|
+
* Override these in your own stylesheet to customize the appearance.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* @import 'chart-factory/core/tokens.css';
|
|
9
|
+
*
|
|
10
|
+
* :root {
|
|
11
|
+
* --font-family: 'Your Font', sans-serif;
|
|
12
|
+
* --color-text-primary: #222;
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
:root {
|
|
17
|
+
/* ===========================
|
|
18
|
+
SPACING
|
|
19
|
+
=========================== */
|
|
20
|
+
--space-0: 0;
|
|
21
|
+
--space-1: 4px;
|
|
22
|
+
--space-2: 8px;
|
|
23
|
+
--space-3: 12px;
|
|
24
|
+
--space-4: 15px;
|
|
25
|
+
--space-5: 20px;
|
|
26
|
+
--space-6: 25px;
|
|
27
|
+
--space-7: 35px;
|
|
28
|
+
--space-8: 40px;
|
|
29
|
+
|
|
30
|
+
/* ===========================
|
|
31
|
+
TYPOGRAPHY
|
|
32
|
+
=========================== */
|
|
33
|
+
/* Default: System font stack */
|
|
34
|
+
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
35
|
+
/* Alternative: Open Sans (uncomment and add Google Font import to use)
|
|
36
|
+
* Add to <head>: <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
|
|
37
|
+
* --font-family: 'Open Sans', sans-serif;
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/* Font Sizes */
|
|
41
|
+
--font-size-xs: 9px;
|
|
42
|
+
--font-size-sm: 10px;
|
|
43
|
+
--font-size-base: 11px;
|
|
44
|
+
--font-size-md: 12px;
|
|
45
|
+
--font-size-lg: 13px;
|
|
46
|
+
--font-size-xl: 14px;
|
|
47
|
+
--font-size-title: 28px;
|
|
48
|
+
--font-size-subtitle: 13px;
|
|
49
|
+
/* Chart-shell text hierarchy (decided from live mockups 2026-07-18):
|
|
50
|
+
card tier 15/11 (ratio 1.36), featured tier 20/14 (ratio 1.43).
|
|
51
|
+
Title size tracks reading context, not chart size. */
|
|
52
|
+
--shell-title-size: 15px;
|
|
53
|
+
--shell-subtitle-size: var(--font-size-base);
|
|
54
|
+
--shell-featured-title-size: 20px;
|
|
55
|
+
--shell-featured-subtitle-size: 14px;
|
|
56
|
+
|
|
57
|
+
/* Font Weights */
|
|
58
|
+
--font-weight-normal: 400;
|
|
59
|
+
--font-weight-semibold: 600;
|
|
60
|
+
--font-weight-bold: 700;
|
|
61
|
+
|
|
62
|
+
/* Letter Spacing */
|
|
63
|
+
--letter-spacing-tight: -0.3px;
|
|
64
|
+
--letter-spacing-wide: 0.8px;
|
|
65
|
+
--letter-spacing-wider: 1px;
|
|
66
|
+
|
|
67
|
+
/* Line Height */
|
|
68
|
+
--line-height-normal: 1.6;
|
|
69
|
+
|
|
70
|
+
/* ===========================
|
|
71
|
+
COLORS
|
|
72
|
+
=========================== */
|
|
73
|
+
|
|
74
|
+
/* Text Colors */
|
|
75
|
+
--color-black: #000;
|
|
76
|
+
--color-text-primary: #333;
|
|
77
|
+
--color-text-muted: #666;
|
|
78
|
+
--color-text-subtle: #767676;
|
|
79
|
+
--color-text-faint: #999;
|
|
80
|
+
--color-text-disabled: #aaa;
|
|
81
|
+
|
|
82
|
+
/* Background Colors */
|
|
83
|
+
--color-bg-body: #f8f8f8;
|
|
84
|
+
--color-bg-container: white;
|
|
85
|
+
--color-bg-hover: #fafafa;
|
|
86
|
+
--color-bg-highlight: #f0f0f0;
|
|
87
|
+
|
|
88
|
+
/* Border Colors */
|
|
89
|
+
--color-border-header: #000;
|
|
90
|
+
--color-border-row: #f0f0f0;
|
|
91
|
+
--color-border-light: #e5e5e5; /* light axis/grid strokes */
|
|
92
|
+
--color-border-footer: #e8e8e8;
|
|
93
|
+
--color-border-tooltip: #ddd;
|
|
94
|
+
|
|
95
|
+
/* Shadows */
|
|
96
|
+
--shadow-container: 0 1px 3px rgba(0, 0, 0, 0.08);
|
|
97
|
+
--shadow-tooltip: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
98
|
+
|
|
99
|
+
/* ===========================
|
|
100
|
+
ANIMATIONS
|
|
101
|
+
=========================== */
|
|
102
|
+
--animation-duration-fast: 200ms;
|
|
103
|
+
--animation-duration-normal: 500ms;
|
|
104
|
+
--animation-duration-slow: 1000ms;
|
|
105
|
+
--animation-stagger-delay: 50ms;
|
|
106
|
+
|
|
107
|
+
/* ===========================
|
|
108
|
+
TOOLTIPS
|
|
109
|
+
=========================== */
|
|
110
|
+
--tooltip-z-index: 9999; /* above typical host-page modals/sticky chrome */
|
|
111
|
+
--tooltip-font-size: 12px; /* tooltip body (independent of chart axis text) */
|
|
112
|
+
--tooltip-title-font-size: 15px; /* ~1.25x body for clear title dominance */
|
|
113
|
+
--tooltip-row-gap: 4px; /* vertical rhythm between shell rows */
|
|
114
|
+
--tooltip-padding: 10px 13px;
|
|
115
|
+
--tooltip-border-radius: 6px;
|
|
116
|
+
--tooltip-min-width: 130px;
|
|
117
|
+
--tooltip-chart-height: 50px;
|
|
118
|
+
--tooltip-bar-gap: var(--space-1);
|
|
119
|
+
--tooltip-bar-min-width: var(--space-2);
|
|
120
|
+
--tooltip-bar-border-radius: 2px;
|
|
121
|
+
--tooltip-label-offset-y: 18px;
|
|
122
|
+
--tooltip-value-offset-y: 18px;
|
|
123
|
+
|
|
124
|
+
/* ===========================
|
|
125
|
+
CHART STORY (story: config — narrative summary module under the chart)
|
|
126
|
+
=========================== */
|
|
127
|
+
--story-font-size: var(--font-size-lg); /* body text of all three variants */
|
|
128
|
+
--story-line-height: 1.6;
|
|
129
|
+
/* Accent drives the panel tint/border, the bold lead-in label, and band
|
|
130
|
+
<b>/<strong> emphasis. The per-chart `accent` option overrides it via an
|
|
131
|
+
inline custom property on the module. */
|
|
132
|
+
--story-accent: var(--chart-primary);
|
|
133
|
+
/* Accent share in the panel wash / hairline (color-mix percentages) */
|
|
134
|
+
--story-panel-bg-alpha: 7%;
|
|
135
|
+
--story-panel-border-alpha: 25%;
|
|
136
|
+
/* Band variant: full-width dark lede strip */
|
|
137
|
+
--story-band-bg: #1f2937;
|
|
138
|
+
--story-band-text: #e5e7eb;
|
|
139
|
+
--story-band-label: #9ca3af; /* overline label tint on the band */
|
|
140
|
+
|
|
141
|
+
/* ===========================
|
|
142
|
+
RESPONSIVE
|
|
143
|
+
=========================== */
|
|
144
|
+
--container-padding: var(--space-8); /* .d3-container inner padding — the one knob for card breathing room */
|
|
145
|
+
--container-padding-mobile: var(--space-6) var(--space-5);
|
|
146
|
+
--title-font-size-mobile: 22px;
|
|
147
|
+
|
|
148
|
+
/* ===========================
|
|
149
|
+
CHART SHARED
|
|
150
|
+
=========================== */
|
|
151
|
+
|
|
152
|
+
/* Primary chart color — single-series default (line/area/bar/scatter,
|
|
153
|
+
forecast/actual lines, series-3). Brand blue, kept distinct from the Set2
|
|
154
|
+
categorical palette used for multi-series charts. */
|
|
155
|
+
--chart-primary: #3b82f6;
|
|
156
|
+
--chart-primary-light: rgba(59, 130, 246, 0.3);
|
|
157
|
+
--chart-primary-faint: rgba(59, 130, 246, 0.1);
|
|
158
|
+
|
|
159
|
+
/* Secondary chart colors */
|
|
160
|
+
--chart-secondary: #22c55e; /* line palette slot 2 (getLineColors) */
|
|
161
|
+
--chart-tertiary: #f97316; /* line palette slot 3 (getLineColors) */
|
|
162
|
+
--chart-green: #22c55e;
|
|
163
|
+
--chart-lime: #84cc16; /* mid-tier threshold color (progress bars) */
|
|
164
|
+
--chart-orange: #f97316;
|
|
165
|
+
--chart-purple: #a855f7;
|
|
166
|
+
--chart-purple-light: rgba(168, 85, 247, 0.4);
|
|
167
|
+
--chart-purple-faint: rgba(168, 85, 247, 0.05);
|
|
168
|
+
--chart-red: #ef4444;
|
|
169
|
+
|
|
170
|
+
/* Multi-series palette (for YoY, comparisons) */
|
|
171
|
+
--chart-series-1: #94a3b8;
|
|
172
|
+
--chart-series-2: #64748b;
|
|
173
|
+
--chart-series-3: var(--chart-primary);
|
|
174
|
+
|
|
175
|
+
/* Semantic chart colors */
|
|
176
|
+
--chart-trend-up: var(--chart-green);
|
|
177
|
+
--chart-trend-down: var(--chart-red);
|
|
178
|
+
--chart-anomaly: var(--chart-red);
|
|
179
|
+
--chart-forecast: var(--chart-primary);
|
|
180
|
+
--chart-actual: var(--chart-primary);
|
|
181
|
+
--chart-budget: var(--chart-green);
|
|
182
|
+
|
|
183
|
+
/* Neutral/gray for cumulative/baseline lines */
|
|
184
|
+
--chart-neutral: #6b7280;
|
|
185
|
+
--chart-neutral-light: rgba(107, 114, 128, 0.4);
|
|
186
|
+
--chart-neutral-faint: rgba(107, 114, 128, 0.05);
|
|
187
|
+
|
|
188
|
+
/* Axes */
|
|
189
|
+
--axis-color: var(--color-text-muted);
|
|
190
|
+
--axis-font-size: var(--font-size-xs);
|
|
191
|
+
--axis-label-font-size: var(--font-size-sm);
|
|
192
|
+
--axis-tick-size: 5px;
|
|
193
|
+
--axis-tick-padding: 3px;
|
|
194
|
+
|
|
195
|
+
/* Grid */
|
|
196
|
+
--grid-color: var(--color-border-row);
|
|
197
|
+
--grid-opacity: 0.5;
|
|
198
|
+
--grid-stroke-opacity: 0.5;
|
|
199
|
+
|
|
200
|
+
/* Hover states */
|
|
201
|
+
--hover-stroke-color: var(--color-text-primary);
|
|
202
|
+
--hover-stroke-width: 1;
|
|
203
|
+
--hover-dash-pattern: 3, 3;
|
|
204
|
+
--link-dot-radius: 3.5; /* snapped dot size on linked-crosshair (linkGroup) charts */
|
|
205
|
+
--brush-selection-opacity: 0.08; /* fill opacity of the brush selection window */
|
|
206
|
+
--brush-veil-opacity: 0.65; /* opacity of the outside-selection veil on linked charts */
|
|
207
|
+
|
|
208
|
+
/* Lines */
|
|
209
|
+
--line-stroke-width: 2;
|
|
210
|
+
--line-stroke-width-thin: 1;
|
|
211
|
+
--line-stroke-width-hover: 3;
|
|
212
|
+
--line-opacity: 1;
|
|
213
|
+
--line-opacity-muted: 0.3;
|
|
214
|
+
--line-dot-stroke-width: 2;
|
|
215
|
+
--line-transition-duration: 150;
|
|
216
|
+
|
|
217
|
+
/* Areas */
|
|
218
|
+
--area-opacity: 0.15;
|
|
219
|
+
--area-opacity-light: 0.1;
|
|
220
|
+
--area-gradient-start: 0.3;
|
|
221
|
+
--area-gradient-end: 0.02;
|
|
222
|
+
|
|
223
|
+
/* Points */
|
|
224
|
+
--point-radius: 4px;
|
|
225
|
+
--point-radius-small: 3px;
|
|
226
|
+
--point-radius-hover: 6px;
|
|
227
|
+
--point-stroke-width: 2px;
|
|
228
|
+
|
|
229
|
+
/* Confidence bands */
|
|
230
|
+
--band-opacity: 0.15;
|
|
231
|
+
--band-border-opacity: 0.3;
|
|
232
|
+
|
|
233
|
+
/* Anomaly indicators */
|
|
234
|
+
--anomaly-pulse-radius: 4;
|
|
235
|
+
--anomaly-dot-radius: 3;
|
|
236
|
+
|
|
237
|
+
/* Legend */
|
|
238
|
+
--legend-swatch-size: 12px;
|
|
239
|
+
--legend-line-width: 24px;
|
|
240
|
+
--legend-line-height: 2px;
|
|
241
|
+
--legend-gap: var(--space-4);
|
|
242
|
+
--legend-font-size: var(--font-size-sm);
|
|
243
|
+
/* Interactive legend: opacity of non-highlighted series when one is
|
|
244
|
+
hovered/isolated (chosen treatment: dim others, highlighted unchanged). */
|
|
245
|
+
--legend-dim-opacity: 0.18;
|
|
246
|
+
|
|
247
|
+
/* Trend indicators (legacy aliases) */
|
|
248
|
+
--trend-up-color: var(--chart-trend-up);
|
|
249
|
+
--trend-down-color: var(--chart-trend-down);
|
|
250
|
+
--trend-neutral-color: var(--color-text-muted);
|
|
251
|
+
|
|
252
|
+
/* Animation */
|
|
253
|
+
--chart-animation-duration: 2s;
|
|
254
|
+
--chart-pulse-min-opacity: 0;
|
|
255
|
+
--chart-pulse-max-opacity: 0.6;
|
|
256
|
+
|
|
257
|
+
/* Annotations: fade-in (ms) when an annotation waits for its anchor
|
|
258
|
+
mark's entrance animation before appearing */
|
|
259
|
+
--annotation-fade-duration: 200;
|
|
260
|
+
|
|
261
|
+
/* Event annotations (type: 'event'): tick + label band below the x-axis */
|
|
262
|
+
--annotation-event-band-offset: 22; /* px from plot bottom to the event ticks */
|
|
263
|
+
--annotation-event-tick-height: 8; /* event tick length */
|
|
264
|
+
--annotation-event-font-size: 10px; /* event label size */
|
|
265
|
+
--annotation-event-guide-color: #d1d5db; /* dotted in-plot guide (guide: true) */
|
|
266
|
+
|
|
267
|
+
/* Point/callout annotations: editorial two-line callouts + leader lines */
|
|
268
|
+
--annotation-title-size: 13px; /* titled callout value line (`title`) */
|
|
269
|
+
--annotation-leader-threshold: 14; /* px dot-to-label gap before an auto leader draws */
|
|
270
|
+
|
|
271
|
+
/* ===========================
|
|
272
|
+
SLOPE CHART SPECIFIC
|
|
273
|
+
=========================== */
|
|
274
|
+
|
|
275
|
+
/* Slope line widths */
|
|
276
|
+
--slope-line-width: var(--line-stroke-width);
|
|
277
|
+
--slope-line-width-hover: 3;
|
|
278
|
+
|
|
279
|
+
/* Slope point sizing */
|
|
280
|
+
--slope-point-radius: var(--point-radius);
|
|
281
|
+
--slope-point-radius-hover: 7px;
|
|
282
|
+
--slope-gap-radius: 6px;
|
|
283
|
+
|
|
284
|
+
/* Slope interaction states */
|
|
285
|
+
--slope-dimmed-opacity: 0.2;
|
|
286
|
+
--slope-transition-duration: 0.2s;
|
|
287
|
+
|
|
288
|
+
/* Slope animation */
|
|
289
|
+
--slope-animation-duration: 800ms;
|
|
290
|
+
--slope-stagger-delay: 80ms;
|
|
291
|
+
--slope-fade-duration: 300ms;
|
|
292
|
+
|
|
293
|
+
/* Slope highlight mode */
|
|
294
|
+
--slope-highlight-color: var(--chart-orange);
|
|
295
|
+
--slope-muted-color: #94a3b8;
|
|
296
|
+
|
|
297
|
+
/* Slope label dodge: minimum vertical gap between stacked side labels */
|
|
298
|
+
--slope-label-min-gap: 15;
|
|
299
|
+
/* Two-line right labels (createIndexed) need roughly double the gap */
|
|
300
|
+
--slope-label-min-gap-stacked: 34;
|
|
301
|
+
|
|
302
|
+
/* Indexed slope: hairline at the origin/no-change value */
|
|
303
|
+
--slope-baseline-color: var(--color-border-light);
|
|
304
|
+
|
|
305
|
+
/* Dodged-label leader lines (defaults to the hairline border color) */
|
|
306
|
+
--slope-leader-color: var(--color-border-light);
|
|
307
|
+
|
|
308
|
+
/* Slope band colors (quartiles, from bottom to top) */
|
|
309
|
+
--slope-band-1: #fef2f2;
|
|
310
|
+
--slope-band-2: #fefce8;
|
|
311
|
+
--slope-band-3: #f0fdf4;
|
|
312
|
+
--slope-band-4: #eff6ff;
|
|
313
|
+
|
|
314
|
+
/* ===========================
|
|
315
|
+
AREA CHART SPECIFIC
|
|
316
|
+
=========================== */
|
|
317
|
+
|
|
318
|
+
/* Area fill opacity */
|
|
319
|
+
--area-fill-opacity: 0.35;
|
|
320
|
+
--area-fill-opacity-hover: 0.5;
|
|
321
|
+
--area-fill-opacity-muted: 0.15;
|
|
322
|
+
|
|
323
|
+
/* Area stroke */
|
|
324
|
+
--area-stroke-width: 1.5;
|
|
325
|
+
--area-stroke-opacity: 1;
|
|
326
|
+
|
|
327
|
+
/* Categorical series palette — Set2 (house default, CVD-safe, muted).
|
|
328
|
+
Drives getAreaColors()/getLineColors(): stacked areas, multi-line, grouped/
|
|
329
|
+
stacked bars, donut, dot, scatter categories. Single-series charts use
|
|
330
|
+
--chart-primary, not these. Override any of these to restyle every
|
|
331
|
+
multi-series chart at once. */
|
|
332
|
+
--area-color-1: #66c2a5;
|
|
333
|
+
--area-color-2: #fc8d62;
|
|
334
|
+
--area-color-3: #8da0cb;
|
|
335
|
+
--area-color-4: #e78ac3;
|
|
336
|
+
--area-color-5: #a6d854;
|
|
337
|
+
--area-color-6: #ffd92f;
|
|
338
|
+
--area-color-7: #e5c494;
|
|
339
|
+
--area-color-8: #b3b3b3;
|
|
340
|
+
|
|
341
|
+
/* Area interaction */
|
|
342
|
+
--area-transition-duration: 0.2s;
|
|
343
|
+
--area-dimmed-opacity: 0.2;
|
|
344
|
+
|
|
345
|
+
/* Area animation */
|
|
346
|
+
--area-animation-duration: 1000ms;
|
|
347
|
+
--area-stagger-delay: 100ms;
|
|
348
|
+
|
|
349
|
+
/* Area gradient (for single-series with gradient fill) */
|
|
350
|
+
--area-gradient-opacity-top: 0.3;
|
|
351
|
+
--area-gradient-opacity-bottom: 0.02;
|
|
352
|
+
|
|
353
|
+
/* Smoothing curve tension (0 = linear, 1 = very smooth) */
|
|
354
|
+
--area-curve-tension: 0.4;
|
|
355
|
+
|
|
356
|
+
/* ===========================
|
|
357
|
+
STREAMGRAPH SPECIFIC
|
|
358
|
+
=========================== */
|
|
359
|
+
|
|
360
|
+
/* Stream layer fill */
|
|
361
|
+
--stream-fill-opacity: 1;
|
|
362
|
+
--stream-stroke-color: #fff;
|
|
363
|
+
--stream-stroke-width: 1;
|
|
364
|
+
|
|
365
|
+
/* Stream interaction */
|
|
366
|
+
--stream-dimmed-opacity: 0.25;
|
|
367
|
+
|
|
368
|
+
/* Stream labels */
|
|
369
|
+
--stream-label-size: 11;
|
|
370
|
+
|
|
371
|
+
/* ===========================
|
|
372
|
+
DOT CHART SPECIFIC
|
|
373
|
+
=========================== */
|
|
374
|
+
|
|
375
|
+
/* Dot sizing */
|
|
376
|
+
--dot-radius: 5px;
|
|
377
|
+
--dot-radius-hover: 7px;
|
|
378
|
+
|
|
379
|
+
/* Connector line (dumbbell) */
|
|
380
|
+
--dot-connector-width: 2.5;
|
|
381
|
+
--dot-connector-color: var(--color-text-disabled);
|
|
382
|
+
|
|
383
|
+
/* Row spacing */
|
|
384
|
+
--dot-row-height: 36px;
|
|
385
|
+
--dot-row-padding: 0.3;
|
|
386
|
+
|
|
387
|
+
/* Header positioning */
|
|
388
|
+
--dot-header-offset: 12px;
|
|
389
|
+
|
|
390
|
+
/* ===========================
|
|
391
|
+
COLOR TEMPERATURE PALETTE
|
|
392
|
+
=========================== */
|
|
393
|
+
/* Based on Kelvin color temperature scale
|
|
394
|
+
* Cold (blue) → Warm (amber)
|
|
395
|
+
* Useful for percentile bands, heat maps, diverging scales */
|
|
396
|
+
|
|
397
|
+
--temp-cold-10: #7AB8FF; /* 10000K - deep cold blue */
|
|
398
|
+
--temp-cold-9: #9CCAFF; /* 9000K - cold blue */
|
|
399
|
+
--temp-cold-8: #B8D9FF; /* 8000K - sky blue */
|
|
400
|
+
--temp-cold-7: #D6E8FF; /* 7000K - pale blue */
|
|
401
|
+
--temp-neutral: #F2F7FF; /* 6000K - cool white */
|
|
402
|
+
--temp-warm-5: #FFF1C1; /* 5000K - neutral daylight */
|
|
403
|
+
--temp-warm-4: #FFD27F; /* 4000K - warm white */
|
|
404
|
+
--temp-warm-3: #FFB347; /* 3000K - tungsten */
|
|
405
|
+
--temp-warm-2: #FF8C1A; /* 2000K - warm orange */
|
|
406
|
+
--temp-warm-1: #FF6A00; /* 1000K - deep amber */
|
|
407
|
+
|
|
408
|
+
/* ===========================
|
|
409
|
+
SCATTER PLOT / TRAJECTORY
|
|
410
|
+
=========================== */
|
|
411
|
+
|
|
412
|
+
/* Trail length (number of time units to show in trail) */
|
|
413
|
+
--scatter-trail-length: 5;
|
|
414
|
+
|
|
415
|
+
/* Trail styling */
|
|
416
|
+
--scatter-trail-width: 3;
|
|
417
|
+
--scatter-trail-width-hover: 4;
|
|
418
|
+
--scatter-trail-opacity: 0.7;
|
|
419
|
+
--scatter-trail-opacity-dimmed: 0.08;
|
|
420
|
+
|
|
421
|
+
/* Trail gradient (fade from start to end) */
|
|
422
|
+
--scatter-trail-gradient-start: 0.1;
|
|
423
|
+
--scatter-trail-gradient-end: 0.9;
|
|
424
|
+
|
|
425
|
+
/* Dot sizing */
|
|
426
|
+
--scatter-dot-radius: 6;
|
|
427
|
+
--scatter-dot-radius-hover: 10;
|
|
428
|
+
--scatter-dot-stroke-width: 2;
|
|
429
|
+
|
|
430
|
+
/* Start dot (trail origin marker) */
|
|
431
|
+
--scatter-start-dot-radius: 4;
|
|
432
|
+
--scatter-start-dot-stroke-width: 1.5;
|
|
433
|
+
--scatter-start-dot-opacity: 0.8;
|
|
434
|
+
|
|
435
|
+
/* Animation timing */
|
|
436
|
+
--scatter-animation-speed: 1000;
|
|
437
|
+
|
|
438
|
+
/* Quadrant chart */
|
|
439
|
+
--quadrant-line-width: 1.5;
|
|
440
|
+
--quadrant-bg-opacity: 0.08;
|
|
441
|
+
|
|
442
|
+
/* Density contour / KDE outlines (dark theme flips these to white-based) */
|
|
443
|
+
--contour-line-color: rgba(0, 0, 0, 0.15);
|
|
444
|
+
--kde-contour-line-color: rgba(0, 0, 0, 0.1);
|
|
445
|
+
|
|
446
|
+
/* ===========================
|
|
447
|
+
VOCABULARY FAMILIES (Release C)
|
|
448
|
+
=========================== */
|
|
449
|
+
|
|
450
|
+
/* Histogram */
|
|
451
|
+
--histogram-bar-gap: 1; /* px gap between bin bars */
|
|
452
|
+
--histogram-overlay-opacity: 0.55; /* overlay-series fill opacity */
|
|
453
|
+
|
|
454
|
+
/* Donut */
|
|
455
|
+
--donut-inner-ratio: 0.62; /* inner radius share; 0 = pie */
|
|
456
|
+
--donut-pad-angle: 0.008; /* radians between slices */
|
|
457
|
+
--donut-corner-radius: 2; /* px slice corner rounding */
|
|
458
|
+
|
|
459
|
+
/* Box plot */
|
|
460
|
+
--box-fill-opacity: 0.35; /* box body fill vs stroke */
|
|
461
|
+
--box-median-width: 2.5; /* median line stroke width */
|
|
462
|
+
--box-outlier-radius: 3; /* px outlier ring radius */
|
|
463
|
+
|
|
464
|
+
/* Calendar heatmap */
|
|
465
|
+
--calendar-cell-radius: 2; /* px cell corner rounding */
|
|
466
|
+
--calendar-month-gap: 3; /* px extra gutter at month starts */
|
|
467
|
+
--calendar-max-cell: 22; /* px step cap for the 7-col vertical layout */
|
|
468
|
+
|
|
469
|
+
/* Sankey */
|
|
470
|
+
--sankey-node-width: 12; /* px node bar width */
|
|
471
|
+
--sankey-node-padding: 12; /* px vertical gap between nodes */
|
|
472
|
+
--sankey-link-opacity: 0.3; /* link ribbon opacity (hover +0.25) */
|
|
473
|
+
--sankey-anim-duration: 900; /* ms each column's links take to draw */
|
|
474
|
+
--sankey-anim-pause: 300; /* ms the flow rests at a node before flowing on */
|
|
475
|
+
|
|
476
|
+
/* ===========================
|
|
477
|
+
BUMP CHART SPECIFIC
|
|
478
|
+
=========================== */
|
|
479
|
+
|
|
480
|
+
/* Layout */
|
|
481
|
+
--bump-margin-top: 30;
|
|
482
|
+
--bump-margin-bottom: 40;
|
|
483
|
+
--bump-label-gap: 10;
|
|
484
|
+
--bump-label-padding: 5;
|
|
485
|
+
--bump-axis-offset: 15;
|
|
486
|
+
|
|
487
|
+
/* Line styling */
|
|
488
|
+
--bump-line-width: 2.5;
|
|
489
|
+
--bump-line-width-hover: 3.5;
|
|
490
|
+
|
|
491
|
+
/* Dot styling */
|
|
492
|
+
--bump-dot-radius: 8;
|
|
493
|
+
--bump-dot-radius-hover: 10;
|
|
494
|
+
--bump-dot-stroke-width: 2;
|
|
495
|
+
--bump-rank-font-size: 10px;
|
|
496
|
+
|
|
497
|
+
/* Interaction states */
|
|
498
|
+
--bump-dimmed-opacity: 0.15;
|
|
499
|
+
--bump-transition-duration: 0.2s;
|
|
500
|
+
|
|
501
|
+
/* Animation */
|
|
502
|
+
--bump-animation-duration: 800;
|
|
503
|
+
--bump-stagger-delay: 100;
|
|
504
|
+
--bump-dot-fade-duration: 300;
|
|
505
|
+
|
|
506
|
+
/* ===========================
|
|
507
|
+
SEQUENTIAL COLOR SCALES (bars/heatmaps — createColorScale)
|
|
508
|
+
=========================== */
|
|
509
|
+
--scale-orange-lo: #fff5eb;
|
|
510
|
+
--scale-orange-hi: #ff6b35;
|
|
511
|
+
--scale-orange-red-hi: #d7191c;
|
|
512
|
+
--scale-blue-lo: #e0f3f8;
|
|
513
|
+
--scale-blue-hi: #4575b4;
|
|
514
|
+
--scale-teal-hi: #1a9988;
|
|
515
|
+
--scale-aqua-1: #a4d7e1;
|
|
516
|
+
--scale-aqua-2: #4ec1d4;
|
|
517
|
+
--scale-aqua-3: #0095b7;
|
|
518
|
+
--scale-aqua-4: #005e8b;
|
|
519
|
+
--scale-gray-lo: #f5f5f5;
|
|
520
|
+
--scale-gray-hi: #333333;
|
|
521
|
+
--scale-purple-1: #f3e5f5;
|
|
522
|
+
--scale-purple-2: #ce93d8;
|
|
523
|
+
--scale-purple-3: #ab47bc;
|
|
524
|
+
--scale-purple-4: #7b1fa2;
|
|
525
|
+
--scale-green-1: #e8f5e9;
|
|
526
|
+
--scale-green-2: #a5d6a7;
|
|
527
|
+
--scale-green-3: #66bb6a;
|
|
528
|
+
--scale-green-4: #2e7d32;
|
|
529
|
+
/* Diagonal band scales (Scatter.createDiagonal) — white center outward */
|
|
530
|
+
--scale-diag-green-1: #ffffff;
|
|
531
|
+
--scale-diag-green-2: #c6f6d5;
|
|
532
|
+
--scale-diag-green-3: #68d391;
|
|
533
|
+
--scale-diag-green-4: #38a169;
|
|
534
|
+
--scale-diag-red-1: #ffffff;
|
|
535
|
+
--scale-diag-red-2: #fed7d7;
|
|
536
|
+
--scale-diag-red-3: #fc8181;
|
|
537
|
+
--scale-diag-red-4: #e53e3e;
|
|
538
|
+
|
|
539
|
+
/* ===========================
|
|
540
|
+
BAR CHART SPECIFIC
|
|
541
|
+
=========================== */
|
|
542
|
+
|
|
543
|
+
/* Bar sizing */
|
|
544
|
+
--bar-height: 24px;
|
|
545
|
+
--bar-height-mini: 18px;
|
|
546
|
+
--bar-gap: 8px;
|
|
547
|
+
--bar-border-radius: 3px;
|
|
548
|
+
|
|
549
|
+
/* Zero baseline on mixed-sign bar charts (tracks the dark theme via the
|
|
550
|
+
underlying text token) */
|
|
551
|
+
--bar-zero-line-color: var(--color-text-primary);
|
|
552
|
+
--bar-zero-line-width: 1.5;
|
|
553
|
+
|
|
554
|
+
/* Gantt */
|
|
555
|
+
--gantt-bar-height: 18px;
|
|
556
|
+
--gantt-bar-gap: 6px;
|
|
557
|
+
--gantt-border-radius: 2px;
|
|
558
|
+
|
|
559
|
+
/* Waterfall connector hairlines (between consecutive bars) */
|
|
560
|
+
--waterfall-connector-color: rgba(0, 0, 0, 0.18);
|
|
561
|
+
|
|
562
|
+
/* Container */
|
|
563
|
+
--container-max-width: 660px;
|
|
564
|
+
|
|
565
|
+
/* Bar track (background) */
|
|
566
|
+
--bar-track-color: var(--color-border-row);
|
|
567
|
+
--bar-track-opacity: 0.5;
|
|
568
|
+
|
|
569
|
+
/* Label positioning */
|
|
570
|
+
--bar-label-gap: 8px;
|
|
571
|
+
--bar-value-padding: 6px;
|
|
572
|
+
--bar-inline-threshold: 0.35;
|
|
573
|
+
|
|
574
|
+
/* Lollipop variant */
|
|
575
|
+
--lollipop-stem-width: 2px;
|
|
576
|
+
--lollipop-dot-radius: 6px;
|
|
577
|
+
--lollipop-dot-radius-hover: 8px;
|
|
578
|
+
|
|
579
|
+
/* Bullet chart */
|
|
580
|
+
--bullet-range-opacity: 0.25;
|
|
581
|
+
--bullet-measure-height: 8px;
|
|
582
|
+
--bullet-marker-width: 3px;
|
|
583
|
+
--bullet-marker-height: 16px;
|
|
584
|
+
|
|
585
|
+
/* Animation */
|
|
586
|
+
--bar-animation-duration: 800ms;
|
|
587
|
+
--bar-stagger-delay: 50ms;
|
|
588
|
+
|
|
589
|
+
/* Row layout */
|
|
590
|
+
--bar-row-height: 32px;
|
|
591
|
+
--bar-category-width: 100px;
|
|
592
|
+
|
|
593
|
+
/* ===========================
|
|
594
|
+
STAT FORMATTING OPTIONS
|
|
595
|
+
=========================== */
|
|
596
|
+
/* Baseball batting average format: .345 instead of 0.345
|
|
597
|
+
* Use formatBaseballAvg() helper or set data-format="baseball-avg"
|
|
598
|
+
*
|
|
599
|
+
* JavaScript helper:
|
|
600
|
+
* function formatBaseballAvg(value) {
|
|
601
|
+
* return value.toFixed(3).replace(/^0\./, '.');
|
|
602
|
+
* }
|
|
603
|
+
*/
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/* ===========================
|
|
607
|
+
INSTAGRAM EXPORT TIER
|
|
608
|
+
===========================
|
|
609
|
+
Opt-in via <html data-size="instagram">, paired with `size: 'instagram'`
|
|
610
|
+
in chart config (the SIZE_PRESETS geometry). Scales the text, stroke,
|
|
611
|
+
marker, and annotation tokens for 1080px social-feed posters that are
|
|
612
|
+
viewed at phone size — roughly 2.4x the screen-reading defaults. Colors
|
|
613
|
+
are untouched, so it composes with the dark theme. Same runtime contract
|
|
614
|
+
as dark mode: builders resolve tokens at render, so flipping the
|
|
615
|
+
attribute needs a re-render (ChartFactory.rerenderAll()). */
|
|
616
|
+
:root[data-size="instagram"] {
|
|
617
|
+
/* Typography */
|
|
618
|
+
--font-size-xs: 22px;
|
|
619
|
+
--font-size-sm: 25px;
|
|
620
|
+
--font-size-base: 27px;
|
|
621
|
+
--font-size-md: 29px;
|
|
622
|
+
--font-size-lg: 32px;
|
|
623
|
+
--font-size-xl: 35px;
|
|
624
|
+
--font-size-title: 64px;
|
|
625
|
+
--font-size-subtitle: 32px;
|
|
626
|
+
--shell-title-size: 38px;
|
|
627
|
+
|
|
628
|
+
/* Marks */
|
|
629
|
+
--line-stroke-width: 5;
|
|
630
|
+
--area-stroke-width: 4;
|
|
631
|
+
--line-dot-stroke-width: 4;
|
|
632
|
+
--bar-height: 56;
|
|
633
|
+
--bar-gap: 18;
|
|
634
|
+
|
|
635
|
+
/* Annotations */
|
|
636
|
+
--annotation-title-size: 34px;
|
|
637
|
+
--annotation-event-font-size: 24px;
|
|
638
|
+
--annotation-event-band-offset: 48;
|
|
639
|
+
--annotation-event-tick-height: 18;
|
|
640
|
+
--annotation-leader-threshold: 30;
|
|
641
|
+
|
|
642
|
+
/* Slope label dodge gaps track the scaled label text */
|
|
643
|
+
--slope-label-min-gap: 34;
|
|
644
|
+
--slope-label-min-gap-stacked: 72;
|
|
645
|
+
|
|
646
|
+
/* Bump chart marks at poster weight */
|
|
647
|
+
--bump-line-width: 6;
|
|
648
|
+
--bump-line-width-hover: 8;
|
|
649
|
+
--bump-dot-radius: 17;
|
|
650
|
+
--bump-dot-radius-hover: 20;
|
|
651
|
+
--bump-dot-stroke-width: 4;
|
|
652
|
+
--bump-rank-font-size: 20px;
|
|
653
|
+
--bump-label-gap: 16;
|
|
654
|
+
--bump-axis-offset: 26;
|
|
655
|
+
--bump-margin-top: 40;
|
|
656
|
+
--bump-margin-bottom: 60;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/* ===========================
|
|
660
|
+
DARK THEME
|
|
661
|
+
===========================
|
|
662
|
+
Opt-in via <html data-theme="dark">. Only color-bearing tokens are
|
|
663
|
+
overridden; spacing, sizing, and opacity tokens carry over.
|
|
664
|
+
|
|
665
|
+
Builders resolve tokens live at render time (getCSSVar reads
|
|
666
|
+
documentElement), so switching themes at runtime requires a re-render:
|
|
667
|
+
call chart.rerender() on each chart facade (tables: table.update(data)).
|
|
668
|
+
CSS-styled surfaces (table chrome, tooltip shell, containers) restyle
|
|
669
|
+
immediately without one. */
|
|
670
|
+
:root[data-theme="dark"] {
|
|
671
|
+
/* Text — --color-black is the strongest ink, not literal black */
|
|
672
|
+
--color-black: #f4f4f5;
|
|
673
|
+
--color-text-primary: #e4e4e7;
|
|
674
|
+
--color-text-muted: #a1a1aa;
|
|
675
|
+
--color-text-subtle: #8b8b93;
|
|
676
|
+
--color-text-faint: #71717a;
|
|
677
|
+
--color-text-disabled: #52525b;
|
|
678
|
+
|
|
679
|
+
/* Backgrounds */
|
|
680
|
+
--color-bg-body: #101012;
|
|
681
|
+
--color-bg-container: #1b1b1e;
|
|
682
|
+
--color-bg-hover: #232327;
|
|
683
|
+
--color-bg-highlight: #2a2a2f;
|
|
684
|
+
|
|
685
|
+
/* Borders */
|
|
686
|
+
--color-border-header: #e4e4e7;
|
|
687
|
+
--color-border-row: #2a2a2e;
|
|
688
|
+
--color-border-light: #333338;
|
|
689
|
+
--color-border-footer: #2f2f34;
|
|
690
|
+
--color-border-tooltip: #3f3f46;
|
|
691
|
+
|
|
692
|
+
/* Shadows */
|
|
693
|
+
--shadow-container: 0 1px 3px rgba(0, 0, 0, 0.6);
|
|
694
|
+
--shadow-tooltip: 0 4px 14px rgba(0, 0, 0, 0.6);
|
|
695
|
+
|
|
696
|
+
/* Chart palette — brightened for dark surfaces */
|
|
697
|
+
--chart-primary: #60a5fa;
|
|
698
|
+
--chart-primary-light: rgba(96, 165, 250, 0.35);
|
|
699
|
+
--chart-primary-faint: rgba(96, 165, 250, 0.12);
|
|
700
|
+
--chart-secondary: #4ade80;
|
|
701
|
+
--chart-tertiary: #fb923c;
|
|
702
|
+
--chart-green: #4ade80;
|
|
703
|
+
--chart-lime: #a3e635;
|
|
704
|
+
--chart-orange: #fb923c;
|
|
705
|
+
--chart-purple: #c084fc;
|
|
706
|
+
--chart-purple-light: rgba(192, 132, 252, 0.4);
|
|
707
|
+
--chart-purple-faint: rgba(192, 132, 252, 0.08);
|
|
708
|
+
--chart-red: #f87171;
|
|
709
|
+
|
|
710
|
+
/* Multi-series palette — lighter gray is the more prominent one on dark */
|
|
711
|
+
--chart-series-1: #64748b;
|
|
712
|
+
--chart-series-2: #94a3b8;
|
|
713
|
+
|
|
714
|
+
/* Neutral/gray for cumulative/baseline lines */
|
|
715
|
+
--chart-neutral: #9ca3af;
|
|
716
|
+
--chart-neutral-light: rgba(156, 163, 175, 0.4);
|
|
717
|
+
--chart-neutral-faint: rgba(156, 163, 175, 0.08);
|
|
718
|
+
|
|
719
|
+
/* Slope */
|
|
720
|
+
--slope-muted-color: #52525b;
|
|
721
|
+
--slope-band-1: #2c1d1d;
|
|
722
|
+
--slope-band-2: #2b2717;
|
|
723
|
+
--slope-band-3: #16281c;
|
|
724
|
+
--slope-band-4: #17222f;
|
|
725
|
+
|
|
726
|
+
/* Misc structural strokes */
|
|
727
|
+
--stream-stroke-color: #1b1b1e;
|
|
728
|
+
--waterfall-connector-color: #52525b;
|
|
729
|
+
--dot-connector-color: #3f3f46;
|
|
730
|
+
--annotation-event-guide-color: #52525b;
|
|
731
|
+
--contour-line-color: rgba(255, 255, 255, 0.15);
|
|
732
|
+
--kde-contour-line-color: rgba(255, 255, 255, 0.12);
|
|
733
|
+
|
|
734
|
+
/* Categorical series palette — Set2, lifted for dark backgrounds */
|
|
735
|
+
--area-color-1: #74d0b3;
|
|
736
|
+
--area-color-2: #ff9e78;
|
|
737
|
+
--area-color-3: #a2b3dc;
|
|
738
|
+
--area-color-4: #ef9dd0;
|
|
739
|
+
--area-color-5: #b6e268;
|
|
740
|
+
--area-color-6: #ffe45c;
|
|
741
|
+
--area-color-7: #ecd2a8;
|
|
742
|
+
--area-color-8: #c6c6c6;
|
|
743
|
+
|
|
744
|
+
/* Temperature palette — extremes stay bright, middle fades to surface */
|
|
745
|
+
--temp-cold-10: #3f7fd1;
|
|
746
|
+
--temp-cold-9: #38689f;
|
|
747
|
+
--temp-cold-8: #2f5377;
|
|
748
|
+
--temp-cold-7: #263e52;
|
|
749
|
+
--temp-neutral: #26262b;
|
|
750
|
+
--temp-warm-5: #4a3a20;
|
|
751
|
+
--temp-warm-4: #6e4f22;
|
|
752
|
+
--temp-warm-3: #9c6a25;
|
|
753
|
+
--temp-warm-2: #d07f1f;
|
|
754
|
+
--temp-warm-1: #ff8a3d;
|
|
755
|
+
|
|
756
|
+
/* Sequential scales — lo ends re-anchor from near-white to surface-tinted
|
|
757
|
+
darks so low values fade into the background, high values stay vivid */
|
|
758
|
+
--scale-orange-lo: #2e2018;
|
|
759
|
+
--scale-orange-hi: #ff8a5c;
|
|
760
|
+
--scale-orange-red-hi: #e35d5d;
|
|
761
|
+
--scale-blue-lo: #16202c;
|
|
762
|
+
--scale-blue-hi: #6ea8dc;
|
|
763
|
+
--scale-teal-hi: #34b3a0;
|
|
764
|
+
--scale-aqua-1: #1a3a42;
|
|
765
|
+
--scale-aqua-2: #16606e;
|
|
766
|
+
--scale-aqua-3: #1d92ab;
|
|
767
|
+
--scale-aqua-4: #5cc6da;
|
|
768
|
+
--scale-gray-lo: #232326;
|
|
769
|
+
--scale-gray-hi: #d4d4d8;
|
|
770
|
+
--scale-purple-1: #241a2b;
|
|
771
|
+
--scale-purple-2: #4a3357;
|
|
772
|
+
--scale-purple-3: #7b57a0;
|
|
773
|
+
--scale-purple-4: #b58ae0;
|
|
774
|
+
--scale-green-1: #16241a;
|
|
775
|
+
--scale-green-2: #2f5138;
|
|
776
|
+
--scale-green-3: #4f8c58;
|
|
777
|
+
--scale-green-4: #7ac47f;
|
|
778
|
+
--scale-diag-green-1: #1b1b1e;
|
|
779
|
+
--scale-diag-green-2: #1d3524;
|
|
780
|
+
--scale-diag-green-3: #2f6b40;
|
|
781
|
+
--scale-diag-green-4: #4caf6d;
|
|
782
|
+
--scale-diag-red-1: #1b1b1e;
|
|
783
|
+
--scale-diag-red-2: #3a2023;
|
|
784
|
+
--scale-diag-red-3: #7a3b3b;
|
|
785
|
+
--scale-diag-red-4: #c25959;
|
|
786
|
+
|
|
787
|
+
/* Chart story — band lifts off the dark container surface; accent follows
|
|
788
|
+
--chart-primary automatically, and the panel wash re-mixes from it */
|
|
789
|
+
--story-band-bg: #2a2a2f;
|
|
790
|
+
--story-band-text: #e4e4e7;
|
|
791
|
+
--story-band-label: #a1a1aa;
|
|
792
|
+
}
|