@corbits/react-ui 0.1.0 → 0.2.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/LICENSE +174 -499
- package/README.md +228 -85
- package/dist/blocks/login/auth-layout.d.ts +1 -1
- package/dist/blocks/login/auth-layout.js +3 -33
- package/dist/blocks/login/login-form.js +6 -119
- package/dist/hooks/use-command-palette-navigation.js +18 -17
- package/dist/hooks/use-controllable-state.d.ts +2 -2
- package/dist/hooks/use-controllable-state.js +23 -15
- package/dist/hooks/use-delayed-autofocus.js +10 -11
- package/dist/hooks/use-dismissable-popover.d.ts +2 -2
- package/dist/hooks/use-dismissable-popover.js +21 -29
- package/dist/hooks/use-list-selection.js +54 -85
- package/dist/hooks/use-prefers-reduced-motion.js +8 -4
- package/dist/hooks/use-scroll-current-into-view.js +5 -7
- package/dist/index.d.ts +0 -11
- package/dist/index.js +10 -19
- package/dist/lib/artifact.js +16 -35
- package/dist/lib/chart-geometry.js +33 -20
- package/dist/lib/chart-palette.js +17 -31
- package/dist/lib/chat-message.js +32 -13
- package/dist/lib/chat-parts.js +2 -1
- package/dist/lib/csv.js +42 -26
- package/dist/lib/metrics.js +30 -48
- package/dist/lib/now-item.js +26 -25
- package/dist/lib/relative-time.js +14 -29
- package/dist/lib/theme.js +32 -30
- package/dist/lib/url.js +9 -8
- package/dist/lib/workflow-display-flow.js +37 -33
- package/dist/lib/workflow-registry.d.ts +0 -41
- package/dist/lib/workflow-registry.js +13 -23
- package/dist/lib/workflow-run-error.js +16 -20
- package/dist/lib/workflow-run-progress.js +94 -52
- package/dist/lib/workflow-run.js +17 -13
- package/dist/styles.css +11 -11
- package/dist/test/render-hook.js +11 -12
- package/dist/theme.css +51 -14
- package/dist/ui/agent-turn.d.ts +1 -1
- package/dist/ui/agent-turn.js +4 -37
- package/dist/ui/animated-number.js +15 -28
- package/dist/ui/approval-card.js +5 -90
- package/dist/ui/artifact-body.js +47 -125
- package/dist/ui/artifact-notice.d.ts +1 -1
- package/dist/ui/artifact-notice.js +9 -16
- package/dist/ui/avatar.d.ts +1 -1
- package/dist/ui/avatar.js +11 -48
- package/dist/ui/badge.js +4 -12
- package/dist/ui/bar-chart.d.ts +1 -1
- package/dist/ui/bar-chart.js +22 -74
- package/dist/ui/block-card.js +7 -45
- package/dist/ui/boot-screen.d.ts +1 -1
- package/dist/ui/boot-screen.js +4 -33
- package/dist/ui/bulk-action-bar.d.ts +1 -1
- package/dist/ui/bulk-action-bar.js +14 -33
- package/dist/ui/button.js +10 -24
- package/dist/ui/card.js +5 -25
- package/dist/ui/category-bars.js +14 -59
- package/dist/ui/chart-frame.d.ts +2 -2
- package/dist/ui/chart-frame.js +6 -85
- package/dist/ui/chat-composer.js +4 -16
- package/dist/ui/chat-dock-timing.js +7 -3
- package/dist/ui/chat-input.js +20 -100
- package/dist/ui/chat-panel.d.ts +1 -1
- package/dist/ui/chat-panel.js +7 -41
- package/dist/ui/chat-thread.js +13 -31
- package/dist/ui/checkbox.js +10 -52
- package/dist/ui/command-palette.js +71 -246
- package/dist/ui/compare-body.d.ts +1 -1
- package/dist/ui/compare-body.js +28 -98
- package/dist/ui/confirm-button.js +8 -15
- package/dist/ui/corbits-mark.js +7 -16
- package/dist/ui/csv-table.d.ts +1 -1
- package/dist/ui/csv-table.js +8 -50
- package/dist/ui/dialog.d.ts +1 -1
- package/dist/ui/dialog.js +32 -62
- package/dist/ui/dictation-status-line.js +7 -25
- package/dist/ui/dither-canvas.d.ts +1 -1
- package/dist/ui/dither-canvas.js +31 -56
- package/dist/ui/embed-body.d.ts +1 -1
- package/dist/ui/embed-body.js +7 -56
- package/dist/ui/empty-state.d.ts +1 -1
- package/dist/ui/empty-state.js +3 -26
- package/dist/ui/file-input.js +17 -37
- package/dist/ui/filter-bar.d.ts +1 -1
- package/dist/ui/filter-bar.js +11 -71
- package/dist/ui/filter-chip.d.ts +1 -1
- package/dist/ui/filter-chip.js +7 -15
- package/dist/ui/gate-block.d.ts +2 -1
- package/dist/ui/gate-block.js +4 -29
- package/dist/ui/horizontal-stepper.d.ts +1 -1
- package/dist/ui/horizontal-stepper.js +18 -45
- package/dist/ui/input.js +1 -6
- package/dist/ui/inspector-shell.d.ts +5 -5
- package/dist/ui/inspector-shell.js +14 -81
- package/dist/ui/intake-form.d.ts +1 -1
- package/dist/ui/intake-form.js +21 -97
- package/dist/ui/kind-card-grid.js +9 -31
- package/dist/ui/library-page-header.js +4 -32
- package/dist/ui/list-detail.js +5 -35
- package/dist/ui/live-run-banner.d.ts +1 -1
- package/dist/ui/live-run-banner.js +5 -15
- package/dist/ui/live-status-line.js +6 -24
- package/dist/ui/menu.js +7 -24
- package/dist/ui/message-bubble.d.ts +3 -3
- package/dist/ui/message-bubble.js +5 -44
- package/dist/ui/mic-button.d.ts +1 -1
- package/dist/ui/mic-button.js +15 -21
- package/dist/ui/mic-permission-dialog.js +5 -41
- package/dist/ui/notifications-bell.js +9 -43
- package/dist/ui/now-cards.d.ts +2 -2
- package/dist/ui/now-cards.js +16 -94
- package/dist/ui/page-panel.js +11 -11
- package/dist/ui/page-shell.js +4 -11
- package/dist/ui/parts-renderer.js +51 -149
- package/dist/ui/profile-card.js +7 -111
- package/dist/ui/progress-checklist.js +11 -49
- package/dist/ui/provider-mark.d.ts +2 -2
- package/dist/ui/provider-mark.js +9 -16
- package/dist/ui/quick-reply-chips.js +6 -14
- package/dist/ui/quote-card.js +12 -32
- package/dist/ui/reasoning-block.d.ts +1 -1
- package/dist/ui/reasoning-block.js +14 -33
- package/dist/ui/research-body.js +32 -213
- package/dist/ui/rich-empty-state.js +6 -48
- package/dist/ui/run-now-button.js +14 -15
- package/dist/ui/section.d.ts +1 -1
- package/dist/ui/section.js +4 -40
- package/dist/ui/select.js +1 -15
- package/dist/ui/selection-checkbox.d.ts +1 -1
- package/dist/ui/selection-checkbox.js +11 -29
- package/dist/ui/settings-panel.js +7 -50
- package/dist/ui/shimmer-text.js +3 -6
- package/dist/ui/sidebar-item-row.d.ts +1 -1
- package/dist/ui/sidebar-item-row.js +9 -39
- package/dist/ui/sidebar-panel.js +15 -40
- package/dist/ui/sidebar.js +15 -76
- package/dist/ui/skeleton.js +3 -7
- package/dist/ui/sortable-table.js +29 -72
- package/dist/ui/sparkline.js +14 -38
- package/dist/ui/stat-grid.js +17 -52
- package/dist/ui/status-dot.d.ts +1 -1
- package/dist/ui/status-dot.js +8 -20
- package/dist/ui/step-list.d.ts +1 -0
- package/dist/ui/step-list.js +11 -50
- package/dist/ui/switch.js +4 -16
- package/dist/ui/table.js +7 -32
- package/dist/ui/tabs.js +39 -54
- package/dist/ui/textarea.js +10 -19
- package/dist/ui/theme-provider.js +54 -78
- package/dist/ui/theme-toggle.js +13 -16
- package/dist/ui/thinking-indicator.js +3 -15
- package/dist/ui/thinking-label.js +16 -35
- package/dist/ui/thinking-mark.d.ts +1 -1
- package/dist/ui/thinking-mark.js +4 -145
- package/dist/ui/time-series-chart.js +43 -174
- package/dist/ui/toast.js +12 -20
- package/dist/ui/token-mosaic.js +5 -43
- package/dist/ui/tool-block.js +18 -70
- package/dist/ui/tool-narrative.d.ts +1 -1
- package/dist/ui/tool-narrative.js +10 -57
- package/dist/ui/tool-picker.js +57 -145
- package/dist/ui/tooltip.d.ts +1 -1
- package/dist/ui/tooltip.js +4 -33
- package/dist/ui/top-bar.js +14 -72
- package/dist/ui/trace-waterfall.d.ts +1 -1
- package/dist/ui/trace-waterfall.js +21 -93
- package/dist/ui/typing-indicator.d.ts +1 -1
- package/dist/ui/typing-indicator.js +4 -18
- package/dist/ui/view-toggle.js +10 -29
- package/dist/ui/voice-waveform.js +3 -11
- package/package.json +94 -535
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useEffect, useState } from "react";
|
|
3
4
|
import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
|
|
@@ -12,43 +13,23 @@ const DEFAULT_INTERVAL_MS = 3_000;
|
|
|
12
13
|
* announces "Working" once, so a screen reader is not re-interrupted every
|
|
13
14
|
* few seconds. Reduced motion is live via `usePrefersReducedMotion` and
|
|
14
15
|
* stops the rotation rather than just stilling the shimmer.
|
|
15
|
-
*/
|
|
16
|
+
*/
|
|
17
|
+
export function ThinkingLabel({ verbs, intervalMs = DEFAULT_INTERVAL_MS, statusLabel = "Working", className, }) {
|
|
16
18
|
const [at, setAt] = useState(0);
|
|
17
19
|
const reduceMotion = usePrefersReducedMotion();
|
|
18
|
-
useEffect(()=>{
|
|
19
|
-
if (verbs.length < 2 || !reduceMotion)
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (verbs.length < 2 || !reduceMotion)
|
|
22
|
+
return;
|
|
20
23
|
setAt(0);
|
|
21
|
-
}, [
|
|
22
|
-
|
|
23
|
-
reduceMotion
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
verbs.length,
|
|
31
|
-
intervalMs,
|
|
32
|
-
reduceMotion
|
|
33
|
-
]);
|
|
34
|
-
if (verbs.length === 0) return null;
|
|
24
|
+
}, [verbs.length, reduceMotion]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (verbs.length < 2 || reduceMotion)
|
|
27
|
+
return;
|
|
28
|
+
const timer = setInterval(() => setAt((current) => (current + 1) % verbs.length), intervalMs);
|
|
29
|
+
return () => clearInterval(timer);
|
|
30
|
+
}, [verbs.length, intervalMs, reduceMotion]);
|
|
31
|
+
if (verbs.length === 0)
|
|
32
|
+
return null;
|
|
35
33
|
const active = at % verbs.length;
|
|
36
|
-
return
|
|
37
|
-
className: cn("text-sm", className),
|
|
38
|
-
children: [
|
|
39
|
-
/*#__PURE__*/ _jsx("span", {
|
|
40
|
-
role: "status",
|
|
41
|
-
className: "sr-only",
|
|
42
|
-
children: statusLabel
|
|
43
|
-
}),
|
|
44
|
-
/*#__PURE__*/ _jsx("span", {
|
|
45
|
-
"aria-hidden": true,
|
|
46
|
-
className: "inline-grid",
|
|
47
|
-
children: verbs.map((verb, index)=>/*#__PURE__*/ _jsx(ShimmerText, {
|
|
48
|
-
className: cn("col-start-1 row-start-1 transition-opacity duration-200", index === active ? "opacity-100" : "opacity-0"),
|
|
49
|
-
children: verb
|
|
50
|
-
}, index))
|
|
51
|
-
})
|
|
52
|
-
]
|
|
53
|
-
});
|
|
34
|
+
return (_jsxs("span", { className: cn("text-sm", className), children: [_jsx("span", { role: "status", className: "sr-only", children: statusLabel }), _jsx("span", { "aria-hidden": true, className: "inline-grid", children: verbs.map((verb, index) => (_jsx(ShimmerText, { className: cn("col-start-1 row-start-1 transition-opacity duration-200", index === active ? "opacity-100" : "opacity-0"), children: verb }, index))) })] }));
|
|
54
35
|
}
|
|
@@ -7,4 +7,4 @@ export interface ThinkingMarkProps {
|
|
|
7
7
|
style?: CSSProperties;
|
|
8
8
|
}
|
|
9
9
|
/** Decorative animated Corbits mark. Pair with visible text or ThinkingIndicator. */
|
|
10
|
-
export declare function ThinkingMark({ variant, paused, className, style }: ThinkingMarkProps): import("react").JSX.Element;
|
|
10
|
+
export declare function ThinkingMark({ variant, paused, className, style, }: ThinkingMarkProps): import("react").JSX.Element;
|
package/dist/ui/thinking-mark.js
CHANGED
|
@@ -1,153 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
3
|
import { useId } from "react";
|
|
3
4
|
import { cn } from "../lib/utils.js";
|
|
4
5
|
import { CORBITS_MARK_PATH } from "./corbits-mark.js";
|
|
5
|
-
/** Decorative animated Corbits mark. Pair with visible text or ThinkingIndicator. */
|
|
6
|
+
/** Decorative animated Corbits mark. Pair with visible text or ThinkingIndicator. */
|
|
7
|
+
export function ThinkingMark({ variant = "silk", paused = false, className, style, }) {
|
|
6
8
|
const id = useId();
|
|
7
9
|
const gradient = `${id}-gradient`;
|
|
8
10
|
const mask = `${id}-mask`;
|
|
9
|
-
return
|
|
10
|
-
viewBox: "0 0 100 70",
|
|
11
|
-
width: "30",
|
|
12
|
-
height: "21",
|
|
13
|
-
"aria-hidden": "true",
|
|
14
|
-
focusable: "false",
|
|
15
|
-
className: cn("inline-block h-auto w-[30px] flex-none overflow-visible", paused && "[&_*]:[animation-play-state:paused]", className),
|
|
16
|
-
style: style,
|
|
17
|
-
children: [
|
|
18
|
-
/*#__PURE__*/ _jsxs("defs", {
|
|
19
|
-
children: [
|
|
20
|
-
variant === "echo" ? /*#__PURE__*/ _jsxs("radialGradient", {
|
|
21
|
-
id: gradient,
|
|
22
|
-
children: [
|
|
23
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
24
|
-
offset: ".38",
|
|
25
|
-
stopColor: "white",
|
|
26
|
-
stopOpacity: "0"
|
|
27
|
-
}),
|
|
28
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
29
|
-
offset: ".65",
|
|
30
|
-
stopColor: "white",
|
|
31
|
-
stopOpacity: ".65"
|
|
32
|
-
}),
|
|
33
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
34
|
-
offset: ".9",
|
|
35
|
-
stopColor: "white"
|
|
36
|
-
}),
|
|
37
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
38
|
-
offset: "1",
|
|
39
|
-
stopColor: "white",
|
|
40
|
-
stopOpacity: "0"
|
|
41
|
-
})
|
|
42
|
-
]
|
|
43
|
-
}) : /*#__PURE__*/ _jsxs("linearGradient", {
|
|
44
|
-
id: gradient,
|
|
45
|
-
x1: "0",
|
|
46
|
-
y1: "0",
|
|
47
|
-
x2: variant === "silk" ? "1" : "0",
|
|
48
|
-
y2: variant === "silk" ? "0" : "1",
|
|
49
|
-
children: [
|
|
50
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
51
|
-
stopColor: "white",
|
|
52
|
-
stopOpacity: "0"
|
|
53
|
-
}),
|
|
54
|
-
variant === "silk" ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
55
|
-
children: [
|
|
56
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
57
|
-
offset: ".45",
|
|
58
|
-
stopColor: "white",
|
|
59
|
-
stopOpacity: ".65"
|
|
60
|
-
}),
|
|
61
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
62
|
-
offset: ".78",
|
|
63
|
-
stopColor: "white"
|
|
64
|
-
})
|
|
65
|
-
]
|
|
66
|
-
}) : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
67
|
-
children: [
|
|
68
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
69
|
-
offset: ".25",
|
|
70
|
-
stopColor: "white"
|
|
71
|
-
}),
|
|
72
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
73
|
-
offset: ".42",
|
|
74
|
-
stopColor: "white",
|
|
75
|
-
stopOpacity: ".7"
|
|
76
|
-
})
|
|
77
|
-
]
|
|
78
|
-
}),
|
|
79
|
-
/*#__PURE__*/ _jsx("stop", {
|
|
80
|
-
offset: "1",
|
|
81
|
-
stopColor: "white",
|
|
82
|
-
stopOpacity: "0"
|
|
83
|
-
})
|
|
84
|
-
]
|
|
85
|
-
}),
|
|
86
|
-
/*#__PURE__*/ _jsxs("mask", {
|
|
87
|
-
id: mask,
|
|
88
|
-
maskUnits: "userSpaceOnUse",
|
|
89
|
-
x: "-10",
|
|
90
|
-
y: "-10",
|
|
91
|
-
width: "120",
|
|
92
|
-
height: "90",
|
|
93
|
-
style: {
|
|
94
|
-
maskType: "luminance"
|
|
95
|
-
},
|
|
96
|
-
children: [
|
|
97
|
-
variant === "silk" && /*#__PURE__*/ _jsx("rect", {
|
|
98
|
-
className: "corbits-thinking-silk [animation:corbits-thinking-sweep_1.45s_cubic-bezier(.22,.05,.38,1)_infinite]",
|
|
99
|
-
x: "-35",
|
|
100
|
-
y: "0",
|
|
101
|
-
width: "48",
|
|
102
|
-
height: "75",
|
|
103
|
-
fill: `url(#${gradient})`
|
|
104
|
-
}),
|
|
105
|
-
variant === "strata" && /*#__PURE__*/ _jsx("rect", {
|
|
106
|
-
className: "corbits-thinking-strata [animation:corbits-thinking-rise_3.2s_cubic-bezier(.3,0,.3,1)_infinite]",
|
|
107
|
-
x: "0",
|
|
108
|
-
y: "-12",
|
|
109
|
-
width: "100",
|
|
110
|
-
height: "33",
|
|
111
|
-
fill: `url(#${gradient})`
|
|
112
|
-
}),
|
|
113
|
-
variant === "echo" && /*#__PURE__*/ _jsxs(_Fragment, {
|
|
114
|
-
children: [
|
|
115
|
-
/*#__PURE__*/ _jsx("circle", {
|
|
116
|
-
className: "corbits-thinking-echo origin-[62px_9px] [animation:corbits-thinking-wave_3.6s_cubic-bezier(.15,.3,.3,1)_infinite]",
|
|
117
|
-
cx: "62",
|
|
118
|
-
cy: "9",
|
|
119
|
-
r: "80",
|
|
120
|
-
fill: `url(#${gradient})`
|
|
121
|
-
}),
|
|
122
|
-
/*#__PURE__*/ _jsx("circle", {
|
|
123
|
-
className: "corbits-thinking-echo origin-[62px_9px] motion-reduce:hidden [animation:corbits-thinking-wave_3.6s_cubic-bezier(.15,.3,.3,1)_-1.8s_infinite]",
|
|
124
|
-
cx: "62",
|
|
125
|
-
cy: "9",
|
|
126
|
-
r: "80",
|
|
127
|
-
fill: `url(#${gradient})`
|
|
128
|
-
})
|
|
129
|
-
]
|
|
130
|
-
})
|
|
131
|
-
]
|
|
132
|
-
})
|
|
133
|
-
]
|
|
134
|
-
}),
|
|
135
|
-
/*#__PURE__*/ _jsx("g", {
|
|
136
|
-
className: "fill-thinking-base",
|
|
137
|
-
opacity: ".7",
|
|
138
|
-
children: /*#__PURE__*/ _jsx("path", {
|
|
139
|
-
d: CORBITS_MARK_PATH,
|
|
140
|
-
transform: "translate(-2.3 -15) scale(.213)"
|
|
141
|
-
})
|
|
142
|
-
}),
|
|
143
|
-
/*#__PURE__*/ _jsx("g", {
|
|
144
|
-
className: "fill-primary",
|
|
145
|
-
mask: `url(#${mask})`,
|
|
146
|
-
children: /*#__PURE__*/ _jsx("path", {
|
|
147
|
-
d: CORBITS_MARK_PATH,
|
|
148
|
-
transform: "translate(-2.3 -15) scale(.213)"
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
]
|
|
152
|
-
});
|
|
11
|
+
return (_jsxs("svg", { viewBox: "0 0 100 70", width: "30", height: "21", "aria-hidden": "true", focusable: "false", className: cn("inline-block h-auto w-[30px] flex-none overflow-visible", paused && "[&_*]:[animation-play-state:paused]", className), style: style, children: [_jsxs("defs", { children: [variant === "echo" ? (_jsxs("radialGradient", { id: gradient, children: [_jsx("stop", { offset: ".38", stopColor: "white", stopOpacity: "0" }), _jsx("stop", { offset: ".65", stopColor: "white", stopOpacity: ".65" }), _jsx("stop", { offset: ".9", stopColor: "white" }), _jsx("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })] })) : (_jsxs("linearGradient", { id: gradient, x1: "0", y1: "0", x2: variant === "silk" ? "1" : "0", y2: variant === "silk" ? "0" : "1", children: [_jsx("stop", { stopColor: "white", stopOpacity: "0" }), variant === "silk" ? (_jsxs(_Fragment, { children: [_jsx("stop", { offset: ".45", stopColor: "white", stopOpacity: ".65" }), _jsx("stop", { offset: ".78", stopColor: "white" })] })) : (_jsxs(_Fragment, { children: [_jsx("stop", { offset: ".25", stopColor: "white" }), _jsx("stop", { offset: ".42", stopColor: "white", stopOpacity: ".7" })] })), _jsx("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })] })), _jsxs("mask", { id: mask, maskUnits: "userSpaceOnUse", x: "-10", y: "-10", width: "120", height: "90", style: { maskType: "luminance" }, children: [variant === "silk" && (_jsx("rect", { className: "corbits-thinking-silk [animation:corbits-thinking-sweep_1.45s_cubic-bezier(.22,.05,.38,1)_infinite]", x: "-35", y: "0", width: "48", height: "75", fill: `url(#${gradient})` })), variant === "strata" && (_jsx("rect", { className: "corbits-thinking-strata [animation:corbits-thinking-rise_3.2s_cubic-bezier(.3,0,.3,1)_infinite]", x: "0", y: "-12", width: "100", height: "33", fill: `url(#${gradient})` })), variant === "echo" && (_jsxs(_Fragment, { children: [_jsx("circle", { className: "corbits-thinking-echo origin-[62px_9px] [animation:corbits-thinking-wave_3.6s_cubic-bezier(.15,.3,.3,1)_infinite]", cx: "62", cy: "9", r: "80", fill: `url(#${gradient})` }), _jsx("circle", { className: "corbits-thinking-echo origin-[62px_9px] motion-reduce:hidden [animation:corbits-thinking-wave_3.6s_cubic-bezier(.15,.3,.3,1)_-1.8s_infinite]", cx: "62", cy: "9", r: "80", fill: `url(#${gradient})` })] }))] })] }), _jsx("g", { className: "fill-thinking-base", opacity: ".7", children: _jsx("path", { d: CORBITS_MARK_PATH, transform: "translate(-2.3 -15) scale(.213)" }) }), _jsx("g", { className: "fill-primary", mask: `url(#${mask})`, children: _jsx("path", { d: CORBITS_MARK_PATH, transform: "translate(-2.3 -15) scale(.213)" }) })] }));
|
|
153
12
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
3
|
import { useRef, useState } from "react";
|
|
3
|
-
import { areaPath, formatCompact, linePath, niceTicks, scaleLinear } from "../lib/chart-geometry.js";
|
|
4
|
-
import { CHART_SERIES_SLOTS, seriesColor, seriesDash } from "../lib/chart-palette.js";
|
|
4
|
+
import { areaPath, formatCompact, linePath, niceTicks, scaleLinear, } from "../lib/chart-geometry.js";
|
|
5
|
+
import { CHART_SERIES_SLOTS, seriesColor, seriesDash, } from "../lib/chart-palette.js";
|
|
5
6
|
import { cn } from "../lib/utils.js";
|
|
6
7
|
import { ChartFrame } from "./chart-frame.js";
|
|
7
8
|
const WIDTH = 480;
|
|
@@ -41,11 +42,12 @@ const PAD_BOTTOM = 22;
|
|
|
41
42
|
* from the theme, the arrow keys move the same index the pointer moves, and the
|
|
42
43
|
* readout is echoed into a `role="status"` so it is announced rather than merely
|
|
43
44
|
* drawn. Anything less makes precise values mouse-only.
|
|
44
|
-
*/
|
|
45
|
+
*/
|
|
46
|
+
export function TimeSeriesChart({ title, description, labels, series, variant = "line", format = formatCompact, className, }) {
|
|
45
47
|
const [active, setActive] = useState(null);
|
|
46
48
|
const svgRef = useRef(null);
|
|
47
49
|
const drawn = series.slice(0, CHART_SERIES_SLOTS);
|
|
48
|
-
const max = Math.max(0, ...drawn.flatMap((entry)=>entry.values));
|
|
50
|
+
const max = Math.max(0, ...drawn.flatMap((entry) => entry.values));
|
|
49
51
|
const ticks = niceTicks(max);
|
|
50
52
|
const axisMax = ticks[ticks.length - 1] ?? 1;
|
|
51
53
|
const plotWidth = WIDTH - PAD_LEFT - PAD_RIGHT;
|
|
@@ -53,197 +55,64 @@ const PAD_BOTTOM = 22;
|
|
|
53
55
|
// A single point has nowhere to travel; dividing by zero would put every mark
|
|
54
56
|
// at NaN and blank the chart.
|
|
55
57
|
const stepX = labels.length > 1 ? plotWidth / (labels.length - 1) : 0;
|
|
56
|
-
const xAt = (index)=>PAD_LEFT + index * stepX;
|
|
57
|
-
const yAt = (value)=>PAD_TOP + plotHeight - scaleLinear(value, axisMax, plotHeight);
|
|
58
|
+
const xAt = (index) => PAD_LEFT + index * stepX;
|
|
59
|
+
const yAt = (value) => PAD_TOP + plotHeight - scaleLinear(value, axisMax, plotHeight);
|
|
58
60
|
function indexFromClientX(clientX) {
|
|
59
61
|
const box = svgRef.current?.getBoundingClientRect();
|
|
60
|
-
if (box === undefined || labels.length === 0)
|
|
62
|
+
if (box === undefined || labels.length === 0)
|
|
63
|
+
return 0;
|
|
61
64
|
// The SVG scales to its container, so client pixels must be converted back
|
|
62
65
|
// into viewBox units before they mean anything.
|
|
63
|
-
const viewX = (clientX - box.left) / box.width * WIDTH;
|
|
66
|
+
const viewX = ((clientX - box.left) / box.width) * WIDTH;
|
|
64
67
|
const raw = stepX === 0 ? 0 : Math.round((viewX - PAD_LEFT) / stepX);
|
|
65
68
|
return Math.min(labels.length - 1, Math.max(0, raw));
|
|
66
69
|
}
|
|
67
70
|
function step(delta) {
|
|
68
|
-
setActive((current)=>{
|
|
71
|
+
setActive((current) => {
|
|
69
72
|
const next = (current ?? 0) + delta;
|
|
70
73
|
return Math.min(labels.length - 1, Math.max(0, next));
|
|
71
74
|
});
|
|
72
75
|
}
|
|
73
|
-
const readout = active === null
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
description
|
|
78
|
-
},
|
|
76
|
+
const readout = active === null
|
|
77
|
+
? ""
|
|
78
|
+
: `${labels[active]}: ${drawn.map((entry) => `${entry.label} ${format(entry.values[active] ?? 0)}`).join(", ")}`;
|
|
79
|
+
return (_jsxs(ChartFrame, { title: title, ...(description === undefined ? {} : { description }),
|
|
79
80
|
// `dash` as well as `color`: the lines carry two channels, so the legend
|
|
80
81
|
// has to cross-reference both or it only explains half the plot.
|
|
81
|
-
legend: drawn.map((entry, index)=>({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
...drawn.map((entry)=>entry.
|
|
90
|
-
],
|
|
91
|
-
|
|
92
|
-
label,
|
|
93
|
-
...drawn.map((entry)=>format(entry.values[index] ?? 0))
|
|
94
|
-
])
|
|
95
|
-
},
|
|
96
|
-
className: className,
|
|
97
|
-
children: [
|
|
98
|
-
/*#__PURE__*/ _jsxs("div", {
|
|
99
|
-
className: "relative",
|
|
100
|
-
children: [
|
|
101
|
-
/*#__PURE__*/ _jsxs("svg", {
|
|
102
|
-
ref: svgRef,
|
|
103
|
-
viewBox: `0 0 ${WIDTH} ${HEIGHT}`,
|
|
104
|
-
className: "h-auto w-full touch-none",
|
|
105
|
-
role: "img",
|
|
106
|
-
"aria-label": `${title}. Use the arrow keys to read each period.`,
|
|
107
|
-
tabIndex: 0,
|
|
108
|
-
onPointerMove: (event)=>setActive(indexFromClientX(event.clientX)),
|
|
109
|
-
onPointerLeave: ()=>setActive(null),
|
|
110
|
-
onFocus: ()=>setActive((current)=>current ?? 0),
|
|
111
|
-
onBlur: ()=>setActive(null),
|
|
112
|
-
onKeyDown: (event)=>{
|
|
82
|
+
legend: drawn.map((entry, index) => ({
|
|
83
|
+
label: entry.label,
|
|
84
|
+
color: seriesColor(index),
|
|
85
|
+
dash: seriesDash(index) ?? "none",
|
|
86
|
+
})), table: {
|
|
87
|
+
columns: ["Period", ...drawn.map((entry) => entry.label)],
|
|
88
|
+
rows: labels.map((label, index) => [
|
|
89
|
+
label,
|
|
90
|
+
...drawn.map((entry) => format(entry.values[index] ?? 0)),
|
|
91
|
+
]),
|
|
92
|
+
}, className: className, children: [_jsxs("div", { className: "relative", children: [_jsxs("svg", { ref: svgRef, viewBox: `0 0 ${WIDTH} ${HEIGHT}`, className: "h-auto w-full touch-none", role: "img", "aria-label": `${title}. Use the arrow keys to read each period.`, tabIndex: 0, onPointerMove: (event) => setActive(indexFromClientX(event.clientX)), onPointerLeave: () => setActive(null), onFocus: () => setActive((current) => current ?? 0), onBlur: () => setActive(null), onKeyDown: (event) => {
|
|
113
93
|
if (event.key === "ArrowRight") {
|
|
114
94
|
event.preventDefault();
|
|
115
95
|
step(1);
|
|
116
|
-
}
|
|
96
|
+
}
|
|
97
|
+
else if (event.key === "ArrowLeft") {
|
|
117
98
|
event.preventDefault();
|
|
118
99
|
step(-1);
|
|
119
|
-
}
|
|
100
|
+
}
|
|
101
|
+
else if (event.key === "Escape") {
|
|
120
102
|
setActive(null);
|
|
121
103
|
}
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}),
|
|
134
|
-
/*#__PURE__*/ _jsx("text", {
|
|
135
|
-
x: PAD_LEFT - 8,
|
|
136
|
-
y: yAt(tick),
|
|
137
|
-
textAnchor: "end",
|
|
138
|
-
dominantBaseline: "middle",
|
|
139
|
-
className: "fill-muted-foreground text-[10px] tabular-nums",
|
|
140
|
-
children: format(tick)
|
|
141
|
-
})
|
|
142
|
-
]
|
|
143
|
-
}, tick)),
|
|
144
|
-
labels.length === 0 ? null : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
145
|
-
children: [
|
|
146
|
-
/*#__PURE__*/ _jsx("text", {
|
|
147
|
-
x: PAD_LEFT,
|
|
148
|
-
y: HEIGHT - 6,
|
|
149
|
-
className: "fill-muted-foreground text-[10px]",
|
|
150
|
-
children: labels[0]
|
|
151
|
-
}),
|
|
152
|
-
/*#__PURE__*/ _jsx("text", {
|
|
153
|
-
x: WIDTH - PAD_RIGHT,
|
|
154
|
-
y: HEIGHT - 6,
|
|
155
|
-
textAnchor: "end",
|
|
156
|
-
className: "fill-muted-foreground text-[10px]",
|
|
157
|
-
children: labels[labels.length - 1]
|
|
158
|
-
})
|
|
159
|
-
]
|
|
160
|
-
}),
|
|
161
|
-
active === null ? null : /*#__PURE__*/ _jsx("line", {
|
|
162
|
-
x1: xAt(active),
|
|
163
|
-
y1: PAD_TOP,
|
|
164
|
-
x2: xAt(active),
|
|
165
|
-
y2: PAD_TOP + plotHeight,
|
|
166
|
-
stroke: "var(--muted-foreground)",
|
|
167
|
-
strokeWidth: 1
|
|
168
|
-
}),
|
|
169
|
-
variant === "area" ? drawn.map((entry, index)=>/*#__PURE__*/ _jsx("path", {
|
|
170
|
-
d: areaPath(entry.values.map((value, pointIndex)=>({
|
|
171
|
-
x: xAt(pointIndex),
|
|
172
|
-
y: yAt(value)
|
|
173
|
-
})), yAt(0)),
|
|
174
|
-
fill: seriesColor(index),
|
|
175
|
-
opacity: 0.14
|
|
176
|
-
}, entry.label)) : null,
|
|
177
|
-
drawn.map((entry, index)=>/*#__PURE__*/ _jsx("path", {
|
|
178
|
-
d: linePath(entry.values.map((value, pointIndex)=>({
|
|
179
|
-
x: xAt(pointIndex),
|
|
180
|
-
y: yAt(value)
|
|
181
|
-
}))),
|
|
182
|
-
fill: "none",
|
|
183
|
-
stroke: seriesColor(index),
|
|
184
|
-
strokeDasharray: seriesDash(index),
|
|
185
|
-
strokeWidth: 2,
|
|
186
|
-
strokeLinecap: "butt",
|
|
187
|
-
strokeLinejoin: "round"
|
|
188
|
-
}, entry.label)),
|
|
189
|
-
active === null ? null : drawn.map((entry, index)=>/*#__PURE__*/ _jsx("circle", {
|
|
190
|
-
cx: xAt(active),
|
|
191
|
-
cy: yAt(entry.values[active] ?? 0),
|
|
192
|
-
r: 4,
|
|
193
|
-
fill: seriesColor(index),
|
|
104
|
+
}, children: [ticks.map((tick) => (_jsxs("g", { children: [_jsx("line", { x1: PAD_LEFT, y1: yAt(tick), x2: WIDTH - PAD_RIGHT, y2: yAt(tick), stroke: "var(--border)", strokeWidth: 1 }), _jsx("text", { x: PAD_LEFT - 8, y: yAt(tick), textAnchor: "end", dominantBaseline: "middle", className: "fill-muted-foreground text-[10px] tabular-nums", children: format(tick) })] }, tick))), labels.length === 0 ? null : (_jsxs(_Fragment, { children: [_jsx("text", { x: PAD_LEFT, y: HEIGHT - 6, className: "fill-muted-foreground text-[10px]", children: labels[0] }), _jsx("text", { x: WIDTH - PAD_RIGHT, y: HEIGHT - 6, textAnchor: "end", className: "fill-muted-foreground text-[10px]", children: labels[labels.length - 1] })] })), active === null ? null : (_jsx("line", { x1: xAt(active), y1: PAD_TOP, x2: xAt(active), y2: PAD_TOP + plotHeight, stroke: "var(--muted-foreground)", strokeWidth: 1 })), variant === "area"
|
|
105
|
+
? drawn.map((entry, index) => (_jsx("path", { d: areaPath(entry.values.map((value, pointIndex) => ({
|
|
106
|
+
x: xAt(pointIndex),
|
|
107
|
+
y: yAt(value),
|
|
108
|
+
})), yAt(0)), fill: seriesColor(index), opacity: 0.14 }, entry.label)))
|
|
109
|
+
: null, drawn.map((entry, index) => (_jsx("path", { d: linePath(entry.values.map((value, pointIndex) => ({
|
|
110
|
+
x: xAt(pointIndex),
|
|
111
|
+
y: yAt(value),
|
|
112
|
+
}))), fill: "none", stroke: seriesColor(index), strokeDasharray: seriesDash(index), strokeWidth: 2, strokeLinecap: "butt", strokeLinejoin: "round" }, entry.label))), active === null
|
|
113
|
+
? null
|
|
114
|
+
: drawn.map((entry, index) => (_jsx("circle", { cx: xAt(active), cy: yAt(entry.values[active] ?? 0), r: 4, fill: seriesColor(index),
|
|
194
115
|
// A 2px ring in the surface colour, so a marker stays legible
|
|
195
116
|
// where it crosses a line or another marker.
|
|
196
|
-
stroke: "var(--card)",
|
|
197
|
-
strokeWidth: 2
|
|
198
|
-
}, entry.label))
|
|
199
|
-
]
|
|
200
|
-
}),
|
|
201
|
-
active === null ? null : /*#__PURE__*/ _jsxs("div", {
|
|
202
|
-
className: "pointer-events-none absolute top-0 left-0 rounded-md border border-border bg-popover px-2 py-1.5 text-xs text-popover-foreground shadow-lg",
|
|
203
|
-
children: [
|
|
204
|
-
/*#__PURE__*/ _jsx("p", {
|
|
205
|
-
className: "font-medium",
|
|
206
|
-
children: labels[active]
|
|
207
|
-
}),
|
|
208
|
-
/*#__PURE__*/ _jsx("ul", {
|
|
209
|
-
className: "mt-1 flex flex-col gap-0.5",
|
|
210
|
-
children: drawn.map((entry, index)=>/*#__PURE__*/ _jsxs("li", {
|
|
211
|
-
className: "flex items-center gap-1.5",
|
|
212
|
-
children: [
|
|
213
|
-
/*#__PURE__*/ _jsx("svg", {
|
|
214
|
-
"aria-hidden": true,
|
|
215
|
-
viewBox: "0 0 20 4",
|
|
216
|
-
className: "h-1 w-5 shrink-0 overflow-visible",
|
|
217
|
-
children: /*#__PURE__*/ _jsx("line", {
|
|
218
|
-
x1: 0,
|
|
219
|
-
y1: 2,
|
|
220
|
-
x2: 20,
|
|
221
|
-
y2: 2,
|
|
222
|
-
stroke: seriesColor(index),
|
|
223
|
-
strokeDasharray: seriesDash(index),
|
|
224
|
-
strokeWidth: 2.5
|
|
225
|
-
})
|
|
226
|
-
}),
|
|
227
|
-
/*#__PURE__*/ _jsx("span", {
|
|
228
|
-
className: "text-muted-foreground",
|
|
229
|
-
children: entry.label
|
|
230
|
-
}),
|
|
231
|
-
/*#__PURE__*/ _jsx("span", {
|
|
232
|
-
className: "ml-auto pl-3 font-mono tabular-nums",
|
|
233
|
-
children: format(entry.values[active] ?? 0)
|
|
234
|
-
})
|
|
235
|
-
]
|
|
236
|
-
}, entry.label))
|
|
237
|
-
})
|
|
238
|
-
]
|
|
239
|
-
})
|
|
240
|
-
]
|
|
241
|
-
}),
|
|
242
|
-
/*#__PURE__*/ _jsx("p", {
|
|
243
|
-
role: "status",
|
|
244
|
-
className: cn("sr-only"),
|
|
245
|
-
children: readout
|
|
246
|
-
})
|
|
247
|
-
]
|
|
248
|
-
});
|
|
117
|
+
stroke: "var(--card)", strokeWidth: 2 }, entry.label)))] }), active === null ? null : (_jsxs("div", { className: "pointer-events-none absolute top-0 left-0 rounded-md border border-border bg-popover px-2 py-1.5 text-xs text-popover-foreground shadow-lg", children: [_jsx("p", { className: "font-medium", children: labels[active] }), _jsx("ul", { className: "mt-1 flex flex-col gap-0.5", children: drawn.map((entry, index) => (_jsxs("li", { className: "flex items-center gap-1.5", children: [_jsx("svg", { "aria-hidden": true, viewBox: "0 0 20 4", className: "h-1 w-5 shrink-0 overflow-visible", children: _jsx("line", { x1: 0, y1: 2, x2: 20, y2: 2, stroke: seriesColor(index), strokeDasharray: seriesDash(index), strokeWidth: 2.5 }) }), _jsx("span", { className: "text-muted-foreground", children: entry.label }), _jsx("span", { className: "ml-auto pl-3 font-mono tabular-nums", children: format(entry.values[active] ?? 0) })] }, entry.label))) })] }))] }), _jsx("p", { role: "status", className: cn("sr-only"), children: readout })] }));
|
|
249
118
|
}
|
package/dist/ui/toast.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
3
|
import { Toaster as Sonner, toast as sonnerToast } from "sonner";
|
|
3
4
|
const TOAST_DURATION_MS = 1800;
|
|
@@ -9,33 +10,24 @@ let sequence = 0;
|
|
|
9
10
|
* as a single status line rather than a growing stack. Each call takes a
|
|
10
11
|
* fresh id — reusing one id would inherit the unmount sonner schedules while
|
|
11
12
|
* a dismissed toast is still animating out, swallowing the new message.
|
|
12
|
-
*/
|
|
13
|
-
|
|
13
|
+
*/
|
|
14
|
+
export function toast(message) {
|
|
15
|
+
if (activeId !== null)
|
|
16
|
+
sonnerToast.dismiss(activeId);
|
|
14
17
|
sequence += 1;
|
|
15
18
|
activeId = `corbits-toast-${sequence}`;
|
|
16
|
-
sonnerToast(message, {
|
|
17
|
-
id: activeId,
|
|
18
|
-
duration: TOAST_DURATION_MS
|
|
19
|
-
});
|
|
19
|
+
sonnerToast(message, { id: activeId, duration: TOAST_DURATION_MS });
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Mount once at the app root. Sonner renders in a portal, so the toast is
|
|
23
23
|
* styled here (unstyled + utility classes) instead of inheriting from a
|
|
24
24
|
* surrounding component; its motion overrides live in theme.css under
|
|
25
25
|
* `.corbits-toast`.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
offset: {
|
|
30
|
-
bottom: "1.25rem"
|
|
31
|
-
},
|
|
32
|
-
mobileOffset: {
|
|
33
|
-
bottom: "1.25rem"
|
|
34
|
-
},
|
|
35
|
-
toastOptions: {
|
|
26
|
+
*/
|
|
27
|
+
export function Toaster(props) {
|
|
28
|
+
return (_jsx(Sonner, { position: "bottom-center", offset: { bottom: "1.25rem" }, mobileOffset: { bottom: "1.25rem" }, toastOptions: {
|
|
36
29
|
unstyled: true,
|
|
37
|
-
className: "corbits-toast border border-border-strong bg-card shadow-surface " +
|
|
38
|
-
|
|
39
|
-
...props
|
|
40
|
-
});
|
|
30
|
+
className: "corbits-toast border border-border-strong bg-card shadow-surface " +
|
|
31
|
+
"px-[0.9rem] py-[0.55rem] font-sans text-[0.8rem] font-[550] text-foreground",
|
|
32
|
+
}, ...props }));
|
|
41
33
|
}
|
package/dist/ui/token-mosaic.js
CHANGED
|
@@ -12,53 +12,15 @@ import { cn } from "../lib/utils.js";
|
|
|
12
12
|
* than asking a reader to track more hues. The legend is the accessible half:
|
|
13
13
|
* the strip itself is one `role="img"` and each legend entry carries the
|
|
14
14
|
* segment's label and compact value.
|
|
15
|
-
*/
|
|
15
|
+
*/
|
|
16
|
+
export function TokenMosaic({ parts, label, className }) {
|
|
16
17
|
const segments = buildMosaic(parts);
|
|
17
|
-
return
|
|
18
|
-
className: cn("flex flex-col gap-2", className),
|
|
19
|
-
children: [
|
|
20
|
-
/*#__PURE__*/ _jsx("div", {
|
|
21
|
-
className: "flex h-2.5 w-full overflow-hidden rounded-[3px] bg-muted",
|
|
22
|
-
role: "img",
|
|
23
|
-
"aria-label": label,
|
|
24
|
-
children: /*#__PURE__*/ _jsx("svg", {
|
|
25
|
-
className: "h-full w-full",
|
|
26
|
-
viewBox: "0 0 100 10",
|
|
27
|
-
preserveAspectRatio: "none",
|
|
28
|
-
children: renderSegmentRects(segments)
|
|
29
|
-
})
|
|
30
|
-
}),
|
|
31
|
-
/*#__PURE__*/ _jsx("div", {
|
|
32
|
-
className: "flex flex-wrap gap-x-4 gap-y-1",
|
|
33
|
-
children: segments.map((segment, index)=>/*#__PURE__*/ _jsxs("span", {
|
|
34
|
-
className: "flex items-center gap-1.5 font-mono text-[11px] tracking-[0.08em] uppercase text-muted-foreground",
|
|
35
|
-
children: [
|
|
36
|
-
/*#__PURE__*/ _jsx("span", {
|
|
37
|
-
"aria-hidden": true,
|
|
38
|
-
className: "size-2 rounded-[1px]",
|
|
39
|
-
style: {
|
|
40
|
-
backgroundColor: seriesColor(index)
|
|
41
|
-
}
|
|
42
|
-
}),
|
|
43
|
-
segment.label,
|
|
44
|
-
" ",
|
|
45
|
-
formatCompact(segment.value)
|
|
46
|
-
]
|
|
47
|
-
}, segment.label))
|
|
48
|
-
})
|
|
49
|
-
]
|
|
50
|
-
});
|
|
18
|
+
return (_jsxs("div", { className: cn("flex flex-col gap-2", className), children: [_jsx("div", { className: "flex h-2.5 w-full overflow-hidden rounded-[3px] bg-muted", role: "img", "aria-label": label, children: _jsx("svg", { className: "h-full w-full", viewBox: "0 0 100 10", preserveAspectRatio: "none", children: renderSegmentRects(segments) }) }), _jsx("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: segments.map((segment, index) => (_jsxs("span", { className: "flex items-center gap-1.5 font-mono text-[11px] tracking-[0.08em] uppercase text-muted-foreground", children: [_jsx("span", { "aria-hidden": true, className: "size-2 rounded-[1px]", style: { backgroundColor: seriesColor(index) } }), segment.label, " ", formatCompact(segment.value)] }, segment.label))) })] }));
|
|
51
19
|
}
|
|
52
20
|
function renderSegmentRects(segments) {
|
|
53
21
|
let x = 0;
|
|
54
|
-
return segments.map((segment, index)=>{
|
|
55
|
-
const rect =
|
|
56
|
-
x: x,
|
|
57
|
-
y: 0,
|
|
58
|
-
width: segment.pct,
|
|
59
|
-
height: 10,
|
|
60
|
-
fill: seriesColor(index)
|
|
61
|
-
}, segment.label);
|
|
22
|
+
return segments.map((segment, index) => {
|
|
23
|
+
const rect = (_jsx("rect", { x: x, y: 0, width: segment.pct, height: 10, fill: seriesColor(index) }, segment.label));
|
|
62
24
|
x += segment.pct;
|
|
63
25
|
return rect;
|
|
64
26
|
});
|