@heyramzi/ui 6.1.0 → 8.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 +32 -40
- package/README.md +10 -4
- package/package.json +31 -29
- package/scripts/sync-shadcn.mjs +29 -16
- package/scripts/sync-transitions.mjs +11 -11
- package/src/ai/ai-button/AiButton.svelte +86 -0
- package/src/ai/ai-button/index.ts +4 -0
- package/src/ai/confirmation/Confirmation.svelte +8 -8
- package/src/ai/confirmation/confirmation-context.svelte.ts +2 -2
- package/src/ai/generation-progress/GenerationProgress.svelte +354 -0
- package/src/ai/generation-progress/index.ts +7 -0
- package/src/ai/index.ts +16 -24
- package/src/ai/prompt-input/PromptInput.svelte +19 -1
- package/src/ai/prompt-input/PromptInputSubmit.svelte +9 -3
- package/src/ai/reasoning/Reasoning.svelte +11 -8
- package/src/ambient.d.ts +4 -0
- package/src/animations/README.md +17 -17
- package/src/animations/index.css +3 -14
- package/src/animations/upstream-coverage.test.ts +1 -1
- package/src/components/copy/clipboard.test.ts +206 -0
- package/src/components/copy/clipboard.ts +49 -0
- package/src/components/copy/copied.svelte.ts +39 -0
- package/src/components/copy/copy-button.svelte +175 -0
- package/src/components/copy/copy-button.test.ts +110 -0
- package/src/components/copy/index.ts +3 -0
- package/src/components/data-table/data-table.test.ts +134 -0
- package/src/components/data-table/data-table.ts +77 -0
- package/src/components/data-table/index.ts +20 -0
- package/src/components/data-table/infinite-scroll.svelte +69 -0
- package/src/components/data-table/pagination.svelte +62 -0
- package/src/components/data-table/row-arrow.svelte +28 -0
- package/src/components/data-table/row-context-menu.svelte +106 -0
- package/src/components/data-table/row-context-menu.test.ts +18 -0
- package/src/components/data-table/sortable-head.svelte +56 -0
- package/src/components/data-table/table-skeleton.svelte +83 -0
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +232 -0
- package/src/components/hold-to-confirm/index.ts +1 -0
- package/src/components/icon/icon.svelte +23 -0
- package/src/components/icon/index.ts +1 -0
- package/src/components/language-flag/index.ts +1 -0
- package/src/components/language-flag/language-flag.svelte +60 -0
- package/src/components/list-page/detail-empty.svelte +50 -0
- package/src/components/list-page/detail-header.svelte +107 -0
- package/src/components/list-page/detail-panel.svelte +90 -0
- package/src/components/list-page/detail-row.svelte +36 -0
- package/src/components/list-page/detail-stack.svelte +33 -0
- package/src/components/list-page/empty-state.svelte +91 -0
- package/src/components/list-page/filter-item.svelte +49 -0
- package/src/components/list-page/filter-popover.svelte +88 -0
- package/src/components/list-page/filter-section.ts +12 -0
- package/src/components/list-page/grouped-list.svelte +116 -0
- package/src/components/list-page/index.ts +28 -0
- package/src/components/list-page/list-page-shell.svelte +195 -0
- package/src/components/list-page/list-table.ts +19 -0
- package/src/components/list-page/master-detail.svelte +206 -0
- package/src/components/list-page/master-detail.test.ts +37 -0
- package/src/components/list-page/notice-bar.svelte +68 -0
- package/src/components/list-page/prev-next.svelte +104 -0
- package/src/components/list-page/queue-rail.ts +25 -0
- package/src/components/list-page/rail-body.svelte +29 -0
- package/src/components/list-page/rail-empty.svelte +51 -0
- package/src/components/list-page/rail-head.svelte +49 -0
- package/src/components/list-page/rail-row.svelte +163 -0
- package/src/components/list-page/section-host.ts +24 -0
- package/src/components/list-page/section-label.svelte +39 -0
- package/src/components/list-page/step.test.ts +21 -0
- package/src/components/list-page/step.ts +10 -0
- package/src/components/list-page/toolbar-search.svelte +63 -0
- package/src/components/list-page/toolbar-trigger.ts +23 -0
- package/src/components/list-page/types.ts +1 -0
- package/src/components/locale-switch/index.ts +1 -0
- package/src/components/locale-switch/locale-switch.svelte +59 -0
- package/src/components/mark/index.ts +1 -0
- package/src/components/mark/mark.svelte +70 -0
- package/src/components/open-in/index.ts +6 -0
- package/src/components/open-in/open-in.svelte +106 -0
- package/src/components/picker/index.ts +4 -0
- package/src/components/picker/mark-picker.svelte +84 -0
- package/src/components/picker/picker.svelte +143 -0
- package/src/components/picker/trigger.ts +42 -0
- package/src/components/picker/types.ts +26 -0
- package/src/components/segmented/animated-tabs.svelte +175 -0
- package/src/components/segmented/collapse.test.ts +49 -0
- package/src/components/segmented/collapse.ts +39 -0
- package/src/components/segmented/index.ts +41 -0
- package/src/components/segmented/section-runs.svelte +79 -0
- package/src/components/segmented/segment.svelte +106 -0
- package/src/components/segmented/segmented-filter.svelte +125 -0
- package/src/components/segmented/segmented-nav.svelte +82 -0
- package/src/components/segmented/segmented-overflow.svelte +85 -0
- package/src/components/segmented/segmented-track.svelte +181 -0
- package/src/components/segmented/segmented.test.ts +20 -0
- package/src/components/segmented/segmented.ts +80 -0
- package/src/components/star-rating-input/index.ts +9 -0
- package/src/components/star-rating-input/star-rating-input.svelte +256 -0
- package/src/components/svg/index.ts +1 -0
- package/src/components/svg/svg.svelte +9 -0
- package/src/effects/border-beam/BorderBeam.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.css +42 -8
- package/src/effects/image-comparison/ImageComparison.svelte +138 -21
- package/src/effects/image-comparison/compare.test.ts +17 -0
- package/src/effects/image-comparison/compare.ts +5 -0
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +338 -0
- package/src/effects/magic-card/MagicCard.css +47 -0
- package/src/effects/magic-card/MagicCard.svelte +57 -0
- package/src/effects/marquee/Marquee.css +27 -1
- package/src/effects/marquee/Marquee.svelte +67 -3
- package/src/effects/reveal/index.ts +2 -1
- package/src/effects/reveal/observe.test.ts +60 -0
- package/src/effects/reveal/observe.ts +33 -1
- package/src/effects/reveal/types.ts +7 -0
- package/src/effects/theme-toggle/ThemeToggle.css +199 -6
- package/src/effects/theme-toggle/ThemeToggle.svelte +51 -26
- package/src/gallery.test.ts +52 -0
- package/src/index.ts +5 -1
- package/src/lib/panel.ts +7 -1
- package/src/lib/sliding-pill.ts +68 -0
- package/src/lib/theme-transition.ts +41 -13
- package/src/lib/tone.ts +48 -0
- package/src/shadcn/accordion/accordion-trigger.svelte +15 -6
- package/src/shadcn/alert/alert.svelte +3 -1
- package/src/shadcn/badge/badge.svelte +8 -7
- package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
- package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +2 -2
- package/src/shadcn/calendar/calendar-month-select.svelte +2 -2
- package/src/shadcn/calendar/calendar-next-button.svelte +2 -2
- package/src/shadcn/calendar/calendar-prev-button.svelte +2 -2
- package/src/shadcn/calendar/calendar-year-select.svelte +2 -2
- package/src/shadcn/calendar/calendar.svelte +6 -0
- 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 +10 -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/command/index.ts +3 -0
- package/src/shadcn/field/index.ts +3 -0
- package/src/shadcn/field/simple-field.svelte +71 -0
- package/src/shadcn/field/simple-field.test.ts +47 -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/radio-group/radio-group-item.svelte +3 -2
- package/src/shadcn/sheet/sheet-content.svelte +1 -0
- package/src/shadcn/sheet/sheet.css +48 -0
- package/src/shadcn/sonner/sonner.svelte +7 -10
- package/src/shadcn/tabs/tabs-list.svelte +13 -2
- package/src/shadcn/tabs/tabs-trigger.svelte +1 -1
- package/src/shadcn/toggle-group/toggle-group.svelte +10 -3
- 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/ai/composer/Composer.css +0 -108
- package/src/ai/composer/Composer.svelte +0 -111
- package/src/ai/composer/index.ts +0 -10
- 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/animations/accordion.css +0 -58
- package/src/animations/icon-swap.css +0 -43
- package/src/animations/notification-badge.css +0 -81
- package/src/animations/panel.css +0 -86
- package/src/animations/reasoning-stream.css +0 -49
- package/src/animations/skeleton-reveal.css +0 -97
- package/src/animations/streaming-text.css +0 -31
- package/src/animations/tabs-sliding.css +0 -83
- package/src/animations/texts-reveal.css +0 -70
- package/src/animations/tooltip.css +0 -72
- package/src/animations/view-transition-reveal.ts +0 -74
- 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/lib/utils.ts +0 -45
- package/src/showcase/AiSection.svelte +0 -157
- package/src/showcase/AnimationsSection.svelte +0 -1658
- package/src/showcase/ChartsSection.svelte +0 -458
- package/src/showcase/EffectsSection.svelte +0 -152
- package/src/showcase/ShadcnSection.svelte +0 -27
- package/src/showcase/ShowcaseImport.svelte +0 -126
- package/src/showcase/ShowcaseList.svelte +0 -132
- package/src/showcase/ShowcaseNav.svelte +0 -247
- package/src/showcase/ShowcaseSection.svelte +0 -112
- package/src/showcase/ShowcaseShell.svelte +0 -55
- package/src/showcase/ShowcaseStage.svelte +0 -342
- package/src/showcase/ShowcaseVariant.svelte +0 -109
- package/src/showcase/assets/image-reveal/art-1.jpg +0 -0
- package/src/showcase/assets/image-reveal/art-2.jpg +0 -0
- package/src/showcase/assets/image-reveal/art-3.jpg +0 -0
- package/src/showcase/check.svg +0 -1
- package/src/showcase/chevron-arms.svg +0 -2
- package/src/showcase/chevron-down.svg +0 -1
- package/src/showcase/copy.svg +0 -2
- package/src/showcase/demos/ai/confirmation.svelte +0 -59
- package/src/showcase/demos/ai/conversation.svelte +0 -59
- package/src/showcase/demos/ai/loading-state.svelte +0 -19
- package/src/showcase/demos/ai/prompt-input.svelte +0 -57
- package/src/showcase/demos/ai/reasoning.svelte +0 -19
- package/src/showcase/demos/ai/thinking-dots.svelte +0 -15
- package/src/showcase/demos/ai/voice-waveform.svelte +0 -24
- package/src/showcase/demos/effects/animated-beam.svelte +0 -50
- package/src/showcase/demos/effects/animated-group.svelte +0 -47
- package/src/showcase/demos/effects/border-beam-default.svelte +0 -20
- package/src/showcase/demos/effects/border-beam-line.svelte +0 -20
- package/src/showcase/demos/effects/border-beam-mono.svelte +0 -20
- package/src/showcase/demos/effects/border-beam-sunset.svelte +0 -20
- package/src/showcase/demos/effects/image-comparison.svelte +0 -25
- package/src/showcase/demos/effects/image-reveal.svelte +0 -49
- package/src/showcase/demos/effects/in-view.svelte +0 -41
- package/src/showcase/demos/effects/integrations-hub.svelte +0 -82
- package/src/showcase/demos/effects/magnetic.svelte +0 -31
- package/src/showcase/demos/effects/marquee.svelte +0 -33
- package/src/showcase/demos/effects/progressive-blur.svelte +0 -47
- package/src/showcase/demos/effects/spotlight.svelte +0 -40
- package/src/showcase/demos/effects/text-effect.svelte +0 -55
- package/src/showcase/demos/shadcn/accordion.svelte +0 -45
- package/src/showcase/demos/shadcn/alert-dialog.svelte +0 -23
- package/src/showcase/demos/shadcn/alert.svelte +0 -30
- package/src/showcase/demos/shadcn/attachment.svelte +0 -71
- package/src/showcase/demos/shadcn/avatar.svelte +0 -30
- package/src/showcase/demos/shadcn/badge.svelte +0 -26
- package/src/showcase/demos/shadcn/breadcrumb.svelte +0 -34
- package/src/showcase/demos/shadcn/bubble.svelte +0 -36
- package/src/showcase/demos/shadcn/button.svelte +0 -11
- package/src/showcase/demos/shadcn/calendar.svelte +0 -8
- package/src/showcase/demos/shadcn/card.svelte +0 -39
- package/src/showcase/demos/shadcn/checkbox.svelte +0 -39
- package/src/showcase/demos/shadcn/collapsible.svelte +0 -20
- package/src/showcase/demos/shadcn/command.svelte +0 -48
- package/src/showcase/demos/shadcn/context-menu.svelte +0 -54
- package/src/showcase/demos/shadcn/demo-harness.svelte +0 -12
- package/src/showcase/demos/shadcn/demos.test.ts +0 -20
- package/src/showcase/demos/shadcn/dialog.svelte +0 -38
- package/src/showcase/demos/shadcn/dropdown-menu.svelte +0 -59
- package/src/showcase/demos/shadcn/empty.svelte +0 -29
- package/src/showcase/demos/shadcn/field.svelte +0 -115
- package/src/showcase/demos/shadcn/hover-card.svelte +0 -32
- package/src/showcase/demos/shadcn/index.ts +0 -358
- package/src/showcase/demos/shadcn/input-otp.svelte +0 -19
- package/src/showcase/demos/shadcn/input.svelte +0 -5
- package/src/showcase/demos/shadcn/label.svelte +0 -11
- package/src/showcase/demos/shadcn/marker.svelte +0 -30
- package/src/showcase/demos/shadcn/message.svelte +0 -75
- package/src/showcase/demos/shadcn/popover.svelte +0 -36
- package/src/showcase/demos/shadcn/progress.svelte +0 -13
- package/src/showcase/demos/shadcn/radio-group.svelte +0 -19
- package/src/showcase/demos/shadcn/scroll-area.svelte +0 -18
- package/src/showcase/demos/shadcn/select.svelte +0 -29
- package/src/showcase/demos/shadcn/separator.svelte +0 -12
- package/src/showcase/demos/shadcn/sheet.svelte +0 -48
- package/src/showcase/demos/shadcn/skeleton.svelte +0 -11
- package/src/showcase/demos/shadcn/slider.svelte +0 -7
- package/src/showcase/demos/shadcn/sonner.svelte +0 -18
- package/src/showcase/demos/shadcn/spinner.svelte +0 -11
- package/src/showcase/demos/shadcn/switch.svelte +0 -9
- package/src/showcase/demos/shadcn/table.svelte +0 -76
- package/src/showcase/demos/shadcn/tabs.svelte +0 -62
- package/src/showcase/demos/shadcn/textarea.svelte +0 -5
- package/src/showcase/demos/shadcn/toggle-group.svelte +0 -18
- package/src/showcase/demos/shadcn/toggle.svelte +0 -14
- package/src/showcase/demos/shadcn/tooltip.svelte +0 -13
- package/src/showcase/heart.svg +0 -1
- package/src/showcase/index.ts +0 -38
- package/src/showcase/kit.test.ts +0 -72
- package/src/showcase/kit.ts +0 -17
- package/src/showcase/plus.svg +0 -1
- package/src/showcase/showcase-shell.css +0 -91
- package/src/showcase/stacked-section.css +0 -15
- package/src/showcase/success-check.svg +0 -1
- package/src/showcase/types.ts +0 -29
- package/src/svg-raw.d.ts +0 -7
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
<script module lang="ts">
|
|
2
|
-
// WHY: each gradient needs a document-unique <defs> id; a module counter keeps
|
|
3
|
-
// SSR and hydration in lockstep (def and ref share the same value per render).
|
|
4
|
-
let gradientSeq = 0;
|
|
5
|
-
</script>
|
|
6
|
-
|
|
7
|
-
<script lang="ts">
|
|
8
|
-
// =========================
|
|
9
|
-
// IMPORTS
|
|
10
|
-
// =========================
|
|
11
|
-
import "./gauge-chart.css";
|
|
12
|
-
import { cn } from "@heyramzi/utils";
|
|
13
|
-
import AnimatedValue from "./animated-value.svelte";
|
|
14
|
-
|
|
15
|
-
// =========================
|
|
16
|
-
// TYPES
|
|
17
|
-
// =========================
|
|
18
|
-
type Props = {
|
|
19
|
-
/** Arc fill, 0-100 (how many notches light up). */
|
|
20
|
-
value: number;
|
|
21
|
-
/** "gauge" = notched arc, "ring" = continuous swept arc. */
|
|
22
|
-
variant?: "gauge" | "ring";
|
|
23
|
-
/** Show the center value/label. Off when the number sits beside the gauge. */
|
|
24
|
-
showValue?: boolean;
|
|
25
|
-
/** Active arc color (CSS color or var). Alias for `activeFill`. */
|
|
26
|
-
color?: string;
|
|
27
|
-
/** Single-hue gradient along the active arc. Alias for `useGradient`. */
|
|
28
|
-
gradient?: boolean;
|
|
29
|
-
/** Center label under the value. Alias for `defaultLabel`. */
|
|
30
|
-
label?: string;
|
|
31
|
-
/** Center statistic. Defaults to `value`. Formatted via `formatOptions`. */
|
|
32
|
-
centerValue?: number;
|
|
33
|
-
/** Notch count around the arc. */
|
|
34
|
-
totalNotches?: number;
|
|
35
|
-
/** Gap between notches as a percentage of the arc. */
|
|
36
|
-
spacing?: number;
|
|
37
|
-
/** Radial depth of the notch band as a percentage of the default. */
|
|
38
|
-
notchLengthPercent?: number;
|
|
39
|
-
/** Corner fillet in viewBox units (0 = sharp). Defaults to a soft pill. */
|
|
40
|
-
notchCornerRadius?: number;
|
|
41
|
-
/** Rectangular notches instead of angular/tapered. */
|
|
42
|
-
uniformWidth?: boolean;
|
|
43
|
-
/** Arc start in degrees (default 135, sweeping to 405 = 270deg with a bottom gap). */
|
|
44
|
-
startAngle?: number;
|
|
45
|
-
endAngle?: number;
|
|
46
|
-
/** Single-hue gradient along the active arc instead of a flat fill. */
|
|
47
|
-
useGradient?: boolean;
|
|
48
|
-
/** Hex stops for the active gradient. Defaults to a tonal ramp of `activeFill`. */
|
|
49
|
-
activeGradient?: [string, string];
|
|
50
|
-
/** Active notch color (CSS color or var). */
|
|
51
|
-
activeFill?: string;
|
|
52
|
-
/** Track notch color. Defaults to `activeFill`. */
|
|
53
|
-
inactiveFill?: string;
|
|
54
|
-
activeFillOpacity?: number;
|
|
55
|
-
inactiveFillOpacity?: number;
|
|
56
|
-
/** Center label under the value. */
|
|
57
|
-
defaultLabel?: string;
|
|
58
|
-
/** Intl formatting for the center value. */
|
|
59
|
-
formatOptions?: Intl.NumberFormatOptions;
|
|
60
|
-
locale?: string;
|
|
61
|
-
prefix?: string;
|
|
62
|
-
suffix?: string;
|
|
63
|
-
/** Fixed square size in px. Omit to fill the parent (responsive). */
|
|
64
|
-
size?: number;
|
|
65
|
-
/** Minimum width when responsive. */
|
|
66
|
-
minWidth?: number;
|
|
67
|
-
/** Accessible description, e.g. "ARR run rate". */
|
|
68
|
-
ariaLabel?: string;
|
|
69
|
-
class?: string;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// =========================
|
|
73
|
-
// PROPS
|
|
74
|
-
// =========================
|
|
75
|
-
let {
|
|
76
|
-
value,
|
|
77
|
-
variant = "gauge",
|
|
78
|
-
showValue = true,
|
|
79
|
-
color,
|
|
80
|
-
gradient,
|
|
81
|
-
label,
|
|
82
|
-
centerValue,
|
|
83
|
-
totalNotches = 40,
|
|
84
|
-
spacing = 25,
|
|
85
|
-
notchLengthPercent = 100,
|
|
86
|
-
notchCornerRadius,
|
|
87
|
-
uniformWidth = false,
|
|
88
|
-
startAngle = 135,
|
|
89
|
-
endAngle = 405,
|
|
90
|
-
useGradient = false,
|
|
91
|
-
activeGradient,
|
|
92
|
-
activeFill = "var(--chart-1)",
|
|
93
|
-
inactiveFill,
|
|
94
|
-
activeFillOpacity = 1,
|
|
95
|
-
inactiveFillOpacity = 0.12,
|
|
96
|
-
defaultLabel = "Total",
|
|
97
|
-
formatOptions,
|
|
98
|
-
locale,
|
|
99
|
-
prefix,
|
|
100
|
-
suffix,
|
|
101
|
-
size,
|
|
102
|
-
minWidth = 160,
|
|
103
|
-
ariaLabel,
|
|
104
|
-
class: className,
|
|
105
|
-
}: Props = $props();
|
|
106
|
-
|
|
107
|
-
// =========================
|
|
108
|
-
// CONST
|
|
109
|
-
// =========================
|
|
110
|
-
// Normalized 100x100 coordinate space so the SVG scales to any container.
|
|
111
|
-
const CX = 50;
|
|
112
|
-
const CY = 50;
|
|
113
|
-
const OUTER_R = 42;
|
|
114
|
-
const gradientId = `hr-gauge-grad-${(gradientSeq += 1)}`;
|
|
115
|
-
|
|
116
|
-
// =========================
|
|
117
|
-
// DERIVED
|
|
118
|
-
// =========================
|
|
119
|
-
const clamped = $derived(Math.max(0, Math.min(100, value)));
|
|
120
|
-
const center = $derived(centerValue ?? value);
|
|
121
|
-
const effFill = $derived(color ?? activeFill);
|
|
122
|
-
const effGradient = $derived(gradient ?? useGradient);
|
|
123
|
-
const effLabel = $derived(label ?? defaultLabel);
|
|
124
|
-
const band = $derived(14 * (Math.max(5, Math.min(100, notchLengthPercent)) / 100));
|
|
125
|
-
const innerR = $derived(OUTER_R - band);
|
|
126
|
-
const midR = $derived((OUTER_R + innerR) / 2);
|
|
127
|
-
const corner = $derived(notchCornerRadius ?? band * 0.22);
|
|
128
|
-
const totalAngle = $derived(endAngle - startAngle);
|
|
129
|
-
const activeCount = $derived(Math.round((clamped / 100) * totalNotches));
|
|
130
|
-
const trackFill = $derived(inactiveFill ?? effFill);
|
|
131
|
-
const activePaint = $derived(effGradient ? `url(#${gradientId})` : effFill);
|
|
132
|
-
const gradStops = $derived(
|
|
133
|
-
activeGradient ?? [`color-mix(in oklab, ${effFill}, white 45%)`, effFill],
|
|
134
|
-
);
|
|
135
|
-
// WHY: ring variant draws a single rounded arc that sweeps from empty; the
|
|
136
|
-
// stroke-dashoffset (with pathLength 100) maps 1:1 to the percent value.
|
|
137
|
-
const ringTrack = $derived(arcPath(startAngle, endAngle));
|
|
138
|
-
const ringOffset = $derived(100 - clamped);
|
|
139
|
-
|
|
140
|
-
const notches = $derived.by(() => {
|
|
141
|
-
const notchAngle = (totalAngle * (1 - spacing / 100)) / totalNotches;
|
|
142
|
-
const gapAngle = (totalAngle * (spacing / 100)) / Math.max(1, totalNotches - 1);
|
|
143
|
-
const half = (notchAngle * 0.8 * Math.PI) / 180 / 2;
|
|
144
|
-
const items: { d: string; active: boolean; index: number }[] = [];
|
|
145
|
-
for (let i = 0; i < totalNotches; i++) {
|
|
146
|
-
const angle = startAngle + i * (notchAngle + gapAngle) + notchAngle / 2;
|
|
147
|
-
items.push({
|
|
148
|
-
index: i,
|
|
149
|
-
active: i < activeCount,
|
|
150
|
-
d: notchPath(buildQuad(angle, half), corner),
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
return items;
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// =========================
|
|
157
|
-
// FUNCTIONS
|
|
158
|
-
// =========================
|
|
159
|
-
function buildQuad(
|
|
160
|
-
angleDeg: number,
|
|
161
|
-
half: number,
|
|
162
|
-
): [number, number, number, number, number, number, number, number] {
|
|
163
|
-
const rad = (angleDeg * Math.PI) / 180;
|
|
164
|
-
if (uniformWidth) {
|
|
165
|
-
// WHY: constant perpendicular half-width gives rectangular notches; the
|
|
166
|
-
// chord at the mid radius keeps them visually consistent with tapered ones.
|
|
167
|
-
const w = midR * Math.sin(half);
|
|
168
|
-
const ux = Math.cos(rad);
|
|
169
|
-
const uy = Math.sin(rad);
|
|
170
|
-
const px = -uy;
|
|
171
|
-
const py = ux;
|
|
172
|
-
const ox = CX + ux * OUTER_R;
|
|
173
|
-
const oy = CY + uy * OUTER_R;
|
|
174
|
-
const ix = CX + ux * innerR;
|
|
175
|
-
const iy = CY + uy * innerR;
|
|
176
|
-
return [
|
|
177
|
-
ox + px * w,
|
|
178
|
-
oy + py * w,
|
|
179
|
-
ox - px * w,
|
|
180
|
-
oy - py * w,
|
|
181
|
-
ix - px * w,
|
|
182
|
-
iy - py * w,
|
|
183
|
-
ix + px * w,
|
|
184
|
-
iy + py * w,
|
|
185
|
-
];
|
|
186
|
-
}
|
|
187
|
-
return [
|
|
188
|
-
CX + Math.cos(rad - half) * OUTER_R,
|
|
189
|
-
CY + Math.sin(rad - half) * OUTER_R,
|
|
190
|
-
CX + Math.cos(rad + half) * OUTER_R,
|
|
191
|
-
CY + Math.sin(rad + half) * OUTER_R,
|
|
192
|
-
CX + Math.cos(rad + half) * innerR,
|
|
193
|
-
CY + Math.sin(rad + half) * innerR,
|
|
194
|
-
CX + Math.cos(rad - half) * innerR,
|
|
195
|
-
CY + Math.sin(rad - half) * innerR,
|
|
196
|
-
];
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function arcPath(startDeg: number, endDeg: number): string {
|
|
200
|
-
const a0 = (startDeg * Math.PI) / 180;
|
|
201
|
-
const a1 = (endDeg * Math.PI) / 180;
|
|
202
|
-
const sx = CX + Math.cos(a0) * midR;
|
|
203
|
-
const sy = CY + Math.sin(a0) * midR;
|
|
204
|
-
const ex = CX + Math.cos(a1) * midR;
|
|
205
|
-
const ey = CY + Math.sin(a1) * midR;
|
|
206
|
-
const large = endDeg - startDeg > 180 ? 1 : 0;
|
|
207
|
-
return `M ${sx} ${sy} A ${midR} ${midR} 0 ${large} 1 ${ex} ${ey}`;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// WHY: rounded corners (lerp toward each vertex, then a quadratic through it)
|
|
211
|
-
// read as soft pills, matching the bklit gauge look.
|
|
212
|
-
function notchPath([x1, y1, x2, y2, x3, y3, x4, y4]: number[], cornerR: number): string {
|
|
213
|
-
if (cornerR <= 0) {
|
|
214
|
-
return `M ${x1} ${y1} L ${x2} ${y2} L ${x3} ${y3} L ${x4} ${y4} Z`;
|
|
215
|
-
}
|
|
216
|
-
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
|
|
217
|
-
const dist = (ax: number, ay: number, bx: number, by: number) => Math.hypot(bx - ax, by - ay);
|
|
218
|
-
const d12 = dist(x1, y1, x2, y2);
|
|
219
|
-
const d23 = dist(x2, y2, x3, y3);
|
|
220
|
-
const d34 = dist(x3, y3, x4, y4);
|
|
221
|
-
const d41 = dist(x4, y4, x1, y1);
|
|
222
|
-
const r1 = Math.min(cornerR / d12, 0.49);
|
|
223
|
-
const r2 = Math.min(cornerR / d23, 0.49);
|
|
224
|
-
const r3 = Math.min(cornerR / d34, 0.49);
|
|
225
|
-
const r4 = Math.min(cornerR / d41, 0.49);
|
|
226
|
-
const p = (ax: number, ay: number, bx: number, by: number, t: number) =>
|
|
227
|
-
`${lerp(ax, bx, t)} ${lerp(ay, by, t)}`;
|
|
228
|
-
return (
|
|
229
|
-
`M ${p(x1, y1, x4, y4, r4)} Q ${x1} ${y1} ${p(x1, y1, x2, y2, r1)} ` +
|
|
230
|
-
`L ${p(x2, y2, x1, y1, r1)} Q ${x2} ${y2} ${p(x2, y2, x3, y3, r2)} ` +
|
|
231
|
-
`L ${p(x3, y3, x2, y2, r2)} Q ${x3} ${y3} ${p(x3, y3, x4, y4, r3)} ` +
|
|
232
|
-
`L ${p(x4, y4, x3, y3, r3)} Q ${x4} ${y4} ${p(x4, y4, x1, y1, r4)} Z`
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
</script>
|
|
236
|
-
|
|
237
|
-
<!-- =========================== -->
|
|
238
|
-
<!-- MARKUP -->
|
|
239
|
-
<!-- =========================== -->
|
|
240
|
-
<div
|
|
241
|
-
class={cn("hr-gauge", className)}
|
|
242
|
-
style:width={size ? `${size}px` : "100%"}
|
|
243
|
-
style:min-width="{minWidth}px"
|
|
244
|
-
role="img"
|
|
245
|
-
aria-label={ariaLabel
|
|
246
|
-
? `${ariaLabel}: ${Math.round(clamped)}%`
|
|
247
|
-
: `Gauge at ${Math.round(clamped)}%`}
|
|
248
|
-
>
|
|
249
|
-
<!-- no-inline-svg-ignore -->
|
|
250
|
-
<svg viewBox="0 0 100 100" aria-hidden="true">
|
|
251
|
-
{#if effGradient}
|
|
252
|
-
<defs>
|
|
253
|
-
<linearGradient id={gradientId} gradientUnits="userSpaceOnUse" x1="8" y1="0" x2="92" y2="0">
|
|
254
|
-
<stop offset="0%" stop-color={gradStops[0]} />
|
|
255
|
-
<stop offset="100%" stop-color={gradStops[1]} />
|
|
256
|
-
</linearGradient>
|
|
257
|
-
</defs>
|
|
258
|
-
{/if}
|
|
259
|
-
{#if variant === "ring"}
|
|
260
|
-
<path
|
|
261
|
-
class="ring-track"
|
|
262
|
-
d={ringTrack}
|
|
263
|
-
stroke={trackFill}
|
|
264
|
-
stroke-opacity={inactiveFillOpacity}
|
|
265
|
-
style:stroke-width="{band}px"
|
|
266
|
-
/>
|
|
267
|
-
<path
|
|
268
|
-
class="ring-fill"
|
|
269
|
-
d={ringTrack}
|
|
270
|
-
pathLength="100"
|
|
271
|
-
stroke={activePaint}
|
|
272
|
-
style:stroke-width="{band}px"
|
|
273
|
-
style:stroke-dashoffset={ringOffset}
|
|
274
|
-
/>
|
|
275
|
-
{:else}
|
|
276
|
-
{#each notches as notch (notch.index)}
|
|
277
|
-
<path class="track" d={notch.d} fill={trackFill} fill-opacity={inactiveFillOpacity} />
|
|
278
|
-
{/each}
|
|
279
|
-
{#each notches as notch (notch.index)}
|
|
280
|
-
{#if notch.active}
|
|
281
|
-
<path
|
|
282
|
-
class="fill"
|
|
283
|
-
d={notch.d}
|
|
284
|
-
fill={activePaint}
|
|
285
|
-
fill-opacity={activeFillOpacity}
|
|
286
|
-
style:animation-delay="{100 + notch.index * 18}ms"
|
|
287
|
-
/>
|
|
288
|
-
{/if}
|
|
289
|
-
{/each}
|
|
290
|
-
{/if}
|
|
291
|
-
</svg>
|
|
292
|
-
|
|
293
|
-
{#if showValue}
|
|
294
|
-
<div class="center">
|
|
295
|
-
<span class="value">
|
|
296
|
-
<AnimatedValue value={center} {formatOptions} {locale} {prefix} {suffix} />
|
|
297
|
-
</span>
|
|
298
|
-
{#if effLabel}
|
|
299
|
-
<span class="label">{effLabel}</span>
|
|
300
|
-
{/if}
|
|
301
|
-
</div>
|
|
302
|
-
{/if}
|
|
303
|
-
</div>
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { hoverBand } from "./hover-band.js";
|
|
3
|
-
|
|
4
|
-
const center = (b: { x: number; width: number } | null) => (b ? b.x + b.width / 2 : NaN);
|
|
5
|
-
|
|
6
|
-
describe("hoverBand", () => {
|
|
7
|
-
it("centers on the point when the gaps are even", () => {
|
|
8
|
-
expect(hoverBand([0, 100, 200], 1, 300)).toEqual({ x: 20, width: 160 });
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("stays centered when the gaps differ", () => {
|
|
12
|
-
const b = hoverBand([0, 40, 200], 1, 300);
|
|
13
|
-
expect(center(b)).toBe(40);
|
|
14
|
-
expect(b?.width).toBe(64);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("stays centered at either end of the line", () => {
|
|
18
|
-
expect(center(hoverBand([0, 100, 200], 0, 300))).toBe(0);
|
|
19
|
-
expect(center(hoverBand([0, 100, 200], 2, 300))).toBe(200);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("falls back to the plot width for a single point", () => {
|
|
23
|
-
expect(hoverBand([50], 0, 100)).toEqual({ x: -30, width: 160 });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("returns null for an index off the data", () => {
|
|
27
|
-
expect(hoverBand([0, 100], -1, 300)).toBeNull();
|
|
28
|
-
expect(hoverBand([0, 100], 2, 300)).toBeNull();
|
|
29
|
-
});
|
|
30
|
-
});
|
package/src/charts/hover-band.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/** How far the hover band reaches each side of the point, as a share of the gap to its neighbour. */
|
|
2
|
-
export const HOVER_BAND_REACH = 0.8;
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The hovered segment's clip, centered on the point at `xs[i]`.
|
|
6
|
-
* Both sides take the shorter neighbour gap, so the dot always sits in the middle.
|
|
7
|
-
*/
|
|
8
|
-
export function hoverBand(
|
|
9
|
-
xs: number[],
|
|
10
|
-
i: number,
|
|
11
|
-
width: number,
|
|
12
|
-
reach = HOVER_BAND_REACH,
|
|
13
|
-
): { x: number; width: number } | null {
|
|
14
|
-
if (i < 0 || i >= xs.length) return null;
|
|
15
|
-
const at = xs[i];
|
|
16
|
-
const before = i > 0 ? at - xs[i - 1] : Infinity;
|
|
17
|
-
const after = i < xs.length - 1 ? xs[i + 1] - at : Infinity;
|
|
18
|
-
const gap = Math.min(before, after);
|
|
19
|
-
const half = (Number.isFinite(gap) ? gap : width) * reach;
|
|
20
|
-
return { x: at - half, width: half * 2 };
|
|
21
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import { getChartContext } from "layerchart";
|
|
6
|
-
import type { Snippet } from "svelte";
|
|
7
|
-
import { prefersReducedMotion, Spring } from "svelte/motion";
|
|
8
|
-
import { fade } from "svelte/transition";
|
|
9
|
-
import { HOVER_BAND_REACH, hoverBand } from "./hover-band.js";
|
|
10
|
-
|
|
11
|
-
// =========================
|
|
12
|
-
// TYPES
|
|
13
|
-
// =========================
|
|
14
|
-
type Props = {
|
|
15
|
-
/** The series: dims while a point is hovered. */
|
|
16
|
-
children: Snippet;
|
|
17
|
-
/** The strokes alone, redrawn at full strength around the hovered point. */
|
|
18
|
-
segment: Snippet;
|
|
19
|
-
/** Headroom above and below the plot so a thick stroke is not cut. */
|
|
20
|
-
bleed?: number;
|
|
21
|
-
/** How far the band reaches each side of the point, as a share of the gap to its neighbour. */
|
|
22
|
-
reach?: number;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// =========================
|
|
26
|
-
// PROPS
|
|
27
|
-
// =========================
|
|
28
|
-
let { children, segment, bleed = 6, reach = HOVER_BAND_REACH }: Props = $props();
|
|
29
|
-
|
|
30
|
-
// =========================
|
|
31
|
-
// STATE
|
|
32
|
-
// =========================
|
|
33
|
-
const ctx = getChartContext();
|
|
34
|
-
const id = `hr-focus-${Math.random().toString(36).slice(2, 8)}`;
|
|
35
|
-
const left = new Spring(0, { stiffness: 0.2, damping: 0.85 });
|
|
36
|
-
const width = new Spring(0, { stiffness: 0.2, damping: 0.85 });
|
|
37
|
-
|
|
38
|
-
// =========================
|
|
39
|
-
// DERIVED
|
|
40
|
-
// =========================
|
|
41
|
-
const band = $derived.by(() => {
|
|
42
|
-
const d = ctx.tooltip.data;
|
|
43
|
-
const xs = (ctx.data as unknown[]).map((r) => Number(ctx.xGet(r)));
|
|
44
|
-
// WHY by x and not indexOf: ctx.data hands back proxies, so identity never matches.
|
|
45
|
-
const at = d ? Number(ctx.xGet(d)) : NaN;
|
|
46
|
-
return hoverBand(xs, xs.indexOf(at), ctx.width, reach);
|
|
47
|
-
});
|
|
48
|
-
const duration = $derived(prefersReducedMotion.current ? 0 : 400);
|
|
49
|
-
|
|
50
|
-
// =========================
|
|
51
|
-
// EFFECTS
|
|
52
|
-
// =========================
|
|
53
|
-
// WHY instant on first hover: the clip should open where the pointer is, not
|
|
54
|
-
// slide in from wherever it last closed.
|
|
55
|
-
let wasOn = false;
|
|
56
|
-
$effect(() => {
|
|
57
|
-
if (!band) {
|
|
58
|
-
wasOn = false;
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const instant = !wasOn || prefersReducedMotion.current;
|
|
62
|
-
left.set(band.x, { instant });
|
|
63
|
-
width.set(band.width, { instant });
|
|
64
|
-
wasOn = true;
|
|
65
|
-
});
|
|
66
|
-
</script>
|
|
67
|
-
|
|
68
|
-
<!-- =========================== -->
|
|
69
|
-
<!-- HOVER FOCUS -->
|
|
70
|
-
<!-- =========================== -->
|
|
71
|
-
<g class="hr-hover-dim" class:hr-hover-dimmed={band !== null}>
|
|
72
|
-
{@render children()}
|
|
73
|
-
</g>
|
|
74
|
-
<!-- WHY outside the if: the segment fades out after hover ends, and without its
|
|
75
|
-
clip it would flash as the whole line. -->
|
|
76
|
-
<defs>
|
|
77
|
-
<clipPath {id}>
|
|
78
|
-
<rect x={left.current} y={-bleed} width={width.current} height={ctx.height + bleed * 2} />
|
|
79
|
-
</clipPath>
|
|
80
|
-
</defs>
|
|
81
|
-
{#if band}
|
|
82
|
-
<g clip-path="url(#{id})" transition:fade={{ duration }}>
|
|
83
|
-
{@render segment()}
|
|
84
|
-
</g>
|
|
85
|
-
{/if}
|
package/src/charts/index.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import "./charts.css";
|
|
2
|
-
|
|
3
|
-
export { default as BarChart } from "./bar-chart.svelte";
|
|
4
|
-
export { default as AreaChart } from "./area-chart.svelte";
|
|
5
|
-
export { default as LineChart } from "./line-chart.svelte";
|
|
6
|
-
export { default as DonutChart } from "./donut-chart.svelte";
|
|
7
|
-
export { default as Sparkline } from "./sparkline.svelte";
|
|
8
|
-
export { default as TimeSeriesChart } from "./time-series-chart.svelte";
|
|
9
|
-
export { default as GaugeChart } from "./gauge-chart.svelte";
|
|
10
|
-
export { default as RingChart } from "./ring-chart.svelte";
|
|
11
|
-
export { default as Legend } from "./legend.svelte";
|
|
12
|
-
export { default as StatCard } from "./stat-card.svelte";
|
|
13
|
-
export { default as NumberChart, type NumberDirection } from "./number-chart.svelte";
|
|
14
|
-
export { default as Figure } from "./figure.svelte";
|
|
15
|
-
export { default as TrendPill } from "./trend-pill.svelte";
|
|
16
|
-
export { default as AnimatedValue } from "./animated-value.svelte";
|
|
17
|
-
export { default as EdgeFade } from "./edge-fade.svelte";
|
|
18
|
-
export { resolveEdgeFade, EDGE_FADE_DEFAULT } from "./edge-fade.js";
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
ChartContainer,
|
|
22
|
-
ChartTooltip,
|
|
23
|
-
ChartStyle,
|
|
24
|
-
type ChartConfig,
|
|
25
|
-
type TooltipSeriesItem,
|
|
26
|
-
getPayloadConfigFromPayload,
|
|
27
|
-
useChart,
|
|
28
|
-
setChartContext,
|
|
29
|
-
THEMES,
|
|
30
|
-
} from "./primitives/index.js";
|
package/src/charts/legend.css
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/* Styles for Legend. Plain stylesheet (see area-chart.css for why). Selectors
|
|
2
|
-
are namespaced under `.hr-legend`; the `.horizontal` layout modifier sits on
|
|
3
|
-
the same root element. */
|
|
4
|
-
|
|
5
|
-
.hr-legend {
|
|
6
|
-
width: 100%;
|
|
7
|
-
font-size: 0.8125rem;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.hr-legend-title {
|
|
11
|
-
margin: 0 0 0.625rem;
|
|
12
|
-
font-size: 0.8125rem;
|
|
13
|
-
font-weight: 600;
|
|
14
|
-
color: var(--foreground);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.hr-legend-items {
|
|
18
|
-
list-style: none;
|
|
19
|
-
margin: 0;
|
|
20
|
-
padding: 0;
|
|
21
|
-
display: flex;
|
|
22
|
-
flex-direction: column;
|
|
23
|
-
gap: 0.125rem;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.hr-legend.horizontal .hr-legend-items {
|
|
27
|
-
flex-direction: row;
|
|
28
|
-
flex-wrap: wrap;
|
|
29
|
-
gap: 0.5rem 1rem;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.hr-legend-item {
|
|
33
|
-
width: 100%;
|
|
34
|
-
display: grid;
|
|
35
|
-
grid-template-columns: auto 1fr auto;
|
|
36
|
-
align-items: center;
|
|
37
|
-
gap: 0.5rem 0.625rem;
|
|
38
|
-
padding: 0.375rem 0.5rem;
|
|
39
|
-
border: 0;
|
|
40
|
-
border-radius: 0.5rem;
|
|
41
|
-
background: transparent;
|
|
42
|
-
font: inherit;
|
|
43
|
-
color: var(--foreground);
|
|
44
|
-
text-align: left;
|
|
45
|
-
cursor: pointer;
|
|
46
|
-
transition:
|
|
47
|
-
background 160ms ease,
|
|
48
|
-
opacity 160ms ease;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.hr-legend.horizontal .hr-legend-item {
|
|
52
|
-
width: auto;
|
|
53
|
-
grid-template-columns: auto auto;
|
|
54
|
-
padding: 0.25rem 0.375rem;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.hr-legend-item:hover,
|
|
58
|
-
.hr-legend-item:focus-visible {
|
|
59
|
-
background: var(--muted);
|
|
60
|
-
outline: none;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.hr-legend-item.dimmed {
|
|
64
|
-
opacity: 0.4;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.hr-legend-marker {
|
|
68
|
-
width: 0.625rem;
|
|
69
|
-
height: 0.625rem;
|
|
70
|
-
border-radius: 3px;
|
|
71
|
-
flex-shrink: 0;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.hr-legend-label {
|
|
75
|
-
font-weight: 500;
|
|
76
|
-
white-space: nowrap;
|
|
77
|
-
overflow: hidden;
|
|
78
|
-
text-overflow: ellipsis;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.hr-legend-value {
|
|
82
|
-
display: inline-flex;
|
|
83
|
-
align-items: baseline;
|
|
84
|
-
gap: 0.3125rem;
|
|
85
|
-
font-variant-numeric: tabular-nums;
|
|
86
|
-
color: var(--foreground);
|
|
87
|
-
white-space: nowrap;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.hr-legend-pct {
|
|
91
|
-
font-size: 0.6875rem;
|
|
92
|
-
color: var(--muted-foreground);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.hr-legend-track {
|
|
96
|
-
grid-column: 1 / -1;
|
|
97
|
-
height: 0.375rem;
|
|
98
|
-
border-radius: 999px;
|
|
99
|
-
background: var(--muted);
|
|
100
|
-
overflow: hidden;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.hr-legend-bar {
|
|
104
|
-
display: block;
|
|
105
|
-
width: 100%;
|
|
106
|
-
height: 100%;
|
|
107
|
-
border-radius: 999px;
|
|
108
|
-
/* WHY: scaleX from the left avoids the layout thrash of animating width;
|
|
109
|
-
the bar's fill fraction is set inline as --hr-bar-scale. The entrance
|
|
110
|
-
sweeps from 0 once (delays match the ring sweep); the transition takes
|
|
111
|
-
over for later data changes. */
|
|
112
|
-
transform-origin: left center;
|
|
113
|
-
transform: scaleX(var(--hr-bar-scale, 0));
|
|
114
|
-
animation: hr-legend-fill var(--chart-motion-reveal, 1100ms)
|
|
115
|
-
var(--chart-ease-reveal, cubic-bezier(0.85, 0, 0.15, 1)) both;
|
|
116
|
-
transition: transform var(--chart-motion-slow, 1.1s)
|
|
117
|
-
var(--chart-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
@keyframes hr-legend-fill {
|
|
121
|
-
from {
|
|
122
|
-
transform: scaleX(0);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
@media (prefers-reduced-motion: reduce) {
|
|
127
|
-
.hr-legend-bar {
|
|
128
|
-
animation: none;
|
|
129
|
-
transition: none;
|
|
130
|
-
}
|
|
131
|
-
}
|