@heyramzi/ui 6.1.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +6 -25
- package/README.md +6 -4
- package/package.json +7 -15
- package/scripts/sync-shadcn.mjs +12 -3
- package/src/ai/index.ts +0 -18
- package/src/animations/README.md +3 -3
- package/src/lib/sliding-pill.ts +68 -0
- package/src/lib/theme-transition.ts +4 -2
- package/src/shadcn/code-block/code-block-actions.svelte +23 -0
- package/src/shadcn/code-block/code-block-content.svelte +55 -0
- package/src/shadcn/code-block/code-block-copy-button.svelte +59 -0
- package/src/shadcn/code-block/code-block-footer.svelte +20 -0
- package/src/shadcn/code-block/code-block-header.svelte +23 -0
- package/src/shadcn/code-block/code-block-line.svelte +71 -0
- package/src/shadcn/code-block/code-block-title.svelte +23 -0
- package/src/shadcn/code-block/code-block.svelte +47 -0
- package/src/shadcn/code-block/index.ts +42 -0
- package/src/shadcn/hooks/highlighter.ts +132 -0
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +98 -0
- package/src/shadcn/kbd/index.ts +10 -0
- package/src/shadcn/kbd/kbd-group.svelte +20 -0
- package/src/shadcn/kbd/kbd.svelte +23 -0
- package/src/shadcn/message-scroller/index.ts +28 -0
- package/src/shadcn/message-scroller/message-scroller-button.svelte +52 -0
- package/src/shadcn/message-scroller/message-scroller-content.svelte +17 -0
- package/src/shadcn/message-scroller/message-scroller-item.svelte +22 -0
- package/src/shadcn/message-scroller/message-scroller-provider.svelte +7 -0
- package/src/shadcn/message-scroller/message-scroller-viewport.svelte +20 -0
- package/src/shadcn/message-scroller/message-scroller.svelte +20 -0
- package/src/shadcn/tabs/tabs-list.svelte +13 -2
- package/src/shadcn/tabs/tabs-trigger.svelte +1 -1
- package/src/shadcn/trace/index.ts +29 -0
- package/src/shadcn/trace/trace-collapsible-content.svelte +29 -0
- package/src/shadcn/trace/trace-collapsible-trigger.svelte +29 -0
- package/src/shadcn/trace/trace-collapsible.svelte +20 -0
- package/src/shadcn/trace/trace-description.svelte +20 -0
- package/src/shadcn/trace/trace-icon.svelte +24 -0
- package/src/shadcn/trace/trace-line.svelte +31 -0
- package/src/shadcn/trace/trace-title.svelte +20 -0
- package/src/shadcn/trace/trace.svelte +23 -0
- package/src/showcase/AiSection.svelte +0 -7
- package/src/showcase/demos/shadcn/code-block.svelte +80 -0
- package/src/showcase/demos/shadcn/index.ts +24 -0
- package/src/showcase/demos/shadcn/message-scroller.svelte +44 -0
- package/src/showcase/demos/shadcn/trace.svelte +51 -0
- package/src/showcase/kit.ts +1 -2
- package/src/ai/conversation/Conversation.svelte +0 -28
- package/src/ai/conversation/ConversationContent.svelte +0 -35
- package/src/ai/conversation/ConversationEmptyState.svelte +0 -46
- package/src/ai/conversation/ConversationScrollButton.svelte +0 -51
- package/src/ai/conversation/index.ts +0 -33
- package/src/ai/conversation/stick-to-bottom-context.svelte.ts +0 -131
- package/src/charts/animated-value.css +0 -7
- package/src/charts/animated-value.svelte +0 -110
- package/src/charts/area-chart.css +0 -29
- package/src/charts/area-chart.svelte +0 -195
- package/src/charts/bar-chart.css +0 -119
- package/src/charts/bar-chart.svelte +0 -269
- package/src/charts/charts.css +0 -201
- package/src/charts/crosshair.svelte +0 -35
- package/src/charts/donut-chart.css +0 -56
- package/src/charts/donut-chart.svelte +0 -158
- package/src/charts/edge-fade.svelte +0 -43
- package/src/charts/edge-fade.ts +0 -16
- package/src/charts/figure.css +0 -100
- package/src/charts/figure.svelte +0 -122
- package/src/charts/gauge-chart.css +0 -94
- package/src/charts/gauge-chart.svelte +0 -303
- package/src/charts/hover-band.test.ts +0 -30
- package/src/charts/hover-band.ts +0 -21
- package/src/charts/hover-focus.svelte +0 -85
- package/src/charts/index.ts +0 -30
- package/src/charts/legend.css +0 -131
- package/src/charts/legend.svelte +0 -112
- package/src/charts/line-chart.css +0 -26
- package/src/charts/line-chart.svelte +0 -256
- package/src/charts/motion.ts +0 -19
- package/src/charts/number-chart.css +0 -168
- package/src/charts/number-chart.svelte +0 -177
- package/src/charts/primitives/chart-container.svelte +0 -57
- package/src/charts/primitives/chart-style.svelte +0 -36
- package/src/charts/primitives/chart-tooltip.svelte +0 -161
- package/src/charts/primitives/chart-utils.ts +0 -54
- package/src/charts/primitives/index.ts +0 -11
- package/src/charts/reveal.svelte +0 -61
- package/src/charts/ring-chart.css +0 -96
- package/src/charts/ring-chart.svelte +0 -158
- package/src/charts/sparkline.css +0 -45
- package/src/charts/sparkline.svelte +0 -140
- package/src/charts/stat-card.css +0 -103
- package/src/charts/stat-card.svelte +0 -267
- package/src/charts/time-series-chart.css +0 -28
- package/src/charts/time-series-chart.svelte +0 -179
- package/src/charts/trend-pill.css +0 -38
- package/src/charts/trend-pill.svelte +0 -48
- package/src/lib/hooks/is-mobile.svelte.ts +0 -11
- package/src/showcase/ChartsSection.svelte +0 -458
- package/src/showcase/demos/ai/conversation.svelte +0 -59
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import "./ring-chart.css";
|
|
6
|
-
import { cn } from "@heyramzi/utils";
|
|
7
|
-
import AnimatedValue from "./animated-value.svelte";
|
|
8
|
-
|
|
9
|
-
// =========================
|
|
10
|
-
// TYPES
|
|
11
|
-
// =========================
|
|
12
|
-
type RingData = {
|
|
13
|
-
label: string;
|
|
14
|
-
value: number;
|
|
15
|
-
/** Denominator for the progress arc. */
|
|
16
|
-
maxValue: number;
|
|
17
|
-
/** CSS color or var. Falls back to --chart-1..5. */
|
|
18
|
-
color?: string;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
type Props = {
|
|
22
|
-
data: RingData[];
|
|
23
|
-
/** Fixed square size in px. Omit to fill the parent (responsive). */
|
|
24
|
-
size?: number;
|
|
25
|
-
/** Ring thickness in viewBox units. */
|
|
26
|
-
strokeWidth?: number;
|
|
27
|
-
/** Gap between concentric rings in viewBox units. */
|
|
28
|
-
ringGap?: number;
|
|
29
|
-
/** Inner radius of the innermost ring in viewBox units. */
|
|
30
|
-
baseInnerRadius?: number;
|
|
31
|
-
lineCap?: "round" | "butt";
|
|
32
|
-
/** Center label when nothing is hovered. */
|
|
33
|
-
defaultLabel?: string;
|
|
34
|
-
formatValue?: (v: number) => string;
|
|
35
|
-
/** Animate arcs on mount. */
|
|
36
|
-
animate?: boolean;
|
|
37
|
-
/** Glow the hovered ring. */
|
|
38
|
-
showGlow?: boolean;
|
|
39
|
-
/** Hovered ring index, bindable for legend hover-sync. */
|
|
40
|
-
hoveredIndex?: number | null;
|
|
41
|
-
onHoverChange?: (index: number | null) => void;
|
|
42
|
-
minWidth?: number;
|
|
43
|
-
ariaLabel?: string;
|
|
44
|
-
class?: string;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// =========================
|
|
48
|
-
// PROPS
|
|
49
|
-
// =========================
|
|
50
|
-
let {
|
|
51
|
-
data,
|
|
52
|
-
size,
|
|
53
|
-
strokeWidth = 11,
|
|
54
|
-
ringGap = 6,
|
|
55
|
-
baseInnerRadius = 48,
|
|
56
|
-
lineCap = "round",
|
|
57
|
-
defaultLabel = "Total",
|
|
58
|
-
formatValue = (v) => v.toLocaleString(),
|
|
59
|
-
animate = true,
|
|
60
|
-
showGlow = true,
|
|
61
|
-
hoveredIndex = $bindable(null),
|
|
62
|
-
onHoverChange,
|
|
63
|
-
minWidth = 170,
|
|
64
|
-
ariaLabel,
|
|
65
|
-
class: className,
|
|
66
|
-
}: Props = $props();
|
|
67
|
-
|
|
68
|
-
// =========================
|
|
69
|
-
// DERIVED
|
|
70
|
-
// =========================
|
|
71
|
-
const rings = $derived.by(() =>
|
|
72
|
-
data.map((d, i) => {
|
|
73
|
-
const radius = baseInnerRadius + i * (strokeWidth + ringGap) + strokeWidth / 2;
|
|
74
|
-
const progress = d.maxValue > 0 ? Math.max(0, Math.min(1, d.value / d.maxValue)) : 0;
|
|
75
|
-
return {
|
|
76
|
-
...d,
|
|
77
|
-
index: i,
|
|
78
|
-
radius,
|
|
79
|
-
progress,
|
|
80
|
-
color: d.color ?? `var(--chart-${(i % 5) + 1})`,
|
|
81
|
-
};
|
|
82
|
-
}),
|
|
83
|
-
);
|
|
84
|
-
const maxRadius = $derived(
|
|
85
|
-
rings.length ? rings[rings.length - 1].radius + strokeWidth / 2 : baseInnerRadius,
|
|
86
|
-
);
|
|
87
|
-
const vb = $derived(maxRadius * 2 + 4);
|
|
88
|
-
const center = $derived(vb / 2);
|
|
89
|
-
const total = $derived(data.reduce((sum, d) => sum + d.value, 0));
|
|
90
|
-
const hoveredRing = $derived(hoveredIndex != null ? (rings[hoveredIndex] ?? null) : null);
|
|
91
|
-
|
|
92
|
-
// =========================
|
|
93
|
-
// FUNCTIONS
|
|
94
|
-
// =========================
|
|
95
|
-
function setHover(index: number | null) {
|
|
96
|
-
hoveredIndex = index;
|
|
97
|
-
onHoverChange?.(index);
|
|
98
|
-
}
|
|
99
|
-
</script>
|
|
100
|
-
|
|
101
|
-
<!-- =========================== -->
|
|
102
|
-
<!-- MARKUP -->
|
|
103
|
-
<!-- =========================== -->
|
|
104
|
-
<div
|
|
105
|
-
class={cn("hr-ring", className)}
|
|
106
|
-
class:glow={showGlow}
|
|
107
|
-
style:width={size ? `${size}px` : "100%"}
|
|
108
|
-
style:min-width="{minWidth}px"
|
|
109
|
-
role="img"
|
|
110
|
-
aria-label={ariaLabel ?? `${defaultLabel}: ${formatValue(total)}`}
|
|
111
|
-
>
|
|
112
|
-
<!-- no-inline-svg-ignore -->
|
|
113
|
-
<svg viewBox="0 0 {vb} {vb}" aria-hidden="true">
|
|
114
|
-
<g transform="rotate(-90 {center} {center})">
|
|
115
|
-
{#each rings as ring (ring.index)}
|
|
116
|
-
<circle
|
|
117
|
-
class="track"
|
|
118
|
-
cx={center}
|
|
119
|
-
cy={center}
|
|
120
|
-
r={ring.radius}
|
|
121
|
-
fill="none"
|
|
122
|
-
stroke={ring.color}
|
|
123
|
-
stroke-width={strokeWidth}
|
|
124
|
-
/>
|
|
125
|
-
{/each}
|
|
126
|
-
{#each rings as ring (ring.index)}
|
|
127
|
-
{@const dimmed = hoveredIndex !== null && hoveredIndex !== ring.index}
|
|
128
|
-
<circle
|
|
129
|
-
class="fill"
|
|
130
|
-
class:animate
|
|
131
|
-
cx={center}
|
|
132
|
-
cy={center}
|
|
133
|
-
r={ring.radius}
|
|
134
|
-
pathLength="100"
|
|
135
|
-
fill="none"
|
|
136
|
-
stroke={ring.color}
|
|
137
|
-
stroke-width={strokeWidth}
|
|
138
|
-
stroke-linecap={lineCap}
|
|
139
|
-
style:stroke-dashoffset={100 - ring.progress * 100}
|
|
140
|
-
style:opacity={dimmed ? 0.25 : 1}
|
|
141
|
-
style:animation-delay="{160 + ring.index * 120}ms"
|
|
142
|
-
style:--ring-color={ring.color}
|
|
143
|
-
onmouseenter={() => setHover(ring.index)}
|
|
144
|
-
onmouseleave={() => setHover(null)}
|
|
145
|
-
></circle>
|
|
146
|
-
{/each}
|
|
147
|
-
</g>
|
|
148
|
-
</svg>
|
|
149
|
-
|
|
150
|
-
<div class="center">
|
|
151
|
-
<span class="value">
|
|
152
|
-
<AnimatedValue value={hoveredRing ? hoveredRing.value : total} format={formatValue} />
|
|
153
|
-
</span>
|
|
154
|
-
{#key hoveredRing?.label ?? defaultLabel}
|
|
155
|
-
<span class="label">{hoveredRing ? hoveredRing.label : defaultLabel}</span>
|
|
156
|
-
{/key}
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
package/src/charts/sparkline.css
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/* Styles for Sparkline. Plain stylesheet (see area-chart.css for why).
|
|
2
|
-
Selectors are namespaced under `.hr-sparkline`. */
|
|
3
|
-
|
|
4
|
-
.hr-sparkline {
|
|
5
|
-
display: flex;
|
|
6
|
-
align-items: center;
|
|
7
|
-
gap: 0.625rem;
|
|
8
|
-
width: 100%;
|
|
9
|
-
}
|
|
10
|
-
.hr-sparkline-chart {
|
|
11
|
-
flex: 1 1 auto;
|
|
12
|
-
min-width: 0;
|
|
13
|
-
}
|
|
14
|
-
/* Bare is an ornament inside another control: no inline value, so no gap. */
|
|
15
|
-
.hr-sparkline[data-bare] {
|
|
16
|
-
gap: 0;
|
|
17
|
-
}
|
|
18
|
-
.hr-sparkline-value {
|
|
19
|
-
flex-shrink: 0;
|
|
20
|
-
font-size: 0.8125rem;
|
|
21
|
-
font-weight: 600;
|
|
22
|
-
font-feature-settings: "tnum";
|
|
23
|
-
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.hr-sparkline .hr-sparkline-end {
|
|
27
|
-
filter: drop-shadow(0 0 3px currentColor);
|
|
28
|
-
opacity: 0.9;
|
|
29
|
-
transform-box: fill-box;
|
|
30
|
-
transform-origin: center;
|
|
31
|
-
/* WHY: the dot lands as the reveal reaches the end of the line. */
|
|
32
|
-
animation: hr-sparkline-pop var(--duration-fast, 250ms) var(--ease-smooth-out)
|
|
33
|
-
calc(var(--chart-motion-reveal, 1100ms) * 0.85) both;
|
|
34
|
-
}
|
|
35
|
-
@keyframes hr-sparkline-pop {
|
|
36
|
-
from {
|
|
37
|
-
opacity: 0;
|
|
38
|
-
transform: scale(0);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
@media (prefers-reduced-motion: reduce) {
|
|
42
|
-
.hr-sparkline .hr-sparkline-end {
|
|
43
|
-
animation: none;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import "./sparkline.css";
|
|
6
|
-
import { Area, Chart, Highlight, LinearGradient, Points, Spline, Svg, Tooltip } from "layerchart";
|
|
7
|
-
import { curveMonotoneX } from "d3-shape";
|
|
8
|
-
import Reveal from "./reveal.svelte";
|
|
9
|
-
|
|
10
|
-
// =========================
|
|
11
|
-
// TYPES
|
|
12
|
-
// =========================
|
|
13
|
-
type Props = {
|
|
14
|
-
data: TData[];
|
|
15
|
-
xKey: keyof TData & string;
|
|
16
|
-
yKey: keyof TData & string;
|
|
17
|
-
color?: string;
|
|
18
|
-
height?: number;
|
|
19
|
-
smooth?: boolean;
|
|
20
|
-
/** Show a dot at the latest point */
|
|
21
|
-
endCap?: boolean;
|
|
22
|
-
/** Show the latest value as inline text */
|
|
23
|
-
showLast?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Ornament mode: no tooltip, no highlight, no end cap, and the plot runs to the edges of its box.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/*
|
|
29
|
-
* For a line inside a control that already states the number and owns the pointer, such as a stat card that links.
|
|
30
|
-
*/
|
|
31
|
-
bare?: boolean;
|
|
32
|
-
formatValue?: (v: number) => string;
|
|
33
|
-
class?: string;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// =========================
|
|
37
|
-
// PROPS
|
|
38
|
-
// =========================
|
|
39
|
-
let {
|
|
40
|
-
data,
|
|
41
|
-
xKey,
|
|
42
|
-
yKey,
|
|
43
|
-
color = "var(--chart-1)",
|
|
44
|
-
height = 44,
|
|
45
|
-
smooth = true,
|
|
46
|
-
endCap = true,
|
|
47
|
-
showLast = false,
|
|
48
|
-
bare = false,
|
|
49
|
-
formatValue = (v) => v.toLocaleString(),
|
|
50
|
-
class: className,
|
|
51
|
-
}: Props = $props();
|
|
52
|
-
|
|
53
|
-
// =========================
|
|
54
|
-
// STATE
|
|
55
|
-
// =========================
|
|
56
|
-
let active = $state<TData | null>(null);
|
|
57
|
-
|
|
58
|
-
// ========================= FUNCTIONS ========================= WHY: called from the tooltip header's value expression so it re-runs on every active-point change; an unread {@const} side effect only evaluates once.
|
|
59
|
-
|
|
60
|
-
// The microtask defers the state write out of template evaluation.
|
|
61
|
-
function trackActive(d: TData): string {
|
|
62
|
-
queueMicrotask(() => {
|
|
63
|
-
active = d;
|
|
64
|
-
});
|
|
65
|
-
return String(d[xKey]);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// =========================
|
|
69
|
-
// DERIVED
|
|
70
|
-
// =========================
|
|
71
|
-
const uid = `hr-spark-${Math.random().toString(36).slice(2, 8)}`;
|
|
72
|
-
const curve = $derived(smooth ? curveMonotoneX : undefined);
|
|
73
|
-
const last = $derived(data.length > 0 ? data[data.length - 1] : null);
|
|
74
|
-
const display = $derived(active ?? last);
|
|
75
|
-
const dot = $derived(endCap && !bare);
|
|
76
|
-
// Bare runs to the edges: the fill reaches the bottom of the box and the line keeps three pixels of head so its stroke is not cut at the series
|
|
77
|
-
|
|
78
|
-
// maximum.
|
|
79
|
-
const padding = $derived(
|
|
80
|
-
bare
|
|
81
|
-
? { top: 3, bottom: 0, left: 0, right: 0 }
|
|
82
|
-
: { top: 4, bottom: 4, left: 0, right: dot ? 6 : 0 },
|
|
83
|
-
);
|
|
84
|
-
</script>
|
|
85
|
-
|
|
86
|
-
<!-- =========================== -->
|
|
87
|
-
<!-- SPARKLINE -->
|
|
88
|
-
<!-- =========================== -->
|
|
89
|
-
<div
|
|
90
|
-
class="hr-sparkline {className ?? ''}"
|
|
91
|
-
role={bare ? undefined : "img"}
|
|
92
|
-
aria-label={bare ? undefined : "Sparkline"}
|
|
93
|
-
aria-hidden={bare ? "true" : undefined}
|
|
94
|
-
data-bare={bare ? "" : undefined}
|
|
95
|
-
onpointerleave={() => (active = null)}
|
|
96
|
-
>
|
|
97
|
-
{#if data.length > 0}
|
|
98
|
-
<div class="hr-sparkline-chart" style:height="{height}px">
|
|
99
|
-
<Chart {data} x={xKey} y={yKey} {padding} tooltipContext={{ mode: "bisect-x" }}>
|
|
100
|
-
<Svg>
|
|
101
|
-
<LinearGradient id={uid} vertical>
|
|
102
|
-
{#snippet stopsContent()}
|
|
103
|
-
<stop offset="0%" stop-color={color} stop-opacity="0.38" />
|
|
104
|
-
<stop offset="100%" stop-color={color} stop-opacity="0" />
|
|
105
|
-
{/snippet}
|
|
106
|
-
</LinearGradient>
|
|
107
|
-
<Reveal bleed={3}>
|
|
108
|
-
<!-- WHY no `y0`: it defaults to the bottom of the plot, which is what
|
|
109
|
-
a fill under a sparkline wants whatever its domain is. -->
|
|
110
|
-
<Area y1={yKey} {curve} fill="url(#{uid})" />
|
|
111
|
-
<Spline {curve} style="stroke: {color}; fill: none" stroke-width="1.5" />
|
|
112
|
-
</Reveal>
|
|
113
|
-
{#if dot && last}
|
|
114
|
-
<!-- WHY: Points resolves its own data and hands the inner circle pixel coords; Circle's data mode clobbers the sibling Spline's data in -->
|
|
115
|
-
<!-- this layerchart prerelease (and a bare object left the dot at the chart origin). -->
|
|
116
|
-
<Points data={[last]} r={3} fill={color} class="hr-sparkline-end" />
|
|
117
|
-
{/if}
|
|
118
|
-
{#if !bare}
|
|
119
|
-
<Highlight points lines={false} />
|
|
120
|
-
{/if}
|
|
121
|
-
</Svg>
|
|
122
|
-
{#if !bare}
|
|
123
|
-
<Tooltip.Root>
|
|
124
|
-
{#snippet children({ data: d })}
|
|
125
|
-
<Tooltip.Header value={trackActive(d as TData)} />
|
|
126
|
-
<Tooltip.List>
|
|
127
|
-
<Tooltip.Item label={String(yKey)} value={formatValue(Number(d[yKey]))} />
|
|
128
|
-
</Tooltip.List>
|
|
129
|
-
{/snippet}
|
|
130
|
-
</Tooltip.Root>
|
|
131
|
-
{/if}
|
|
132
|
-
</Chart>
|
|
133
|
-
</div>
|
|
134
|
-
{#if showLast && display}
|
|
135
|
-
<span class="hr-sparkline-value" style:color>
|
|
136
|
-
{formatValue(Number(display[yKey]))}
|
|
137
|
-
</span>
|
|
138
|
-
{/if}
|
|
139
|
-
{/if}
|
|
140
|
-
</div>
|
package/src/charts/stat-card.css
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/* Styles for StatCard. Plain stylesheet (see area-chart.css for why). All
|
|
2
|
-
selectors are already namespaced under `.hr-stat-card`. */
|
|
3
|
-
|
|
4
|
-
.hr-stat-card {
|
|
5
|
-
display: flex;
|
|
6
|
-
flex-direction: column;
|
|
7
|
-
gap: 0.375rem;
|
|
8
|
-
padding: 1.25rem 1.5rem;
|
|
9
|
-
border: 1px solid var(--border, oklch(0.92 0.004 286));
|
|
10
|
-
border-radius: 1rem;
|
|
11
|
-
background: var(--card, white);
|
|
12
|
-
box-shadow: var(--chart-card-shadow);
|
|
13
|
-
min-width: 0;
|
|
14
|
-
/* WHY: clips the edge-to-edge chart to the card's rounded corners. */
|
|
15
|
-
overflow: hidden;
|
|
16
|
-
transition: border-color var(--chart-motion, 250ms) var(--chart-ease-out, ease);
|
|
17
|
-
}
|
|
18
|
-
.hr-stat-card:hover {
|
|
19
|
-
border-color: color-mix(in srgb, var(--ring, var(--chart-1)) 28%, var(--border, transparent));
|
|
20
|
-
}
|
|
21
|
-
/* WHY: a bare figure, not a card. Dropping the chrome avoids a card-in-card
|
|
22
|
-
when the figure is placed inside another surface, and lets the chart be the
|
|
23
|
-
whole element. */
|
|
24
|
-
.hr-stat-figure-only {
|
|
25
|
-
padding: 0;
|
|
26
|
-
gap: 0;
|
|
27
|
-
border: 0;
|
|
28
|
-
border-radius: 0;
|
|
29
|
-
background: none;
|
|
30
|
-
box-shadow: none;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/* WHY: the gauge variant sits the figure and a radial gauge side by side
|
|
34
|
-
instead of bleeding a chart to the bottom edge; no negative margins here. */
|
|
35
|
-
.hr-stat-gauge-row {
|
|
36
|
-
display: flex;
|
|
37
|
-
flex-wrap: wrap;
|
|
38
|
-
align-items: center;
|
|
39
|
-
gap: 1rem;
|
|
40
|
-
}
|
|
41
|
-
/* WHY the floor: below the width a gauge and a figure share, the row wraps the
|
|
42
|
-
gauge to its own line rather than squeezing the figure to nothing. */
|
|
43
|
-
.hr-stat-gauge-row .hr-stat-gauge-figure {
|
|
44
|
-
flex: 1 1 auto;
|
|
45
|
-
min-width: 6rem;
|
|
46
|
-
}
|
|
47
|
-
.hr-stat-gauge-row .hr-gauge {
|
|
48
|
-
flex: 0 0 auto;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/* WHY: the chart bleeds past the card padding to the left/right/bottom edges,
|
|
52
|
-
matching bklit's edge-to-edge stat-card chart; overflow:hidden on the card
|
|
53
|
-
clips the corners to the radius. */
|
|
54
|
-
.hr-stat-chart {
|
|
55
|
-
margin: 0.5rem -1.5rem -1.25rem;
|
|
56
|
-
width: auto;
|
|
57
|
-
}
|
|
58
|
-
.hr-stat-figure-only .hr-stat-chart {
|
|
59
|
-
margin: 0;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.hr-stat-card .hr-stat-spline {
|
|
63
|
-
transition: opacity var(--chart-motion-fast, 150ms) ease;
|
|
64
|
-
}
|
|
65
|
-
.hr-stat-card .hr-stat-bars {
|
|
66
|
-
transform-box: fill-box;
|
|
67
|
-
transform-origin: bottom;
|
|
68
|
-
animation: hr-stat-grow var(--chart-motion-reveal, 1100ms)
|
|
69
|
-
var(--chart-ease-reveal, cubic-bezier(0.85, 0, 0.15, 1)) both;
|
|
70
|
-
}
|
|
71
|
-
.hr-stat-card .hr-stat-bars:nth-of-type(2) {
|
|
72
|
-
animation-delay: var(--chart-stagger, 30ms);
|
|
73
|
-
}
|
|
74
|
-
.hr-stat-card .hr-stat-bars:nth-of-type(3) {
|
|
75
|
-
animation-delay: calc(var(--chart-stagger, 30ms) * 2);
|
|
76
|
-
}
|
|
77
|
-
.hr-stat-card .hr-stat-bars:nth-of-type(4) {
|
|
78
|
-
animation-delay: calc(var(--chart-stagger, 30ms) * 3);
|
|
79
|
-
}
|
|
80
|
-
.hr-stat-card .hr-stat-bars:nth-of-type(5) {
|
|
81
|
-
animation-delay: calc(var(--chart-stagger, 30ms) * 4);
|
|
82
|
-
}
|
|
83
|
-
.hr-stat-card .hr-stat-bars:nth-of-type(6) {
|
|
84
|
-
animation-delay: calc(var(--chart-stagger, 30ms) * 5);
|
|
85
|
-
}
|
|
86
|
-
.hr-stat-card .hr-stat-bars:nth-of-type(n + 7) {
|
|
87
|
-
animation-delay: calc(var(--chart-stagger, 30ms) * 6);
|
|
88
|
-
}
|
|
89
|
-
@keyframes hr-stat-grow {
|
|
90
|
-
from {
|
|
91
|
-
transform: scaleY(0);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
.hr-stat-card .hr-stat-bar-active {
|
|
95
|
-
filter: brightness(1.08);
|
|
96
|
-
pointer-events: none;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
@media (prefers-reduced-motion: reduce) {
|
|
100
|
-
.hr-stat-card .hr-stat-bars {
|
|
101
|
-
animation: none;
|
|
102
|
-
}
|
|
103
|
-
}
|