@opendata-ai/openchart-core 6.4.1 → 6.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opendata-ai/openchart-core",
3
- "version": "6.4.1",
3
+ "version": "6.5.1",
4
4
  "description": "Types, theme, colors, accessibility, and utilities for openchart",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Riley Hilliard",
@@ -56,6 +56,7 @@
56
56
  "devDependencies": {
57
57
  "@types/d3-color": "^3.1.3",
58
58
  "@types/d3-format": "^3.0.4",
59
- "@types/d3-time-format": "^4.0.3"
59
+ "@types/d3-time-format": "^4.0.3",
60
+ "lightningcss-cli": "^1.32.0"
60
61
  }
61
62
  }
@@ -0,0 +1,117 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Animation scoped rules (.oc-animate enables animation on the chart root)
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-animate {
6
+ /* Vertical bars (default): smooth ease-out, no overshoot.
7
+ oc-mark-bar is reserved for future mark type aliases. */
8
+ & .oc-mark-rect rect,
9
+ & .oc-mark-bar rect {
10
+ animation: oc-enter-bar var(--oc-animation-duration) var(--oc-ease-smooth) both;
11
+ animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));
12
+ }
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
+ }
@@ -0,0 +1,53 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Wrapper roots
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-chart-root {
6
+ width: 100%;
7
+ }
8
+
9
+ .oc-table-root,
10
+ .oc-graph-root {
11
+ width: 100%;
12
+ height: 100%;
13
+ }
14
+
15
+ .oc-table-root {
16
+ overflow: auto;
17
+ }
18
+
19
+ /* ---------------------------------------------------------------------------
20
+ * Chart container
21
+ * --------------------------------------------------------------------------- */
22
+
23
+ .oc-chart {
24
+ font-family: var(--oc-font-family);
25
+ display: block;
26
+ width: 100%;
27
+ }
28
+
29
+ /* ---------------------------------------------------------------------------
30
+ * Screen reader only utility
31
+ * --------------------------------------------------------------------------- */
32
+
33
+ .oc-sr-only {
34
+ position: absolute;
35
+ width: 1px;
36
+ height: 1px;
37
+ padding: 0;
38
+ margin: -1px;
39
+ overflow: hidden;
40
+ clip-path: inset(50%);
41
+ white-space: nowrap;
42
+ border-width: 0;
43
+ }
44
+
45
+ /* ---------------------------------------------------------------------------
46
+ * Editable hover feedback
47
+ * --------------------------------------------------------------------------- */
48
+
49
+ .oc-editable-hover {
50
+ outline: 1.5px solid rgba(79, 70, 229, 0.35);
51
+ outline-offset: 2px;
52
+ border-radius: 2px;
53
+ }
@@ -0,0 +1,36 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Chrome (title, subtitle, source, footer)
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-chrome {
6
+ font-family: var(--oc-font-family);
7
+ }
8
+
9
+ .oc-title {
10
+ font-size: var(--oc-title-size);
11
+ font-weight: var(--oc-title-weight);
12
+ letter-spacing: var(--oc-title-tracking);
13
+ fill: var(--oc-text);
14
+ }
15
+
16
+ .oc-subtitle {
17
+ font-size: var(--oc-subtitle-size);
18
+ font-weight: var(--oc-subtitle-weight);
19
+ fill: var(--oc-text-secondary);
20
+ }
21
+
22
+ .oc-source,
23
+ .oc-byline,
24
+ .oc-footer {
25
+ font-size: var(--oc-source-size);
26
+ font-weight: var(--oc-source-weight);
27
+ fill: var(--oc-text-muted);
28
+ }
29
+
30
+ /* ---------------------------------------------------------------------------
31
+ * Table footer chrome
32
+ * --------------------------------------------------------------------------- */
33
+
34
+ .oc-chrome-footer {
35
+ padding-top: 16px;
36
+ }
@@ -0,0 +1,20 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Dark mode overrides
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-dark {
6
+ --oc-bg: #1a1a2e;
7
+ --oc-text: #e0e0e0;
8
+ --oc-text-secondary: #b0b0b0;
9
+ --oc-text-muted: #808080;
10
+ --oc-gridline: #333355;
11
+ --oc-axis: #999999;
12
+ --oc-border: #444466;
13
+ --oc-focus: #60a5fa;
14
+ --oc-hover-bg: rgba(255, 255, 255, 0.05);
15
+ --oc-tooltip-bg: rgba(30, 30, 50, 0.85);
16
+ --oc-tooltip-border: rgba(255, 255, 255, 0.08);
17
+ --oc-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 0 1px rgba(0, 0, 0, 0.4);
18
+ --oc-tooltip-text: #e0e0e0;
19
+ --oc-legend-text: #b0b0b0;
20
+ }
@@ -0,0 +1,106 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Graph
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-graph-wrapper {
6
+ position: relative;
7
+ overflow: hidden;
8
+ background: var(--oc-bg);
9
+ font-family: var(--oc-font-family);
10
+ width: 100%;
11
+ height: 100%;
12
+ }
13
+
14
+ .oc-graph-canvas {
15
+ display: block;
16
+ cursor: grab;
17
+ }
18
+
19
+ .oc-graph-canvas--dragging {
20
+ cursor: grabbing;
21
+ }
22
+
23
+ .oc-graph-chrome {
24
+ padding: 16px 16px 8px;
25
+
26
+ & .oc-title {
27
+ font-size: var(--oc-title-size);
28
+ font-weight: var(--oc-title-weight);
29
+ letter-spacing: var(--oc-title-tracking);
30
+ color: var(--oc-text);
31
+ margin: 0 0 4px;
32
+ }
33
+
34
+ & .oc-subtitle {
35
+ font-size: var(--oc-subtitle-size);
36
+ color: var(--oc-text-secondary);
37
+ margin: 0;
38
+ }
39
+ }
40
+
41
+ .oc-graph-legend {
42
+ position: absolute;
43
+ top: 8px;
44
+ right: 8px;
45
+ background: var(--oc-bg);
46
+ border: 1px solid var(--oc-border);
47
+ border-radius: var(--oc-border-radius);
48
+ padding: 8px 12px;
49
+ font-size: 12px;
50
+ color: var(--oc-text-secondary);
51
+ max-height: 200px;
52
+ overflow-y: auto;
53
+ }
54
+
55
+ .oc-graph-legend-item {
56
+ display: flex;
57
+ align-items: center;
58
+ gap: 6px;
59
+ padding: 2px 0;
60
+ }
61
+
62
+ .oc-graph-legend-swatch {
63
+ width: 10px;
64
+ height: 10px;
65
+ border-radius: 50%;
66
+ flex-shrink: 0;
67
+ }
68
+
69
+ .oc-graph-search {
70
+ position: absolute;
71
+ top: 8px;
72
+ left: 8px;
73
+
74
+ & input {
75
+ font-family: var(--oc-font-family);
76
+ font-size: var(--oc-body-size);
77
+ padding: 6px 10px;
78
+ border: 1px solid var(--oc-border);
79
+ border-radius: var(--oc-border-radius);
80
+ background: var(--oc-bg);
81
+ color: var(--oc-text);
82
+ outline: none;
83
+
84
+ &:focus {
85
+ border-color: var(--oc-focus);
86
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
87
+ }
88
+ }
89
+ }
90
+
91
+ /* Dark mode graph overrides (darker bg for canvas-based rendering) */
92
+ .oc-dark .oc-graph-wrapper,
93
+ .oc-graph-wrapper.oc-dark {
94
+ --oc-bg: #0d1117;
95
+ }
96
+
97
+ .oc-dark .oc-graph-legend,
98
+ .oc-dark.oc-graph-wrapper .oc-graph-legend {
99
+ background: rgba(13, 17, 23, 0.85);
100
+ border-color: rgba(255, 255, 255, 0.1);
101
+ }
102
+
103
+ .oc-dark .oc-graph-search input {
104
+ background: rgba(13, 17, 23, 0.85);
105
+ border-color: rgba(255, 255, 255, 0.1);
106
+ }
@@ -0,0 +1,22 @@
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
+ */
8
+
9
+ /* For optimal typography, load Inter: https://fonts.google.com/specimen/Inter */
10
+
11
+ @import "./tokens.css";
12
+ @import "./dark.css";
13
+ @import "./base.css";
14
+ @import "./chrome.css";
15
+ @import "./tooltip.css";
16
+ @import "./legend.css";
17
+ @import "./table.css";
18
+ @import "./table-animation.css";
19
+ @import "./graph.css";
20
+ @import "./keyframes.css";
21
+ @import "./animation.css";
22
+ @import "./reduced-motion.css";
@@ -0,0 +1,120 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Animation keyframes
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ /* Bar entrance: clip-path reveal bottom-to-top + fade in (vertical columns).
6
+ Bars grow upward from baseline with a soft opacity fade. */
7
+ @keyframes oc-enter-bar {
8
+ from {
9
+ clip-path: inset(100% 0 0 0);
10
+ opacity: 0;
11
+ }
12
+ 75% {
13
+ opacity: 1;
14
+ }
15
+ to {
16
+ clip-path: inset(0 0 0 0);
17
+ opacity: 1;
18
+ }
19
+ }
20
+
21
+ /* Bar entrance: clip-path reveal left-to-right + fade in (horizontal bars).
22
+ Bars grow rightward from axis with a soft opacity fade. */
23
+ @keyframes oc-enter-bar-h {
24
+ from {
25
+ clip-path: inset(0 100% 0 0);
26
+ opacity: 0;
27
+ }
28
+ 75% {
29
+ opacity: 1;
30
+ }
31
+ to {
32
+ clip-path: inset(0 0 0 0);
33
+ opacity: 1;
34
+ }
35
+ }
36
+
37
+ /* Line/area entrance: clip-path reveal left-to-right + fade in.
38
+ Lines draw in following reading direction with a soft lead-in. */
39
+ @keyframes oc-enter-line {
40
+ from {
41
+ clip-path: inset(0 100% 0 0);
42
+ opacity: 0;
43
+ }
44
+ 15% {
45
+ opacity: 1;
46
+ }
47
+ to {
48
+ clip-path: inset(0 0 0 0);
49
+ opacity: 1;
50
+ }
51
+ }
52
+
53
+ /* Point/arc entrance: scale up + fade in from center */
54
+ @keyframes oc-enter-point {
55
+ from {
56
+ opacity: 0;
57
+ transform: scale(0.3);
58
+ }
59
+ to {
60
+ opacity: 1;
61
+ transform: scale(1);
62
+ }
63
+ }
64
+
65
+ /* Pure opacity fade (no transform). Safe for elements with existing transforms
66
+ like arc groups that use translate() for positioning. */
67
+ @keyframes oc-enter-fade-only {
68
+ from {
69
+ opacity: 0;
70
+ }
71
+ to {
72
+ opacity: 1;
73
+ }
74
+ }
75
+
76
+ /* Fade + subtle slide up for text, rule, tick, annotations */
77
+ @keyframes oc-enter-fade {
78
+ from {
79
+ opacity: 0;
80
+ transform: translateY(4px);
81
+ }
82
+ to {
83
+ opacity: 1;
84
+ transform: translateY(0);
85
+ }
86
+ }
87
+
88
+ /* Table row entrance: slide up only, no opacity (cells fade independently
89
+ to avoid opacity compounding between row and cell animations) */
90
+ @keyframes oc-table-enter-row {
91
+ from {
92
+ transform: translateY(6px);
93
+ }
94
+ to {
95
+ transform: translateY(0);
96
+ }
97
+ }
98
+
99
+ /* Table bar fill entrance: clip-path grow only, no opacity
100
+ (preserves resting opacity: 0.15 from table.css) */
101
+ @keyframes oc-table-enter-bar-fill {
102
+ from {
103
+ clip-path: inset(0 100% 0 0);
104
+ }
105
+ to {
106
+ clip-path: inset(0 0 0 0);
107
+ }
108
+ }
109
+
110
+ /* Tooltip entrance */
111
+ @keyframes oc-tooltip-in {
112
+ from {
113
+ opacity: 0;
114
+ transform: translateY(2px);
115
+ }
116
+ to {
117
+ opacity: 1;
118
+ transform: translateY(0);
119
+ }
120
+ }
@@ -0,0 +1,16 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Legend
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-legend {
6
+ font-family: var(--oc-font-family);
7
+ font-size: var(--oc-body-size);
8
+ }
9
+
10
+ .oc-legend-entry {
11
+ cursor: default;
12
+ }
13
+
14
+ .oc-legend text {
15
+ fill: var(--oc-legend-text);
16
+ }
@@ -0,0 +1,44 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Reduced motion
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ @media (prefers-reduced-motion: reduce) {
6
+ .oc-table-sort-btn::before,
7
+ .oc-table-sort-btn::after,
8
+ .oc-table-search input,
9
+ .oc-table-pagination button {
10
+ transition: none;
11
+ }
12
+
13
+ /* Disable all chart entrance animations */
14
+ .oc-animate .oc-mark-rect rect,
15
+ .oc-animate .oc-mark-bar rect,
16
+ .oc-animate .oc-mark-arc,
17
+ .oc-animate .oc-mark-line,
18
+ .oc-animate .oc-mark-area,
19
+ .oc-animate circle.oc-mark-point,
20
+ .oc-animate circle.oc-mark-circle,
21
+ .oc-animate .oc-mark-text text,
22
+ .oc-animate .oc-mark-rule line,
23
+ .oc-animate .oc-mark-tick line,
24
+ .oc-animate .oc-mark-label,
25
+ .oc-animate .oc-annotation {
26
+ animation: none;
27
+ }
28
+
29
+ /* Disable all table entrance animations */
30
+ .oc-table-wrapper.oc-animate > .oc-chrome,
31
+ .oc-table-wrapper.oc-animate thead,
32
+ .oc-table-wrapper.oc-animate tbody tr,
33
+ .oc-table-wrapper.oc-animate tbody td,
34
+ .oc-table-wrapper.oc-animate td.oc-table-heatmap,
35
+ .oc-table-wrapper.oc-animate td.oc-table-category,
36
+ .oc-table-wrapper.oc-animate .oc-table-bar-fill,
37
+ .oc-table-wrapper.oc-animate .oc-table-sparkline > svg,
38
+ .oc-table-wrapper.oc-animate .oc-table-sparkline-dot,
39
+ .oc-table-wrapper.oc-animate .oc-table-sparkline-labels,
40
+ .oc-table-wrapper.oc-animate .oc-table-search,
41
+ .oc-table-wrapper.oc-animate .oc-table-pagination {
42
+ animation: none;
43
+ }
44
+ }
@@ -0,0 +1,91 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Table entrance animations (.oc-table-wrapper.oc-animate)
3
+ * --------------------------------------------------------------------------- */
4
+
5
+ .oc-table-wrapper.oc-animate {
6
+ /* Chrome (title/subtitle): fade + slide up */
7
+ & > .oc-chrome {
8
+ animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)
9
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
10
+ }
11
+
12
+ /* Table header: quick fade before rows start */
13
+ & thead {
14
+ animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)
15
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
16
+ }
17
+
18
+ /* Row entrance: slide up only, no opacity (cells handle their own fading
19
+ to avoid opacity compounding between row and cell animations) */
20
+ & tbody tr {
21
+ animation: oc-table-enter-row var(--oc-animation-duration)
22
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
23
+ animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));
24
+ }
25
+
26
+ /* Cell text: fade in synced with row slide */
27
+ & tbody td {
28
+ animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)
29
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
30
+ animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));
31
+ }
32
+
33
+ /* Heatmap/category cell backgrounds: longer fade, delayed after row appears */
34
+ & td.oc-table-heatmap,
35
+ & td.oc-table-category {
36
+ animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.7)
37
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
38
+ animation-delay: calc(
39
+ var(--oc-animation-stagger) *
40
+ var(--oc-row-index, 0) +
41
+ var(--oc-animation-duration) *
42
+ 0.3
43
+ );
44
+ }
45
+
46
+ /* Bar fill: clip-path grow only (no opacity change to preserve resting
47
+ opacity: 0.15 from table.css) */
48
+ & .oc-table-bar-fill {
49
+ animation: oc-table-enter-bar-fill calc(var(--oc-animation-duration) * 0.8)
50
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
51
+ animation-delay: calc(
52
+ var(--oc-animation-stagger) *
53
+ var(--oc-row-index, 0) +
54
+ var(--oc-animation-duration) *
55
+ 0.3
56
+ );
57
+ }
58
+
59
+ /* Sparkline SVG: clip-path reveal left-to-right. Targets the SVG directly
60
+ (not the wrapper) to avoid clipping absolutely-positioned dots and labels. */
61
+ & .oc-table-sparkline > svg {
62
+ animation: oc-enter-line calc(var(--oc-animation-duration) * 0.8)
63
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
64
+ animation-delay: calc(
65
+ var(--oc-animation-stagger) *
66
+ var(--oc-row-index, 0) +
67
+ var(--oc-animation-duration) *
68
+ 0.4
69
+ );
70
+ }
71
+
72
+ /* Sparkline dots and labels: fade in after the line draws through */
73
+ & .oc-table-sparkline-dot,
74
+ & .oc-table-sparkline-labels {
75
+ animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.3)
76
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
77
+ animation-delay: calc(
78
+ var(--oc-animation-stagger) *
79
+ var(--oc-row-index, 0) +
80
+ var(--oc-animation-duration) *
81
+ 0.8
82
+ );
83
+ }
84
+
85
+ /* Search and pagination: quick fade on mount */
86
+ & .oc-table-search,
87
+ & .oc-table-pagination {
88
+ animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)
89
+ var(--oc-animation-ease, var(--oc-ease-smooth)) both;
90
+ }
91
+ }