react-os-shell 4.31.0 → 4.54.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/{Browser-63NYU74S.js → Browser-5NHZNED2.js} +6 -6
- package/dist/{Browser-63NYU74S.js.map → Browser-5NHZNED2.js.map} +1 -1
- package/dist/{Calculator-XERXEV35.js → Calculator-PHKNMRLX.js} +5 -5
- package/dist/{Calculator-XERXEV35.js.map → Calculator-PHKNMRLX.js.map} +1 -1
- package/dist/{CurrencyConverter-OSZISLHT.js → CurrencyConverter-MEG7RHEK.js} +5 -5
- package/dist/{CurrencyConverter-OSZISLHT.js.map → CurrencyConverter-MEG7RHEK.js.map} +1 -1
- package/dist/{Documents-YP4GBBRF.js → Documents-YOUMLERR.js} +7 -7
- package/dist/{Documents-YP4GBBRF.js.map → Documents-YOUMLERR.js.map} +1 -1
- package/dist/{Files-6JWIE3VH.js → Files-4NQ5IFUE.js} +8 -8
- package/dist/{Files-6JWIE3VH.js.map → Files-4NQ5IFUE.js.map} +1 -1
- package/dist/{Notepad-EHO56UNK.js → Notepad-UHTEKEEM.js} +7 -7
- package/dist/{Notepad-EHO56UNK.js.map → Notepad-UHTEKEEM.js.map} +1 -1
- package/dist/{PomodoroTimer-5ZSIG7SQ.js → PomodoroTimer-5B5AFXQH.js} +7 -7
- package/dist/{PomodoroTimer-5ZSIG7SQ.js.map → PomodoroTimer-5B5AFXQH.js.map} +1 -1
- package/dist/{Preview-67IPCMSN.js → Preview-2CCBN25S.js} +8 -8
- package/dist/{Preview-67IPCMSN.js.map → Preview-2CCBN25S.js.map} +1 -1
- package/dist/{Spreadsheet-HVXBAFR7.js → Spreadsheet-2N6TMVQU.js} +6 -6
- package/dist/{Spreadsheet-HVXBAFR7.js.map → Spreadsheet-2N6TMVQU.js.map} +1 -1
- package/dist/{Stock-4BORXILI.js → Stock-KTWRNBI6.js} +5 -5
- package/dist/{Stock-4BORXILI.js.map → Stock-KTWRNBI6.js.map} +1 -1
- package/dist/{Weather-ZPPSEUIY.js → Weather-B7MO7N4N.js} +5 -5
- package/dist/{Weather-ZPPSEUIY.js.map → Weather-B7MO7N4N.js.map} +1 -1
- package/dist/{WorldClock-LBKYWDWE.js → WorldClock-M5MEV74F.js} +5 -5
- package/dist/{WorldClock-LBKYWDWE.js.map → WorldClock-M5MEV74F.js.map} +1 -1
- package/dist/apps/index.js +16 -16
- package/dist/{chunk-22BNPLM4.js → chunk-3OCL3DB4.js} +3 -3
- package/dist/{chunk-22BNPLM4.js.map → chunk-3OCL3DB4.js.map} +1 -1
- package/dist/{chunk-7NIFBQUX.js → chunk-3SUSQHOW.js} +492 -118
- package/dist/chunk-3SUSQHOW.js.map +1 -0
- package/dist/{chunk-GUWAKATU.js → chunk-5S65ZC5W.js} +3 -3
- package/dist/{chunk-GUWAKATU.js.map → chunk-5S65ZC5W.js.map} +1 -1
- package/dist/{chunk-BT3EQNH3.js → chunk-BIZJ7RLC.js} +4 -4
- package/dist/{chunk-BT3EQNH3.js.map → chunk-BIZJ7RLC.js.map} +1 -1
- package/dist/{chunk-X5PZYTAK.js → chunk-ECE3B3FZ.js} +3 -3
- package/dist/{chunk-X5PZYTAK.js.map → chunk-ECE3B3FZ.js.map} +1 -1
- package/dist/{chunk-X6DOWIY2.js → chunk-FHPPPDHL.js} +3 -3
- package/dist/{chunk-X6DOWIY2.js.map → chunk-FHPPPDHL.js.map} +1 -1
- package/dist/{chunk-OI253GOA.js → chunk-IOCOH2QQ.js} +4 -4
- package/dist/{chunk-OI253GOA.js.map → chunk-IOCOH2QQ.js.map} +1 -1
- package/dist/{chunk-4AKVHY4B.js → chunk-TK6HI2U4.js} +23 -3
- package/dist/chunk-TK6HI2U4.js.map +1 -0
- package/dist/chunk-XVXEYKMT.js +7 -0
- package/dist/{chunk-SGS3IQEL.js.map → chunk-XVXEYKMT.js.map} +1 -1
- package/dist/{chunk-C22EFSND.js → chunk-ZCDFNZQS.js} +21 -6
- package/dist/chunk-ZCDFNZQS.js.map +1 -0
- package/dist/{index-CdxMm6Dk.d.ts → index-B6QGa8SJ.d.ts} +293 -38
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -14
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +4 -4
- package/dist/ui.css +117 -43
- package/package.json +1 -1
- package/dist/chunk-4AKVHY4B.js.map +0 -1
- package/dist/chunk-7NIFBQUX.js.map +0 -1
- package/dist/chunk-C22EFSND.js.map +0 -1
- package/dist/chunk-SGS3IQEL.js +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Breadcrumbs } from './chunk-HNH7FOYB.js';
|
|
2
2
|
import { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
3
|
-
import { useIsMobile, useShellPrefs } from './chunk-
|
|
3
|
+
import { useIsMobile, PopupMenu, PopupMenuItem, useShellPrefs } from './chunk-ZCDFNZQS.js';
|
|
4
4
|
import { registerModalEscapeInterceptor, useFocusTrap, useScrollLock } from './chunk-OXLLRKBC.js';
|
|
5
5
|
import { glassStyle } from './chunk-3CUSBZWG.js';
|
|
6
6
|
import { forwardRef, useId, useCallback, useState, useRef, useEffect, createContext, useLayoutEffect, useMemo, Children, isValidElement, cloneElement, useContext, Fragment as Fragment$1, useSyncExternalStore } from 'react';
|
|
@@ -13,11 +13,27 @@ var BUTTON_VARIANTS = {
|
|
|
13
13
|
secondary: "border border-gray-300 bg-white text-gray-700 shadow-sm hover:bg-gray-50 focus:ring-blue-400/30",
|
|
14
14
|
ghost: "text-gray-700 hover:bg-gray-100 focus:ring-blue-400/30",
|
|
15
15
|
"ghost-danger": "text-red-600 hover:bg-red-50 focus:ring-red-400/30",
|
|
16
|
-
danger: "bg-red-600 text-white shadow-sm hover:bg-red-700 focus:ring-red-400/40"
|
|
16
|
+
danger: "bg-red-600 text-white shadow-sm hover:bg-red-700 focus:ring-red-400/40",
|
|
17
|
+
/**
|
|
18
|
+
* A button that reads as a link: no box, no padding, underlined on hover.
|
|
19
|
+
* For an action that belongs in running text or beside a field — "Forgot
|
|
20
|
+
* your password?", "Use a different address" — where a boxed button would
|
|
21
|
+
* claim more of the page than the action deserves.
|
|
22
|
+
*
|
|
23
|
+
* It is still a <button>. Anything that NAVIGATES should be an anchor, so it
|
|
24
|
+
* can be middle-clicked and read off the status bar; this is for actions
|
|
25
|
+
* that merely look quiet.
|
|
26
|
+
*/
|
|
27
|
+
link: "text-blue-600 underline-offset-4 hover:underline focus:ring-blue-400/30"
|
|
17
28
|
};
|
|
18
29
|
var SIZES = {
|
|
19
30
|
sm: "gap-1 px-2.5 py-1 text-xs",
|
|
20
31
|
md: "gap-1.5 px-3 py-1.5 text-sm",
|
|
32
|
+
// `py-2.5`, not `py-2`: this rung has to come out 40px to match IconButton's
|
|
33
|
+
// `h-10`, which is the promise IconButton's docblock makes for every rung.
|
|
34
|
+
// `py-2` gives 36px (20px line box + 8px twice) and puts a 4px step between a
|
|
35
|
+
// Button and an IconButton sitting in the same row.
|
|
36
|
+
lg: "gap-2 px-4 py-2.5 text-sm",
|
|
21
37
|
// 44px is the WCAG 2.5.5 floor, and a floor is not a comfortable size. Use it
|
|
22
38
|
// ONLY for chrome that sits outside the task — switching screens, ending a
|
|
23
39
|
// shift — and never on the path someone is actually working through. It
|
|
@@ -31,6 +47,16 @@ var SIZES = {
|
|
|
31
47
|
"touch-xl": "gap-3 h-20 px-8 text-2xl"
|
|
32
48
|
// 80px — keypad keys, tender
|
|
33
49
|
};
|
|
50
|
+
var LINK_BASE = "inline-flex items-center font-medium transition-colors focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-60";
|
|
51
|
+
var LINK_SIZES = {
|
|
52
|
+
sm: "gap-1 text-xs",
|
|
53
|
+
md: "gap-1.5 text-sm",
|
|
54
|
+
lg: "gap-2 text-sm",
|
|
55
|
+
"touch-sm": "gap-1.5 text-base",
|
|
56
|
+
"touch": "gap-2 text-base",
|
|
57
|
+
"touch-lg": "gap-2 text-lg",
|
|
58
|
+
"touch-xl": "gap-3 text-2xl"
|
|
59
|
+
};
|
|
34
60
|
function Spinner() {
|
|
35
61
|
return /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
36
62
|
/* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
@@ -63,7 +89,18 @@ var Button = forwardRef(function Button2({
|
|
|
63
89
|
disabled: isDisabled,
|
|
64
90
|
"aria-busy": loading || void 0,
|
|
65
91
|
"aria-describedby": reasonId,
|
|
66
|
-
className: [
|
|
92
|
+
className: [
|
|
93
|
+
// `link` takes the base WITHOUT the box: no rounding, no padding from
|
|
94
|
+
// the size table. It cannot cancel those by overriding — two padding
|
|
95
|
+
// utilities in one class attribute resolve by compiled-stylesheet
|
|
96
|
+
// order, not by the order they were written — so it never receives
|
|
97
|
+
// them, and keeps only the size's gap and text size.
|
|
98
|
+
variant === "link" ? LINK_BASE : BUTTON_BASE,
|
|
99
|
+
BUTTON_VARIANTS[variant],
|
|
100
|
+
variant === "link" ? LINK_SIZES[size] : SIZES[size],
|
|
101
|
+
block ? "w-full" : "",
|
|
102
|
+
className
|
|
103
|
+
].filter(Boolean).join(" "),
|
|
67
104
|
...rest,
|
|
68
105
|
children: [
|
|
69
106
|
loading ? /* @__PURE__ */ jsx(Spinner, {}) : leftIcon,
|
|
@@ -82,6 +119,7 @@ var Button_default = Button;
|
|
|
82
119
|
var SQUARE = {
|
|
83
120
|
sm: "h-6 w-6",
|
|
84
121
|
md: "h-8 w-8",
|
|
122
|
+
lg: "h-10 w-10",
|
|
85
123
|
"touch-sm": "h-11 w-11",
|
|
86
124
|
"touch": "h-14 w-14",
|
|
87
125
|
"touch-lg": "h-16 w-16",
|
|
@@ -105,7 +143,12 @@ var IconButton_default = IconButton;
|
|
|
105
143
|
var INPUT_SHAPE_PRE = "block w-full rounded-md border border-gray-300 bg-white";
|
|
106
144
|
var INPUT_SHAPE_POST = "text-gray-800 placeholder:text-gray-400 shadow-sm focus:border-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-400/30";
|
|
107
145
|
var INPUT_SIZES = {
|
|
146
|
+
// The desktop rungs carry no explicit height: a text control's height should
|
|
147
|
+
// follow its own font, or a long label wraps out of a box that was pinned.
|
|
148
|
+
// The touch rung does carry one, for the same reason Button's does.
|
|
149
|
+
sm: "px-2.5 py-1 text-xs",
|
|
108
150
|
md: "px-3 py-1.5 text-sm",
|
|
151
|
+
lg: "px-3.5 py-2 text-base",
|
|
109
152
|
// 56px, matching Button's `touch`. `text-base` is 16px BY AGREEMENT with the
|
|
110
153
|
// rule in ui.css that forces `font-size: 16px !important` on every form
|
|
111
154
|
// control under `(pointer: coarse)` — the rule that stops iOS zooming the
|
|
@@ -130,6 +173,7 @@ var Input = forwardRef(function Input2({ invalid, leftIcon, rightAdornment, size
|
|
|
130
173
|
"input",
|
|
131
174
|
{
|
|
132
175
|
ref,
|
|
176
|
+
"aria-invalid": invalid || void 0,
|
|
133
177
|
className: inputClasses({ invalid, size, className: [pad2, className].filter(Boolean).join(" ") }),
|
|
134
178
|
...rest
|
|
135
179
|
}
|
|
@@ -143,7 +187,7 @@ var Input = forwardRef(function Input2({ invalid, leftIcon, rightAdornment, size
|
|
|
143
187
|
] });
|
|
144
188
|
});
|
|
145
189
|
var Input_default = Input;
|
|
146
|
-
var Textarea = forwardRef(function Textarea2({ invalid, autoGrow, className = "", onInput, rows = 3, ...rest }, ref) {
|
|
190
|
+
var Textarea = forwardRef(function Textarea2({ invalid, autoGrow, className = "", onInput, rows = 3, size, ...rest }, ref) {
|
|
147
191
|
const handleInput = useCallback((e) => {
|
|
148
192
|
if (autoGrow) {
|
|
149
193
|
const el = e.currentTarget;
|
|
@@ -156,9 +200,10 @@ var Textarea = forwardRef(function Textarea2({ invalid, autoGrow, className = ""
|
|
|
156
200
|
"textarea",
|
|
157
201
|
{
|
|
158
202
|
ref,
|
|
203
|
+
"aria-invalid": invalid || void 0,
|
|
159
204
|
rows,
|
|
160
205
|
onInput: handleInput,
|
|
161
|
-
className: inputClasses({ invalid, className: `${autoGrow ? "resize-none overflow-hidden" : ""} ${className}`.trim() }),
|
|
206
|
+
className: inputClasses({ invalid, size, className: `${autoGrow ? "resize-none overflow-hidden" : ""} ${className}`.trim() }),
|
|
162
207
|
...rest
|
|
163
208
|
}
|
|
164
209
|
);
|
|
@@ -201,14 +246,15 @@ function matchTypeahead(options, buffer, fromIndex) {
|
|
|
201
246
|
var MENU_GAP = 4;
|
|
202
247
|
var VIEWPORT_MARGIN = 8;
|
|
203
248
|
var MENU_MAX_HEIGHT = 240;
|
|
204
|
-
var NativeSelect = forwardRef(function NativeSelect2({ value, onChange, options, placeholder, invalid, className = "", ...rest }, ref) {
|
|
249
|
+
var NativeSelect = forwardRef(function NativeSelect2({ value, onChange, options, placeholder, invalid, className = "", size, ...rest }, ref) {
|
|
205
250
|
return /* @__PURE__ */ jsxs(
|
|
206
251
|
"select",
|
|
207
252
|
{
|
|
208
253
|
ref,
|
|
209
254
|
value,
|
|
210
255
|
onChange: (e) => onChange(e.target.value),
|
|
211
|
-
|
|
256
|
+
"aria-invalid": invalid || void 0,
|
|
257
|
+
className: inputClasses({ invalid, size, className: `pr-8 ${className}`.trim() }),
|
|
212
258
|
...rest,
|
|
213
259
|
children: [
|
|
214
260
|
placeholder !== void 0 && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: placeholder }),
|
|
@@ -257,7 +303,21 @@ function useAnchoredPosition(triggerRef, open) {
|
|
|
257
303
|
}, [open, triggerRef]);
|
|
258
304
|
return pos;
|
|
259
305
|
}
|
|
260
|
-
var ListboxSelect = forwardRef(function ListboxSelect2({
|
|
306
|
+
var ListboxSelect = forwardRef(function ListboxSelect2({
|
|
307
|
+
value,
|
|
308
|
+
onChange,
|
|
309
|
+
options,
|
|
310
|
+
placeholder,
|
|
311
|
+
invalid,
|
|
312
|
+
className = "",
|
|
313
|
+
id,
|
|
314
|
+
disabled,
|
|
315
|
+
size,
|
|
316
|
+
"aria-describedby": describedBy,
|
|
317
|
+
"aria-label": ariaLabel,
|
|
318
|
+
"aria-labelledby": labelledBy,
|
|
319
|
+
...rest
|
|
320
|
+
}, ref) {
|
|
261
321
|
const [open, setOpen] = useState(false);
|
|
262
322
|
const [active, setActive] = useState(-1);
|
|
263
323
|
const wrapRef = useRef(null);
|
|
@@ -391,10 +451,13 @@ var ListboxSelect = forwardRef(function ListboxSelect2({ value, onChange, option
|
|
|
391
451
|
"aria-controls": open ? listboxId : void 0,
|
|
392
452
|
"aria-activedescendant": open && active >= 0 ? optionId(active) : void 0,
|
|
393
453
|
"aria-invalid": invalid || void 0,
|
|
454
|
+
"aria-describedby": describedBy,
|
|
455
|
+
"aria-label": ariaLabel,
|
|
456
|
+
"aria-labelledby": labelledBy,
|
|
394
457
|
disabled,
|
|
395
458
|
onClick: () => open ? close() : openList(),
|
|
396
459
|
onKeyDown,
|
|
397
|
-
className: inputClasses({ invalid, className: `pr-8 text-left ${className}`.trim() }),
|
|
460
|
+
className: inputClasses({ invalid, size, className: `pr-8 text-left ${className}`.trim() }),
|
|
398
461
|
children: /* @__PURE__ */ jsx("span", { className: `block truncate ${selectedLabel === void 0 ? "text-gray-400" : ""}`, children: selectedLabel ?? placeholder ?? "\xA0" })
|
|
399
462
|
}
|
|
400
463
|
),
|
|
@@ -556,10 +619,23 @@ function FormField({
|
|
|
556
619
|
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
557
620
|
label && /* @__PURE__ */ jsxs("label", { id: labelId, htmlFor, className: "mb-1 block text-xs font-medium text-gray-600", children: [
|
|
558
621
|
label,
|
|
559
|
-
required && /* @__PURE__ */ jsx("span", { className: "ml-0.5 text-red-500", children: "*" })
|
|
622
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-0.5 text-red-500", children: "*" })
|
|
560
623
|
] }),
|
|
561
624
|
children,
|
|
562
|
-
error ?
|
|
625
|
+
error ? (
|
|
626
|
+
// A validation message appears after the user submits, without focus
|
|
627
|
+
// moving to it. Without a live region it reaches nobody — and this is
|
|
628
|
+
// the one status message a form cannot afford to lose.
|
|
629
|
+
/* @__PURE__ */ jsx(
|
|
630
|
+
"p",
|
|
631
|
+
{
|
|
632
|
+
id: htmlFor ? `${htmlFor}-error` : void 0,
|
|
633
|
+
role: "alert",
|
|
634
|
+
className: "mt-1 text-[11px] text-red-600",
|
|
635
|
+
children: error
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
) : hint ? /* @__PURE__ */ jsx("p", { id: htmlFor ? `${htmlFor}-hint` : void 0, className: "mt-1 text-[11px] text-gray-400", children: hint }) : null
|
|
563
639
|
] });
|
|
564
640
|
}
|
|
565
641
|
function Label({ required, children, className = "", ...rest }) {
|
|
@@ -1413,6 +1489,7 @@ var DatePicker = forwardRef(function DatePicker2({ value, onChange, min, max, in
|
|
|
1413
1489
|
{
|
|
1414
1490
|
ref,
|
|
1415
1491
|
type: "date",
|
|
1492
|
+
"aria-invalid": invalid || void 0,
|
|
1416
1493
|
value: toInputValue(value),
|
|
1417
1494
|
min: toInputValue(min) || void 0,
|
|
1418
1495
|
max: toInputValue(max) || void 0,
|
|
@@ -1701,6 +1778,23 @@ var InputNumber = forwardRef(function InputNumber2({
|
|
|
1701
1778
|
setText(next);
|
|
1702
1779
|
onChange(parse(next));
|
|
1703
1780
|
};
|
|
1781
|
+
const bump = (by) => {
|
|
1782
|
+
const from = parse(textRef.current) ?? 0;
|
|
1783
|
+
let next = from + by;
|
|
1784
|
+
if (min != null && next < min) next = min;
|
|
1785
|
+
if (max != null && next > max) next = max;
|
|
1786
|
+
const places = precision ?? String(step ?? 1).split(".")[1]?.length ?? 0;
|
|
1787
|
+
next = Number(next.toFixed(places));
|
|
1788
|
+
setText(format(next, precision));
|
|
1789
|
+
onChange(next);
|
|
1790
|
+
};
|
|
1791
|
+
const handleKeyDown = (event) => {
|
|
1792
|
+
const unit = step ?? 1;
|
|
1793
|
+
const by = event.key === "ArrowUp" ? unit : event.key === "ArrowDown" ? -unit : event.key === "PageUp" ? unit * 10 : event.key === "PageDown" ? -unit * 10 : null;
|
|
1794
|
+
if (by === null || disabled) return;
|
|
1795
|
+
event.preventDefault();
|
|
1796
|
+
bump(by);
|
|
1797
|
+
};
|
|
1704
1798
|
const handleBlur = () => {
|
|
1705
1799
|
const parsed = parse(text);
|
|
1706
1800
|
if (parsed == null) {
|
|
@@ -1710,6 +1804,7 @@ var InputNumber = forwardRef(function InputNumber2({
|
|
|
1710
1804
|
let v = parsed;
|
|
1711
1805
|
if (min != null && v < min) v = min;
|
|
1712
1806
|
if (max != null && v > max) v = max;
|
|
1807
|
+
if (precision != null) v = Number(v.toFixed(precision));
|
|
1713
1808
|
setText(format(v, precision));
|
|
1714
1809
|
if (v !== parsed) onChange(v);
|
|
1715
1810
|
}
|
|
@@ -1727,8 +1822,14 @@ var InputNumber = forwardRef(function InputNumber2({
|
|
|
1727
1822
|
disabled,
|
|
1728
1823
|
placeholder,
|
|
1729
1824
|
step,
|
|
1825
|
+
role: "spinbutton",
|
|
1826
|
+
"aria-valuenow": value ?? void 0,
|
|
1827
|
+
"aria-valuemin": min,
|
|
1828
|
+
"aria-valuemax": max,
|
|
1829
|
+
"aria-valuetext": value == null ? void 0 : format(value, precision),
|
|
1730
1830
|
"aria-invalid": invalid || void 0,
|
|
1731
1831
|
onChange: (e) => handleChange(e.target.value),
|
|
1832
|
+
onKeyDown: handleKeyDown,
|
|
1732
1833
|
onBlur: handleBlur,
|
|
1733
1834
|
className: inputClasses({
|
|
1734
1835
|
invalid,
|
|
@@ -2104,13 +2205,52 @@ var PADDING = {
|
|
|
2104
2205
|
md: { body: "p-4", edge: "px-4 py-3" },
|
|
2105
2206
|
lg: { body: "p-6", edge: "px-6 py-4" }
|
|
2106
2207
|
};
|
|
2107
|
-
function Card({
|
|
2208
|
+
function Card({
|
|
2209
|
+
children,
|
|
2210
|
+
header,
|
|
2211
|
+
footer,
|
|
2212
|
+
padded = true,
|
|
2213
|
+
padding,
|
|
2214
|
+
headingLevel,
|
|
2215
|
+
headerActions,
|
|
2216
|
+
"aria-label": ariaLabel,
|
|
2217
|
+
className = "",
|
|
2218
|
+
bodyClassName = "",
|
|
2219
|
+
style
|
|
2220
|
+
}) {
|
|
2108
2221
|
const p = PADDING[padding ?? (padded ? "md" : "none")];
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2222
|
+
const headingId = useId();
|
|
2223
|
+
const titled = headingLevel != null && header != null;
|
|
2224
|
+
const Heading = `h${headingLevel}`;
|
|
2225
|
+
const named = titled || ariaLabel != null && ariaLabel !== "";
|
|
2226
|
+
const Root = named ? "section" : "div";
|
|
2227
|
+
const surface = `rounded-lg border border-gray-200 bg-white shadow-sm ${className}`.trim();
|
|
2228
|
+
const headerCls = `border-b border-gray-100 ${p.edge} text-sm font-semibold text-gray-900`;
|
|
2229
|
+
return /* @__PURE__ */ jsxs(
|
|
2230
|
+
Root,
|
|
2231
|
+
{
|
|
2232
|
+
className: surface,
|
|
2233
|
+
style,
|
|
2234
|
+
...titled ? { "aria-labelledby": headingId } : named ? { "aria-label": ariaLabel } : {},
|
|
2235
|
+
children: [
|
|
2236
|
+
header != null && (headerActions != null ? (
|
|
2237
|
+
// With actions the row has to be a flex container, so the heading is
|
|
2238
|
+
// nested rather than being the row itself — and only the title is
|
|
2239
|
+
// inside it.
|
|
2240
|
+
/* @__PURE__ */ jsxs("div", { className: `${headerCls} flex items-center justify-between gap-3`, children: [
|
|
2241
|
+
titled ? /* @__PURE__ */ jsx(Heading, { id: headingId, children: header }) : /* @__PURE__ */ jsx("span", { children: header }),
|
|
2242
|
+
headerActions
|
|
2243
|
+
] })
|
|
2244
|
+
) : titled ? (
|
|
2245
|
+
// Without them the heading carries the row's own styling rather than
|
|
2246
|
+
// nesting a second element, so the title is not two boxes deep.
|
|
2247
|
+
/* @__PURE__ */ jsx(Heading, { id: headingId, className: headerCls, children: header })
|
|
2248
|
+
) : /* @__PURE__ */ jsx("div", { className: headerCls, children: header })),
|
|
2249
|
+
/* @__PURE__ */ jsx("div", { className: [p.body, bodyClassName].filter(Boolean).join(" "), children }),
|
|
2250
|
+
footer && /* @__PURE__ */ jsx("div", { className: `border-t border-gray-100 ${p.edge}`, children: footer })
|
|
2251
|
+
]
|
|
2252
|
+
}
|
|
2253
|
+
);
|
|
2114
2254
|
}
|
|
2115
2255
|
function StatCard({ label, value, icon, delta, className = "" }) {
|
|
2116
2256
|
const deltaColor = delta?.direction === "up" ? "text-green-600" : delta?.direction === "down" ? "text-red-600" : "text-gray-500";
|
|
@@ -2336,7 +2476,8 @@ function DescriptionList({
|
|
|
2336
2476
|
bordered = false,
|
|
2337
2477
|
size = "md",
|
|
2338
2478
|
title,
|
|
2339
|
-
className = ""
|
|
2479
|
+
className = "",
|
|
2480
|
+
emptyText: empty = "\u2014"
|
|
2340
2481
|
}) {
|
|
2341
2482
|
const resolved = typeof columns === "number" ? { base: columns } : columns;
|
|
2342
2483
|
const base = resolved.base ?? 1;
|
|
@@ -2361,7 +2502,7 @@ function DescriptionList({
|
|
|
2361
2502
|
].filter(Boolean).join(" "),
|
|
2362
2503
|
children: [
|
|
2363
2504
|
/* @__PURE__ */ jsx("dt", { className: `${text} text-gray-500`, children: item.label }),
|
|
2364
|
-
/* @__PURE__ */ jsx("dd", { className: `mt-0.5 min-w-0 break-words ${text} text-gray-900`, children: item.value })
|
|
2505
|
+
/* @__PURE__ */ jsx("dd", { className: `mt-0.5 min-w-0 break-words ${text} text-gray-900`, children: item.value === null || item.value === void 0 || item.value === "" ? empty : item.value })
|
|
2365
2506
|
]
|
|
2366
2507
|
},
|
|
2367
2508
|
item.key ?? i
|
|
@@ -2642,49 +2783,89 @@ function Banner({
|
|
|
2642
2783
|
}
|
|
2643
2784
|
);
|
|
2644
2785
|
}
|
|
2645
|
-
|
|
2786
|
+
var tabButtonId = (prefix, id) => `${prefix}-tab-${id}`;
|
|
2787
|
+
var tabPanelId = (prefix, id) => `${prefix}-panel-${id}`;
|
|
2788
|
+
var LIST_CLASS = {
|
|
2789
|
+
underline: "flex items-center gap-1 border-b border-gray-200",
|
|
2790
|
+
pill: "inline-flex items-center gap-1 rounded-lg bg-gray-100 p-1"
|
|
2791
|
+
};
|
|
2792
|
+
function tabClass(variant, active) {
|
|
2646
2793
|
if (variant === "pill") {
|
|
2647
|
-
return
|
|
2648
|
-
const active = t.id === value;
|
|
2649
|
-
return /* @__PURE__ */ jsxs(
|
|
2650
|
-
"button",
|
|
2651
|
-
{
|
|
2652
|
-
type: "button",
|
|
2653
|
-
role: "tab",
|
|
2654
|
-
"aria-selected": active,
|
|
2655
|
-
tabIndex: active ? 0 : -1,
|
|
2656
|
-
disabled: t.disabled,
|
|
2657
|
-
onClick: () => onChange(t.id),
|
|
2658
|
-
className: `inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${active ? "bg-blue-600 text-white shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
2659
|
-
children: [
|
|
2660
|
-
t.icon,
|
|
2661
|
-
t.label
|
|
2662
|
-
]
|
|
2663
|
-
},
|
|
2664
|
-
t.id
|
|
2665
|
-
);
|
|
2666
|
-
}) });
|
|
2794
|
+
return `inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${active ? "bg-blue-600 text-white shadow-sm" : "text-gray-600 hover:text-gray-900"}`;
|
|
2667
2795
|
}
|
|
2668
|
-
return
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
}
|
|
2796
|
+
return `-mb-px inline-flex items-center gap-1.5 border-b-2 px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${active ? "border-blue-600 text-blue-600" : "border-transparent text-gray-600 hover:border-gray-300 hover:text-gray-900"}`;
|
|
2797
|
+
}
|
|
2798
|
+
function Tabs({
|
|
2799
|
+
items,
|
|
2800
|
+
value,
|
|
2801
|
+
onChange,
|
|
2802
|
+
variant = "underline",
|
|
2803
|
+
idPrefix,
|
|
2804
|
+
className = "",
|
|
2805
|
+
"aria-label": ariaLabel,
|
|
2806
|
+
"aria-labelledby": ariaLabelledBy
|
|
2807
|
+
}) {
|
|
2808
|
+
const buttons = useRef([]);
|
|
2809
|
+
const step = (from, direction) => {
|
|
2810
|
+
for (let i = 1; i <= items.length; i += 1) {
|
|
2811
|
+
const at = ((from + direction * i) % items.length + items.length) % items.length;
|
|
2812
|
+
if (!items[at]?.disabled) return at;
|
|
2813
|
+
}
|
|
2814
|
+
return null;
|
|
2815
|
+
};
|
|
2816
|
+
const edge = (direction) => {
|
|
2817
|
+
const order = direction === 1 ? items.map((_, i) => i) : items.map((_, i) => items.length - 1 - i);
|
|
2818
|
+
for (const i of order) if (!items[i]?.disabled) return i;
|
|
2819
|
+
return null;
|
|
2820
|
+
};
|
|
2821
|
+
const onKeyDown = (event) => {
|
|
2822
|
+
const current = items.findIndex((t) => t.id === value);
|
|
2823
|
+
let next = null;
|
|
2824
|
+
if (event.key === "ArrowRight" || event.key === "ArrowDown") next = step(current, 1);
|
|
2825
|
+
else if (event.key === "ArrowLeft" || event.key === "ArrowUp") next = step(current, -1);
|
|
2826
|
+
else if (event.key === "Home") next = edge(1);
|
|
2827
|
+
else if (event.key === "End") next = edge(-1);
|
|
2828
|
+
else return;
|
|
2829
|
+
event.preventDefault();
|
|
2830
|
+
if (next === null || next === current) return;
|
|
2831
|
+
onChange(items[next].id);
|
|
2832
|
+
buttons.current[next]?.focus();
|
|
2833
|
+
};
|
|
2834
|
+
return /* @__PURE__ */ jsx(
|
|
2835
|
+
"div",
|
|
2836
|
+
{
|
|
2837
|
+
role: "tablist",
|
|
2838
|
+
"aria-label": ariaLabel,
|
|
2839
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2840
|
+
onKeyDown,
|
|
2841
|
+
className: `${LIST_CLASS[variant]} ${className}`.trim(),
|
|
2842
|
+
children: items.map((t, i) => {
|
|
2843
|
+
const active = t.id === value;
|
|
2844
|
+
return /* @__PURE__ */ jsxs(
|
|
2845
|
+
"button",
|
|
2846
|
+
{
|
|
2847
|
+
ref: (el) => {
|
|
2848
|
+
buttons.current[i] = el;
|
|
2849
|
+
},
|
|
2850
|
+
type: "button",
|
|
2851
|
+
role: "tab",
|
|
2852
|
+
id: idPrefix ? tabButtonId(idPrefix, t.id) : void 0,
|
|
2853
|
+
"aria-controls": idPrefix ? tabPanelId(idPrefix, t.id) : void 0,
|
|
2854
|
+
"aria-selected": active,
|
|
2855
|
+
tabIndex: active ? 0 : -1,
|
|
2856
|
+
disabled: t.disabled,
|
|
2857
|
+
onClick: () => onChange(t.id),
|
|
2858
|
+
className: tabClass(variant, active),
|
|
2859
|
+
children: [
|
|
2860
|
+
t.icon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "inline-flex shrink-0", children: t.icon }),
|
|
2861
|
+
t.label
|
|
2862
|
+
]
|
|
2863
|
+
},
|
|
2864
|
+
t.id
|
|
2865
|
+
);
|
|
2866
|
+
})
|
|
2867
|
+
}
|
|
2868
|
+
);
|
|
2688
2869
|
}
|
|
2689
2870
|
function Accordion({
|
|
2690
2871
|
items,
|
|
@@ -2789,11 +2970,6 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
|
|
|
2789
2970
|
}
|
|
2790
2971
|
);
|
|
2791
2972
|
}
|
|
2792
|
-
function ColoredBadge({ colorClass, children, size = "sm", capitalize = false }) {
|
|
2793
|
-
const sizeCls = size === "xs" ? "px-2 py-0.5 text-[10px]" : size === "md" ? "px-2.5 py-0.5 text-xs" : "px-2 py-0.5 text-xs";
|
|
2794
|
-
const capCls = capitalize ? "capitalize" : "";
|
|
2795
|
-
return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full font-medium ${sizeCls} ${capCls} ${colorClass}`, children });
|
|
2796
|
-
}
|
|
2797
2973
|
var GROUP_COLORS = {
|
|
2798
2974
|
success: "bg-green-100 text-green-800",
|
|
2799
2975
|
active: "bg-blue-100 text-blue-800",
|
|
@@ -2819,6 +2995,36 @@ function StatusBadge({ status }) {
|
|
|
2819
2995
|
const label = status.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
2820
2996
|
return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${color}`, children: label });
|
|
2821
2997
|
}
|
|
2998
|
+
function ColoredBadge({
|
|
2999
|
+
colorClass,
|
|
3000
|
+
tone,
|
|
3001
|
+
children,
|
|
3002
|
+
size = "sm",
|
|
3003
|
+
capitalize = false,
|
|
3004
|
+
closable = false,
|
|
3005
|
+
onClose,
|
|
3006
|
+
closeLabel,
|
|
3007
|
+
className = ""
|
|
3008
|
+
}) {
|
|
3009
|
+
const colour = colorClass ?? GROUP_COLORS[tone ?? "neutral"];
|
|
3010
|
+
const sizeCls = size === "xs" ? "px-2 py-0.5 text-[10px]" : size === "md" ? "px-2.5 py-0.5 text-xs" : "px-2 py-0.5 text-xs";
|
|
3011
|
+
const capCls = capitalize ? "capitalize" : "";
|
|
3012
|
+
const closeName = closeLabel ?? (typeof children === "string" ? `Remove ${children}` : "Remove");
|
|
3013
|
+
const closeSize = size === "xs" ? "h-2.5 w-2.5" : "h-3 w-3";
|
|
3014
|
+
return /* @__PURE__ */ jsxs("span", { className: ["inline-flex items-center rounded-full font-medium", sizeCls, capCls, colour, className].filter(Boolean).join(" "), children: [
|
|
3015
|
+
children,
|
|
3016
|
+
closable && /* @__PURE__ */ jsx(
|
|
3017
|
+
"button",
|
|
3018
|
+
{
|
|
3019
|
+
type: "button",
|
|
3020
|
+
onClick: onClose,
|
|
3021
|
+
"aria-label": closeName,
|
|
3022
|
+
className: "-mr-0.5 ml-1 inline-flex shrink-0 items-center justify-center rounded-full opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-blue-400/40",
|
|
3023
|
+
children: /* @__PURE__ */ jsx("svg", { className: closeSize, viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" }) })
|
|
3024
|
+
}
|
|
3025
|
+
)
|
|
3026
|
+
] });
|
|
3027
|
+
}
|
|
2822
3028
|
function EmptyState({
|
|
2823
3029
|
title,
|
|
2824
3030
|
message,
|
|
@@ -2830,12 +3036,14 @@ function EmptyState({
|
|
|
2830
3036
|
children
|
|
2831
3037
|
}) {
|
|
2832
3038
|
const v = frameless ? "none" : variant ?? "dashed";
|
|
2833
|
-
const
|
|
3039
|
+
const custom = typeof icon !== "boolean" && icon != null ? icon : null;
|
|
3040
|
+
const showIcon = custom ? false : icon ?? v !== "card";
|
|
2834
3041
|
const primary = message ?? (title ? void 0 : "Nothing here yet.");
|
|
2835
3042
|
const secondary = description ?? hint;
|
|
2836
3043
|
const frame = v === "card" ? "rounded-md border border-gray-200 bg-white px-6 py-12" : v === "none" ? "px-6 py-12" : "rounded-lg border-2 border-dashed border-gray-300 px-6 py-12";
|
|
2837
3044
|
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col items-center justify-center text-center ${frame}`, children: [
|
|
2838
|
-
|
|
3045
|
+
custom && /* @__PURE__ */ jsx("div", { className: "mb-3 flex h-10 w-10 items-center justify-center text-gray-300", "aria-hidden": "true", children: custom }),
|
|
3046
|
+
showIcon && /* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-gray-300 mb-3", "aria-hidden": "true", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
|
|
2839
3047
|
title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900", children: title }),
|
|
2840
3048
|
primary && /* @__PURE__ */ jsx("p", { className: `text-sm text-gray-500 ${title ? "mt-2" : ""}`, children: primary }),
|
|
2841
3049
|
secondary && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 mt-1", children: secondary }),
|
|
@@ -3854,6 +4062,133 @@ function TopNav({ items, activeKey, onSelect, brand, actions, className }) {
|
|
|
3854
4062
|
}
|
|
3855
4063
|
);
|
|
3856
4064
|
}
|
|
4065
|
+
function DropdownMenu({
|
|
4066
|
+
trigger,
|
|
4067
|
+
items,
|
|
4068
|
+
align = "end",
|
|
4069
|
+
"aria-label": ariaLabel,
|
|
4070
|
+
className = "",
|
|
4071
|
+
disabled
|
|
4072
|
+
}) {
|
|
4073
|
+
const [open, setOpen] = useState(false);
|
|
4074
|
+
const [active, setActive] = useState(0);
|
|
4075
|
+
const wrapRef = useRef(null);
|
|
4076
|
+
const triggerRef = useRef(null);
|
|
4077
|
+
const itemRefs = useRef([]);
|
|
4078
|
+
const menuId = useId();
|
|
4079
|
+
const close = useCallback((restoreFocus) => {
|
|
4080
|
+
setOpen(false);
|
|
4081
|
+
if (restoreFocus) triggerRef.current?.focus();
|
|
4082
|
+
}, []);
|
|
4083
|
+
const enabledFrom = (from, step) => {
|
|
4084
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
4085
|
+
const at = ((from + step * i) % items.length + items.length) % items.length;
|
|
4086
|
+
if (!items[at]?.disabled) return at;
|
|
4087
|
+
}
|
|
4088
|
+
return from;
|
|
4089
|
+
};
|
|
4090
|
+
useEffect(() => {
|
|
4091
|
+
if (!open) return;
|
|
4092
|
+
const onPointerDown = (e) => {
|
|
4093
|
+
if (!wrapRef.current?.contains(e.target)) close(false);
|
|
4094
|
+
};
|
|
4095
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
4096
|
+
return () => document.removeEventListener("pointerdown", onPointerDown, true);
|
|
4097
|
+
}, [open, close]);
|
|
4098
|
+
useEffect(() => {
|
|
4099
|
+
if (open) itemRefs.current[active]?.focus();
|
|
4100
|
+
}, [open, active]);
|
|
4101
|
+
useEffect(() => {
|
|
4102
|
+
if (!open) return;
|
|
4103
|
+
return registerModalEscapeInterceptor((event) => {
|
|
4104
|
+
if (event.key !== "Escape") return false;
|
|
4105
|
+
close(true);
|
|
4106
|
+
return true;
|
|
4107
|
+
});
|
|
4108
|
+
}, [open, close]);
|
|
4109
|
+
const openAt = (index) => {
|
|
4110
|
+
setActive(index);
|
|
4111
|
+
setOpen(true);
|
|
4112
|
+
};
|
|
4113
|
+
const onTriggerKeyDown = (e) => {
|
|
4114
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
4115
|
+
e.preventDefault();
|
|
4116
|
+
openAt(enabledFrom(0, 1));
|
|
4117
|
+
} else if (e.key === "ArrowUp") {
|
|
4118
|
+
e.preventDefault();
|
|
4119
|
+
openAt(enabledFrom(items.length - 1, -1));
|
|
4120
|
+
}
|
|
4121
|
+
};
|
|
4122
|
+
const onMenuKeyDown = (e) => {
|
|
4123
|
+
if (e.key === "ArrowDown") {
|
|
4124
|
+
e.preventDefault();
|
|
4125
|
+
setActive(enabledFrom(active + 1, 1));
|
|
4126
|
+
} else if (e.key === "ArrowUp") {
|
|
4127
|
+
e.preventDefault();
|
|
4128
|
+
setActive(enabledFrom(active - 1, -1));
|
|
4129
|
+
} else if (e.key === "Home") {
|
|
4130
|
+
e.preventDefault();
|
|
4131
|
+
setActive(enabledFrom(0, 1));
|
|
4132
|
+
} else if (e.key === "End") {
|
|
4133
|
+
e.preventDefault();
|
|
4134
|
+
setActive(enabledFrom(items.length - 1, -1));
|
|
4135
|
+
} else if (e.key === "Tab") {
|
|
4136
|
+
e.preventDefault();
|
|
4137
|
+
close(true);
|
|
4138
|
+
}
|
|
4139
|
+
};
|
|
4140
|
+
const select = (item) => {
|
|
4141
|
+
if (item.disabled) return;
|
|
4142
|
+
close(true);
|
|
4143
|
+
item.onSelect();
|
|
4144
|
+
};
|
|
4145
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: `relative inline-flex ${className}`.trim(), children: [
|
|
4146
|
+
/* @__PURE__ */ jsx(
|
|
4147
|
+
"button",
|
|
4148
|
+
{
|
|
4149
|
+
ref: triggerRef,
|
|
4150
|
+
type: "button",
|
|
4151
|
+
"aria-haspopup": "menu",
|
|
4152
|
+
"aria-expanded": open,
|
|
4153
|
+
"aria-controls": open ? menuId : void 0,
|
|
4154
|
+
"aria-label": ariaLabel,
|
|
4155
|
+
disabled,
|
|
4156
|
+
onClick: () => open ? close(false) : openAt(enabledFrom(0, 1)),
|
|
4157
|
+
onKeyDown: onTriggerKeyDown,
|
|
4158
|
+
className: "inline-flex items-center justify-center rounded-md text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400 disabled:cursor-not-allowed disabled:opacity-60",
|
|
4159
|
+
children: trigger
|
|
4160
|
+
}
|
|
4161
|
+
),
|
|
4162
|
+
open && /* @__PURE__ */ jsx(
|
|
4163
|
+
"div",
|
|
4164
|
+
{
|
|
4165
|
+
className: `absolute top-full z-50 mt-1 ${align === "end" ? "right-0" : "left-0"}`,
|
|
4166
|
+
onKeyDown: onMenuKeyDown,
|
|
4167
|
+
children: /* @__PURE__ */ jsx(PopupMenu, { portal: false, minWidth: 180, children: /* @__PURE__ */ jsx("div", { id: menuId, role: "menu", "aria-orientation": "vertical", "aria-label": ariaLabel, children: items.map((item, i) => /* @__PURE__ */ jsxs(
|
|
4168
|
+
PopupMenuItem,
|
|
4169
|
+
{
|
|
4170
|
+
ref: (el) => {
|
|
4171
|
+
itemRefs.current[i] = el;
|
|
4172
|
+
},
|
|
4173
|
+
role: "menuitem",
|
|
4174
|
+
tabIndex: i === active ? 0 : -1,
|
|
4175
|
+
danger: item.danger,
|
|
4176
|
+
disabled: item.disabled,
|
|
4177
|
+
onMouseEnter: () => {
|
|
4178
|
+
if (!item.disabled) setActive(i);
|
|
4179
|
+
},
|
|
4180
|
+
onClick: () => select(item),
|
|
4181
|
+
children: [
|
|
4182
|
+
item.icon,
|
|
4183
|
+
item.label
|
|
4184
|
+
]
|
|
4185
|
+
},
|
|
4186
|
+
item.key
|
|
4187
|
+
)) }) })
|
|
4188
|
+
}
|
|
4189
|
+
)
|
|
4190
|
+
] });
|
|
4191
|
+
}
|
|
3857
4192
|
var SIZE_PX2 = { sm: 320, md: 448, lg: 640 };
|
|
3858
4193
|
var SIDE_POSITION = {
|
|
3859
4194
|
right: "inset-y-0 right-0",
|
|
@@ -4297,6 +4632,7 @@ function Pagination({
|
|
|
4297
4632
|
showEdges && /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Last page", disabled: page === pageCount, onClick: () => go(pageCount), className: `${BTN} text-gray-600 hover:bg-gray-100`, children: "\xBB" })
|
|
4298
4633
|
] });
|
|
4299
4634
|
}
|
|
4635
|
+
var isGroup = (h) => Array.isArray(h.columns);
|
|
4300
4636
|
var PAD = {
|
|
4301
4637
|
sm: "px-2 py-1.5",
|
|
4302
4638
|
md: "px-3 py-2"
|
|
@@ -4319,6 +4655,7 @@ function DataTable({
|
|
|
4319
4655
|
sort = null,
|
|
4320
4656
|
onSortChange,
|
|
4321
4657
|
pagination,
|
|
4658
|
+
caption,
|
|
4322
4659
|
loading = false,
|
|
4323
4660
|
bordered = false,
|
|
4324
4661
|
size = "md",
|
|
@@ -4336,13 +4673,52 @@ function DataTable({
|
|
|
4336
4673
|
if (!onSortChange) return;
|
|
4337
4674
|
const field = fieldOf(col);
|
|
4338
4675
|
const current = directionFor(col);
|
|
4339
|
-
|
|
4340
|
-
|
|
4676
|
+
const first = col.sortFirst ?? "asc";
|
|
4677
|
+
const second = first === "asc" ? "desc" : "asc";
|
|
4678
|
+
if (current === null) onSortChange({ field, direction: first });
|
|
4679
|
+
else if (current === first) onSortChange({ field, direction: second });
|
|
4341
4680
|
else onSortChange(null);
|
|
4342
4681
|
};
|
|
4682
|
+
const leaves = columns.flatMap((h) => isGroup(h) ? h.columns : [h]);
|
|
4683
|
+
const grouped = columns.some(isGroup);
|
|
4343
4684
|
const cellBase = `${PAD[size]} ${size === "sm" ? "text-xs" : "text-sm"}`;
|
|
4685
|
+
const headerCell = (col, ci, rowSpan) => {
|
|
4686
|
+
const dir = directionFor(col);
|
|
4687
|
+
const align = ALIGN2[col.align ?? (col.numeric ? "right" : "left")];
|
|
4688
|
+
const pinned = col.fixed === "left";
|
|
4689
|
+
return /* @__PURE__ */ jsx(
|
|
4690
|
+
"th",
|
|
4691
|
+
{
|
|
4692
|
+
scope: "col",
|
|
4693
|
+
rowSpan: rowSpan > 1 ? rowSpan : void 0,
|
|
4694
|
+
"aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : col.sortable && onSortChange ? "none" : void 0,
|
|
4695
|
+
style: { width: col.width, ...pinned ? { left: offsets[ci] ?? 0 } : {} },
|
|
4696
|
+
className: [
|
|
4697
|
+
cellBase,
|
|
4698
|
+
align,
|
|
4699
|
+
"font-semibold uppercase tracking-wide text-gray-500",
|
|
4700
|
+
size === "sm" ? "text-[10px]" : "text-xs",
|
|
4701
|
+
pinned ? "sticky z-10 bg-gray-50" : "",
|
|
4702
|
+
col.headerClassName ?? ""
|
|
4703
|
+
].filter(Boolean).join(" "),
|
|
4704
|
+
children: col.sortable && onSortChange ? /* @__PURE__ */ jsxs(
|
|
4705
|
+
"button",
|
|
4706
|
+
{
|
|
4707
|
+
type: "button",
|
|
4708
|
+
onClick: () => toggleSort(col),
|
|
4709
|
+
className: `inline-flex items-center font-semibold uppercase tracking-wide hover:text-gray-700 ${align}`,
|
|
4710
|
+
children: [
|
|
4711
|
+
col.title,
|
|
4712
|
+
/* @__PURE__ */ jsx(SortIcon, { direction: dir })
|
|
4713
|
+
]
|
|
4714
|
+
}
|
|
4715
|
+
) : col.title
|
|
4716
|
+
},
|
|
4717
|
+
col.key
|
|
4718
|
+
);
|
|
4719
|
+
};
|
|
4344
4720
|
let fixedOffset = 0;
|
|
4345
|
-
const offsets =
|
|
4721
|
+
const offsets = leaves.map((col) => {
|
|
4346
4722
|
if (col.fixed !== "left") return null;
|
|
4347
4723
|
const at = fixedOffset;
|
|
4348
4724
|
fixedOffset += col.width ?? 0;
|
|
@@ -4358,56 +4734,56 @@ function DataTable({
|
|
|
4358
4734
|
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
|
|
4359
4735
|
] }),
|
|
4360
4736
|
/* @__PURE__ */ jsxs("table", { className: "w-full border-collapse tabular-nums", style: minWidth ? { minWidth } : void 0, children: [
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
{
|
|
4368
|
-
scope: "col",
|
|
4369
|
-
"aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : void 0,
|
|
4370
|
-
style: {
|
|
4371
|
-
width: col.width,
|
|
4372
|
-
...pinned ? { left: offsets[ci] ?? 0 } : {}
|
|
4373
|
-
},
|
|
4374
|
-
className: [
|
|
4375
|
-
cellBase,
|
|
4376
|
-
align,
|
|
4377
|
-
"font-semibold uppercase tracking-wide text-gray-500",
|
|
4378
|
-
size === "sm" ? "text-[10px]" : "text-xs",
|
|
4379
|
-
pinned ? "sticky z-10 bg-gray-50" : "",
|
|
4380
|
-
col.headerClassName ?? ""
|
|
4381
|
-
].filter(Boolean).join(" "),
|
|
4382
|
-
children: col.sortable && onSortChange ? /* @__PURE__ */ jsxs(
|
|
4383
|
-
"button",
|
|
4737
|
+
caption && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
|
|
4738
|
+
/* @__PURE__ */ jsxs("thead", { children: [
|
|
4739
|
+
/* @__PURE__ */ jsx("tr", { className: "border-b border-gray-200 bg-gray-50", children: columns.map((h, hi) => {
|
|
4740
|
+
if (isGroup(h)) {
|
|
4741
|
+
return /* @__PURE__ */ jsx(
|
|
4742
|
+
"th",
|
|
4384
4743
|
{
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
className:
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4744
|
+
scope: "colgroup",
|
|
4745
|
+
colSpan: h.columns.length,
|
|
4746
|
+
className: [
|
|
4747
|
+
cellBase,
|
|
4748
|
+
"text-center",
|
|
4749
|
+
"font-semibold uppercase tracking-wide text-gray-500",
|
|
4750
|
+
size === "sm" ? "text-[10px]" : "text-xs",
|
|
4751
|
+
"border-b border-gray-200",
|
|
4752
|
+
h.headerClassName ?? ""
|
|
4753
|
+
].filter(Boolean).join(" "),
|
|
4754
|
+
children: h.title
|
|
4755
|
+
},
|
|
4756
|
+
h.key ?? `group-${hi}`
|
|
4757
|
+
);
|
|
4758
|
+
}
|
|
4759
|
+
return headerCell(h, leaves.indexOf(h), grouped ? 2 : 1);
|
|
4760
|
+
}) }),
|
|
4761
|
+
grouped && /* @__PURE__ */ jsx("tr", { className: "border-b border-gray-200 bg-gray-50", children: columns.flatMap((h) => isGroup(h) ? h.columns : []).map(
|
|
4762
|
+
(col) => headerCell(col, leaves.indexOf(col), 1)
|
|
4763
|
+
) })
|
|
4764
|
+
] }),
|
|
4765
|
+
/* @__PURE__ */ jsx("tbody", { children: data.length === 0 && !loading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: leaves.length, className: `${cellBase} py-10 text-center text-gray-500`, children: emptyText }) }) : data.map((row, i) => {
|
|
4399
4766
|
const rowProps = onRow?.(row, i);
|
|
4400
4767
|
return /* @__PURE__ */ jsx(
|
|
4401
4768
|
"tr",
|
|
4402
4769
|
{
|
|
4403
4770
|
onClick: rowProps?.onClick,
|
|
4771
|
+
...rowProps?.onClick ? {
|
|
4772
|
+
tabIndex: 0,
|
|
4773
|
+
onKeyDown: (e) => {
|
|
4774
|
+
if (e.target !== e.currentTarget) return;
|
|
4775
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
4776
|
+
e.preventDefault();
|
|
4777
|
+
rowProps.onClick?.();
|
|
4778
|
+
}
|
|
4779
|
+
} : {},
|
|
4404
4780
|
className: [
|
|
4405
4781
|
"border-b border-gray-100 last:border-b-0",
|
|
4406
|
-
rowProps?.onClick ? "cursor-pointer hover:bg-gray-50" : "",
|
|
4782
|
+
rowProps?.onClick ? "cursor-pointer hover:bg-gray-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-400" : "",
|
|
4407
4783
|
rowClassName?.(row, i) ?? "",
|
|
4408
4784
|
rowProps?.className ?? ""
|
|
4409
4785
|
].filter(Boolean).join(" "),
|
|
4410
|
-
children:
|
|
4786
|
+
children: leaves.map((col, ci) => {
|
|
4411
4787
|
const pinned = col.fixed === "left";
|
|
4412
4788
|
return /* @__PURE__ */ jsx(
|
|
4413
4789
|
"td",
|
|
@@ -4415,7 +4791,8 @@ function DataTable({
|
|
|
4415
4791
|
style: pinned ? { left: offsets[ci] ?? 0 } : void 0,
|
|
4416
4792
|
className: [
|
|
4417
4793
|
cellBase,
|
|
4418
|
-
ALIGN2[col.align ?? "left"],
|
|
4794
|
+
ALIGN2[col.align ?? (col.numeric ? "right" : "left")],
|
|
4795
|
+
col.numeric ? "font-mono" : "",
|
|
4419
4796
|
"text-gray-900",
|
|
4420
4797
|
col.ellipsis ? "max-w-0 truncate" : "",
|
|
4421
4798
|
// A pinned cell needs its own background or the
|
|
@@ -5137,16 +5514,13 @@ var COPY2 = {
|
|
|
5137
5514
|
404: { title: "Page not found", body: "The page you're looking for doesn't exist or was moved." },
|
|
5138
5515
|
500: { title: "Something went wrong", body: "An unexpected error occurred. Please try again." }
|
|
5139
5516
|
};
|
|
5140
|
-
function ErrorPage({ code = 404 }) {
|
|
5517
|
+
function ErrorPage({ code = 404, actions }) {
|
|
5141
5518
|
const c = COPY2[code];
|
|
5142
5519
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center bg-gray-50 p-6 text-center", children: [
|
|
5143
5520
|
/* @__PURE__ */ jsx("div", { className: "text-7xl font-bold tracking-tight text-gray-400", children: code }),
|
|
5144
5521
|
/* @__PURE__ */ jsx("h1", { className: "mt-2 text-xl font-semibold text-gray-900", children: c.title }),
|
|
5145
5522
|
/* @__PURE__ */ jsx("p", { className: "mt-1 max-w-sm text-sm text-gray-500", children: c.body }),
|
|
5146
|
-
/* @__PURE__ */
|
|
5147
|
-
/* @__PURE__ */ jsx(Button_default, { variant: "secondary", children: "Go back" }),
|
|
5148
|
-
/* @__PURE__ */ jsx(Button_default, { children: "Take me home" })
|
|
5149
|
-
] })
|
|
5523
|
+
actions && /* @__PURE__ */ jsx("div", { className: "mt-6 flex items-center gap-2", children: actions })
|
|
5150
5524
|
] });
|
|
5151
5525
|
}
|
|
5152
5526
|
function subscribeMediaQuery(cb) {
|
|
@@ -5282,6 +5656,6 @@ var ALT_SHIFT_D = isMac ? "\u2325\u21E7D" : "Alt+Shift+D";
|
|
|
5282
5656
|
var ALT_SHIFT_E = isMac ? "\u2325\u21E7E" : "Alt+Shift+E";
|
|
5283
5657
|
var ALT_SHIFT_N = isMac ? "\u2325\u21E7N" : "Alt+Shift+N";
|
|
5284
5658
|
|
|
5285
|
-
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, Button_default, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CMD_SHIFT_Z, CMD_Z, Card, ChatTemplate, Checkbox_default, CheckoutTemplate, ColoredBadge, ContainerFillChart, CountBadge, DashboardTemplate, DataTable, DataTablePage, DatePicker_default, DateRangePicker, DescriptionList, Divider, DonutChart, Drawer, ENTER, EmailTemplate, EmptyState, ErrorPage, FilePicker, FormField, FormLayoutPage, GalleryTemplate, GlobalSearch, Grid, HelpCenter, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, ListFooter, ListLoadError, LoadingSpinner, MAX_FRACTION_DIGITS, MOD, Markdown, MediaUploadField, MediaUploadGrid, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, PageHeader, Pagination, Paragraph, Radio_default, Result, SHIFT, SearchableSelect, Segmented, Select_default, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Sparkline, Stack, StatCard, Statistic, StatusBadge, StatusBadgeProvider, Switch_default, Tabs, Text, Textarea_default, TileButton_default, Title, Tooltip, TopNav, appendKey, applyThemePrefs, backspace, firstEnabledIndex, formatDate, inputClasses, isMac, isSeverityTone, lastEnabledIndex, matchTypeahead, mediaFileName, nextEnabledIndex, resolveTheme, severityOf, toISODate, useClickOutside, useTheme };
|
|
5286
|
-
//# sourceMappingURL=chunk-
|
|
5287
|
-
//# sourceMappingURL=chunk-
|
|
5659
|
+
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, Button_default, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CMD_SHIFT_Z, CMD_Z, Card, ChatTemplate, Checkbox_default, CheckoutTemplate, ColoredBadge, ContainerFillChart, CountBadge, DashboardTemplate, DataTable, DataTablePage, DatePicker_default, DateRangePicker, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, ENTER, EmailTemplate, EmptyState, ErrorPage, FilePicker, FormField, FormLayoutPage, GROUP_COLORS, GalleryTemplate, GlobalSearch, Grid, HelpCenter, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, ListFooter, ListLoadError, LoadingSpinner, MAX_FRACTION_DIGITS, MOD, Markdown, MediaUploadField, MediaUploadGrid, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, PageHeader, Pagination, Paragraph, Radio_default, Result, SHIFT, SearchableSelect, Segmented, Select_default, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Sparkline, Stack, StatCard, Statistic, StatusBadge, StatusBadgeProvider, Switch_default, Tabs, Text, Textarea_default, TileButton_default, Title, Tooltip, TopNav, appendKey, applyThemePrefs, backspace, firstEnabledIndex, formatDate, inputClasses, isMac, isSeverityTone, lastEnabledIndex, matchTypeahead, mediaFileName, nextEnabledIndex, resolveTheme, severityOf, tabButtonId, tabPanelId, toISODate, useClickOutside, useTheme };
|
|
5660
|
+
//# sourceMappingURL=chunk-3SUSQHOW.js.map
|
|
5661
|
+
//# sourceMappingURL=chunk-3SUSQHOW.js.map
|