@alfadocs/ui-kit 0.14.1 → 0.15.1

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.
Files changed (36) hide show
  1. package/dist/_chunks/carousel.agent-OTn-kMQg.js +1669 -0
  2. package/dist/_chunks/{header-D0ULgQl3.js → header-DqmKROIY.js} +42 -52
  3. package/dist/_chunks/{map-view-Dd48BxVB.js → map-view-DVP-Kp9l.js} +445 -444
  4. package/dist/_chunks/menu-XRhW3_99.js +16 -0
  5. package/dist/_chunks/{patient-shell-CL20JnVJ.js → patient-shell-BE0CdPOJ.js} +2 -2
  6. package/dist/_chunks/public-header.agent-ZLBAQ30j.js +242 -0
  7. package/dist/_chunks/stat-CYEx8sIR.js +317 -0
  8. package/dist/_chunks/use-count-up-BLLetaZ8.js +109 -0
  9. package/dist/agent-catalog.json +92 -1
  10. package/dist/components/carousel/carousel.agent.d.ts +4 -0
  11. package/dist/components/carousel/carousel.d.ts +45 -0
  12. package/dist/components/carousel/index.d.ts +3 -0
  13. package/dist/components/carousel/index.js +6 -0
  14. package/dist/components/header/index.js +1 -1
  15. package/dist/components/index.d.ts +2 -0
  16. package/dist/components/map-view/index.js +1 -1
  17. package/dist/components/map-view/map-view.d.ts +8 -0
  18. package/dist/components/public-header/index.d.ts +3 -0
  19. package/dist/components/public-header/index.js +6 -0
  20. package/dist/components/public-header/public-header.agent.d.ts +4 -0
  21. package/dist/components/public-header/public-header.d.ts +43 -0
  22. package/dist/components/stat/index.js +1 -1
  23. package/dist/components/stat/stat.d.ts +31 -0
  24. package/dist/hooks/index.d.ts +2 -0
  25. package/dist/hooks/index.js +10 -8
  26. package/dist/hooks/use-count-up.d.ts +88 -0
  27. package/dist/i18n/config.js +51 -0
  28. package/dist/i18n/resources.d.ts +51 -0
  29. package/dist/index.js +367 -361
  30. package/dist/locales/de.json +17 -0
  31. package/dist/locales/en.json +17 -0
  32. package/dist/locales/it.json +17 -0
  33. package/dist/patterns/patient-shell/index.js +1 -1
  34. package/dist/tokens.css +1 -1
  35. package/package.json +10 -1
  36. package/dist/_chunks/stat-CDQ_a0vk.js +0 -228
@@ -0,0 +1,16 @@
1
+ import { c as e } from "./createLucideIcon-CrFbzy84.js";
2
+ /**
3
+ * @license lucide-react v1.8.0 - ISC
4
+ *
5
+ * This source code is licensed under the ISC license.
6
+ * See the LICENSE file in the root directory of this source tree.
7
+ */
8
+ const t = [
9
+ ["path", { d: "M4 5h16", key: "1tepv9" }],
10
+ ["path", { d: "M4 12h16", key: "1lakjw" }],
11
+ ["path", { d: "M4 19h16", key: "1djgab" }]
12
+ ], o = e("menu", t);
13
+ export {
14
+ o as M
15
+ };
16
+ //# sourceMappingURL=menu-XRhW3_99.js.map
@@ -4,7 +4,7 @@ import { useTranslation as c } from "react-i18next";
4
4
  import { A as y } from "./app-frame-BYx1gcV7.js";
5
5
  import { I } from "./icon-button-C4CGcYuz.js";
6
6
  import { D as n } from "./dropdown-menu-dyV7gHh_.js";
7
- import { H as L, g as A, f as H, e as x, a as C, c as M, d as B } from "./header-D0ULgQl3.js";
7
+ import { H as L, g as A, f as H, e as x, a as C, c as M, d as B } from "./header-DqmKROIY.js";
8
8
  import { L as N } from "./logo-_Z-jLq80.js";
9
9
  import { S as T, a as _, h as O, j as P, k as W, i as j } from "./sidebar-D8Lq065m.js";
10
10
  import { T as z } from "./theme-root-CSKD5ZRm.js";
@@ -185,4 +185,4 @@ V.displayName = "PatientShell";
185
185
  export {
186
186
  V as P
187
187
  };
188
- //# sourceMappingURL=patient-shell-CL20JnVJ.js.map
188
+ //# sourceMappingURL=patient-shell-BE0CdPOJ.js.map
@@ -0,0 +1,242 @@
1
+ import { jsxs as g, jsx as s } from "react/jsx-runtime";
2
+ import { forwardRef as P, useId as Y, useState as b, useCallback as N, useImperativeHandle as q, useEffect as j, useRef as L } from "react";
3
+ import { c as C } from "./index-D2ZczOXr.js";
4
+ import { useTranslation as S } from "react-i18next";
5
+ import { I as D } from "./icon-button-C4CGcYuz.js";
6
+ import { S as c } from "./sheet-BT0izeoI.js";
7
+ import { X as F } from "./x-CCcI3eJp.js";
8
+ import { M as W } from "./menu-XRhW3_99.js";
9
+ const X = C(
10
+ [
11
+ "ds:flex ds:items-center ds:gap-[var(--spacing-md)]",
12
+ "ds:w-full ds:z-[var(--z-sticky)]",
13
+ "ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:sm:ps-[var(--spacing-lg)] ds:sm:pe-[var(--spacing-lg)]",
14
+ "ds:h-14 ds:md:h-16",
15
+ "ds:transition-[background-color,box-shadow,transform] ds:duration-[var(--animation-duration)]",
16
+ "ds:motion-reduce:transition-none"
17
+ ].join(" "),
18
+ {
19
+ variants: {
20
+ variant: {
21
+ default: "ds:bg-[var(--card)] ds:text-[var(--foreground)] ds:border-b ds:border-[color:var(--border)]",
22
+ // Transparent fades to default once data-stuck="true" (set by the
23
+ // rAF scroll listener). The fade is handled via the same
24
+ // background utility so `data-stuck` swaps cleanly between states.
25
+ transparent: [
26
+ "ds:bg-transparent ds:text-[var(--foreground)]",
27
+ "ds:data-[stuck=true]:bg-[var(--card)]",
28
+ "ds:data-[stuck=true]:shadow-[var(--shadow-md)]",
29
+ "ds:forced-colors:border-b ds:forced-colors:border-[CanvasText]"
30
+ ].join(" "),
31
+ // `dark` flips its own scope into the dark token set so nav
32
+ // links + buttons inside read off-white text on the blue-800
33
+ // surface. Without the `theme-dark` scope the children inherit
34
+ // the light-theme `--foreground` (blue-500) and fail
35
+ // color-contrast at ~1.3:1.
36
+ dark: "theme-dark ds:bg-[var(--color-blue-800)] ds:text-[var(--foreground)]"
37
+ },
38
+ sticky: {
39
+ none: "",
40
+ top: "ds:sticky ds:top-0",
41
+ // `scroll-up` is sticky but translates off-screen when scrolling
42
+ // down past `stickyOffset` (handled by data-hidden="true") and
43
+ // slides back in when scrolling up.
44
+ "scroll-up": [
45
+ "ds:sticky ds:top-0",
46
+ "ds:data-[hidden=true]:-translate-y-full"
47
+ ].join(" ")
48
+ }
49
+ },
50
+ defaultVariants: { variant: "default", sticky: "none" }
51
+ }
52
+ ), $ = C(
53
+ [
54
+ "ds:inline-flex ds:items-center",
55
+ "ds:type-body-sm ds:font-medium",
56
+ "ds:text-[var(--foreground)]",
57
+ "ds:rounded-[var(--radius-sm)]",
58
+ "ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)]",
59
+ "ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid",
60
+ "ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]",
61
+ "ds:hover:text-[var(--primary)]",
62
+ "ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none",
63
+ "ds:data-[active=true]:text-[var(--primary)]",
64
+ "ds:data-[active=true]:[box-shadow:inset_0_-2px_0_var(--primary)]"
65
+ ].join(" ")
66
+ );
67
+ function G() {
68
+ const [e, d] = b(() => typeof window > "u" || !window.matchMedia ? !1 : window.matchMedia("(prefers-reduced-motion: reduce)").matches);
69
+ return j(() => {
70
+ if (typeof window > "u" || !window.matchMedia) return;
71
+ const r = window.matchMedia("(prefers-reduced-motion: reduce)"), n = () => d(r.matches);
72
+ return r.addEventListener("change", n), () => r.removeEventListener("change", n);
73
+ }, []), e;
74
+ }
75
+ function J(e, d, r) {
76
+ const [n, a] = b(!1), [p, o] = b(!1), l = L(0), u = L(!1);
77
+ return j(() => {
78
+ if (!e || typeof window > "u") return;
79
+ l.current = window.scrollY;
80
+ const f = () => {
81
+ const t = window.scrollY;
82
+ if (a(t > r), d === "scroll-up") {
83
+ const v = t - l.current;
84
+ v > 4 && t > r ? o(!0) : (v < -4 || t <= r) && o(!1);
85
+ }
86
+ l.current = t, u.current = !1;
87
+ }, m = () => {
88
+ u.current || (u.current = !0, window.requestAnimationFrame(f));
89
+ };
90
+ return window.addEventListener("scroll", m, { passive: !0 }), f(), () => {
91
+ window.removeEventListener("scroll", m);
92
+ };
93
+ }, [e, d, r]), { stuck: n, hidden: p };
94
+ }
95
+ const I = P(
96
+ ({
97
+ logo: e,
98
+ homeHref: d = "/",
99
+ homeLabel: r,
100
+ navSlot: n,
101
+ actionsSlot: a,
102
+ variant: p = "default",
103
+ sticky: o = "none",
104
+ stickyOffset: l = 80,
105
+ menuLabel: u,
106
+ navLabel: f,
107
+ id: m,
108
+ className: t,
109
+ ...v
110
+ }, E) => {
111
+ const { t: h } = S(), y = G(), O = Y(), H = `${m ?? O}-sheet`, [i, w] = b(!1), _ = p === "transparent" || o === "scroll-up", { stuck: z, hidden: T } = J(
112
+ _,
113
+ o,
114
+ l
115
+ ), A = y ? !1 : T, k = N(() => w(!0), []), M = N(() => w(!1), []);
116
+ q(
117
+ E,
118
+ () => ({
119
+ openMenu: k,
120
+ closeMenu: M,
121
+ getMenuOpen: () => i
122
+ }),
123
+ [k, M, i]
124
+ );
125
+ const B = r ?? h("publicHeader.homeLabel", "AlfaDocs — home"), x = f ?? h("publicHeader.primaryNavLabel", "Primary"), V = u ?? (i ? h("publicHeader.closeMenu", "Close menu") : h("publicHeader.openMenu", "Open menu"));
126
+ return /* @__PURE__ */ g(
127
+ "header",
128
+ {
129
+ ...v,
130
+ "data-component": "public-header",
131
+ "data-component-id": m,
132
+ "data-stuck": z ? "true" : void 0,
133
+ "data-hidden": A ? "true" : void 0,
134
+ "data-state": y ? "reduced-motion" : void 0,
135
+ className: X({ variant: p, sticky: o, className: t }),
136
+ children: [
137
+ /* @__PURE__ */ s(
138
+ "a",
139
+ {
140
+ href: d,
141
+ "aria-label": B,
142
+ className: "ds:inline-flex ds:items-center ds:rounded-[var(--radius-sm)] ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]",
143
+ children: e
144
+ }
145
+ ),
146
+ n ? /* @__PURE__ */ s(
147
+ "nav",
148
+ {
149
+ "aria-label": x,
150
+ className: "ds:hidden ds:md:flex ds:items-center ds:gap-[var(--spacing-md)] ds:ms-[var(--spacing-lg)]",
151
+ children: n
152
+ }
153
+ ) : null,
154
+ a ? /* @__PURE__ */ s("div", { className: "ds:hidden ds:md:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:ms-auto", children: a }) : null,
155
+ /* @__PURE__ */ g(c, { open: i, onOpenChange: w, children: [
156
+ /* @__PURE__ */ s(c.Trigger, { asChild: !0, children: /* @__PURE__ */ s(
157
+ D,
158
+ {
159
+ size: "md",
160
+ intent: "ghost",
161
+ className: "ds:ms-auto ds:md:hidden",
162
+ icon: i ? /* @__PURE__ */ s(F, { "aria-hidden": "true" }) : /* @__PURE__ */ s(W, { "aria-hidden": "true" }),
163
+ "aria-controls": H,
164
+ "aria-expanded": i,
165
+ "aria-label": V
166
+ }
167
+ ) }),
168
+ /* @__PURE__ */ g(c.Content, { side: "end", size: "md", id: H, children: [
169
+ /* @__PURE__ */ s(c.Header, { children: /* @__PURE__ */ s(c.Title, { children: x }) }),
170
+ /* @__PURE__ */ s(c.Body, { children: /* @__PURE__ */ g("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]", children: [
171
+ n ? /* @__PURE__ */ s(
172
+ "nav",
173
+ {
174
+ "aria-label": x,
175
+ className: "ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]",
176
+ children: n
177
+ }
178
+ ) : null,
179
+ a ? /* @__PURE__ */ s("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:mt-[var(--spacing-md)]", children: a }) : null
180
+ ] }) })
181
+ ] })
182
+ ] })
183
+ ]
184
+ }
185
+ );
186
+ }
187
+ );
188
+ I.displayName = "PublicHeader";
189
+ const R = P(({ active: e, className: d, children: r, ...n }, a) => /* @__PURE__ */ s(
190
+ "a",
191
+ {
192
+ ref: a,
193
+ ...n,
194
+ "data-active": e ? "true" : void 0,
195
+ "aria-current": e ? "page" : void 0,
196
+ className: [$(), d].filter(Boolean).join(" "),
197
+ children: r
198
+ }
199
+ ));
200
+ R.displayName = "PublicHeader.NavLink";
201
+ const de = Object.assign(I, {
202
+ NavLink: R
203
+ }), ae = {
204
+ id: "public-header",
205
+ capabilities: ["open", "close"],
206
+ state: {
207
+ menuOpen: {
208
+ type: "boolean",
209
+ description: "Whether the mobile drawer is currently open.",
210
+ read: (e) => e.getMenuOpen()
211
+ }
212
+ },
213
+ actions: {
214
+ open_menu: {
215
+ safety: "read",
216
+ description: "Open the mobile drawer.",
217
+ invoke: (e) => {
218
+ e.openMenu();
219
+ }
220
+ },
221
+ close_menu: {
222
+ safety: "read",
223
+ description: "Close the mobile drawer.",
224
+ invoke: (e) => {
225
+ e.closeMenu();
226
+ }
227
+ }
228
+ },
229
+ domHooks: {
230
+ root: { attr: "data-component", value: "public-header" },
231
+ instanceId: {
232
+ attr: "data-component-id",
233
+ sourceProp: "id",
234
+ description: "Sourced from the id prop on PublicHeader."
235
+ }
236
+ }
237
+ };
238
+ export {
239
+ de as P,
240
+ ae as p
241
+ };
242
+ //# sourceMappingURL=public-header.agent-ZLBAQ30j.js.map
@@ -0,0 +1,317 @@
1
+ import { jsxs as z, jsx as i } from "react/jsx-runtime";
2
+ import { forwardRef as Q, useId as X, useCallback as L, useRef as Z, useMemo as tt } from "react";
3
+ import { c as V } from "./index-D2ZczOXr.js";
4
+ import { useTranslation as U } from "react-i18next";
5
+ import { u as et } from "./use-count-up-BLLetaZ8.js";
6
+ const O = V("ds:flex ds:flex-col", {
7
+ variants: {
8
+ variant: {
9
+ default: "ds:gap-[var(--spacing-xs)]",
10
+ outlined: [
11
+ "ds:gap-[var(--spacing-xs)]",
12
+ "ds:border ds:border-[color:var(--border)]",
13
+ "ds:rounded-[var(--radius-md)]",
14
+ "ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]",
15
+ "ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]"
16
+ ].join(" "),
17
+ // White card surface with the shared card shadow — matches
18
+ // `Card variant="elevated"` tokens (`--card` + `--shadow-card`) so
19
+ // a grid of elevated Stats reads as a set of shaded panels without
20
+ // nesting a Card around each one.
21
+ elevated: [
22
+ "ds:gap-[var(--spacing-xs)]",
23
+ "ds:bg-[var(--card)]",
24
+ "ds:text-[var(--card-foreground)]",
25
+ "ds:shadow-[var(--shadow-card)]",
26
+ "ds:rounded-[var(--radius-lg)]",
27
+ "ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]",
28
+ "ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]",
29
+ // Forced-colors: UA strips shadow, so render a border as the
30
+ // separation cue — mirrors Card's forced-colors behaviour.
31
+ "ds:forced-colors:border ds:forced-colors:border-[CanvasText]"
32
+ ].join(" "),
33
+ compact: "ds:gap-[var(--spacing-none)]"
34
+ },
35
+ size: {
36
+ sm: "",
37
+ md: "",
38
+ lg: ""
39
+ },
40
+ align: {
41
+ start: "ds:items-start ds:text-start",
42
+ center: "ds:items-center ds:text-center",
43
+ end: "ds:items-end ds:text-end"
44
+ }
45
+ },
46
+ defaultVariants: {
47
+ variant: "default",
48
+ size: "md",
49
+ align: "start"
50
+ }
51
+ }), P = V("type-metric ds:text-[var(--foreground)]", {
52
+ variants: {
53
+ size: {
54
+ sm: "ds:[--type-metric-size:var(--font-size-xl)]",
55
+ md: "ds:[--type-metric-size:var(--font-size-3xl)]",
56
+ lg: "ds:[--type-metric-size:var(--font-size-5xl)]"
57
+ },
58
+ variant: {
59
+ default: "",
60
+ outlined: "",
61
+ elevated: "",
62
+ compact: ""
63
+ }
64
+ },
65
+ compoundVariants: [
66
+ {
67
+ variant: "compact",
68
+ size: "sm",
69
+ className: "ds:[--type-metric-size:var(--font-size-lg)]"
70
+ },
71
+ {
72
+ variant: "compact",
73
+ size: "md",
74
+ className: "ds:[--type-metric-size:var(--font-size-xl)]"
75
+ },
76
+ {
77
+ variant: "compact",
78
+ size: "lg",
79
+ className: "ds:[--type-metric-size:var(--font-size-2xl)]"
80
+ }
81
+ ],
82
+ defaultVariants: {
83
+ size: "md",
84
+ variant: "default"
85
+ }
86
+ }), st = V(
87
+ "ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-label",
88
+ {
89
+ variants: {
90
+ trend: {
91
+ up: "ds:text-[var(--success)]",
92
+ down: "ds:text-[var(--destructive)]",
93
+ flat: "ds:text-[var(--muted-foreground)]"
94
+ }
95
+ },
96
+ defaultVariants: {
97
+ trend: "flat"
98
+ }
99
+ }
100
+ ), rt = { up: "↑", down: "↓", flat: "→" }, at = {
101
+ up: "stat.trend.up",
102
+ down: "stat.trend.down",
103
+ flat: "stat.trend.flat"
104
+ };
105
+ function nt({
106
+ trend: d,
107
+ delta: t,
108
+ deltaFormat: c = "decimal",
109
+ locale: a
110
+ }) {
111
+ const { t: e, i18n: o } = U(), l = typeof t == "string" ? t : new Intl.NumberFormat(a ?? o.language, {
112
+ style: c === "percent" ? "percent" : "decimal"
113
+ }).format(c === "percent" ? t / 100 : t);
114
+ return /* @__PURE__ */ z("span", { className: st({ trend: d }), children: [
115
+ /* @__PURE__ */ i("span", { "aria-hidden": "true", children: rt[d] }),
116
+ /* @__PURE__ */ i("span", { className: "ds:sr-only", children: e(at[d]) }),
117
+ l
118
+ ] });
119
+ }
120
+ function it(d, t) {
121
+ const c = d.trim();
122
+ if (c === "") return null;
123
+ let a = "", e = c;
124
+ e.startsWith("+") ? (a = "+", e = e.slice(1).trimStart()) : (e.startsWith("-") || e.startsWith("−")) && (a = "-", e = e.slice(1).trimStart());
125
+ let o = "";
126
+ const l = e.match(/[KMB]$/i);
127
+ l && (o = l[0], e = e.slice(0, -1).trimEnd());
128
+ let m = "", u = ".";
129
+ try {
130
+ const b = new Intl.NumberFormat(t).formatToParts(12345.6);
131
+ for (const n of b)
132
+ n.type === "group" ? m = n.value : n.type === "decimal" && (u = n.value);
133
+ } catch {
134
+ }
135
+ const g = e.match(/^(\d+)\.(\d+)$/);
136
+ if (g && !(g[2].length === 3 && m === ".")) {
137
+ const n = Number.parseFloat(e);
138
+ if (Number.isFinite(n))
139
+ return { target: n, sign: a, suffix: o };
140
+ }
141
+ let s = e;
142
+ m !== "" && (s = s.split(m).join("")), u !== "." && (s = s.split(u).join(".")), s = s.replace(/[\s\u00A0\u202F]/g, "");
143
+ const v = Number.parseFloat(s);
144
+ return Number.isFinite(v) ? { target: v, sign: a, suffix: o } : null;
145
+ }
146
+ const dt = Q(
147
+ ({
148
+ label: d,
149
+ value: t,
150
+ format: c,
151
+ currency: a,
152
+ locale: e,
153
+ trend: o,
154
+ delta: l,
155
+ deltaFormat: m = "decimal",
156
+ icon: u,
157
+ loading: g = !1,
158
+ animate: s = !1,
159
+ animateOnEveryView: v = !1,
160
+ animateDurationMs: b = 1600,
161
+ animateLocale: n,
162
+ animateSeparators: h,
163
+ variant: x = "default",
164
+ size: y = "md",
165
+ align: I = "start",
166
+ className: M,
167
+ ...j
168
+ }, k) => {
169
+ const { i18n: B } = U(), R = X(), f = e ?? B.language, K = L(() => {
170
+ if (typeof t == "string") return t;
171
+ switch (c) {
172
+ case "currency":
173
+ return new Intl.NumberFormat(f, {
174
+ style: "currency",
175
+ currency: a ?? "USD"
176
+ }).format(t);
177
+ case "percent":
178
+ return new Intl.NumberFormat(f, { style: "percent" }).format(
179
+ t
180
+ );
181
+ case "decimal":
182
+ return new Intl.NumberFormat(f, { style: "decimal" }).format(
183
+ t
184
+ );
185
+ default:
186
+ return new Intl.NumberFormat(f).format(t);
187
+ }
188
+ }, [t, c, f, a])(), N = n ?? f;
189
+ Z(!1);
190
+ const r = tt(() => s ? typeof t == "number" ? Number.isFinite(t) ? { target: t, sign: "", suffix: "" } : null : it(t, N) : null, [s, t, N]), Y = s && r !== null, _ = (r == null ? void 0 : r.target) ?? 0, F = (r == null ? void 0 : r.sign) ?? "", T = (r == null ? void 0 : r.suffix) ?? "", q = L(
191
+ (w) => {
192
+ const C = (() => {
193
+ try {
194
+ return new Intl.NumberFormat(N, {
195
+ useGrouping: !0
196
+ });
197
+ } catch {
198
+ return null;
199
+ }
200
+ })();
201
+ let p;
202
+ if (C)
203
+ if (h) {
204
+ const W = Math.abs(w), A = Math.trunc(W), D = W - A, H = h.thousand ?? "", S = String(A).replace(
205
+ /\B(?=(\d{3})+(?!\d))/g,
206
+ H
207
+ );
208
+ if (D === 0)
209
+ p = S;
210
+ else {
211
+ const G = D.toFixed(6).replace(/0+$/, "").slice(2), J = h.decimal ?? ".";
212
+ p = G ? S + J + G : S;
213
+ }
214
+ } else
215
+ p = C.format(Math.abs(w));
216
+ else
217
+ p = String(Math.abs(w));
218
+ let E = F;
219
+ return F === "" && w < 0 && (E = "-"), `${E}${p}${T}`;
220
+ },
221
+ [N, h, F, T]
222
+ ), $ = et({
223
+ to: _,
224
+ from: 0,
225
+ durationMs: b,
226
+ startOnVisible: !0,
227
+ retriggerOnReEntry: v,
228
+ // `formatter` is the only path we use — it owns both the locale
229
+ // formatting and the sign/suffix re-application.
230
+ formatter: q
231
+ });
232
+ return g ? /* @__PURE__ */ z(
233
+ "div",
234
+ {
235
+ ref: k,
236
+ role: "group",
237
+ "aria-busy": "true",
238
+ "aria-label": d,
239
+ "data-component": "stat",
240
+ className: O({ variant: x, size: y, align: I, className: M }),
241
+ ...j,
242
+ children: [
243
+ /* @__PURE__ */ i("div", { className: "ds:h-[var(--skeleton-label-h)] ds:w-[var(--skeleton-label-w)] ds:animate-pulse ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]" }),
244
+ /* @__PURE__ */ i("div", { className: "ds:h-[var(--skeleton-value-h)] ds:w-[var(--skeleton-value-w)] ds:animate-pulse ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]" })
245
+ ]
246
+ }
247
+ ) : /* @__PURE__ */ z(
248
+ "div",
249
+ {
250
+ ref: k,
251
+ role: "group",
252
+ "aria-labelledby": R,
253
+ "data-component": "stat",
254
+ className: O({ variant: x, size: y, align: I, className: M }),
255
+ ...j,
256
+ children: [
257
+ /* @__PURE__ */ z("span", { className: "ds:inline-flex ds:items-center", children: [
258
+ u && /* @__PURE__ */ i(
259
+ "span",
260
+ {
261
+ "aria-hidden": "true",
262
+ className: [
263
+ "ds:me-[var(--spacing-xs)] ds:inline-flex ds:shrink-0",
264
+ // Accent tint on the leading icon. The icon is decorative
265
+ // (aria-hidden), so magenta-500's 3.2:1 contrast on white
266
+ // is acceptable here — the Stat label + value still
267
+ // carry the accessible name at `--foreground`.
268
+ "ds:text-[color:var(--accent)]",
269
+ "ds:forced-colors:text-[CanvasText]"
270
+ ].join(" "),
271
+ children: u
272
+ }
273
+ ),
274
+ /* @__PURE__ */ i(
275
+ "span",
276
+ {
277
+ id: R,
278
+ className: "type-label ds:text-[var(--muted-foreground)]",
279
+ children: d
280
+ }
281
+ )
282
+ ] }),
283
+ Y ? (
284
+ // The animated number is wrapped in an `aria-live="off"` span
285
+ // so screen readers don't announce every interpolated frame.
286
+ // The `role="group"` ancestor (with `aria-labelledby` pointing
287
+ // at the label) carries the final accessible reading — the
288
+ // animated frames are decorative only.
289
+ /* @__PURE__ */ i(
290
+ "span",
291
+ {
292
+ ref: $.ref,
293
+ "aria-live": "off",
294
+ className: P({ size: y, variant: x }),
295
+ children: $.value
296
+ }
297
+ )
298
+ ) : /* @__PURE__ */ i("span", { className: P({ size: y, variant: x }), children: K }),
299
+ o != null && l != null && /* @__PURE__ */ i(
300
+ nt,
301
+ {
302
+ trend: o,
303
+ delta: l,
304
+ deltaFormat: m,
305
+ locale: e
306
+ }
307
+ )
308
+ ]
309
+ }
310
+ );
311
+ }
312
+ );
313
+ dt.displayName = "Stat";
314
+ export {
315
+ dt as S
316
+ };
317
+ //# sourceMappingURL=stat-CYEx8sIR.js.map
@@ -0,0 +1,109 @@
1
+ import { useMemo as D, useState as T, useRef as e, useCallback as v, useEffect as U } from "react";
2
+ const H = (l) => 1 - Math.pow(1 - l, 3);
3
+ function J(l, u, d) {
4
+ if (d) return d;
5
+ let m;
6
+ try {
7
+ m = new Intl.NumberFormat(l);
8
+ } catch {
9
+ return (r) => String(r);
10
+ }
11
+ return u ? (r) => {
12
+ if (!Number.isFinite(r)) return String(r);
13
+ const o = r < 0 ? "-" : "", w = Math.abs(r), p = Math.trunc(w), g = w - p, R = String(p), P = u.thousand ?? "", i = R.replace(/\B(?=(\d{3})+(?!\d))/g, P);
14
+ if (g === 0) return o + i;
15
+ const F = g.toFixed(6).replace(/0+$/, "").slice(2), t = u.decimal ?? ".";
16
+ return F ? o + i + t + F : o + i;
17
+ } : (r) => m.format(r);
18
+ }
19
+ function K() {
20
+ return typeof window > "u" || typeof window.matchMedia != "function" ? !1 : window.matchMedia("(prefers-reduced-motion: reduce)").matches;
21
+ }
22
+ function W(l) {
23
+ const {
24
+ to: u,
25
+ from: d = 0,
26
+ durationMs: m = 1600,
27
+ startOnVisible: r = !0,
28
+ retriggerOnReEntry: o = !1,
29
+ locale: w,
30
+ separators: p,
31
+ formatter: g,
32
+ reduceMotion: R
33
+ } = l, P = D(
34
+ () => J(
35
+ w ?? (typeof navigator < "u" ? navigator.language : void 0),
36
+ p,
37
+ g
38
+ ),
39
+ [w, p, g]
40
+ ), i = D(() => typeof R == "boolean" ? R : K(), [R]), [F, t] = T(u), [$, b] = T(!0), E = e(null), n = e(null), s = e(null), f = e(null), h = e(!1), O = e(d), S = e(u), G = e(m), x = e(i), V = e(o), A = e(r);
41
+ O.current = d, S.current = u, G.current = m, x.current = i, V.current = o, A.current = r;
42
+ const c = v(() => {
43
+ s.current != null && (typeof window < "u" && window.cancelAnimationFrame(s.current), s.current = null), f.current = null;
44
+ }, []), k = v((a) => {
45
+ f.current == null && (f.current = a);
46
+ const C = a - f.current, I = Math.max(G.current, 0), M = I === 0 ? 1 : Math.min(C / I, 1), j = H(M), N = O.current, B = S.current, z = N + (B - N) * j;
47
+ if (M >= 1) {
48
+ t(B), b(!0), s.current = null, f.current = null;
49
+ return;
50
+ }
51
+ t(z), s.current = window.requestAnimationFrame(k);
52
+ }, []), y = v(() => {
53
+ if (!(typeof window > "u")) {
54
+ if (x.current) {
55
+ c(), t(S.current), b(!0), h.current = !0;
56
+ return;
57
+ }
58
+ c(), t(O.current), b(!1), f.current = null, s.current = window.requestAnimationFrame(k), h.current = !0;
59
+ }
60
+ }, [c, k]), q = v(() => {
61
+ c(), t(O.current), b(!1), h.current = !1;
62
+ }, [c]);
63
+ return U(() => {
64
+ if (!(typeof window > "u")) {
65
+ if (x.current) {
66
+ t(S.current), b(!0);
67
+ return;
68
+ }
69
+ A.current || y();
70
+ }
71
+ }, []), U(() => () => {
72
+ c(), n.current && (n.current.disconnect(), n.current = null);
73
+ }, [c]), {
74
+ ref: v(
75
+ (a) => {
76
+ if (a === null) {
77
+ E.current = null, n.current && (n.current.disconnect(), n.current = null);
78
+ return;
79
+ }
80
+ if (E.current = a, typeof window > "u" || x.current || !A.current || n.current) return;
81
+ if (typeof IntersectionObserver > "u") {
82
+ y();
83
+ return;
84
+ }
85
+ const C = new IntersectionObserver(
86
+ (I) => {
87
+ const M = I[0];
88
+ if (M)
89
+ if (M.isIntersecting) {
90
+ if (h.current && !V.current) return;
91
+ y();
92
+ } else V.current && h.current && q();
93
+ },
94
+ { threshold: 0.4 }
95
+ );
96
+ C.observe(a), n.current = C;
97
+ },
98
+ [y, q]
99
+ ),
100
+ value: P(F),
101
+ done: $,
102
+ start: y,
103
+ reset: q
104
+ };
105
+ }
106
+ export {
107
+ W as u
108
+ };
109
+ //# sourceMappingURL=use-count-up-BLLetaZ8.js.map