@skiddph/prui 0.7.0 → 0.9.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 (79) 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 +193 -0
  23. package/dist/core/date-picker.d.ts +62 -0
  24. package/dist/core/date-picker.js +314 -0
  25. package/dist/core/dialog.d.ts +15 -0
  26. package/dist/core/dialog.js +77 -60
  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 +23 -1
  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 +187 -98
  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/time-picker.d.ts +68 -0
  54. package/dist/core/time-picker.js +305 -0
  55. package/dist/core/timeline.d.ts +22 -0
  56. package/dist/core/timeline.js +57 -0
  57. package/dist/core/toast.d.ts +36 -0
  58. package/dist/core/toast.js +123 -0
  59. package/dist/core/tooltip.d.ts +23 -0
  60. package/dist/core/tooltip.js +96 -0
  61. package/dist/core/tree-view.d.ts +34 -0
  62. package/dist/core/tree-view.js +133 -0
  63. package/dist/core.js +160 -62
  64. package/dist/data-table/data-table.d.ts +22 -1
  65. package/dist/data-table.js +1 -1
  66. package/dist/forms/form.d.ts +8 -0
  67. package/dist/forms.js +213 -200
  68. package/dist/i18n/index.d.ts +89 -0
  69. package/dist/i18n.js +105 -0
  70. package/dist/index.d.ts +1 -0
  71. package/dist/index.js +263 -155
  72. package/dist/prui-utilities.css +1 -1
  73. package/dist/prui.css +111 -4
  74. package/dist/theme/base.css +110 -3
  75. package/dist/theme/index.d.ts +27 -0
  76. package/dist/theme.js +86 -58
  77. package/package.json +9 -2
  78. package/dist/chunks/auth-shell-BG5vx9eG.js +0 -1054
  79. package/dist/chunks/data-table-toolbar-BUy2EWPy.js +0 -581
@@ -0,0 +1,180 @@
1
+ import { jsxs as F, jsx as s } from "react/jsx-runtime";
2
+ import * as f from "react";
3
+ import { ChevronLeft as Z, ChevronRight as k } from "lucide-react";
4
+ import { cn as W } from "./cn.js";
5
+ import { usePruiI18n as ee } from "../i18n.js";
6
+ const K = 864e5, te = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], re = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
7
+ function j(a) {
8
+ const o = a.getFullYear(), i = String(a.getMonth() + 1).padStart(2, "0"), n = String(a.getDate()).padStart(2, "0");
9
+ return `${o}-${i}-${n}`;
10
+ }
11
+ function u(a) {
12
+ const [o, i, n] = a.split("-").map(Number);
13
+ return new Date(o, (i ?? 1) - 1, n ?? 1);
14
+ }
15
+ function ne(a, o) {
16
+ const [i, n] = a.split("-").map(Number), g = new Date(i, (n ?? 1) - 1, 1), h = (g.getDay() - o + 7) % 7;
17
+ return new Date(g.getTime() - h * K);
18
+ }
19
+ function v(a) {
20
+ return `${a.getFullYear()}-${String(a.getMonth() + 1).padStart(2, "0")}`;
21
+ }
22
+ function ae(a, o, i) {
23
+ let n = a;
24
+ return o && n < u(o) && (n = u(o)), i && n > u(i) && (n = u(i)), n;
25
+ }
26
+ const oe = f.forwardRef(function({ value: o, defaultValue: i, onSelect: n, month: g, onMonthChange: h, min: x, max: Y, disabled: N, showToday: _ = !0, weekStartsOn: b = 0, className: L, onKeyDown: M, ...q }, G) {
27
+ const { t: H } = ee(), [V, z] = f.useState(i ?? ""), [w, R] = f.useState(null), $ = o !== void 0, D = $ ? o : V, S = j(/* @__PURE__ */ new Date()), T = f.useRef(null);
28
+ T.current === null && (T.current = g ?? v(D ? u(D) : /* @__PURE__ */ new Date()));
29
+ const [B, J] = f.useState(T.current), l = g ?? B, C = (e) => {
30
+ J(e), h == null || h(e);
31
+ }, A = (e) => {
32
+ $ || z(e), n == null || n(e);
33
+ }, O = f.useMemo(() => ne(l, b), [l, b]), Q = b === 1 ? re : te, P = new Intl.DateTimeFormat(void 0, { month: "long", year: "numeric" }).format(
34
+ new Date(Number(l.slice(0, 4)), Number(l.slice(5, 7)) - 1, 1)
35
+ ), y = (e) => {
36
+ const t = new Date(Number(l.slice(0, 4)), Number(l.slice(5, 7)) - 1 + e, 1);
37
+ C(v(t));
38
+ }, I = (e) => x && e < x || Y && e > Y ? !0 : (N == null ? void 0 : N(e)) ?? !1, p = (e, t) => {
39
+ const r = ae(new Date(u(e).getTime() + t * K), x, Y), c = j(r);
40
+ C(v(r)), R(c);
41
+ };
42
+ f.useEffect(() => {
43
+ if (!w) return;
44
+ const e = document.querySelector(`[data-prui-calendar-day="${w}"]`);
45
+ e && (e.focus(), R(null));
46
+ }, [w, l]);
47
+ const X = (e) => {
48
+ var c, d;
49
+ if (M == null || M(e), e.defaultPrevented) return;
50
+ const t = (d = (c = document.activeElement) == null ? void 0 : c.dataset) == null ? void 0 : d.pruiCalendarDay;
51
+ if (!t) return;
52
+ const r = u(t);
53
+ switch (e.key) {
54
+ case "ArrowLeft":
55
+ e.preventDefault(), p(t, -1);
56
+ break;
57
+ case "ArrowRight":
58
+ e.preventDefault(), p(t, 1);
59
+ break;
60
+ case "ArrowUp":
61
+ e.preventDefault(), p(t, -7);
62
+ break;
63
+ case "ArrowDown":
64
+ e.preventDefault(), p(t, 7);
65
+ break;
66
+ case "Home": {
67
+ e.preventDefault();
68
+ const m = (r.getDay() - b + 7) % 7;
69
+ p(t, -m);
70
+ break;
71
+ }
72
+ case "End": {
73
+ e.preventDefault();
74
+ const m = (b + 6 - r.getDay() + 7) % 7;
75
+ p(t, m);
76
+ break;
77
+ }
78
+ case "PageUp":
79
+ e.preventDefault(), y(-1);
80
+ break;
81
+ case "PageDown":
82
+ e.preventDefault(), y(1);
83
+ break;
84
+ case "Enter":
85
+ case " ":
86
+ e.preventDefault(), I(t) || A(t);
87
+ break;
88
+ }
89
+ }, E = [];
90
+ for (let e = 0; e < 42; e++) {
91
+ const t = j(new Date(O.getTime() + e * K));
92
+ E.push(v(u(t)) === l ? t : null);
93
+ }
94
+ return /* @__PURE__ */ F("div", { ref: G, className: W("prui-calendar inline-flex flex-col gap-2 rounded-[var(--prui-radius)] border border-[var(--prui-line)] bg-[var(--prui-surface)] p-3", L), onKeyDown: X, ...q, children: [
95
+ /* @__PURE__ */ F("div", { className: "flex items-center justify-between gap-2", children: [
96
+ /* @__PURE__ */ s(
97
+ "button",
98
+ {
99
+ type: "button",
100
+ "aria-label": "Previous month",
101
+ onClick: () => y(-1),
102
+ className: "inline-flex h-7 w-7 cursor-pointer items-center justify-center rounded-[var(--prui-radius-1)] text-[var(--prui-dim)] transition-colors hover:bg-[var(--prui-raise)] hover:text-[var(--prui-fg)]",
103
+ children: /* @__PURE__ */ s(Z, { className: "h-4 w-4", "aria-hidden": !0 })
104
+ }
105
+ ),
106
+ /* @__PURE__ */ s("span", { "aria-live": "polite", className: "text-sm font-medium text-[var(--prui-fg)]", children: P }),
107
+ /* @__PURE__ */ s(
108
+ "button",
109
+ {
110
+ type: "button",
111
+ "aria-label": "Next month",
112
+ onClick: () => y(1),
113
+ className: "inline-flex h-7 w-7 cursor-pointer items-center justify-center rounded-[var(--prui-radius-1)] text-[var(--prui-dim)] transition-colors hover:bg-[var(--prui-raise)] hover:text-[var(--prui-fg)]",
114
+ children: /* @__PURE__ */ s(k, { className: "h-4 w-4", "aria-hidden": !0 })
115
+ }
116
+ )
117
+ ] }),
118
+ /* @__PURE__ */ F("div", { role: "grid", "aria-label": P, className: "flex flex-col gap-1", children: [
119
+ /* @__PURE__ */ s("div", { role: "row", className: "grid grid-cols-7 text-center text-xs font-medium text-[var(--prui-dim)]", children: Q.map((e) => /* @__PURE__ */ s("span", { role: "columnheader", className: "px-1 py-0.5", children: e }, e)) }),
120
+ Array.from({ length: 6 }).map((e, t) => /* @__PURE__ */ s("div", { role: "row", className: "grid grid-cols-7 gap-0.5", children: E.slice(t * 7, t * 7 + 7).map((r, c) => {
121
+ if (r === null) return /* @__PURE__ */ s("span", { role: "gridcell" }, c);
122
+ const d = r === D, m = r === S, U = I(r);
123
+ return /* @__PURE__ */ s(
124
+ "button",
125
+ {
126
+ type: "button",
127
+ role: "gridcell",
128
+ "aria-selected": d,
129
+ "aria-disabled": U || void 0,
130
+ "aria-current": m ? "date" : void 0,
131
+ "data-prui-calendar-day": r,
132
+ tabIndex: d || !D && r === S || !D && t === 0 && c === 0 && E[0] === r ? 0 : -1,
133
+ onClick: () => A(r),
134
+ className: W(
135
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-[var(--prui-radius-1)] text-sm outline-none",
136
+ "focus-visible:ring-2 focus-visible:ring-[var(--prui-brand)]",
137
+ d ? "bg-[var(--prui-brand)] text-[var(--prui-brand-fg,#fff)] font-medium" : "text-[var(--prui-fg)] hover:bg-[var(--prui-raise)]",
138
+ m && !d && "border border-[var(--prui-brand)]/50",
139
+ U && "opacity-40 pointer-events-none"
140
+ ),
141
+ children: Number(r.slice(8, 10))
142
+ },
143
+ r
144
+ );
145
+ }) }, t))
146
+ ] }),
147
+ _ ? /* @__PURE__ */ s(
148
+ "button",
149
+ {
150
+ type: "button",
151
+ onClick: () => {
152
+ C(v(/* @__PURE__ */ new Date())), A(S);
153
+ },
154
+ className: "cursor-pointer self-center rounded-[var(--prui-radius-1)] px-2 py-1 text-xs text-[var(--prui-brand)] transition-colors hover:bg-[var(--prui-brand)]/10",
155
+ children: H.today
156
+ }
157
+ ) : null
158
+ ] });
159
+ });
160
+ oe.displayName = "Calendar";
161
+ const ce = {
162
+ name: "Calendar",
163
+ props: [
164
+ { name: "value", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
165
+ { name: "defaultValue", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
166
+ { name: "onSelect", type: "(date: string) => void", default: null, control: "none" },
167
+ { name: "month", type: "string 'YYYY-MM'", default: "selection or today", control: "text" },
168
+ { name: "onMonthChange", type: "(month: string) => void", default: null, control: "none" },
169
+ { name: "min", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
170
+ { name: "max", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
171
+ { name: "weekStartsOn", type: "0 | 1", default: "0", control: "select", options: ["0", "1"] },
172
+ { name: "showToday", type: "boolean", default: "true", control: "boolean" }
173
+ ]
174
+ };
175
+ export {
176
+ oe as Calendar,
177
+ ce as calendarPropsMeta,
178
+ u as fromDateKey,
179
+ j as toDateKey
180
+ };
@@ -1,7 +1,11 @@
1
1
  import { SurfaceProps } from './surface';
2
2
  import { PropsMeta } from './props-meta';
3
3
  import * as React from "react";
4
- export type BadgeVariant = "default" | "brand" | "ok" | "warn" | "danger" | "outline";
4
+ /**
5
+ * Badge variants. Standard vocabulary: neutral / brand / success / warning /
6
+ * danger / outline; the original ok/warn/default names are aliases.
7
+ */
8
+ export type BadgeVariant = "default" | "neutral" | "brand" | "info" | "ok" | "success" | "warn" | "warning" | "danger" | "outline";
5
9
  export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, SurfaceProps {
6
10
  variant?: BadgeVariant;
7
11
  }
package/dist/core/card.js CHANGED
@@ -1,18 +1,22 @@
1
1
  import { jsx as t } from "react/jsx-runtime";
2
2
  import * as n from "react";
3
3
  import { resolveSurface as g, withSurface as x } from "./surface.js";
4
- import { cn as d } from "./cn.js";
4
+ import { cn as s } from "./cn.js";
5
5
  const w = {
6
6
  default: "bg-[var(--prui-raise)] text-[var(--prui-fg)] border-transparent",
7
+ neutral: "bg-[var(--prui-raise)] text-[var(--prui-fg)] border-transparent",
7
8
  brand: "bg-[var(--prui-brand)]/15 text-[var(--prui-brand)] border-transparent",
9
+ info: "bg-[var(--prui-brand)]/15 text-[var(--prui-brand)] border-transparent",
8
10
  ok: "bg-[var(--prui-ok)]/15 text-[var(--prui-ok)] border-transparent",
11
+ success: "bg-[var(--prui-ok)]/15 text-[var(--prui-ok)] border-transparent",
9
12
  warn: "bg-[var(--prui-warn)]/15 text-[var(--prui-warn)] border-transparent",
13
+ warning: "bg-[var(--prui-warn)]/15 text-[var(--prui-warn)] border-transparent",
10
14
  danger: "bg-[var(--prui-danger)]/15 text-[var(--prui-danger)] border-transparent",
11
15
  outline: "bg-transparent text-[var(--prui-fg)] border-[var(--prui-line)]"
12
16
  }, y = n.forwardRef(
13
- ({ className: a, style: e, variant: r = "default", bg: o, fg: i, radius: l, texture: p, textureColor: u, elevation: c, ...m }, f) => {
14
- const v = g({ bg: o, fg: i, radius: l, texture: p, textureColor: u, elevation: c }), s = x(
15
- d(
17
+ ({ className: a, style: e, variant: r = "default", bg: i, fg: o, radius: p, texture: l, textureColor: u, elevation: c, ...f }, m) => {
18
+ const v = g({ bg: i, fg: o, radius: p, texture: l, textureColor: u, elevation: c }), d = x(
19
+ s(
16
20
  "prui-badge inline-flex items-center gap-1 rounded-[var(--prui-s-radius,var(--prui-radius-full))] border px-2 py-0.5",
17
21
  "text-xs font-medium whitespace-nowrap",
18
22
  w[r],
@@ -24,11 +28,11 @@ const w = {
24
28
  return /* @__PURE__ */ t(
25
29
  "span",
26
30
  {
27
- ref: f,
31
+ ref: m,
28
32
  "data-variant": r,
29
- style: s.style,
30
- className: s.className,
31
- ...m
33
+ style: d.style,
34
+ className: d.className,
35
+ ...f
32
36
  }
33
37
  );
34
38
  }
@@ -37,7 +41,7 @@ y.displayName = "Badge";
37
41
  const z = {
38
42
  name: "Badge",
39
43
  props: [
40
- { name: "variant", type: "'default' | 'brand' | 'ok' | 'warn' | 'danger' | 'outline'", default: "'default'", control: "select", options: ["default", "brand", "ok", "warn", "danger", "outline"] },
44
+ { name: "variant", type: "'neutral' | 'brand' | 'success' | 'warning' | 'danger' | 'outline' | 'info' | 'ok' | 'warn' | 'default'", default: "'default' (neutral)", control: "select", options: ["neutral", "brand", "success", "warning", "danger", "outline", "info", "ok", "warn", "default"] },
41
45
  { name: "children", type: "ReactNode", default: null, control: "text" }
42
46
  ]
43
47
  }, N = {
@@ -46,38 +50,38 @@ const z = {
46
50
  ghost: "border border-transparent bg-transparent",
47
51
  elevated: "border border-[var(--prui-line)] prui-elev-md"
48
52
  }, C = n.forwardRef(
49
- ({ className: a, style: e, variant: r = "default", unstyled: o, bg: i, fg: l, radius: p, texture: u, textureColor: c, elevation: m, ...f }, v) => {
50
- const s = g({ bg: i, fg: l, radius: p, texture: u, textureColor: c, elevation: m }), b = x(
51
- d(
53
+ ({ className: a, style: e, variant: r = "default", unstyled: i, bg: o, fg: p, radius: l, texture: u, textureColor: c, elevation: f, ...m }, v) => {
54
+ const d = g({ bg: o, fg: p, radius: l, texture: u, textureColor: c, elevation: f }), b = x(
55
+ s(
52
56
  "prui-card rounded-[var(--prui-s-radius,var(--prui-radius))]",
53
- o ? [] : [N[r]],
57
+ i ? [] : [N[r]],
54
58
  a
55
59
  ),
56
60
  e,
57
- s
61
+ d
58
62
  );
59
- return /* @__PURE__ */ t("div", { ref: v, className: b.className, style: b.style, ...f });
63
+ return /* @__PURE__ */ t("div", { ref: v, className: b.className, style: b.style, ...m });
60
64
  }
61
65
  );
62
66
  C.displayName = "Card";
63
67
  const h = n.forwardRef(
64
- ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: d("prui-card-header flex flex-col gap-1 p-4", a), ...e })
68
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: s("prui-card-header flex flex-col gap-1 p-4", a), ...e })
65
69
  );
66
70
  h.displayName = "CardHeader";
67
71
  const R = n.forwardRef(
68
- ({ className: a, ...e }, r) => /* @__PURE__ */ t("h3", { ref: r, className: d("prui-card-title text-base font-semibold text-[var(--prui-fg)]", a), ...e })
72
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("h3", { ref: r, className: s("prui-card-title text-base font-semibold text-[var(--prui-fg)]", a), ...e })
69
73
  );
70
74
  R.displayName = "CardTitle";
71
75
  const k = n.forwardRef(
72
- ({ className: a, ...e }, r) => /* @__PURE__ */ t("p", { ref: r, className: d("prui-card-description text-sm text-[var(--prui-dim)]", a), ...e })
76
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("p", { ref: r, className: s("prui-card-description text-sm text-[var(--prui-dim)]", a), ...e })
73
77
  );
74
78
  k.displayName = "CardDescription";
75
79
  const j = n.forwardRef(
76
- ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: d("prui-card-content p-4 pt-0", a), ...e })
80
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: s("prui-card-content p-4 pt-0", a), ...e })
77
81
  );
78
82
  j.displayName = "CardContent";
79
83
  const S = n.forwardRef(
80
- ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: d("prui-card-footer flex items-center p-4 pt-0", a), ...e })
84
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: s("prui-card-footer flex items-center p-4 pt-0", a), ...e })
81
85
  );
82
86
  S.displayName = "CardFooter";
83
87
  const D = {
@@ -91,23 +95,23 @@ const D = {
91
95
  md: "h-8 w-8 text-xs",
92
96
  lg: "h-12 w-12 text-base"
93
97
  }, B = n.forwardRef(
94
- ({ className: a, src: e, alt: r, fallback: o, size: i = "md", ...l }, p) => {
95
- const [u, c] = n.useState(!1), m = e && !u, f = o ?? (r ? r.split(/\s+/).slice(0, 2).map((v) => {
96
- var s;
97
- return ((s = v[0]) == null ? void 0 : s.toUpperCase()) ?? "";
98
+ ({ className: a, src: e, alt: r, fallback: i, size: o = "md", ...p }, l) => {
99
+ const [u, c] = n.useState(!1), f = e && !u, m = i ?? (r ? r.split(/\s+/).slice(0, 2).map((v) => {
100
+ var d;
101
+ return ((d = v[0]) == null ? void 0 : d.toUpperCase()) ?? "";
98
102
  }).join("") : "");
99
103
  return /* @__PURE__ */ t(
100
104
  "span",
101
105
  {
102
- ref: p,
103
- className: d(
106
+ ref: l,
107
+ className: s(
104
108
  "prui-avatar relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden",
105
109
  "rounded-[var(--prui-radius-full)] bg-[var(--prui-raise)] text-[var(--prui-dim)] font-medium",
106
- A[i],
110
+ A[o],
107
111
  a
108
112
  ),
109
- ...l,
110
- children: m ? /* @__PURE__ */ t("img", { src: e, alt: r ?? "", className: "h-full w-full object-cover", onError: () => c(!0) }) : f
113
+ ...p,
114
+ children: f ? /* @__PURE__ */ t("img", { src: e, alt: r ?? "", className: "h-full w-full object-cover", onError: () => c(!0) }) : m
111
115
  }
112
116
  );
113
117
  }
@@ -0,0 +1,19 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ /**
4
+ * Checkbox: a button-based checkbox with an accessible checked state,
5
+ * native Space/Enter toggling, an indeterminate visual state, and an
6
+ * optional label rendered as a real <label> pair.
7
+ */
8
+ export interface CheckboxProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value"> {
9
+ checked?: boolean;
10
+ defaultChecked?: boolean;
11
+ /** Neither checked nor unchecked (e.g. "some rows selected"). */
12
+ indeterminate?: boolean;
13
+ disabled?: boolean;
14
+ onChange?: (checked: boolean, e: React.MouseEvent<HTMLButtonElement>) => void;
15
+ /** Label rendered beside the box; click toggles. */
16
+ label?: React.ReactNode;
17
+ }
18
+ export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLButtonElement>>;
19
+ export declare const checkboxPropsMeta: PropsMeta;
@@ -0,0 +1,55 @@
1
+ import { jsx as n, jsxs as y } from "react/jsx-runtime";
2
+ import * as f from "react";
3
+ import { Minus as g, Check as N } from "lucide-react";
4
+ import { cn as p } from "./cn.js";
5
+ const C = f.forwardRef(function({ className: b, checked: c, defaultChecked: m = !1, indeterminate: r = !1, disabled: o, onChange: a, label: l, ...h }, x) {
6
+ const [k, v] = f.useState(m), i = c !== void 0, e = i ? c : k, s = (t) => {
7
+ if (o) return;
8
+ const d = r ? !0 : !e;
9
+ i || v(d), a == null || a(d, t);
10
+ }, u = /* @__PURE__ */ n(
11
+ "button",
12
+ {
13
+ ref: x,
14
+ type: "button",
15
+ role: "checkbox",
16
+ "aria-checked": r ? "mixed" : e,
17
+ "aria-disabled": o,
18
+ "data-state": e ? "checked" : "unchecked",
19
+ disabled: o,
20
+ onClick: s,
21
+ className: p(
22
+ "prui-checkbox inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-[var(--prui-radius-1)] border",
23
+ "transition-colors duration-[var(--prui-duration-fast)] cursor-pointer outline-none",
24
+ "focus-visible:ring-2 focus-visible:ring-[var(--prui-brand)] focus-visible:ring-offset-1",
25
+ e || r ? "border-transparent bg-[var(--prui-brand)] text-[var(--prui-brand-fg,#fff)]" : "border-[var(--prui-line)] bg-[var(--prui-background)]",
26
+ o && "opacity-50 cursor-not-allowed",
27
+ b
28
+ ),
29
+ ...h,
30
+ children: r && !e ? /* @__PURE__ */ n(g, { className: "h-3 w-3", "aria-hidden": !0 }) : e ? /* @__PURE__ */ n(N, { className: "h-3 w-3", "aria-hidden": !0 }) : null
31
+ }
32
+ );
33
+ return l === void 0 ? u : /* @__PURE__ */ y("span", { className: "inline-flex items-center gap-2", children: [
34
+ u,
35
+ /* @__PURE__ */ n("span", { className: p("text-sm select-none", o ? "text-[var(--prui-dim)]" : "text-[var(--prui-fg)]", "cursor-pointer"), onClick: (t) => {
36
+ t.preventDefault(), s(t);
37
+ }, children: l })
38
+ ] });
39
+ });
40
+ C.displayName = "Checkbox";
41
+ const D = {
42
+ name: "Checkbox",
43
+ props: [
44
+ { name: "checked", type: "boolean", default: "undefined", control: "boolean" },
45
+ { name: "defaultChecked", type: "boolean", default: "false", control: "boolean" },
46
+ { name: "indeterminate", type: "boolean", default: "false", control: "boolean" },
47
+ { name: "disabled", type: "boolean", default: "false", control: "boolean" },
48
+ { name: "onChange", type: "(checked, event) => void", default: null, control: "none" },
49
+ { name: "label", type: "ReactNode", default: null, control: "text" }
50
+ ]
51
+ };
52
+ export {
53
+ C as Checkbox,
54
+ D as checkboxPropsMeta
55
+ };
@@ -0,0 +1,32 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ /**
4
+ * Combobox: a text input with a filtered listbox (the editable Select).
5
+ * Full ARIA 1.2 combobox pattern: aria-expanded/controls/activedescendant,
6
+ * ArrowDown/Up move, Home/End jump, Enter picks, Escape (topmost only)
7
+ * closes and refocuses, typing filters. Controlled and uncontrolled value.
8
+ */
9
+ export interface ComboboxOption {
10
+ label: string;
11
+ value: string;
12
+ disabled?: boolean;
13
+ }
14
+ export interface ComboboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "defaultValue"> {
15
+ options: ComboboxOption[];
16
+ value?: string;
17
+ defaultValue?: string;
18
+ onChange?: (value: string) => void;
19
+ onOpenChange?: (open: boolean) => void;
20
+ placeholder?: string;
21
+ /** Input placeholder when no value is set. */
22
+ emptyText?: React.ReactNode;
23
+ /** Message when no option matches the query. */
24
+ noMatchText?: React.ReactNode;
25
+ /** Start with the listbox open. */
26
+ defaultOpen?: boolean;
27
+ /** Match function; default is label contains query (case-insensitive). */
28
+ filter?: (option: ComboboxOption, query: string) => boolean;
29
+ disabled?: boolean;
30
+ }
31
+ export declare const Combobox: React.ForwardRefExoticComponent<ComboboxProps & React.RefAttributes<HTMLInputElement>>;
32
+ export declare const comboboxPropsMeta: PropsMeta;
@@ -0,0 +1,193 @@
1
+ import { jsxs as $, Fragment as Z, jsx as c } from "react/jsx-runtime";
2
+ import * as a from "react";
3
+ import { ChevronDown as _ } from "lucide-react";
4
+ import { cn as x } from "./cn.js";
5
+ import { useOverlayStack as K, useEscapeKey as ee, Portal as te } from "./overlay.js";
6
+ import { useAnchoredPosition as re } from "./anchor.js";
7
+ import { endIndex as ae, homeIndex as ne, moveIndex as j } from "./list-nav.js";
8
+ const oe = a.forwardRef(function({
9
+ options: d,
10
+ value: h,
11
+ defaultValue: P,
12
+ onChange: g,
13
+ onOpenChange: y,
14
+ placeholder: U = "Type to search...",
15
+ emptyText: I,
16
+ noMatchText: z = "No matches.",
17
+ defaultOpen: F = !1,
18
+ filter: w,
19
+ disabled: D,
20
+ id: W,
21
+ className: A,
22
+ onKeyDown: k,
23
+ ...S
24
+ }, v) {
25
+ var q, C;
26
+ const [H, O] = a.useState(P ?? ""), [n, Q] = a.useState(F), [m, R] = a.useState(null), [l, s] = a.useState(0), p = a.useRef(null), E = a.useRef(null), N = a.useRef(null), b = a.useId(), L = h !== void 0 ? h : H, V = (q = d.find((e) => e.value === L)) == null ? void 0 : q.label, u = (e) => {
27
+ var t, o;
28
+ if (Q(e), y == null || y(e), !e) {
29
+ R(null);
30
+ const i = document.activeElement;
31
+ i && ((t = E.current) != null && t.contains(i)) && ((o = p.current) == null || o.focus());
32
+ }
33
+ }, { setElement: B, isTop: G } = K(n);
34
+ ee(n, G, () => {
35
+ var e;
36
+ u(!1), (e = p.current) == null || e.focus();
37
+ }), a.useEffect(() => {
38
+ if (!n) return;
39
+ const e = (t) => {
40
+ var i, T;
41
+ const o = t.target;
42
+ (i = N.current) != null && i.contains(o) || (T = E.current) != null && T.contains(o) || u(!1);
43
+ };
44
+ return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
45
+ });
46
+ const r = a.useMemo(() => {
47
+ if (m === null) return d;
48
+ const e = m.toLowerCase();
49
+ return e ? d.filter((t) => w ? w(t, e) : t.label.toLowerCase().includes(e)) : d;
50
+ }, [d, m, w]);
51
+ a.useEffect(() => {
52
+ s((e) => e < r.length ? e : Math.max(0, r.length - 1));
53
+ }, [r.length]);
54
+ const M = (e) => {
55
+ var t;
56
+ e.disabled || (h === void 0 && O(e.value), g == null || g(e.value), R(null), u(!1), (t = p.current) == null || t.focus());
57
+ }, J = N, { ref: X, position: f } = re({ active: n, anchorRef: J, side: "bottom", align: "start" }), Y = (e) => {
58
+ if (k == null || k(e), e.defaultPrevented) return;
59
+ if (!n && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
60
+ e.preventDefault(), u(!0);
61
+ return;
62
+ }
63
+ if (!n) return;
64
+ const t = (o) => {
65
+ var i;
66
+ return !((i = r[o]) != null && i.disabled);
67
+ };
68
+ switch (e.key) {
69
+ case "ArrowDown":
70
+ e.preventDefault(), s(j(l, 1, r.length, { enabled: t }));
71
+ break;
72
+ case "ArrowUp":
73
+ e.preventDefault(), s(j(l, -1, r.length, { enabled: t }));
74
+ break;
75
+ case "Home":
76
+ r.length && (e.preventDefault(), s(ne(r.length, t)));
77
+ break;
78
+ case "End":
79
+ r.length && (e.preventDefault(), s(ae(r.length, t)));
80
+ break;
81
+ case "Enter":
82
+ e.preventDefault(), r[l] && M(r[l]);
83
+ break;
84
+ case "Tab":
85
+ u(!1);
86
+ break;
87
+ }
88
+ };
89
+ return /* @__PURE__ */ $(Z, { children: [
90
+ /* @__PURE__ */ $("div", { ref: N, className: x("prui-combobox relative inline-flex w-full items-center", A), children: [
91
+ /* @__PURE__ */ c(
92
+ "input",
93
+ {
94
+ ref: (e) => {
95
+ p.current = e, typeof v == "function" ? v(e) : v && (v.current = e);
96
+ },
97
+ id: W,
98
+ type: "text",
99
+ role: "combobox",
100
+ "aria-expanded": n,
101
+ "aria-haspopup": "listbox",
102
+ "aria-controls": n ? b : void 0,
103
+ "aria-activedescendant": n && r[l] ? `${b}-option-${l}` : void 0,
104
+ "aria-autocomplete": "list",
105
+ autoComplete: "off",
106
+ disabled: D,
107
+ placeholder: U,
108
+ className: x(
109
+ "prui-combobox-trigger h-9 w-full pr-8",
110
+ "bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
111
+ "outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
112
+ "disabled:opacity-50 disabled:cursor-not-allowed cursor-text",
113
+ A
114
+ ),
115
+ value: m !== null ? m : V ?? "",
116
+ onChange: (e) => {
117
+ R(e.target.value), u(!0), s(0);
118
+ },
119
+ onFocus: () => {
120
+ !n && !D && u(!0);
121
+ },
122
+ onKeyDown: Y,
123
+ ...S
124
+ }
125
+ ),
126
+ /* @__PURE__ */ c(_, { className: "pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--prui-dim)]", "aria-hidden": !0 })
127
+ ] }),
128
+ n ? /* @__PURE__ */ c(te, { children: /* @__PURE__ */ c(
129
+ "div",
130
+ {
131
+ ref: (e) => {
132
+ E.current = e, X(e), B(e);
133
+ },
134
+ id: b,
135
+ role: "listbox",
136
+ "aria-label": S["aria-label"] ?? "Options",
137
+ tabIndex: -1,
138
+ "data-state": "open",
139
+ className: x(
140
+ "prui-combobox-content fixed z-[var(--prui-z-overlay)] min-w-40 max-h-60 overflow-auto p-1",
141
+ "border border-[var(--prui-line)] rounded-[var(--prui-radius)] bg-[var(--prui-surface)] shadow-[var(--prui-shadow-md)]"
142
+ ),
143
+ style: {
144
+ top: (f == null ? void 0 : f.top) ?? -9999,
145
+ left: (f == null ? void 0 : f.left) ?? -9999,
146
+ minWidth: ((C = p.current) == null ? void 0 : C.offsetWidth) ?? 200
147
+ },
148
+ children: d.length === 0 && I ? /* @__PURE__ */ c("div", { className: "px-3 py-2 text-sm text-[var(--prui-dim)]", children: I }) : r.length === 0 ? /* @__PURE__ */ c("div", { className: "px-3 py-2 text-sm text-[var(--prui-dim)]", role: "option", "aria-selected": "false", "aria-disabled": "true", children: z }) : r.map((e, t) => {
149
+ const o = L === e.value;
150
+ return /* @__PURE__ */ c(
151
+ "div",
152
+ {
153
+ id: `${b}-option-${t}`,
154
+ role: "option",
155
+ "aria-selected": o,
156
+ "aria-disabled": e.disabled,
157
+ "data-active": t === l || void 0,
158
+ "data-selected": o || void 0,
159
+ tabIndex: -1,
160
+ onMouseEnter: () => s(t),
161
+ onClick: () => M(e),
162
+ className: x(
163
+ "flex cursor-pointer items-center rounded-[calc(var(--prui-radius)-1px)] px-3 py-1.5 text-sm text-[var(--prui-fg)]",
164
+ t === l && "bg-[var(--prui-raise)]",
165
+ o && "font-medium",
166
+ e.disabled && "opacity-50 pointer-events-none"
167
+ ),
168
+ children: e.label
169
+ },
170
+ e.value
171
+ );
172
+ })
173
+ }
174
+ ) }) : null
175
+ ] });
176
+ });
177
+ oe.displayName = "Combobox";
178
+ const me = {
179
+ name: "Combobox",
180
+ props: [
181
+ { name: "options", type: "ComboboxOption[]", default: null, control: "object" },
182
+ { name: "value", type: "string", default: "undefined", control: "text" },
183
+ { name: "defaultValue", type: "string", default: "undefined", control: "text" },
184
+ { name: "onChange", type: "(value: string) => void", default: null, control: "none" },
185
+ { name: "placeholder", type: "string", default: "'Type to search...'", control: "text" },
186
+ { name: "noMatchText", type: "ReactNode", default: "'No matches.'", control: "text" },
187
+ { name: "filter", type: "(option, query) => boolean", default: "label contains query", control: "none" }
188
+ ]
189
+ };
190
+ export {
191
+ oe as Combobox,
192
+ me as comboboxPropsMeta
193
+ };