@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.
- 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 +193 -0
- package/dist/core/date-picker.d.ts +62 -0
- package/dist/core/date-picker.js +314 -0
- package/dist/core/dialog.d.ts +15 -0
- package/dist/core/dialog.js +77 -60
- 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 +23 -1
- 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 +187 -98
- 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/time-picker.d.ts +68 -0
- package/dist/core/time-picker.js +305 -0
- 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 +160 -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 +89 -0
- package/dist/i18n.js +105 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +263 -155
- 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,129 @@
|
|
|
1
|
+
import { jsx as t, jsxs as Y } from "react/jsx-runtime";
|
|
2
|
+
import * as a from "react";
|
|
3
|
+
import { X as k } from "lucide-react";
|
|
4
|
+
import { cn as P } from "./cn.js";
|
|
5
|
+
import { useReducedMotion as j, useOverlay as A, Portal as E } from "./overlay.js";
|
|
6
|
+
import { usePruiI18n as F } from "../i18n.js";
|
|
7
|
+
const L = {
|
|
8
|
+
left: "left-0 top-0 h-full prui-drawer-panel",
|
|
9
|
+
right: "right-0 top-0 h-full prui-drawer-panel",
|
|
10
|
+
top: "left-0 top-0 w-full prui-drawer-panel",
|
|
11
|
+
bottom: "left-0 bottom-0 w-full prui-drawer-panel"
|
|
12
|
+
}, $ = {
|
|
13
|
+
left: "translateX(0)",
|
|
14
|
+
right: "translateX(0)",
|
|
15
|
+
top: "translateY(0)",
|
|
16
|
+
bottom: "translateY(0)"
|
|
17
|
+
}, q = {
|
|
18
|
+
left: "translateX(-100%)",
|
|
19
|
+
right: "translateX(100%)",
|
|
20
|
+
top: "translateY(-100%)",
|
|
21
|
+
bottom: "translateY(100%)"
|
|
22
|
+
}, h = a.forwardRef(function({ open: n, defaultOpen: i = !1, onOpenChange: s, side: r = "right", size: o, children: v, ariaLabel: w, hideClose: y, className: g, style: x }, S) {
|
|
23
|
+
const [N, D] = a.useState(i), m = n !== void 0, l = m ? n : N, [M, u] = a.useState(l), [p, d] = a.useState(!1), f = j(), { t: R } = F(), c = (e) => {
|
|
24
|
+
m || D(e), s == null || s(e);
|
|
25
|
+
};
|
|
26
|
+
a.useEffect(() => {
|
|
27
|
+
if (l) {
|
|
28
|
+
if (u(!0), f) {
|
|
29
|
+
d(!0);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const C = requestAnimationFrame(() => d(!0));
|
|
33
|
+
return () => cancelAnimationFrame(C);
|
|
34
|
+
}
|
|
35
|
+
if (d(!1), f) {
|
|
36
|
+
u(!1);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const e = setTimeout(() => u(!1), 300);
|
|
40
|
+
return () => clearTimeout(e);
|
|
41
|
+
}, [l, f]);
|
|
42
|
+
const { ref: T } = A({
|
|
43
|
+
open: l,
|
|
44
|
+
onEscape: () => c(!1)
|
|
45
|
+
});
|
|
46
|
+
if (!M) return null;
|
|
47
|
+
const X = {
|
|
48
|
+
transform: p ? $[r] : q[r],
|
|
49
|
+
transition: "transform var(--prui-duration-slow) var(--prui-ease-out)",
|
|
50
|
+
...r === "left" || r === "right" ? { width: typeof o == "number" ? `${o}px` : o ?? "400px" } : { maxHeight: typeof o == "number" ? `${o}px` : o ?? "80vh" },
|
|
51
|
+
...x
|
|
52
|
+
};
|
|
53
|
+
return /* @__PURE__ */ t(E, { children: /* @__PURE__ */ t("div", { ref: T, children: /* @__PURE__ */ t(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
className: "prui-drawer-overlay fixed inset-0 z-[var(--prui-z-modal)]",
|
|
57
|
+
style: {
|
|
58
|
+
backgroundColor: "var(--prui-scrim)",
|
|
59
|
+
opacity: p ? 1 : 0,
|
|
60
|
+
transition: "opacity var(--prui-duration-slow) var(--prui-ease-out)"
|
|
61
|
+
},
|
|
62
|
+
onMouseDown: (e) => {
|
|
63
|
+
e.target === e.currentTarget && c(!1);
|
|
64
|
+
},
|
|
65
|
+
children: /* @__PURE__ */ Y(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
ref: S,
|
|
69
|
+
role: "dialog",
|
|
70
|
+
"aria-modal": "true",
|
|
71
|
+
"aria-label": w,
|
|
72
|
+
"data-state": p ? "open" : "closed",
|
|
73
|
+
className: P(
|
|
74
|
+
"absolute flex flex-col overflow-y-auto border border-[var(--prui-line)] bg-[var(--prui-surface)]",
|
|
75
|
+
"text-[var(--prui-fg)] shadow-[var(--prui-shadow-modal)] outline-none",
|
|
76
|
+
L[r],
|
|
77
|
+
g
|
|
78
|
+
),
|
|
79
|
+
style: X,
|
|
80
|
+
children: [
|
|
81
|
+
r === "bottom" ? /* @__PURE__ */ t("div", { "aria-hidden": !0, className: "mx-auto mt-2 mb-1 h-1 w-10 shrink-0 rounded-[var(--prui-radius-full)] bg-[var(--prui-line)]" }) : null,
|
|
82
|
+
v,
|
|
83
|
+
y ? null : /* @__PURE__ */ t(
|
|
84
|
+
"button",
|
|
85
|
+
{
|
|
86
|
+
type: "button",
|
|
87
|
+
"aria-label": R.close,
|
|
88
|
+
onClick: () => c(!1),
|
|
89
|
+
className: "absolute right-3 top-3 rounded-[var(--prui-radius-1)] p-1 text-[var(--prui-dim)] transition-colors hover:bg-[var(--prui-raise)] hover:text-[var(--prui-fg)] cursor-pointer",
|
|
90
|
+
children: /* @__PURE__ */ t(k, { className: "h-4 w-4", "aria-hidden": !0 })
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
) }) });
|
|
98
|
+
});
|
|
99
|
+
h.displayName = "Drawer";
|
|
100
|
+
const H = a.forwardRef(function(n, i) {
|
|
101
|
+
return /* @__PURE__ */ t(h, { ref: i, side: "bottom", ...n });
|
|
102
|
+
});
|
|
103
|
+
H.displayName = "Sheet";
|
|
104
|
+
const J = {
|
|
105
|
+
name: "Drawer",
|
|
106
|
+
props: [
|
|
107
|
+
{ name: "open", type: "boolean", default: "undefined", control: "boolean" },
|
|
108
|
+
{ name: "defaultOpen", type: "boolean", default: "false", control: "boolean" },
|
|
109
|
+
{ name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" },
|
|
110
|
+
{ name: "side", type: "'left' | 'right' | 'top' | 'bottom'", default: "'right'", control: "select", options: ["left", "right", "top", "bottom"] },
|
|
111
|
+
{ name: "size", type: "number | string (CSS length)", default: "400px / 80vh", control: "text" },
|
|
112
|
+
{ name: "ariaLabel", type: "string", default: null, control: "text" },
|
|
113
|
+
{ name: "hideClose", type: "boolean", default: "false", control: "boolean" }
|
|
114
|
+
]
|
|
115
|
+
}, K = {
|
|
116
|
+
name: "Sheet",
|
|
117
|
+
props: [
|
|
118
|
+
{ name: "open", type: "boolean", default: "undefined", control: "boolean" },
|
|
119
|
+
{ name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" },
|
|
120
|
+
{ name: "size", type: "number | string (max height)", default: "80vh", control: "text" },
|
|
121
|
+
{ name: "ariaLabel", type: "string", default: null, control: "text" }
|
|
122
|
+
]
|
|
123
|
+
};
|
|
124
|
+
export {
|
|
125
|
+
h as Drawer,
|
|
126
|
+
H as Sheet,
|
|
127
|
+
J as drawerPropsMeta,
|
|
128
|
+
K as sheetPropsMeta
|
|
129
|
+
};
|
package/dist/core/dropdown.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { PropsMeta } from './props-meta';
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Dropdown: an anchored menu over a trigger. Full WAI-ARIA menu keyboard
|
|
5
|
+
* support: Enter/Space/ArrowDown open, ArrowUp/Down + Home/End move,
|
|
6
|
+
* printable-character typeahead selects, Escape (topmost overlay only)
|
|
7
|
+
* closes and restores focus to the trigger, Tab closes. Non-modal: no scroll
|
|
8
|
+
* lock and no background inertness.
|
|
9
|
+
*/
|
|
3
10
|
export interface DropdownItem {
|
|
4
11
|
label: string;
|
|
5
12
|
onSelect?: () => void;
|
|
@@ -17,8 +24,5 @@ export interface DropdownProps {
|
|
|
17
24
|
align?: "start" | "end";
|
|
18
25
|
className?: string;
|
|
19
26
|
}
|
|
20
|
-
export declare const Dropdown:
|
|
21
|
-
({ items, trigger, children, open: openProp, defaultOpen, onOpenChange, align, className, }: DropdownProps): React.JSX.Element;
|
|
22
|
-
displayName: string;
|
|
23
|
-
};
|
|
27
|
+
export declare const Dropdown: React.ForwardRefExoticComponent<DropdownProps & React.RefAttributes<HTMLDivElement>>;
|
|
24
28
|
export declare const dropdownPropsMeta: PropsMeta;
|
package/dist/core/dropdown.js
CHANGED
|
@@ -1,89 +1,174 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import * as
|
|
3
|
-
import { cn as
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { jsxs as I, jsx as p } from "react/jsx-runtime";
|
|
2
|
+
import * as o from "react";
|
|
3
|
+
import { cn as x } from "./cn.js";
|
|
4
|
+
import { useOverlayStack as P, useEscapeKey as _ } from "./overlay.js";
|
|
5
|
+
import { typeaheadIndex as $, endIndex as q, homeIndex as B, moveIndex as R } from "./list-nav.js";
|
|
6
|
+
const F = "[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']", H = o.forwardRef(function({
|
|
7
|
+
items: N,
|
|
6
8
|
trigger: m,
|
|
7
|
-
children:
|
|
8
|
-
open:
|
|
9
|
-
defaultOpen:
|
|
10
|
-
onOpenChange:
|
|
11
|
-
align:
|
|
12
|
-
className:
|
|
13
|
-
})
|
|
14
|
-
const [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
children: A,
|
|
10
|
+
open: h,
|
|
11
|
+
defaultOpen: K = !1,
|
|
12
|
+
onOpenChange: b,
|
|
13
|
+
align: C = "start",
|
|
14
|
+
className: S
|
|
15
|
+
}, i) {
|
|
16
|
+
const [j, M] = o.useState(K), D = h !== void 0, r = D ? h : j, v = o.useRef(null), c = o.useRef(null), y = o.useRef(null), [d, w] = o.useState(-1), E = o.useRef({ buffer: "", at: 0 }), s = (e) => {
|
|
17
|
+
var n, t;
|
|
18
|
+
if (D || M(e), b == null || b(e), !e) {
|
|
19
|
+
w(-1), E.current = { buffer: "", at: 0 };
|
|
20
|
+
const a = document.activeElement;
|
|
21
|
+
a && ((n = c.current) != null && n.contains(a)) && ((t = y.current) == null || t.focus());
|
|
22
|
+
}
|
|
23
|
+
}, { setElement: T, isTop: L } = P(r);
|
|
24
|
+
_(r, L, () => {
|
|
25
|
+
s(!1);
|
|
26
|
+
}), o.useEffect(() => {
|
|
27
|
+
if (!r) return;
|
|
28
|
+
const e = (n) => {
|
|
29
|
+
v.current && !v.current.contains(n.target) && s(!1);
|
|
23
30
|
};
|
|
24
|
-
return document.addEventListener("mousedown", e), document.
|
|
25
|
-
|
|
31
|
+
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
32
|
+
});
|
|
33
|
+
const f = o.useCallback(() => {
|
|
34
|
+
const e = c.current;
|
|
35
|
+
return e ? Array.from(e.querySelectorAll(F)) : [];
|
|
36
|
+
}, []), u = (e) => {
|
|
37
|
+
var t;
|
|
38
|
+
w(e), (t = f()[e]) == null || t.focus();
|
|
39
|
+
};
|
|
40
|
+
o.useEffect(() => {
|
|
41
|
+
var t;
|
|
42
|
+
if (!r) return;
|
|
43
|
+
const e = f(), n = e.findIndex((a) => !a.disabled);
|
|
44
|
+
n >= 0 ? (w(n), (t = e[n]) == null || t.focus()) : c.current && c.current.focus();
|
|
45
|
+
}, [r, f]);
|
|
46
|
+
const U = (e) => {
|
|
47
|
+
const n = f(), t = (a) => {
|
|
48
|
+
var l;
|
|
49
|
+
return !((l = n[a]) != null && l.disabled);
|
|
26
50
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
51
|
+
switch (e.key) {
|
|
52
|
+
case "ArrowDown":
|
|
53
|
+
e.preventDefault(), u(R(d, 1, n.length, { enabled: t }));
|
|
54
|
+
break;
|
|
55
|
+
case "ArrowUp":
|
|
56
|
+
e.preventDefault(), u(R(d, -1, n.length, { enabled: t }));
|
|
57
|
+
break;
|
|
58
|
+
case "Home":
|
|
59
|
+
e.preventDefault(), u(B(n.length, t));
|
|
60
|
+
break;
|
|
61
|
+
case "End":
|
|
62
|
+
e.preventDefault(), u(q(n.length, t));
|
|
63
|
+
break;
|
|
64
|
+
case "Tab":
|
|
65
|
+
s(!1);
|
|
66
|
+
break;
|
|
67
|
+
case "Enter":
|
|
68
|
+
case " ":
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
if (e.key.length === 1) {
|
|
72
|
+
const a = () => n.map((z) => z.textContent ?? ""), { index: l } = $(a, E.current, e.key, d);
|
|
73
|
+
l >= 0 && l !== d && (e.preventDefault(), u(l));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}, g = () => {
|
|
77
|
+
s(!0);
|
|
78
|
+
};
|
|
79
|
+
let k;
|
|
80
|
+
if (o.isValidElement(m)) {
|
|
81
|
+
const e = m;
|
|
82
|
+
k = o.cloneElement(e, {
|
|
83
|
+
ref: (n) => {
|
|
84
|
+
y.current = n;
|
|
85
|
+
const t = e.props.ref;
|
|
86
|
+
typeof t == "function" ? t(n) : t && typeof t == "object" && (t.current = n);
|
|
87
|
+
},
|
|
88
|
+
"aria-haspopup": "menu",
|
|
89
|
+
"aria-expanded": r,
|
|
90
|
+
onClick: (n) => {
|
|
91
|
+
const t = e.props.onClick;
|
|
92
|
+
t == null || t(n), n.defaultPrevented || s(!r);
|
|
93
|
+
},
|
|
94
|
+
onKeyDown: (n) => {
|
|
95
|
+
const t = e.props.onKeyDown;
|
|
96
|
+
t == null || t(n), !n.defaultPrevented && (n.key === "ArrowDown" || n.key === "Enter" || n.key === " ") && (r || (n.preventDefault(), g()));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
} else
|
|
100
|
+
k = /* @__PURE__ */ p(
|
|
101
|
+
"button",
|
|
30
102
|
{
|
|
31
|
-
|
|
32
|
-
|
|
103
|
+
type: "button",
|
|
104
|
+
ref: (e) => {
|
|
105
|
+
y.current = e;
|
|
106
|
+
},
|
|
33
107
|
"aria-haspopup": "menu",
|
|
34
|
-
"aria-expanded":
|
|
35
|
-
onClick: () =>
|
|
108
|
+
"aria-expanded": r,
|
|
109
|
+
onClick: () => s(!r),
|
|
36
110
|
onKeyDown: (e) => {
|
|
37
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(),
|
|
111
|
+
(e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") && !r && (e.preventDefault(), g());
|
|
38
112
|
},
|
|
39
113
|
children: m
|
|
40
114
|
}
|
|
41
|
-
)
|
|
42
|
-
|
|
115
|
+
);
|
|
116
|
+
return /* @__PURE__ */ I("div", { ref: (e) => {
|
|
117
|
+
v.current = e, typeof i == "function" ? i(e) : i && (i.current = e);
|
|
118
|
+
}, className: x("prui-dropdown relative inline-block", S), "data-state": r ? "open" : "closed", children: [
|
|
119
|
+
k,
|
|
120
|
+
r ? /* @__PURE__ */ p(
|
|
43
121
|
"div",
|
|
44
122
|
{
|
|
123
|
+
ref: (e) => {
|
|
124
|
+
c.current = e, T((e == null ? void 0 : e.parentElement) ?? null);
|
|
125
|
+
},
|
|
45
126
|
role: "menu",
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
127
|
+
tabIndex: -1,
|
|
128
|
+
onKeyDown: U,
|
|
129
|
+
className: x(
|
|
130
|
+
"prui-dropdown-menu absolute z-[var(--prui-z-overlay)] mt-1 min-w-40 rounded-[var(--prui-radius)] border border-[var(--prui-line)]",
|
|
131
|
+
"bg-[var(--prui-surface)] p-1 shadow-[var(--prui-shadow-md)] outline-none",
|
|
132
|
+
C === "end" ? "right-0" : "left-0"
|
|
50
133
|
),
|
|
51
|
-
children:
|
|
52
|
-
e.separatorBefore ? /* @__PURE__ */
|
|
53
|
-
/* @__PURE__ */
|
|
134
|
+
children: A ?? (N ?? []).map((e, n) => /* @__PURE__ */ I(o.Fragment, { children: [
|
|
135
|
+
e.separatorBefore ? /* @__PURE__ */ p("div", { className: "my-1 h-px bg-[var(--prui-line)]" }) : null,
|
|
136
|
+
/* @__PURE__ */ p(
|
|
54
137
|
"button",
|
|
55
138
|
{
|
|
56
139
|
type: "button",
|
|
57
140
|
role: "menuitem",
|
|
141
|
+
tabIndex: -1,
|
|
58
142
|
disabled: e.disabled,
|
|
59
143
|
onClick: () => {
|
|
60
|
-
var
|
|
61
|
-
e.disabled || (
|
|
144
|
+
var t;
|
|
145
|
+
e.disabled || (s(!1), (t = e.onSelect) == null || t.call(e));
|
|
62
146
|
},
|
|
63
|
-
className:
|
|
147
|
+
className: x(
|
|
64
148
|
"flex w-full items-center rounded-[calc(var(--prui-radius)-1px)] px-2.5 py-1.5 text-left text-sm",
|
|
65
|
-
"hover:bg-[var(--prui-raise)] cursor-pointer disabled:opacity-50 disabled:pointer-events-none",
|
|
149
|
+
"hover:bg-[var(--prui-raise)] focus-visible:bg-[var(--prui-raise)] outline-none cursor-pointer disabled:opacity-50 disabled:pointer-events-none",
|
|
66
150
|
e.danger ? "text-[var(--prui-danger)]" : "text-[var(--prui-fg)]"
|
|
67
151
|
),
|
|
68
152
|
children: e.label
|
|
69
153
|
}
|
|
70
154
|
)
|
|
71
|
-
] }, `${e.label}-${
|
|
155
|
+
] }, `${e.label}-${n}`))
|
|
72
156
|
}
|
|
73
157
|
) : null
|
|
74
158
|
] });
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const
|
|
159
|
+
});
|
|
160
|
+
H.displayName = "Dropdown";
|
|
161
|
+
const Q = {
|
|
78
162
|
name: "Dropdown",
|
|
79
163
|
props: [
|
|
80
164
|
{ name: "items", type: "DropdownItem[]", default: "[]", control: "object" },
|
|
81
165
|
{ name: "trigger", type: "ReactNode", default: null, control: "none" },
|
|
82
166
|
{ name: "align", type: "'start' | 'end'", default: "'start'", control: "select", options: ["start", "end"] },
|
|
83
|
-
{ name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" }
|
|
167
|
+
{ name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" },
|
|
168
|
+
{ name: "open", type: "boolean", default: "undefined", control: "boolean" }
|
|
84
169
|
]
|
|
85
170
|
};
|
|
86
171
|
export {
|
|
87
|
-
|
|
88
|
-
|
|
172
|
+
H as Dropdown,
|
|
173
|
+
Q as dropdownPropsMeta
|
|
89
174
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PropsMeta } from './props-meta';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* FileUpload: an accessible dropzone + file picker. The dropzone is a real
|
|
5
|
+
* button wrapping a visually-hidden input (keyboard + screen reader
|
|
6
|
+
* native); drag events highlight the zone. Files render as a removable
|
|
7
|
+
* list. Accept/multiple mirror the native input attributes.
|
|
8
|
+
*/
|
|
9
|
+
export interface FileUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onError"> {
|
|
10
|
+
/** Accepted file types (native input accept syntax). */
|
|
11
|
+
accept?: string;
|
|
12
|
+
/** Allow multiple files. Default true. */
|
|
13
|
+
multiple?: boolean;
|
|
14
|
+
/** Validate/reject files; return an error message string or null. */
|
|
15
|
+
validate?: (file: File) => string | null;
|
|
16
|
+
onFiles?: (files: File[]) => void;
|
|
17
|
+
/** Control the visible file list externally. */
|
|
18
|
+
files?: File[];
|
|
19
|
+
/** Max file size in bytes per file. */
|
|
20
|
+
maxSize?: number;
|
|
21
|
+
/** Primary dropzone copy. */
|
|
22
|
+
hint?: React.ReactNode;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/** Hide the selected-files list (caller renders their own). */
|
|
25
|
+
hideList?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare const FileUpload: React.ForwardRefExoticComponent<FileUploadProps & React.RefAttributes<HTMLInputElement>>;
|
|
28
|
+
export declare const fileUploadPropsMeta: PropsMeta;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { jsxs as h, jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import * as i from "react";
|
|
3
|
+
import { UploadCloud as M, File as S, X as T } from "lucide-react";
|
|
4
|
+
import { cn as k } from "./cn.js";
|
|
5
|
+
import { usePruiI18n as z } from "../i18n.js";
|
|
6
|
+
function C(n) {
|
|
7
|
+
return n < 1024 ? `${n} B` : n < 1024 * 1024 ? `${(n / 1024).toFixed(1)} KB` : `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
8
|
+
}
|
|
9
|
+
const K = i.forwardRef(function({ accept: F, multiple: v = !0, validate: p, onFiles: o, files: b, maxSize: f, hint: R, disabled: l, hideList: B, className: j, ...A }, s) {
|
|
10
|
+
const { t: y } = z(), [E, N] = i.useState([]), [$, m] = i.useState(!1), [g, I] = i.useState([]), x = b !== void 0, u = x ? b : E, w = i.useRef(null), D = (e) => {
|
|
11
|
+
if (l) return;
|
|
12
|
+
const r = [], a = [];
|
|
13
|
+
for (const d of Array.from(e)) {
|
|
14
|
+
const U = f != null && d.size > f ? `${d.name} is larger than ${C(f)}.` : (p == null ? void 0 : p(d)) ?? null;
|
|
15
|
+
U ? r.push(U) : a.push(d);
|
|
16
|
+
}
|
|
17
|
+
I(r);
|
|
18
|
+
const c = v ? [...u, ...a] : a.slice(-1);
|
|
19
|
+
x || N(c), o == null || o(c);
|
|
20
|
+
}, L = (e) => {
|
|
21
|
+
const r = u.filter((a, c) => c !== e);
|
|
22
|
+
x || N(r), o == null || o(r);
|
|
23
|
+
};
|
|
24
|
+
return /* @__PURE__ */ h("div", { className: k("prui-file-upload flex flex-col gap-2", j), ...A, children: [
|
|
25
|
+
/* @__PURE__ */ h(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
type: "button",
|
|
29
|
+
disabled: l,
|
|
30
|
+
"aria-describedby": g.length ? "prui-file-upload-errors" : void 0,
|
|
31
|
+
onClick: () => {
|
|
32
|
+
var e;
|
|
33
|
+
return (e = w.current) == null ? void 0 : e.click();
|
|
34
|
+
},
|
|
35
|
+
onDragOver: (e) => {
|
|
36
|
+
e.preventDefault(), l || m(!0);
|
|
37
|
+
},
|
|
38
|
+
onDragLeave: () => m(!1),
|
|
39
|
+
onDrop: (e) => {
|
|
40
|
+
var r, a;
|
|
41
|
+
e.preventDefault(), m(!1), (a = (r = e.dataTransfer) == null ? void 0 : r.files) != null && a.length && D(e.dataTransfer.files);
|
|
42
|
+
},
|
|
43
|
+
"data-dragging": $ || void 0,
|
|
44
|
+
"data-disabled": l || void 0,
|
|
45
|
+
className: k(
|
|
46
|
+
"flex cursor-pointer flex-col items-center justify-center gap-2 rounded-[var(--prui-radius)] border border-dashed p-8 text-sm",
|
|
47
|
+
"transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[var(--prui-brand)]",
|
|
48
|
+
$ ? "border-[var(--prui-brand)] bg-[var(--prui-brand)]/10 text-[var(--prui-brand)]" : "border-[var(--prui-line)] bg-[var(--prui-background)] text-[var(--prui-dim)] hover:border-[var(--prui-dim)]",
|
|
49
|
+
l && "opacity-50 cursor-not-allowed"
|
|
50
|
+
),
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ t(M, { className: "h-6 w-6", "aria-hidden": !0 }),
|
|
53
|
+
/* @__PURE__ */ t("span", { children: R ?? y.dropFiles })
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
/* @__PURE__ */ t(
|
|
58
|
+
"input",
|
|
59
|
+
{
|
|
60
|
+
ref: (e) => {
|
|
61
|
+
w.current = e, typeof s == "function" ? s(e) : s && (s.current = e);
|
|
62
|
+
},
|
|
63
|
+
type: "file",
|
|
64
|
+
accept: F,
|
|
65
|
+
multiple: v,
|
|
66
|
+
disabled: l,
|
|
67
|
+
className: "sr-only",
|
|
68
|
+
tabIndex: -1,
|
|
69
|
+
"aria-hidden": !0,
|
|
70
|
+
onChange: (e) => {
|
|
71
|
+
var r;
|
|
72
|
+
(r = e.target.files) != null && r.length && D(e.target.files), e.target.value = "";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
g.length > 0 ? /* @__PURE__ */ t("div", { id: "prui-file-upload-errors", role: "alert", className: "flex flex-col gap-1 text-xs text-[var(--prui-danger)]", children: g.map((e, r) => /* @__PURE__ */ t("span", { children: e }, r)) }) : null,
|
|
77
|
+
!B && u.length > 0 ? /* @__PURE__ */ t("ul", { className: "flex flex-col gap-1", "data-testid": "file-upload-list", children: u.map((e, r) => /* @__PURE__ */ h("li", { className: "flex items-center gap-2 rounded-[var(--prui-radius-1)] bg-[var(--prui-raise)] px-3 py-2 text-sm text-[var(--prui-fg)]", children: [
|
|
78
|
+
/* @__PURE__ */ t(S, { className: "h-4 w-4 shrink-0 text-[var(--prui-dim)]", "aria-hidden": !0 }),
|
|
79
|
+
/* @__PURE__ */ t("span", { className: "min-w-0 flex-1 truncate", children: e.name }),
|
|
80
|
+
/* @__PURE__ */ t("span", { className: "text-xs text-[var(--prui-dim)]", children: C(e.size) }),
|
|
81
|
+
/* @__PURE__ */ t(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
"aria-label": `${y.removeFile}: ${e.name}`,
|
|
86
|
+
onClick: () => L(r),
|
|
87
|
+
className: "rounded-[var(--prui-radius-1)] p-1 text-[var(--prui-dim)] transition-colors hover:text-[var(--prui-danger)] cursor-pointer",
|
|
88
|
+
children: /* @__PURE__ */ t(T, { className: "h-3.5 w-3.5", "aria-hidden": !0 })
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
] }, `${e.name}-${r}`)) }) : null
|
|
92
|
+
] });
|
|
93
|
+
});
|
|
94
|
+
K.displayName = "FileUpload";
|
|
95
|
+
const q = {
|
|
96
|
+
name: "FileUpload",
|
|
97
|
+
props: [
|
|
98
|
+
{ name: "accept", type: "string (input accept)", default: "undefined", control: "text" },
|
|
99
|
+
{ name: "multiple", type: "boolean", default: "true", control: "boolean" },
|
|
100
|
+
{ name: "onFiles", type: "(files: File[]) => void", default: null, control: "none" },
|
|
101
|
+
{ name: "files", type: "File[]", default: "internal state", control: "none" },
|
|
102
|
+
{ name: "maxSize", type: "number (bytes)", default: "undefined", control: "number" },
|
|
103
|
+
{ name: "validate", type: "(file: File) => string | null", default: null, control: "none" },
|
|
104
|
+
{ name: "hint", type: "ReactNode", default: "'Drag files here or click to browse'", control: "text" },
|
|
105
|
+
{ name: "hideList", type: "boolean", default: "false", control: "boolean" }
|
|
106
|
+
]
|
|
107
|
+
};
|
|
108
|
+
export {
|
|
109
|
+
K as FileUpload,
|
|
110
|
+
q as fileUploadPropsMeta
|
|
111
|
+
};
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export { cn } from './cn';
|
|
3
3
|
export { resolveSurface, withSurface, type SurfaceProps, type SurfaceRadius, type SurfaceTexture, type SurfaceElevation } from './surface';
|
|
4
4
|
export type { PropsMeta, PropMeta, PropControl } from './props-meta';
|
|
5
|
+
export { Portal, useReducedMotion, useFocusTrap, useEscapeKey, useScrollLock, useInertBackground, useOverlay, useOverlayStack, pushOverlay, removeOverlay, isTopOverlay, overlayCount, getFocusable, overlayPropsMeta, } from './overlay';
|
|
6
|
+
export { moveIndex, homeIndex, endIndex, typeaheadIndex } from './list-nav';
|
|
5
7
|
export { Button, buttonPropsMeta, type ButtonProps, type ButtonVariant, type ButtonSize, } from './button';
|
|
6
8
|
export { Input, inputPropsMeta, Textarea, textareaPropsMeta, type InputProps, type TextareaProps, } from './input';
|
|
7
9
|
export { Label, labelPropsMeta, Separator, separatorPropsMeta, type LabelProps, type SeparatorProps } from './label';
|
|
@@ -9,7 +11,27 @@ export { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, selectPr
|
|
|
9
11
|
export { Switch, switchPropsMeta, type SwitchProps } from './switch';
|
|
10
12
|
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsPropsMeta, type TabsProps, type TabsListProps, type TabsTriggerProps, type TabsContentProps, } from './tabs';
|
|
11
13
|
export { Badge, badgePropsMeta, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, cardPropsMeta, Avatar, avatarPropsMeta, type BadgeProps, type BadgeVariant, type AvatarProps, } from './card';
|
|
12
|
-
export { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, dialogPropsMeta, type DialogProps, type DialogContentProps, } from './dialog';
|
|
14
|
+
export { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogBody, DialogFooter, dialogPropsMeta, dialogBodyPropsMeta, type DialogProps, type DialogContentProps, type DialogBodyProps, } from './dialog';
|
|
13
15
|
export { Dropdown, dropdownPropsMeta, type DropdownProps, type DropdownItem, } from './dropdown';
|
|
14
16
|
export { ScrollArea, scrollAreaPropsMeta, type ScrollAreaProps } from './scroll-area';
|
|
15
17
|
export { Modal, confirmModal, modalPropsMeta, confirmModalPropsMeta, type ModalProps, type ModalSize, type ConfirmModalOptions, type ConfirmModalType, } from './modal';
|
|
18
|
+
export { computePosition, useAnchoredPosition, type AnchorSide, type AnchorAlign, type AnchoredPosition } from './anchor';
|
|
19
|
+
export { Spinner, spinnerPropsMeta, type SpinnerProps, type SpinnerSize } from './spinner';
|
|
20
|
+
export { Skeleton, skeletonPropsMeta, type SkeletonProps } from './skeleton';
|
|
21
|
+
export { Alert, alertPropsMeta, type AlertProps, type AlertVariant } from './alert';
|
|
22
|
+
export { Progress, progressPropsMeta, type ProgressProps } from './progress';
|
|
23
|
+
export { Toaster, toast, dismissAllToasts, toasterPropsMeta, toastPropsMeta, type ToasterProps, type ToastOptions, type ToastVariant, type ToastHandle } from './toast';
|
|
24
|
+
export { Tooltip, tooltipPropsMeta, type TooltipProps } from './tooltip';
|
|
25
|
+
export { Popover, popoverPropsMeta, type PopoverProps } from './popover';
|
|
26
|
+
export { Drawer, Sheet, drawerPropsMeta, sheetPropsMeta, type DrawerProps, type DrawerSide } from './drawer';
|
|
27
|
+
export { Checkbox, checkboxPropsMeta, type CheckboxProps } from './checkbox';
|
|
28
|
+
export { RadioGroup, Radio, radioGroupPropsMeta, type RadioGroupProps, type RadioProps } from './radio';
|
|
29
|
+
export { Combobox, comboboxPropsMeta, type ComboboxProps, type ComboboxOption } from './combobox';
|
|
30
|
+
export { Accordion, AccordionItem, accordionPropsMeta, type AccordionProps, type AccordionItemProps } from './accordion';
|
|
31
|
+
export { Breadcrumb, BreadcrumbItem, BreadcrumbEllipsis, breadcrumbPropsMeta, type BreadcrumbProps, type BreadcrumbItemProps } from './breadcrumb';
|
|
32
|
+
export { TreeView, treeViewPropsMeta, type TreeViewProps, type TreeViewItem } from './tree-view';
|
|
33
|
+
export { Timeline, timelinePropsMeta, type TimelineProps, type TimelineItemData, type TimelineVariant } from './timeline';
|
|
34
|
+
export { Calendar, calendarPropsMeta, toDateKey, fromDateKey, type CalendarProps } from './calendar';
|
|
35
|
+
export { DatePicker, DateRangePicker, datePickerPropsMeta, dateRangePickerPropsMeta, type DatePickerProps, type DateRangePickerProps, type DateRange, type MaxRange } from './date-picker';
|
|
36
|
+
export { TimePicker, TimeRangePicker, TimePanel, timePickerPropsMeta, timeRangePickerPropsMeta, type TimePickerProps, type TimeRangePickerProps, type TimeRange } from './time-picker';
|
|
37
|
+
export { FileUpload, fileUploadPropsMeta, type FileUploadProps } from './file-upload';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared list/menus keyboard navigation helpers.
|
|
3
|
+
*
|
|
4
|
+
* Pure index math plus a typeahead buffer, reused by Dropdown, Select,
|
|
5
|
+
* CommandPalette, the nav rail flyout, Combobox and any roving-tabIndex
|
|
6
|
+
* list. No DOM assumptions: callers own focus and rendering.
|
|
7
|
+
*/
|
|
8
|
+
/** Next index for ArrowUp/ArrowDown (and Left/Right in horizontal lists). */
|
|
9
|
+
export declare function moveIndex(current: number, delta: 1 | -1, length: number, opts?: {
|
|
10
|
+
loop?: boolean;
|
|
11
|
+
enabled?: (index: number) => boolean;
|
|
12
|
+
}): number;
|
|
13
|
+
/** Home / End clamps. */
|
|
14
|
+
export declare function homeIndex(length: number, enabled?: (i: number) => boolean): number;
|
|
15
|
+
export declare function endIndex(length: number, enabled?: (i: number) => boolean): number;
|
|
16
|
+
/**
|
|
17
|
+
* Typeahead: given the item labels, find the next item whose label starts
|
|
18
|
+
* with the accumulated prefix (searching forward from the active item,
|
|
19
|
+
* wrapping). Case-insensitive; resets after `resetMs` of inactivity.
|
|
20
|
+
*/
|
|
21
|
+
export declare function typeaheadIndex(labels: () => string[], state: {
|
|
22
|
+
buffer: string;
|
|
23
|
+
at: number;
|
|
24
|
+
}, key: string, activeIndex: number, resetMs?: number): {
|
|
25
|
+
index: number;
|
|
26
|
+
buffer: string;
|
|
27
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
function m(n, r, t, f = {}) {
|
|
2
|
+
if (t <= 0) return -1;
|
|
3
|
+
const { loop: o = !0, enabled: u } = f;
|
|
4
|
+
if (n < 0)
|
|
5
|
+
return r > 0 ? h(0, 1, t, u) : h(t - 1, -1, t, u);
|
|
6
|
+
let i = n;
|
|
7
|
+
for (let e = 0; e < t; e++) {
|
|
8
|
+
if (i = i + r, i >= t || i < 0) {
|
|
9
|
+
if (!o) return n;
|
|
10
|
+
i = i < 0 ? t - 1 : 0;
|
|
11
|
+
}
|
|
12
|
+
if (!u || u(i)) return i;
|
|
13
|
+
}
|
|
14
|
+
return n;
|
|
15
|
+
}
|
|
16
|
+
function h(n, r, t, f) {
|
|
17
|
+
for (let o = n; o >= 0 && o < t; o += r)
|
|
18
|
+
if (!f || f(o)) return o;
|
|
19
|
+
return -1;
|
|
20
|
+
}
|
|
21
|
+
function p(n, r) {
|
|
22
|
+
return h(0, 1, n, r);
|
|
23
|
+
}
|
|
24
|
+
function w(n, r) {
|
|
25
|
+
return h(n - 1, -1, n, r);
|
|
26
|
+
}
|
|
27
|
+
function a(n, r, t, f, o = 500) {
|
|
28
|
+
var x, b;
|
|
29
|
+
if (t.length !== 1) return { index: f, buffer: r.buffer };
|
|
30
|
+
const u = Date.now(), e = u - r.at < o ? r.buffer + t.toLowerCase() : t.toLowerCase();
|
|
31
|
+
r.buffer = e, r.at = u;
|
|
32
|
+
const c = n().map((s) => s.trim().toLowerCase());
|
|
33
|
+
for (let s = 1; s <= c.length; s++) {
|
|
34
|
+
const d = (f + s) % c.length;
|
|
35
|
+
if ((x = c[d]) != null && x.startsWith(e)) return { index: d, buffer: e };
|
|
36
|
+
}
|
|
37
|
+
if (e.length > 1) {
|
|
38
|
+
const s = e[e.length - 1];
|
|
39
|
+
for (let d = 1; d <= c.length; d++) {
|
|
40
|
+
const l = (f + d) % c.length;
|
|
41
|
+
if ((b = c[l]) != null && b.startsWith(s)) return { index: l, buffer: e };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { index: f, buffer: e };
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
w as endIndex,
|
|
48
|
+
p as homeIndex,
|
|
49
|
+
m as moveIndex,
|
|
50
|
+
a as typeaheadIndex
|
|
51
|
+
};
|