@opendata-ai/openchart-core 7.10.0 → 8.0.0-rc.1
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 +1154 -119
- package/dist/index.js +530 -41
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -1
- package/dist/styles.css.map +1 -0
- package/package.json +9 -3
- package/schema/chart.schema.json +8957 -0
- package/schema/table.schema.json +861 -0
- package/schema/vizspec.schema.json +17694 -0
- package/src/accessibility/alt-text.ts +39 -1
- package/src/accessibility/aria.ts +4 -2
- package/src/colors/__tests__/colorblind.test.ts +12 -0
- package/src/colors/colorblind.ts +11 -2
- package/src/colors/contrast.ts +11 -0
- package/src/colors/index.ts +9 -1
- package/src/colors/palettes.ts +47 -0
- package/src/helpers/__tests__/deep-merge.test.ts +54 -0
- package/src/helpers/__tests__/spec-builders.test.ts +3 -3
- package/src/helpers/deep-merge.ts +29 -0
- package/src/helpers/spec-builders.ts +7 -7
- package/src/index.ts +29 -1
- package/src/labels/collision.ts +1 -0
- package/src/layout/chrome.ts +24 -0
- package/src/layout/index.ts +1 -1
- package/src/locale/__tests__/format.test.ts +347 -11
- package/src/locale/format.ts +243 -18
- package/src/locale/index.ts +10 -1
- package/src/responsive/index.ts +2 -0
- package/src/responsive/metrics.ts +74 -9
- package/src/schema/__tests__/generated-artifacts.test.ts +42 -0
- package/src/schema/__tests__/schema.test.ts +179 -0
- package/src/styles/__tests__/reduced-motion-selectors.test.ts +28 -0
- package/src/styles/animation.css +197 -168
- package/src/styles/base.css +89 -62
- package/src/styles/chrome.css +173 -179
- package/src/styles/dark.css +38 -35
- package/src/styles/graph.css +116 -111
- package/src/styles/index.css +5 -0
- package/src/styles/keyframes.css +115 -100
- package/src/styles/legend.css +14 -12
- package/src/styles/reduced-motion.css +61 -40
- package/src/styles/series-search.css +153 -0
- package/src/styles/sparkline.css +14 -12
- package/src/styles/table-animation.css +82 -80
- package/src/styles/table.css +314 -302
- package/src/styles/token-definitions.ts +199 -0
- package/src/styles/tokens.css +132 -128
- package/src/styles/tooltip.css +109 -115
- package/src/styles/you-draw-it.css +126 -0
- package/src/types/__tests__/encoding.test.ts +86 -17
- package/src/types/__tests__/spec.test.ts +16 -12
- package/src/types/encoding.ts +69 -25
- package/src/types/events.ts +12 -0
- package/src/types/index.ts +39 -3
- package/src/types/layout.ts +414 -8
- package/src/types/schema-roots.ts +32 -0
- package/src/types/spec.ts +643 -84
- package/src/types/table.ts +3 -2
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { CSS_TOKEN_ROOT_SELECTORS } from '../token-definitions';
|
|
5
|
+
|
|
6
|
+
describe('reduced-motion.css', () => {
|
|
7
|
+
it('uses the same root selectors as CSS_TOKEN_ROOT_SELECTORS', () => {
|
|
8
|
+
const css = readFileSync(resolve(__dirname, '../reduced-motion.css'), 'utf8');
|
|
9
|
+
const selectors = CSS_TOKEN_ROOT_SELECTORS.every((sel) => css.includes(sel));
|
|
10
|
+
expect(selectors).toBe(true);
|
|
11
|
+
|
|
12
|
+
const isBlocks = [...css.matchAll(/:is\(\s*([\s\S]*?)\s*\)/g)];
|
|
13
|
+
const selectorsInCss = new Set(
|
|
14
|
+
isBlocks.flatMap((m) =>
|
|
15
|
+
m[1]
|
|
16
|
+
.split(',')
|
|
17
|
+
.map((s) => s.trim())
|
|
18
|
+
.filter(Boolean),
|
|
19
|
+
),
|
|
20
|
+
);
|
|
21
|
+
for (const sel of CSS_TOKEN_ROOT_SELECTORS) {
|
|
22
|
+
expect(selectorsInCss.has(sel)).toBe(true);
|
|
23
|
+
}
|
|
24
|
+
for (const sel of selectorsInCss) {
|
|
25
|
+
expect(CSS_TOKEN_ROOT_SELECTORS).toContain(sel);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
package/src/styles/animation.css
CHANGED
|
@@ -1,170 +1,199 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
@layer oc.animation {
|
|
2
|
+
/* ---------------------------------------------------------------------------
|
|
3
|
+
* Animation scoped rules (.oc-animate enables animation on the chart root)
|
|
4
|
+
* --------------------------------------------------------------------------- */
|
|
5
|
+
|
|
6
|
+
.oc-animate {
|
|
7
|
+
/* Vertical bars (default): smooth ease-out, no overshoot.
|
|
8
|
+
oc-mark-bar is reserved for future mark type aliases. */
|
|
9
|
+
& .oc-mark-rect rect,
|
|
10
|
+
& .oc-mark-bar rect {
|
|
11
|
+
animation: oc-enter-bar var(--oc-animation-duration) var(--oc-ease-smooth) both;
|
|
12
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Horizontal bars (data-orient is on the mark group, not the SVG root) */
|
|
16
|
+
& .oc-mark-rect[data-orient="horizontal"] rect,
|
|
17
|
+
& .oc-mark-bar[data-orient="horizontal"] rect {
|
|
18
|
+
animation-name: oc-enter-bar-h;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Stacked bar/column segments: chain sequentially so each segment starts
|
|
22
|
+
right when the previous one finishes, creating one fluid reveal.
|
|
23
|
+
Uses linear easing so handoffs between segments are seamless (no
|
|
24
|
+
deceleration/acceleration stutter at segment boundaries). */
|
|
25
|
+
& .oc-mark-rect[data-stack-pos] rect {
|
|
26
|
+
animation-duration: var(--oc-stack-segment-duration, 150ms);
|
|
27
|
+
animation-timing-function: linear;
|
|
28
|
+
animation-delay: calc(
|
|
29
|
+
var(--oc-animation-stagger) *
|
|
30
|
+
var(--oc-mark-index, 0) +
|
|
31
|
+
var(--oc-stack-pos, 0) *
|
|
32
|
+
var(--oc-stack-segment-duration, 150ms)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Line marks: entire group clips left-to-right (no WAAPI needed) */
|
|
37
|
+
& .oc-mark-line {
|
|
38
|
+
animation: oc-enter-line var(--oc-animation-duration)
|
|
39
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
40
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Area marks: entire group clips left-to-right + fades in */
|
|
44
|
+
& .oc-mark-area {
|
|
45
|
+
animation: oc-enter-line var(--oc-animation-duration)
|
|
46
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
47
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Arc marks (pie/donut slices): simple fade in.
|
|
51
|
+
Scale transforms break arc positioning because arcs use translate()
|
|
52
|
+
on parent groups. A clean fade is more elegant for pie/donut anyway. */
|
|
53
|
+
& .oc-mark-arc {
|
|
54
|
+
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
55
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
56
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Point marks (scatter, dot).
|
|
60
|
+
Points render as bare <circle> elements with class oc-mark-point directly,
|
|
61
|
+
not wrapped in a group, so we target circle.oc-mark-point (not descendant).
|
|
62
|
+
Duration is 40% of the configured duration (quick pop-in relative to other marks). */
|
|
63
|
+
& circle.oc-mark-point,
|
|
64
|
+
& circle.oc-mark-circle {
|
|
65
|
+
animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)
|
|
66
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
67
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Points on line/area charts: delay so they pop in as the line draws through. */
|
|
71
|
+
& .oc-mark-line ~ circle.oc-mark-point,
|
|
72
|
+
& .oc-mark-area ~ circle.oc-mark-point {
|
|
73
|
+
animation-delay: calc(
|
|
74
|
+
var(--oc-animation-duration) *
|
|
75
|
+
0.35 +
|
|
76
|
+
var(--oc-animation-stagger) *
|
|
77
|
+
var(--oc-mark-index, 0)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Text marks: fade + slight slide up */
|
|
82
|
+
& .oc-mark-text text {
|
|
83
|
+
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)
|
|
84
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
85
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Rule marks: fade in */
|
|
89
|
+
& .oc-mark-rule line {
|
|
90
|
+
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)
|
|
91
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
92
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Tick marks: fade in */
|
|
96
|
+
& .oc-mark-tick line {
|
|
97
|
+
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)
|
|
98
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
99
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Data labels: fade after their parent mark */
|
|
103
|
+
& .oc-mark-label {
|
|
104
|
+
animation: oc-enter-fade 300ms var(--oc-ease-smooth) both;
|
|
105
|
+
animation-delay: calc(
|
|
106
|
+
var(--oc-animation-stagger) *
|
|
107
|
+
var(--oc-mark-index, 0) +
|
|
108
|
+
var(--oc-animation-duration) *
|
|
109
|
+
0.7
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Annotations: fade in after marks finish */
|
|
114
|
+
& .oc-annotation {
|
|
115
|
+
animation: oc-enter-fade 400ms var(--oc-ease-smooth) both;
|
|
116
|
+
animation-delay: calc(var(--oc-animation-duration) + var(--oc-annotation-delay, 200ms));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Tilemap tiles: fade in with jittered stagger for organic feel.
|
|
120
|
+
Per-tile delay is computed in the renderer with pseudo-random variation. */
|
|
121
|
+
& .oc-tilemap-tile {
|
|
122
|
+
animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.35) ease-in both;
|
|
123
|
+
animation-delay: var(--oc-tile-delay, 0ms);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Map features: fill color reveal with shuffled stagger.
|
|
127
|
+
Per-feature --oc-map-delay is computed in the renderer via a seeded
|
|
128
|
+
Fisher-Yates shuffle so features pop in organically. */
|
|
129
|
+
& .oc-map-feature {
|
|
130
|
+
animation: oc-enter-map-fill var(--oc-animation-duration)
|
|
131
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
132
|
+
animation-delay: var(--oc-map-delay, 0ms);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Bulk mode: high feature counts (counties, ~3k+) get a single group
|
|
136
|
+
fade instead of per-feature fill animations. opacity is GPU-compositable
|
|
137
|
+
so this stays smooth regardless of child count. */
|
|
138
|
+
& .oc-map-features[data-bulk-animate] {
|
|
139
|
+
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
140
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
& .oc-map-features[data-bulk-animate] .oc-map-feature {
|
|
144
|
+
animation: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Map borders: fade in near the end of the feature sweep */
|
|
148
|
+
& .oc-map-borders path {
|
|
149
|
+
animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4) ease-in both;
|
|
150
|
+
animation-delay: calc(var(--oc-animation-duration) * 0.7);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Sankey nodes: fade in with stagger by column depth (left-to-right) */
|
|
154
|
+
& .oc-sankey-node rect {
|
|
155
|
+
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
156
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
157
|
+
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* Sankey links: fade in after nodes, with stagger.
|
|
161
|
+
Links delay by 30% of duration so nodes appear first, then links flow in. */
|
|
162
|
+
& .oc-sankey-link path {
|
|
163
|
+
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
164
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
165
|
+
animation-delay: calc(
|
|
166
|
+
var(--oc-animation-duration) *
|
|
167
|
+
0.3 +
|
|
168
|
+
var(--oc-animation-stagger) *
|
|
169
|
+
var(--oc-mark-index, 0)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Barlist rows: fade + slide up per row, bars grow left-to-right */
|
|
174
|
+
& .oc-barlist-row {
|
|
175
|
+
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)
|
|
176
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
177
|
+
animation-delay: var(--oc-row-delay, 0ms);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
& .oc-barlist-bar {
|
|
181
|
+
animation: oc-enter-bar-h var(--oc-animation-duration)
|
|
182
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
183
|
+
animation-delay: var(--oc-row-delay, 0ms);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* ---------------------------------------------------------------------------
|
|
188
|
+
* Sparkline mode: pair the line/area reveal with a stronger ease-out so it
|
|
189
|
+
* doesn't read as a uniform left-to-right swipe. cubic-bezier(0.16, 1, 0.3, 1)
|
|
190
|
+
* is "expo-out" — fast initial draw that decelerates noticeably at the end,
|
|
191
|
+
* giving the trend a hand-drawn feel. Duration is bumped via the engine
|
|
192
|
+
* (compile.ts) so the cleanup timer stays in sync.
|
|
193
|
+
* --------------------------------------------------------------------------- */
|
|
194
|
+
|
|
195
|
+
.oc-animate[data-display="sparkline"] .oc-mark-line,
|
|
196
|
+
.oc-animate[data-display="sparkline"] .oc-mark-area {
|
|
197
|
+
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
|
12
198
|
}
|
|
13
|
-
|
|
14
|
-
/* Horizontal bars (data-orient is on the mark group, not the SVG root) */
|
|
15
|
-
& .oc-mark-rect[data-orient="horizontal"] rect,
|
|
16
|
-
& .oc-mark-bar[data-orient="horizontal"] rect {
|
|
17
|
-
animation-name: oc-enter-bar-h;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/* Stacked bar/column segments: chain sequentially so each segment starts
|
|
21
|
-
right when the previous one finishes, creating one fluid reveal.
|
|
22
|
-
Uses linear easing so handoffs between segments are seamless (no
|
|
23
|
-
deceleration/acceleration stutter at segment boundaries). */
|
|
24
|
-
& .oc-mark-rect[data-stack-pos] rect {
|
|
25
|
-
animation-duration: var(--oc-stack-segment-duration, 150ms);
|
|
26
|
-
animation-timing-function: linear;
|
|
27
|
-
animation-delay: calc(
|
|
28
|
-
var(--oc-animation-stagger) *
|
|
29
|
-
var(--oc-mark-index, 0) +
|
|
30
|
-
var(--oc-stack-pos, 0) *
|
|
31
|
-
var(--oc-stack-segment-duration, 150ms)
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* Line marks: entire group clips left-to-right (no WAAPI needed) */
|
|
36
|
-
& .oc-mark-line {
|
|
37
|
-
animation: oc-enter-line var(--oc-animation-duration)
|
|
38
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
39
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* Area marks: entire group clips left-to-right + fades in */
|
|
43
|
-
& .oc-mark-area {
|
|
44
|
-
animation: oc-enter-line var(--oc-animation-duration)
|
|
45
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
46
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/* Arc marks (pie/donut slices): simple fade in.
|
|
50
|
-
Scale transforms break arc positioning because arcs use translate()
|
|
51
|
-
on parent groups. A clean fade is more elegant for pie/donut anyway. */
|
|
52
|
-
& .oc-mark-arc {
|
|
53
|
-
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
54
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
55
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/* Point marks (scatter, dot).
|
|
59
|
-
Points render as bare <circle> elements with class oc-mark-point directly,
|
|
60
|
-
not wrapped in a group, so we target circle.oc-mark-point (not descendant).
|
|
61
|
-
Duration is 40% of the configured duration (quick pop-in relative to other marks). */
|
|
62
|
-
& circle.oc-mark-point,
|
|
63
|
-
& circle.oc-mark-circle {
|
|
64
|
-
animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)
|
|
65
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
66
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/* Points on line/area charts: delay so they pop in as the line draws through. */
|
|
70
|
-
& .oc-mark-line ~ circle.oc-mark-point,
|
|
71
|
-
& .oc-mark-area ~ circle.oc-mark-point {
|
|
72
|
-
animation-delay: calc(
|
|
73
|
-
var(--oc-animation-duration) *
|
|
74
|
-
0.35 +
|
|
75
|
-
var(--oc-animation-stagger) *
|
|
76
|
-
var(--oc-mark-index, 0)
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/* Text marks: fade + slight slide up */
|
|
81
|
-
& .oc-mark-text text {
|
|
82
|
-
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)
|
|
83
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
84
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/* Rule marks: fade in */
|
|
88
|
-
& .oc-mark-rule line {
|
|
89
|
-
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)
|
|
90
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
91
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/* Tick marks: fade in */
|
|
95
|
-
& .oc-mark-tick line {
|
|
96
|
-
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)
|
|
97
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
98
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/* Data labels: fade after their parent mark */
|
|
102
|
-
& .oc-mark-label {
|
|
103
|
-
animation: oc-enter-fade 300ms var(--oc-ease-smooth) both;
|
|
104
|
-
animation-delay: calc(
|
|
105
|
-
var(--oc-animation-stagger) *
|
|
106
|
-
var(--oc-mark-index, 0) +
|
|
107
|
-
var(--oc-animation-duration) *
|
|
108
|
-
0.7
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/* Annotations: fade in after marks finish */
|
|
113
|
-
& .oc-annotation {
|
|
114
|
-
animation: oc-enter-fade 400ms var(--oc-ease-smooth) both;
|
|
115
|
-
animation-delay: calc(var(--oc-animation-duration) + var(--oc-annotation-delay, 200ms));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/* Tilemap tiles: fade in with jittered stagger for organic feel.
|
|
119
|
-
Per-tile delay is computed in the renderer with pseudo-random variation. */
|
|
120
|
-
& .oc-tilemap-tile {
|
|
121
|
-
animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.35) ease-in both;
|
|
122
|
-
animation-delay: var(--oc-tile-delay, 0ms);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/* Sankey nodes: fade in with stagger by column depth (left-to-right) */
|
|
126
|
-
& .oc-sankey-node rect {
|
|
127
|
-
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
128
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
129
|
-
animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/* Sankey links: fade in after nodes, with stagger.
|
|
133
|
-
Links delay by 30% of duration so nodes appear first, then links flow in. */
|
|
134
|
-
& .oc-sankey-link path {
|
|
135
|
-
animation: oc-enter-fade-only var(--oc-animation-duration)
|
|
136
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
137
|
-
animation-delay: calc(
|
|
138
|
-
var(--oc-animation-duration) *
|
|
139
|
-
0.3 +
|
|
140
|
-
var(--oc-animation-stagger) *
|
|
141
|
-
var(--oc-mark-index, 0)
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/* Barlist rows: fade + slide up per row, bars grow left-to-right */
|
|
146
|
-
& .oc-barlist-row {
|
|
147
|
-
animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)
|
|
148
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
149
|
-
animation-delay: var(--oc-row-delay, 0ms);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
& .oc-barlist-bar {
|
|
153
|
-
animation: oc-enter-bar-h var(--oc-animation-duration)
|
|
154
|
-
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
155
|
-
animation-delay: var(--oc-row-delay, 0ms);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/* ---------------------------------------------------------------------------
|
|
160
|
-
* Sparkline mode: pair the line/area reveal with a stronger ease-out so it
|
|
161
|
-
* doesn't read as a uniform left-to-right swipe. cubic-bezier(0.16, 1, 0.3, 1)
|
|
162
|
-
* is "expo-out" — fast initial draw that decelerates noticeably at the end,
|
|
163
|
-
* giving the trend a hand-drawn feel. Duration is bumped via the engine
|
|
164
|
-
* (compile.ts) so the cleanup timer stays in sync.
|
|
165
|
-
* --------------------------------------------------------------------------- */
|
|
166
|
-
|
|
167
|
-
.oc-animate[data-display="sparkline"] .oc-mark-line,
|
|
168
|
-
.oc-animate[data-display="sparkline"] .oc-mark-area {
|
|
169
|
-
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
|
170
199
|
}
|
package/src/styles/base.css
CHANGED
|
@@ -1,75 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
@layer oc.base {
|
|
2
|
+
/* ---------------------------------------------------------------------------
|
|
3
|
+
* Wrapper roots
|
|
4
|
+
* --------------------------------------------------------------------------- */
|
|
4
5
|
|
|
5
|
-
.oc-chart-root {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
6
|
+
.oc-chart-root {
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
}
|
|
9
10
|
|
|
10
|
-
.oc-table-root,
|
|
11
|
-
.oc-graph-root,
|
|
12
|
-
.oc-sankey-root,
|
|
13
|
-
.oc-barlist-root
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
.oc-table-root,
|
|
12
|
+
.oc-graph-root,
|
|
13
|
+
.oc-sankey-root,
|
|
14
|
+
.oc-barlist-root,
|
|
15
|
+
.oc-tilemap-root,
|
|
16
|
+
.oc-map-root {
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
}
|
|
17
20
|
|
|
18
|
-
.oc-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
+
.oc-table-root {
|
|
22
|
+
overflow: auto;
|
|
23
|
+
}
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
/* ---------------------------------------------------------------------------
|
|
26
|
+
* Chart container
|
|
27
|
+
* --------------------------------------------------------------------------- */
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
.oc-chart {
|
|
30
|
+
font-family: var(--oc-font-family);
|
|
31
|
+
display: block;
|
|
32
|
+
width: 100%;
|
|
33
|
+
}
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
width: 100%;
|
|
34
|
-
}
|
|
35
|
+
/* ---------------------------------------------------------------------------
|
|
36
|
+
* BarList SVG container
|
|
37
|
+
* --------------------------------------------------------------------------- */
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
.oc-tilemap,
|
|
40
|
+
.oc-map {
|
|
41
|
+
display: block;
|
|
42
|
+
width: 100%;
|
|
43
|
+
height: auto;
|
|
44
|
+
}
|
|
39
45
|
|
|
40
|
-
.oc-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
height: auto;
|
|
44
|
-
}
|
|
46
|
+
.oc-map-feature {
|
|
47
|
+
transition: opacity 400ms ease;
|
|
48
|
+
}
|
|
45
49
|
|
|
46
|
-
.oc-barlist {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
+
.oc-barlist {
|
|
51
|
+
display: block;
|
|
52
|
+
width: 100%;
|
|
53
|
+
}
|
|
50
54
|
|
|
51
|
-
/* ---------------------------------------------------------------------------
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
.oc-sr-only {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
55
|
+
/* ---------------------------------------------------------------------------
|
|
56
|
+
* Screen reader only utility
|
|
57
|
+
* --------------------------------------------------------------------------- */
|
|
58
|
+
|
|
59
|
+
.oc-sr-only {
|
|
60
|
+
position: absolute;
|
|
61
|
+
width: 1px;
|
|
62
|
+
height: 1px;
|
|
63
|
+
padding: 0;
|
|
64
|
+
margin: -1px;
|
|
65
|
+
overflow: hidden;
|
|
66
|
+
clip-path: inset(50%);
|
|
67
|
+
white-space: nowrap;
|
|
68
|
+
border-width: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* ---------------------------------------------------------------------------
|
|
72
|
+
* Editable hover feedback
|
|
73
|
+
* --------------------------------------------------------------------------- */
|
|
74
|
+
|
|
75
|
+
.oc-editable-hover {
|
|
76
|
+
outline: 1.5px solid var(--oc-editable-hover);
|
|
77
|
+
outline-offset: 2px;
|
|
78
|
+
border-radius: 2px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ---------------------------------------------------------------------------
|
|
82
|
+
* Keyboard focus indicators
|
|
83
|
+
*
|
|
84
|
+
* --oc-focus carries a light value in tokens.css and a dark value in
|
|
85
|
+
* dark.css, so both rings stay visible in either mode.
|
|
86
|
+
* --------------------------------------------------------------------------- */
|
|
66
87
|
|
|
67
|
-
/*
|
|
68
|
-
|
|
69
|
-
|
|
88
|
+
/* Container ring when the chart itself receives keyboard focus. */
|
|
89
|
+
.oc-root:focus-visible {
|
|
90
|
+
outline: 2px solid var(--oc-focus);
|
|
91
|
+
outline-offset: 2px;
|
|
92
|
+
}
|
|
70
93
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
94
|
+
/* Mark ring during arrow-key navigation (see wireKeyboardNav). Outline on
|
|
95
|
+
* SVG elements draws around the mark's bounding box, same technique as
|
|
96
|
+
* .oc-editable-hover above. */
|
|
97
|
+
.oc-mark-focused {
|
|
98
|
+
outline: 2px solid var(--oc-focus);
|
|
99
|
+
outline-offset: 1px;
|
|
100
|
+
border-radius: 2px;
|
|
101
|
+
}
|
|
75
102
|
}
|