@opendata-ai/openchart-core 8.0.0-rc.2 → 8.0.0-rc.21

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.
Files changed (82) hide show
  1. package/dist/index.d.ts +490 -25
  2. package/dist/index.js +57 -19
  3. package/dist/index.js.map +1 -1
  4. package/dist/styles.css +1 -1
  5. package/dist/styles.css.map +1 -1
  6. package/package.json +1 -2
  7. package/schema/chart.schema.json +485 -35
  8. package/schema/table.schema.json +35 -1
  9. package/schema/vizspec.schema.json +1305 -120
  10. package/src/accessibility/__tests__/alt-text.test.ts +0 -110
  11. package/src/accessibility/__tests__/aria.test.ts +0 -125
  12. package/src/accessibility/alt-text.ts +0 -155
  13. package/src/accessibility/aria.ts +0 -75
  14. package/src/accessibility/index.ts +0 -6
  15. package/src/colors/__tests__/colorblind.test.ts +0 -75
  16. package/src/colors/__tests__/contrast.test.ts +0 -119
  17. package/src/colors/__tests__/palettes.test.ts +0 -74
  18. package/src/colors/colorblind.ts +0 -131
  19. package/src/colors/contrast.ts +0 -143
  20. package/src/colors/index.ts +0 -36
  21. package/src/colors/palettes.ts +0 -206
  22. package/src/helpers/__tests__/deep-merge.test.ts +0 -54
  23. package/src/helpers/__tests__/spec-builders.test.ts +0 -338
  24. package/src/helpers/deep-merge.ts +0 -29
  25. package/src/helpers/spec-builders.ts +0 -479
  26. package/src/index.ts +0 -215
  27. package/src/labels/__tests__/collision.test.ts +0 -310
  28. package/src/labels/collision.ts +0 -249
  29. package/src/labels/index.ts +0 -13
  30. package/src/layout/__tests__/chrome.test.ts +0 -208
  31. package/src/layout/__tests__/text-measure.test.ts +0 -57
  32. package/src/layout/chrome.ts +0 -470
  33. package/src/layout/index.ts +0 -18
  34. package/src/layout/text-measure.ts +0 -404
  35. package/src/layout/text-wrap.ts +0 -93
  36. package/src/locale/__tests__/format.test.ts +0 -606
  37. package/src/locale/format.ts +0 -459
  38. package/src/locale/index.ts +0 -21
  39. package/src/responsive/__tests__/breakpoints.test.ts +0 -146
  40. package/src/responsive/__tests__/metrics.test.ts +0 -52
  41. package/src/responsive/breakpoints.ts +0 -172
  42. package/src/responsive/index.ts +0 -53
  43. package/src/responsive/metrics.ts +0 -299
  44. package/src/schema/__tests__/generated-artifacts.test.ts +0 -42
  45. package/src/schema/__tests__/schema.test.ts +0 -179
  46. package/src/styles/__tests__/reduced-motion-selectors.test.ts +0 -28
  47. package/src/styles/animation.css +0 -199
  48. package/src/styles/base.css +0 -102
  49. package/src/styles/chrome.css +0 -174
  50. package/src/styles/dark.css +0 -44
  51. package/src/styles/graph.css +0 -135
  52. package/src/styles/index.css +0 -28
  53. package/src/styles/keyframes.css +0 -135
  54. package/src/styles/legend.css +0 -18
  55. package/src/styles/reduced-motion.css +0 -67
  56. package/src/styles/series-search.css +0 -153
  57. package/src/styles/sparkline.css +0 -16
  58. package/src/styles/table-animation.css +0 -93
  59. package/src/styles/table.css +0 -398
  60. package/src/styles/token-definitions.ts +0 -199
  61. package/src/styles/tokens.css +0 -156
  62. package/src/styles/tooltip.css +0 -126
  63. package/src/styles/you-draw-it.css +0 -126
  64. package/src/theme/__tests__/dark-mode.test.ts +0 -232
  65. package/src/theme/__tests__/defaults.test.ts +0 -73
  66. package/src/theme/__tests__/resolve.test.ts +0 -277
  67. package/src/theme/dark-mode.ts +0 -258
  68. package/src/theme/defaults.ts +0 -110
  69. package/src/theme/index.ts +0 -8
  70. package/src/theme/presets.ts +0 -64
  71. package/src/theme/resolve.ts +0 -312
  72. package/src/types/__tests__/encoding.test.ts +0 -368
  73. package/src/types/__tests__/gradient.test.ts +0 -95
  74. package/src/types/__tests__/spec.test.ts +0 -499
  75. package/src/types/encoding.ts +0 -280
  76. package/src/types/events.ts +0 -154
  77. package/src/types/index.ts +0 -287
  78. package/src/types/layout.ts +0 -1966
  79. package/src/types/schema-roots.ts +0 -32
  80. package/src/types/spec.ts +0 -2867
  81. package/src/types/table.ts +0 -108
  82. package/src/types/theme.ts +0 -209
@@ -1,44 +0,0 @@
1
- /* GENERATED FILE — do not edit. Source: packages/core/src/styles/token-definitions.ts. Regenerate: bun run generate:tokens */
2
-
3
- @layer oc.tokens {
4
- /* ---------------------------------------------------------------------------
5
- * Dark mode overrides (fallback defaults)
6
- *
7
- * At runtime, the JS theme engine stamps dark-adapted --oc-* custom
8
- * properties on each .oc-root container. These CSS values serve as
9
- * fallbacks for contexts where JS hasn't mounted yet.
10
- * --------------------------------------------------------------------------- */
11
-
12
- .oc-dark {
13
- /* Surfaces (zinc-based achromatic ramp) */
14
- --oc-bg: #09090b;
15
- --oc-card: #111113;
16
- --oc-secondary: #27272a;
17
-
18
- /* Text levels — see tokens.css for the cross-mode naming rationale */
19
- --oc-text: #f7f8f8;
20
- --oc-text-secondary: #d0d6e0;
21
- --oc-text-muted: #a1a1aa;
22
- --oc-text-faint: #52525b;
23
-
24
- /* Lines */
25
- --oc-gridline: rgba(255, 255, 255, 0.05);
26
- --oc-axis: rgba(255, 255, 255, 0.1);
27
- --oc-border: rgba(255, 255, 255, 0.1);
28
-
29
- /* Brand and semantic — accent stays cyan (no darkening on dark bg) */
30
- --oc-accent: #06b6d4;
31
- --oc-accent-strong: #06b6d4;
32
- --oc-positive: #34d399;
33
- --oc-negative: #fb7185;
34
- --oc-focus: #60a5fa;
35
-
36
- /* Interactive states */
37
- --oc-hover-bg: rgba(255, 255, 255, 0.05);
38
- --oc-tooltip-bg: rgba(17, 17, 19, 0.92);
39
- --oc-tooltip-border: rgba(255, 255, 255, 0.08);
40
- --oc-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 0 1px rgba(0, 0, 0, 0.4);
41
- --oc-tooltip-text: #f7f8f8;
42
- --oc-legend-text: #d0d6e0;
43
- }
44
- }
@@ -1,135 +0,0 @@
1
- @layer oc.components {
2
- /* ---------------------------------------------------------------------------
3
- * Graph
4
- * --------------------------------------------------------------------------- */
5
-
6
- .oc-graph-wrapper {
7
- position: relative;
8
- overflow: hidden;
9
- background: var(--oc-bg);
10
- font-family: var(--oc-font-family);
11
- width: 100%;
12
- height: 100%;
13
- }
14
-
15
- .oc-graph-canvas {
16
- display: block;
17
- width: 100%;
18
- height: 100%;
19
- cursor: grab;
20
- }
21
-
22
- .oc-graph-canvas--dragging {
23
- cursor: grabbing;
24
- }
25
-
26
- .oc-graph-chrome {
27
- position: absolute;
28
- top: 0;
29
- left: 0;
30
- right: 0;
31
- z-index: 2;
32
- padding: 16px 16px 8px;
33
- pointer-events: none;
34
-
35
- & .oc-title {
36
- font-size: var(--oc-title-size);
37
- font-weight: var(--oc-title-weight);
38
- letter-spacing: var(--oc-title-tracking);
39
- color: var(--oc-text);
40
- margin: 0 0 4px;
41
- --_stroke: color-mix(in srgb, var(--oc-bg) 80%, transparent);
42
- text-shadow:
43
- -2px -2px 0 var(--_stroke),
44
- 2px -2px 0 var(--_stroke),
45
- -2px 2px 0 var(--_stroke),
46
- 2px 2px 0 var(--_stroke),
47
- 0 -2px 0 var(--_stroke),
48
- 0 2px 0 var(--_stroke),
49
- -2px 0 0 var(--_stroke),
50
- 2px 0 0 var(--_stroke);
51
- }
52
-
53
- & .oc-subtitle {
54
- font-size: var(--oc-subtitle-size);
55
- color: var(--oc-text-secondary);
56
- margin: 0;
57
- --_stroke: color-mix(in srgb, var(--oc-bg) 80%, transparent);
58
- text-shadow:
59
- -1px -1px 0 var(--_stroke),
60
- 1px -1px 0 var(--_stroke),
61
- -1px 1px 0 var(--_stroke),
62
- 1px 1px 0 var(--_stroke);
63
- }
64
- }
65
-
66
- .oc-graph-legend {
67
- position: absolute;
68
- top: 8px;
69
- right: 8px;
70
- background: var(--oc-bg);
71
- border: 1px solid var(--oc-border);
72
- border-radius: var(--oc-border-radius);
73
- padding: 8px 12px;
74
- font-size: 12px;
75
- color: var(--oc-text-secondary);
76
- max-height: 200px;
77
- overflow-y: auto;
78
- }
79
-
80
- .oc-graph-legend-item {
81
- display: flex;
82
- align-items: center;
83
- gap: 6px;
84
- padding: 2px 0;
85
- }
86
-
87
- .oc-graph-legend-swatch {
88
- width: 10px;
89
- height: 10px;
90
- border-radius: 50%;
91
- flex-shrink: 0;
92
- }
93
-
94
- .oc-graph-search {
95
- position: absolute;
96
- top: 8px;
97
- left: 8px;
98
-
99
- & input {
100
- font-family: var(--oc-font-family);
101
- font-size: var(--oc-body-size);
102
- padding: 6px 10px;
103
- border: 1px solid var(--oc-border);
104
- border-radius: var(--oc-border-radius);
105
- background: var(--oc-bg);
106
- color: var(--oc-text);
107
- outline: none;
108
-
109
- &:focus {
110
- border-color: var(--oc-focus);
111
- box-shadow: 0 0 0 2px var(--oc-focus-ring-strong);
112
- }
113
- }
114
- }
115
-
116
- /* Dark mode graph overrides (darker bg for canvas-based rendering) */
117
- .oc-dark .oc-graph-wrapper,
118
- .oc-graph-wrapper.oc-dark {
119
- /* GitHub-dark canvas background, intentionally not a token */
120
- --oc-bg: #0d1117;
121
- }
122
-
123
- /*
124
- * graph-mount.ts stamps .oc-dark on both .oc-graph-wrapper and
125
- * .oc-graph-container simultaneously, so the self-variant
126
- * (.oc-dark.oc-graph-wrapper) and descendant variant
127
- * (.oc-dark .oc-graph-legend) resolve identically.
128
- */
129
- .oc-dark .oc-graph-legend,
130
- .oc-dark.oc-graph-wrapper .oc-graph-legend,
131
- .oc-dark .oc-graph-search input {
132
- background: rgba(13, 17, 23, 0.85);
133
- border-color: var(--oc-border);
134
- }
135
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * @opendata-ai/openchart-core styles
3
- *
4
- * CSS with oc- prefix for all class names.
5
- * CSS custom properties for theme overrides.
6
- * Dark mode via .oc-dark class on the container.
7
- * Cascade layers: oc.tokens, oc.base, oc.components, oc.animation, oc.reduced-motion.
8
- */
9
-
10
- /* For optimal typography, load Inter: https://fonts.google.com/specimen/Inter */
11
-
12
- @layer oc.tokens, oc.base, oc.components, oc.animation, oc.reduced-motion;
13
-
14
- @import "./tokens.css";
15
- @import "./dark.css";
16
- @import "./base.css";
17
- @import "./chrome.css";
18
- @import "./tooltip.css";
19
- @import "./legend.css";
20
- @import "./series-search.css";
21
- @import "./you-draw-it.css";
22
- @import "./table.css";
23
- @import "./table-animation.css";
24
- @import "./graph.css";
25
- @import "./sparkline.css";
26
- @import "./keyframes.css";
27
- @import "./animation.css";
28
- @import "./reduced-motion.css";
@@ -1,135 +0,0 @@
1
- @layer oc.animation {
2
- /* ---------------------------------------------------------------------------
3
- * Animation keyframes
4
- * --------------------------------------------------------------------------- */
5
-
6
- /* Bar entrance: clip-path reveal bottom-to-top + fade in (vertical columns).
7
- Bars grow upward from baseline with a soft opacity fade. */
8
- @keyframes oc-enter-bar {
9
- from {
10
- clip-path: inset(100% 0 0 0);
11
- opacity: 0;
12
- }
13
- 75% {
14
- opacity: 1;
15
- }
16
- to {
17
- clip-path: inset(0 0 0 0);
18
- opacity: 1;
19
- }
20
- }
21
-
22
- /* Bar entrance: clip-path reveal left-to-right + fade in (horizontal bars).
23
- Bars grow rightward from axis with a soft opacity fade. */
24
- @keyframes oc-enter-bar-h {
25
- from {
26
- clip-path: inset(0 100% 0 0);
27
- opacity: 0;
28
- }
29
- 75% {
30
- opacity: 1;
31
- }
32
- to {
33
- clip-path: inset(0 0 0 0);
34
- opacity: 1;
35
- }
36
- }
37
-
38
- /* Line/area entrance: clip-path reveal left-to-right + fade in.
39
- Lines draw in following reading direction with a soft lead-in. */
40
- @keyframes oc-enter-line {
41
- from {
42
- clip-path: inset(0 100% 0 0);
43
- opacity: 0;
44
- }
45
- 15% {
46
- opacity: 1;
47
- }
48
- to {
49
- clip-path: inset(0 0 0 0);
50
- opacity: 1;
51
- }
52
- }
53
-
54
- /* Point/arc entrance: scale up + fade in from center */
55
- @keyframes oc-enter-point {
56
- from {
57
- opacity: 0;
58
- transform: scale(0.3);
59
- }
60
- to {
61
- opacity: 1;
62
- transform: scale(1);
63
- }
64
- }
65
-
66
- /* Map feature entrance: fade in while transitioning fill from a neutral base
67
- to the data-driven color stored in --oc-feature-fill. */
68
- @keyframes oc-enter-map-fill {
69
- from {
70
- fill: var(--oc-secondary);
71
- opacity: 0;
72
- }
73
- to {
74
- fill: var(--oc-feature-fill);
75
- opacity: 1;
76
- }
77
- }
78
-
79
- /* Pure opacity fade (no transform). Safe for elements with existing transforms
80
- like arc groups that use translate() for positioning. */
81
- @keyframes oc-enter-fade-only {
82
- from {
83
- opacity: 0;
84
- }
85
- to {
86
- opacity: 1;
87
- }
88
- }
89
-
90
- /* Fade + subtle slide up for text, rule, tick, annotations */
91
- @keyframes oc-enter-fade {
92
- from {
93
- opacity: 0;
94
- transform: translateY(4px);
95
- }
96
- to {
97
- opacity: 1;
98
- transform: translateY(0);
99
- }
100
- }
101
-
102
- /* Table row entrance: slide up only, no opacity (cells fade independently
103
- to avoid opacity compounding between row and cell animations) */
104
- @keyframes oc-table-enter-row {
105
- from {
106
- transform: translateY(6px);
107
- }
108
- to {
109
- transform: translateY(0);
110
- }
111
- }
112
-
113
- /* Table bar fill entrance: clip-path grow only, no opacity
114
- (preserves resting opacity: 0.15 from table.css) */
115
- @keyframes oc-table-enter-bar-fill {
116
- from {
117
- clip-path: inset(0 100% 0 0);
118
- }
119
- to {
120
- clip-path: inset(0 0 0 0);
121
- }
122
- }
123
-
124
- /* Tooltip entrance */
125
- @keyframes oc-tooltip-in {
126
- from {
127
- opacity: 0;
128
- transform: translateY(2px);
129
- }
130
- to {
131
- opacity: 1;
132
- transform: translateY(0);
133
- }
134
- }
135
- }
@@ -1,18 +0,0 @@
1
- @layer oc.components {
2
- /* ---------------------------------------------------------------------------
3
- * Legend
4
- * --------------------------------------------------------------------------- */
5
-
6
- .oc-legend {
7
- font-family: var(--oc-font-family);
8
- font-size: var(--oc-body-size);
9
- }
10
-
11
- .oc-legend-entry {
12
- cursor: default;
13
- }
14
-
15
- .oc-legend text {
16
- fill: var(--oc-legend-text);
17
- }
18
- }
@@ -1,67 +0,0 @@
1
- /* ---------------------------------------------------------------------------
2
- * Reduced motion
3
- *
4
- * Catch-all: last-declared layer beats every earlier layer regardless of
5
- * specificity. No !important, no hand-maintained selector mirror.
6
- *
7
- * Selector list matches CSS_TOKEN_ROOT_SELECTORS in token-definitions.ts.
8
- * --------------------------------------------------------------------------- */
9
-
10
- @layer oc.reduced-motion {
11
- @media (prefers-reduced-motion: reduce) {
12
- :is(
13
- .oc-root,
14
- .oc-chart-root,
15
- .oc-table-wrapper,
16
- .oc-table-root,
17
- .oc-graph-wrapper,
18
- .oc-graph-root,
19
- .oc-sankey-root,
20
- .oc-tilemap-root,
21
- .oc-barlist-root,
22
- .oc-map-root
23
- ),
24
- :is(
25
- .oc-root,
26
- .oc-chart-root,
27
- .oc-table-wrapper,
28
- .oc-table-root,
29
- .oc-graph-wrapper,
30
- .oc-graph-root,
31
- .oc-sankey-root,
32
- .oc-tilemap-root,
33
- .oc-barlist-root,
34
- .oc-map-root
35
- )
36
- *,
37
- :is(
38
- .oc-root,
39
- .oc-chart-root,
40
- .oc-table-wrapper,
41
- .oc-table-root,
42
- .oc-graph-wrapper,
43
- .oc-graph-root,
44
- .oc-sankey-root,
45
- .oc-tilemap-root,
46
- .oc-barlist-root,
47
- .oc-map-root
48
- )
49
- *::before,
50
- :is(
51
- .oc-root,
52
- .oc-chart-root,
53
- .oc-table-wrapper,
54
- .oc-table-root,
55
- .oc-graph-wrapper,
56
- .oc-graph-root,
57
- .oc-sankey-root,
58
- .oc-tilemap-root,
59
- .oc-barlist-root,
60
- .oc-map-root
61
- )
62
- *::after {
63
- animation: none;
64
- transition: none;
65
- }
66
- }
67
- }
@@ -1,153 +0,0 @@
1
- @layer oc.components {
2
- /* ---------------------------------------------------------------------------
3
- * Series search (seriesSearch)
4
- *
5
- * DOM combobox overlaid on the SVG band the engine reserves below chrome.
6
- * The wrapper is absolutely positioned by the vanilla adapter (inline
7
- * left/top/width/height), so everything here is visual only. All colors come
8
- * from --oc-* tokens, which flip in .oc-dark.
9
- * --------------------------------------------------------------------------- */
10
-
11
- .oc-series-search {
12
- position: absolute;
13
- display: flex;
14
- align-items: center;
15
- justify-content: flex-end;
16
- gap: 8px;
17
- font-family: var(--oc-font-family);
18
- z-index: 10;
19
- }
20
-
21
- /* Chips: removable filter tokens for the current selection. They flow to the
22
- * left of the input and scroll horizontally rather than wrapping over the
23
- * chart when a reader picks many series. */
24
- .oc-series-search-chips {
25
- display: flex;
26
- align-items: center;
27
- gap: 6px;
28
- min-width: 0;
29
- overflow-x: auto;
30
- scrollbar-width: none;
31
- }
32
-
33
- .oc-series-search-chips::-webkit-scrollbar {
34
- display: none;
35
- }
36
-
37
- .oc-series-search-chip {
38
- display: inline-flex;
39
- align-items: center;
40
- gap: 4px;
41
- padding: 3px 4px 3px 10px;
42
- border: 1px solid var(--oc-border);
43
- border-radius: 999px;
44
- background: var(--oc-secondary);
45
- color: var(--oc-text-secondary);
46
- font-size: 12px;
47
- font-weight: 500;
48
- line-height: 16px;
49
- white-space: nowrap;
50
- }
51
-
52
- .oc-series-search-chip-remove {
53
- display: inline-flex;
54
- align-items: center;
55
- justify-content: center;
56
- /* 16px glyph, but a >=24px hit area (WCAG 2.5.5 target size) via padding
57
- pulled back with negative margin so the chip layout stays tight. */
58
- width: 16px;
59
- height: 16px;
60
- padding: 4px;
61
- margin: -4px -2px -4px -4px;
62
- border: none;
63
- border-radius: 50%;
64
- background: transparent;
65
- color: var(--oc-text-muted);
66
- cursor: pointer;
67
- transition:
68
- color 0.15s,
69
- background-color 0.15s;
70
- }
71
-
72
- .oc-series-search-chip-remove:hover {
73
- color: var(--oc-text);
74
- background: var(--oc-hover-bg);
75
- }
76
-
77
- .oc-series-search-chip-remove:focus-visible {
78
- outline: 2px solid var(--oc-focus);
79
- outline-offset: 1px;
80
- }
81
-
82
- .oc-series-search-chip-remove svg {
83
- display: block;
84
- }
85
-
86
- /* Combobox: input + popup listbox. Styling matches the table search input
87
- * (border, radius, focus ring) so the two search surfaces read as one system. */
88
- .oc-series-search-box {
89
- position: relative;
90
- flex: 0 1 220px;
91
- min-width: 120px;
92
- }
93
-
94
- .oc-series-search-icon {
95
- position: absolute;
96
- left: 9px;
97
- top: 50%;
98
- transform: translateY(-50%);
99
- color: var(--oc-text-muted);
100
- pointer-events: none;
101
- }
102
-
103
- /* Shared skin provided by the grouped rule in table.css.
104
- Only divergent props live here. */
105
- .oc-series-search-input {
106
- height: 32px;
107
- padding: 0 10px 0 28px;
108
- }
109
-
110
- .oc-series-search-listbox {
111
- position: absolute;
112
- top: calc(100% + 4px);
113
- right: 0;
114
- min-width: 100%;
115
- max-height: 240px;
116
- overflow-y: auto;
117
- margin: 0;
118
- padding: 4px;
119
- list-style: none;
120
- border: 1px solid var(--oc-border);
121
- border-radius: 8px;
122
- background: var(--oc-card);
123
- box-shadow: var(--oc-tooltip-shadow);
124
- z-index: 20;
125
- }
126
-
127
- .oc-series-search-option {
128
- padding: 6px 10px;
129
- border-radius: 4px;
130
- font-size: 13px;
131
- color: var(--oc-text);
132
- cursor: pointer;
133
- white-space: nowrap;
134
- overflow: hidden;
135
- text-overflow: ellipsis;
136
- }
137
-
138
- .oc-series-search-option[aria-selected="true"],
139
- .oc-series-search-option:hover {
140
- background: var(--oc-hover-bg);
141
- }
142
-
143
- /* The typed substring within each suggestion. */
144
- .oc-series-search-match {
145
- font-weight: 600;
146
- }
147
-
148
- .oc-series-search-empty {
149
- padding: 6px 10px;
150
- font-size: 12px;
151
- color: var(--oc-text-muted);
152
- }
153
- }
@@ -1,16 +0,0 @@
1
- @layer oc.components {
2
- /**
3
- * Sparkline display mode.
4
- *
5
- * Stamped on the SVG root as data-display="sparkline" by the renderer when
6
- * the spec sets display: 'sparkline'. Strips any inherited padding/margin
7
- * so the mark renders truly edge-to-edge in tight container layouts (KPI
8
- * cards, table cells, dashboard tiles).
9
- */
10
-
11
- .oc-chart[data-display="sparkline"] {
12
- display: block;
13
- margin: 0;
14
- padding: 0;
15
- }
16
- }
@@ -1,93 +0,0 @@
1
- @layer oc.animation {
2
- /* ---------------------------------------------------------------------------
3
- * Table entrance animations (.oc-table-wrapper.oc-animate)
4
- * --------------------------------------------------------------------------- */
5
-
6
- .oc-table-wrapper.oc-animate {
7
- /* Chrome (title/subtitle): fade + slide up */
8
- & > .oc-chrome {
9
- animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)
10
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
11
- }
12
-
13
- /* Table header: quick fade before rows start */
14
- & thead {
15
- animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)
16
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
17
- }
18
-
19
- /* Row entrance: slide up only, no opacity (cells handle their own fading
20
- to avoid opacity compounding between row and cell animations) */
21
- & tbody tr {
22
- animation: oc-table-enter-row var(--oc-animation-duration)
23
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
24
- animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));
25
- }
26
-
27
- /* Cell text: fade in synced with row slide */
28
- & tbody td {
29
- animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)
30
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
31
- animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));
32
- }
33
-
34
- /* Heatmap/category cell backgrounds: longer fade, delayed after row appears */
35
- & td.oc-table-heatmap,
36
- & td.oc-table-category {
37
- animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.7)
38
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
39
- animation-delay: calc(
40
- var(--oc-animation-stagger) *
41
- var(--oc-row-index, 0) +
42
- var(--oc-animation-duration) *
43
- 0.3
44
- );
45
- }
46
-
47
- /* Bar fill: clip-path grow only (no opacity change to preserve resting
48
- opacity: 0.15 from table.css) */
49
- & .oc-table-bar-fill {
50
- animation: oc-table-enter-bar-fill calc(var(--oc-animation-duration) * 0.8)
51
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
52
- animation-delay: calc(
53
- var(--oc-animation-stagger) *
54
- var(--oc-row-index, 0) +
55
- var(--oc-animation-duration) *
56
- 0.3
57
- );
58
- }
59
-
60
- /* Sparkline SVG: clip-path reveal left-to-right. Targets the SVG directly
61
- (not the wrapper) to avoid clipping absolutely-positioned dots and labels. */
62
- & .oc-table-sparkline > svg {
63
- animation: oc-enter-line calc(var(--oc-animation-duration) * 0.8)
64
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
65
- animation-delay: calc(
66
- var(--oc-animation-stagger) *
67
- var(--oc-row-index, 0) +
68
- var(--oc-animation-duration) *
69
- 0.4
70
- );
71
- }
72
-
73
- /* Sparkline dots and labels: fade in after the line draws through */
74
- & .oc-table-sparkline-dot,
75
- & .oc-table-sparkline-labels {
76
- animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.3)
77
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
78
- animation-delay: calc(
79
- var(--oc-animation-stagger) *
80
- var(--oc-row-index, 0) +
81
- var(--oc-animation-duration) *
82
- 0.8
83
- );
84
- }
85
-
86
- /* Search and pagination: quick fade on mount */
87
- & .oc-table-search,
88
- & .oc-table-pagination {
89
- animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)
90
- var(--oc-animation-ease, var(--oc-ease-smooth)) both;
91
- }
92
- }
93
- }