@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
@@ -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,183 @@
1
+ import { jsxs as G, Fragment as J, jsx as i } from "react/jsx-runtime";
2
+ import * as o from "react";
3
+ import { ChevronDown as X } from "lucide-react";
4
+ import { cn as N } from "./cn.js";
5
+ import { useOverlayStack as Y, useEscapeKey as Z, Portal as _ } from "./overlay.js";
6
+ import { useAnchoredPosition as K } from "./anchor.js";
7
+ import { endIndex as ee, homeIndex as te, moveIndex as q } from "./list-nav.js";
8
+ const re = o.forwardRef(function({
9
+ options: u,
10
+ value: x,
11
+ defaultValue: C,
12
+ onChange: h,
13
+ onOpenChange: y,
14
+ placeholder: T = "Type to search...",
15
+ emptyText: R,
16
+ noMatchText: $ = "No matches.",
17
+ defaultOpen: L = !1,
18
+ filter: g,
19
+ disabled: I,
20
+ id: U,
21
+ className: z,
22
+ onKeyDown: w,
23
+ ...D
24
+ }, b) {
25
+ var M, j;
26
+ const [F, P] = o.useState(C ?? ""), [a, W] = o.useState(L), [p, k] = o.useState(null), [n, s] = o.useState(0), c = o.useRef(null), E = o.useRef(null), v = o.useId(), A = x !== void 0 ? x : F, H = (M = u.find((e) => e.value === A)) == null ? void 0 : M.label, d = (e) => {
27
+ var t, l;
28
+ if (W(e), y == null || y(e), !e) {
29
+ k(null);
30
+ const m = document.activeElement;
31
+ m && ((t = E.current) != null && t.contains(m)) && ((l = c.current) == null || l.focus());
32
+ }
33
+ }, { setElement: O, isTop: Q } = Y(a);
34
+ Z(a, Q, () => {
35
+ var e;
36
+ d(!1), (e = c.current) == null || e.focus();
37
+ });
38
+ const r = o.useMemo(() => {
39
+ if (p === null) return u;
40
+ const e = p.toLowerCase();
41
+ return e ? u.filter((t) => g ? g(t, e) : t.label.toLowerCase().includes(e)) : u;
42
+ }, [u, p, g]);
43
+ o.useEffect(() => {
44
+ s((e) => e < r.length ? e : Math.max(0, r.length - 1));
45
+ }, [r.length]);
46
+ const S = (e) => {
47
+ var t;
48
+ e.disabled || (x === void 0 && P(e.value), h == null || h(e.value), k(null), d(!1), (t = c.current) == null || t.focus());
49
+ }, { ref: V, position: f } = K({ active: a, anchorRef: c, side: "bottom", align: "start" }), B = (e) => {
50
+ if (w == null || w(e), e.defaultPrevented) return;
51
+ if (!a && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
52
+ e.preventDefault(), d(!0);
53
+ return;
54
+ }
55
+ if (!a) return;
56
+ const t = (l) => {
57
+ var m;
58
+ return !((m = r[l]) != null && m.disabled);
59
+ };
60
+ switch (e.key) {
61
+ case "ArrowDown":
62
+ e.preventDefault(), s(q(n, 1, r.length, { enabled: t }));
63
+ break;
64
+ case "ArrowUp":
65
+ e.preventDefault(), s(q(n, -1, r.length, { enabled: t }));
66
+ break;
67
+ case "Home":
68
+ r.length && (e.preventDefault(), s(te(r.length, t)));
69
+ break;
70
+ case "End":
71
+ r.length && (e.preventDefault(), s(ee(r.length, t)));
72
+ break;
73
+ case "Enter":
74
+ e.preventDefault(), r[n] && S(r[n]);
75
+ break;
76
+ case "Tab":
77
+ d(!1);
78
+ break;
79
+ }
80
+ };
81
+ return /* @__PURE__ */ G(J, { children: [
82
+ /* @__PURE__ */ i(
83
+ "input",
84
+ {
85
+ ref: (e) => {
86
+ c.current = e, typeof b == "function" ? b(e) : b && (b.current = e);
87
+ },
88
+ id: U,
89
+ type: "text",
90
+ role: "combobox",
91
+ "aria-expanded": a,
92
+ "aria-haspopup": "listbox",
93
+ "aria-controls": a ? v : void 0,
94
+ "aria-activedescendant": a && r[n] ? `${v}-option-${n}` : void 0,
95
+ "aria-autocomplete": "list",
96
+ autoComplete: "off",
97
+ disabled: I,
98
+ placeholder: T,
99
+ className: N(
100
+ "prui-combobox-trigger flex h-9 w-full items-center justify-between gap-2 border border-[var(--prui-line)]",
101
+ "bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
102
+ "outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
103
+ "disabled:opacity-50 disabled:cursor-not-allowed cursor-text",
104
+ z
105
+ ),
106
+ value: p !== null ? p : H ?? "",
107
+ onChange: (e) => {
108
+ k(e.target.value), d(!0), s(0);
109
+ },
110
+ onFocus: () => {
111
+ !a && !I && d(!0);
112
+ },
113
+ onKeyDown: B,
114
+ ...D
115
+ }
116
+ ),
117
+ /* @__PURE__ */ i("span", { className: "pointer-events-none relative", children: /* @__PURE__ */ i(X, { className: "pointer-events-none absolute -left-7 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--prui-dim)]", "aria-hidden": !0 }) }),
118
+ a ? /* @__PURE__ */ i(_, { children: /* @__PURE__ */ i(
119
+ "div",
120
+ {
121
+ ref: (e) => {
122
+ E.current = e, V(e), O(e);
123
+ },
124
+ id: v,
125
+ role: "listbox",
126
+ "aria-label": D["aria-label"] ?? "Options",
127
+ tabIndex: -1,
128
+ "data-state": "open",
129
+ className: N(
130
+ "prui-combobox-content fixed z-[var(--prui-z-overlay)] min-w-40 max-h-60 overflow-auto p-1",
131
+ "border border-[var(--prui-line)] rounded-[var(--prui-radius)] bg-[var(--prui-surface)] shadow-[var(--prui-shadow-md)]"
132
+ ),
133
+ style: {
134
+ top: (f == null ? void 0 : f.top) ?? -9999,
135
+ left: (f == null ? void 0 : f.left) ?? -9999,
136
+ minWidth: ((j = c.current) == null ? void 0 : j.offsetWidth) ?? 200
137
+ },
138
+ children: u.length === 0 && R ? /* @__PURE__ */ i("div", { className: "px-3 py-2 text-sm text-[var(--prui-dim)]", children: R }) : r.length === 0 ? /* @__PURE__ */ i("div", { className: "px-3 py-2 text-sm text-[var(--prui-dim)]", role: "option", "aria-selected": "false", "aria-disabled": "true", children: $ }) : r.map((e, t) => {
139
+ const l = A === e.value;
140
+ return /* @__PURE__ */ i(
141
+ "div",
142
+ {
143
+ id: `${v}-option-${t}`,
144
+ role: "option",
145
+ "aria-selected": l,
146
+ "aria-disabled": e.disabled,
147
+ "data-active": t === n || void 0,
148
+ "data-selected": l || void 0,
149
+ tabIndex: -1,
150
+ onMouseEnter: () => s(t),
151
+ onClick: () => S(e),
152
+ className: N(
153
+ "flex cursor-pointer items-center rounded-[calc(var(--prui-radius)-1px)] px-3 py-1.5 text-sm text-[var(--prui-fg)]",
154
+ t === n && "bg-[var(--prui-raise)]",
155
+ l && "font-medium",
156
+ e.disabled && "opacity-50 pointer-events-none"
157
+ ),
158
+ children: e.label
159
+ },
160
+ e.value
161
+ );
162
+ })
163
+ }
164
+ ) }) : null
165
+ ] });
166
+ });
167
+ re.displayName = "Combobox";
168
+ const ce = {
169
+ name: "Combobox",
170
+ props: [
171
+ { name: "options", type: "ComboboxOption[]", default: null, control: "object" },
172
+ { name: "value", type: "string", default: "undefined", control: "text" },
173
+ { name: "defaultValue", type: "string", default: "undefined", control: "text" },
174
+ { name: "onChange", type: "(value: string) => void", default: null, control: "none" },
175
+ { name: "placeholder", type: "string", default: "'Type to search...'", control: "text" },
176
+ { name: "noMatchText", type: "ReactNode", default: "'No matches.'", control: "text" },
177
+ { name: "filter", type: "(option, query) => boolean", default: "label contains query", control: "none" }
178
+ ]
179
+ };
180
+ export {
181
+ re as Combobox,
182
+ ce as comboboxPropsMeta
183
+ };
@@ -0,0 +1,41 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ /**
4
+ * DatePicker / DateRangePicker: a text trigger opening a Calendar popover.
5
+ * Values stay plain "YYYY-MM-DD" strings (native input-compatible, no date
6
+ * library). The trigger is keyboard-operable (Enter/Space/ArrowDown opens,
7
+ * Escape topmost closes and refocuses); typing a date in the input is also
8
+ * accepted. The range picker anchors on the start date and shows a
9
+ * start–end chip row.
10
+ */
11
+ export interface DatePickerProps {
12
+ value?: string;
13
+ defaultValue?: string;
14
+ onChange?: (date: string) => void;
15
+ min?: string;
16
+ max?: string;
17
+ placeholder?: string;
18
+ disabled?: boolean;
19
+ className?: string;
20
+ /** Accessible label for the trigger input. */
21
+ ariaLabel?: string;
22
+ }
23
+ export declare const DatePicker: React.ForwardRefExoticComponent<DatePickerProps & React.RefAttributes<HTMLInputElement>>;
24
+ export interface DateRange {
25
+ from?: string;
26
+ to?: string;
27
+ }
28
+ export interface DateRangePickerProps {
29
+ value?: DateRange;
30
+ defaultValue?: DateRange;
31
+ onChange?: (range: DateRange) => void;
32
+ min?: string;
33
+ max?: string;
34
+ placeholder?: string;
35
+ disabled?: boolean;
36
+ className?: string;
37
+ ariaLabel?: string;
38
+ }
39
+ export declare const DateRangePicker: React.ForwardRefExoticComponent<DateRangePickerProps & React.RefAttributes<HTMLInputElement>>;
40
+ export declare const datePickerPropsMeta: PropsMeta;
41
+ export declare const dateRangePickerPropsMeta: PropsMeta;