@skiddph/prui 0.7.0 → 0.8.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 (77) hide show
  1. package/dist/app/resource.d.ts +44 -1
  2. package/dist/app.js +1 -1
  3. package/dist/chunks/auth-shell-DQJ4UmUv.js +1208 -0
  4. package/dist/chunks/data-table-toolbar-B-5J2Ozl.js +736 -0
  5. package/dist/core/accordion.d.ts +16 -0
  6. package/dist/core/accordion.js +108 -0
  7. package/dist/core/alert.d.ts +20 -0
  8. package/dist/core/alert.js +63 -0
  9. package/dist/core/anchor.d.ts +35 -0
  10. package/dist/core/anchor.js +39 -0
  11. package/dist/core/breadcrumb.d.ts +30 -0
  12. package/dist/core/breadcrumb.js +67 -0
  13. package/dist/core/button.d.ts +8 -1
  14. package/dist/core/button.js +23 -18
  15. package/dist/core/calendar.d.ts +29 -0
  16. package/dist/core/calendar.js +180 -0
  17. package/dist/core/card.d.ts +5 -1
  18. package/dist/core/card.js +33 -29
  19. package/dist/core/checkbox.d.ts +19 -0
  20. package/dist/core/checkbox.js +55 -0
  21. package/dist/core/combobox.d.ts +32 -0
  22. package/dist/core/combobox.js +183 -0
  23. package/dist/core/date-picker.d.ts +41 -0
  24. package/dist/core/date-picker.js +202 -0
  25. package/dist/core/dialog.d.ts +8 -0
  26. package/dist/core/dialog.js +59 -61
  27. package/dist/core/drawer.d.ts +34 -0
  28. package/dist/core/drawer.js +129 -0
  29. package/dist/core/dropdown.d.ts +8 -4
  30. package/dist/core/dropdown.js +136 -51
  31. package/dist/core/file-upload.d.ts +28 -0
  32. package/dist/core/file-upload.js +111 -0
  33. package/dist/core/index.d.ts +21 -0
  34. package/dist/core/list-nav.d.ts +27 -0
  35. package/dist/core/list-nav.js +51 -0
  36. package/dist/core/modal.d.ts +14 -5
  37. package/dist/core/modal.js +163 -156
  38. package/dist/core/overlay.d.ts +93 -0
  39. package/dist/core/overlay.js +189 -0
  40. package/dist/core/popover.d.ts +29 -0
  41. package/dist/core/popover.js +124 -0
  42. package/dist/core/progress.d.ts +21 -0
  43. package/dist/core/progress.js +59 -0
  44. package/dist/core/radio.d.ts +20 -0
  45. package/dist/core/radio.js +115 -0
  46. package/dist/core/select.d.ts +6 -0
  47. package/dist/core/select.js +178 -97
  48. package/dist/core/skeleton.d.ts +20 -0
  49. package/dist/core/skeleton.js +41 -0
  50. package/dist/core/spinner.d.ts +15 -0
  51. package/dist/core/spinner.js +41 -0
  52. package/dist/core/tabs.js +82 -53
  53. package/dist/core/timeline.d.ts +22 -0
  54. package/dist/core/timeline.js +57 -0
  55. package/dist/core/toast.d.ts +36 -0
  56. package/dist/core/toast.js +123 -0
  57. package/dist/core/tooltip.d.ts +23 -0
  58. package/dist/core/tooltip.js +96 -0
  59. package/dist/core/tree-view.d.ts +34 -0
  60. package/dist/core/tree-view.js +133 -0
  61. package/dist/core.js +152 -62
  62. package/dist/data-table/data-table.d.ts +22 -1
  63. package/dist/data-table.js +1 -1
  64. package/dist/forms/form.d.ts +8 -0
  65. package/dist/forms.js +213 -200
  66. package/dist/i18n/index.d.ts +83 -0
  67. package/dist/i18n.js +99 -0
  68. package/dist/index.d.ts +1 -0
  69. package/dist/index.js +256 -156
  70. package/dist/prui-utilities.css +1 -1
  71. package/dist/prui.css +111 -4
  72. package/dist/theme/base.css +110 -3
  73. package/dist/theme/index.d.ts +27 -0
  74. package/dist/theme.js +86 -58
  75. package/package.json +9 -2
  76. package/dist/chunks/auth-shell-BG5vx9eG.js +0 -1054
  77. package/dist/chunks/data-table-toolbar-BUy2EWPy.js +0 -581
@@ -1,144 +1,225 @@
1
- import { jsxs as b, jsx as s, Fragment as P } from "react/jsx-runtime";
2
- import * as o from "react";
3
- import { ChevronDown as z, Check as D } from "lucide-react";
4
- import { cn as m } from "./cn.js";
5
- const S = o.createContext(null);
6
- function g() {
7
- const r = o.useContext(S);
8
- if (!r) throw new Error("Select parts must be used inside <Select>");
9
- return r;
1
+ import { jsxs as E, jsx as h, Fragment as H } from "react/jsx-runtime";
2
+ import * as r from "react";
3
+ import { ChevronDown as M, Check as B } from "lucide-react";
4
+ import { cn as A } from "./cn.js";
5
+ import { useOverlayStack as G, useEscapeKey as J } from "./overlay.js";
6
+ import { typeaheadIndex as Q, endIndex as W, homeIndex as X, moveIndex as L } from "./list-nav.js";
7
+ const P = r.createContext(null);
8
+ function D() {
9
+ const n = r.useContext(P);
10
+ if (!n) throw new Error("Select parts must be used inside <Select>");
11
+ return n;
10
12
  }
11
- const F = ({
12
- options: r,
13
- value: a,
14
- defaultValue: t,
13
+ const Y = ({
14
+ options: n,
15
+ value: s,
16
+ defaultValue: p,
15
17
  placeholder: i = "Select...",
16
- disabled: e,
17
- name: d,
18
- id: u,
19
- onChange: l,
20
- onOpenChange: p,
21
- children: f,
22
- ...c
18
+ disabled: u,
19
+ name: l,
20
+ id: v,
21
+ onChange: c,
22
+ onOpenChange: d,
23
+ children: S,
24
+ ...g
23
25
  }) => {
24
- const [v, I] = o.useState(t ?? ""), [R, T] = o.useState(!1), [V, j] = o.useState(), x = a !== void 0 ? a : v, O = (n) => {
25
- a === void 0 && I(n), l == null || l(n);
26
- }, E = (n) => {
27
- T(n), p == null || p(n);
28
- };
29
- return /* @__PURE__ */ b(
30
- S.Provider,
26
+ var j;
27
+ const [b, y] = r.useState(p ?? ""), [x, w] = r.useState(!1), [t, N] = r.useState(null), [k, V] = r.useState({}), e = s !== void 0 ? s : b, o = r.useCallback((a, O) => {
28
+ V((R) => {
29
+ if (O === null) {
30
+ if (!(a in R)) return R;
31
+ const F = { ...R };
32
+ return delete F[a], F;
33
+ }
34
+ return R[a] === O ? R : { ...R, [a]: O };
35
+ });
36
+ }, []), I = (a) => {
37
+ s === void 0 && y(a), c == null || c(a);
38
+ }, m = (a) => {
39
+ w(a), d == null || d(a);
40
+ }, f = () => t == null ? void 0 : t.focus(), T = k[e] ?? ((j = n == null ? void 0 : n.find((a) => a.value === e)) == null ? void 0 : j.label);
41
+ return /* @__PURE__ */ E(
42
+ P.Provider,
31
43
  {
32
- value: { value: x, open: R, triggerId: V, setValue: O, setOpen: E, registerTrigger: j },
44
+ value: { value: e, displayValue: T, open: x, triggerId: (t == null ? void 0 : t.id) || void 0, setValue: I, setOpen: m, registerTrigger: N, returnFocusToTrigger: f, registerLabel: o },
33
45
  children: [
34
- d ? /* @__PURE__ */ s("input", { type: "hidden", name: d, value: x }) : null,
35
- f ?? /* @__PURE__ */ b(P, { children: [
36
- /* @__PURE__ */ s(h, { disabled: e, id: u, ...c, children: /* @__PURE__ */ s(y, { placeholder: i }) }),
37
- /* @__PURE__ */ s(w, { children: (r ?? []).map((n) => /* @__PURE__ */ s(N, { value: n.value, disabled: n.disabled, children: n.label }, n.value)) })
46
+ l ? /* @__PURE__ */ h("input", { type: "hidden", name: l, value: e }) : null,
47
+ S ?? /* @__PURE__ */ E(H, { children: [
48
+ /* @__PURE__ */ h(U, { disabled: u, id: v, ...g, children: /* @__PURE__ */ h($, { placeholder: i }) }),
49
+ /* @__PURE__ */ h(z, { children: (n ?? []).map((a) => /* @__PURE__ */ h(q, { value: a.value, disabled: a.disabled, children: a.label }, a.value)) })
38
50
  ] })
39
51
  ]
40
52
  }
41
53
  );
42
54
  };
43
- F.displayName = "Select";
44
- const h = o.forwardRef(
45
- ({ className: r, children: a, onClick: t, disabled: i, id: e, ...d }, u) => {
46
- const { open: l, setOpen: p, registerTrigger: f } = g();
47
- return o.useEffect(() => {
48
- e && f(e);
49
- }, [e, f]), /* @__PURE__ */ b(
55
+ Y.displayName = "Select";
56
+ const U = r.forwardRef(
57
+ ({ className: n, children: s, onClick: p, onKeyDown: i, disabled: u, id: l, ...v }, c) => {
58
+ const { open: d, setOpen: S, registerTrigger: g } = D(), b = r.useRef(null), y = r.useId(), x = l ?? `prui-select-${y}`;
59
+ r.useEffect(() => (g(b.current), () => g(null)), [g]);
60
+ const w = `${x}-listbox`;
61
+ return /* @__PURE__ */ E(
50
62
  "button",
51
63
  {
52
- ref: u,
53
- id: e,
64
+ ref: (t) => {
65
+ b.current = t, typeof c == "function" ? c(t) : c && (c.current = t);
66
+ },
67
+ id: x,
54
68
  type: "button",
55
69
  role: "combobox",
56
- "aria-expanded": l,
70
+ "aria-expanded": d,
57
71
  "aria-haspopup": "listbox",
58
- disabled: i,
59
- "data-state": l ? "open" : "closed",
60
- className: m(
72
+ "aria-controls": d ? w : void 0,
73
+ disabled: u,
74
+ "data-state": d ? "open" : "closed",
75
+ className: A(
61
76
  "prui-select-trigger flex h-9 w-full items-center justify-between gap-2 border border-[var(--prui-line)]",
62
77
  "bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)]",
63
78
  "outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
64
79
  "disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer",
65
- r
80
+ n
66
81
  ),
67
- onClick: (c) => {
68
- t == null || t(c), c.defaultPrevented || p(!l);
82
+ onClick: (t) => {
83
+ p == null || p(t), t.defaultPrevented || S(!d);
84
+ },
85
+ onKeyDown: (t) => {
86
+ i == null || i(t), !t.defaultPrevented && !d && (t.key === "ArrowDown" || t.key === "ArrowUp" || t.key === "Enter" || t.key === " ") && (t.preventDefault(), S(!0));
69
87
  },
70
- ...d,
88
+ ...v,
71
89
  children: [
72
- a,
73
- /* @__PURE__ */ s(z, { className: m("h-4 w-4 shrink-0 text-[var(--prui-dim)] transition-transform", l && "rotate-180"), "aria-hidden": !0 })
90
+ s,
91
+ /* @__PURE__ */ h(M, { className: A("h-4 w-4 shrink-0 text-[var(--prui-dim)] transition-transform", d && "rotate-180"), "aria-hidden": !0 })
74
92
  ]
75
93
  }
76
94
  );
77
95
  }
78
96
  );
79
- h.displayName = "SelectTrigger";
80
- const y = o.forwardRef(
81
- ({ className: r, placeholder: a, children: t, ...i }, e) => {
82
- const { value: d } = g();
83
- return /* @__PURE__ */ s("span", { ref: e, className: m("truncate", r), ...i, children: t ?? (d || /* @__PURE__ */ s("span", { className: "text-[var(--prui-dim)]", children: a })) });
97
+ U.displayName = "SelectTrigger";
98
+ const $ = r.forwardRef(
99
+ ({ className: n, placeholder: s, children: p, ...i }, u) => {
100
+ const { value: l, displayValue: v } = D();
101
+ return /* @__PURE__ */ h("span", { ref: u, className: A("truncate", n), ...i, children: p ?? v ?? (l || /* @__PURE__ */ h("span", { className: "text-[var(--prui-dim)]", children: s })) });
84
102
  }
85
103
  );
86
- y.displayName = "SelectValue";
87
- const w = o.forwardRef(
88
- ({ className: r, children: a, ...t }, i) => {
89
- const { open: e, setOpen: d, triggerId: u } = g();
90
- return e ? /* @__PURE__ */ s(
104
+ $.displayName = "SelectValue";
105
+ const z = r.forwardRef(
106
+ ({ className: n, children: s, id: p, ...i }, u) => {
107
+ const { open: l, setOpen: v, triggerId: c, setValue: d, returnFocusToTrigger: S } = D(), g = r.useRef(null), [b, y] = r.useState(-1), x = r.useRef({ buffer: "", at: 0 }), { setElement: w, isTop: t } = G(l);
108
+ J(l, t, () => {
109
+ v(!1), S();
110
+ });
111
+ const N = r.useCallback(() => {
112
+ const e = g.current;
113
+ return e ? Array.from(e.querySelectorAll("[role='option']")) : [];
114
+ }, []), k = (e) => {
115
+ var o;
116
+ y(e), (o = N()[e]) == null || o.focus();
117
+ };
118
+ if (r.useEffect(() => {
119
+ var f;
120
+ if (!l) return;
121
+ y(-1);
122
+ const e = N(), o = e.findIndex((T) => T.getAttribute("aria-selected") === "true"), I = e.findIndex((T) => T.getAttribute("aria-disabled") !== "true"), m = o >= 0 ? o : I;
123
+ m >= 0 && (y(m), (f = e[m]) == null || f.focus());
124
+ }, [l, N]), !l) return null;
125
+ const V = (e) => {
126
+ const o = N(), I = (m) => {
127
+ var f;
128
+ return ((f = o[m]) == null ? void 0 : f.getAttribute("aria-disabled")) !== "true";
129
+ };
130
+ switch (e.key) {
131
+ case "ArrowDown":
132
+ e.preventDefault(), k(L(b, 1, o.length, { enabled: I }));
133
+ break;
134
+ case "ArrowUp":
135
+ e.preventDefault(), k(L(b, -1, o.length, { enabled: I }));
136
+ break;
137
+ case "Home":
138
+ e.preventDefault(), k(X(o.length, I));
139
+ break;
140
+ case "End":
141
+ e.preventDefault(), k(W(o.length, I));
142
+ break;
143
+ case "Enter":
144
+ case " ": {
145
+ e.preventDefault();
146
+ const m = o[b];
147
+ if (m && I(b)) {
148
+ const f = m.dataset.value;
149
+ f !== void 0 ? (d(f), v(!1), S()) : m.click();
150
+ }
151
+ break;
152
+ }
153
+ case "Tab":
154
+ v(!1);
155
+ break;
156
+ default:
157
+ if (e.key.length === 1) {
158
+ const m = () => o.map((T) => T.textContent ?? ""), { index: f } = Q(m, x.current, e.key, b);
159
+ f >= 0 && f !== b && (e.preventDefault(), k(f));
160
+ }
161
+ }
162
+ };
163
+ return /* @__PURE__ */ h(
91
164
  "div",
92
165
  {
93
- ref: i,
166
+ ref: (e) => {
167
+ g.current = e, w((e == null ? void 0 : e.parentElement) ?? null), typeof u == "function" ? u(e) : u && (u.current = e);
168
+ },
169
+ id: p ?? (c ? `${c}-listbox` : void 0),
94
170
  role: "listbox",
95
- "aria-labelledby": u,
171
+ "aria-labelledby": c,
96
172
  tabIndex: -1,
97
- "data-state": e ? "open" : "closed",
98
- className: m(
99
- "prui-select-content absolute z-50 mt-1 min-w-40 max-h-60 overflow-auto p-1",
100
- "bg-[var(--prui-surface)] border border-[var(--prui-line)] rounded-[var(--prui-radius)] shadow-lg",
101
- r
173
+ "data-state": l ? "open" : "closed",
174
+ onKeyDown: V,
175
+ className: A(
176
+ "prui-select-content absolute z-[var(--prui-z-overlay)] mt-1 min-w-40 max-h-60 overflow-auto p-1",
177
+ "bg-[var(--prui-surface)] border border-[var(--prui-line)] rounded-[var(--prui-radius)] shadow-[var(--prui-shadow-md)] outline-none",
178
+ n
102
179
  ),
103
- ...t,
104
- children: a
180
+ ...i,
181
+ children: s
105
182
  }
106
- ) : null;
183
+ );
107
184
  }
108
185
  );
109
- w.displayName = "SelectContent";
110
- const N = o.forwardRef(
111
- ({ className: r, value: a, disabled: t, children: i, onClick: e, ...d }, u) => {
112
- const { value: l, setValue: p, setOpen: f } = g(), c = l === a;
113
- return /* @__PURE__ */ b(
186
+ z.displayName = "SelectContent";
187
+ const q = r.forwardRef(
188
+ ({ className: n, value: s, disabled: p, children: i, onClick: u, tabIndex: l = -1, ...v }, c) => {
189
+ const { value: d, setValue: S, setOpen: g, returnFocusToTrigger: b, registerLabel: y } = D(), x = d === s, w = typeof i == "string" || typeof i == "number" ? String(i) : void 0;
190
+ return r.useEffect(() => {
191
+ w !== void 0 && y(s, w);
192
+ }, [s, w, y]), /* @__PURE__ */ E(
114
193
  "div",
115
194
  {
116
- ref: u,
195
+ ref: c,
117
196
  role: "option",
118
- "aria-selected": c,
119
- "aria-disabled": t,
120
- "data-selected": c || void 0,
121
- className: m(
197
+ "aria-selected": x,
198
+ "aria-disabled": p,
199
+ "data-selected": x || void 0,
200
+ "data-value": s,
201
+ tabIndex: l,
202
+ className: A(
122
203
  "prui-select-item relative flex cursor-pointer items-center gap-2 rounded-[calc(var(--prui-radius)-1px)]",
123
- "py-1.5 pl-3 pr-8 text-sm text-[var(--prui-fg)] hover:bg-[var(--prui-raise)]",
124
- c && "font-medium",
125
- t && "opacity-50 pointer-events-none",
126
- r
204
+ "py-1.5 pl-3 pr-8 text-sm text-[var(--prui-fg)] hover:bg-[var(--prui-raise)] focus-visible:bg-[var(--prui-raise)] outline-none",
205
+ x && "font-medium",
206
+ p && "opacity-50 pointer-events-none",
207
+ n
127
208
  ),
128
- onClick: (v) => {
129
- e == null || e(v), !(v.defaultPrevented || t) && (p(a), f(!1));
209
+ onClick: (t) => {
210
+ u == null || u(t), !(t.defaultPrevented || p) && (S(s), g(!1), b());
130
211
  },
131
- ...d,
212
+ ...v,
132
213
  children: [
133
214
  i,
134
- c ? /* @__PURE__ */ s(D, { className: "absolute right-2 h-4 w-4 text-[var(--prui-brand)]", "aria-hidden": !0 }) : null
215
+ x ? /* @__PURE__ */ h(B, { className: "absolute right-2 h-4 w-4 text-[var(--prui-brand)]", "aria-hidden": !0 }) : null
135
216
  ]
136
217
  }
137
218
  );
138
219
  }
139
220
  );
140
- N.displayName = "SelectItem";
141
- const A = {
221
+ q.displayName = "SelectItem";
222
+ const te = {
142
223
  name: "Select",
143
224
  props: [
144
225
  { name: "options", type: "SelectOption[]", default: "[]", control: "object" },
@@ -150,10 +231,10 @@ const A = {
150
231
  ]
151
232
  };
152
233
  export {
153
- F as Select,
154
- w as SelectContent,
155
- N as SelectItem,
156
- h as SelectTrigger,
157
- y as SelectValue,
158
- A as selectPropsMeta
234
+ Y as Select,
235
+ z as SelectContent,
236
+ q as SelectItem,
237
+ U as SelectTrigger,
238
+ $ as SelectValue,
239
+ te as selectPropsMeta
159
240
  };
@@ -0,0 +1,20 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ /**
4
+ * Skeleton: a placeholder shimmer for loading layouts. Purely decorative
5
+ * (aria-hidden); pair with a live region or <Spinner> for the accessible
6
+ * loading announcement.
7
+ */
8
+ export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement>, SurfacePropsLike {
9
+ /** Shape preset. */
10
+ variant?: "text" | "rect" | "circle";
11
+ /** Text variant line height in rem units (e.g. 1 for a text line). */
12
+ lines?: number;
13
+ }
14
+ interface SurfacePropsLike {
15
+ /** Any CSS background value overriding the shimmer base. */
16
+ bg?: string;
17
+ }
18
+ export declare const Skeleton: React.ForwardRefExoticComponent<SkeletonProps & React.RefAttributes<HTMLDivElement>>;
19
+ export declare const skeletonPropsMeta: PropsMeta;
20
+ export {};
@@ -0,0 +1,41 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import * as c from "react";
3
+ import { cn as o } from "./cn.js";
4
+ const s = {
5
+ text: "rounded-[var(--prui-radius-1)] h-4",
6
+ rect: "rounded-[var(--prui-radius)]",
7
+ circle: "rounded-[var(--prui-radius-full)] aspect-square"
8
+ }, p = c.forwardRef(
9
+ ({ className: a, variant: n = "text", lines: e = 1, bg: i, style: l, ...u }, d) => n === "text" && e > 1 ? /* @__PURE__ */ t("div", { className: o("prui-skeleton-group flex flex-col gap-2", a), role: "presentation", children: Array.from({ length: e }).map((m, r) => /* @__PURE__ */ t(
10
+ "div",
11
+ {
12
+ ref: r === 0 ? d : void 0,
13
+ "aria-hidden": !0,
14
+ className: o("prui-skeleton prui-anim-fade", s.text, r === e - 1 && "w-2/3"),
15
+ style: { backgroundColor: i ?? void 0, ...l }
16
+ },
17
+ r
18
+ )) }) : /* @__PURE__ */ t(
19
+ "div",
20
+ {
21
+ ref: d,
22
+ "aria-hidden": !0,
23
+ className: o("prui-skeleton prui-anim-fade", s[n], a),
24
+ style: { backgroundColor: i ?? void 0, ...l },
25
+ ...u
26
+ }
27
+ )
28
+ );
29
+ p.displayName = "Skeleton";
30
+ const k = {
31
+ name: "Skeleton",
32
+ props: [
33
+ { name: "variant", type: "'text' | 'rect' | 'circle'", default: "'text'", control: "select", options: ["text", "rect", "circle"] },
34
+ { name: "lines", type: "number (text variant)", default: "1", control: "number" },
35
+ { name: "bg", type: "string (CSS background)", default: "shimmer token", control: "text" }
36
+ ]
37
+ };
38
+ export {
39
+ p as Skeleton,
40
+ k as skeletonPropsMeta
41
+ };
@@ -0,0 +1,15 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ /**
4
+ * Spinner: an inline loading indicator with an accessible label. Announces
5
+ * through role="status" so screen readers hear loading state without
6
+ * stealing focus.
7
+ */
8
+ export type SpinnerSize = "xs" | "sm" | "md" | "lg";
9
+ export interface SpinnerProps extends React.HTMLAttributes<HTMLSpanElement> {
10
+ /** Accessible label announced to screen readers. */
11
+ label?: string;
12
+ size?: SpinnerSize;
13
+ }
14
+ export declare const Spinner: React.ForwardRefExoticComponent<SpinnerProps & React.RefAttributes<HTMLSpanElement>>;
15
+ export declare const spinnerPropsMeta: PropsMeta;
@@ -0,0 +1,41 @@
1
+ import { jsxs as m, jsx as s } from "react/jsx-runtime";
2
+ import * as p from "react";
3
+ import { Loader2 as l } from "lucide-react";
4
+ import { cn as n } from "./cn.js";
5
+ import { usePruiI18n as c } from "../i18n.js";
6
+ const d = {
7
+ xs: "h-3 w-3",
8
+ sm: "h-4 w-4",
9
+ md: "h-6 w-6",
10
+ lg: "h-8 w-8"
11
+ }, f = p.forwardRef(
12
+ ({ className: r, label: e, size: i = "md", ...t }, a) => {
13
+ const { t: o } = c();
14
+ return /* @__PURE__ */ m(
15
+ "span",
16
+ {
17
+ ref: a,
18
+ role: "status",
19
+ "aria-label": e ?? o.loading,
20
+ className: n("prui-spinner inline-flex items-center justify-center text-[var(--prui-dim)]", r),
21
+ ...t,
22
+ children: [
23
+ /* @__PURE__ */ s(l, { className: n("animate-spin", d[i]), "aria-hidden": !0 }),
24
+ e ? /* @__PURE__ */ s("span", { className: "sr-only", children: e }) : null
25
+ ]
26
+ }
27
+ );
28
+ }
29
+ );
30
+ f.displayName = "Spinner";
31
+ const w = {
32
+ name: "Spinner",
33
+ props: [
34
+ { name: "label", type: "string", default: "'Loading...'", control: "text", description: "Accessible label." },
35
+ { name: "size", type: "'xs' | 'sm' | 'md' | 'lg'", default: "'md'", control: "select", options: ["xs", "sm", "md", "lg"] }
36
+ ]
37
+ };
38
+ export {
39
+ f as Spinner,
40
+ w as spinnerPropsMeta
41
+ };
package/dist/core/tabs.js CHANGED
@@ -1,82 +1,111 @@
1
- import { jsx as l } from "react/jsx-runtime";
2
- import * as r from "react";
3
- import { cn as c } from "./cn.js";
4
- const f = r.createContext(null);
5
- function m() {
6
- const t = r.useContext(f);
7
- if (!t) throw new Error("Tabs parts must be used inside <Tabs>");
8
- return t;
1
+ import { jsx as f } from "react/jsx-runtime";
2
+ import * as l from "react";
3
+ import { cn as m } from "./cn.js";
4
+ const y = l.createContext(null);
5
+ function g() {
6
+ const n = l.useContext(y);
7
+ if (!n) throw new Error("Tabs parts must be used inside <Tabs>");
8
+ return n;
9
9
  }
10
- const x = ({ value: t, defaultValue: e, onChange: a, className: i, children: o, ...s }) => {
11
- const [b, u] = r.useState(e ?? ""), n = t !== void 0 ? t : b, d = r.useId(), v = (p) => {
12
- t === void 0 && u(p), a == null || a(p);
10
+ const x = ({ value: n, defaultValue: a, onChange: s, className: i, children: o, ...u }) => {
11
+ const [b, t] = l.useState(a ?? ""), e = n !== void 0 ? n : b, c = l.useId(), p = (d) => {
12
+ n === void 0 && t(d), s == null || s(d);
13
13
  };
14
- return /* @__PURE__ */ l(f.Provider, { value: { value: n, setValue: v, baseId: d }, children: /* @__PURE__ */ l("div", { className: c("prui-tabs", i), ...s, children: o }) });
14
+ return /* @__PURE__ */ f(y.Provider, { value: { value: e, setValue: p, baseId: c }, children: /* @__PURE__ */ f("div", { className: m("prui-tabs", i), ...u, children: o }) });
15
15
  };
16
16
  x.displayName = "Tabs";
17
- const g = r.forwardRef(
18
- ({ className: t, ...e }, a) => /* @__PURE__ */ l(
19
- "div",
20
- {
21
- ref: a,
22
- role: "tablist",
23
- className: c(
24
- "prui-tabs-list inline-flex h-9 items-center gap-1 rounded-[var(--prui-radius)] bg-[var(--prui-raise)] p-1",
25
- t
26
- ),
27
- ...e
28
- }
29
- )
17
+ const T = l.forwardRef(
18
+ ({ className: n, onKeyDown: a, ...s }, i) => {
19
+ const o = l.useRef(null), u = () => {
20
+ const t = o.current;
21
+ return t ? Array.from(t.querySelectorAll("[role='tab']")) : [];
22
+ };
23
+ return /* @__PURE__ */ f(
24
+ "div",
25
+ {
26
+ ref: (t) => {
27
+ o.current = t, typeof i == "function" ? i(t) : i && (i.current = t);
28
+ },
29
+ role: "tablist",
30
+ "aria-orientation": "horizontal",
31
+ onKeyDown: (t) => {
32
+ var d, v;
33
+ if (a == null || a(t), t.defaultPrevented) return;
34
+ const e = u(), c = e.findIndex((r) => r.tabIndex === 0), p = t.key === "ArrowRight" || t.key === "ArrowDown" ? 1 : t.key === "ArrowLeft" || t.key === "ArrowUp" ? -1 : 0;
35
+ if (p !== 0) {
36
+ t.preventDefault();
37
+ const r = e[(c + p + e.length) % e.length];
38
+ r == null || r.focus(), r == null || r.click();
39
+ return;
40
+ }
41
+ if (t.key === "Home") {
42
+ t.preventDefault(), (d = e[0]) == null || d.focus(), (v = e[0]) == null || v.click();
43
+ return;
44
+ }
45
+ if (t.key === "End") {
46
+ t.preventDefault();
47
+ const r = e[e.length - 1];
48
+ r == null || r.focus(), r == null || r.click();
49
+ }
50
+ },
51
+ className: m(
52
+ "prui-tabs-list inline-flex h-9 items-center gap-1 rounded-[var(--prui-radius)] bg-[var(--prui-raise)] p-1",
53
+ n
54
+ ),
55
+ ...s
56
+ }
57
+ );
58
+ }
30
59
  );
31
- g.displayName = "TabsList";
32
- const T = r.forwardRef(
33
- ({ className: t, value: e, onClick: a, ...i }, o) => {
34
- const { value: s, setValue: b, baseId: u } = m(), n = s === e;
35
- return /* @__PURE__ */ l(
60
+ T.displayName = "TabsList";
61
+ const w = l.forwardRef(
62
+ ({ className: n, value: a, onClick: s, ...i }, o) => {
63
+ const { value: u, setValue: b, baseId: t } = g(), e = u === a;
64
+ return /* @__PURE__ */ f(
36
65
  "button",
37
66
  {
38
67
  ref: o,
39
68
  type: "button",
40
69
  role: "tab",
41
- id: `${u}-tab-${e}`,
42
- "aria-selected": n,
43
- "aria-controls": `${u}-panel-${e}`,
44
- "data-state": n ? "active" : "inactive",
45
- tabIndex: n ? 0 : -1,
46
- className: c(
70
+ id: `${t}-tab-${a}`,
71
+ "aria-selected": e,
72
+ "aria-controls": e ? `${t}-panel-${a}` : void 0,
73
+ "data-state": e ? "active" : "inactive",
74
+ tabIndex: e ? 0 : -1,
75
+ className: m(
47
76
  "prui-tabs-trigger inline-flex items-center justify-center whitespace-nowrap rounded-[calc(var(--prui-radius)-1px)]",
48
77
  "px-3 py-1 text-sm font-medium transition-colors cursor-pointer outline-none",
49
78
  "focus-visible:ring-2 focus-visible:ring-[var(--prui-brand)]",
50
- n ? "bg-[var(--prui-background)] text-[var(--prui-fg)] shadow" : "text-[var(--prui-dim)] hover:text-[var(--prui-fg)]",
51
- t
79
+ e ? "bg-[var(--prui-background)] text-[var(--prui-fg)] shadow" : "text-[var(--prui-dim)] hover:text-[var(--prui-fg)]",
80
+ n
52
81
  ),
53
- onClick: (d) => {
54
- a == null || a(d), d.defaultPrevented || b(e);
82
+ onClick: (c) => {
83
+ s == null || s(c), c.defaultPrevented || b(a);
55
84
  },
56
85
  ...i
57
86
  }
58
87
  );
59
88
  }
60
89
  );
61
- T.displayName = "TabsTrigger";
62
- const y = r.forwardRef(
63
- ({ className: t, value: e, ...a }, i) => {
64
- const { value: o, baseId: s } = m();
65
- return o !== e ? null : /* @__PURE__ */ l(
90
+ w.displayName = "TabsTrigger";
91
+ const h = l.forwardRef(
92
+ ({ className: n, value: a, ...s }, i) => {
93
+ const { value: o, baseId: u } = g();
94
+ return o !== a ? null : /* @__PURE__ */ f(
66
95
  "div",
67
96
  {
68
97
  ref: i,
69
98
  role: "tabpanel",
70
- id: `${s}-panel-${e}`,
71
- "aria-labelledby": `${s}-tab-${e}`,
99
+ id: `${u}-panel-${a}`,
100
+ "aria-labelledby": `${u}-tab-${a}`,
72
101
  tabIndex: 0,
73
- className: c("prui-tabs-content mt-2 outline-none", t),
74
- ...a
102
+ className: m("prui-tabs-content mt-2 outline-none", n),
103
+ ...s
75
104
  }
76
105
  );
77
106
  }
78
107
  );
79
- y.displayName = "TabsContent";
108
+ h.displayName = "TabsContent";
80
109
  const $ = {
81
110
  name: "Tabs",
82
111
  props: [
@@ -87,8 +116,8 @@ const $ = {
87
116
  };
88
117
  export {
89
118
  x as Tabs,
90
- y as TabsContent,
91
- g as TabsList,
92
- T as TabsTrigger,
119
+ h as TabsContent,
120
+ T as TabsList,
121
+ w as TabsTrigger,
93
122
  $ as tabsPropsMeta
94
123
  };
@@ -0,0 +1,22 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ /**
4
+ * Timeline: a vertical chronological list with markers, timestamps, and
5
+ * optional icons/colors per item. Presentational (role="list" semantics);
6
+ * content is fully caller-owned.
7
+ */
8
+ export type TimelineVariant = "brand" | "success" | "warning" | "danger" | "neutral";
9
+ export interface TimelineItemData {
10
+ title: React.ReactNode;
11
+ time?: React.ReactNode;
12
+ description?: React.ReactNode;
13
+ icon?: React.ReactNode;
14
+ variant?: TimelineVariant;
15
+ }
16
+ export interface TimelineProps extends React.HTMLAttributes<HTMLOListElement> {
17
+ items: TimelineItemData[];
18
+ /** Marker alignment relative to the content column. Default left. */
19
+ align?: "left" | "alternate" | "right";
20
+ }
21
+ export declare const Timeline: React.ForwardRefExoticComponent<TimelineProps & React.RefAttributes<HTMLOListElement>>;
22
+ export declare const timelinePropsMeta: PropsMeta;