@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.
- package/dist/app/resource.d.ts +44 -1
- package/dist/app.js +1 -1
- package/dist/chunks/auth-shell-DQJ4UmUv.js +1208 -0
- package/dist/chunks/data-table-toolbar-B-5J2Ozl.js +736 -0
- package/dist/core/accordion.d.ts +16 -0
- package/dist/core/accordion.js +108 -0
- package/dist/core/alert.d.ts +20 -0
- package/dist/core/alert.js +63 -0
- package/dist/core/anchor.d.ts +35 -0
- package/dist/core/anchor.js +39 -0
- package/dist/core/breadcrumb.d.ts +30 -0
- package/dist/core/breadcrumb.js +67 -0
- package/dist/core/button.d.ts +8 -1
- package/dist/core/button.js +23 -18
- package/dist/core/calendar.d.ts +29 -0
- package/dist/core/calendar.js +180 -0
- package/dist/core/card.d.ts +5 -1
- package/dist/core/card.js +33 -29
- package/dist/core/checkbox.d.ts +19 -0
- package/dist/core/checkbox.js +55 -0
- package/dist/core/combobox.d.ts +32 -0
- package/dist/core/combobox.js +183 -0
- package/dist/core/date-picker.d.ts +41 -0
- package/dist/core/date-picker.js +202 -0
- package/dist/core/dialog.d.ts +8 -0
- package/dist/core/dialog.js +59 -61
- package/dist/core/drawer.d.ts +34 -0
- package/dist/core/drawer.js +129 -0
- package/dist/core/dropdown.d.ts +8 -4
- package/dist/core/dropdown.js +136 -51
- package/dist/core/file-upload.d.ts +28 -0
- package/dist/core/file-upload.js +111 -0
- package/dist/core/index.d.ts +21 -0
- package/dist/core/list-nav.d.ts +27 -0
- package/dist/core/list-nav.js +51 -0
- package/dist/core/modal.d.ts +14 -5
- package/dist/core/modal.js +163 -156
- package/dist/core/overlay.d.ts +93 -0
- package/dist/core/overlay.js +189 -0
- package/dist/core/popover.d.ts +29 -0
- package/dist/core/popover.js +124 -0
- package/dist/core/progress.d.ts +21 -0
- package/dist/core/progress.js +59 -0
- package/dist/core/radio.d.ts +20 -0
- package/dist/core/radio.js +115 -0
- package/dist/core/select.d.ts +6 -0
- package/dist/core/select.js +178 -97
- package/dist/core/skeleton.d.ts +20 -0
- package/dist/core/skeleton.js +41 -0
- package/dist/core/spinner.d.ts +15 -0
- package/dist/core/spinner.js +41 -0
- package/dist/core/tabs.js +82 -53
- package/dist/core/timeline.d.ts +22 -0
- package/dist/core/timeline.js +57 -0
- package/dist/core/toast.d.ts +36 -0
- package/dist/core/toast.js +123 -0
- package/dist/core/tooltip.d.ts +23 -0
- package/dist/core/tooltip.js +96 -0
- package/dist/core/tree-view.d.ts +34 -0
- package/dist/core/tree-view.js +133 -0
- package/dist/core.js +152 -62
- package/dist/data-table/data-table.d.ts +22 -1
- package/dist/data-table.js +1 -1
- package/dist/forms/form.d.ts +8 -0
- package/dist/forms.js +213 -200
- package/dist/i18n/index.d.ts +83 -0
- package/dist/i18n.js +99 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +256 -156
- package/dist/prui-utilities.css +1 -1
- package/dist/prui.css +111 -4
- package/dist/theme/base.css +110 -3
- package/dist/theme/index.d.ts +27 -0
- package/dist/theme.js +86 -58
- package/package.json +9 -2
- package/dist/chunks/auth-shell-BG5vx9eG.js +0 -1054
- 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
|
+
};
|
package/dist/core/card.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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:
|
|
14
|
-
const v = g({ bg:
|
|
15
|
-
|
|
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:
|
|
31
|
+
ref: m,
|
|
28
32
|
"data-variant": r,
|
|
29
|
-
style:
|
|
30
|
-
className:
|
|
31
|
-
...
|
|
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: "'
|
|
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:
|
|
50
|
-
const
|
|
51
|
-
|
|
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
|
-
|
|
57
|
+
i ? [] : [N[r]],
|
|
54
58
|
a
|
|
55
59
|
),
|
|
56
60
|
e,
|
|
57
|
-
|
|
61
|
+
d
|
|
58
62
|
);
|
|
59
|
-
return /* @__PURE__ */ t("div", { ref: v, className: b.className, style: b.style, ...
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
95
|
-
const [u, c] = n.useState(!1),
|
|
96
|
-
var
|
|
97
|
-
return ((
|
|
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:
|
|
103
|
-
className:
|
|
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[
|
|
110
|
+
A[o],
|
|
107
111
|
a
|
|
108
112
|
),
|
|
109
|
-
...
|
|
110
|
-
children:
|
|
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;
|