react-os-shell 4.63.0 → 4.67.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/README.md +1 -0
- package/dist/{Browser-SPTNLEMR.js → Browser-NBYPPENQ.js} +6 -6
- package/dist/{Browser-SPTNLEMR.js.map → Browser-NBYPPENQ.js.map} +1 -1
- package/dist/{Calculator-XMOPPCK3.js → Calculator-UNAVT7IE.js} +5 -5
- package/dist/{Calculator-XMOPPCK3.js.map → Calculator-UNAVT7IE.js.map} +1 -1
- package/dist/ConfirmDialog-SREDNTIB.js +3 -0
- package/dist/{ConfirmDialog-EEH4CWSW.js.map → ConfirmDialog-SREDNTIB.js.map} +1 -1
- package/dist/{CurrencyConverter-24HNX6C6.js → CurrencyConverter-KURXJHLK.js} +5 -5
- package/dist/{CurrencyConverter-24HNX6C6.js.map → CurrencyConverter-KURXJHLK.js.map} +1 -1
- package/dist/{Documents-GMRVVCH7.js → Documents-7CUBCETC.js} +6 -6
- package/dist/{Documents-GMRVVCH7.js.map → Documents-7CUBCETC.js.map} +1 -1
- package/dist/{Files-ITH4SVML.js → Files-UXEDRQF4.js} +6 -6
- package/dist/{Files-ITH4SVML.js.map → Files-UXEDRQF4.js.map} +1 -1
- package/dist/{Notepad-GE5P55TL.js → Notepad-ON4T45UP.js} +6 -6
- package/dist/{Notepad-GE5P55TL.js.map → Notepad-ON4T45UP.js.map} +1 -1
- package/dist/{PomodoroTimer-ER5STVKM.js → PomodoroTimer-J7V5VXR4.js} +5 -5
- package/dist/{PomodoroTimer-ER5STVKM.js.map → PomodoroTimer-J7V5VXR4.js.map} +1 -1
- package/dist/{Preview-UXVDXCDJ.js → Preview-QINOPDT2.js} +6 -6
- package/dist/{Preview-UXVDXCDJ.js.map → Preview-QINOPDT2.js.map} +1 -1
- package/dist/{Spreadsheet-B32JQVX4.js → Spreadsheet-OFF3J4HN.js} +6 -6
- package/dist/{Spreadsheet-B32JQVX4.js.map → Spreadsheet-OFF3J4HN.js.map} +1 -1
- package/dist/{Stock-FSFPFDQT.js → Stock-BSU7S7MW.js} +5 -5
- package/dist/{Stock-FSFPFDQT.js.map → Stock-BSU7S7MW.js.map} +1 -1
- package/dist/{Weather-HXOERJJV.js → Weather-BKNRVMG6.js} +5 -5
- package/dist/{Weather-HXOERJJV.js.map → Weather-BKNRVMG6.js.map} +1 -1
- package/dist/{WorldClock-2FUGLIUZ.js → WorldClock-VMTD2QWD.js} +5 -5
- package/dist/{WorldClock-2FUGLIUZ.js.map → WorldClock-VMTD2QWD.js.map} +1 -1
- package/dist/apps/index.js +16 -16
- package/dist/{chunk-CWA27IGB.js → chunk-B3IYV7JN.js} +588 -274
- package/dist/chunk-B3IYV7JN.js.map +1 -0
- package/dist/{chunk-OXLLRKBC.js → chunk-CDR2Q64Q.js} +38 -22
- package/dist/chunk-CDR2Q64Q.js.map +1 -0
- package/dist/{chunk-LYQVLRWQ.js → chunk-E2N5WEHI.js} +3 -3
- package/dist/{chunk-LYQVLRWQ.js.map → chunk-E2N5WEHI.js.map} +1 -1
- package/dist/{chunk-JMESET3G.js → chunk-GRSVL6WX.js} +4 -4
- package/dist/{chunk-JMESET3G.js.map → chunk-GRSVL6WX.js.map} +1 -1
- package/dist/{chunk-TO6ZZHJK.js → chunk-HAFM6ZQD.js} +4 -4
- package/dist/{chunk-TO6ZZHJK.js.map → chunk-HAFM6ZQD.js.map} +1 -1
- package/dist/chunk-K35QFOJF.js +7 -0
- package/dist/{chunk-WCGHIJZR.js.map → chunk-K35QFOJF.js.map} +1 -1
- package/dist/{index-Ka32s3Ij.d.ts → index-DM-d12A7.d.ts} +88 -22
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -8
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +3 -3
- package/package.json +1 -1
- package/dist/ConfirmDialog-EEH4CWSW.js +0 -3
- package/dist/chunk-CWA27IGB.js.map +0 -1
- package/dist/chunk-OXLLRKBC.js.map +0 -1
- package/dist/chunk-WCGHIJZR.js +0 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Breadcrumbs } from './chunk-HNH7FOYB.js';
|
|
2
2
|
import { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
3
3
|
import { useIsMobile, PopupMenu, PopupMenuItem, useShellPrefs } from './chunk-ZCDFNZQS.js';
|
|
4
|
-
import { registerModalEscapeInterceptor, useFocusTrap, useScrollLock } from './chunk-
|
|
4
|
+
import { registerModalEscapeInterceptor, useFocusTrap, useScrollLock } from './chunk-CDR2Q64Q.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, Component, useSyncExternalStore } from 'react';
|
|
7
7
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -164,7 +164,7 @@ function inputClasses(opts) {
|
|
|
164
164
|
return [shape, opts?.invalid ? INPUT_INVALID : "", INPUT_DISABLED, opts?.className ?? ""].filter(Boolean).join(" ");
|
|
165
165
|
}
|
|
166
166
|
var Input = forwardRef(function Input2({ invalid, leftIcon, rightAdornment, size, className = "", ...rest }, ref) {
|
|
167
|
-
const
|
|
167
|
+
const pad5 = `${leftIcon ? "pl-9" : ""} ${rightAdornment ? "pr-9" : ""}`.trim();
|
|
168
168
|
const field = (
|
|
169
169
|
// `inputMode` needs no plumbing — it rides the native spread onto the
|
|
170
170
|
// <input>, which is how a till sets inputMode="none" to keep the OS
|
|
@@ -174,7 +174,7 @@ var Input = forwardRef(function Input2({ invalid, leftIcon, rightAdornment, size
|
|
|
174
174
|
{
|
|
175
175
|
ref,
|
|
176
176
|
"aria-invalid": invalid || void 0,
|
|
177
|
-
className: inputClasses({ invalid, size, className: [
|
|
177
|
+
className: inputClasses({ invalid, size, className: [pad5, className].filter(Boolean).join(" ") }),
|
|
178
178
|
...rest
|
|
179
179
|
}
|
|
180
180
|
)
|
|
@@ -282,7 +282,8 @@ function useAnchoredPosition(triggerRef, open) {
|
|
|
282
282
|
const placeAbove = spaceBelow < Math.min(MENU_MAX_HEIGHT, 160) && spaceAbove > spaceBelow;
|
|
283
283
|
const maxHeight = Math.max(96, Math.min(MENU_MAX_HEIGHT, placeAbove ? spaceAbove : spaceBelow));
|
|
284
284
|
const left = Math.max(VIEWPORT_MARGIN, Math.min(rect.left, window.innerWidth - rect.width - VIEWPORT_MARGIN));
|
|
285
|
-
const
|
|
285
|
+
const width = Math.min(rect.width, window.innerWidth - 2 * VIEWPORT_MARGIN);
|
|
286
|
+
const next = { left, width, maxHeight };
|
|
286
287
|
if (placeAbove) next.bottom = window.innerHeight - rect.top + MENU_GAP;
|
|
287
288
|
else next.top = rect.bottom + MENU_GAP;
|
|
288
289
|
setPos(next);
|
|
@@ -497,12 +498,12 @@ var ListboxSelect = forwardRef(function ListboxSelect2({
|
|
|
497
498
|
ref: listRef,
|
|
498
499
|
id: listboxId,
|
|
499
500
|
role: "listbox",
|
|
500
|
-
className: "fixed z-[
|
|
501
|
+
className: "fixed z-[10000] overflow-y-auto rounded-2xl py-1",
|
|
501
502
|
style: {
|
|
502
503
|
left: menuPos?.left,
|
|
503
504
|
top: menuPos?.top,
|
|
504
505
|
bottom: menuPos?.bottom,
|
|
505
|
-
|
|
506
|
+
width: menuPos?.width,
|
|
506
507
|
maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT,
|
|
507
508
|
visibility: menuPos ? void 0 : "hidden",
|
|
508
509
|
...glassStyle()
|
|
@@ -1098,6 +1099,273 @@ function MediaUploadGrid({
|
|
|
1098
1099
|
}
|
|
1099
1100
|
) });
|
|
1100
1101
|
}
|
|
1102
|
+
var MONTH_NAMES = [
|
|
1103
|
+
"January",
|
|
1104
|
+
"February",
|
|
1105
|
+
"March",
|
|
1106
|
+
"April",
|
|
1107
|
+
"May",
|
|
1108
|
+
"June",
|
|
1109
|
+
"July",
|
|
1110
|
+
"August",
|
|
1111
|
+
"September",
|
|
1112
|
+
"October",
|
|
1113
|
+
"November",
|
|
1114
|
+
"December"
|
|
1115
|
+
];
|
|
1116
|
+
var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
1117
|
+
var DAY_SHORT = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
1118
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
1119
|
+
function toKey(d) {
|
|
1120
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
1121
|
+
}
|
|
1122
|
+
function fromKey(key) {
|
|
1123
|
+
if (!key) return null;
|
|
1124
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(key);
|
|
1125
|
+
if (!m) return null;
|
|
1126
|
+
const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
1127
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
1128
|
+
}
|
|
1129
|
+
var monthKey = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}`;
|
|
1130
|
+
var YEARS_PER_PAGE = 12;
|
|
1131
|
+
var yearPageStart = (y) => Math.floor(y / YEARS_PER_PAGE) * YEARS_PER_PAGE;
|
|
1132
|
+
function monthStart(key) {
|
|
1133
|
+
const m = /^(\d{4})-(\d{2})$/.exec(key);
|
|
1134
|
+
return m ? new Date(Number(m[1]), Number(m[2]) - 1, 1) : /* @__PURE__ */ new Date();
|
|
1135
|
+
}
|
|
1136
|
+
function buildCells(view, weekStartsOn) {
|
|
1137
|
+
const first = new Date(view.getFullYear(), view.getMonth(), 1);
|
|
1138
|
+
const lead = (first.getDay() - weekStartsOn + 7) % 7;
|
|
1139
|
+
const start = new Date(first.getFullYear(), first.getMonth(), 1 - lead);
|
|
1140
|
+
return Array.from({ length: 42 }, (_, i) => new Date(start.getFullYear(), start.getMonth(), start.getDate() + i));
|
|
1141
|
+
}
|
|
1142
|
+
var addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
1143
|
+
var addMonths = (d, n) => {
|
|
1144
|
+
const target = new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
1145
|
+
const lastDay = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
|
|
1146
|
+
return new Date(target.getFullYear(), target.getMonth(), Math.min(d.getDate(), lastDay));
|
|
1147
|
+
};
|
|
1148
|
+
function Calendar({
|
|
1149
|
+
value,
|
|
1150
|
+
endValue,
|
|
1151
|
+
mode = "single",
|
|
1152
|
+
onSelect,
|
|
1153
|
+
min,
|
|
1154
|
+
max,
|
|
1155
|
+
month,
|
|
1156
|
+
defaultMonth,
|
|
1157
|
+
onMonthChange,
|
|
1158
|
+
weekStartsOn = 0,
|
|
1159
|
+
quickJump = true,
|
|
1160
|
+
"aria-label": ariaLabel,
|
|
1161
|
+
className = ""
|
|
1162
|
+
}) {
|
|
1163
|
+
const selected = fromKey(value);
|
|
1164
|
+
const today = /* @__PURE__ */ new Date();
|
|
1165
|
+
const todayKey = toKey(today);
|
|
1166
|
+
const [innerMonth, setInnerMonth] = useState(() => {
|
|
1167
|
+
if (defaultMonth) return defaultMonth;
|
|
1168
|
+
if (selected) return monthKey(selected);
|
|
1169
|
+
const here = monthKey(today);
|
|
1170
|
+
if (min && here < min.slice(0, 7)) return min.slice(0, 7);
|
|
1171
|
+
if (max && here > max.slice(0, 7)) return max.slice(0, 7);
|
|
1172
|
+
return here;
|
|
1173
|
+
});
|
|
1174
|
+
const viewMonth = month ?? innerMonth;
|
|
1175
|
+
const view = monthStart(viewMonth);
|
|
1176
|
+
const [active, setActive] = useState(() => value ?? todayKey);
|
|
1177
|
+
const gridRef = useRef(null);
|
|
1178
|
+
const shouldFocus = useRef(false);
|
|
1179
|
+
const [panel, setPanel] = useState("days");
|
|
1180
|
+
const cells = useMemo(() => buildCells(view, weekStartsOn), [viewMonth, weekStartsOn]);
|
|
1181
|
+
const outOfRange = (key) => !!min && key < min || !!max && key > max;
|
|
1182
|
+
const activeInView = cells.some((c) => toKey(c) === active);
|
|
1183
|
+
const fallbackActive = toKey(cells.find((c) => c.getMonth() === view.getMonth()) ?? cells[0]);
|
|
1184
|
+
const activeKey = activeInView ? active : fallbackActive;
|
|
1185
|
+
useEffect(() => {
|
|
1186
|
+
if (!shouldFocus.current) return;
|
|
1187
|
+
shouldFocus.current = false;
|
|
1188
|
+
gridRef.current?.querySelector('[data-active="true"]')?.focus();
|
|
1189
|
+
}, [activeKey, viewMonth]);
|
|
1190
|
+
const pageBy = (n) => {
|
|
1191
|
+
if (panel === "years") return new Date(view.getFullYear() + n * YEARS_PER_PAGE, view.getMonth(), 1);
|
|
1192
|
+
if (panel === "months") return new Date(view.getFullYear() + n, view.getMonth(), 1);
|
|
1193
|
+
return addMonths(view, n);
|
|
1194
|
+
};
|
|
1195
|
+
const pageBack = () => pageBy(-1);
|
|
1196
|
+
const pageForward = () => pageBy(1);
|
|
1197
|
+
const goToMonth = (next) => {
|
|
1198
|
+
const key = monthKey(next);
|
|
1199
|
+
if (month === void 0) setInnerMonth(key);
|
|
1200
|
+
onMonthChange?.(key);
|
|
1201
|
+
};
|
|
1202
|
+
const moveTo = (next) => {
|
|
1203
|
+
shouldFocus.current = true;
|
|
1204
|
+
setActive(toKey(next));
|
|
1205
|
+
if (monthKey(next) !== viewMonth) goToMonth(next);
|
|
1206
|
+
};
|
|
1207
|
+
const onKeyDown = (e) => {
|
|
1208
|
+
const current = fromKey(activeKey) ?? today;
|
|
1209
|
+
const step = {
|
|
1210
|
+
ArrowLeft: () => addDays(current, -1),
|
|
1211
|
+
ArrowRight: () => addDays(current, 1),
|
|
1212
|
+
ArrowUp: () => addDays(current, -7),
|
|
1213
|
+
ArrowDown: () => addDays(current, 7),
|
|
1214
|
+
// Home and End are the week, not the month: the grid's rows are weeks, and
|
|
1215
|
+
// this is what the ARIA date-grid pattern asks for.
|
|
1216
|
+
Home: () => addDays(current, -((current.getDay() - weekStartsOn + 7) % 7)),
|
|
1217
|
+
End: () => addDays(current, 6 - (current.getDay() - weekStartsOn + 7) % 7),
|
|
1218
|
+
PageUp: () => addMonths(current, e.shiftKey ? -12 : -1),
|
|
1219
|
+
PageDown: () => addMonths(current, e.shiftKey ? 12 : 1)
|
|
1220
|
+
};
|
|
1221
|
+
if (step[e.key]) {
|
|
1222
|
+
e.preventDefault();
|
|
1223
|
+
moveTo(step[e.key]());
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1227
|
+
e.preventDefault();
|
|
1228
|
+
if (!outOfRange(activeKey)) onSelect(activeKey);
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
const inRange = (key) => {
|
|
1232
|
+
if (mode !== "range" || !value || !endValue) return false;
|
|
1233
|
+
return key > value && key < endValue;
|
|
1234
|
+
};
|
|
1235
|
+
const label = ariaLabel ?? `${MONTH_NAMES[view.getMonth()]} ${view.getFullYear()}`;
|
|
1236
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
1237
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between px-1", children: [
|
|
1238
|
+
/* @__PURE__ */ jsx(
|
|
1239
|
+
"button",
|
|
1240
|
+
{
|
|
1241
|
+
type: "button",
|
|
1242
|
+
"aria-label": panel === "years" ? "Previous years" : panel === "months" ? "Previous year" : "Previous month",
|
|
1243
|
+
onClick: () => goToMonth(pageBack()),
|
|
1244
|
+
className: "rounded-full p-1 text-gray-600 hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1245
|
+
children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) })
|
|
1246
|
+
}
|
|
1247
|
+
),
|
|
1248
|
+
/* @__PURE__ */ jsx("div", { "aria-live": "polite", className: "flex items-center gap-1 text-sm font-semibold text-gray-800", children: quickJump ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1249
|
+
panel !== "years" && /* @__PURE__ */ jsx(
|
|
1250
|
+
"button",
|
|
1251
|
+
{
|
|
1252
|
+
type: "button",
|
|
1253
|
+
"aria-label": `Choose a month, currently ${MONTH_NAMES[view.getMonth()]}`,
|
|
1254
|
+
onClick: () => setPanel((p) => p === "months" ? "days" : "months"),
|
|
1255
|
+
className: "rounded-md px-1.5 py-0.5 transition-colors hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1256
|
+
children: MONTH_NAMES[view.getMonth()]
|
|
1257
|
+
}
|
|
1258
|
+
),
|
|
1259
|
+
/* @__PURE__ */ jsx(
|
|
1260
|
+
"button",
|
|
1261
|
+
{
|
|
1262
|
+
type: "button",
|
|
1263
|
+
"aria-label": `Choose a year, currently ${view.getFullYear()}`,
|
|
1264
|
+
onClick: () => setPanel((p) => p === "years" ? "days" : "years"),
|
|
1265
|
+
className: "rounded-md px-1.5 py-0.5 transition-colors hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1266
|
+
children: view.getFullYear()
|
|
1267
|
+
}
|
|
1268
|
+
)
|
|
1269
|
+
] }) : /* @__PURE__ */ jsxs("span", { children: [
|
|
1270
|
+
MONTH_NAMES[view.getMonth()],
|
|
1271
|
+
" ",
|
|
1272
|
+
view.getFullYear()
|
|
1273
|
+
] }) }),
|
|
1274
|
+
/* @__PURE__ */ jsx(
|
|
1275
|
+
"button",
|
|
1276
|
+
{
|
|
1277
|
+
type: "button",
|
|
1278
|
+
"aria-label": panel === "years" ? "Next years" : panel === "months" ? "Next year" : "Next month",
|
|
1279
|
+
onClick: () => goToMonth(pageForward()),
|
|
1280
|
+
className: "rounded-full p-1 text-gray-600 hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1281
|
+
children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
|
|
1282
|
+
}
|
|
1283
|
+
)
|
|
1284
|
+
] }),
|
|
1285
|
+
panel === "months" && /* @__PURE__ */ jsx("div", { role: "group", "aria-label": "Choose a month", className: "grid grid-cols-3 gap-1 text-center text-sm", children: MONTH_NAMES.map((name, m) => /* @__PURE__ */ jsx(
|
|
1286
|
+
"button",
|
|
1287
|
+
{
|
|
1288
|
+
type: "button",
|
|
1289
|
+
"aria-pressed": m === view.getMonth(),
|
|
1290
|
+
onClick: () => {
|
|
1291
|
+
goToMonth(new Date(view.getFullYear(), m, 1));
|
|
1292
|
+
setPanel("days");
|
|
1293
|
+
},
|
|
1294
|
+
className: [
|
|
1295
|
+
"rounded-md py-4 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1296
|
+
m === view.getMonth() ? "bg-blue-600 font-semibold text-white" : m === today.getMonth() && view.getFullYear() === today.getFullYear() ? "font-medium text-blue-600 hover:bg-gray-100" : "text-gray-700 hover:bg-gray-100"
|
|
1297
|
+
].join(" "),
|
|
1298
|
+
children: name.slice(0, 3)
|
|
1299
|
+
},
|
|
1300
|
+
name
|
|
1301
|
+
)) }),
|
|
1302
|
+
panel === "years" && /* @__PURE__ */ jsx("div", { role: "group", "aria-label": "Choose a year", className: "grid grid-cols-3 gap-1 text-center text-sm", children: Array.from({ length: YEARS_PER_PAGE }, (_, i) => yearPageStart(view.getFullYear()) + i).map((y) => /* @__PURE__ */ jsx(
|
|
1303
|
+
"button",
|
|
1304
|
+
{
|
|
1305
|
+
type: "button",
|
|
1306
|
+
"aria-pressed": y === view.getFullYear(),
|
|
1307
|
+
onClick: () => {
|
|
1308
|
+
goToMonth(new Date(y, view.getMonth(), 1));
|
|
1309
|
+
setPanel("months");
|
|
1310
|
+
},
|
|
1311
|
+
className: [
|
|
1312
|
+
"rounded-md py-4 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1313
|
+
y === view.getFullYear() ? "bg-blue-600 font-semibold text-white" : y === today.getFullYear() ? "font-medium text-blue-600 hover:bg-gray-100" : "text-gray-700 hover:bg-gray-100"
|
|
1314
|
+
].join(" "),
|
|
1315
|
+
children: y
|
|
1316
|
+
},
|
|
1317
|
+
y
|
|
1318
|
+
)) }),
|
|
1319
|
+
/* @__PURE__ */ jsxs(
|
|
1320
|
+
"div",
|
|
1321
|
+
{
|
|
1322
|
+
ref: gridRef,
|
|
1323
|
+
role: "grid",
|
|
1324
|
+
"aria-label": label,
|
|
1325
|
+
onKeyDown,
|
|
1326
|
+
hidden: panel !== "days",
|
|
1327
|
+
children: [
|
|
1328
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 text-center text-xs font-medium text-gray-500", children: Array.from({ length: 7 }, (_, i) => (i + weekStartsOn) % 7).map((d) => (
|
|
1329
|
+
// abbr carries the full name: "Su" is read as a word otherwise.
|
|
1330
|
+
/* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": DAY_NAMES[d], className: "py-1", children: /* @__PURE__ */ jsx("abbr", { title: DAY_NAMES[d], className: "no-underline", children: DAY_SHORT[d] }) }, d)
|
|
1331
|
+
)) }),
|
|
1332
|
+
Array.from({ length: 6 }, (_, row) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 text-center text-sm", children: cells.slice(row * 7, row * 7 + 7).map((cell) => {
|
|
1333
|
+
const key = toKey(cell);
|
|
1334
|
+
const outside = cell.getMonth() !== view.getMonth();
|
|
1335
|
+
const isSelected = key === value || mode === "range" && key === endValue;
|
|
1336
|
+
const between = inRange(key);
|
|
1337
|
+
const disabled = outOfRange(key);
|
|
1338
|
+
return /* @__PURE__ */ jsx("div", { role: "gridcell", "aria-selected": isSelected, children: /* @__PURE__ */ jsx(
|
|
1339
|
+
"button",
|
|
1340
|
+
{
|
|
1341
|
+
type: "button",
|
|
1342
|
+
"data-active": key === activeKey,
|
|
1343
|
+
tabIndex: key === activeKey ? 0 : -1,
|
|
1344
|
+
disabled,
|
|
1345
|
+
"aria-label": `${cell.getDate()} ${MONTH_NAMES[cell.getMonth()]} ${cell.getFullYear()}`,
|
|
1346
|
+
"aria-current": key === todayKey ? "date" : void 0,
|
|
1347
|
+
onClick: () => {
|
|
1348
|
+
setActive(key);
|
|
1349
|
+
onSelect(key);
|
|
1350
|
+
},
|
|
1351
|
+
className: [
|
|
1352
|
+
// 44px below `sm`, compact above it. A 32px cell is under
|
|
1353
|
+
// every touch-target guideline there is, and a date grid
|
|
1354
|
+
// is seven of them side by side — the case where missing
|
|
1355
|
+
// by four pixels picks the wrong day rather than nothing.
|
|
1356
|
+
"w-full rounded-md py-1.5 min-h-11 sm:min-h-0 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
1357
|
+
disabled ? "cursor-not-allowed text-gray-300" : isSelected ? "bg-blue-600 font-semibold text-white" : between ? "bg-blue-100 text-blue-800" : outside ? "text-gray-300 hover:bg-gray-100" : "text-gray-700 hover:bg-gray-100",
|
|
1358
|
+
key === todayKey && !isSelected ? "font-semibold text-blue-600" : ""
|
|
1359
|
+
].filter(Boolean).join(" "),
|
|
1360
|
+
children: cell.getDate()
|
|
1361
|
+
}
|
|
1362
|
+
) }, key);
|
|
1363
|
+
}) }, row))
|
|
1364
|
+
]
|
|
1365
|
+
}
|
|
1366
|
+
)
|
|
1367
|
+
] });
|
|
1368
|
+
}
|
|
1101
1369
|
function useClickOutside(ref, onClose) {
|
|
1102
1370
|
useEffect(() => {
|
|
1103
1371
|
const handler = (e) => {
|
|
@@ -1108,10 +1376,8 @@ function useClickOutside(ref, onClose) {
|
|
|
1108
1376
|
}, [ref, onClose]);
|
|
1109
1377
|
}
|
|
1110
1378
|
var PRESET_LABELS = ["Last 2 Weeks", "Last Month", "Last 3 Months", "Last 6 Months", "Last 12 Months"];
|
|
1111
|
-
var
|
|
1112
|
-
var
|
|
1113
|
-
var yearPageStart = (y) => Math.floor(y / YEARS_PER_PAGE) * YEARS_PER_PAGE;
|
|
1114
|
-
var pad = (n) => String(n).padStart(2, "0");
|
|
1379
|
+
var monthKeyOf = (d) => `${d.getFullYear()}-${pad2(d.getMonth() + 1)}`;
|
|
1380
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
1115
1381
|
var EDGE_MARGIN = 8;
|
|
1116
1382
|
function clipBounds(el) {
|
|
1117
1383
|
for (let node = el.parentElement; node; node = node.parentElement) {
|
|
@@ -1125,7 +1391,7 @@ function clipBounds(el) {
|
|
|
1125
1391
|
return { left: 0, right: window.innerWidth };
|
|
1126
1392
|
}
|
|
1127
1393
|
function toISODate(d) {
|
|
1128
|
-
return `${d.getFullYear()}-${
|
|
1394
|
+
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
|
|
1129
1395
|
}
|
|
1130
1396
|
function parseDate(s) {
|
|
1131
1397
|
const [y, m, d] = s.split("-").map(Number);
|
|
@@ -1151,10 +1417,7 @@ function DateRangePicker({
|
|
|
1151
1417
|
const panelRef = useRef(null);
|
|
1152
1418
|
const [align, setAlign] = useState("left");
|
|
1153
1419
|
const now = /* @__PURE__ */ new Date();
|
|
1154
|
-
const [
|
|
1155
|
-
const [year, setYear] = useState(from ? parseDate(from).getFullYear() : now.getFullYear());
|
|
1156
|
-
const [view, setView] = useState("days");
|
|
1157
|
-
const [yearPage, setYearPage] = useState(() => yearPageStart(year));
|
|
1420
|
+
const [viewMonth, setViewMonth] = useState(() => monthKeyOf(from ? parseDate(from) : now));
|
|
1158
1421
|
const displayDate = (s) => s ? formatDisplay(s) : "";
|
|
1159
1422
|
useClickOutside(ref, useCallback(() => {
|
|
1160
1423
|
if (open) setOpen(false);
|
|
@@ -1179,11 +1442,7 @@ function DateRangePicker({
|
|
|
1179
1442
|
setTempFrom(from);
|
|
1180
1443
|
setTempTo(to);
|
|
1181
1444
|
setActivePreset(null);
|
|
1182
|
-
|
|
1183
|
-
setMonth(anchor.getMonth());
|
|
1184
|
-
setYear(anchor.getFullYear());
|
|
1185
|
-
setYearPage(yearPageStart(anchor.getFullYear()));
|
|
1186
|
-
setView("days");
|
|
1445
|
+
setViewMonth(monthKeyOf(from ? parseDate(from) : now));
|
|
1187
1446
|
setOpen(true);
|
|
1188
1447
|
};
|
|
1189
1448
|
const handlePreset = (label) => {
|
|
@@ -1216,10 +1475,7 @@ function DateRangePicker({
|
|
|
1216
1475
|
setTempFrom(toISODate(start));
|
|
1217
1476
|
setTempTo(toISODate(end));
|
|
1218
1477
|
setActivePreset(label);
|
|
1219
|
-
|
|
1220
|
-
setYear(start.getFullYear());
|
|
1221
|
-
setYearPage(yearPageStart(start.getFullYear()));
|
|
1222
|
-
setView("days");
|
|
1478
|
+
setViewMonth(monthKeyOf(start));
|
|
1223
1479
|
};
|
|
1224
1480
|
const handleCalendarSelect = (date) => {
|
|
1225
1481
|
setActivePreset("Custom");
|
|
@@ -1243,57 +1499,6 @@ function DateRangePicker({
|
|
|
1243
1499
|
onChange("", "");
|
|
1244
1500
|
setOpen(false);
|
|
1245
1501
|
};
|
|
1246
|
-
const changeMonth = (delta) => {
|
|
1247
|
-
let m = month + delta, y = year;
|
|
1248
|
-
if (m < 0) {
|
|
1249
|
-
m = 11;
|
|
1250
|
-
y--;
|
|
1251
|
-
} else if (m > 11) {
|
|
1252
|
-
m = 0;
|
|
1253
|
-
y++;
|
|
1254
|
-
}
|
|
1255
|
-
setMonth(m);
|
|
1256
|
-
setYear(y);
|
|
1257
|
-
};
|
|
1258
|
-
const handleStep = (delta) => {
|
|
1259
|
-
if (view === "days") changeMonth(delta);
|
|
1260
|
-
else if (view === "months") setYear(year + delta);
|
|
1261
|
-
else setYearPage(yearPage + delta * YEARS_PER_PAGE);
|
|
1262
|
-
};
|
|
1263
|
-
const selectMonth = (m) => {
|
|
1264
|
-
setMonth(m);
|
|
1265
|
-
setView("days");
|
|
1266
|
-
};
|
|
1267
|
-
const selectYear = (y) => {
|
|
1268
|
-
setYear(y);
|
|
1269
|
-
setView("months");
|
|
1270
|
-
};
|
|
1271
|
-
const openYears = () => {
|
|
1272
|
-
setYearPage(yearPageStart(year));
|
|
1273
|
-
setView("years");
|
|
1274
|
-
};
|
|
1275
|
-
const firstDay = new Date(year, month, 1).getDay();
|
|
1276
|
-
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1277
|
-
const prevDays = new Date(year, month, 0).getDate();
|
|
1278
|
-
const monthName = new Date(year, month).toLocaleString("default", { month: "long" });
|
|
1279
|
-
const cells = [];
|
|
1280
|
-
for (let i = firstDay - 1; i >= 0; i--) {
|
|
1281
|
-
const d = new Date(year, month - 1, prevDays - i);
|
|
1282
|
-
cells.push({ day: prevDays - i, current: false, date: toISODate(d) });
|
|
1283
|
-
}
|
|
1284
|
-
for (let d = 1; d <= daysInMonth; d++) {
|
|
1285
|
-
cells.push({ day: d, current: true, date: toISODate(new Date(year, month, d)) });
|
|
1286
|
-
}
|
|
1287
|
-
const remaining = 42 - cells.length;
|
|
1288
|
-
for (let d = 1; d <= remaining; d++) {
|
|
1289
|
-
cells.push({ day: d, current: false, date: toISODate(new Date(year, month + 1, d)) });
|
|
1290
|
-
}
|
|
1291
|
-
const isInRange = (date) => {
|
|
1292
|
-
if (!tempFrom || !tempTo) return false;
|
|
1293
|
-
const s = tempFrom < tempTo ? tempFrom : tempTo;
|
|
1294
|
-
const e = tempFrom < tempTo ? tempTo : tempFrom;
|
|
1295
|
-
return date > s && date < e;
|
|
1296
|
-
};
|
|
1297
1502
|
const displayText = from && to ? `${displayDate(from)} \u2014 ${displayDate(to)}` : from ? `From ${displayDate(from)}` : to ? `To ${displayDate(to)}` : "";
|
|
1298
1503
|
return /* @__PURE__ */ jsxs("div", { className: "relative", ref, children: [
|
|
1299
1504
|
/* @__PURE__ */ jsxs(
|
|
@@ -1349,85 +1554,18 @@ function DateRangePicker({
|
|
|
1349
1554
|
] })
|
|
1350
1555
|
] }),
|
|
1351
1556
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
|
|
1352
|
-
/* @__PURE__ */
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
),
|
|
1365
|
-
view === "years" ? /* @__PURE__ */ jsxs("span", { className: "px-1.5 py-0.5", children: [
|
|
1366
|
-
yearPage,
|
|
1367
|
-
" \u2013 ",
|
|
1368
|
-
yearPage + YEARS_PER_PAGE - 1
|
|
1369
|
-
] }) : /* @__PURE__ */ jsx(
|
|
1370
|
-
"button",
|
|
1371
|
-
{
|
|
1372
|
-
type: "button",
|
|
1373
|
-
onClick: openYears,
|
|
1374
|
-
className: "px-1.5 py-0.5 rounded-md hover:bg-gray-100 transition-colors",
|
|
1375
|
-
children: year
|
|
1376
|
-
}
|
|
1377
|
-
)
|
|
1378
|
-
] }),
|
|
1379
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => handleStep(1), "aria-label": "Next", className: "p-1 rounded-full hover:bg-gray-100 text-gray-600", children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) }) })
|
|
1380
|
-
] }),
|
|
1381
|
-
/* @__PURE__ */ jsxs("div", { className: "min-h-[13.75rem]", children: [
|
|
1382
|
-
view === "days" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1383
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 text-center text-xs font-medium text-gray-500 mb-1", children: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((d) => /* @__PURE__ */ jsx("div", { className: "py-1", children: d }, d)) }),
|
|
1384
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 text-center text-sm", children: cells.map((c, i) => {
|
|
1385
|
-
const isStart = c.date === tempFrom;
|
|
1386
|
-
const isEnd = c.date === tempTo;
|
|
1387
|
-
const isSelected = isStart || isEnd;
|
|
1388
|
-
const inRange = isInRange(c.date);
|
|
1389
|
-
return /* @__PURE__ */ jsx(
|
|
1390
|
-
"button",
|
|
1391
|
-
{
|
|
1392
|
-
type: "button",
|
|
1393
|
-
onClick: () => handleCalendarSelect(c.date),
|
|
1394
|
-
className: `py-1.5 rounded-md transition-colors ${!c.current ? "text-gray-300" : isSelected ? "bg-blue-600 text-white font-semibold" : inRange ? "bg-blue-100 text-blue-800" : "text-gray-700 hover:bg-gray-100"}`,
|
|
1395
|
-
children: c.day
|
|
1396
|
-
},
|
|
1397
|
-
i
|
|
1398
|
-
);
|
|
1399
|
-
}) })
|
|
1400
|
-
] }),
|
|
1401
|
-
view === "months" && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 text-center text-sm", children: MONTH_NAMES.map((name, m) => {
|
|
1402
|
-
const isCurrent = m === month;
|
|
1403
|
-
const isThisMonth = m === now.getMonth() && year === now.getFullYear();
|
|
1404
|
-
return /* @__PURE__ */ jsx(
|
|
1405
|
-
"button",
|
|
1406
|
-
{
|
|
1407
|
-
type: "button",
|
|
1408
|
-
onClick: () => selectMonth(m),
|
|
1409
|
-
className: `py-4 rounded-md transition-colors ${isCurrent ? "bg-blue-600 text-white font-semibold" : isThisMonth ? "text-blue-600 font-medium hover:bg-gray-100" : "text-gray-700 hover:bg-gray-100"}`,
|
|
1410
|
-
children: name
|
|
1411
|
-
},
|
|
1412
|
-
name
|
|
1413
|
-
);
|
|
1414
|
-
}) }),
|
|
1415
|
-
view === "years" && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 text-center text-sm", children: Array.from({ length: YEARS_PER_PAGE }, (_, i) => yearPage + i).map((y) => {
|
|
1416
|
-
const isCurrent = y === year;
|
|
1417
|
-
const isThisYear = y === now.getFullYear();
|
|
1418
|
-
return /* @__PURE__ */ jsx(
|
|
1419
|
-
"button",
|
|
1420
|
-
{
|
|
1421
|
-
type: "button",
|
|
1422
|
-
onClick: () => selectYear(y),
|
|
1423
|
-
className: `py-4 rounded-md transition-colors ${isCurrent ? "bg-blue-600 text-white font-semibold" : isThisYear ? "text-blue-600 font-medium hover:bg-gray-100" : "text-gray-700 hover:bg-gray-100"}`,
|
|
1424
|
-
children: y
|
|
1425
|
-
},
|
|
1426
|
-
y
|
|
1427
|
-
);
|
|
1428
|
-
}) })
|
|
1429
|
-
] })
|
|
1430
|
-
] }),
|
|
1557
|
+
/* @__PURE__ */ jsx("div", { className: "w-64", children: /* @__PURE__ */ jsx(
|
|
1558
|
+
Calendar,
|
|
1559
|
+
{
|
|
1560
|
+
mode: "range",
|
|
1561
|
+
value: tempFrom || null,
|
|
1562
|
+
endValue: tempTo || null,
|
|
1563
|
+
month: viewMonth,
|
|
1564
|
+
onMonthChange: setViewMonth,
|
|
1565
|
+
onSelect: handleCalendarSelect,
|
|
1566
|
+
"aria-label": "Date range"
|
|
1567
|
+
}
|
|
1568
|
+
) }),
|
|
1431
1569
|
/* @__PURE__ */ jsxs("div", { className: "border-l border-gray-200 pl-4 flex flex-col gap-1 min-w-[130px]", children: [
|
|
1432
1570
|
PRESET_LABELS.map((label) => /* @__PURE__ */ jsx(
|
|
1433
1571
|
"button",
|
|
@@ -1469,45 +1607,14 @@ function DateRangePicker({
|
|
|
1469
1607
|
)
|
|
1470
1608
|
] });
|
|
1471
1609
|
}
|
|
1472
|
-
var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
1473
|
-
function toInputValue(value) {
|
|
1474
|
-
if (value === null || value === void 0 || value === "") return "";
|
|
1475
|
-
if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : toISODate(value);
|
|
1476
|
-
if (ISO_DATE.test(value)) return value;
|
|
1477
|
-
const parsed = new Date(value);
|
|
1478
|
-
return Number.isNaN(parsed.getTime()) ? "" : toISODate(parsed);
|
|
1479
|
-
}
|
|
1480
|
-
function fromInputValue(raw) {
|
|
1481
|
-
if (!ISO_DATE.test(raw)) return null;
|
|
1482
|
-
const [year, month, day] = raw.split("-").map(Number);
|
|
1483
|
-
const date = new Date(year, month - 1, day);
|
|
1484
|
-
return date.getMonth() === month - 1 && date.getDate() === day ? date : null;
|
|
1485
|
-
}
|
|
1486
|
-
var DatePicker = forwardRef(function DatePicker2({ value, onChange, min, max, invalid, size, className = "", ...rest }, ref) {
|
|
1487
|
-
return /* @__PURE__ */ jsx(
|
|
1488
|
-
"input",
|
|
1489
|
-
{
|
|
1490
|
-
ref,
|
|
1491
|
-
type: "date",
|
|
1492
|
-
"aria-invalid": invalid || void 0,
|
|
1493
|
-
value: toInputValue(value),
|
|
1494
|
-
min: toInputValue(min) || void 0,
|
|
1495
|
-
max: toInputValue(max) || void 0,
|
|
1496
|
-
onChange: (event) => onChange?.(fromInputValue(event.target.value)),
|
|
1497
|
-
className: inputClasses({ invalid, size, className }),
|
|
1498
|
-
...rest
|
|
1499
|
-
}
|
|
1500
|
-
);
|
|
1501
|
-
});
|
|
1502
|
-
var DatePicker_default = DatePicker;
|
|
1503
1610
|
var TIME = /^\d{2}:\d{2}(:\d{2})?$/;
|
|
1504
|
-
var
|
|
1505
|
-
function
|
|
1611
|
+
var pad3 = (n) => String(n).padStart(2, "0");
|
|
1612
|
+
function toInputValue(value, withSeconds) {
|
|
1506
1613
|
if (value === null || value === void 0 || value === "") return "";
|
|
1507
1614
|
if (value instanceof Date) {
|
|
1508
1615
|
if (Number.isNaN(value.getTime())) return "";
|
|
1509
|
-
const base = `${
|
|
1510
|
-
return withSeconds ? `${base}:${
|
|
1616
|
+
const base = `${pad3(value.getHours())}:${pad3(value.getMinutes())}`;
|
|
1617
|
+
return withSeconds ? `${base}:${pad3(value.getSeconds())}` : base;
|
|
1511
1618
|
}
|
|
1512
1619
|
return TIME.test(value) ? value : "";
|
|
1513
1620
|
}
|
|
@@ -1520,9 +1627,9 @@ var TimePicker = forwardRef(function TimePicker2({ value, onChange, min, max, in
|
|
|
1520
1627
|
type: "time",
|
|
1521
1628
|
step,
|
|
1522
1629
|
"aria-invalid": invalid || void 0,
|
|
1523
|
-
value:
|
|
1524
|
-
min:
|
|
1525
|
-
max:
|
|
1630
|
+
value: toInputValue(value, withSeconds),
|
|
1631
|
+
min: toInputValue(min, withSeconds) || void 0,
|
|
1632
|
+
max: toInputValue(max, withSeconds) || void 0,
|
|
1526
1633
|
onChange: (event) => onChange?.(TIME.test(event.target.value) ? event.target.value : null),
|
|
1527
1634
|
className: inputClasses({ invalid, size, className }),
|
|
1528
1635
|
...rest
|
|
@@ -1530,10 +1637,252 @@ var TimePicker = forwardRef(function TimePicker2({ value, onChange, min, max, in
|
|
|
1530
1637
|
);
|
|
1531
1638
|
});
|
|
1532
1639
|
var TimePicker_default = TimePicker;
|
|
1640
|
+
var POPUP_MAX_WIDTH = 448;
|
|
1641
|
+
var MENU_MAX_HEIGHT2 = 240;
|
|
1642
|
+
var MENU_GAP2 = 4;
|
|
1643
|
+
var VIEWPORT_MARGIN2 = 8;
|
|
1644
|
+
function useDropdownPosition(triggerRef, open) {
|
|
1645
|
+
const [pos, setPos] = useState(null);
|
|
1646
|
+
useLayoutEffect(() => {
|
|
1647
|
+
if (!open) {
|
|
1648
|
+
setPos(null);
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN;
|
|
1652
|
+
const compute = () => {
|
|
1653
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
1654
|
+
if (!rect) return;
|
|
1655
|
+
lastLeft = rect.left;
|
|
1656
|
+
lastTop = rect.top;
|
|
1657
|
+
lastRight = rect.right;
|
|
1658
|
+
lastBottom = rect.bottom;
|
|
1659
|
+
const spaceBelow = window.innerHeight - rect.bottom - MENU_GAP2 - VIEWPORT_MARGIN2;
|
|
1660
|
+
const spaceAbove = rect.top - MENU_GAP2 - VIEWPORT_MARGIN2;
|
|
1661
|
+
const placeAbove = spaceBelow < Math.min(MENU_MAX_HEIGHT2, 160) && spaceAbove > spaceBelow;
|
|
1662
|
+
const maxHeight = Math.max(96, Math.min(MENU_MAX_HEIGHT2, placeAbove ? spaceAbove : spaceBelow));
|
|
1663
|
+
const next = { minWidth: rect.width, maxHeight };
|
|
1664
|
+
if (window.innerWidth - rect.left < POPUP_MAX_WIDTH) {
|
|
1665
|
+
next.right = Math.max(VIEWPORT_MARGIN2, window.innerWidth - rect.right);
|
|
1666
|
+
} else {
|
|
1667
|
+
next.left = Math.max(VIEWPORT_MARGIN2, rect.left);
|
|
1668
|
+
}
|
|
1669
|
+
if (placeAbove) next.bottom = window.innerHeight - rect.top + MENU_GAP2;
|
|
1670
|
+
else next.top = rect.bottom + MENU_GAP2;
|
|
1671
|
+
setPos(next);
|
|
1672
|
+
};
|
|
1673
|
+
compute();
|
|
1674
|
+
let raf = requestAnimationFrame(function tick() {
|
|
1675
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
1676
|
+
if (rect && (rect.left !== lastLeft || rect.top !== lastTop || rect.right !== lastRight || rect.bottom !== lastBottom)) {
|
|
1677
|
+
compute();
|
|
1678
|
+
}
|
|
1679
|
+
raf = requestAnimationFrame(tick);
|
|
1680
|
+
});
|
|
1681
|
+
window.addEventListener("scroll", compute, true);
|
|
1682
|
+
window.addEventListener("resize", compute);
|
|
1683
|
+
return () => {
|
|
1684
|
+
cancelAnimationFrame(raf);
|
|
1685
|
+
window.removeEventListener("scroll", compute, true);
|
|
1686
|
+
window.removeEventListener("resize", compute);
|
|
1687
|
+
};
|
|
1688
|
+
}, [open, triggerRef]);
|
|
1689
|
+
return pos;
|
|
1690
|
+
}
|
|
1691
|
+
var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
1692
|
+
var MONTH_NAMES2 = [
|
|
1693
|
+
"January",
|
|
1694
|
+
"February",
|
|
1695
|
+
"March",
|
|
1696
|
+
"April",
|
|
1697
|
+
"May",
|
|
1698
|
+
"June",
|
|
1699
|
+
"July",
|
|
1700
|
+
"August",
|
|
1701
|
+
"September",
|
|
1702
|
+
"October",
|
|
1703
|
+
"November",
|
|
1704
|
+
"December"
|
|
1705
|
+
];
|
|
1706
|
+
function toInputValue2(value) {
|
|
1707
|
+
if (value === null || value === void 0 || value === "") return "";
|
|
1708
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : toISODate(value);
|
|
1709
|
+
if (ISO_DATE.test(value)) return value;
|
|
1710
|
+
const parsed = new Date(value);
|
|
1711
|
+
return Number.isNaN(parsed.getTime()) ? "" : toISODate(parsed);
|
|
1712
|
+
}
|
|
1713
|
+
function fromInputValue(raw) {
|
|
1714
|
+
if (!ISO_DATE.test(raw)) return null;
|
|
1715
|
+
const [year, month, day] = raw.split("-").map(Number);
|
|
1716
|
+
const date = new Date(year, month - 1, day);
|
|
1717
|
+
return date.getMonth() === month - 1 && date.getDate() === day ? date : null;
|
|
1718
|
+
}
|
|
1719
|
+
function display(key) {
|
|
1720
|
+
const d = fromInputValue(key);
|
|
1721
|
+
return d ? `${d.getDate()} ${MONTH_NAMES2[d.getMonth()]} ${d.getFullYear()}` : "";
|
|
1722
|
+
}
|
|
1723
|
+
var DatePicker = forwardRef(function DatePicker2({
|
|
1724
|
+
value,
|
|
1725
|
+
onChange,
|
|
1726
|
+
min,
|
|
1727
|
+
max,
|
|
1728
|
+
invalid,
|
|
1729
|
+
size,
|
|
1730
|
+
native,
|
|
1731
|
+
weekStartsOn,
|
|
1732
|
+
className = "",
|
|
1733
|
+
"aria-label": ariaLabel,
|
|
1734
|
+
"aria-describedby": describedBy,
|
|
1735
|
+
id,
|
|
1736
|
+
name,
|
|
1737
|
+
disabled,
|
|
1738
|
+
placeholder,
|
|
1739
|
+
...rest
|
|
1740
|
+
}, ref) {
|
|
1741
|
+
const current = toInputValue2(value);
|
|
1742
|
+
const lo = toInputValue2(min);
|
|
1743
|
+
const hi = toInputValue2(max);
|
|
1744
|
+
const [open, setOpen] = useState(false);
|
|
1745
|
+
const wrapRef = useRef(null);
|
|
1746
|
+
const triggerRef = useRef(null);
|
|
1747
|
+
const panelRef = useRef(null);
|
|
1748
|
+
const panelId = useId();
|
|
1749
|
+
const pos = useDropdownPosition(triggerRef, open);
|
|
1750
|
+
useEffect(() => {
|
|
1751
|
+
if (!open) return;
|
|
1752
|
+
const onPointerDown = (e) => {
|
|
1753
|
+
const target = e.target;
|
|
1754
|
+
if (wrapRef.current?.contains(target) || panelRef.current?.contains(target)) return;
|
|
1755
|
+
setOpen(false);
|
|
1756
|
+
};
|
|
1757
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
1758
|
+
return () => document.removeEventListener("pointerdown", onPointerDown, true);
|
|
1759
|
+
}, [open]);
|
|
1760
|
+
useEffect(() => {
|
|
1761
|
+
if (!open) return;
|
|
1762
|
+
return registerModalEscapeInterceptor((event) => {
|
|
1763
|
+
if (event.key !== "Escape") return false;
|
|
1764
|
+
setOpen(false);
|
|
1765
|
+
triggerRef.current?.focus();
|
|
1766
|
+
return true;
|
|
1767
|
+
});
|
|
1768
|
+
}, [open]);
|
|
1769
|
+
if (native) {
|
|
1770
|
+
return /* @__PURE__ */ jsx(
|
|
1771
|
+
"input",
|
|
1772
|
+
{
|
|
1773
|
+
ref,
|
|
1774
|
+
type: "date",
|
|
1775
|
+
id,
|
|
1776
|
+
name,
|
|
1777
|
+
disabled,
|
|
1778
|
+
"aria-label": ariaLabel,
|
|
1779
|
+
"aria-describedby": describedBy,
|
|
1780
|
+
"aria-invalid": invalid || void 0,
|
|
1781
|
+
value: current,
|
|
1782
|
+
min: lo || void 0,
|
|
1783
|
+
max: hi || void 0,
|
|
1784
|
+
onChange: (event) => onChange?.(fromInputValue(event.target.value)),
|
|
1785
|
+
className: inputClasses({ invalid, size, className }),
|
|
1786
|
+
...rest
|
|
1787
|
+
}
|
|
1788
|
+
);
|
|
1789
|
+
}
|
|
1790
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: "relative", children: [
|
|
1791
|
+
/* @__PURE__ */ jsx("input", { ref, type: "hidden", name, value: current }),
|
|
1792
|
+
/* @__PURE__ */ jsxs(
|
|
1793
|
+
"button",
|
|
1794
|
+
{
|
|
1795
|
+
ref: triggerRef,
|
|
1796
|
+
type: "button",
|
|
1797
|
+
id,
|
|
1798
|
+
disabled,
|
|
1799
|
+
"aria-haspopup": "dialog",
|
|
1800
|
+
"aria-expanded": open,
|
|
1801
|
+
"aria-controls": open ? panelId : void 0,
|
|
1802
|
+
"aria-describedby": describedBy,
|
|
1803
|
+
"aria-invalid": invalid || void 0,
|
|
1804
|
+
"aria-label": ariaLabel ? `${ariaLabel}${current ? `, ${display(current)}` : ""}` : void 0,
|
|
1805
|
+
onClick: () => setOpen((o) => !o),
|
|
1806
|
+
className: `${inputClasses({ invalid, size, className })} flex items-center justify-between text-left`,
|
|
1807
|
+
children: [
|
|
1808
|
+
/* @__PURE__ */ jsx("span", { className: current ? "text-gray-900" : "text-gray-400", children: current ? display(current) : placeholder ?? "Select a date" }),
|
|
1809
|
+
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4 shrink-0 text-gray-400", fill: "none", stroke: "currentColor", strokeWidth: "1.75", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3M4 11h16M5 7h14a1 1 0 011 1v11a1 1 0 01-1 1H5a1 1 0 01-1-1V8a1 1 0 011-1z" }) })
|
|
1810
|
+
]
|
|
1811
|
+
}
|
|
1812
|
+
),
|
|
1813
|
+
open && createPortal(
|
|
1814
|
+
/* @__PURE__ */ jsxs(
|
|
1815
|
+
"div",
|
|
1816
|
+
{
|
|
1817
|
+
ref: panelRef,
|
|
1818
|
+
id: panelId,
|
|
1819
|
+
role: "dialog",
|
|
1820
|
+
"aria-label": ariaLabel ?? "Choose a date",
|
|
1821
|
+
className: "fixed z-[400] w-72 rounded-xl border border-gray-200 bg-white p-3 shadow-lg",
|
|
1822
|
+
style: {
|
|
1823
|
+
left: pos?.left,
|
|
1824
|
+
right: pos?.right,
|
|
1825
|
+
top: pos?.top,
|
|
1826
|
+
bottom: pos?.bottom,
|
|
1827
|
+
// Hidden for the first paint until the layout effect measures the
|
|
1828
|
+
// trigger, so the panel never flashes at (0,0).
|
|
1829
|
+
visibility: pos ? void 0 : "hidden"
|
|
1830
|
+
},
|
|
1831
|
+
children: [
|
|
1832
|
+
/* @__PURE__ */ jsx(
|
|
1833
|
+
Calendar,
|
|
1834
|
+
{
|
|
1835
|
+
value: current || null,
|
|
1836
|
+
min: lo || null,
|
|
1837
|
+
max: hi || null,
|
|
1838
|
+
weekStartsOn,
|
|
1839
|
+
onSelect: (key) => {
|
|
1840
|
+
setOpen(false);
|
|
1841
|
+
triggerRef.current?.focus();
|
|
1842
|
+
onChange?.(fromInputValue(key));
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
),
|
|
1846
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-between border-t border-gray-100 pt-2", children: [
|
|
1847
|
+
/* @__PURE__ */ jsx(
|
|
1848
|
+
"button",
|
|
1849
|
+
{
|
|
1850
|
+
type: "button",
|
|
1851
|
+
onClick: () => {
|
|
1852
|
+
setOpen(false);
|
|
1853
|
+
triggerRef.current?.focus();
|
|
1854
|
+
onChange?.(null);
|
|
1855
|
+
},
|
|
1856
|
+
className: "rounded-md px-2 py-1 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-700",
|
|
1857
|
+
children: "Clear"
|
|
1858
|
+
}
|
|
1859
|
+
),
|
|
1860
|
+
/* @__PURE__ */ jsx(
|
|
1861
|
+
"button",
|
|
1862
|
+
{
|
|
1863
|
+
type: "button",
|
|
1864
|
+
onClick: () => {
|
|
1865
|
+
setOpen(false);
|
|
1866
|
+
triggerRef.current?.focus();
|
|
1867
|
+
onChange?.(/* @__PURE__ */ new Date());
|
|
1868
|
+
},
|
|
1869
|
+
className: "rounded-md px-2 py-1 text-sm font-medium text-blue-600 hover:bg-blue-50",
|
|
1870
|
+
children: "Today"
|
|
1871
|
+
}
|
|
1872
|
+
)
|
|
1873
|
+
] })
|
|
1874
|
+
]
|
|
1875
|
+
}
|
|
1876
|
+
),
|
|
1877
|
+
document.body
|
|
1878
|
+
)
|
|
1879
|
+
] });
|
|
1880
|
+
});
|
|
1881
|
+
var DatePicker_default = DatePicker;
|
|
1533
1882
|
var ISO_LOCAL = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/;
|
|
1534
|
-
var
|
|
1883
|
+
var pad4 = (n) => String(n).padStart(2, "0");
|
|
1535
1884
|
function serialise(date) {
|
|
1536
|
-
return `${date.getFullYear()}-${
|
|
1885
|
+
return `${date.getFullYear()}-${pad4(date.getMonth() + 1)}-${pad4(date.getDate())}T${pad4(date.getHours())}:${pad4(date.getMinutes())}`;
|
|
1537
1886
|
}
|
|
1538
1887
|
function toInputValue3(value) {
|
|
1539
1888
|
if (value === null || value === void 0 || value === "") return "";
|
|
@@ -1677,8 +2026,8 @@ function Segmented({
|
|
|
1677
2026
|
className = ""
|
|
1678
2027
|
}) {
|
|
1679
2028
|
const groupId = useId();
|
|
1680
|
-
const track = `inline-flex items-center gap-1 rounded-lg bg-gray-100 p-1 ${block ? "w-full" : ""} ${className}`.trim();
|
|
1681
|
-
const itemBase = `inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors ${block ? "flex-1" : ""}`;
|
|
2029
|
+
const track = `inline-flex max-w-full items-center gap-1 overflow-x-auto rounded-lg bg-gray-100 p-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden ${block ? "w-full" : ""} ${className}`.trim();
|
|
2030
|
+
const itemBase = `inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap rounded-md font-medium transition-colors ${block ? "flex-1" : ""}`;
|
|
1682
2031
|
if (name) {
|
|
1683
2032
|
return /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": label, className: track, children: options.map((opt) => {
|
|
1684
2033
|
const id = `${groupId}-${opt.value}`;
|
|
@@ -2029,57 +2378,6 @@ function FilePicker({
|
|
|
2029
2378
|
error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-red-600", children: error })
|
|
2030
2379
|
] });
|
|
2031
2380
|
}
|
|
2032
|
-
var POPUP_MAX_WIDTH = 448;
|
|
2033
|
-
var MENU_MAX_HEIGHT2 = 240;
|
|
2034
|
-
var MENU_GAP2 = 4;
|
|
2035
|
-
var VIEWPORT_MARGIN2 = 8;
|
|
2036
|
-
function useDropdownPosition(triggerRef, open) {
|
|
2037
|
-
const [pos, setPos] = useState(null);
|
|
2038
|
-
useLayoutEffect(() => {
|
|
2039
|
-
if (!open) {
|
|
2040
|
-
setPos(null);
|
|
2041
|
-
return;
|
|
2042
|
-
}
|
|
2043
|
-
let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN;
|
|
2044
|
-
const compute = () => {
|
|
2045
|
-
const rect = triggerRef.current?.getBoundingClientRect();
|
|
2046
|
-
if (!rect) return;
|
|
2047
|
-
lastLeft = rect.left;
|
|
2048
|
-
lastTop = rect.top;
|
|
2049
|
-
lastRight = rect.right;
|
|
2050
|
-
lastBottom = rect.bottom;
|
|
2051
|
-
const spaceBelow = window.innerHeight - rect.bottom - MENU_GAP2 - VIEWPORT_MARGIN2;
|
|
2052
|
-
const spaceAbove = rect.top - MENU_GAP2 - VIEWPORT_MARGIN2;
|
|
2053
|
-
const placeAbove = spaceBelow < Math.min(MENU_MAX_HEIGHT2, 160) && spaceAbove > spaceBelow;
|
|
2054
|
-
const maxHeight = Math.max(96, Math.min(MENU_MAX_HEIGHT2, placeAbove ? spaceAbove : spaceBelow));
|
|
2055
|
-
const next = { minWidth: rect.width, maxHeight };
|
|
2056
|
-
if (window.innerWidth - rect.left < POPUP_MAX_WIDTH) {
|
|
2057
|
-
next.right = Math.max(VIEWPORT_MARGIN2, window.innerWidth - rect.right);
|
|
2058
|
-
} else {
|
|
2059
|
-
next.left = Math.max(VIEWPORT_MARGIN2, rect.left);
|
|
2060
|
-
}
|
|
2061
|
-
if (placeAbove) next.bottom = window.innerHeight - rect.top + MENU_GAP2;
|
|
2062
|
-
else next.top = rect.bottom + MENU_GAP2;
|
|
2063
|
-
setPos(next);
|
|
2064
|
-
};
|
|
2065
|
-
compute();
|
|
2066
|
-
let raf = requestAnimationFrame(function tick() {
|
|
2067
|
-
const rect = triggerRef.current?.getBoundingClientRect();
|
|
2068
|
-
if (rect && (rect.left !== lastLeft || rect.top !== lastTop || rect.right !== lastRight || rect.bottom !== lastBottom)) {
|
|
2069
|
-
compute();
|
|
2070
|
-
}
|
|
2071
|
-
raf = requestAnimationFrame(tick);
|
|
2072
|
-
});
|
|
2073
|
-
window.addEventListener("scroll", compute, true);
|
|
2074
|
-
window.addEventListener("resize", compute);
|
|
2075
|
-
return () => {
|
|
2076
|
-
cancelAnimationFrame(raf);
|
|
2077
|
-
window.removeEventListener("scroll", compute, true);
|
|
2078
|
-
window.removeEventListener("resize", compute);
|
|
2079
|
-
};
|
|
2080
|
-
}, [open, triggerRef]);
|
|
2081
|
-
return pos;
|
|
2082
|
-
}
|
|
2083
2381
|
function ClearButton({ onClear, ariaLabel = "Clear selection" }) {
|
|
2084
2382
|
return /* @__PURE__ */ jsx(
|
|
2085
2383
|
"button",
|
|
@@ -2229,7 +2527,7 @@ function SearchableSelect({
|
|
|
2229
2527
|
"div",
|
|
2230
2528
|
{
|
|
2231
2529
|
ref: menuRef,
|
|
2232
|
-
className: "fixed z-[
|
|
2530
|
+
className: "fixed z-[10000] rounded-2xl overflow-hidden",
|
|
2233
2531
|
style: {
|
|
2234
2532
|
left: menuPos?.left,
|
|
2235
2533
|
right: menuPos?.right,
|
|
@@ -2398,7 +2696,7 @@ function TagInput({
|
|
|
2398
2696
|
"div",
|
|
2399
2697
|
{
|
|
2400
2698
|
ref: menuRef,
|
|
2401
|
-
className: "fixed z-[
|
|
2699
|
+
className: "fixed z-[10000] rounded-2xl overflow-hidden",
|
|
2402
2700
|
style: {
|
|
2403
2701
|
left: menuPos?.left,
|
|
2404
2702
|
right: menuPos?.right,
|
|
@@ -2714,23 +3012,23 @@ function DescriptionList({
|
|
|
2714
3012
|
const resolved = typeof columns === "number" ? { base: columns } : columns;
|
|
2715
3013
|
const base = resolved.base ?? 1;
|
|
2716
3014
|
const widest = Math.max(base, resolved.sm ?? 0, resolved.lg ?? 0);
|
|
2717
|
-
const
|
|
3015
|
+
const pad5 = size === "sm" ? "px-3 py-2" : "px-4 py-3";
|
|
2718
3016
|
const text = size === "sm" ? "text-xs" : "text-sm";
|
|
2719
3017
|
return /* @__PURE__ */ jsxs("div", { className: [bordered ? "rounded-lg border border-gray-200 bg-white" : "", className].filter(Boolean).join(" "), children: [
|
|
2720
|
-
title && /* @__PURE__ */ jsx("div", { className: `${
|
|
3018
|
+
title && /* @__PURE__ */ jsx("div", { className: `${pad5} ${bordered ? "border-b border-gray-100" : ""} text-sm font-semibold text-gray-900`.trim(), children: title }),
|
|
2721
3019
|
/* @__PURE__ */ jsx("dl", { className: [
|
|
2722
3020
|
"grid",
|
|
2723
3021
|
COLS2[base],
|
|
2724
3022
|
resolved.sm ? SM[resolved.sm] : "",
|
|
2725
3023
|
resolved.lg ? LG[resolved.lg] : "",
|
|
2726
3024
|
bordered ? "" : "gap-x-6 gap-y-3",
|
|
2727
|
-
bordered ? "" :
|
|
3025
|
+
bordered ? "" : pad5 === "px-4 py-3" ? "py-1" : ""
|
|
2728
3026
|
].filter(Boolean).join(" "), children: items.map((item, i) => /* @__PURE__ */ jsxs(
|
|
2729
3027
|
"div",
|
|
2730
3028
|
{
|
|
2731
3029
|
className: [
|
|
2732
3030
|
item.span ? SPAN[widest] : "",
|
|
2733
|
-
bordered ? `${
|
|
3031
|
+
bordered ? `${pad5} border-b border-gray-100 last:border-b-0` : ""
|
|
2734
3032
|
].filter(Boolean).join(" "),
|
|
2735
3033
|
children: [
|
|
2736
3034
|
/* @__PURE__ */ jsx("dt", { className: `${text} text-gray-500`, children: item.label }),
|
|
@@ -4484,12 +4782,28 @@ function DropdownMenu({
|
|
|
4484
4782
|
)
|
|
4485
4783
|
] });
|
|
4486
4784
|
}
|
|
4487
|
-
var
|
|
4785
|
+
var SIZE_CLASS = {
|
|
4786
|
+
sm: "sm:w-[320px]",
|
|
4787
|
+
md: "sm:w-[448px]",
|
|
4788
|
+
lg: "sm:w-[640px]"
|
|
4789
|
+
};
|
|
4488
4790
|
var SIDE_POSITION = {
|
|
4489
4791
|
right: "inset-y-0 right-0",
|
|
4490
4792
|
left: "inset-y-0 left-0",
|
|
4491
4793
|
bottom: "inset-x-0 bottom-0"
|
|
4492
4794
|
};
|
|
4795
|
+
function CloseButton({ onClose }) {
|
|
4796
|
+
return /* @__PURE__ */ jsx(
|
|
4797
|
+
"button",
|
|
4798
|
+
{
|
|
4799
|
+
type: "button",
|
|
4800
|
+
onClick: onClose,
|
|
4801
|
+
"aria-label": "Close",
|
|
4802
|
+
className: "rounded-md p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
|
|
4803
|
+
children: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6 6l8 8M14 6l-8 8" }) })
|
|
4804
|
+
}
|
|
4805
|
+
);
|
|
4806
|
+
}
|
|
4493
4807
|
function Drawer({
|
|
4494
4808
|
open,
|
|
4495
4809
|
onClose,
|
|
@@ -4500,10 +4814,12 @@ function Drawer({
|
|
|
4500
4814
|
children,
|
|
4501
4815
|
blocking = false,
|
|
4502
4816
|
initialFocus,
|
|
4817
|
+
"aria-label": ariaLabel,
|
|
4503
4818
|
className = ""
|
|
4504
4819
|
}) {
|
|
4505
4820
|
const panelRef = useRef(null);
|
|
4506
4821
|
const bodyId = useId();
|
|
4822
|
+
const titleId = useId();
|
|
4507
4823
|
useFocusTrap(panelRef, open, initialFocus);
|
|
4508
4824
|
useScrollLock(open);
|
|
4509
4825
|
useEffect(() => {
|
|
@@ -4516,7 +4832,7 @@ function Drawer({
|
|
|
4516
4832
|
}, [open, blocking, onClose]);
|
|
4517
4833
|
if (!open) return null;
|
|
4518
4834
|
const isBottom = side === "bottom";
|
|
4519
|
-
const panelStyle = isBottom ? { maxHeight: "85vh" } :
|
|
4835
|
+
const panelStyle = isBottom ? { maxHeight: "85vh" } : void 0;
|
|
4520
4836
|
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[9999]", role: "presentation", children: [
|
|
4521
4837
|
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black/30", onClick: blocking ? void 0 : onClose, "aria-hidden": "true" }),
|
|
4522
4838
|
/* @__PURE__ */ jsxs(
|
|
@@ -4525,29 +4841,27 @@ function Drawer({
|
|
|
4525
4841
|
ref: panelRef,
|
|
4526
4842
|
role: "dialog",
|
|
4527
4843
|
"aria-modal": "true",
|
|
4528
|
-
"aria-
|
|
4844
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
4845
|
+
"aria-label": title ? void 0 : ariaLabel,
|
|
4529
4846
|
"aria-describedby": children ? bodyId : void 0,
|
|
4530
4847
|
style: panelStyle,
|
|
4531
4848
|
className: [
|
|
4532
4849
|
"fixed flex flex-col bg-white shadow-xl",
|
|
4850
|
+
// Full width on a phone, the asked-for width from `sm` up. A 320px
|
|
4851
|
+
// drawer on a 375px screen leaves a 55px strip of scrim: too narrow
|
|
4852
|
+
// to aim at, too wide to read as an edge, and it makes the panel look
|
|
4853
|
+
// like a desktop rail that was squeezed rather than a sheet built for
|
|
4854
|
+
// the screen it is on.
|
|
4855
|
+
isBottom ? "" : `w-full max-w-full ${SIZE_CLASS[size]}`,
|
|
4533
4856
|
SIDE_POSITION[side],
|
|
4534
4857
|
isBottom ? "rounded-t-xl" : "",
|
|
4535
4858
|
className
|
|
4536
4859
|
].filter(Boolean).join(" "),
|
|
4537
4860
|
children: [
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
!blocking && /* @__PURE__ */ jsx(
|
|
4541
|
-
|
|
4542
|
-
{
|
|
4543
|
-
type: "button",
|
|
4544
|
-
onClick: onClose,
|
|
4545
|
-
"aria-label": "Close",
|
|
4546
|
-
className: "rounded-md p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600",
|
|
4547
|
-
children: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6 6l8 8M14 6l-8 8" }) })
|
|
4548
|
-
}
|
|
4549
|
-
)
|
|
4550
|
-
] }),
|
|
4861
|
+
title ? /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between gap-4 border-b border-gray-100 px-4 py-3", children: [
|
|
4862
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "text-base font-semibold text-gray-900", children: title }),
|
|
4863
|
+
!blocking && /* @__PURE__ */ jsx(CloseButton, { onClose })
|
|
4864
|
+
] }) : !blocking && /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 z-10", children: /* @__PURE__ */ jsx(CloseButton, { onClose }) }),
|
|
4551
4865
|
/* @__PURE__ */ jsx("div", { id: bodyId, className: "min-h-0 flex-1 overflow-y-auto px-4 py-4", children }),
|
|
4552
4866
|
footer && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 justify-end gap-3 border-t border-gray-100 px-4 py-3", children: footer })
|
|
4553
4867
|
]
|
|
@@ -5204,8 +5518,8 @@ function Sparkline({
|
|
|
5204
5518
|
const max = Math.max(...data);
|
|
5205
5519
|
const min = Math.min(...data);
|
|
5206
5520
|
const span = max - min || 1;
|
|
5207
|
-
const
|
|
5208
|
-
const y = (v) => height -
|
|
5521
|
+
const pad5 = strokeWidth + (showDots ? 2 : 0);
|
|
5522
|
+
const y = (v) => height - pad5 - (v - min) / span * (height - pad5 * 2);
|
|
5209
5523
|
const pts = data.length === 1 ? [[0, height / 2], [width, height / 2]] : data.map((v, i) => [i * width / (data.length - 1), y(v)]);
|
|
5210
5524
|
const line = pts.map(([x, yy], i) => `${i === 0 ? "M" : "L"}${x.toFixed(2)},${yy.toFixed(2)}`).join(" ");
|
|
5211
5525
|
const area = `${line} L${width.toFixed(2)},${height} L0,${height} Z`;
|
|
@@ -6107,6 +6421,6 @@ var ALT_SHIFT_D = isMac ? "\u2325\u21E7D" : "Alt+Shift+D";
|
|
|
6107
6421
|
var ALT_SHIFT_E = isMac ? "\u2325\u21E7E" : "Alt+Shift+E";
|
|
6108
6422
|
var ALT_SHIFT_N = isMac ? "\u2325\u21E7N" : "Alt+Shift+N";
|
|
6109
6423
|
|
|
6110
|
-
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, DateTimePicker_default, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, ENTER, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker, FormField, FormLayoutPage, GROUP_COLORS, GalleryTemplate, GlobalSearch, Grid, HelpCenter, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, LineChart, 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, Stepper, Switch_default, Tabs, TagInput, Text, Textarea_default, TileButton_default, TimePicker_default, Title, Tooltip, TopNav, appendKey, applyThemePrefs, backspace, firstEnabledIndex, formatDate, inputClasses, isMac, isSeverityTone, lastEnabledIndex, matchTypeahead, mediaFileName, nextEnabledIndex, resolveTheme, severityOf, tabButtonId, tabPanelId, toISODate, useClickOutside, useTheme };
|
|
6111
|
-
//# sourceMappingURL=chunk-
|
|
6112
|
-
//# sourceMappingURL=chunk-
|
|
6424
|
+
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, Calendar, Card, ChatTemplate, Checkbox_default, CheckoutTemplate, ColoredBadge, ContainerFillChart, CountBadge, DashboardTemplate, DataTable, DataTablePage, DatePicker_default, DateRangePicker, DateTimePicker_default, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, ENTER, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker, FormField, FormLayoutPage, GROUP_COLORS, GalleryTemplate, GlobalSearch, Grid, HelpCenter, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, LineChart, 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, Stepper, Switch_default, Tabs, TagInput, Text, Textarea_default, TileButton_default, TimePicker_default, Title, Tooltip, TopNav, appendKey, applyThemePrefs, backspace, firstEnabledIndex, formatDate, fromKey, inputClasses, isMac, isSeverityTone, lastEnabledIndex, matchTypeahead, mediaFileName, nextEnabledIndex, resolveTheme, severityOf, tabButtonId, tabPanelId, toISODate, toKey, useClickOutside, useTheme };
|
|
6425
|
+
//# sourceMappingURL=chunk-B3IYV7JN.js.map
|
|
6426
|
+
//# sourceMappingURL=chunk-B3IYV7JN.js.map
|