@devalok/shilp-sutra 0.43.0 → 0.44.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/MIGRATION.md +46 -0
- package/dist/_chunks/chat.js +163 -162
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js +34 -32
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/oauth-button.js +102 -97
- package/dist/_chunks/oauth-button.js.map +1 -1
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/composed/command-palette.js +3 -3
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.d.ts +6 -0
- package/dist/composed/content-card.d.ts.map +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/extensions/file-attachment.d.ts.map +1 -1
- package/dist/composed/file-preview/audio-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +146 -142
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.js +5 -2
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/page-header.js +1 -1
- package/dist/composed/page-header.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/audio-player.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +595 -586
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.js +164 -162
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/shell/notification-center.d.ts.map +1 -1
- package/dist/shell/notification-center.js +101 -97
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/sidebar.d.ts.map +1 -1
- package/dist/shell/sidebar.js +137 -122
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/top-bar.d.ts.map +1 -1
- package/dist/shell/top-bar.js +86 -83
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/semantic.css +1 -0
- package/dist/ui/avatar.js +1 -1
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/breadcrumb.js +2 -2
- package/dist/ui/breadcrumb.js.map +1 -1
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts +82 -7
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +74 -108
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/combobox.js +2 -2
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/dropdown-menu.js +9 -3
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/index.d.ts +2 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +58 -57
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/menubar.js +9 -3
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -1
- package/dist/ui/select.js +5 -2
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sidebar.js +73 -73
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/stat-card.d.ts +8 -5
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +168 -150
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +5 -2
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/truncated-text.d.ts +37 -0
- package/dist/ui/truncated-text.d.ts.map +1 -0
- package/dist/ui/truncated-text.js +53 -0
- package/dist/ui/truncated-text.js.map +1 -0
- package/docs/components/ui/card.md +13 -4
- package/docs/components/ui/stat-card.md +7 -2
- package/docs/components/ui/truncated-text.md +49 -0
- package/llms-full.txt +70 -7
- package/make-kit/components/card.md +14 -4
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/references/components-full.md +70 -7
package/dist/ui/stat-card.js
CHANGED
|
@@ -4,14 +4,15 @@ import { springs as t, tweens as n } from "./lib/motion.js";
|
|
|
4
4
|
import { cn as r } from "./lib/utils.js";
|
|
5
5
|
import { Icon as i } from "./icon.js";
|
|
6
6
|
import { t as a } from "../_chunks/normalize-icon.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
7
|
+
import { Card as o, CardContent as s } from "./card.js";
|
|
8
|
+
import { n as c } from "../_chunks/link-context.js";
|
|
9
|
+
import { StatFlash as l } from "./stat-flash.js";
|
|
10
|
+
import * as u from "react";
|
|
11
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
12
|
+
import { IconMinus as m, IconTrendingDown as h, IconTrendingUp as g } from "@tabler/icons-react";
|
|
13
|
+
import { motion as _ } from "framer-motion";
|
|
13
14
|
//#region src/ui/stat-card.tsx
|
|
14
|
-
function
|
|
15
|
+
function v(e, t, n) {
|
|
15
16
|
let r = e.filter((e) => Number.isFinite(e));
|
|
16
17
|
if (r.length < 2) return "";
|
|
17
18
|
let i = Math.min(...r), a = Math.max(...r) - i || 1, o = t / (r.length - 1);
|
|
@@ -20,41 +21,41 @@ function g(e, t, n) {
|
|
|
20
21
|
return `${t === 0 ? "M" : "L"}${r.toFixed(1)},${s.toFixed(1)}`;
|
|
21
22
|
}).join(" ");
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
-
let n =
|
|
25
|
-
if (
|
|
24
|
+
function y({ data: e, colorClass: t }) {
|
|
25
|
+
let n = u.useId(), i = u.useRef(null), [a, o] = u.useState(0), s = v(e, 80, 32);
|
|
26
|
+
if (u.useEffect(() => {
|
|
26
27
|
i.current && o(i.current.getTotalLength());
|
|
27
28
|
}, [s]), !s) return null;
|
|
28
|
-
let
|
|
29
|
-
return /* @__PURE__ */
|
|
29
|
+
let c = `${s} L${80 .toFixed(1)},${32 .toFixed(1)} L0,${32 .toFixed(1)} Z`;
|
|
30
|
+
return /* @__PURE__ */ p("div", {
|
|
30
31
|
className: r("w-20 h-8", t),
|
|
31
32
|
"aria-hidden": "true",
|
|
32
|
-
children: [/* @__PURE__ */
|
|
33
|
+
children: [/* @__PURE__ */ p("svg", {
|
|
33
34
|
viewBox: "0 0 80 32",
|
|
34
35
|
className: "w-full h-full overflow-visible",
|
|
35
36
|
preserveAspectRatio: "none",
|
|
36
37
|
children: [
|
|
37
|
-
/* @__PURE__ */
|
|
38
|
+
/* @__PURE__ */ f("defs", { children: /* @__PURE__ */ p("linearGradient", {
|
|
38
39
|
id: `sparkline-fill-${n}`,
|
|
39
40
|
x1: "0",
|
|
40
41
|
y1: "0",
|
|
41
42
|
x2: "0",
|
|
42
43
|
y2: "1",
|
|
43
|
-
children: [/* @__PURE__ */
|
|
44
|
+
children: [/* @__PURE__ */ f("stop", {
|
|
44
45
|
offset: "0%",
|
|
45
46
|
stopColor: "currentColor",
|
|
46
47
|
stopOpacity: "0.1"
|
|
47
|
-
}), /* @__PURE__ */
|
|
48
|
+
}), /* @__PURE__ */ f("stop", {
|
|
48
49
|
offset: "100%",
|
|
49
50
|
stopColor: "currentColor",
|
|
50
51
|
stopOpacity: "0"
|
|
51
52
|
})]
|
|
52
53
|
}) }),
|
|
53
|
-
/* @__PURE__ */
|
|
54
|
-
d:
|
|
54
|
+
/* @__PURE__ */ f("path", {
|
|
55
|
+
d: c,
|
|
55
56
|
fill: `url(#sparkline-fill-${n})`
|
|
56
57
|
}),
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ f("path", {
|
|
58
59
|
ref: i,
|
|
59
60
|
d: s,
|
|
60
61
|
fill: "none",
|
|
@@ -70,57 +71,95 @@ function _({ data: e, colorClass: t }) {
|
|
|
70
71
|
}
|
|
71
72
|
})
|
|
72
73
|
]
|
|
73
|
-
}), a > 0 && /* @__PURE__ */
|
|
74
|
+
}), a > 0 && /* @__PURE__ */ f("style", { children: `@keyframes sparkline-draw-${n.replace(/:/g, "")} { to { stroke-dashoffset: 0; } }` })]
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
|
-
function
|
|
77
|
+
function b({ progress: e, label: t }) {
|
|
77
78
|
let n = Math.max(0, Math.min(100, e)), i = n >= 90 ? "bg-success-9" : n >= 70 ? "bg-warning-9" : "bg-accent-9";
|
|
78
|
-
return /* @__PURE__ */
|
|
79
|
+
return /* @__PURE__ */ f("div", {
|
|
79
80
|
className: "h-1 w-full rounded-pill bg-surface-raised mt-ds-04",
|
|
80
81
|
role: "progressbar",
|
|
81
82
|
"aria-label": `${t} progress`,
|
|
82
83
|
"aria-valuenow": n,
|
|
83
84
|
"aria-valuemin": 0,
|
|
84
85
|
"aria-valuemax": 100,
|
|
85
|
-
children: /* @__PURE__ */
|
|
86
|
+
children: /* @__PURE__ */ f("div", {
|
|
86
87
|
className: r("h-full rounded-pill transition-[width] duration-moderate-02 ease-productive-standard", i),
|
|
87
88
|
style: { width: `${n}%` }
|
|
88
89
|
})
|
|
89
90
|
});
|
|
90
91
|
}
|
|
91
|
-
var
|
|
92
|
-
let
|
|
93
|
-
if (
|
|
94
|
-
ref:
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
var x = u.forwardRef(({ className: u, label: v, title: x, value: S, prefix: C, suffix: w, delta: T, deltaPlacement: E = "block", icon: D, loading: O, comparisonLabel: k, secondaryLabel: A, progress: j, variant: M = "default", accentStyle: N = "none", iconFill: P = "soft", flash: F, flashSpeed: I, sparkline: L, onClick: R, href: z, footer: B, ...V }, H) => {
|
|
93
|
+
let U = c(), W = x ?? v ?? "", G = (R || z) && !V["aria-label"] ? `View ${W}` : V["aria-label"];
|
|
94
|
+
if (O) return /* @__PURE__ */ f(o, {
|
|
95
|
+
ref: H,
|
|
96
|
+
variant: M,
|
|
97
|
+
className: u,
|
|
98
|
+
...V,
|
|
99
|
+
children: /* @__PURE__ */ p(s, { children: [
|
|
100
|
+
/* @__PURE__ */ f("div", { className: "h-ds-04 w-24 rounded-control-inner bg-skeleton-base animate-pulse mb-ds-05" }),
|
|
101
|
+
/* @__PURE__ */ f("div", { className: "h-ds-sm w-32 rounded-control bg-skeleton-base animate-pulse mb-ds-03" }),
|
|
102
|
+
/* @__PURE__ */ f("div", { className: "h-3 w-16 rounded-control-inner bg-skeleton-base animate-pulse" })
|
|
103
|
+
] })
|
|
104
|
+
});
|
|
105
|
+
let K = T?.direction === "up" ? g : T?.direction === "down" ? h : m, q = T?.direction === "up" ? "text-success-11" : T?.direction === "down" ? "text-error-11" : "text-surface-fg-muted", J = T?.direction === "up" ? "text-success-11" : T?.direction === "down" ? "text-error-11" : "text-accent-11", Y = T ? /* @__PURE__ */ p(_.div, {
|
|
106
|
+
className: r("flex items-center gap-ds-02 text-ds-sm font-medium", q, E === "block" && "mt-ds-03"),
|
|
107
|
+
initial: {
|
|
108
|
+
opacity: 0,
|
|
109
|
+
y: 8
|
|
110
|
+
},
|
|
111
|
+
animate: {
|
|
112
|
+
opacity: 1,
|
|
113
|
+
y: 0
|
|
114
|
+
},
|
|
115
|
+
transition: {
|
|
116
|
+
...t.smooth,
|
|
117
|
+
delay: .2
|
|
118
|
+
},
|
|
97
119
|
children: [
|
|
98
|
-
/* @__PURE__ */
|
|
99
|
-
|
|
100
|
-
|
|
120
|
+
/* @__PURE__ */ f(_.span, {
|
|
121
|
+
className: "inline-flex",
|
|
122
|
+
initial: {
|
|
123
|
+
opacity: .5,
|
|
124
|
+
scale: 1.4
|
|
125
|
+
},
|
|
126
|
+
animate: {
|
|
127
|
+
opacity: 1,
|
|
128
|
+
scale: 1
|
|
129
|
+
},
|
|
130
|
+
transition: t.bouncy,
|
|
131
|
+
children: /* @__PURE__ */ f(i, {
|
|
132
|
+
icon: K,
|
|
133
|
+
size: "sm"
|
|
134
|
+
})
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ f("span", { children: T.value }),
|
|
137
|
+
k && /* @__PURE__ */ f("span", {
|
|
138
|
+
className: "text-surface-fg-subtle font-normal",
|
|
139
|
+
children: k
|
|
140
|
+
})
|
|
101
141
|
]
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
/* @__PURE__ */ d("div", {
|
|
142
|
+
}) : null, X = /* @__PURE__ */ p(d, { children: [
|
|
143
|
+
/* @__PURE__ */ p("div", {
|
|
105
144
|
className: "flex items-center justify-between mb-ds-04",
|
|
106
|
-
children: [/* @__PURE__ */
|
|
145
|
+
children: [/* @__PURE__ */ f(_.p, {
|
|
107
146
|
className: "text-ds-md font-medium text-surface-fg-muted",
|
|
108
147
|
initial: { opacity: 0 },
|
|
109
148
|
animate: { opacity: 1 },
|
|
110
149
|
transition: n.fade,
|
|
111
|
-
children:
|
|
112
|
-
}), /* @__PURE__ */
|
|
150
|
+
children: W
|
|
151
|
+
}), /* @__PURE__ */ p("div", {
|
|
113
152
|
className: "flex items-center gap-ds-03",
|
|
114
|
-
children: [
|
|
115
|
-
data:
|
|
116
|
-
colorClass:
|
|
117
|
-
}),
|
|
118
|
-
icon:
|
|
119
|
-
flash:
|
|
120
|
-
fill:
|
|
121
|
-
speed:
|
|
122
|
-
}) :
|
|
123
|
-
className: r("inline-flex items-center justify-center rounded-control p-ds-02",
|
|
153
|
+
children: [L && L.length >= 2 && /* @__PURE__ */ f(y, {
|
|
154
|
+
data: L,
|
|
155
|
+
colorClass: J
|
|
156
|
+
}), D && F ? /* @__PURE__ */ f(l, {
|
|
157
|
+
icon: D,
|
|
158
|
+
flash: F,
|
|
159
|
+
fill: P,
|
|
160
|
+
speed: I
|
|
161
|
+
}) : D ? N === "icon" ? /* @__PURE__ */ f(_.span, {
|
|
162
|
+
className: r("inline-flex items-center justify-center rounded-control p-ds-02", P === "solid" ? "bg-accent-9 text-accent-fg" : "bg-accent-3 text-accent-11"),
|
|
124
163
|
initial: {
|
|
125
164
|
opacity: 0,
|
|
126
165
|
scale: .96
|
|
@@ -131,11 +170,11 @@ var y = c.forwardRef(({ className: c, label: g, title: y, value: b, prefix: x, s
|
|
|
131
170
|
},
|
|
132
171
|
transition: t.snappy,
|
|
133
172
|
"aria-hidden": "true",
|
|
134
|
-
children: /* @__PURE__ */
|
|
173
|
+
children: /* @__PURE__ */ f(e, {
|
|
135
174
|
size: "md",
|
|
136
|
-
children: a(
|
|
175
|
+
children: a(D, "md")
|
|
137
176
|
})
|
|
138
|
-
}) : /* @__PURE__ */
|
|
177
|
+
}) : /* @__PURE__ */ f(_.span, {
|
|
139
178
|
className: "text-surface-fg-muted",
|
|
140
179
|
initial: {
|
|
141
180
|
opacity: 0,
|
|
@@ -147,43 +186,46 @@ var y = c.forwardRef(({ className: c, label: g, title: y, value: b, prefix: x, s
|
|
|
147
186
|
},
|
|
148
187
|
transition: t.snappy,
|
|
149
188
|
"aria-hidden": "true",
|
|
150
|
-
children: /* @__PURE__ */
|
|
189
|
+
children: /* @__PURE__ */ f(e, {
|
|
151
190
|
size: "lg",
|
|
152
|
-
children: a(
|
|
191
|
+
children: a(D, "lg")
|
|
153
192
|
})
|
|
154
193
|
}) : null]
|
|
155
194
|
})]
|
|
156
195
|
}),
|
|
157
|
-
/* @__PURE__ */
|
|
158
|
-
className: "
|
|
159
|
-
children: /* @__PURE__ */
|
|
160
|
-
className:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
/* @__PURE__ */ p("div", {
|
|
197
|
+
className: r(E === "inline" && T && "flex items-baseline gap-ds-03"),
|
|
198
|
+
children: [/* @__PURE__ */ f("div", {
|
|
199
|
+
className: "overflow-hidden",
|
|
200
|
+
children: /* @__PURE__ */ p(_.p, {
|
|
201
|
+
className: r("inline-block text-ds-3xl font-semibold", N === "tint" ? "text-accent-11" : "text-surface-fg"),
|
|
202
|
+
initial: {
|
|
203
|
+
opacity: 0,
|
|
204
|
+
y: "100%"
|
|
205
|
+
},
|
|
206
|
+
animate: {
|
|
207
|
+
opacity: 1,
|
|
208
|
+
y: 0
|
|
209
|
+
},
|
|
210
|
+
transition: t.smooth,
|
|
211
|
+
children: [
|
|
212
|
+
C && /* @__PURE__ */ f("span", {
|
|
213
|
+
className: "text-surface-fg-muted text-ds-lg",
|
|
214
|
+
children: C
|
|
215
|
+
}),
|
|
216
|
+
/* @__PURE__ */ f("span", {
|
|
217
|
+
className: "tabular-nums",
|
|
218
|
+
children: S
|
|
219
|
+
}),
|
|
220
|
+
w && /* @__PURE__ */ f("span", {
|
|
221
|
+
className: "text-surface-fg-muted text-ds-lg",
|
|
222
|
+
children: w
|
|
223
|
+
})
|
|
224
|
+
]
|
|
225
|
+
})
|
|
226
|
+
}), E === "inline" && Y]
|
|
185
227
|
}),
|
|
186
|
-
|
|
228
|
+
A && /* @__PURE__ */ f(_.p, {
|
|
187
229
|
className: "text-ds-sm text-surface-fg-subtle mt-ds-01",
|
|
188
230
|
initial: { opacity: 0 },
|
|
189
231
|
animate: { opacity: 1 },
|
|
@@ -191,59 +233,22 @@ var y = c.forwardRef(({ className: c, label: g, title: y, value: b, prefix: x, s
|
|
|
191
233
|
...n.fade,
|
|
192
234
|
delay: .1
|
|
193
235
|
},
|
|
194
|
-
children:
|
|
236
|
+
children: A
|
|
195
237
|
}),
|
|
196
|
-
|
|
238
|
+
j != null && /* @__PURE__ */ f(_.div, {
|
|
197
239
|
initial: { opacity: 0 },
|
|
198
240
|
animate: { opacity: 1 },
|
|
199
241
|
transition: {
|
|
200
242
|
...n.fade,
|
|
201
243
|
delay: .15
|
|
202
244
|
},
|
|
203
|
-
children: /* @__PURE__ */
|
|
204
|
-
progress:
|
|
205
|
-
label:
|
|
245
|
+
children: /* @__PURE__ */ f(b, {
|
|
246
|
+
progress: j,
|
|
247
|
+
label: W
|
|
206
248
|
})
|
|
207
249
|
}),
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
initial: {
|
|
211
|
-
opacity: 0,
|
|
212
|
-
y: 8
|
|
213
|
-
},
|
|
214
|
-
animate: {
|
|
215
|
-
opacity: 1,
|
|
216
|
-
y: 0
|
|
217
|
-
},
|
|
218
|
-
transition: {
|
|
219
|
-
...t.smooth,
|
|
220
|
-
delay: .2
|
|
221
|
-
},
|
|
222
|
-
children: [
|
|
223
|
-
/* @__PURE__ */ u(h.span, {
|
|
224
|
-
className: "inline-flex",
|
|
225
|
-
initial: {
|
|
226
|
-
opacity: .5,
|
|
227
|
-
scale: 1.4
|
|
228
|
-
},
|
|
229
|
-
animate: {
|
|
230
|
-
opacity: 1,
|
|
231
|
-
scale: 1
|
|
232
|
-
},
|
|
233
|
-
transition: t.bouncy,
|
|
234
|
-
children: /* @__PURE__ */ u(i, {
|
|
235
|
-
icon: W,
|
|
236
|
-
size: "sm"
|
|
237
|
-
})
|
|
238
|
-
}),
|
|
239
|
-
/* @__PURE__ */ u("span", { children: C.value }),
|
|
240
|
-
E && /* @__PURE__ */ u("span", {
|
|
241
|
-
className: "text-surface-fg-subtle font-normal",
|
|
242
|
-
children: E
|
|
243
|
-
})
|
|
244
|
-
]
|
|
245
|
-
}),
|
|
246
|
-
L && /* @__PURE__ */ u(h.div, {
|
|
250
|
+
E === "block" && Y,
|
|
251
|
+
B && /* @__PURE__ */ f(_.div, {
|
|
247
252
|
className: "mt-ds-04 pt-ds-04 border-t border-surface-border text-ds-sm",
|
|
248
253
|
initial: { opacity: 0 },
|
|
249
254
|
animate: { opacity: 1 },
|
|
@@ -251,31 +256,44 @@ var y = c.forwardRef(({ className: c, label: g, title: y, value: b, prefix: x, s
|
|
|
251
256
|
...n.fade,
|
|
252
257
|
delay: .25
|
|
253
258
|
},
|
|
254
|
-
children:
|
|
259
|
+
children: B
|
|
260
|
+
})
|
|
261
|
+
] }), Z = N === "tint" ? "bg-linear-to-t from-accent-2 to-surface-raised" : void 0, Q = /* @__PURE__ */ f(s, { children: X });
|
|
262
|
+
return z ? /* @__PURE__ */ f(U, {
|
|
263
|
+
ref: H,
|
|
264
|
+
href: z,
|
|
265
|
+
onClick: R,
|
|
266
|
+
className: "block no-underline",
|
|
267
|
+
"aria-label": G,
|
|
268
|
+
...V,
|
|
269
|
+
children: /* @__PURE__ */ f(o, {
|
|
270
|
+
variant: M,
|
|
271
|
+
interactive: !0,
|
|
272
|
+
className: Z,
|
|
273
|
+
children: Q
|
|
255
274
|
})
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
children: q
|
|
275
|
+
}) : R ? /* @__PURE__ */ f(o, {
|
|
276
|
+
ref: H,
|
|
277
|
+
variant: M,
|
|
278
|
+
interactive: !0,
|
|
279
|
+
className: r(Z, u),
|
|
280
|
+
role: "button",
|
|
281
|
+
tabIndex: 0,
|
|
282
|
+
"aria-label": G,
|
|
283
|
+
onClick: R,
|
|
284
|
+
onKeyDown: (e) => {
|
|
285
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), R());
|
|
286
|
+
},
|
|
287
|
+
...V,
|
|
288
|
+
children: Q
|
|
289
|
+
}) : /* @__PURE__ */ f(o, {
|
|
290
|
+
ref: H,
|
|
291
|
+
variant: M,
|
|
292
|
+
className: r(Z, u),
|
|
293
|
+
...V,
|
|
294
|
+
children: Q
|
|
277
295
|
});
|
|
278
296
|
});
|
|
279
|
-
|
|
297
|
+
x.displayName = "StatCard";
|
|
280
298
|
//#endregion
|
|
281
|
-
export {
|
|
299
|
+
export { x as StatCard };
|
package/dist/ui/stat-card.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat-card.js","names":[],"sources":["../../src/ui/stat-card.tsx"],"sourcesContent":["'use client'\n\nimport { IconMinus, IconTrendingDown, IconTrendingUp } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { IconProvider } from './icon-context'\nimport type { IconInput } from './lib/icon-input'\nimport { useLink } from './lib/link-context'\nimport { springs, tweens } from './lib/motion'\nimport { normalizeIcon } from './lib/normalize-icon'\nimport { cn } from './lib/utils'\nimport { StatFlash, type FlashPreset, type FlashSpec, type FlashSpeed } from './stat-flash'\n\n/**\n * Props for StatCard — a dashboard metric tile displaying a label, a large numeric value,\n * an optional trend delta (with directional arrow icon), and an optional header icon.\n *\n * **Surface:** `surface=\"raised\"` (default) is elevation-led — the shadow's own 1px ring is the\n * edge, no border (make-kit rule #6). `surface=\"flat\"` is border-led, no shadow.\n *\n * **Accent:** `accentStyle=\"none\"` (default) is neutral; `\"icon\"` wraps `icon` in an accent chip\n * (`iconFill=\"soft\" | \"solid\"`); `\"tint\"` applies a subtle accent surface wash + accent value.\n * (Replaces the removed `accent` left-rail prop — see CHANGELOG migration.)\n *\n * **Delta direction:** `'up'` renders a green trending-up arrow, `'down'` renders a red\n * trending-down arrow, `'neutral'` renders a grey dash. The `delta.value` is a formatted\n * string (e.g. `\"+8%\"` or `\"−120\"`).\n *\n * **Loading state:** Pass `loading={true}` to render a pulse-skeleton placeholder instead of data.\n *\n * @example\n * // Revenue metric with a positive trend:\n * <StatCard\n * label=\"Monthly Revenue\"\n * value=\"$48,200\"\n * delta={{ value: \"+12%\", direction: \"up\" }}\n * icon={<IconCurrencyDollar />}\n * />\n *\n * @example\n * // Open ticket count with a downward trend (good for support queues):\n * <StatCard\n * label=\"Open Tickets\"\n * value={142}\n * delta={{ value: \"−18\", direction: \"down\" }}\n * />\n *\n * @example\n * // Loading skeleton while data is fetching:\n * <StatCard label=\"Users\" value={0} loading={isFetching} />\n *\n * @example\n * // Simple metric with no trend (stable, neutral):\n * <StatCard\n * label=\"Storage Used\"\n * value=\"4.2 GB\"\n * delta={{ value: \"No change\", direction: \"neutral\" }}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Heading text for the metric. `title` is an alias for `label`. */\n label?: string\n /** Alias for `label` — use whichever feels natural. */\n title?: string\n value: string | number\n /** Prefix before value, e.g. \"$\" */\n prefix?: string\n /** Suffix after value, e.g. \"users\" */\n suffix?: string\n delta?: {\n value: string\n direction: 'up' | 'down' | 'neutral'\n }\n icon?: IconInput\n loading?: boolean\n /** Comparison period label shown after delta, e.g. \"vs last month\" */\n comparisonLabel?: string\n /** Secondary metric below main value, e.g. \"of $50,000 target\" */\n secondaryLabel?: string\n /** Progress toward a target (0-100). Renders a thin progress bar below the value. */\n progress?: number\n /** Surface treatment: `raised` (ring-in-shadow, no border — default) or `flat` (border, no shadow). */\n surface?: 'raised' | 'flat'\n /** How the brand accent reads: `none` (neutral — default), `icon` (accent chip around `icon`), or `tint` (subtle accent surface wash + accent value). */\n accentStyle?: 'none' | 'icon' | 'tint'\n /** When `accentStyle=\"icon\"`: `soft` (tinted chip) or `solid` (filled accent chip). @default 'soft' */\n iconFill?: 'soft' | 'solid'\n /**\n * Opt-in entrance flash: the icon chip mounts showing a transient state (e.g. a green up-arrow)\n * then settles to `icon`. A preset (`'up' | 'down' | 'goal' | 'record' | 'alert' | 'live'`) or an\n * explicit `{ tone, icon }`. Requires `icon`; implies the icon chip. Off by default.\n */\n flash?: FlashPreset | FlashSpec\n /** Speed of the entrance flash: `fast` | `normal` | `slow`. @default 'normal' */\n flashSpeed?: FlashSpeed\n /** Sparkline data points. Renders a mini SVG line chart in the card. */\n sparkline?: number[]\n /** Make the card clickable with hover state */\n onClick?: () => void\n /** Href — makes the card a link (uses the LinkContext Link component) */\n href?: string\n /** Footer content rendered below the card body, e.g. \"View details →\" */\n footer?: React.ReactNode\n}\n\nfunction buildSparklinePath(raw: number[], width: number, height: number): string {\n const data = raw.filter((v) => Number.isFinite(v))\n if (data.length < 2) return ''\n const min = Math.min(...data)\n const max = Math.max(...data)\n const range = max - min || 1\n const stepX = width / (data.length - 1)\n return data\n .map((v, i) => {\n const x = i * stepX\n const y = height - ((v - min) / range) * height\n return `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`\n })\n .join(' ')\n}\n\nfunction Sparkline({\n data,\n colorClass,\n}: {\n data: number[]\n colorClass: string\n}) {\n const id = React.useId()\n const pathRef = React.useRef<SVGPathElement>(null)\n const [pathLength, setPathLength] = React.useState(0)\n const svgWidth = 80\n const svgHeight = 32\n const path = buildSparklinePath(data, svgWidth, svgHeight)\n\n React.useEffect(() => {\n if (pathRef.current) {\n setPathLength(pathRef.current.getTotalLength())\n }\n }, [path])\n\n if (!path) return null\n\n // Build area fill path (close to bottom-right then bottom-left)\n const areaPath = `${path} L${svgWidth.toFixed(1)},${svgHeight.toFixed(1)} L0,${svgHeight.toFixed(1)} Z`\n\n return (\n <div className={cn('w-20 h-8', colorClass)} aria-hidden=\"true\">\n <svg\n viewBox={`0 0 ${svgWidth} ${svgHeight}`}\n className=\"w-full h-full overflow-visible\"\n preserveAspectRatio=\"none\"\n >\n <defs>\n <linearGradient id={`sparkline-fill-${id}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"currentColor\" stopOpacity=\"0.1\" />\n <stop offset=\"100%\" stopColor=\"currentColor\" stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={areaPath} fill={`url(#sparkline-fill-${id})`} />\n <path\n ref={pathRef}\n d={path}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n opacity: pathLength === 0 ? 0 : 1,\n strokeDasharray: pathLength,\n strokeDashoffset: pathLength,\n animation: pathLength > 0 ? `sparkline-draw-${id.replace(/:/g, '')} 1s ease-out forwards` : 'none',\n }}\n />\n </svg>\n {pathLength > 0 && (\n <style>{`@keyframes sparkline-draw-${id.replace(/:/g, '')} { to { stroke-dashoffset: 0; } }`}</style>\n )}\n </div>\n )\n}\n\nfunction ProgressBar({ progress, label }: { progress: number; label: string }) {\n const clamped = Math.max(0, Math.min(100, progress))\n const barColor =\n clamped >= 90 ? 'bg-success-9' : clamped >= 70 ? 'bg-warning-9' : 'bg-accent-9'\n\n return (\n <div className=\"h-1 w-full rounded-pill bg-surface-raised mt-ds-04\" role=\"progressbar\" aria-label={`${label} progress`} aria-valuenow={clamped} aria-valuemin={0} aria-valuemax={100}>\n <div\n className={cn('h-full rounded-pill transition-[width] duration-moderate-02 ease-productive-standard', barColor)}\n style={{ width: `${clamped}%` }}\n />\n </div>\n )\n}\n\nconst StatCard = React.forwardRef<HTMLDivElement, StatCardProps>(\n (\n {\n className,\n label,\n title,\n value,\n prefix,\n suffix,\n delta,\n icon,\n loading,\n comparisonLabel,\n secondaryLabel,\n progress,\n surface = 'raised',\n accentStyle = 'none',\n iconFill = 'soft',\n flash,\n flashSpeed,\n sparkline,\n onClick,\n href,\n footer,\n ...props\n },\n ref,\n ) => {\n const Link = useLink()\n const resolvedLabel = title ?? label ?? ''\n const isClickable = !!(onClick || href)\n const computedAriaLabel =\n isClickable && !props['aria-label'] ? `View ${resolvedLabel}` : props['aria-label']\n\n if (loading) {\n return (\n <div\n ref={ref}\n className={cn(\n 'rounded-surface bg-surface-raised p-ds-05b',\n surface === 'flat' ? 'border border-surface-border' : 'shadow-raised',\n className,\n )}\n {...props}\n >\n <div className=\"h-ds-04 w-24 rounded-control-inner bg-skeleton-base animate-pulse mb-ds-05\" />\n <div className=\"h-ds-sm w-32 rounded-control bg-skeleton-base animate-pulse mb-ds-03\" />\n <div className=\"h-3 w-16 rounded-control-inner bg-skeleton-base animate-pulse\" />\n </div>\n )\n }\n\n const DeltaIcon =\n delta?.direction === 'up'\n ? IconTrendingUp\n : delta?.direction === 'down'\n ? IconTrendingDown\n : IconMinus\n\n const deltaColour =\n delta?.direction === 'up'\n ? 'text-success-11'\n : delta?.direction === 'down'\n ? 'text-error-11'\n : 'text-surface-fg-muted'\n\n const sparklineColor =\n delta?.direction === 'up'\n ? 'text-success-11'\n : delta?.direction === 'down'\n ? 'text-error-11'\n : 'text-accent-11'\n\n const cardContent = (\n <>\n <div className=\"flex items-center justify-between mb-ds-04\">\n <motion.p\n className=\"text-ds-md font-medium text-surface-fg-muted\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweens.fade}\n >\n {resolvedLabel}\n </motion.p>\n <div className=\"flex items-center gap-ds-03\">\n {sparkline && sparkline.length >= 2 && (\n <Sparkline data={sparkline} colorClass={sparklineColor} />\n )}\n {icon && flash ? (\n <StatFlash icon={icon} flash={flash} fill={iconFill} speed={flashSpeed} />\n ) : icon ? (\n accentStyle === 'icon' ? (\n <motion.span\n className={cn(\n 'inline-flex items-center justify-center rounded-control p-ds-02',\n iconFill === 'solid'\n ? 'bg-accent-9 text-accent-fg'\n : 'bg-accent-3 text-accent-11',\n )}\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.snappy}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"md\">{normalizeIcon(icon, 'md')}</IconProvider>\n </motion.span>\n ) : (\n <motion.span\n className=\"text-surface-fg-muted\"\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.snappy}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"lg\">{normalizeIcon(icon, 'lg')}</IconProvider>\n </motion.span>\n )\n ) : null}\n </div>\n </div>\n <div className=\"overflow-hidden\">\n <motion.p\n className={cn(\n 'inline-block text-ds-3xl font-semibold',\n accentStyle === 'tint' ? 'text-accent-11' : 'text-surface-fg',\n )}\n initial={{ opacity: 0, y: '100%' }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.smooth}\n >\n {prefix && (\n <span className=\"text-surface-fg-muted text-ds-lg\">{prefix}</span>\n )}\n <span className=\"tabular-nums\">{value}</span>\n {suffix && (\n <span className=\"text-surface-fg-muted text-ds-lg\">{suffix}</span>\n )}\n </motion.p>\n </div>\n {secondaryLabel && (\n <motion.p\n className=\"text-ds-sm text-surface-fg-subtle mt-ds-01\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ ...tweens.fade, delay: 0.1 }}\n >\n {secondaryLabel}\n </motion.p>\n )}\n {progress != null && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ ...tweens.fade, delay: 0.15 }}\n >\n <ProgressBar progress={progress} label={resolvedLabel} />\n </motion.div>\n )}\n {delta && (\n <motion.div\n className={cn(\n 'mt-ds-03 flex items-center gap-ds-02 text-ds-sm font-medium',\n deltaColour,\n )}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ ...springs.smooth, delay: 0.2 }}\n >\n <motion.span\n className=\"inline-flex\"\n initial={{ opacity: 0.5, scale: 1.4 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.bouncy}\n >\n <Icon icon={DeltaIcon} size=\"sm\" />\n </motion.span>\n <span>{delta.value}</span>\n {comparisonLabel && (\n <span className=\"text-surface-fg-subtle font-normal\">{comparisonLabel}</span>\n )}\n </motion.div>\n )}\n {footer && (\n <motion.div\n className=\"mt-ds-04 pt-ds-04 border-t border-surface-border text-ds-sm\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ ...tweens.fade, delay: 0.25 }}\n >\n {footer}\n </motion.div>\n )}\n </>\n )\n\n const cardClasses = cn(\n 'rounded-surface p-ds-05b',\n accentStyle === 'tint'\n ? 'bg-linear-to-t from-accent-2 to-surface-raised'\n : 'bg-surface-raised',\n surface === 'flat' ? 'border border-surface-border' : 'shadow-raised',\n isClickable &&\n 'cursor-pointer hover:shadow-raised-hover transition-[box-shadow] duration-fast-02 ease-productive-standard group',\n className,\n )\n\n if (href) {\n return (\n <Link\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={href}\n onClick={onClick}\n className={cn(cardClasses, 'block no-underline')}\n aria-label={computedAriaLabel}\n {...(props as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n >\n {cardContent}\n </Link>\n )\n }\n\n return (\n <div\n ref={ref}\n className={cardClasses}\n onClick={onClick}\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n aria-label={computedAriaLabel}\n onKeyDown={\n onClick\n ? (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onClick()\n }\n }\n : undefined\n }\n {...props}\n >\n {cardContent}\n </div>\n )\n },\n)\n\nStatCard.displayName = 'StatCard'\n\nexport { StatCard }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stat-card.js","names":[],"sources":["../../src/ui/stat-card.tsx"],"sourcesContent":["'use client'\n\nimport { IconMinus, IconTrendingDown, IconTrendingUp } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Card, CardContent } from './card'\nimport { Icon } from './icon'\nimport { IconProvider } from './icon-context'\nimport type { IconInput } from './lib/icon-input'\nimport { useLink } from './lib/link-context'\nimport { springs, tweens } from './lib/motion'\nimport { normalizeIcon } from './lib/normalize-icon'\nimport { cn } from './lib/utils'\nimport { type FlashPreset, type FlashSpec, type FlashSpeed,StatFlash } from './stat-flash'\n\n/**\n * Props for StatCard — a dashboard metric tile displaying a label, a large numeric value,\n * an optional trend delta (with directional arrow icon), and an optional header icon.\n *\n * **Surface:** delegated to `Card` via `variant` — `default` (ring-in-shadow, no border) |\n * `elevated` | `outline` (border, no shadow) | `flat`. StatCard composes `<Card>`, so the surface,\n * padding (gap model), and elevation all live in one place.\n *\n * **Accent:** `accentStyle=\"none\"` (default) is neutral; `\"icon\"` wraps `icon` in an accent chip\n * (`iconFill=\"soft\" | \"solid\"`); `\"tint\"` applies a subtle accent surface wash + accent value.\n * (Replaces the removed `accent` left-rail prop — see CHANGELOG migration.)\n *\n * **Delta direction:** `'up'` renders a green trending-up arrow, `'down'` renders a red\n * trending-down arrow, `'neutral'` renders a grey dash. The `delta.value` is a formatted\n * string (e.g. `\"+8%\"` or `\"−120\"`).\n *\n * **Loading state:** Pass `loading={true}` to render a pulse-skeleton placeholder instead of data.\n *\n * @example\n * // Revenue metric with a positive trend:\n * <StatCard\n * label=\"Monthly Revenue\"\n * value=\"$48,200\"\n * delta={{ value: \"+12%\", direction: \"up\" }}\n * icon={<IconCurrencyDollar />}\n * />\n *\n * @example\n * // Open ticket count with a downward trend (good for support queues):\n * <StatCard\n * label=\"Open Tickets\"\n * value={142}\n * delta={{ value: \"−18\", direction: \"down\" }}\n * />\n *\n * @example\n * // Loading skeleton while data is fetching:\n * <StatCard label=\"Users\" value={0} loading={isFetching} />\n *\n * @example\n * // Simple metric with no trend (stable, neutral):\n * <StatCard\n * label=\"Storage Used\"\n * value=\"4.2 GB\"\n * delta={{ value: \"No change\", direction: \"neutral\" }}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface StatCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'> {\n /** Heading text for the metric. `title` is an alias for `label`. */\n label?: string\n /** Alias for `label` — use whichever feels natural. */\n title?: string\n value: string | number\n /** Prefix before value, e.g. \"$\" */\n prefix?: string\n /** Suffix after value, e.g. \"users\" */\n suffix?: string\n delta?: {\n value: string\n direction: 'up' | 'down' | 'neutral'\n }\n /** Where the delta sits relative to the value: `block` (below — default) or `inline` (on the value's baseline, to its right). @default 'block' */\n deltaPlacement?: 'block' | 'inline'\n icon?: IconInput\n loading?: boolean\n /** Comparison period label shown after delta, e.g. \"vs last month\" */\n comparisonLabel?: string\n /** Secondary metric below main value, e.g. \"of $50,000 target\" */\n secondaryLabel?: string\n /** Progress toward a target (0-100). Renders a thin progress bar below the value. */\n progress?: number\n /** Surface variant, delegated to Card: `default` (ring-in-shadow) | `elevated` | `outline` (border, no shadow) | `flat`. @default 'default' */\n variant?: 'default' | 'elevated' | 'outline' | 'flat'\n /** How the brand accent reads: `none` (neutral — default), `icon` (accent chip around `icon`), or `tint` (subtle accent surface wash + accent value). */\n accentStyle?: 'none' | 'icon' | 'tint'\n /** When `accentStyle=\"icon\"`: `soft` (tinted chip) or `solid` (filled accent chip). @default 'soft' */\n iconFill?: 'soft' | 'solid'\n /**\n * Opt-in entrance flash: the icon chip mounts showing a transient state (e.g. a green up-arrow)\n * then settles to `icon`. A preset (`'up' | 'down' | 'goal' | 'record' | 'alert' | 'live'`) or an\n * explicit `{ tone, icon }`. Requires `icon`; implies the icon chip. Off by default.\n */\n flash?: FlashPreset | FlashSpec\n /** Speed of the entrance flash: `fast` | `normal` | `slow`. @default 'normal' */\n flashSpeed?: FlashSpeed\n /** Sparkline data points. Renders a mini SVG line chart in the card. */\n sparkline?: number[]\n /** Make the card clickable with hover state */\n onClick?: () => void\n /** Href — makes the card a link (uses the LinkContext Link component) */\n href?: string\n /** Footer content rendered below the card body, e.g. \"View details →\" */\n footer?: React.ReactNode\n}\n\nfunction buildSparklinePath(raw: number[], width: number, height: number): string {\n const data = raw.filter((v) => Number.isFinite(v))\n if (data.length < 2) return ''\n const min = Math.min(...data)\n const max = Math.max(...data)\n const range = max - min || 1\n const stepX = width / (data.length - 1)\n return data\n .map((v, i) => {\n const x = i * stepX\n const y = height - ((v - min) / range) * height\n return `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`\n })\n .join(' ')\n}\n\nfunction Sparkline({\n data,\n colorClass,\n}: {\n data: number[]\n colorClass: string\n}) {\n const id = React.useId()\n const pathRef = React.useRef<SVGPathElement>(null)\n const [pathLength, setPathLength] = React.useState(0)\n const svgWidth = 80\n const svgHeight = 32\n const path = buildSparklinePath(data, svgWidth, svgHeight)\n\n React.useEffect(() => {\n if (pathRef.current) {\n setPathLength(pathRef.current.getTotalLength())\n }\n }, [path])\n\n if (!path) return null\n\n // Build area fill path (close to bottom-right then bottom-left)\n const areaPath = `${path} L${svgWidth.toFixed(1)},${svgHeight.toFixed(1)} L0,${svgHeight.toFixed(1)} Z`\n\n return (\n <div className={cn('w-20 h-8', colorClass)} aria-hidden=\"true\">\n <svg\n viewBox={`0 0 ${svgWidth} ${svgHeight}`}\n className=\"w-full h-full overflow-visible\"\n preserveAspectRatio=\"none\"\n >\n <defs>\n <linearGradient id={`sparkline-fill-${id}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"currentColor\" stopOpacity=\"0.1\" />\n <stop offset=\"100%\" stopColor=\"currentColor\" stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={areaPath} fill={`url(#sparkline-fill-${id})`} />\n <path\n ref={pathRef}\n d={path}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n opacity: pathLength === 0 ? 0 : 1,\n strokeDasharray: pathLength,\n strokeDashoffset: pathLength,\n animation: pathLength > 0 ? `sparkline-draw-${id.replace(/:/g, '')} 1s ease-out forwards` : 'none',\n }}\n />\n </svg>\n {pathLength > 0 && (\n <style>{`@keyframes sparkline-draw-${id.replace(/:/g, '')} { to { stroke-dashoffset: 0; } }`}</style>\n )}\n </div>\n )\n}\n\nfunction ProgressBar({ progress, label }: { progress: number; label: string }) {\n const clamped = Math.max(0, Math.min(100, progress))\n const barColor =\n clamped >= 90 ? 'bg-success-9' : clamped >= 70 ? 'bg-warning-9' : 'bg-accent-9'\n\n return (\n <div className=\"h-1 w-full rounded-pill bg-surface-raised mt-ds-04\" role=\"progressbar\" aria-label={`${label} progress`} aria-valuenow={clamped} aria-valuemin={0} aria-valuemax={100}>\n <div\n className={cn('h-full rounded-pill transition-[width] duration-moderate-02 ease-productive-standard', barColor)}\n style={{ width: `${clamped}%` }}\n />\n </div>\n )\n}\n\nconst StatCard = React.forwardRef<HTMLDivElement, StatCardProps>(\n (\n {\n className,\n label,\n title,\n value,\n prefix,\n suffix,\n delta,\n deltaPlacement = 'block',\n icon,\n loading,\n comparisonLabel,\n secondaryLabel,\n progress,\n variant = 'default',\n accentStyle = 'none',\n iconFill = 'soft',\n flash,\n flashSpeed,\n sparkline,\n onClick,\n href,\n footer,\n ...props\n },\n ref,\n ) => {\n const Link = useLink()\n const resolvedLabel = title ?? label ?? ''\n const isClickable = !!(onClick || href)\n const computedAriaLabel =\n isClickable && !props['aria-label'] ? `View ${resolvedLabel}` : props['aria-label']\n\n if (loading) {\n return (\n <Card ref={ref} variant={variant} className={className} {...props}>\n <CardContent>\n <div className=\"h-ds-04 w-24 rounded-control-inner bg-skeleton-base animate-pulse mb-ds-05\" />\n <div className=\"h-ds-sm w-32 rounded-control bg-skeleton-base animate-pulse mb-ds-03\" />\n <div className=\"h-3 w-16 rounded-control-inner bg-skeleton-base animate-pulse\" />\n </CardContent>\n </Card>\n )\n }\n\n const DeltaIcon =\n delta?.direction === 'up'\n ? IconTrendingUp\n : delta?.direction === 'down'\n ? IconTrendingDown\n : IconMinus\n\n const deltaColour =\n delta?.direction === 'up'\n ? 'text-success-11'\n : delta?.direction === 'down'\n ? 'text-error-11'\n : 'text-surface-fg-muted'\n\n const sparklineColor =\n delta?.direction === 'up'\n ? 'text-success-11'\n : delta?.direction === 'down'\n ? 'text-error-11'\n : 'text-accent-11'\n\n const deltaNode = delta ? (\n <motion.div\n className={cn(\n 'flex items-center gap-ds-02 text-ds-sm font-medium',\n deltaColour,\n // block placement owns the gap to the value; inline rides the value's baseline row.\n deltaPlacement === 'block' && 'mt-ds-03',\n )}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ ...springs.smooth, delay: 0.2 }}\n >\n <motion.span\n className=\"inline-flex\"\n initial={{ opacity: 0.5, scale: 1.4 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.bouncy}\n >\n <Icon icon={DeltaIcon} size=\"sm\" />\n </motion.span>\n <span>{delta.value}</span>\n {comparisonLabel && (\n <span className=\"text-surface-fg-subtle font-normal\">{comparisonLabel}</span>\n )}\n </motion.div>\n ) : null\n\n const cardContent = (\n <>\n <div className=\"flex items-center justify-between mb-ds-04\">\n <motion.p\n className=\"text-ds-md font-medium text-surface-fg-muted\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweens.fade}\n >\n {resolvedLabel}\n </motion.p>\n <div className=\"flex items-center gap-ds-03\">\n {sparkline && sparkline.length >= 2 && (\n <Sparkline data={sparkline} colorClass={sparklineColor} />\n )}\n {icon && flash ? (\n <StatFlash icon={icon} flash={flash} fill={iconFill} speed={flashSpeed} />\n ) : icon ? (\n accentStyle === 'icon' ? (\n <motion.span\n className={cn(\n 'inline-flex items-center justify-center rounded-control p-ds-02',\n iconFill === 'solid'\n ? 'bg-accent-9 text-accent-fg'\n : 'bg-accent-3 text-accent-11',\n )}\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.snappy}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"md\">{normalizeIcon(icon, 'md')}</IconProvider>\n </motion.span>\n ) : (\n <motion.span\n className=\"text-surface-fg-muted\"\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.snappy}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"lg\">{normalizeIcon(icon, 'lg')}</IconProvider>\n </motion.span>\n )\n ) : null}\n </div>\n </div>\n <div className={cn(deltaPlacement === 'inline' && delta && 'flex items-baseline gap-ds-03')}>\n <div className=\"overflow-hidden\">\n <motion.p\n className={cn(\n 'inline-block text-ds-3xl font-semibold',\n accentStyle === 'tint' ? 'text-accent-11' : 'text-surface-fg',\n )}\n initial={{ opacity: 0, y: '100%' }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.smooth}\n >\n {prefix && (\n <span className=\"text-surface-fg-muted text-ds-lg\">{prefix}</span>\n )}\n <span className=\"tabular-nums\">{value}</span>\n {suffix && (\n <span className=\"text-surface-fg-muted text-ds-lg\">{suffix}</span>\n )}\n </motion.p>\n </div>\n {deltaPlacement === 'inline' && deltaNode}\n </div>\n {secondaryLabel && (\n <motion.p\n className=\"text-ds-sm text-surface-fg-subtle mt-ds-01\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ ...tweens.fade, delay: 0.1 }}\n >\n {secondaryLabel}\n </motion.p>\n )}\n {progress != null && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ ...tweens.fade, delay: 0.15 }}\n >\n <ProgressBar progress={progress} label={resolvedLabel} />\n </motion.div>\n )}\n {deltaPlacement === 'block' && deltaNode}\n {footer && (\n <motion.div\n className=\"mt-ds-04 pt-ds-04 border-t border-surface-border text-ds-sm\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ ...tweens.fade, delay: 0.25 }}\n >\n {footer}\n </motion.div>\n )}\n </>\n )\n\n // accentStyle=\"tint\" → a subtle accent gradient wash over Card's surface.\n const tintClass =\n accentStyle === 'tint' ? 'bg-linear-to-t from-accent-2 to-surface-raised' : undefined\n const body = <CardContent>{cardContent}</CardContent>\n\n // href → wrap Card in the framework Link (Card stays the shell; hover-lift inside).\n if (href) {\n return (\n <Link\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={href}\n onClick={onClick}\n className=\"block no-underline\"\n aria-label={computedAriaLabel}\n {...(props as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n >\n <Card variant={variant} interactive className={tintClass}>\n {body}\n </Card>\n </Link>\n )\n }\n\n // onClick → interactive Card with button semantics + keyboard activation.\n if (onClick) {\n return (\n <Card\n ref={ref}\n variant={variant}\n interactive\n className={cn(tintClass, className)}\n role=\"button\"\n tabIndex={0}\n aria-label={computedAriaLabel}\n onClick={onClick}\n onKeyDown={(e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onClick()\n }\n }}\n {...props}\n >\n {body}\n </Card>\n )\n }\n\n return (\n <Card ref={ref} variant={variant} className={cn(tintClass, className)} {...props}>\n {body}\n </Card>\n )\n },\n)\n\nStatCard.displayName = 'StatCard'\n\nexport { StatCard }\n"],"mappings":"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"}
|
package/dist/ui/tabs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/ui/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,KAAK,eAAe,GAAG,YAAY,GAAG,UAAU,CAAA;AAIhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,QAAA,MAAM,IAAI,mJAyCR,CAAA;AAGF,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAA;AAGjF,KAAK,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAClC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAgBrC,QAAA,MAAM,gBAAgB;;;;8EAwBpB,CAAA;AAEF,QAAA,MAAM,mBAAmB;;;8EAuBxB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,aACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,EAC/D,YAAY,CAAC,OAAO,gBAAgB,CAAC;IACvC,kFAAkF;IAClF,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,QAAA,MAAM,QAAQ,sFA6BZ,CAAA;AAGF,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAClE,YAAY,CAAC,OAAO,mBAAmB,CAAC;CAAG;AAa/C,QAAA,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/ui/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,KAAK,eAAe,GAAG,YAAY,GAAG,UAAU,CAAA;AAIhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,QAAA,MAAM,IAAI,mJAyCR,CAAA;AAGF,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAA;AAGjF,KAAK,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAClC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAgBrC,QAAA,MAAM,gBAAgB;;;;8EAwBpB,CAAA;AAEF,QAAA,MAAM,mBAAmB;;;8EAuBxB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,aACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,EAC/D,YAAY,CAAC,OAAO,gBAAgB,CAAC;IACvC,kFAAkF;IAClF,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,QAAA,MAAM,QAAQ,sFA6BZ,CAAA;AAGF,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAClE,YAAY,CAAC,OAAO,mBAAmB,CAAC;CAAG;AAa/C,QAAA,MAAM,WAAW,4FAsDf,CAAA;AAGF,QAAA,MAAM,WAAW,0JA0Bf,CAAA;AAGF,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAA;AAE3F,OAAO,EAAE,IAAI,EAAE,WAAW,EAAC,QAAQ,EAAE,WAAW,EAAE,CAAA;AAClD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAC,QAAQ,EAAE,CAAA"}
|
package/dist/ui/tabs.js
CHANGED
|
@@ -135,8 +135,11 @@ var b = {
|
|
|
135
135
|
transition: i.smooth
|
|
136
136
|
}),
|
|
137
137
|
/* @__PURE__ */ l("span", {
|
|
138
|
-
className: "relative z-[1] inline-flex items-center gap-ds-02",
|
|
139
|
-
children:
|
|
138
|
+
className: "relative z-[1] inline-flex min-w-0 items-center gap-ds-02",
|
|
139
|
+
children: /* @__PURE__ */ l("span", {
|
|
140
|
+
className: "truncate",
|
|
141
|
+
children: r
|
|
142
|
+
})
|
|
140
143
|
}),
|
|
141
144
|
y === "line" && w && /* @__PURE__ */ l(f.span, {
|
|
142
145
|
layoutId: `${d.layoutId}-line`,
|