@skiddph/prui 0.1.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/LICENSE +201 -0
- package/dist/app/app.d.ts +91 -0
- package/dist/app/auto-pages.d.ts +20 -0
- package/dist/app/form.d.ts +44 -0
- package/dist/app/index.d.ts +8 -0
- package/dist/app/resource.d.ts +61 -0
- package/dist/app/settings.d.ts +27 -0
- package/dist/app/stat-row.d.ts +20 -0
- package/dist/app.js +18 -0
- package/dist/chunks/data-table-toolbar-C9likJBN.js +430 -0
- package/dist/chunks/settings-DUz5nyX-.js +731 -0
- package/dist/core/button.d.ts +14 -0
- package/dist/core/button.js +58 -0
- package/dist/core/card.d.ts +24 -0
- package/dist/core/card.js +122 -0
- package/dist/core/cn.d.ts +3 -0
- package/dist/core/cn.js +8 -0
- package/dist/core/dialog.d.ts +25 -0
- package/dist/core/dialog.js +102 -0
- package/dist/core/dropdown.d.ts +24 -0
- package/dist/core/dropdown.js +89 -0
- package/dist/core/index.d.ts +14 -0
- package/dist/core/input.d.ts +8 -0
- package/dist/core/input.js +42 -0
- package/dist/core/label.d.ts +12 -0
- package/dist/core/label.js +52 -0
- package/dist/core/modal.d.ts +56 -0
- package/dist/core/modal.js +303 -0
- package/dist/core/props-meta.d.ts +26 -0
- package/dist/core/props-meta.js +1 -0
- package/dist/core/scroll-area.d.ts +8 -0
- package/dist/core/scroll-area.js +27 -0
- package/dist/core/select.d.ts +38 -0
- package/dist/core/select.js +157 -0
- package/dist/core/switch.d.ts +10 -0
- package/dist/core/switch.js +57 -0
- package/dist/core/tabs.d.ts +22 -0
- package/dist/core/tabs.js +94 -0
- package/dist/core.js +64 -0
- package/dist/data-table/data-table-daterange-filter.d.ts +14 -0
- package/dist/data-table/data-table-faceted-filter.d.ts +17 -0
- package/dist/data-table/data-table-number-range-filter.d.ts +14 -0
- package/dist/data-table/data-table-pagination.d.ts +24 -0
- package/dist/data-table/data-table-toolbar.d.ts +38 -0
- package/dist/data-table/data-table.d.ts +47 -0
- package/dist/data-table/index.d.ts +7 -0
- package/dist/data-table.js +12 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +125 -0
- package/dist/pages/forgot-password.d.ts +21 -0
- package/dist/pages/index.d.ts +18 -0
- package/dist/pages/login.d.ts +24 -0
- package/dist/pages/logout.d.ts +12 -0
- package/dist/pages/otp.d.ts +18 -0
- package/dist/pages/profile-settings.d.ts +55 -0
- package/dist/pages/register.d.ts +19 -0
- package/dist/pages/reset-password.d.ts +20 -0
- package/dist/pages/shared.d.ts +55 -0
- package/dist/pages/status.d.ts +33 -0
- package/dist/pages.js +806 -0
- package/dist/prui.css +120 -0
- package/dist/theme/base.css +36 -0
- package/dist/theme/control.css +16 -0
- package/dist/theme/daylight.css +16 -0
- package/dist/theme/ember.css +16 -0
- package/dist/theme/index.d.ts +55 -0
- package/dist/theme/workshop.css +16 -0
- package/dist/theme.js +63 -0
- package/package.json +81 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PropsMeta } from './props-meta';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Modal, ported from icanhelp-tracker's production modal (the invented one):
|
|
5
|
+
* size scale xs/sm/md/lg/xl, open/close animations, shake-on-blocked-close,
|
|
6
|
+
* overlay blur, body scroll lock, noPadding/padding control, closeOnOverlayClick
|
|
7
|
+
* false = shake feedback, and an imperative confirmModal() that renders a
|
|
8
|
+
* typed confirmation dialog imperatively and resolves a Promise<boolean>.
|
|
9
|
+
* Restyled onto PRUI tokens instead of hardcoded hex.
|
|
10
|
+
*/
|
|
11
|
+
export type ModalSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
12
|
+
export interface ModalProps {
|
|
13
|
+
open: boolean;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
/** Block overlay/esc close (still shows the X unless hideClose). */
|
|
17
|
+
disableDefaultClose?: boolean;
|
|
18
|
+
/** When false, an overlay click shakes instead of closing. Default true. */
|
|
19
|
+
closeOnOverlayClick?: boolean;
|
|
20
|
+
size?: ModalSize;
|
|
21
|
+
xs?: boolean;
|
|
22
|
+
sm?: boolean;
|
|
23
|
+
md?: boolean;
|
|
24
|
+
lg?: boolean;
|
|
25
|
+
xl?: boolean;
|
|
26
|
+
/** Custom max-width CSS value. */
|
|
27
|
+
maxWidth?: string;
|
|
28
|
+
/** Custom padding, e.g. "24px 32px". */
|
|
29
|
+
padding?: string;
|
|
30
|
+
noPadding?: boolean;
|
|
31
|
+
showCloseButton?: boolean;
|
|
32
|
+
/** Accessible label. */
|
|
33
|
+
ariaLabel?: string;
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function Modal({ open, onClose, children, disableDefaultClose, closeOnOverlayClick, size, xs, sm, md, lg, xl, maxWidth, padding, noPadding, showCloseButton, ariaLabel, className, }: ModalProps): React.JSX.Element | null;
|
|
37
|
+
export declare namespace Modal {
|
|
38
|
+
var displayName: string;
|
|
39
|
+
}
|
|
40
|
+
export type ConfirmModalType = "success" | "warning" | "danger" | "error" | "info";
|
|
41
|
+
export interface ConfirmModalOptions {
|
|
42
|
+
title: string;
|
|
43
|
+
message: string;
|
|
44
|
+
confirmText?: string;
|
|
45
|
+
cancelText?: string;
|
|
46
|
+
type?: ConfirmModalType;
|
|
47
|
+
size?: ModalSize;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* confirmModal({ title, message, type }) => Promise<boolean>
|
|
51
|
+
* Renders the confirmation modal imperatively; resolves true on confirm,
|
|
52
|
+
* false on cancel/Escape/overlay-shake close. Focus-trapped like the original.
|
|
53
|
+
*/
|
|
54
|
+
export declare function confirmModal(options: ConfirmModalOptions): Promise<boolean>;
|
|
55
|
+
export declare const modalPropsMeta: PropsMeta;
|
|
56
|
+
export declare const confirmModalPropsMeta: PropsMeta;
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { jsx as e, jsxs as d } from "react/jsx-runtime";
|
|
2
|
+
import * as r from "react";
|
|
3
|
+
import { createRoot as I } from "react-dom/client";
|
|
4
|
+
import { X as K } from "lucide-react";
|
|
5
|
+
import { cn as Y } from "./cn.js";
|
|
6
|
+
const P = {
|
|
7
|
+
xs: { width: "320px", minWidth: "280px" },
|
|
8
|
+
sm: { width: "448px", minWidth: "320px" },
|
|
9
|
+
md: { width: "640px", minWidth: "384px" },
|
|
10
|
+
lg: { width: "896px", minWidth: "512px" },
|
|
11
|
+
xl: { width: "1152px", minWidth: "640px" }
|
|
12
|
+
}, D = {
|
|
13
|
+
xs: "24px 32px",
|
|
14
|
+
sm: "24px 32px",
|
|
15
|
+
md: "32px 40px",
|
|
16
|
+
lg: "32px 40px",
|
|
17
|
+
xl: "40px 48px"
|
|
18
|
+
};
|
|
19
|
+
function O({
|
|
20
|
+
open: n,
|
|
21
|
+
onClose: o,
|
|
22
|
+
children: W,
|
|
23
|
+
disableDefaultClose: u = !1,
|
|
24
|
+
closeOnOverlayClick: L = !0,
|
|
25
|
+
size: y,
|
|
26
|
+
xs: T,
|
|
27
|
+
sm: S,
|
|
28
|
+
md: z,
|
|
29
|
+
lg: f,
|
|
30
|
+
xl: v,
|
|
31
|
+
maxWidth: E,
|
|
32
|
+
padding: N,
|
|
33
|
+
noPadding: h = !1,
|
|
34
|
+
showCloseButton: M = !0,
|
|
35
|
+
ariaLabel: x,
|
|
36
|
+
className: k
|
|
37
|
+
}) {
|
|
38
|
+
const l = y ?? (T ? "xs" : S ? "sm" : f ? "lg" : v ? "xl" : "md"), [R, g] = r.useState(n), [c, m] = r.useState(!1), [w, i] = r.useState(!1), C = r.useRef(null);
|
|
39
|
+
if (r.useEffect(() => {
|
|
40
|
+
if (n) {
|
|
41
|
+
g(!0);
|
|
42
|
+
const t = setTimeout(() => {
|
|
43
|
+
m(!0), document.body.classList.add("modal-open");
|
|
44
|
+
}, 10);
|
|
45
|
+
return () => clearTimeout(t);
|
|
46
|
+
}
|
|
47
|
+
m(!1), document.body.classList.remove("modal-open");
|
|
48
|
+
}, [n]), r.useEffect(() => () => document.body.classList.remove("modal-open"), []), r.useEffect(() => {
|
|
49
|
+
if (!n) return;
|
|
50
|
+
const t = (p) => {
|
|
51
|
+
p.key === "Escape" && (u ? (i(!0), setTimeout(() => i(!1), 500)) : o());
|
|
52
|
+
};
|
|
53
|
+
return document.addEventListener("keydown", t), () => document.removeEventListener("keydown", t);
|
|
54
|
+
}, [n, u, o]), !R && !c) return null;
|
|
55
|
+
const a = (t) => {
|
|
56
|
+
if (t.target === t.currentTarget) {
|
|
57
|
+
if (u || !L) {
|
|
58
|
+
i(!0), setTimeout(() => i(!1), 500);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
o();
|
|
62
|
+
}
|
|
63
|
+
}, s = P[l], b = h ? "0" : N ?? D[l];
|
|
64
|
+
return /* @__PURE__ */ e(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
className: "prui-modal-overlay fixed inset-0 z-[10000] flex justify-center overflow-y-auto p-4",
|
|
68
|
+
style: {
|
|
69
|
+
alignItems: "flex-start",
|
|
70
|
+
paddingTop: "10vh",
|
|
71
|
+
backgroundColor: "rgba(0, 0, 0, 0.55)",
|
|
72
|
+
backdropFilter: "blur(4px)",
|
|
73
|
+
opacity: c ? 1 : 0,
|
|
74
|
+
transition: "opacity 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)"
|
|
75
|
+
},
|
|
76
|
+
onClick: a,
|
|
77
|
+
onMouseDown: (t) => {
|
|
78
|
+
t.target === t.currentTarget && a(t);
|
|
79
|
+
},
|
|
80
|
+
children: /* @__PURE__ */ d(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
ref: C,
|
|
84
|
+
role: "dialog",
|
|
85
|
+
"aria-modal": "true",
|
|
86
|
+
"aria-label": x,
|
|
87
|
+
className: Y(
|
|
88
|
+
"prui-modal-content relative h-fit m-auto w-full",
|
|
89
|
+
w && "prui-modal-shake",
|
|
90
|
+
k
|
|
91
|
+
),
|
|
92
|
+
style: {
|
|
93
|
+
width: s.width,
|
|
94
|
+
minWidth: s.minWidth,
|
|
95
|
+
maxWidth: E ?? s.width,
|
|
96
|
+
padding: b,
|
|
97
|
+
backgroundColor: "var(--prui-surface)",
|
|
98
|
+
border: "1px solid var(--prui-line)",
|
|
99
|
+
borderRadius: "var(--prui-radius-3)",
|
|
100
|
+
boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.2)",
|
|
101
|
+
color: "var(--prui-fg)",
|
|
102
|
+
transform: c ? "scale(1) translateY(0)" : "scale(0.95) translateY(8px)",
|
|
103
|
+
opacity: c ? 1 : 0,
|
|
104
|
+
transition: "transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), opacity 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)"
|
|
105
|
+
},
|
|
106
|
+
onTransitionEnd: () => {
|
|
107
|
+
n || g(!1);
|
|
108
|
+
},
|
|
109
|
+
children: [
|
|
110
|
+
M && !u ? /* @__PURE__ */ e(
|
|
111
|
+
"button",
|
|
112
|
+
{
|
|
113
|
+
type: "button",
|
|
114
|
+
onClick: o,
|
|
115
|
+
"aria-label": "Close modal",
|
|
116
|
+
className: "absolute right-4 top-4 flex h-10 w-10 cursor-pointer items-center justify-center rounded-[var(--prui-radius)] text-[var(--prui-dim)] transition-all hover:bg-[var(--prui-raise)] hover:text-[var(--prui-fg)]",
|
|
117
|
+
children: /* @__PURE__ */ e(K, { className: "h-4 w-4", "aria-hidden": !0 })
|
|
118
|
+
}
|
|
119
|
+
) : null,
|
|
120
|
+
W
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
O.displayName = "Modal";
|
|
128
|
+
const B = {
|
|
129
|
+
success: "var(--prui-ok)",
|
|
130
|
+
warning: "var(--prui-warn)",
|
|
131
|
+
danger: "var(--prui-danger)",
|
|
132
|
+
error: "var(--prui-danger)",
|
|
133
|
+
info: "var(--prui-brand)",
|
|
134
|
+
default: "var(--prui-brand)"
|
|
135
|
+
}, A = ({ type: n }) => {
|
|
136
|
+
const o = B[n ?? "default"];
|
|
137
|
+
switch (n) {
|
|
138
|
+
case "success":
|
|
139
|
+
return /* @__PURE__ */ d("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: o }, children: [
|
|
140
|
+
/* @__PURE__ */ e("path", { d: "M9 12l2 2 4-4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
141
|
+
/* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" })
|
|
142
|
+
] });
|
|
143
|
+
case "warning":
|
|
144
|
+
return /* @__PURE__ */ e("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: o }, children: /* @__PURE__ */ e("path", { d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.694-.833-2.464 0L4.34 16.5c-.77.833.192 2.5 1.732 2.5z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
145
|
+
case "danger":
|
|
146
|
+
case "error":
|
|
147
|
+
return /* @__PURE__ */ d("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: o }, children: [
|
|
148
|
+
/* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" }),
|
|
149
|
+
/* @__PURE__ */ e("path", { d: "M15 9l-6 6m0-6l6 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
150
|
+
] });
|
|
151
|
+
case "info":
|
|
152
|
+
return /* @__PURE__ */ d("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: o }, children: [
|
|
153
|
+
/* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" }),
|
|
154
|
+
/* @__PURE__ */ e("path", { d: "M12 8v4m0 4h.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
155
|
+
] });
|
|
156
|
+
default:
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function G(n) {
|
|
161
|
+
const { title: o, message: W, confirmText: u = "Confirm", cancelText: L = "Cancel", type: y, size: T = "sm" } = n, S = B[y ?? "default"];
|
|
162
|
+
return new Promise((z) => {
|
|
163
|
+
const f = document.createElement("div");
|
|
164
|
+
document.body.appendChild(f);
|
|
165
|
+
const v = I(f), E = () => {
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
v.unmount(), f.remove();
|
|
168
|
+
}, 320);
|
|
169
|
+
}, N = () => {
|
|
170
|
+
const [h, M] = r.useState(!1), [x, k] = r.useState(!1), [l, R] = r.useState(!1), g = r.useRef(null), c = r.useRef(null);
|
|
171
|
+
r.useEffect(() => {
|
|
172
|
+
const i = setTimeout(() => {
|
|
173
|
+
M(!0), k(!0), document.body.classList.add("modal-open");
|
|
174
|
+
}, 10);
|
|
175
|
+
return () => clearTimeout(i);
|
|
176
|
+
}, []), r.useEffect(() => {
|
|
177
|
+
var C;
|
|
178
|
+
if (!h || l) return;
|
|
179
|
+
(C = c.current) == null || C.focus();
|
|
180
|
+
const i = (a) => {
|
|
181
|
+
if (l) return;
|
|
182
|
+
if (a.key === "Escape") {
|
|
183
|
+
a.preventDefault(), m(!1);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (a.key !== "Tab") return;
|
|
187
|
+
const s = [g.current, c.current].filter((j) => !!j);
|
|
188
|
+
if (!s.length) return;
|
|
189
|
+
const b = s[0], t = s[s.length - 1], p = document.activeElement;
|
|
190
|
+
!p || !s.some((j) => j === p) ? (a.preventDefault(), b.focus()) : a.shiftKey && p === b ? (a.preventDefault(), t.focus()) : !a.shiftKey && p === t && (a.preventDefault(), b.focus());
|
|
191
|
+
};
|
|
192
|
+
return document.addEventListener("keydown", i), () => document.removeEventListener("keydown", i);
|
|
193
|
+
}, [h, l]);
|
|
194
|
+
const m = (i) => {
|
|
195
|
+
R(!0), k(!1), document.body.classList.remove("modal-open"), setTimeout(() => {
|
|
196
|
+
E(), z(i);
|
|
197
|
+
}, 300);
|
|
198
|
+
};
|
|
199
|
+
if (!h) return null;
|
|
200
|
+
const w = P[T];
|
|
201
|
+
return /* @__PURE__ */ e(
|
|
202
|
+
"div",
|
|
203
|
+
{
|
|
204
|
+
className: "prui-modal-overlay fixed inset-0 z-[10001] flex justify-center overflow-y-auto p-4",
|
|
205
|
+
style: {
|
|
206
|
+
alignItems: "flex-start",
|
|
207
|
+
paddingTop: "12vh",
|
|
208
|
+
backgroundColor: "rgba(0, 0, 0, 0.55)",
|
|
209
|
+
backdropFilter: "blur(4px)",
|
|
210
|
+
opacity: x ? 1 : 0,
|
|
211
|
+
transition: "opacity 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)"
|
|
212
|
+
},
|
|
213
|
+
children: /* @__PURE__ */ d(
|
|
214
|
+
"div",
|
|
215
|
+
{
|
|
216
|
+
role: "alertdialog",
|
|
217
|
+
"aria-modal": "true",
|
|
218
|
+
"aria-label": o,
|
|
219
|
+
className: "prui-modal-content relative m-auto w-full",
|
|
220
|
+
style: {
|
|
221
|
+
width: w.width,
|
|
222
|
+
minWidth: w.minWidth,
|
|
223
|
+
backgroundColor: "var(--prui-surface)",
|
|
224
|
+
border: "1px solid var(--prui-line)",
|
|
225
|
+
borderRadius: "var(--prui-radius-3)",
|
|
226
|
+
boxShadow: "0 20px 25px -5px rgba(0,0,0,0.4), 0 10px 10px -5px rgba(0,0,0,0.2)",
|
|
227
|
+
color: "var(--prui-fg)",
|
|
228
|
+
transform: x ? "scale(1) translateY(0)" : "scale(0.95) translateY(8px)",
|
|
229
|
+
opacity: x ? 1 : 0,
|
|
230
|
+
transition: "transform 0.3s cubic-bezier(0.25,0.1,0.25,1), opacity 0.3s cubic-bezier(0.25,0.1,0.25,1)"
|
|
231
|
+
},
|
|
232
|
+
children: [
|
|
233
|
+
/* @__PURE__ */ d("div", { className: "flex items-start gap-3 p-4 pb-2", children: [
|
|
234
|
+
/* @__PURE__ */ e(A, { type: y }),
|
|
235
|
+
/* @__PURE__ */ d("div", { className: "min-w-0", children: [
|
|
236
|
+
/* @__PURE__ */ e("h2", { className: "m-0 text-lg font-semibold leading-normal", style: { color: "var(--prui-fg)" }, children: o }),
|
|
237
|
+
/* @__PURE__ */ e("p", { className: "mt-2 text-sm leading-normal", style: { color: "var(--prui-dim)" }, children: W })
|
|
238
|
+
] })
|
|
239
|
+
] }),
|
|
240
|
+
/* @__PURE__ */ d("div", { className: "flex items-center justify-end gap-3 px-4 pb-4", children: [
|
|
241
|
+
/* @__PURE__ */ e(
|
|
242
|
+
"button",
|
|
243
|
+
{
|
|
244
|
+
type: "button",
|
|
245
|
+
ref: g,
|
|
246
|
+
disabled: l,
|
|
247
|
+
onClick: () => m(!1),
|
|
248
|
+
className: "cursor-pointer rounded-[var(--prui-radius)] border px-4 py-2 text-sm font-medium transition-all disabled:opacity-60",
|
|
249
|
+
style: { background: "transparent", borderColor: "var(--prui-line)", color: "var(--prui-fg)" },
|
|
250
|
+
children: L
|
|
251
|
+
}
|
|
252
|
+
),
|
|
253
|
+
/* @__PURE__ */ e(
|
|
254
|
+
"button",
|
|
255
|
+
{
|
|
256
|
+
type: "button",
|
|
257
|
+
ref: c,
|
|
258
|
+
disabled: l,
|
|
259
|
+
onClick: () => m(!0),
|
|
260
|
+
className: "cursor-pointer rounded-[var(--prui-radius)] border border-transparent px-4 py-2 text-sm font-medium text-white transition-all disabled:opacity-60",
|
|
261
|
+
style: { backgroundColor: S },
|
|
262
|
+
children: u
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] })
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
};
|
|
272
|
+
v.render(/* @__PURE__ */ e(N, {}));
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
const H = {
|
|
276
|
+
name: "Modal",
|
|
277
|
+
props: [
|
|
278
|
+
{ name: "open", type: "boolean", default: null, control: "boolean" },
|
|
279
|
+
{ name: "onClose", type: "() => void", default: null, control: "none" },
|
|
280
|
+
{ name: "size", type: "'xs' | 'sm' | 'md' | 'lg' | 'xl'", default: "'md'", control: "select", options: ["xs", "sm", "md", "lg", "xl"] },
|
|
281
|
+
{ name: "closeOnOverlayClick", type: "boolean", default: "true", control: "boolean" },
|
|
282
|
+
{ name: "disableDefaultClose", type: "boolean", default: "false", control: "boolean" },
|
|
283
|
+
{ name: "noPadding", type: "boolean", default: "false", control: "boolean" },
|
|
284
|
+
{ name: "showCloseButton", type: "boolean", default: "true", control: "boolean" },
|
|
285
|
+
{ name: "padding", type: "string (CSS)", default: "per-size", control: "text" },
|
|
286
|
+
{ name: "maxWidth", type: "string (CSS)", default: "per-size", control: "text" }
|
|
287
|
+
]
|
|
288
|
+
}, J = {
|
|
289
|
+
name: "confirmModal",
|
|
290
|
+
props: [
|
|
291
|
+
{ name: "title", type: "string", default: null, control: "text" },
|
|
292
|
+
{ name: "message", type: "string", default: null, control: "textarea" },
|
|
293
|
+
{ name: "confirmText", type: "string", default: "'Confirm'", control: "text" },
|
|
294
|
+
{ name: "cancelText", type: "string", default: "'Cancel'", control: "text" },
|
|
295
|
+
{ name: "type", type: "'success' | 'warning' | 'danger' | 'error' | 'info'", default: "undefined", control: "select", options: ["success", "warning", "danger", "error", "info"] }
|
|
296
|
+
]
|
|
297
|
+
};
|
|
298
|
+
export {
|
|
299
|
+
O as Modal,
|
|
300
|
+
G as confirmModal,
|
|
301
|
+
J as confirmModalPropsMeta,
|
|
302
|
+
H as modalPropsMeta
|
|
303
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prop metadata system.
|
|
3
|
+
* Every PRUI component exports a propsMeta declaration describing its props,
|
|
4
|
+
* types, defaults, and control hints. This is the single source that drives
|
|
5
|
+
* docs tables, playground controls, and generated snippets later.
|
|
6
|
+
*/
|
|
7
|
+
export type PropControl = "text" | "textarea" | "number" | "boolean" | "select" | "multiselect" | "color" | "date" | "daterange" | "icon" | "object" | "none";
|
|
8
|
+
export interface PropMeta {
|
|
9
|
+
/** Prop name as written in JSX. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Human-readable type label, e.g. "'primary' | 'default'". */
|
|
12
|
+
type: string;
|
|
13
|
+
/** Default value rendered into snippets; null when required. */
|
|
14
|
+
default: string | number | boolean | null;
|
|
15
|
+
/** Control hint for the playground. "none" hides the control. */
|
|
16
|
+
control: PropControl;
|
|
17
|
+
/** Options for select/multiselect controls. */
|
|
18
|
+
options?: readonly string[];
|
|
19
|
+
/** Short description for docs tables. */
|
|
20
|
+
description?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PropsMeta {
|
|
23
|
+
/** Component name, e.g. "Button". */
|
|
24
|
+
name: string;
|
|
25
|
+
props: readonly PropMeta[];
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PropsMeta } from './props-meta';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export interface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** Max height in px before scrolling. */
|
|
5
|
+
maxHeight?: number | string;
|
|
6
|
+
}
|
|
7
|
+
export declare const ScrollArea: React.ForwardRefExoticComponent<ScrollAreaProps & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export declare const scrollAreaPropsMeta: PropsMeta;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import * as n from "react";
|
|
3
|
+
import { cn as c } from "./cn.js";
|
|
4
|
+
const m = n.forwardRef(
|
|
5
|
+
({ className: r, maxHeight: e, children: o, ...a }, l) => /* @__PURE__ */ t(
|
|
6
|
+
"div",
|
|
7
|
+
{
|
|
8
|
+
ref: l,
|
|
9
|
+
className: c("prui-scroll-area relative overflow-y-auto", r),
|
|
10
|
+
style: e !== void 0 ? { maxHeight: e } : void 0,
|
|
11
|
+
...a,
|
|
12
|
+
children: o
|
|
13
|
+
}
|
|
14
|
+
)
|
|
15
|
+
);
|
|
16
|
+
m.displayName = "ScrollArea";
|
|
17
|
+
const d = {
|
|
18
|
+
name: "ScrollArea",
|
|
19
|
+
props: [
|
|
20
|
+
{ name: "maxHeight", type: "number | string", default: "undefined", control: "number" },
|
|
21
|
+
{ name: "children", type: "ReactNode", default: null, control: "text" }
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
m as ScrollArea,
|
|
26
|
+
d as scrollAreaPropsMeta
|
|
27
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { PropsMeta } from './props-meta';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export interface SelectOption {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value"> {
|
|
9
|
+
options?: SelectOption[];
|
|
10
|
+
value?: string;
|
|
11
|
+
defaultValue?: string;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
name?: string;
|
|
15
|
+
onChange?: (value: string) => void;
|
|
16
|
+
onOpenChange?: (open: boolean) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare const Select: {
|
|
19
|
+
({ options, value: valueProp, defaultValue, placeholder, disabled, name, onChange, onOpenChange, children, }: SelectProps): React.JSX.Element;
|
|
20
|
+
displayName: string;
|
|
21
|
+
};
|
|
22
|
+
export type SelectTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
23
|
+
export declare const SelectTrigger: React.ForwardRefExoticComponent<SelectTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
24
|
+
export interface SelectValueProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare const SelectValue: React.ForwardRefExoticComponent<SelectValueProps & React.RefAttributes<HTMLSpanElement>>;
|
|
28
|
+
export type SelectContentProps = React.HTMLAttributes<HTMLDivElement>;
|
|
29
|
+
export declare const SelectContent: React.ForwardRefExoticComponent<SelectContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
30
|
+
export type SelectItemProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
31
|
+
value: string;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
};
|
|
34
|
+
export declare const SelectItem: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
35
|
+
value: string;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
38
|
+
export declare const selectPropsMeta: PropsMeta;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { jsxs as b, jsx as s, Fragment as O } from "react/jsx-runtime";
|
|
2
|
+
import * as o from "react";
|
|
3
|
+
import { ChevronDown as E, Check as P } from "lucide-react";
|
|
4
|
+
import { cn as m } from "./cn.js";
|
|
5
|
+
const S = o.createContext(null);
|
|
6
|
+
function g() {
|
|
7
|
+
const r = o.useContext(S);
|
|
8
|
+
if (!r) throw new Error("Select parts must be used inside <Select>");
|
|
9
|
+
return r;
|
|
10
|
+
}
|
|
11
|
+
const z = ({
|
|
12
|
+
options: r,
|
|
13
|
+
value: a,
|
|
14
|
+
defaultValue: t,
|
|
15
|
+
placeholder: i = "Select...",
|
|
16
|
+
disabled: e,
|
|
17
|
+
name: d,
|
|
18
|
+
onChange: c,
|
|
19
|
+
onOpenChange: l,
|
|
20
|
+
children: f
|
|
21
|
+
}) => {
|
|
22
|
+
const [p, u] = o.useState(t ?? ""), [v, I] = o.useState(!1), [R, T] = o.useState(), x = a !== void 0 ? a : p, V = (n) => {
|
|
23
|
+
a === void 0 && u(n), c == null || c(n);
|
|
24
|
+
}, j = (n) => {
|
|
25
|
+
I(n), l == null || l(n);
|
|
26
|
+
};
|
|
27
|
+
return /* @__PURE__ */ b(
|
|
28
|
+
S.Provider,
|
|
29
|
+
{
|
|
30
|
+
value: { value: x, open: v, triggerId: R, setValue: V, setOpen: j, registerTrigger: T },
|
|
31
|
+
children: [
|
|
32
|
+
d ? /* @__PURE__ */ s("input", { type: "hidden", name: d, value: x }) : null,
|
|
33
|
+
f ?? /* @__PURE__ */ b(O, { children: [
|
|
34
|
+
/* @__PURE__ */ s(h, { disabled: e, children: /* @__PURE__ */ s(y, { placeholder: i }) }),
|
|
35
|
+
/* @__PURE__ */ s(w, { children: (r ?? []).map((n) => /* @__PURE__ */ s(N, { value: n.value, disabled: n.disabled, children: n.label }, n.value)) })
|
|
36
|
+
] })
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
z.displayName = "Select";
|
|
42
|
+
const h = o.forwardRef(
|
|
43
|
+
({ className: r, children: a, onClick: t, disabled: i, id: e, ...d }, c) => {
|
|
44
|
+
const { open: l, setOpen: f, registerTrigger: p } = g();
|
|
45
|
+
return o.useEffect(() => {
|
|
46
|
+
e && p(e);
|
|
47
|
+
}, [e, p]), /* @__PURE__ */ b(
|
|
48
|
+
"button",
|
|
49
|
+
{
|
|
50
|
+
ref: c,
|
|
51
|
+
id: e,
|
|
52
|
+
type: "button",
|
|
53
|
+
role: "combobox",
|
|
54
|
+
"aria-expanded": l,
|
|
55
|
+
"aria-haspopup": "listbox",
|
|
56
|
+
disabled: i,
|
|
57
|
+
"data-state": l ? "open" : "closed",
|
|
58
|
+
className: m(
|
|
59
|
+
"prui-select-trigger flex h-9 w-full items-center justify-between gap-2 border border-[var(--prui-line)]",
|
|
60
|
+
"bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)]",
|
|
61
|
+
"outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
|
|
62
|
+
"disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer",
|
|
63
|
+
r
|
|
64
|
+
),
|
|
65
|
+
onClick: (u) => {
|
|
66
|
+
t == null || t(u), u.defaultPrevented || f(!l);
|
|
67
|
+
},
|
|
68
|
+
...d,
|
|
69
|
+
children: [
|
|
70
|
+
a,
|
|
71
|
+
/* @__PURE__ */ s(E, { className: m("h-4 w-4 shrink-0 text-[var(--prui-dim)] transition-transform", l && "rotate-180"), "aria-hidden": !0 })
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
h.displayName = "SelectTrigger";
|
|
78
|
+
const y = o.forwardRef(
|
|
79
|
+
({ className: r, placeholder: a, children: t, ...i }, e) => {
|
|
80
|
+
const { value: d } = g();
|
|
81
|
+
return /* @__PURE__ */ s("span", { ref: e, className: m("truncate", r), ...i, children: t ?? (d || /* @__PURE__ */ s("span", { className: "text-[var(--prui-dim)]", children: a })) });
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
y.displayName = "SelectValue";
|
|
85
|
+
const w = o.forwardRef(
|
|
86
|
+
({ className: r, children: a, ...t }, i) => {
|
|
87
|
+
const { open: e, setOpen: d, triggerId: c } = g();
|
|
88
|
+
return e ? /* @__PURE__ */ s(
|
|
89
|
+
"div",
|
|
90
|
+
{
|
|
91
|
+
ref: i,
|
|
92
|
+
role: "listbox",
|
|
93
|
+
"aria-labelledby": c,
|
|
94
|
+
tabIndex: -1,
|
|
95
|
+
"data-state": e ? "open" : "closed",
|
|
96
|
+
className: m(
|
|
97
|
+
"prui-select-content absolute z-50 mt-1 min-w-40 max-h-60 overflow-auto p-1",
|
|
98
|
+
"bg-[var(--prui-surface)] border border-[var(--prui-line)] rounded-[var(--prui-radius)] shadow-lg",
|
|
99
|
+
r
|
|
100
|
+
),
|
|
101
|
+
...t,
|
|
102
|
+
children: a
|
|
103
|
+
}
|
|
104
|
+
) : null;
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
w.displayName = "SelectContent";
|
|
108
|
+
const N = o.forwardRef(
|
|
109
|
+
({ className: r, value: a, disabled: t, children: i, onClick: e, ...d }, c) => {
|
|
110
|
+
const { value: l, setValue: f, setOpen: p } = g(), u = l === a;
|
|
111
|
+
return /* @__PURE__ */ b(
|
|
112
|
+
"div",
|
|
113
|
+
{
|
|
114
|
+
ref: c,
|
|
115
|
+
role: "option",
|
|
116
|
+
"aria-selected": u,
|
|
117
|
+
"aria-disabled": t,
|
|
118
|
+
"data-selected": u || void 0,
|
|
119
|
+
className: m(
|
|
120
|
+
"prui-select-item relative flex cursor-pointer items-center gap-2 rounded-[calc(var(--prui-radius)-1px)]",
|
|
121
|
+
"py-1.5 pl-3 pr-8 text-sm text-[var(--prui-fg)] hover:bg-[var(--prui-raise)]",
|
|
122
|
+
u && "font-medium",
|
|
123
|
+
t && "opacity-50 pointer-events-none",
|
|
124
|
+
r
|
|
125
|
+
),
|
|
126
|
+
onClick: (v) => {
|
|
127
|
+
e == null || e(v), !(v.defaultPrevented || t) && (f(a), p(!1));
|
|
128
|
+
},
|
|
129
|
+
...d,
|
|
130
|
+
children: [
|
|
131
|
+
i,
|
|
132
|
+
u ? /* @__PURE__ */ s(P, { className: "absolute right-2 h-4 w-4 text-[var(--prui-brand)]", "aria-hidden": !0 }) : null
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
N.displayName = "SelectItem";
|
|
139
|
+
const U = {
|
|
140
|
+
name: "Select",
|
|
141
|
+
props: [
|
|
142
|
+
{ name: "options", type: "SelectOption[]", default: "[]", control: "object" },
|
|
143
|
+
{ name: "value", type: "string", default: "undefined", control: "text" },
|
|
144
|
+
{ name: "defaultValue", type: "string", default: "undefined", control: "text" },
|
|
145
|
+
{ name: "placeholder", type: "string", default: "'Select...'", control: "text" },
|
|
146
|
+
{ name: "disabled", type: "boolean", default: "false", control: "boolean" },
|
|
147
|
+
{ name: "onChange", type: "(value: string) => void", default: null, control: "none" }
|
|
148
|
+
]
|
|
149
|
+
};
|
|
150
|
+
export {
|
|
151
|
+
z as Select,
|
|
152
|
+
w as SelectContent,
|
|
153
|
+
N as SelectItem,
|
|
154
|
+
h as SelectTrigger,
|
|
155
|
+
y as SelectValue,
|
|
156
|
+
U as selectPropsMeta
|
|
157
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PropsMeta } from './props-meta';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export interface SwitchProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange"> {
|
|
4
|
+
checked?: boolean;
|
|
5
|
+
defaultChecked?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
onChange?: (checked: boolean) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const Switch: React.ForwardRefExoticComponent<SwitchProps & React.RefAttributes<HTMLButtonElement>>;
|
|
10
|
+
export declare const switchPropsMeta: PropsMeta;
|