@danieljoffe/shared-ui 0.0.1 → 0.1.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.
Files changed (54) hide show
  1. package/dist/index.js +110 -5358
  2. package/dist/lib/Alert.js +72 -0
  3. package/dist/lib/AspectRatio.js +31 -0
  4. package/dist/lib/Avatar.js +47 -0
  5. package/dist/lib/Badge.js +43 -0
  6. package/dist/lib/Breadcrumb.js +28 -0
  7. package/dist/lib/Button.js +82 -0
  8. package/dist/lib/CTACard.js +31 -0
  9. package/dist/lib/Card.js +91 -0
  10. package/dist/lib/Checkbox.js +75 -0
  11. package/dist/lib/Container.js +35 -0
  12. package/dist/lib/Divider.js +48 -0
  13. package/dist/lib/Dropdown.js +158 -0
  14. package/dist/lib/FormFieldError.js +8 -0
  15. package/dist/lib/Grid.js +67 -0
  16. package/dist/lib/GridBg.js +31 -0
  17. package/dist/lib/Heading.js +40 -0
  18. package/dist/lib/Input.js +55 -0
  19. package/dist/lib/Kbd.js +19 -0
  20. package/dist/lib/Loading.js +44 -0
  21. package/dist/lib/Modal.js +119 -0
  22. package/dist/lib/PageContainer.js +35 -0
  23. package/dist/lib/PageLayout.js +25 -0
  24. package/dist/lib/Pagination.js +111 -0
  25. package/dist/lib/ProgressBar.js +68 -0
  26. package/dist/lib/Section.js +58 -0
  27. package/dist/lib/SectionLabel.js +19 -0
  28. package/dist/lib/Select.js +67 -0
  29. package/dist/lib/Sidebar.js +97 -0
  30. package/dist/lib/Skeleton.js +63 -0
  31. package/dist/lib/Spacer.js +17 -0
  32. package/dist/lib/Spinner.js +39 -0
  33. package/dist/lib/Stack.js +59 -0
  34. package/dist/lib/StatsCard.js +79 -0
  35. package/dist/lib/StructuredData.js +15 -0
  36. package/dist/lib/Switch.js +69 -0
  37. package/dist/lib/Table.js +91 -0
  38. package/dist/lib/Tabs.js +101 -0
  39. package/dist/lib/Text.js +48 -0
  40. package/dist/lib/Textarea.js +50 -0
  41. package/dist/lib/ThemeProvider.js +54 -0
  42. package/dist/lib/ThemeToggle.js +29 -0
  43. package/dist/lib/Toast.js +95 -0
  44. package/dist/lib/Tooltip.js +70 -0
  45. package/dist/lib/index.js +112 -0
  46. package/dist/lib/styles/formStyles.js +24 -0
  47. package/dist/lib/styles/semanticVariants.js +27 -0
  48. package/dist/lib/types.js +1 -0
  49. package/dist/lib/utils/ErrorBoundary.js +17 -0
  50. package/dist/lib/utils/ModalErrorBoundary.js +17 -0
  51. package/dist/lib/utils/cn.js +8 -0
  52. package/dist/lib/utils/index.js +10 -0
  53. package/dist/lib/utils/validateProps.js +7 -0
  54. package/package.json +7 -4
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ import { jsxs as y, jsx as e } from "react/jsx-runtime";
3
+ import { ChevronLeft as N, ChevronRight as S } from "lucide-react";
4
+ import { FOCUS_RING_OFFSET as l, FOCUS_RING as m, DISABLED as x } from "./styles/formStyles.js";
5
+ import { cn as n } from "./utils/cn.js";
6
+ const h = {
7
+ sm: "p-1",
8
+ md: "p-1.5",
9
+ lg: "p-2"
10
+ }, w = {
11
+ sm: "h-6 min-w-6 px-1.5 text-xs",
12
+ md: "h-8 min-w-8 px-2 text-sm",
13
+ lg: "h-10 min-w-10 px-3 text-base"
14
+ }, b = {
15
+ sm: "h-3.5 w-3.5",
16
+ md: "h-4 w-4",
17
+ lg: "h-5 w-5"
18
+ };
19
+ function k({
20
+ currentPage: i,
21
+ totalPages: o,
22
+ onPageChange: a,
23
+ className: p,
24
+ ariaLabel: u = "Pagination",
25
+ size: s = "md"
26
+ }) {
27
+ const f = () => {
28
+ if (o <= 7)
29
+ return Array.from({ length: o }, (r, v) => v + 1);
30
+ const t = [1];
31
+ i > 3 && t.push("...");
32
+ for (let r = Math.max(2, i - 1); r <= Math.min(o - 1, i + 1); r++)
33
+ t.push(r);
34
+ return i < o - 2 && t.push("..."), t.push(o), t;
35
+ }, d = i <= 1, c = i >= o;
36
+ return /* @__PURE__ */ y(
37
+ "nav",
38
+ {
39
+ "aria-label": u,
40
+ className: n("flex items-center gap-1", p),
41
+ children: [
42
+ /* @__PURE__ */ e(
43
+ "button",
44
+ {
45
+ onClick: () => a(i - 1),
46
+ disabled: d,
47
+ "aria-label": "Previous page",
48
+ "aria-disabled": d ? "true" : void 0,
49
+ className: n(
50
+ "rounded-md text-text-secondary hover:bg-surface-tertiary transition-colors cursor-pointer",
51
+ x,
52
+ m,
53
+ l,
54
+ h[s]
55
+ ),
56
+ children: /* @__PURE__ */ e(N, { className: b[s] })
57
+ }
58
+ ),
59
+ f().map(
60
+ (t, r) => t === "..." ? /* @__PURE__ */ e(
61
+ "span",
62
+ {
63
+ className: n(
64
+ "px-1 text-text-tertiary",
65
+ s === "sm" ? "text-xs" : s === "lg" ? "text-base" : "text-sm"
66
+ ),
67
+ children: "..."
68
+ },
69
+ `dots-${r}`
70
+ ) : /* @__PURE__ */ e(
71
+ "button",
72
+ {
73
+ onClick: () => a(t),
74
+ "aria-label": t === i ? `Page ${t}` : `Go to page ${t}`,
75
+ "aria-current": t === i ? "page" : void 0,
76
+ className: n(
77
+ "rounded-md transition-colors cursor-pointer",
78
+ m,
79
+ l,
80
+ w[s],
81
+ t === i ? "bg-brand-600 text-white font-medium" : "text-text-secondary hover:bg-surface-tertiary"
82
+ ),
83
+ children: t
84
+ },
85
+ t
86
+ )
87
+ ),
88
+ /* @__PURE__ */ e(
89
+ "button",
90
+ {
91
+ onClick: () => a(i + 1),
92
+ disabled: c,
93
+ "aria-label": "Next page",
94
+ "aria-disabled": c ? "true" : void 0,
95
+ className: n(
96
+ "rounded-md text-text-secondary hover:bg-surface-tertiary transition-colors cursor-pointer",
97
+ x,
98
+ m,
99
+ l,
100
+ h[s]
101
+ ),
102
+ children: /* @__PURE__ */ e(S, { className: b[s] })
103
+ }
104
+ )
105
+ ]
106
+ }
107
+ );
108
+ }
109
+ export {
110
+ k as Pagination
111
+ };
@@ -0,0 +1,68 @@
1
+ import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
+ import { Text as h } from "./Text.js";
3
+ import { cn as t } from "./utils/cn.js";
4
+ import "react";
5
+ const f = {
6
+ accent: "bg-brand-500",
7
+ success: "bg-success",
8
+ error: "bg-error"
9
+ }, g = {
10
+ sm: "h-1",
11
+ md: "h-2",
12
+ lg: "h-3"
13
+ };
14
+ function w({
15
+ value: s,
16
+ max: i = 100,
17
+ variant: n = "accent",
18
+ size: l = "md",
19
+ showLabel: o = !1,
20
+ className: c,
21
+ "aria-label": d = "Progress",
22
+ ref: m,
23
+ ...u
24
+ }) {
25
+ const a = Math.min(Math.max(s / i * 100, 0), 100);
26
+ return /* @__PURE__ */ r("div", { ref: m, className: "w-full", ...u, children: [
27
+ /* @__PURE__ */ e(
28
+ "div",
29
+ {
30
+ role: "progressbar",
31
+ "aria-valuenow": Math.round(a),
32
+ "aria-valuemin": 0,
33
+ "aria-valuemax": 100,
34
+ "aria-label": d,
35
+ className: t(
36
+ "w-full bg-surface-elevated rounded-full overflow-hidden",
37
+ g[l],
38
+ c
39
+ ),
40
+ children: /* @__PURE__ */ e(
41
+ "div",
42
+ {
43
+ className: t(
44
+ "h-full transition-all duration-300 ease-out motion-reduce:transition-none",
45
+ f[n]
46
+ ),
47
+ style: { width: `${a}%` }
48
+ }
49
+ )
50
+ }
51
+ ),
52
+ o && /* @__PURE__ */ r(
53
+ h,
54
+ {
55
+ variant: "caption",
56
+ className: "mt-1.5 text-right",
57
+ "aria-hidden": "true",
58
+ children: [
59
+ Math.round(a),
60
+ "%"
61
+ ]
62
+ }
63
+ )
64
+ ] });
65
+ }
66
+ export {
67
+ w as ProgressBar
68
+ };
@@ -0,0 +1,58 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import { Container as f } from "./Container.js";
3
+ import { cn as y } from "./utils/cn.js";
4
+ import "react";
5
+ const u = {
6
+ none: "py-0",
7
+ sm: "py-4 sm:py-6",
8
+ md: "py-6 sm:py-8 md:py-12",
9
+ lg: "py-8 sm:py-12 md:py-16",
10
+ xl: "py-12 sm:py-16 md:py-24"
11
+ }, v = {
12
+ default: "bg-surface",
13
+ alt: "bg-surface-secondary",
14
+ elevated: "bg-surface-elevated",
15
+ none: ""
16
+ }, x = {
17
+ visible: "overflow-visible",
18
+ hidden: "overflow-hidden",
19
+ auto: "overflow-auto"
20
+ };
21
+ function h({
22
+ children: e,
23
+ ref: l,
24
+ padding: n = "md",
25
+ background: s = "none",
26
+ center: a = !1,
27
+ overflow: m = "visible",
28
+ fullWidth: r = !0,
29
+ contain: o,
30
+ className: p,
31
+ ...i
32
+ }) {
33
+ const c = o ? /* @__PURE__ */ t(f, { size: o, children: e }) : e, d = s === "elevated";
34
+ return /* @__PURE__ */ t(
35
+ "section",
36
+ {
37
+ ref: l,
38
+ className: y(
39
+ "relative",
40
+ u[n],
41
+ v[s],
42
+ x[m],
43
+ a && "flex flex-col justify-center",
44
+ r && "w-full",
45
+ // Elevated sections float inside their parent — pull off the edges
46
+ // and add internal horizontal padding so content isn't flush to the
47
+ // card surface.
48
+ d && "max-w-[calc(100%-2rem)] mx-auto px-4 sm:px-6 md:px-8",
49
+ p
50
+ ),
51
+ ...i,
52
+ children: c
53
+ }
54
+ );
55
+ }
56
+ export {
57
+ h as Section
58
+ };
@@ -0,0 +1,19 @@
1
+ import { jsxs as m, jsx as e } from "react/jsx-runtime";
2
+ import { Text as o } from "./Text.js";
3
+ import { cn as c } from "./utils/cn.js";
4
+ import "react";
5
+ function x({
6
+ icon: r,
7
+ label: t,
8
+ ref: i,
9
+ className: a
10
+ }) {
11
+ return /* @__PURE__ */ m("div", { ref: i, className: c("flex items-center gap-2 mb-8", a), children: [
12
+ /* @__PURE__ */ e("div", { className: "p-1.5 rounded-md bg-surface-tertiary text-text-secondary", children: r }),
13
+ /* @__PURE__ */ e(o, { variant: "label", children: t }),
14
+ /* @__PURE__ */ e("div", { className: "flex-1 h-px bg-border ml-2" })
15
+ ] });
16
+ }
17
+ export {
18
+ x as SectionLabel
19
+ };
@@ -0,0 +1,67 @@
1
+ import { jsxs as l, jsx as t } from "react/jsx-runtime";
2
+ import { ChevronDown as N } from "lucide-react";
3
+ import { useId as S } from "react";
4
+ import { FORM_LABEL as D, REQUIRED_MARK as R, DISABLED as L, BASE_FIELD as b, FIELD_ERROR as g, FIELD_SUCCESS as F } from "./styles/formStyles.js";
5
+ import { Text as o } from "./Text.js";
6
+ import { cn as _ } from "./utils/cn.js";
7
+ const A = {
8
+ sm: "px-3 py-1.5 pr-8 text-sm",
9
+ md: "px-4 py-2.5 pr-10",
10
+ lg: "px-5 py-3 pr-12 text-lg"
11
+ };
12
+ function O({
13
+ label: n,
14
+ error: e,
15
+ helperText: r,
16
+ success: m,
17
+ size: p = "md",
18
+ options: v,
19
+ className: h,
20
+ id: u,
21
+ required: s,
22
+ ref: f,
23
+ ...E
24
+ }) {
25
+ const I = S(), a = u ?? I, c = e ? `${a}-error` : void 0, d = r && !e ? `${a}-helper` : void 0, x = c || d, y = () => e ? g : m ? F : "";
26
+ return /* @__PURE__ */ l("div", { className: "w-full", children: [
27
+ n && /* @__PURE__ */ l("label", { htmlFor: a, className: D, children: [
28
+ n,
29
+ s && /* @__PURE__ */ t("span", { className: R, children: "*" })
30
+ ] }),
31
+ /* @__PURE__ */ l("div", { className: "relative", children: [
32
+ /* @__PURE__ */ t(
33
+ "select",
34
+ {
35
+ ref: f,
36
+ id: a,
37
+ "aria-invalid": e ? "true" : void 0,
38
+ "aria-required": s || void 0,
39
+ "aria-describedby": x,
40
+ required: s,
41
+ className: _(
42
+ b,
43
+ A[p],
44
+ "appearance-none",
45
+ L,
46
+ y(),
47
+ h
48
+ ),
49
+ ...E,
50
+ children: v.map((i) => /* @__PURE__ */ t("option", { value: i.value, children: i.label }, i.value))
51
+ }
52
+ ),
53
+ /* @__PURE__ */ t(
54
+ N,
55
+ {
56
+ className: "absolute right-3 top-1/2 -translate-y-1/2 size-5 text-text-tertiary pointer-events-none",
57
+ "aria-hidden": "true"
58
+ }
59
+ )
60
+ ] }),
61
+ e && /* @__PURE__ */ t(o, { variant: "error", id: c, className: "mt-1.5", role: "alert", children: e }),
62
+ r && !e && /* @__PURE__ */ t(o, { variant: "helper", id: d, className: "mt-1.5", children: r })
63
+ ] });
64
+ }
65
+ export {
66
+ O as Select
67
+ };
@@ -0,0 +1,97 @@
1
+ "use client";
2
+ import { jsxs as d, jsx as e, Fragment as u } from "react/jsx-runtime";
3
+ import { ChevronDown as x } from "lucide-react";
4
+ import { useState as h } from "react";
5
+ import { Button as p } from "./Button.js";
6
+ import { cn as m } from "./utils/cn.js";
7
+ function b({
8
+ item: r,
9
+ activeId: i,
10
+ onSelect: o,
11
+ collapsed: t,
12
+ depth: a = 0
13
+ }) {
14
+ const [n, l] = h(!1), s = i === r.id, c = r.children && r.children.length > 0;
15
+ return /* @__PURE__ */ d("div", { children: [
16
+ /* @__PURE__ */ d(
17
+ p,
18
+ {
19
+ variant: "bare",
20
+ size: "sm",
21
+ onClick: () => {
22
+ c && l(!n), o?.(r.id);
23
+ },
24
+ className: m(
25
+ "w-full justify-start",
26
+ a > 0 && "ml-6 w-[calc(100%-1.5rem)]",
27
+ s ? "bg-brand-50 text-brand-700 font-medium" : "text-text-secondary hover:bg-surface-tertiary hover:text-text-primary"
28
+ ),
29
+ children: [
30
+ r.icon,
31
+ !t && /* @__PURE__ */ d(u, { children: [
32
+ /* @__PURE__ */ e("span", { className: "flex-1 text-left truncate", children: r.label }),
33
+ r.badge !== void 0 && /* @__PURE__ */ e("span", { className: "text-xs px-1.5 py-0.5 rounded-full bg-surface-tertiary text-text-tertiary", children: r.badge }),
34
+ c && /* @__PURE__ */ e(
35
+ x,
36
+ {
37
+ className: m(
38
+ "h-4 w-4 text-text-tertiary transition-transform duration-200 motion-reduce:transition-none",
39
+ n && "rotate-180"
40
+ )
41
+ }
42
+ )
43
+ ] })
44
+ ]
45
+ }
46
+ ),
47
+ c && n && !t && /* @__PURE__ */ e("div", { className: "mt-0.5", children: r.children?.map((f) => /* @__PURE__ */ e(
48
+ b,
49
+ {
50
+ item: f,
51
+ activeId: i,
52
+ onSelect: o,
53
+ collapsed: t,
54
+ depth: a + 1
55
+ },
56
+ f.id
57
+ )) })
58
+ ] });
59
+ }
60
+ function C({
61
+ items: r,
62
+ activeId: i,
63
+ onSelect: o,
64
+ header: t,
65
+ footer: a,
66
+ collapsed: n = !1,
67
+ className: l
68
+ }) {
69
+ return /* @__PURE__ */ d(
70
+ "aside",
71
+ {
72
+ className: m(
73
+ "flex flex-col h-full bg-surface border-r border-border",
74
+ "transition-all duration-200 motion-reduce:transition-none",
75
+ n ? "w-16" : "w-48 md:w-60",
76
+ l
77
+ ),
78
+ children: [
79
+ t && /* @__PURE__ */ e("div", { className: "p-4 border-b border-border shrink-0", children: t }),
80
+ /* @__PURE__ */ e("nav", { className: "flex-1 overflow-y-auto p-2 space-y-0.5", children: r.map((s) => /* @__PURE__ */ e(
81
+ b,
82
+ {
83
+ item: s,
84
+ activeId: i,
85
+ onSelect: o,
86
+ collapsed: n
87
+ },
88
+ s.id
89
+ )) }),
90
+ a && /* @__PURE__ */ e("div", { className: "p-4 border-t border-border shrink-0", children: a })
91
+ ]
92
+ }
93
+ );
94
+ }
95
+ export {
96
+ C as Sidebar
97
+ };
@@ -0,0 +1,63 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import { cn as r } from "./utils/cn.js";
3
+ const d = {
4
+ sm: "h-3",
5
+ md: "h-4",
6
+ lg: "h-5"
7
+ }, i = {
8
+ sm: 32,
9
+ md: 40,
10
+ lg: 56
11
+ }, f = {
12
+ sm: 80,
13
+ md: 120,
14
+ lg: 180
15
+ };
16
+ function p({
17
+ className: l,
18
+ variant: m = "text",
19
+ width: e,
20
+ height: n,
21
+ lines: a = 1,
22
+ size: s = "md"
23
+ }) {
24
+ const c = "animate-pulse motion-reduce:animate-none bg-surface-tertiary";
25
+ if (m === "circular") {
26
+ const o = i[s];
27
+ return /* @__PURE__ */ t(
28
+ "div",
29
+ {
30
+ className: r(c, "rounded-full", l),
31
+ style: {
32
+ width: e || o,
33
+ height: n || e || o
34
+ }
35
+ }
36
+ );
37
+ }
38
+ return m === "rectangular" ? /* @__PURE__ */ t(
39
+ "div",
40
+ {
41
+ className: r(c, "rounded-lg", l),
42
+ style: {
43
+ width: e || "100%",
44
+ height: n || f[s]
45
+ }
46
+ }
47
+ ) : /* @__PURE__ */ t("div", { className: r("space-y-2", l), style: { width: e }, children: Array.from({ length: a }).map((o, u) => /* @__PURE__ */ t(
48
+ "div",
49
+ {
50
+ className: r(
51
+ c,
52
+ d[s],
53
+ "rounded-xs",
54
+ u === a - 1 && a > 1 && "w-3/4"
55
+ ),
56
+ style: { height: n }
57
+ },
58
+ u
59
+ )) });
60
+ }
61
+ export {
62
+ p as Skeleton
63
+ };
@@ -0,0 +1,17 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import { cn as e } from "./utils/cn.js";
3
+ import "react";
4
+ const h = {
5
+ xs: "h-2",
6
+ sm: "h-4",
7
+ md: "h-8",
8
+ lg: "h-12",
9
+ xl: "h-16",
10
+ "2xl": "h-24"
11
+ };
12
+ function n({ size: s = "md", className: m, ref: r, ...o }) {
13
+ return /* @__PURE__ */ t("div", { ref: r, className: e(h[s], m), ...o });
14
+ }
15
+ export {
16
+ n as Spacer
17
+ };
@@ -0,0 +1,39 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import { SEMANTIC_SPINNER as s } from "./styles/semanticVariants.js";
3
+ import { cn as d } from "./utils/cn.js";
4
+ import "react";
5
+ const m = {
6
+ sm: "size-4 border-2",
7
+ md: "size-8 border-2",
8
+ lg: "size-12 border-3"
9
+ }, l = {
10
+ accent: "border-brand-500/30 border-t-brand-500",
11
+ ...s
12
+ };
13
+ function f({
14
+ size: r = "md",
15
+ variant: e = "accent",
16
+ "aria-label": n = "Loading",
17
+ className: o,
18
+ ref: i,
19
+ ...a
20
+ }) {
21
+ return /* @__PURE__ */ t(
22
+ "div",
23
+ {
24
+ ref: i,
25
+ role: "status",
26
+ "aria-label": n,
27
+ className: d(
28
+ "inline-block rounded-full animate-spin motion-reduce:animate-none",
29
+ m[r],
30
+ l[e],
31
+ o
32
+ ),
33
+ ...a
34
+ }
35
+ );
36
+ }
37
+ export {
38
+ f as Spinner
39
+ };
@@ -0,0 +1,59 @@
1
+ import { jsx as f } from "react/jsx-runtime";
2
+ import { cn as m } from "./utils/cn.js";
3
+ import "react";
4
+ const p = {
5
+ vertical: "flex-col",
6
+ horizontal: "flex-row"
7
+ }, u = {
8
+ none: "gap-0",
9
+ xs: "gap-1",
10
+ sm: "gap-2",
11
+ md: "gap-4",
12
+ lg: "gap-6",
13
+ xl: "gap-8"
14
+ }, d = {
15
+ start: "items-start",
16
+ center: "items-center",
17
+ end: "items-end",
18
+ stretch: "items-stretch"
19
+ }, g = {
20
+ start: "justify-start",
21
+ center: "justify-center",
22
+ end: "justify-end",
23
+ between: "justify-between",
24
+ around: "justify-around",
25
+ evenly: "justify-evenly"
26
+ };
27
+ function v({
28
+ as: t,
29
+ children: e,
30
+ direction: s = "vertical",
31
+ gap: n = "md",
32
+ align: r = "stretch",
33
+ justify: a = "start",
34
+ wrap: o = !1,
35
+ className: i,
36
+ ref: c,
37
+ ...l
38
+ }) {
39
+ return /* @__PURE__ */ f(
40
+ t || "div",
41
+ {
42
+ ref: c,
43
+ className: m(
44
+ "flex",
45
+ p[s],
46
+ u[n],
47
+ d[r],
48
+ g[a],
49
+ o && "flex-wrap",
50
+ i
51
+ ),
52
+ ...l,
53
+ children: e
54
+ }
55
+ );
56
+ }
57
+ export {
58
+ v as Stack
59
+ };
@@ -0,0 +1,79 @@
1
+ import { jsxs as t, jsx as e } from "react/jsx-runtime";
2
+ import { TrendingUp as f, TrendingDown as u } from "lucide-react";
3
+ import { Text as c } from "./Text.js";
4
+ import { cn as i } from "./utils/cn.js";
5
+ function g({
6
+ title: n,
7
+ value: m,
8
+ change: s,
9
+ changeLabel: d,
10
+ changeUnit: l = "%",
11
+ invertChange: x = !1,
12
+ icon: o,
13
+ className: p
14
+ }) {
15
+ const r = s !== void 0 && s >= 0, a = x ? !r : r;
16
+ return /* @__PURE__ */ t(
17
+ "div",
18
+ {
19
+ className: i(
20
+ "p-3 sm:p-6 bg-surface-elevated border border-border rounded-xl shadow-xs",
21
+ p
22
+ ),
23
+ children: [
24
+ /* @__PURE__ */ t("div", { className: "flex items-start justify-between", children: [
25
+ /* @__PURE__ */ t("div", { children: [
26
+ /* @__PURE__ */ e(c, { variant: "caption", children: n }),
27
+ /* @__PURE__ */ e(
28
+ c,
29
+ {
30
+ variant: "bodyLg",
31
+ as: "p",
32
+ className: "mt-1 sm:mt-1.5 text-lg sm:text-2xl font-semibold tracking-tight",
33
+ children: m
34
+ }
35
+ )
36
+ ] }),
37
+ o && /* @__PURE__ */ e("div", { className: "p-2.5 bg-surface-tertiary rounded-lg text-text-secondary", children: o })
38
+ ] }),
39
+ s !== void 0 && /* @__PURE__ */ t("div", { className: "mt-3 flex items-center gap-1.5 text-xs", children: [
40
+ r ? /* @__PURE__ */ e(
41
+ f,
42
+ {
43
+ className: i(
44
+ "h-3.5 w-3.5",
45
+ a ? "text-success" : "text-error"
46
+ )
47
+ }
48
+ ) : /* @__PURE__ */ e(
49
+ u,
50
+ {
51
+ className: i(
52
+ "h-3.5 w-3.5",
53
+ a ? "text-success" : "text-error"
54
+ )
55
+ }
56
+ ),
57
+ /* @__PURE__ */ t(
58
+ "span",
59
+ {
60
+ className: i(
61
+ "font-medium",
62
+ a ? "text-success" : "text-error"
63
+ ),
64
+ children: [
65
+ r ? "+" : "",
66
+ s,
67
+ l
68
+ ]
69
+ }
70
+ ),
71
+ d && /* @__PURE__ */ e("span", { className: "text-text-tertiary", children: d })
72
+ ] })
73
+ ]
74
+ }
75
+ );
76
+ }
77
+ export {
78
+ g as StatsCard
79
+ };
@@ -0,0 +1,15 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ function n({ data: t }) {
3
+ return /* @__PURE__ */ r(
4
+ "script",
5
+ {
6
+ type: "application/ld+json",
7
+ dangerouslySetInnerHTML: {
8
+ __html: JSON.stringify(t).replace(/</g, "\\u003c")
9
+ }
10
+ }
11
+ );
12
+ }
13
+ export {
14
+ n as StructuredData
15
+ };