@ramme-io/ui 4.0.1 → 4.1.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 (83) hide show
  1. package/README.md +159 -7
  2. package/dist/blocks/ai/Actions.js +2 -2
  3. package/dist/blocks/ai/PromptInput.js +6 -6
  4. package/dist/component-registry.js +389 -359
  5. package/dist/components/ai/AIChatThread/AIChatThread.js +81 -73
  6. package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.d.ts +28 -0
  7. package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.js +70 -0
  8. package/dist/components/ai/ArchitectureReferenceCard/index.d.ts +2 -0
  9. package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.d.ts +30 -0
  10. package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.js +82 -0
  11. package/dist/components/ai/CounterpartyGraphCard/index.d.ts +2 -0
  12. package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.d.ts +29 -0
  13. package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.js +69 -0
  14. package/dist/components/ai/DivergenceMetricsCard/index.d.ts +2 -0
  15. package/dist/components/ai/KeyInjectionOverlay.d.ts +10 -0
  16. package/dist/components/ai/KeyInjectionOverlay.js +11 -11
  17. package/dist/components/ai/NewsSummaryCard/NewsSummaryCard.js +17 -17
  18. package/dist/components/ai/StockChart/StockChart.js +4 -4
  19. package/dist/components/auth/AuthLayout.js +4 -4
  20. package/dist/components/auth/LoginPage.d.ts +22 -0
  21. package/dist/components/auth/LoginPage.js +50 -42
  22. package/dist/components/data-display/CodeBlock.d.ts +33 -7
  23. package/dist/components/data-display/CodeBlock.js +134 -41
  24. package/dist/components/data-display/Table.js +8 -8
  25. package/dist/components/feedback/EmptyState.js +9 -9
  26. package/dist/components/feedback/ToastProvider.js +4 -4
  27. package/dist/components/forms/Checkbox.js +5 -5
  28. package/dist/components/forms/ComboBox.js +2 -2
  29. package/dist/components/forms/DatePicker.js +37 -32
  30. package/dist/components/forms/FileUpload.js +39 -37
  31. package/dist/components/forms/Input.js +19 -18
  32. package/dist/components/forms/MultiSelect.js +9 -8
  33. package/dist/components/forms/Radio.js +6 -6
  34. package/dist/components/forms/SegmentedControl.d.ts +1 -1
  35. package/dist/components/forms/SegmentedControl.js +28 -11
  36. package/dist/components/forms/Select.js +9 -8
  37. package/dist/components/forms/Textarea.d.ts +13 -11
  38. package/dist/components/forms/Textarea.js +36 -16
  39. package/dist/components/forms/ToggleSwitch.js +9 -9
  40. package/dist/components/layout/AboutRamme.d.ts +8 -0
  41. package/dist/components/layout/Accordion.js +25 -32
  42. package/dist/components/layout/AppShell.js +7 -7
  43. package/dist/components/layout/Card.js +38 -21
  44. package/dist/components/layout/DetailDrawer.js +37 -38
  45. package/dist/components/layout/Drawer.js +50 -51
  46. package/dist/components/layout/List.js +9 -9
  47. package/dist/components/layout/Modal.js +5 -5
  48. package/dist/components/layout/PageHeader.js +7 -7
  49. package/dist/components/layout/SectionHeader.js +4 -4
  50. package/dist/components/layout/SettingsContainer.d.ts +12 -0
  51. package/dist/components/layout/SettingsContainer.js +30 -18
  52. package/dist/components/layout/Sheet.d.ts +58 -0
  53. package/dist/components/layout/Sheet.js +144 -0
  54. package/dist/components/layout/Sidebar.js +1 -1
  55. package/dist/components/layout/UserNav.d.ts +13 -0
  56. package/dist/components/layout/UserNav.js +17 -17
  57. package/dist/components/molecular/ConnectorOverlay.d.ts +12 -0
  58. package/dist/components/navigation/Breadcrumbs.js +8 -8
  59. package/dist/components/navigation/Menu.js +6 -6
  60. package/dist/components/navigation/MobileNav.d.ts +44 -1
  61. package/dist/components/navigation/MobileNav.js +97 -71
  62. package/dist/components/navigation/Pagination.js +46 -41
  63. package/dist/components/navigation/Stepper.js +17 -17
  64. package/dist/components/navigation/Tabs.js +18 -11
  65. package/dist/components/theme/ThemeLab.d.ts +7 -1
  66. package/dist/components/theme/ThemeLab.js +175 -154
  67. package/dist/components/ui/icon-loader.d.ts +1 -1
  68. package/dist/contexts/ThemeContext.js +111 -82
  69. package/dist/data/mockData.d.ts +0 -3
  70. package/dist/index.css +1 -1
  71. package/dist/index.d.ts +10 -0
  72. package/dist/index.js +222 -197
  73. package/dist/lib/hooks/useBodyScrollLock.d.ts +27 -0
  74. package/dist/lib/hooks/useBodyScrollLock.js +18 -0
  75. package/dist/lib/hooks/useSheetGesture.d.ts +81 -0
  76. package/dist/lib/hooks/useSheetGesture.js +70 -0
  77. package/dist/lib/theme/themeUtils.d.ts +21 -0
  78. package/dist/lib/theme/themeUtils.js +31 -17
  79. package/dist/setupTests.d.ts +1 -0
  80. package/dist/wizardManifest.js +364 -19
  81. package/package.json +10 -4
  82. package/src/wizardManifest.ts +364 -19
  83. package/tailwind.preset.js +98 -10
@@ -24,11 +24,50 @@ export interface MobileNavProps {
24
24
  drawerFooter?: React.ReactNode;
25
25
  /** Additional CSS classes on the root bar. */
26
26
  className?: string;
27
+ /**
28
+ * How navigation is presented.
29
+ *
30
+ * - `'bar'` (default) — the fixed bottom tab bar, with a "More" drawer for
31
+ * `secondaryItems`.
32
+ * - `'sheet'` — no fixed bar at all. Every destination (tabs AND
33
+ * secondaryItems) lives in a `Sheet`, which the host opens via `isOpen`.
34
+ * Use this when the app already has a top header to hang a trigger from:
35
+ * a persistent bottom bar stacks directly on top of a mobile browser's
36
+ * own toolbar, and the two together eat ~120px of a phone screen before
37
+ * any content is drawn.
38
+ *
39
+ * `Sheet`, not `Drawer` — this surface is thumb-driven, which is the line
40
+ * Sheet's own docs draw between the two. It opens at 60% and grows to
41
+ * full as you drag or scroll it up, keeping the page visible behind it so
42
+ * the menu reads as a layer over where you are rather than a departure
43
+ * from it. ramme-marketing's AppHeader uses the same component the same
44
+ * way; this is that pattern, with the item rendering shared rather than
45
+ * hand-rolled per app.
46
+ */
47
+ variant?: 'bar' | 'sheet';
48
+ /**
49
+ * Controlled drawer state. Required for `'sheet'`, which has no trigger of
50
+ * its own. Ignored by `'bar'`, whose "More" button owns its own state.
51
+ */
52
+ isOpen?: boolean;
53
+ /** Fired when the sheet wants to close (backdrop, Escape, item tapped). */
54
+ onOpenChange?: (open: boolean) => void;
55
+ /**
56
+ * Extra content rendered inside the panel body, after the destinations and
57
+ * scrolling with them.
58
+ *
59
+ * The mirror of `drawerHeader` at the other end, and deliberately NOT
60
+ * `drawerFooter`: that one maps to the surface's sticky footer, pinned above
61
+ * the home indicator and always visible. Use this for content that belongs
62
+ * *with* the list rather than under it — a control that the header hides at
63
+ * narrow widths and would otherwise be unreachable, say.
64
+ */
65
+ children?: React.ReactNode;
27
66
  }
28
67
  /**
29
68
  * @wizard
30
69
  * @name MobileNav
31
- * @description A fixed bottom tab bar for mobile screens, providing native-feeling navigation with primary icon+label tabs and a "More" drawer for secondary links. Hidden on md: and up via Tailwind. Designed as the mobile counterpart to the desktop Sidebar.
70
+ * @description Mobile navigation, in two shapes. 'bar' is a fixed bottom tab bar with icon+label tabs and a "More" drawer for secondary links. 'sheet' drops the bar entirely and puts every destination in a bottom drawer the host opens from its own trigger — the right choice when a mobile browser's toolbar already owns the bottom edge. Hidden on md: and up via Tailwind. The mobile counterpart to the desktop Sidebar.
32
71
  * @tags navigation, mobile, bottom-bar, shell, ui
33
72
  * @category navigation
34
73
  * @id mobile-nav
@@ -40,5 +79,9 @@ export interface MobileNavProps {
40
79
  * @param {ReactNode} drawerHeader - Optional slot rendered at the top of the drawer body.
41
80
  * @param {ReactNode} drawerFooter - Optional slot rendered in the sticky drawer footer (e.g. Logout button).
42
81
  * @param {string} className - Additional CSS classes on the root nav bar.
82
+ * @param {string} variant - 'bar' (default) renders the fixed bottom tab bar with a "More" Drawer. 'sheet' renders no bar at all and puts every destination in a Sheet — opening at 60% and growing to full as you drag or scroll it up — which the host opens itself — use it when a top header can hold the trigger, since a fixed bar and a mobile browser's own toolbar stack into ~120px of lost screen.
83
+ * @param {boolean} isOpen - Controlled drawer state. Required by 'sheet', which has no trigger of its own; ignored by 'bar'.
84
+ * @param {function} onOpenChange - Fired when the sheet wants to close (backdrop, Escape, or an item tapped).
85
+ * @param {ReactNode} children - Extra content rendered in the panel body after the destinations, scrolling with them. The mirror of drawerHeader; use it instead of drawerFooter when the content belongs with the list rather than pinned under it.
43
86
  */
44
87
  export declare const MobileNav: React.FC<MobileNavProps>;
@@ -1,98 +1,126 @@
1
- import { jsxs as l, Fragment as g, jsx as r } from "react/jsx-runtime";
2
- import { useState as w, useCallback as f } from "react";
3
- import { cn as c } from "../../utils/cn.js";
4
- import { Icon as a } from "../ui/Icon.js";
5
- import { Drawer as y } from "../layout/Drawer.js";
6
- const C = ({ tab: n, isActive: o, onTap: s }) => /* @__PURE__ */ l(
1
+ import { jsxs as i, Fragment as w, jsx as r } from "react/jsx-runtime";
2
+ import { useState as S, useCallback as p } from "react";
3
+ import { cn as m } from "../../utils/cn.js";
4
+ import { Icon as u } from "../ui/Icon.js";
5
+ import { Drawer as z } from "../layout/Drawer.js";
6
+ import { Sheet as B } from "../layout/Sheet.js";
7
+ const v = ({ tab: t, isActive: s, onTap: o }) => /* @__PURE__ */ i(
7
8
  "button",
8
9
  {
9
- onClick: s,
10
- className: c(
10
+ onClick: o,
11
+ className: m(
11
12
  "flex flex-1 flex-col items-center justify-center gap-0.5 py-1.5 transition-colors duration-150",
12
- o ? "text-primary" : "text-muted-foreground active:text-foreground"
13
+ s ? "text-primary" : "text-muted-foreground active:text-foreground"
13
14
  ),
14
15
  children: [
15
16
  /* @__PURE__ */ r(
16
- a,
17
+ u,
17
18
  {
18
- name: n.icon,
19
- className: c(
19
+ name: t.icon,
20
+ className: m(
20
21
  "h-5 w-5 transition-transform duration-150",
21
- o && "scale-110"
22
+ s && "scale-110"
22
23
  )
23
24
  }
24
25
  ),
25
- /* @__PURE__ */ r("span", { className: "text-[10px] font-medium leading-tight", children: n.label })
26
+ /* @__PURE__ */ r("span", { className: "text-[10px] font-medium leading-tight", children: t.label })
26
27
  ]
27
28
  }
28
- ), D = ({ item: n, isActive: o, onTap: s }) => /* @__PURE__ */ l(
29
+ ), A = ({ item: t, isActive: s, onTap: o }) => /* @__PURE__ */ i(
29
30
  "button",
30
31
  {
31
- onClick: s,
32
- className: c(
32
+ onClick: o,
33
+ className: m(
33
34
  "flex w-full items-center gap-3 rounded-lg p-3 text-left transition-colors duration-150",
34
- o ? "bg-primary/10 text-primary" : "text-foreground hover:bg-muted active:bg-muted"
35
+ s ? "bg-primary/10 text-primary" : "text-foreground hover:bg-muted active:bg-muted"
35
36
  ),
36
37
  children: [
37
- /* @__PURE__ */ r(a, { name: n.icon, className: "h-5 w-5 shrink-0" }),
38
- /* @__PURE__ */ r("span", { className: "text-fluid-base font-medium", children: n.label })
38
+ /* @__PURE__ */ r(u, { name: t.icon, className: "h-5 w-5 shrink-0" }),
39
+ /* @__PURE__ */ r("span", { className: "text-fluid-base font-medium", children: t.label })
39
40
  ]
40
41
  }
41
- ), z = ({
42
- tabs: n,
43
- secondaryItems: o = [],
44
- activeTabId: s,
45
- onNavigate: t,
46
- drawerTitle: u = "Menu",
47
- drawerHeader: m,
48
- drawerFooter: x,
49
- className: h
42
+ ), J = ({
43
+ tabs: t,
44
+ secondaryItems: s = [],
45
+ activeTabId: o,
46
+ onNavigate: l,
47
+ drawerTitle: x = "Menu",
48
+ drawerHeader: h,
49
+ drawerFooter: b,
50
+ className: g,
51
+ variant: D = "bar",
52
+ isOpen: j,
53
+ onOpenChange: a,
54
+ children: T
50
55
  }) => {
51
- const [p, d] = w(!1), b = f(
56
+ const [C, I] = S(!1), n = D === "sheet", f = n ? !!j : C, c = p(
52
57
  (e) => {
53
- var i;
54
- (i = e.onClick) == null || i.call(e), t == null || t(e);
58
+ n ? a == null || a(e) : I(e);
55
59
  },
56
- [t]
57
- ), k = f(
60
+ [n, a]
61
+ ), k = n ? [...t, ...s] : s, M = p(
58
62
  (e) => {
59
- var i;
60
- (i = e.onClick) == null || i.call(e), t == null || t(e), d(!1);
63
+ var d;
64
+ (d = e.onClick) == null || d.call(e), l == null || l(e);
61
65
  },
62
- [t]
66
+ [l]
67
+ ), N = p(
68
+ (e) => {
69
+ var d;
70
+ (d = e.onClick) == null || d.call(e), l == null || l(e), c(!1);
71
+ },
72
+ // `setIsDrawerOpen` closes over `onOpenChange`, so it belongs here. Without
73
+ // it, a host that memoises `onNavigate` but passes `onOpenChange` inline
74
+ // keeps the first render's close handler for the life of the component and
75
+ // the sheet stops closing on tap.
76
+ [l, c]
63
77
  );
64
- return /* @__PURE__ */ l(g, { children: [
65
- /* @__PURE__ */ r(
78
+ if (n && k.length === 0) return null;
79
+ const y = /* @__PURE__ */ i(w, { children: [
80
+ h && /* @__PURE__ */ r("div", { className: "mb-fluid-md pb-fluid-sm border-b border-border", children: h }),
81
+ /* @__PURE__ */ r("div", { className: "space-y-1", children: k.map((e) => /* @__PURE__ */ r(
82
+ A,
83
+ {
84
+ item: e,
85
+ isActive: o === e.id,
86
+ onTap: () => N(e)
87
+ },
88
+ e.id
89
+ )) }),
90
+ T
91
+ ] });
92
+ return /* @__PURE__ */ i(w, { children: [
93
+ !n && /* @__PURE__ */ r(
66
94
  "nav",
67
95
  {
68
- className: c(
69
- "fixed inset-x-0 bottom-0 z-40 md:hidden",
96
+ className: m(
97
+ "fixed inset-x-0 bottom-0 z-nav md:hidden",
70
98
  "border-t border-border bg-card/95 backdrop-blur-md",
71
99
  "supports-[backdrop-filter]:bg-card/80",
72
100
  // Safe area for notched phones (iPhone etc.)
73
101
  "pb-[env(safe-area-inset-bottom,0px)]",
74
- h
102
+ g
75
103
  ),
76
- children: /* @__PURE__ */ l("div", { className: "flex items-stretch", children: [
77
- n.map((e) => /* @__PURE__ */ r(
78
- C,
104
+ children: /* @__PURE__ */ i("div", { className: "flex items-stretch", children: [
105
+ t.map((e) => /* @__PURE__ */ r(
106
+ v,
79
107
  {
80
108
  tab: e,
81
- isActive: s === e.id,
82
- onTap: () => b(e)
109
+ isActive: o === e.id,
110
+ onTap: () => M(e)
83
111
  },
84
112
  e.id
85
113
  )),
86
- o.length > 0 && /* @__PURE__ */ l(
114
+ s.length > 0 && /* @__PURE__ */ i(
87
115
  "button",
88
116
  {
89
- onClick: () => d(!0),
90
- className: c(
117
+ onClick: () => c(!0),
118
+ className: m(
91
119
  "flex flex-1 flex-col items-center justify-center gap-0.5 py-1.5 transition-colors duration-150",
92
- p ? "text-primary" : "text-muted-foreground active:text-foreground"
120
+ f ? "text-primary" : "text-muted-foreground active:text-foreground"
93
121
  ),
94
122
  children: [
95
- /* @__PURE__ */ r(a, { name: "menu", className: "h-5 w-5" }),
123
+ /* @__PURE__ */ r(u, { name: "menu", className: "h-5 w-5" }),
96
124
  /* @__PURE__ */ r("span", { className: "text-[10px] font-medium leading-tight", children: "More" })
97
125
  ]
98
126
  }
@@ -100,31 +128,29 @@ const C = ({ tab: n, isActive: o, onTap: s }) => /* @__PURE__ */ l(
100
128
  ] })
101
129
  }
102
130
  ),
103
- /* @__PURE__ */ l(
104
- y,
131
+ n ? /* @__PURE__ */ r(
132
+ B,
105
133
  {
106
- isOpen: p,
107
- onClose: () => d(!1),
134
+ isOpen: f,
135
+ onClose: () => c(!1),
136
+ title: x,
137
+ footer: b,
138
+ children: y
139
+ }
140
+ ) : /* @__PURE__ */ r(
141
+ z,
142
+ {
143
+ isOpen: f,
144
+ onClose: () => c(!1),
108
145
  position: "bottom",
109
146
  size: "85dvh",
110
- title: u,
111
- footer: x,
112
- children: [
113
- m && /* @__PURE__ */ r("div", { className: "mb-fluid-md pb-fluid-sm border-b border-border", children: m }),
114
- /* @__PURE__ */ r("div", { className: "space-y-1", children: o.map((e) => /* @__PURE__ */ r(
115
- D,
116
- {
117
- item: e,
118
- isActive: s === e.id,
119
- onTap: () => k(e)
120
- },
121
- e.id
122
- )) })
123
- ]
147
+ title: x,
148
+ footer: b,
149
+ children: y
124
150
  }
125
151
  )
126
152
  ] });
127
153
  };
128
154
  export {
129
- z as MobileNav
155
+ J as MobileNav
130
156
  };
@@ -1,6 +1,6 @@
1
- import { jsxs as x, jsx as m } from "react/jsx-runtime";
2
- import { useMemo as N, useCallback as o } from "react";
3
- import { Button as e } from "../ui/Button.js";
1
+ import { jsxs as u, jsx as m } from "react/jsx-runtime";
2
+ import { useMemo as N, useCallback as e } from "react";
3
+ import { Button as o } from "../ui/Button.js";
4
4
  const j = ({
5
5
  currentPage: s,
6
6
  totalPages: l,
@@ -21,50 +21,55 @@ const j = ({
21
21
  for (let f = h; f <= d; f++)
22
22
  i.push(f);
23
23
  return d < l && (d < l - 1 && i.push("..."), i.push(l)), i;
24
- }, [s, l, c]), v = o((i) => {
24
+ }, [s, l, c]), v = e((i) => {
25
25
  n(i);
26
- }, [n]), k = o(() => {
26
+ }, [n]), x = e(() => {
27
27
  n(s - 1);
28
- }, [s, n]), u = o(() => {
28
+ }, [s, n]), k = e(() => {
29
29
  n(s + 1);
30
30
  }, [s, n]);
31
- return l <= 1 ? null : /* @__PURE__ */ x("nav", { className: `flex items-center justify-center gap-2 ${p || ""}`, "aria-label": "Pagination", children: [
32
- /* @__PURE__ */ m(
33
- e,
34
- {
35
- variant: "outline",
36
- size: "sm",
37
- onClick: k,
38
- disabled: s === 1,
39
- iconLeft: "chevron-left",
40
- children: "Previous"
41
- }
42
- ),
43
- /* @__PURE__ */ m("div", { className: "flex items-center gap-1", children: t.map(
44
- (i, r) => typeof i == "number" ? /* @__PURE__ */ m(
45
- e,
31
+ return l <= 1 ? null : (
32
+ /* flex-wrap so the control folds instead of overflowing. Previous + the
33
+ page buttons + Next is wider than a 360px viewport, and without wrapping
34
+ the nav painted 74px past its container on every product that paginates. */
35
+ /* @__PURE__ */ u("nav", { className: `flex flex-wrap items-center justify-center gap-2 ${p || ""}`, "aria-label": "Pagination", children: [
36
+ /* @__PURE__ */ m(
37
+ o,
46
38
  {
47
- variant: s === i ? "primary" : "ghost",
39
+ variant: "outline",
48
40
  size: "sm",
49
- onClick: () => v(i),
50
- className: "w-10",
51
- children: i
52
- },
53
- i
54
- ) : /* @__PURE__ */ m("span", { className: "px-2 py-1 text-sm text-muted-foreground", children: "..." }, `ellipsis-${r}`)
55
- ) }),
56
- /* @__PURE__ */ m(
57
- e,
58
- {
59
- variant: "outline",
60
- size: "sm",
61
- onClick: u,
62
- disabled: s === l,
63
- iconRight: "chevron-right",
64
- children: "Next"
65
- }
66
- )
67
- ] });
41
+ onClick: x,
42
+ disabled: s === 1,
43
+ iconLeft: "chevron-left",
44
+ children: "Previous"
45
+ }
46
+ ),
47
+ /* @__PURE__ */ m("div", { className: "flex items-center gap-1", children: t.map(
48
+ (i, r) => typeof i == "number" ? /* @__PURE__ */ m(
49
+ o,
50
+ {
51
+ variant: s === i ? "primary" : "ghost",
52
+ size: "sm",
53
+ onClick: () => v(i),
54
+ className: "w-10",
55
+ children: i
56
+ },
57
+ i
58
+ ) : /* @__PURE__ */ m("span", { className: "px-2 py-1 text-sm text-muted-foreground", children: "..." }, `ellipsis-${r}`)
59
+ ) }),
60
+ /* @__PURE__ */ m(
61
+ o,
62
+ {
63
+ variant: "outline",
64
+ size: "sm",
65
+ onClick: k,
66
+ disabled: s === l,
67
+ iconRight: "chevron-right",
68
+ children: "Next"
69
+ }
70
+ )
71
+ ] })
72
+ );
68
73
  };
69
74
  export {
70
75
  j as Pagination
@@ -1,33 +1,33 @@
1
- import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
- import n from "react";
3
- import { Icon as d } from "../ui/Icon.js";
4
- const b = ({ steps: i, currentStep: r, className: c }) => /* @__PURE__ */ e("div", { className: `flex justify-between items-start ${c || ""}`, children: i.map((l, t) => {
5
- const s = t < r, m = t === r, o = t > r;
6
- return /* @__PURE__ */ a(n.Fragment, { children: [
7
- /* @__PURE__ */ a("div", { className: "flex flex-col items-center text-center", children: [
8
- /* @__PURE__ */ e(
1
+ import { jsx as r, jsxs as l } from "react/jsx-runtime";
2
+ import d from "react";
3
+ import { Icon as n } from "../ui/Icon.js";
4
+ const b = ({ steps: m, currentStep: t, className: o }) => /* @__PURE__ */ r("div", { className: `flex justify-between items-start ${o || ""}`, children: m.map((a, e) => {
5
+ const s = e < t, i = e === t, c = e > t;
6
+ return /* @__PURE__ */ l(d.Fragment, { children: [
7
+ /* @__PURE__ */ l("div", { className: "flex flex-col items-center text-center", children: [
8
+ /* @__PURE__ */ r(
9
9
  "div",
10
10
  {
11
11
  className: `w-8 h-8 rounded-full flex items-center justify-center border-2 transition-all duration-300
12
12
  ${s ? "bg-primary border-primary text-white" : ""}
13
- ${m ? "bg-card border-primary text-primary" : ""}
14
- ${o ? "bg-card border-border text-text-light" : ""}
13
+ ${i ? "bg-card border-primary text-primary" : ""}
14
+ ${c ? "bg-card border-border text-muted-foreground" : ""}
15
15
  `,
16
- children: s ? /* @__PURE__ */ e(d, { name: "check", size: 16 }) : /* @__PURE__ */ e("span", { children: t + 1 })
16
+ children: s ? /* @__PURE__ */ r(n, { name: "check", size: 16 }) : /* @__PURE__ */ r("span", { children: e + 1 })
17
17
  }
18
18
  ),
19
- /* @__PURE__ */ a("div", { className: "mt-2", children: [
20
- /* @__PURE__ */ e("p", { className: `font-semibold text-sm ${m ? "text-primary" : "text-text"}`, children: l.label }),
21
- l.summary && /* @__PURE__ */ e("p", { className: "text-xs text-text-light mt-1", children: l.summary })
19
+ /* @__PURE__ */ l("div", { className: "mt-2", children: [
20
+ /* @__PURE__ */ r("p", { className: `font-semibold text-sm ${i ? "text-primary" : "text-foreground"}`, children: a.label }),
21
+ a.summary && /* @__PURE__ */ r("p", { className: "text-xs text-muted-foreground mt-1", children: a.summary })
22
22
  ] })
23
23
  ] }),
24
- t < i.length - 1 && /* @__PURE__ */ e("div", { className: "flex-1 mt-4 mx-2 h-0.5", children: /* @__PURE__ */ e(
24
+ e < m.length - 1 && /* @__PURE__ */ r("div", { className: "flex-1 mt-4 mx-2 h-0.5", children: /* @__PURE__ */ r(
25
25
  "div",
26
26
  {
27
- className: `h-full w-full rounded-full transition-colors duration-300 ${t < r ? "bg-primary" : "bg-border"}`
27
+ className: `h-full w-full rounded-full transition-colors duration-300 ${e < t ? "bg-primary" : "bg-border"}`
28
28
  }
29
29
  ) })
30
- ] }, t);
30
+ ] }, e);
31
31
  }) });
32
32
  export {
33
33
  b as Stepper
@@ -1,30 +1,37 @@
1
- import { jsxs as i, jsx as a } from "react/jsx-runtime";
2
- import p, { useMemo as f, useState as g, useCallback as v } from "react";
1
+ import { jsxs as t, jsx as a } from "react/jsx-runtime";
2
+ import p, { useMemo as x, useState as g, useCallback as v } from "react";
3
3
  import { cn as l } from "../../utils/cn.js";
4
- const k = ({ children: o }) => /* @__PURE__ */ a("div", { role: "tabpanel", className: "p-4 bg-card rounded-b-lg border border-t-0 border-border", children: o }), C = ({ children: o, defaultActiveTab: e, className: c, size: s = "md" }) => {
5
- const d = f(() => e || (o.length > 0 ? o[0].props.id : ""), [o, e]), [n, m] = g(d), b = v((r) => m(r), []);
6
- return /* @__PURE__ */ i("div", { className: c, children: [
4
+ const k = ({ children: o }) => /* @__PURE__ */ a(
5
+ "div",
6
+ {
7
+ role: "tabpanel",
8
+ className: "@container bg-card py-fluid-md px-0 @md:px-fluid-md",
9
+ children: o
10
+ }
11
+ ), C = ({ children: o, defaultActiveTab: e, className: c, size: s = "md" }) => {
12
+ const d = x(() => e || (o.length > 0 ? o[0].props.id : ""), [o, e]), [n, m] = g(d), u = v((r) => m(r), []);
13
+ return /* @__PURE__ */ t("div", { className: c, children: [
7
14
  /* @__PURE__ */ a("div", { className: "flex border-b border-border mb-px", role: "tablist", children: o.map((r) => {
8
- const t = r.props.icon, u = s === "sm" ? 14 : 16, x = t && p.isValidElement(t) ? p.cloneElement(t, {
9
- size: u,
15
+ const i = r.props.icon, b = s === "sm" ? 14 : 16, f = i && p.isValidElement(i) ? p.cloneElement(i, {
16
+ size: b,
10
17
  className: l("mr-2", s === "sm" ? "mt-[1px]" : "")
11
18
  // slight alignment tweak for smaller text
12
19
  }) : null;
13
- return /* @__PURE__ */ i(
20
+ return /* @__PURE__ */ t(
14
21
  "button",
15
22
  {
16
23
  id: `tab-${r.props.id}`,
17
24
  role: "tab",
18
25
  "aria-controls": r.props.id,
19
26
  "aria-selected": n === r.props.id,
20
- onClick: () => b(r.props.id),
27
+ onClick: () => u(r.props.id),
21
28
  className: l(
22
- "inline-flex items-center text-text font-medium border-b-2 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
29
+ "inline-flex items-center text-foreground font-medium border-b-2 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
23
30
  s === "sm" ? "px-3 py-1.5 text-sm" : "px-4 py-2 text-lg",
24
31
  n === r.props.id ? "border-primary" : "border-transparent hover:border-border"
25
32
  ),
26
33
  children: [
27
- x,
34
+ f,
28
35
  r.props.label
29
36
  ]
30
37
  },
@@ -17,8 +17,14 @@ export interface ThemeLabProps {
17
17
  onTokensChange: (tokens: ThemeTokensDraft) => void;
18
18
  /** Saves activeTokens as the new master restore point. */
19
19
  onSave: () => void;
20
- /** Restores DOM and store to savedTokens. */
20
+ /** Restores DOM and store to savedTokens — discards edits since the last save. */
21
21
  onRevert: () => void;
22
+ /**
23
+ * Drops the user's theme entirely so the app's own theme takes over again.
24
+ * Optional: a host that has no baked-in theme has nothing to reset to, and
25
+ * the control is hidden rather than shown doing nothing.
26
+ */
27
+ onResetToDefault?: () => void;
22
28
  profiles: AestheticProfile[];
23
29
  profileIcons: Record<string, string>;
24
30
  activeProfileId?: string;