@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
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';
|
|
@@ -13,3 +15,22 @@ export { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Di
|
|
|
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 } from './date-picker';
|
|
36
|
+
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
|
+
};
|
package/dist/core/modal.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ import * as React from "react";
|
|
|
7
7
|
* false = shake feedback, and an imperative confirmModal() that renders a
|
|
8
8
|
* typed confirmation dialog imperatively and resolves a Promise<boolean>.
|
|
9
9
|
* Restyled onto PRUI tokens instead of hardcoded hex.
|
|
10
|
+
*
|
|
11
|
+
* Built on the shared overlay infrastructure (core/overlay): portaled to the
|
|
12
|
+
* body, focus-trapped with initial focus and focus restoration, Escape is
|
|
13
|
+
* answered only by the topmost overlay, and the background is aria-hidden +
|
|
14
|
+
* inert where supported while open. prefers-reduced-motion disables the
|
|
15
|
+
* shake/scale/fade choreography.
|
|
10
16
|
*/
|
|
11
17
|
export type ModalSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
12
18
|
export interface ModalProps {
|
|
@@ -32,11 +38,12 @@ export interface ModalProps {
|
|
|
32
38
|
/** Accessible label. */
|
|
33
39
|
ariaLabel?: string;
|
|
34
40
|
className?: string;
|
|
41
|
+
/** Inline style applied to the modal content element. */
|
|
42
|
+
style?: React.CSSProperties;
|
|
43
|
+
/** Initial focus target: the first focusable, the dialog itself, a specific element, or none. */
|
|
44
|
+
initialFocus?: React.RefObject<HTMLElement | null> | "first" | "container" | false;
|
|
35
45
|
}
|
|
36
|
-
export declare
|
|
37
|
-
export declare namespace Modal {
|
|
38
|
-
var displayName: string;
|
|
39
|
-
}
|
|
46
|
+
export declare const Modal: React.ForwardRefExoticComponent<ModalProps & React.RefAttributes<HTMLDivElement>>;
|
|
40
47
|
export type ConfirmModalType = "success" | "warning" | "danger" | "error" | "info";
|
|
41
48
|
export interface ConfirmModalOptions {
|
|
42
49
|
title: string;
|
|
@@ -49,7 +56,9 @@ export interface ConfirmModalOptions {
|
|
|
49
56
|
/**
|
|
50
57
|
* confirmModal({ title, message, type }) => Promise<boolean>
|
|
51
58
|
* Renders the confirmation modal imperatively; resolves true on confirm,
|
|
52
|
-
* false on cancel/Escape/overlay-shake close. Focus-trapped
|
|
59
|
+
* false on cancel/Escape/overlay-shake close. Focus-trapped via the shared
|
|
60
|
+
* overlay infrastructure: initial focus lands on the confirm action and
|
|
61
|
+
* focus returns to the invoker on close.
|
|
53
62
|
*/
|
|
54
63
|
export declare function confirmModal(options: ConfirmModalOptions): Promise<boolean>;
|
|
55
64
|
export declare const modalPropsMeta: PropsMeta;
|