@devalok/shilp-sutra 0.38.0 → 0.40.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/AGENTS.md +151 -0
- package/MIGRATION.md +255 -0
- package/README.md +3 -0
- package/dist/_chunks/badge-group.js +76 -75
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/chart-container.js +50 -0
- package/dist/_chunks/chart-container.js.map +1 -0
- package/dist/_chunks/chat.js +236 -228
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/colors.js +30 -0
- package/dist/_chunks/colors.js.map +1 -0
- package/dist/_chunks/document-preview.js +2 -2
- package/dist/_chunks/document-preview.js.map +1 -1
- package/dist/_chunks/emoji-data.js +45 -0
- package/dist/_chunks/emoji-data.js.map +1 -0
- package/dist/_chunks/grid-lines.js +72 -0
- package/dist/_chunks/grid-lines.js.map +1 -0
- package/dist/_chunks/image-preview.js +2 -2
- package/dist/_chunks/image-preview.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js +35 -263
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/normalize-icon.js +18 -0
- package/dist/_chunks/normalize-icon.js.map +1 -0
- package/dist/_chunks/oauth-button.js +227 -0
- package/dist/_chunks/oauth-button.js.map +1 -0
- package/dist/_chunks/popover.js +3 -3
- package/dist/_chunks/popover.js.map +1 -1
- package/dist/_chunks/primitives.js +107 -107
- package/dist/_chunks/primitives.js.map +1 -1
- package/dist/_chunks/shared.js +5 -5
- package/dist/_chunks/shared.js.map +1 -1
- package/dist/_chunks/{text.js → success.js} +26 -63
- package/dist/_chunks/success.js.map +1 -0
- package/dist/_chunks/tiptap.js +1952 -1949
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/_chunks/tooltip.js +58 -0
- package/dist/_chunks/tooltip.js.map +1 -0
- package/dist/_chunks/tree-view.js +101 -96
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/_chunks/use-calendar.js +5 -5
- package/dist/_chunks/use-calendar.js.map +1 -1
- package/dist/ai/ai-command-provider.d.ts +3 -2
- package/dist/ai/ai-command-provider.d.ts.map +1 -1
- package/dist/ai/ai-command-provider.js.map +1 -1
- package/dist/ai/block-renderer.js +11 -9
- package/dist/ai/block-renderer.js.map +1 -1
- package/dist/ai/blocks/error.js +31 -0
- package/dist/ai/blocks/error.js.map +1 -0
- package/dist/ai/blocks/index.d.ts +0 -2
- package/dist/ai/blocks/index.d.ts.map +1 -1
- package/dist/ai/blocks/index.js +2 -2
- package/dist/ai/blocks/text.js +19 -0
- package/dist/ai/blocks/text.js.map +1 -0
- package/dist/ai/command-bar.d.ts.map +1 -1
- package/dist/ai/command-bar.js +198 -193
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.d.ts +2 -1
- package/dist/ai/conversation.d.ts.map +1 -1
- package/dist/ai/conversation.js +92 -87
- package/dist/ai/conversation.js.map +1 -1
- package/dist/ai/index.d.ts +0 -4
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +45 -46
- package/dist/ai/index.js.map +1 -1
- package/dist/composed/activity-feed.d.ts +2 -1
- package/dist/composed/activity-feed.d.ts.map +1 -1
- package/dist/composed/activity-feed.js +5 -5
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/avatar-group.js +4 -4
- package/dist/composed/avatar-group.js.map +1 -1
- package/dist/composed/bulk-action-bar.d.ts +2 -2
- package/dist/composed/bulk-action-bar.d.ts.map +1 -1
- package/dist/composed/bulk-action-bar.js +12 -12
- package/dist/composed/bulk-action-bar.js.map +1 -1
- package/dist/composed/command-palette.d.ts +2 -1
- package/dist/composed/command-palette.d.ts.map +1 -1
- package/dist/composed/command-palette.js +106 -101
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.js +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/date-picker/index.js +747 -3
- package/dist/composed/date-picker/index.js.map +1 -0
- package/dist/composed/emoji-picker.js +4 -4
- package/dist/composed/emoji-picker.js.map +1 -1
- package/dist/composed/empty-state.d.ts +3 -3
- package/dist/composed/empty-state.d.ts.map +1 -1
- package/dist/composed/empty-state.js +40 -31
- package/dist/composed/empty-state.js.map +1 -1
- package/dist/composed/error-boundary.js +3 -3
- package/dist/composed/error-boundary.js.map +1 -1
- package/dist/composed/extensions/emoji-node.js +81 -0
- package/dist/composed/extensions/emoji-node.js.map +1 -0
- package/dist/composed/extensions/emoji-suggestion.js +117 -0
- package/dist/composed/extensions/emoji-suggestion.js.map +1 -0
- package/dist/composed/file-preview.js +498 -2
- package/dist/composed/file-preview.js.map +1 -0
- package/dist/composed/filter-bar.js +1 -1
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/index.d.ts +0 -15
- package/dist/composed/index.d.ts.map +1 -1
- package/dist/composed/index.js +16 -24
- package/dist/composed/inline-edit.js +1 -1
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/composed/loading-skeleton.js +9 -9
- package/dist/composed/loading-skeleton.js.map +1 -1
- package/dist/composed/markdown-viewer.js +3 -3
- package/dist/composed/markdown-viewer.js.map +1 -1
- package/dist/composed/multi-select-popover.js +1 -1
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/page-header.js +1 -1
- package/dist/composed/page-header.js.map +1 -1
- package/dist/composed/page-skeletons.js +15 -15
- package/dist/composed/page-skeletons.js.map +1 -1
- package/dist/composed/priority-indicator.js +3 -3
- package/dist/composed/priority-indicator.js.map +1 -1
- package/dist/composed/rich-chat-input.js +2073 -2
- package/dist/composed/rich-chat-input.js.map +1 -0
- package/dist/composed/rich-text-editor.js +75 -72
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/schedule-view.js +3 -3
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/composed/status-badge.d.ts +3 -2
- package/dist/composed/status-badge.d.ts.map +1 -1
- package/dist/composed/status-badge.js +58 -53
- package/dist/composed/status-badge.js.map +1 -1
- package/dist/shell/app-command-palette.d.ts +2 -1
- package/dist/shell/app-command-palette.d.ts.map +1 -1
- package/dist/shell/app-command-palette.js.map +1 -1
- package/dist/shell/bottom-navbar.d.ts +3 -1
- package/dist/shell/bottom-navbar.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.js +94 -86
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/command-registry.d.ts +2 -1
- package/dist/shell/command-registry.d.ts.map +1 -1
- package/dist/shell/command-registry.js.map +1 -1
- package/dist/shell/notification-center.js +8 -8
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/notification-preferences.js +1 -1
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/shell/sidebar.d.ts +7 -4
- package/dist/shell/sidebar.d.ts.map +1 -1
- package/dist/shell/sidebar.js +148 -134
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/top-bar.d.ts +4 -3
- package/dist/shell/top-bar.d.ts.map +1 -1
- package/dist/shell/top-bar.js +116 -108
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/semantic.css +82 -9
- package/dist/ui/accordion.js +1 -1
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/alert-dialog.js +3 -3
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/alert.js +2 -2
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/autocomplete.js +2 -2
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/avatar.js +11 -11
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-indicator.js +1 -1
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/badge.d.ts +3 -2
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/banner.js +1 -1
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/breadcrumb.js +1 -1
- package/dist/ui/breadcrumb.js.map +1 -1
- package/dist/ui/button.d.ts +5 -4
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +66 -65
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.js +5 -5
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/charts/area-chart.js +177 -0
- package/dist/ui/charts/area-chart.js.map +1 -0
- package/dist/ui/charts/bar-chart.js +127 -0
- package/dist/ui/charts/bar-chart.js.map +1 -0
- package/dist/ui/charts/chart-container.js +3 -0
- package/dist/ui/charts/gauge-chart.js +72 -0
- package/dist/ui/charts/gauge-chart.js.map +1 -0
- package/dist/ui/charts/index.js +10 -1035
- package/dist/ui/charts/line-chart.js +135 -0
- package/dist/ui/charts/line-chart.js.map +1 -0
- package/dist/ui/charts/pie-chart.js +111 -0
- package/dist/ui/charts/pie-chart.js.map +1 -0
- package/dist/ui/charts/radar-chart.js +170 -0
- package/dist/ui/charts/radar-chart.js.map +1 -0
- package/dist/ui/charts/sparkline.js +119 -0
- package/dist/ui/charts/sparkline.js.map +1 -0
- package/dist/ui/chat/message.d.ts +3 -3
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/chat/system-message.d.ts +2 -1
- package/dist/ui/chat/system-message.d.ts.map +1 -1
- package/dist/ui/checkbox.js +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/code.js +2 -2
- package/dist/ui/code.js.map +1 -1
- package/dist/ui/color-input.js +10 -10
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/color-swatch.js +3 -3
- package/dist/ui/color-swatch.js.map +1 -1
- package/dist/ui/combobox.d.ts +2 -1
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +100 -95
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/container.d.ts +6 -1
- package/dist/ui/container.d.ts.map +1 -1
- package/dist/ui/container.js +2 -1
- package/dist/ui/container.js.map +1 -1
- package/dist/ui/context-menu.js +6 -6
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-body.js +1 -1
- package/dist/ui/data-table-body.js.map +1 -1
- package/dist/ui/data-table-bulk-actions.js +2 -2
- package/dist/ui/data-table-bulk-actions.js.map +1 -1
- package/dist/ui/data-table-card.js +2 -2
- package/dist/ui/data-table-card.js.map +1 -1
- package/dist/ui/data-table-header.js +2 -2
- package/dist/ui/data-table-header.js.map +1 -1
- package/dist/ui/data-table-pagination.js +3 -3
- package/dist/ui/data-table-pagination.js.map +1 -1
- package/dist/ui/data-table-toolbar.js +1 -1
- package/dist/ui/data-table-toolbar.js.map +1 -1
- package/dist/ui/data-table.js +1 -1
- package/dist/ui/data-table.js.map +1 -1
- package/dist/ui/devalok-grain.d.ts +1 -1
- package/dist/ui/devalok-grain.js.map +1 -1
- package/dist/ui/dialog.js +2 -2
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dropdown-menu.js +6 -6
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/file-upload.js +4 -4
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/hover-card.js +1 -1
- package/dist/ui/hover-card.js.map +1 -1
- package/dist/ui/icon-button.d.ts +9 -2
- package/dist/ui/icon-button.d.ts.map +1 -1
- package/dist/ui/icon-button.js +14 -13
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/index.d.ts +1 -3
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +31 -33
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input-otp.js +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/input.js +2 -2
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/lib/icon-input.d.ts +42 -0
- package/dist/ui/lib/icon-input.d.ts.map +1 -0
- package/dist/ui/lib/normalize-icon.d.ts +39 -0
- package/dist/ui/lib/normalize-icon.d.ts.map +1 -0
- package/dist/ui/link.js +1 -1
- package/dist/ui/link.js.map +1 -1
- package/dist/ui/menubar.js +8 -8
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.js +3 -3
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/number-input.js +3 -3
- package/dist/ui/number-input.js.map +1 -1
- package/dist/ui/oauth-button/index.d.ts +3 -0
- package/dist/ui/oauth-button/index.d.ts.map +1 -0
- package/dist/ui/oauth-button/index.js +3 -0
- package/dist/ui/oauth-button/oauth-button.d.ts +208 -0
- package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -0
- package/dist/ui/pagination.js +1 -1
- package/dist/ui/pagination.js.map +1 -1
- package/dist/ui/progress.js +2 -2
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/radio.js +1 -1
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/segmented-control.d.ts +3 -4
- package/dist/ui/segmented-control.d.ts.map +1 -1
- package/dist/ui/segmented-control.js +53 -45
- package/dist/ui/segmented-control.js.map +1 -1
- package/dist/ui/select.js +3 -3
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sheet.js +2 -2
- package/dist/ui/sheet.js.map +1 -1
- package/dist/ui/sidebar.js +11 -11
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/skeleton.js +9 -9
- package/dist/ui/skeleton.js.map +1 -1
- package/dist/ui/slider.js +2 -2
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/split-button.js +7 -7
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stack.d.ts +6 -1
- package/dist/ui/stack.d.ts.map +1 -1
- package/dist/ui/stack.js +2 -1
- package/dist/ui/stack.js.map +1 -1
- package/dist/ui/stat-card.d.ts +2 -3
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +118 -116
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/status-dot.js +2 -2
- package/dist/ui/status-dot.js.map +1 -1
- package/dist/ui/stepper.d.ts +2 -1
- package/dist/ui/stepper.d.ts.map +1 -1
- package/dist/ui/stepper.js +74 -69
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/switch.js +2 -2
- package/dist/ui/switch.js.map +1 -1
- package/dist/ui/tabs.js +3 -3
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/text.d.ts +7 -2
- package/dist/ui/text.d.ts.map +1 -1
- package/dist/ui/text.js +2 -1
- package/dist/ui/text.js.map +1 -1
- package/dist/ui/textarea.js +1 -1
- package/dist/ui/textarea.js.map +1 -1
- package/dist/ui/toast.js +8 -8
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/toaster.d.ts +11 -2
- package/dist/ui/toaster.d.ts.map +1 -1
- package/dist/ui/toaster.js.map +1 -1
- package/dist/ui/toggle.js +1 -1
- package/dist/ui/toggle.js.map +1 -1
- package/dist/ui/tooltip.js +12 -12
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/ui/tree-view/tree-item.d.ts +3 -2
- package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
- package/dist/ui/tree-view/use-tree.d.ts +2 -1
- package/dist/ui/tree-view/use-tree.d.ts.map +1 -1
- package/docs/components/_header.md +90 -1
- package/docs/components/ui/oauth-button.md +86 -0
- package/docs/recipes/customize-brand.md +100 -4
- package/docs/recipes/index.md +5 -1
- package/docs/recipes/install-astro.md +15 -0
- package/docs/recipes/install-next-app-router.md +21 -5
- package/docs/recipes/install-next-pages.md +2 -0
- package/docs/recipes/install-remix.md +15 -0
- package/docs/recipes/install-tanstack-start.md +15 -0
- package/docs/recipes/install-vite.md +15 -0
- package/docs/recipes/troubleshoot.md +22 -0
- package/llms-full.txt +177 -2
- package/llms-quick.txt +247 -0
- package/llms.txt +116 -3
- package/package.json +80 -2
- package/scripts/welcome.mjs +219 -0
- package/skill/README.md +99 -0
- package/skill/SKILL.md +163 -0
- package/skill/install.sh +59 -0
- package/skill/references/components-full.md +7083 -0
- package/skill/references/components.md +778 -0
- package/skill/references/customize-brand.md +314 -0
- package/skill/references/server-components.md +211 -0
- package/skill/references/setup-astro.md +195 -0
- package/skill/references/setup-next-app-router.md +248 -0
- package/skill/references/setup-next-pages.md +127 -0
- package/skill/references/setup-remix.md +188 -0
- package/skill/references/setup-tanstack-start.md +160 -0
- package/skill/references/setup-vite.md +187 -0
- package/skill/references/troubleshoot.md +241 -0
- package/dist/_chunks/date-picker.js +0 -748
- package/dist/_chunks/date-picker.js.map +0 -1
- package/dist/_chunks/file-preview.js +0 -499
- package/dist/_chunks/file-preview.js.map +0 -1
- package/dist/_chunks/rich-chat-input.js +0 -2071
- package/dist/_chunks/rich-chat-input.js.map +0 -1
- package/dist/_chunks/text.js.map +0 -1
- package/dist/ui/charts/index.js.map +0 -1
- /package/{LICENSE → skill/LICENSE} +0 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { motionProps as e, tweens as t } from "../lib/motion.js";
|
|
3
|
+
import { cn as n } from "../lib/utils.js";
|
|
4
|
+
import { n as r, r as i, t as a } from "../../_chunks/tooltip.js";
|
|
5
|
+
import { r as o, t as s } from "../../_chunks/colors.js";
|
|
6
|
+
import { n as c, t as l } from "../../_chunks/grid-lines.js";
|
|
7
|
+
import { t as u } from "../../_chunks/chart-container.js";
|
|
8
|
+
import * as d from "react";
|
|
9
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
|
+
import { motion as h } from "framer-motion";
|
|
11
|
+
import { scaleLinear as g, scalePoint as _ } from "d3-scale";
|
|
12
|
+
import { curveLinear as v, curveMonotoneX as y, line as b } from "d3-shape";
|
|
13
|
+
//#region src/ui/charts/line-chart.tsx
|
|
14
|
+
var x = d.forwardRef(({ data: d, xKey: x, series: S, curved: C = !1, showDots: w = !1, dotSize: T = 4, strokeWidth: E = 2, height: D = 300, showGrid: O = !0, showTooltip: k = !0, showLegend: A = !1, animate: j = !0, xLabel: M, yLabel: N, ariaLabel: P, className: F, ...I }, L) => {
|
|
15
|
+
let { tooltip: R, show: z, hide: B } = r(), V = o(), H = j && !V, U = S.map((e, t) => s(e.color, t));
|
|
16
|
+
return /* @__PURE__ */ m(h.div, {
|
|
17
|
+
ref: L,
|
|
18
|
+
className: n("relative", F),
|
|
19
|
+
...H ? {
|
|
20
|
+
initial: {
|
|
21
|
+
opacity: 0,
|
|
22
|
+
scale: .96
|
|
23
|
+
},
|
|
24
|
+
animate: {
|
|
25
|
+
opacity: 1,
|
|
26
|
+
scale: 1
|
|
27
|
+
},
|
|
28
|
+
transition: t.fade
|
|
29
|
+
} : {},
|
|
30
|
+
...e(I),
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ p(u, {
|
|
33
|
+
height: D,
|
|
34
|
+
ariaLabel: P ?? "Line chart",
|
|
35
|
+
children: ({ width: e, height: t, margin: n }) => {
|
|
36
|
+
let r = d.map((e) => e[x]), i = r.every((e) => typeof e == "number"), a, o;
|
|
37
|
+
if (i) {
|
|
38
|
+
let t = r, n = Math.min(...t), i = Math.max(...t), s = g().domain([n, i]).range([0, e]);
|
|
39
|
+
a = s, o = (e) => s(Number(e[x]));
|
|
40
|
+
} else {
|
|
41
|
+
let t = r.map(String), n = _().domain(t).range([0, e]).padding(.5);
|
|
42
|
+
a = n, o = (e) => n(String(e[x])) ?? 0;
|
|
43
|
+
}
|
|
44
|
+
let s = d.flatMap((e) => S.map((t) => Number(e[t.key]) || 0)), u = Math.max(...s), h = g().domain([0, u * 1.1]).range([t, 0]).nice(), D = C ? y : v, A = b().curve(D).defined((e) => e != null);
|
|
45
|
+
return /* @__PURE__ */ m(f, { children: [
|
|
46
|
+
/* @__PURE__ */ p("desc", { children: d.map((e) => `${String(e[x])} — ${S.map((t) => `${t.label}: ${Number(e[t.key]).toLocaleString()}`).join(", ")}`).join(". ") }),
|
|
47
|
+
O && /* @__PURE__ */ p(l, {
|
|
48
|
+
width: e,
|
|
49
|
+
height: t,
|
|
50
|
+
yScale: h,
|
|
51
|
+
horizontal: !0
|
|
52
|
+
}),
|
|
53
|
+
S.map((e, t) => /* @__PURE__ */ m("g", { children: [/* @__PURE__ */ p("path", {
|
|
54
|
+
d: A.x((e) => o(e)).y((t) => h(Number(t[e.key]) || 0))(d) ?? "",
|
|
55
|
+
fill: "none",
|
|
56
|
+
stroke: U[t],
|
|
57
|
+
strokeWidth: E,
|
|
58
|
+
strokeLinejoin: "round",
|
|
59
|
+
strokeLinecap: "round"
|
|
60
|
+
}), w && d.map((n, r) => /* @__PURE__ */ p("circle", {
|
|
61
|
+
cx: o(n),
|
|
62
|
+
cy: h(Number(n[e.key]) || 0),
|
|
63
|
+
r: T,
|
|
64
|
+
fill: U[t],
|
|
65
|
+
className: "transition-opacity hover:opacity-80"
|
|
66
|
+
}, `${e.key}-dot-${r}`))] }, e.key)),
|
|
67
|
+
k && d.map((n, r) => {
|
|
68
|
+
let i = o(n), a = e / Math.max(d.length - 1, 1), s = String(n[x]), c = `${s}: ${S.map((e) => `${e.label} ${Number(n[e.key]).toLocaleString()}`).join(", ")}`, l = /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("div", {
|
|
69
|
+
className: "font-medium",
|
|
70
|
+
children: s
|
|
71
|
+
}), S.map((e, t) => /* @__PURE__ */ m("div", {
|
|
72
|
+
className: "flex items-center gap-ds-02",
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ p("span", {
|
|
75
|
+
className: "inline-block h-2 w-2 rounded-pill",
|
|
76
|
+
style: { backgroundColor: U[t] }
|
|
77
|
+
}),
|
|
78
|
+
/* @__PURE__ */ m("span", {
|
|
79
|
+
className: "text-surface-fg-muted",
|
|
80
|
+
children: [e.label, ":"]
|
|
81
|
+
}),
|
|
82
|
+
" ",
|
|
83
|
+
Number(n[e.key]).toLocaleString()
|
|
84
|
+
]
|
|
85
|
+
}, e.key))] });
|
|
86
|
+
return /* @__PURE__ */ p("rect", {
|
|
87
|
+
x: i - a / 2,
|
|
88
|
+
y: 0,
|
|
89
|
+
width: a,
|
|
90
|
+
height: t,
|
|
91
|
+
fill: "transparent",
|
|
92
|
+
tabIndex: 0,
|
|
93
|
+
role: "graphics-symbol",
|
|
94
|
+
"aria-label": c,
|
|
95
|
+
className: "focus-visible:outline-hidden",
|
|
96
|
+
onMouseMove: (e) => {
|
|
97
|
+
let t = e.currentTarget.closest("div")?.getBoundingClientRect();
|
|
98
|
+
z(e.clientX - (t?.left ?? 0), e.clientY - (t?.top ?? 0), l);
|
|
99
|
+
},
|
|
100
|
+
onMouseLeave: B,
|
|
101
|
+
onFocus: (e) => {
|
|
102
|
+
let t = e.currentTarget.closest("div")?.getBoundingClientRect(), n = e.currentTarget.getBoundingClientRect();
|
|
103
|
+
z(n.left + n.width / 2 - (t?.left ?? 0), n.top + n.height / 2 - (t?.top ?? 0), l);
|
|
104
|
+
},
|
|
105
|
+
onBlur: B
|
|
106
|
+
}, `hover-${r}`);
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ p(c, {
|
|
109
|
+
scale: a,
|
|
110
|
+
orientation: "bottom",
|
|
111
|
+
transform: `translate(0,${t})`,
|
|
112
|
+
label: M
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ p(c, {
|
|
115
|
+
scale: h,
|
|
116
|
+
orientation: "left",
|
|
117
|
+
label: N
|
|
118
|
+
})
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
121
|
+
}),
|
|
122
|
+
k && /* @__PURE__ */ p(a, { state: R }),
|
|
123
|
+
A && S.length > 1 && /* @__PURE__ */ p(i, {
|
|
124
|
+
items: S.map((e, t) => ({
|
|
125
|
+
label: e.label,
|
|
126
|
+
color: U[t]
|
|
127
|
+
})),
|
|
128
|
+
className: "mt-ds-04"
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
x.displayName = "LineChart";
|
|
134
|
+
//#endregion
|
|
135
|
+
export { x as LineChart };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-chart.js","names":[],"sources":["../../../src/ui/charts/line-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { ScaleLinear, ScalePoint } from 'd3-scale'\nimport { scaleLinear, scalePoint } from 'd3-scale'\nimport { curveLinear,curveMonotoneX, line } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { type AnyScale,Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { DataPoint, Series } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface LineChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis */\n xKey: string\n /** Series definitions — each becomes a line */\n series: Series[]\n /** Use curved (monotone) interpolation */\n curved?: boolean\n /** Show dots at data points */\n showDots?: boolean\n /** Dot radius */\n dotSize?: number\n /** Line stroke width */\n strokeWidth?: number\n /** Chart height */\n height?: number\n /** Show grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(\n (\n {\n data,\n xKey,\n series,\n curved = false,\n showDots = false,\n dotSize = 4,\n strokeWidth = 2,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n xLabel,\n yLabel,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Line chart'}>\n {({ width, height: innerHeight, margin }) => {\n void margin\n\n // Determine if x-axis data is numeric or categorical\n const xValues = data.map((d) => d[xKey])\n const isNumericX = xValues.every((v) => typeof v === 'number')\n\n // Build x scale and accessor\n let xAxisScale: ScaleLinear<number, number> | ScalePoint<string>\n let getX: (d: DataPoint) => number\n\n if (isNumericX) {\n const numericValues = xValues as number[]\n const xMin = Math.min(...numericValues)\n const xMax = Math.max(...numericValues)\n const linearX = scaleLinear<number, number>()\n .domain([xMin, xMax])\n .range([0, width])\n xAxisScale = linearX\n getX = (d: DataPoint) => linearX(Number(d[xKey]))\n } else {\n const categories = xValues.map(String)\n const pointX = scalePoint<string>()\n .domain(categories)\n .range([0, width])\n .padding(0.5)\n xAxisScale = pointX\n getX = (d: DataPoint) => pointX(String(d[xKey])) ?? 0\n }\n\n // Build y scale across all series\n const allValues = data.flatMap((d) =>\n series.map((s) => Number(d[s.key]) || 0),\n )\n const yMax = Math.max(...allValues)\n const yScale = scaleLinear<number, number>()\n .domain([0, yMax * 1.1])\n .range([innerHeight, 0])\n .nice()\n\n // Line generator\n const curveType = curved ? curveMonotoneX : curveLinear\n const lineGen = line<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n // Build data summary for screen readers\n const dataSummary = data.map((d) => {\n const xVal = String(d[xKey])\n const vals = series.map((s) =>\n `${s.label}: ${Number(d[s.key]).toLocaleString()}`\n ).join(', ')\n return `${xVal} — ${vals}`\n }).join('. ')\n\n return (\n <>\n {/* Screen-reader data summary */}\n <desc>{dataSummary}</desc>\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Lines */}\n {series.map((s, seriesIdx) => {\n const pathGen = lineGen\n .x((d) => getX(d))\n .y((d) => yScale(Number(d[s.key]) || 0))\n\n const pathD = pathGen(data) ?? ''\n\n return (\n <g key={s.key}>\n {/* Line path */}\n <path\n d={pathD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n\n {/* Data point dots */}\n {showDots &&\n data.map((d, i) => {\n const cx = getX(d)\n const cy = yScale(Number(d[s.key]) || 0)\n return (\n <circle\n key={`${s.key}-dot-${i}`}\n cx={cx}\n cy={cy}\n r={dotSize}\n fill={colors[seriesIdx]}\n className=\"transition-opacity hover:opacity-80\"\n />\n )\n })}\n </g>\n )\n })}\n\n {/* Invisible hover/focus rectangles for tooltip */}\n {showTooltip &&\n data.map((d, i) => {\n const cx = getX(d)\n const sliceWidth = width / Math.max(data.length - 1, 1)\n const xVal = String(d[xKey])\n const pointAriaLabel = `${xVal}: ${series.map((s) => `${s.label} ${Number(d[s.key]).toLocaleString()}`).join(', ')}`\n\n const tooltipContent = (\n <div>\n <div className=\"font-medium\">{xVal}</div>\n {series.map((s, sIdx) => (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {Number(d[s.key]).toLocaleString()}\n </div>\n ))}\n </div>\n )\n\n return (\n <rect\n key={`hover-${i}`}\n x={cx - sliceWidth / 2}\n y={0}\n width={sliceWidth}\n height={innerHeight}\n fill=\"transparent\"\n tabIndex={0}\n role=\"graphics-symbol\"\n aria-label={pointAriaLabel}\n className=\"focus-visible:outline-hidden\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n tooltipContent,\n )\n }}\n onMouseLeave={hide}\n onFocus={(e) => {\n const svgRect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const sliceRect = e.currentTarget.getBoundingClientRect()\n show(\n sliceRect.left + sliceRect.width / 2 - (svgRect?.left ?? 0),\n sliceRect.top + sliceRect.height / 2 - (svgRect?.top ?? 0),\n tooltipContent,\n )\n }}\n onBlur={hide}\n />\n )\n })}\n\n {/* Axes */}\n <Axis\n scale={xAxisScale as AnyScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={yScale} orientation=\"left\" label={yLabel} />\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && series.length > 1 && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nLineChart.displayName = 'LineChart'\n"],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { motionProps as e, tweens as t } from "../lib/motion.js";
|
|
3
|
+
import { cn as n } from "../lib/utils.js";
|
|
4
|
+
import { n as r, r as i, t as a } from "../../_chunks/tooltip.js";
|
|
5
|
+
import { r as o, t as s } from "../../_chunks/colors.js";
|
|
6
|
+
import * as c from "react";
|
|
7
|
+
import { useEffect as l, useRef as u, useState as d } from "react";
|
|
8
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
9
|
+
import { motion as h } from "framer-motion";
|
|
10
|
+
import { arc as g, pie as _ } from "d3-shape";
|
|
11
|
+
//#region src/ui/charts/pie-chart.tsx
|
|
12
|
+
var v = c.forwardRef(({ data: c, variant: v = "pie", innerRadius: y = .6, padAngle: b = 0, cornerRadius: x = 0, height: S = 300, showTooltip: C = !0, showLegend: w = !1, showLabels: T = !1, animate: E = !0, className: D, centerLabel: O, ariaLabel: k, ...A }, j) => {
|
|
13
|
+
let M = u(null), [N, P] = d(0), [F, I] = d(null), { tooltip: L, show: R, hide: z } = r(), B = o(), V = E && !B;
|
|
14
|
+
l(() => {
|
|
15
|
+
if (!M.current) return;
|
|
16
|
+
let e = new ResizeObserver((e) => {
|
|
17
|
+
let t = e[0];
|
|
18
|
+
t && P(t.contentRect.width);
|
|
19
|
+
});
|
|
20
|
+
return e.observe(M.current), () => e.disconnect();
|
|
21
|
+
}, []);
|
|
22
|
+
let H = (N > 0 ? Math.min(N, S) : S) / 2, U = v === "donut" ? H * y : 0, W = c.map((e, t) => s(e.color, t)), G = c.reduce((e, t) => e + t.value, 0), K = _().value((e) => e.value).padAngle(b).sort(null)(c), q = g().innerRadius(U).outerRadius(H - 2).cornerRadius(x), J = U + (H - 2 - U) * .7, Y = g().innerRadius(J).outerRadius(J);
|
|
23
|
+
return /* @__PURE__ */ m(h.div, {
|
|
24
|
+
ref: (e) => {
|
|
25
|
+
M.current = e, typeof j == "function" ? j(e) : j && (j.current = e);
|
|
26
|
+
},
|
|
27
|
+
className: n("relative w-full", D),
|
|
28
|
+
...V ? {
|
|
29
|
+
initial: {
|
|
30
|
+
opacity: 0,
|
|
31
|
+
scale: .96
|
|
32
|
+
},
|
|
33
|
+
animate: {
|
|
34
|
+
opacity: 1,
|
|
35
|
+
scale: 1
|
|
36
|
+
},
|
|
37
|
+
transition: t.fade
|
|
38
|
+
} : {},
|
|
39
|
+
...e(A),
|
|
40
|
+
children: [N > 0 && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("svg", {
|
|
41
|
+
width: N,
|
|
42
|
+
height: S,
|
|
43
|
+
role: "img",
|
|
44
|
+
"aria-label": k ?? "Pie chart",
|
|
45
|
+
children: /* @__PURE__ */ m("g", {
|
|
46
|
+
transform: `translate(${N / 2},${S / 2})`,
|
|
47
|
+
children: [
|
|
48
|
+
K.map((e, t) => {
|
|
49
|
+
let n = q(e);
|
|
50
|
+
if (!n) return null;
|
|
51
|
+
let [r, i] = q.centroid(e), a = Math.atan2(i, r), o = Math.cos(a) * 4, s = Math.sin(a) * 4, c = F === t;
|
|
52
|
+
return /* @__PURE__ */ p("path", {
|
|
53
|
+
d: n,
|
|
54
|
+
fill: W[t],
|
|
55
|
+
className: "cursor-pointer transition-transform",
|
|
56
|
+
style: { transform: c ? `translate(${o}px, ${s}px)` : void 0 },
|
|
57
|
+
onMouseEnter: () => I(t),
|
|
58
|
+
onMouseMove: (t) => {
|
|
59
|
+
if (C) {
|
|
60
|
+
let n = t.currentTarget.closest("div")?.getBoundingClientRect(), r = G > 0 ? (e.data.value / G * 100).toFixed(1) : "0";
|
|
61
|
+
R(t.clientX - (n?.left ?? 0), t.clientY - (n?.top ?? 0), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("div", {
|
|
62
|
+
className: "font-medium",
|
|
63
|
+
children: e.data.label
|
|
64
|
+
}), /* @__PURE__ */ m("div", { children: [
|
|
65
|
+
e.data.value.toLocaleString(),
|
|
66
|
+
" (",
|
|
67
|
+
r,
|
|
68
|
+
"%)"
|
|
69
|
+
] })] }));
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
onMouseLeave: () => {
|
|
73
|
+
I(null), z();
|
|
74
|
+
}
|
|
75
|
+
}, `slice-${e.data.label}-${t}`);
|
|
76
|
+
}),
|
|
77
|
+
T && K.map((e, t) => {
|
|
78
|
+
let [n, r] = Y.centroid(e), i = G > 0 ? (e.data.value / G * 100).toFixed(0) : "0";
|
|
79
|
+
return G > 0 && e.data.value / G < .03 ? null : /* @__PURE__ */ m("text", {
|
|
80
|
+
x: n,
|
|
81
|
+
y: r,
|
|
82
|
+
textAnchor: "middle",
|
|
83
|
+
dominantBaseline: "central",
|
|
84
|
+
className: "pointer-events-none fill-accent-fg text-ds-xs font-medium",
|
|
85
|
+
children: [i, "%"]
|
|
86
|
+
}, `label-${e.data.label}-${t}`);
|
|
87
|
+
}),
|
|
88
|
+
v === "donut" && O && U > 0 && /* @__PURE__ */ p("foreignObject", {
|
|
89
|
+
x: -U * .7,
|
|
90
|
+
y: -U * .7,
|
|
91
|
+
width: U * 1.4,
|
|
92
|
+
height: U * 1.4,
|
|
93
|
+
children: /* @__PURE__ */ p("div", {
|
|
94
|
+
className: "flex h-full w-full items-center justify-center text-center text-surface-fg",
|
|
95
|
+
children: O
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
]
|
|
99
|
+
})
|
|
100
|
+
}), C && /* @__PURE__ */ p(a, { state: L })] }), w && /* @__PURE__ */ p(i, {
|
|
101
|
+
items: c.map((e, t) => ({
|
|
102
|
+
label: e.label,
|
|
103
|
+
color: W[t]
|
|
104
|
+
})),
|
|
105
|
+
className: "mt-ds-04"
|
|
106
|
+
})]
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
v.displayName = "PieChart";
|
|
110
|
+
//#endregion
|
|
111
|
+
export { v as PieChart };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/ui/charts/pie-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { PieArcDatum } from 'd3-shape'\nimport { arc as d3Arc,pie as d3Pie } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\nimport { useEffect,useRef, useState } from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\n\ninterface PieSlice {\n label: string\n value: number\n color?: string\n}\n\nexport interface PieChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data with label and value */\n data: PieSlice[]\n /** Pie or donut variant */\n variant?: 'pie' | 'donut'\n /** Inner radius ratio for donut (0-1, default 0.6) */\n innerRadius?: number\n /** Gap angle between slices in radians */\n padAngle?: number\n /** Corner radius for slice edges */\n cornerRadius?: number\n /** Chart height (and width, since pie is square) */\n height?: number\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Show percentage labels on/near slices */\n showLabels?: boolean\n /** Animate slices */\n animate?: boolean\n className?: string\n /** Content to show in center of donut */\n centerLabel?: React.ReactNode\n /** Accessible label for the chart */\n ariaLabel?: string\n}\n\nexport const PieChart = React.forwardRef<HTMLDivElement, PieChartProps>(\n (\n {\n data,\n variant = 'pie',\n innerRadius: innerRadiusRatio = 0.6,\n padAngle = 0,\n cornerRadius = 0,\n height = 300,\n showTooltip = true,\n showLegend = false,\n showLabels = false,\n animate = true,\n className,\n centerLabel,\n ariaLabel,\n ...props\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [containerWidth, setContainerWidth] = useState(0)\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n useEffect(() => {\n if (!containerRef.current) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) setContainerWidth(entry.contentRect.width)\n })\n observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [])\n\n // Pie chart is square — use the smaller of width/height\n const size = containerWidth > 0 ? Math.min(containerWidth, height) : height\n const outerRadius = size / 2\n const innerR = variant === 'donut' ? outerRadius * innerRadiusRatio : 0\n\n // Resolve colors for each slice\n const colors = data.map((d, i) => resolveColor(d.color, i))\n\n // Compute total for percentages\n const total = data.reduce((sum, d) => sum + d.value, 0)\n\n // D3 pie layout\n const pieLayout = d3Pie<PieSlice>()\n .value((d) => d.value)\n .padAngle(padAngle)\n .sort(null)\n\n const arcs = pieLayout(data)\n\n // D3 arc generator\n const arcGenerator = d3Arc<PieArcDatum<PieSlice>>()\n .innerRadius(innerR)\n .outerRadius(outerRadius - 2) // slight inset so hover offset doesn't clip\n .cornerRadius(cornerRadius)\n\n // Label arc — position labels at 70% of the way from inner to outer radius\n const labelRadius = innerR + (outerRadius - 2 - innerR) * 0.7\n const labelArc = d3Arc<PieArcDatum<PieSlice>>()\n .innerRadius(labelRadius)\n .outerRadius(labelRadius)\n\n return (\n <motion.div\n ref={(node) => {\n (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n className={cn('relative w-full', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n {containerWidth > 0 && (\n <>\n <svg\n width={containerWidth}\n height={height}\n role=\"img\"\n aria-label={ariaLabel ?? 'Pie chart'}\n >\n <g transform={`translate(${containerWidth / 2},${height / 2})`}>\n {arcs.map((d, i) => {\n const path = arcGenerator(d)\n if (!path) return null\n\n // Hover offset: push slice outward along its centroid angle\n const [cx, cy] = arcGenerator.centroid(d)\n const angle = Math.atan2(cy, cx)\n const offsetX = Math.cos(angle) * 4\n const offsetY = Math.sin(angle) * 4\n const isHovered = hoveredIndex === i\n\n return (\n <path\n key={`slice-${d.data.label}-${i}`}\n d={path}\n fill={colors[i]}\n className=\"cursor-pointer transition-transform\"\n style={{\n transform: isHovered\n ? `translate(${offsetX}px, ${offsetY}px)`\n : undefined,\n }}\n onMouseEnter={() => setHoveredIndex(i)}\n onMouseMove={(e) => {\n if (showTooltip) {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const pct =\n total > 0\n ? ((d.data.value / total) * 100).toFixed(1)\n : '0'\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">{d.data.label}</div>\n <div>\n {d.data.value.toLocaleString()} ({pct}%)\n </div>\n </div>,\n )\n }\n }}\n onMouseLeave={() => {\n setHoveredIndex(null)\n hide()\n }}\n />\n )\n })}\n\n {/* Percentage labels */}\n {showLabels &&\n arcs.map((d, i) => {\n const [lx, ly] = labelArc.centroid(d)\n const pct =\n total > 0\n ? ((d.data.value / total) * 100).toFixed(0)\n : '0'\n\n // Skip tiny slices (< 3%) to avoid label overlap\n if (total > 0 && d.data.value / total < 0.03) return null\n\n return (\n <text\n key={`label-${d.data.label}-${i}`}\n x={lx}\n y={ly}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"pointer-events-none fill-accent-fg text-ds-xs font-medium\"\n >\n {pct}%\n </text>\n )\n })}\n\n {/* Center label for donut variant */}\n {variant === 'donut' && centerLabel && innerR > 0 && (\n <foreignObject\n x={-innerR * 0.7}\n y={-innerR * 0.7}\n width={innerR * 1.4}\n height={innerR * 1.4}\n >\n <div className=\"flex h-full w-full items-center justify-center text-center text-surface-fg\">\n {centerLabel}\n </div>\n </foreignObject>\n )}\n </g>\n </svg>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n </>\n )}\n\n {/* Legend */}\n {showLegend && (\n <Legend\n items={data.map((d, i) => ({\n label: d.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nPieChart.displayName = 'PieChart'\n"],"mappings":"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"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { motionProps as e, tweens as t } from "../lib/motion.js";
|
|
3
|
+
import { cn as n } from "../lib/utils.js";
|
|
4
|
+
import { n as r, r as i, t as a } from "../../_chunks/tooltip.js";
|
|
5
|
+
import { r as o, t as s } from "../../_chunks/colors.js";
|
|
6
|
+
import * as c from "react";
|
|
7
|
+
import { useEffect as l, useRef as u, useState as d } from "react";
|
|
8
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
9
|
+
import { motion as h } from "framer-motion";
|
|
10
|
+
import { curveLinearClosed as g, lineRadial as _ } from "d3-shape";
|
|
11
|
+
//#region src/ui/charts/radar-chart.tsx
|
|
12
|
+
var v = c.forwardRef(({ data: c, axes: v, series: y, maxValue: b, levels: x = 5, fillOpacity: S = .25, showDots: C = !1, height: w = 300, showTooltip: T = !0, showLegend: E = !1, animate: D = !0, ariaLabel: O, className: k, ...A }, j) => {
|
|
13
|
+
let M = u(null), [N, P] = d(0), { tooltip: F, show: I, hide: L } = r(), R = o(), z = D && !R;
|
|
14
|
+
l(() => {
|
|
15
|
+
if (!M.current) return;
|
|
16
|
+
let e = new ResizeObserver((e) => {
|
|
17
|
+
let t = e[0];
|
|
18
|
+
t && P(t.contentRect.width);
|
|
19
|
+
});
|
|
20
|
+
return e.observe(M.current), () => e.disconnect();
|
|
21
|
+
}, []);
|
|
22
|
+
let B = (N > 0 ? Math.min(N, w) : w) / 2 - 40, V = y.map((e, t) => s(e.color, t)), H = b ?? Math.max(...c.flatMap((e) => y.map((t) => Number(e[t.key]) || 0)), 1), U = 2 * Math.PI / v.length, W = _().radius((e) => B * e / H).angle((e, t) => t * U).curve(g), G = (e) => v.map((t, n) => Number(c[n]?.[e]) || 0), K = (e, t) => {
|
|
23
|
+
let n = U * e - Math.PI / 2, r = B * t / H;
|
|
24
|
+
return {
|
|
25
|
+
x: r * Math.cos(n),
|
|
26
|
+
y: r * Math.sin(n)
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
return /* @__PURE__ */ m(h.div, {
|
|
30
|
+
ref: (e) => {
|
|
31
|
+
M.current = e, typeof j == "function" ? j(e) : j && (j.current = e);
|
|
32
|
+
},
|
|
33
|
+
className: n("relative w-full", k),
|
|
34
|
+
...z ? {
|
|
35
|
+
initial: {
|
|
36
|
+
opacity: 0,
|
|
37
|
+
scale: .96
|
|
38
|
+
},
|
|
39
|
+
animate: {
|
|
40
|
+
opacity: 1,
|
|
41
|
+
scale: 1
|
|
42
|
+
},
|
|
43
|
+
transition: t.fade
|
|
44
|
+
} : {},
|
|
45
|
+
...e(A),
|
|
46
|
+
children: [N > 0 && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("svg", {
|
|
47
|
+
width: N,
|
|
48
|
+
height: w,
|
|
49
|
+
role: "img",
|
|
50
|
+
"aria-label": O ?? "Radar chart",
|
|
51
|
+
children: /* @__PURE__ */ m("g", {
|
|
52
|
+
transform: `translate(${N / 2},${w / 2})`,
|
|
53
|
+
children: [
|
|
54
|
+
Array.from({ length: x }, (e, t) => {
|
|
55
|
+
let n = B / x * (t + 1);
|
|
56
|
+
return /* @__PURE__ */ p("polygon", {
|
|
57
|
+
points: v.map((e, t) => {
|
|
58
|
+
let r = U * t - Math.PI / 2;
|
|
59
|
+
return `${n * Math.cos(r)},${n * Math.sin(r)}`;
|
|
60
|
+
}).join(" "),
|
|
61
|
+
fill: "none",
|
|
62
|
+
stroke: "var(--color-surface-border)",
|
|
63
|
+
strokeDasharray: "3,3",
|
|
64
|
+
strokeWidth: 1
|
|
65
|
+
}, `grid-${t}`);
|
|
66
|
+
}),
|
|
67
|
+
v.map((e, t) => {
|
|
68
|
+
let n = U * t - Math.PI / 2;
|
|
69
|
+
return /* @__PURE__ */ p("line", {
|
|
70
|
+
x1: 0,
|
|
71
|
+
y1: 0,
|
|
72
|
+
x2: B * Math.cos(n),
|
|
73
|
+
y2: B * Math.sin(n),
|
|
74
|
+
stroke: "var(--color-surface-border)",
|
|
75
|
+
strokeWidth: 1
|
|
76
|
+
}, `axis-${t}`);
|
|
77
|
+
}),
|
|
78
|
+
v.map((e, t) => {
|
|
79
|
+
let n = U * t - Math.PI / 2, r = B + 18, i = r * Math.cos(n), a = r * Math.sin(n), o = "middle";
|
|
80
|
+
return Math.abs(Math.cos(n)) > .1 && (o = Math.cos(n) > 0 ? "start" : "end"), /* @__PURE__ */ p("text", {
|
|
81
|
+
x: i,
|
|
82
|
+
y: a,
|
|
83
|
+
textAnchor: o,
|
|
84
|
+
dominantBaseline: "central",
|
|
85
|
+
className: "fill-surface-fg-muted text-ds-xs",
|
|
86
|
+
children: e
|
|
87
|
+
}, `label-${t}`);
|
|
88
|
+
}),
|
|
89
|
+
Array.from({ length: x }, (e, t) => {
|
|
90
|
+
let n = Math.round(H / x * (t + 1)), r = B / x * (t + 1), i = -Math.PI / 2;
|
|
91
|
+
return /* @__PURE__ */ p("text", {
|
|
92
|
+
x: r * Math.cos(i) + 4,
|
|
93
|
+
y: r * Math.sin(i),
|
|
94
|
+
textAnchor: "start",
|
|
95
|
+
dominantBaseline: "auto",
|
|
96
|
+
className: "fill-surface-fg-subtle text-ds-xs",
|
|
97
|
+
children: n
|
|
98
|
+
}, `level-label-${t}`);
|
|
99
|
+
}),
|
|
100
|
+
y.map((e, t) => {
|
|
101
|
+
let n = G(e.key), r = W(n);
|
|
102
|
+
return r ? /* @__PURE__ */ m("g", { children: [/* @__PURE__ */ p("path", {
|
|
103
|
+
d: r,
|
|
104
|
+
fill: V[t],
|
|
105
|
+
fillOpacity: S,
|
|
106
|
+
stroke: V[t],
|
|
107
|
+
strokeWidth: 2,
|
|
108
|
+
strokeLinejoin: "round"
|
|
109
|
+
}), C && n.map((n, r) => {
|
|
110
|
+
let { x: i, y: a } = K(r, n);
|
|
111
|
+
return /* @__PURE__ */ p("circle", {
|
|
112
|
+
cx: i,
|
|
113
|
+
cy: a,
|
|
114
|
+
r: 4,
|
|
115
|
+
fill: V[t],
|
|
116
|
+
stroke: "var(--color-surface-base)",
|
|
117
|
+
strokeWidth: 2,
|
|
118
|
+
className: "transition-opacity"
|
|
119
|
+
}, `dot-${e.key}-${r}`);
|
|
120
|
+
})] }, e.key) : null;
|
|
121
|
+
}),
|
|
122
|
+
T && v.map((e, t) => {
|
|
123
|
+
let n = U * t - Math.PI / 2;
|
|
124
|
+
return /* @__PURE__ */ p("circle", {
|
|
125
|
+
cx: B * Math.cos(n),
|
|
126
|
+
cy: B * Math.sin(n),
|
|
127
|
+
r: 16,
|
|
128
|
+
fill: "transparent",
|
|
129
|
+
className: "cursor-pointer",
|
|
130
|
+
onMouseMove: (n) => {
|
|
131
|
+
let r = n.currentTarget.closest("div")?.getBoundingClientRect();
|
|
132
|
+
I(n.clientX - (r?.left ?? 0), n.clientY - (r?.top ?? 0), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("div", {
|
|
133
|
+
className: "font-medium",
|
|
134
|
+
children: e
|
|
135
|
+
}), y.map((e, n) => {
|
|
136
|
+
let r = Number(c[t]?.[e.key]) || 0;
|
|
137
|
+
return /* @__PURE__ */ m("div", {
|
|
138
|
+
className: "flex items-center gap-ds-02",
|
|
139
|
+
children: [
|
|
140
|
+
/* @__PURE__ */ p("span", {
|
|
141
|
+
className: "inline-block h-2 w-2 rounded-pill",
|
|
142
|
+
style: { backgroundColor: V[n] }
|
|
143
|
+
}),
|
|
144
|
+
/* @__PURE__ */ m("span", {
|
|
145
|
+
className: "text-surface-fg-muted",
|
|
146
|
+
children: [e.label, ":"]
|
|
147
|
+
}),
|
|
148
|
+
" ",
|
|
149
|
+
r.toLocaleString()
|
|
150
|
+
]
|
|
151
|
+
}, e.key);
|
|
152
|
+
})] }));
|
|
153
|
+
},
|
|
154
|
+
onMouseLeave: L
|
|
155
|
+
}, `hover-${t}`);
|
|
156
|
+
})
|
|
157
|
+
]
|
|
158
|
+
})
|
|
159
|
+
}), T && /* @__PURE__ */ p(a, { state: F })] }), E && /* @__PURE__ */ p(i, {
|
|
160
|
+
items: y.map((e, t) => ({
|
|
161
|
+
label: e.label,
|
|
162
|
+
color: V[t]
|
|
163
|
+
})),
|
|
164
|
+
className: "mt-ds-04"
|
|
165
|
+
})]
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
v.displayName = "RadarChart";
|
|
169
|
+
//#endregion
|
|
170
|
+
export { v as RadarChart };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radar-chart.js","names":[],"sources":["../../../src/ui/charts/radar-chart.tsx"],"sourcesContent":["'use client'\n\nimport { curveLinearClosed,lineRadial } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\nimport { useEffect,useRef, useState } from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\n\nexport interface RadarChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array (one entry per data point / axis) */\n data: Record<string, string | number>[]\n /** Axis labels (3-8 axes) */\n axes: string[]\n /** Series to plot */\n series: { key: string; label: string; color?: string }[]\n /** Max value (auto-detect if not set) */\n maxValue?: number\n /** Number of concentric grid rings (default: 5) */\n levels?: number\n /** Fill opacity for the data polygon (default: 0.25) */\n fillOpacity?: number\n /** Show dots at vertices */\n showDots?: boolean\n /** Chart height (default: 300) */\n height?: number\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(\n (\n {\n data,\n axes,\n series,\n maxValue: maxValueProp,\n levels = 5,\n fillOpacity = 0.25,\n showDots = false,\n height = 300,\n showTooltip = true,\n showLegend = false,\n animate = true,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [containerWidth, setContainerWidth] = useState(0)\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n useEffect(() => {\n if (!containerRef.current) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) setContainerWidth(entry.contentRect.width)\n })\n observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [])\n\n // Radar chart is square — use the smaller of width/height\n const svgSize = containerWidth > 0 ? Math.min(containerWidth, height) : height\n const radius = svgSize / 2 - 40 // leave room for labels\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n // Auto-detect maxValue if not provided\n const maxValue =\n maxValueProp ??\n Math.max(\n ...data.flatMap((d) => series.map((s) => Number(d[s.key]) || 0)),\n 1,\n )\n\n // Angle per axis slice\n const angleSlice = (2 * Math.PI) / axes.length\n\n // D3 radial line generator for the data polygon\n const radarLine = lineRadial<number>()\n .radius((d) => (radius * d) / maxValue)\n .angle((_, i) => i * angleSlice)\n .curve(curveLinearClosed)\n\n // Convert a data row into an array of values aligned with axes\n const getSeriesValues = (seriesKey: string): number[] =>\n axes.map((_, i) => Number(data[i]?.[seriesKey]) || 0)\n\n // Convert polar to cartesian for a given axis index and value\n const polarToXY = (axisIndex: number, value: number) => {\n const angle = angleSlice * axisIndex - Math.PI / 2\n const r = (radius * value) / maxValue\n return {\n x: r * Math.cos(angle),\n y: r * Math.sin(angle),\n }\n }\n\n return (\n <motion.div\n ref={(node) => {\n (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n className={cn('relative w-full', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n {containerWidth > 0 && (\n <>\n <svg\n width={containerWidth}\n height={height}\n role=\"img\"\n aria-label={ariaLabel ?? 'Radar chart'}\n >\n <g transform={`translate(${containerWidth / 2},${height / 2})`}>\n {/* Concentric grid polygons */}\n {Array.from({ length: levels }, (_, i) => {\n const levelRadius = (radius / levels) * (i + 1)\n const points = axes\n .map((_, j) => {\n const angle = angleSlice * j - Math.PI / 2\n return `${levelRadius * Math.cos(angle)},${levelRadius * Math.sin(angle)}`\n })\n .join(' ')\n return (\n <polygon\n key={`grid-${i}`}\n points={points}\n fill=\"none\"\n stroke=\"var(--color-surface-border)\"\n strokeDasharray=\"3,3\"\n strokeWidth={1}\n />\n )\n })}\n\n {/* Axis lines from center to outer edge */}\n {axes.map((_, i) => {\n const angle = angleSlice * i - Math.PI / 2\n const x = radius * Math.cos(angle)\n const y = radius * Math.sin(angle)\n return (\n <line\n key={`axis-${i}`}\n x1={0}\n y1={0}\n x2={x}\n y2={y}\n stroke=\"var(--color-surface-border)\"\n strokeWidth={1}\n />\n )\n })}\n\n {/* Axis labels */}\n {axes.map((label, i) => {\n const angle = angleSlice * i - Math.PI / 2\n const labelRadius = radius + 18\n const x = labelRadius * Math.cos(angle)\n const y = labelRadius * Math.sin(angle)\n\n // Determine text-anchor based on position\n let textAnchor: 'start' | 'middle' | 'end' = 'middle'\n if (Math.abs(Math.cos(angle)) > 0.1) {\n textAnchor = Math.cos(angle) > 0 ? 'start' : 'end'\n }\n\n return (\n <text\n key={`label-${i}`}\n x={x}\n y={y}\n textAnchor={textAnchor}\n dominantBaseline=\"central\"\n className=\"fill-surface-fg-muted text-ds-xs\"\n >\n {label}\n </text>\n )\n })}\n\n {/* Level value labels on the first axis */}\n {Array.from({ length: levels }, (_, i) => {\n const levelValue = Math.round((maxValue / levels) * (i + 1))\n const levelRadius = (radius / levels) * (i + 1)\n const angle = -Math.PI / 2 // first axis is at top\n const x = levelRadius * Math.cos(angle) + 4\n const y = levelRadius * Math.sin(angle)\n return (\n <text\n key={`level-label-${i}`}\n x={x}\n y={y}\n textAnchor=\"start\"\n dominantBaseline=\"auto\"\n className=\"fill-surface-fg-subtle text-ds-xs\"\n >\n {levelValue}\n </text>\n )\n })}\n\n {/* Data polygons — one per series */}\n {series.map((s, seriesIdx) => {\n const values = getSeriesValues(s.key)\n const pathD = radarLine(values)\n if (!pathD) return null\n\n return (\n <g key={s.key}>\n <path\n d={pathD}\n fill={colors[seriesIdx]}\n fillOpacity={fillOpacity}\n stroke={colors[seriesIdx]}\n strokeWidth={2}\n strokeLinejoin=\"round\"\n />\n\n {/* Vertex dots */}\n {showDots &&\n values.map((v, i) => {\n const { x, y } = polarToXY(i, v)\n return (\n <circle\n key={`dot-${s.key}-${i}`}\n cx={x}\n cy={y}\n r={4}\n fill={colors[seriesIdx]}\n stroke=\"var(--color-surface-base)\"\n strokeWidth={2}\n className=\"transition-opacity\"\n />\n )\n })}\n </g>\n )\n })}\n\n {/* Invisible hover areas at each vertex for tooltips */}\n {showTooltip &&\n axes.map((axisLabel, i) => {\n // Place a transparent circle at the outermost series point\n // for hit detection. Use the max value point for the axis.\n const angle = angleSlice * i - Math.PI / 2\n const hitX = radius * Math.cos(angle)\n const hitY = radius * Math.sin(angle)\n\n return (\n <circle\n key={`hover-${i}`}\n cx={hitX}\n cy={hitY}\n r={16}\n fill=\"transparent\"\n className=\"cursor-pointer\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">{axisLabel}</div>\n {series.map((s, sIdx) => {\n const val = Number(data[i]?.[s.key]) || 0\n return (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {val.toLocaleString()}\n </div>\n )\n })}\n </div>,\n )\n }}\n onMouseLeave={hide}\n />\n )\n })}\n </g>\n </svg>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n </>\n )}\n\n {/* Legend */}\n {showLegend && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nRadarChart.displayName = 'RadarChart'\n"],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../lib/utils.js";
|
|
3
|
+
import { r as t, t as n } from "../../_chunks/colors.js";
|
|
4
|
+
import * as r from "react";
|
|
5
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
6
|
+
import { motion as o } from "framer-motion";
|
|
7
|
+
import { scaleLinear as s } from "d3-scale";
|
|
8
|
+
import { area as c, curveMonotoneX as l, line as u } from "d3-shape";
|
|
9
|
+
//#region src/ui/charts/sparkline.tsx
|
|
10
|
+
var d = {
|
|
11
|
+
duration: 1,
|
|
12
|
+
ease: "easeOut"
|
|
13
|
+
}, f = r.forwardRef(({ data: r, variant: f = "line", width: p = 120, height: m = 32, color: h, showLastDot: g = !1, strokeWidth: _ = 1.5, animate: v = !0, className: y, ...b }, x) => {
|
|
14
|
+
let S = n(h, 0), C = t(), w = v && !C;
|
|
15
|
+
if (!r.length) return null;
|
|
16
|
+
let T = f === "bar" ? 1 : _, E = p - T * 2, D = m - T * 2, O = s().domain([0, Math.max(r.length - 1, 1)]).range([T, T + E]), k = Math.min(...r), A = Math.max(...r), j = k === A ? [k - 1, A + 1] : [k, A], M = s().domain(j).range([T + D, T]);
|
|
17
|
+
if (f === "bar") {
|
|
18
|
+
let t = Math.max(1, (E - 1 * (r.length - 1)) / r.length), n = T + D;
|
|
19
|
+
return /* @__PURE__ */ i("svg", {
|
|
20
|
+
ref: x,
|
|
21
|
+
width: p,
|
|
22
|
+
height: m,
|
|
23
|
+
role: "img",
|
|
24
|
+
"aria-label": "Sparkline bar chart",
|
|
25
|
+
className: e("inline-block align-middle", y),
|
|
26
|
+
...b,
|
|
27
|
+
children: r.map((e, r) => {
|
|
28
|
+
let a = T + r * (t + 1), o = M(e);
|
|
29
|
+
return /* @__PURE__ */ i("rect", {
|
|
30
|
+
x: a,
|
|
31
|
+
y: o,
|
|
32
|
+
width: t,
|
|
33
|
+
height: Math.max(1, n - o),
|
|
34
|
+
rx: Math.min(1, t / 2),
|
|
35
|
+
fill: S
|
|
36
|
+
}, r);
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (f === "area") {
|
|
41
|
+
let t = c().curve(l).x((e, t) => O(t)).y0(T + D).y1((e) => M(e)), n = u().curve(l).x((e, t) => O(t)).y((e) => M(e)), s = t(r) ?? "", f = n(r) ?? "", h = O(r.length - 1), v = M(r[r.length - 1]);
|
|
42
|
+
return /* @__PURE__ */ a("svg", {
|
|
43
|
+
ref: x,
|
|
44
|
+
width: p,
|
|
45
|
+
height: m,
|
|
46
|
+
role: "img",
|
|
47
|
+
"aria-label": "Sparkline area chart",
|
|
48
|
+
className: e("inline-block align-middle", y),
|
|
49
|
+
...b,
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ i("path", {
|
|
52
|
+
d: s,
|
|
53
|
+
fill: S,
|
|
54
|
+
opacity: .2
|
|
55
|
+
}),
|
|
56
|
+
w ? /* @__PURE__ */ i(o.path, {
|
|
57
|
+
d: f,
|
|
58
|
+
fill: "none",
|
|
59
|
+
stroke: S,
|
|
60
|
+
strokeWidth: _,
|
|
61
|
+
strokeLinejoin: "round",
|
|
62
|
+
strokeLinecap: "round",
|
|
63
|
+
initial: { pathLength: 0 },
|
|
64
|
+
animate: { pathLength: 1 },
|
|
65
|
+
transition: d
|
|
66
|
+
}) : /* @__PURE__ */ i("path", {
|
|
67
|
+
d: f,
|
|
68
|
+
fill: "none",
|
|
69
|
+
stroke: S,
|
|
70
|
+
strokeWidth: _,
|
|
71
|
+
strokeLinejoin: "round",
|
|
72
|
+
strokeLinecap: "round"
|
|
73
|
+
}),
|
|
74
|
+
g && /* @__PURE__ */ i("circle", {
|
|
75
|
+
cx: h,
|
|
76
|
+
cy: v,
|
|
77
|
+
r: _ + 1,
|
|
78
|
+
fill: S
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
let N = u().curve(l).x((e, t) => O(t)).y((e) => M(e))(r) ?? "", P = O(r.length - 1), F = M(r[r.length - 1]);
|
|
84
|
+
return /* @__PURE__ */ a("svg", {
|
|
85
|
+
ref: x,
|
|
86
|
+
width: p,
|
|
87
|
+
height: m,
|
|
88
|
+
role: "img",
|
|
89
|
+
"aria-label": "Sparkline chart",
|
|
90
|
+
className: e("inline-block align-middle", y),
|
|
91
|
+
...b,
|
|
92
|
+
children: [w ? /* @__PURE__ */ i(o.path, {
|
|
93
|
+
d: N,
|
|
94
|
+
fill: "none",
|
|
95
|
+
stroke: S,
|
|
96
|
+
strokeWidth: _,
|
|
97
|
+
strokeLinejoin: "round",
|
|
98
|
+
strokeLinecap: "round",
|
|
99
|
+
initial: { pathLength: 0 },
|
|
100
|
+
animate: { pathLength: 1 },
|
|
101
|
+
transition: d
|
|
102
|
+
}) : /* @__PURE__ */ i("path", {
|
|
103
|
+
d: N,
|
|
104
|
+
fill: "none",
|
|
105
|
+
stroke: S,
|
|
106
|
+
strokeWidth: _,
|
|
107
|
+
strokeLinejoin: "round",
|
|
108
|
+
strokeLinecap: "round"
|
|
109
|
+
}), g && /* @__PURE__ */ i("circle", {
|
|
110
|
+
cx: P,
|
|
111
|
+
cy: F,
|
|
112
|
+
r: _ + 1,
|
|
113
|
+
fill: S
|
|
114
|
+
})]
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
f.displayName = "Sparkline";
|
|
118
|
+
//#endregion
|
|
119
|
+
export { f as Sparkline };
|