react-os-shell 4.63.0 → 4.74.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.
Files changed (64) hide show
  1. package/README.md +3 -0
  2. package/dist/{Browser-SPTNLEMR.js → Browser-ZF5X2FON.js} +7 -7
  3. package/dist/{Browser-SPTNLEMR.js.map → Browser-ZF5X2FON.js.map} +1 -1
  4. package/dist/{Calculator-XMOPPCK3.js → Calculator-SA62H5S3.js} +6 -6
  5. package/dist/{Calculator-XMOPPCK3.js.map → Calculator-SA62H5S3.js.map} +1 -1
  6. package/dist/ConfirmDialog-SREDNTIB.js +3 -0
  7. package/dist/{ConfirmDialog-EEH4CWSW.js.map → ConfirmDialog-SREDNTIB.js.map} +1 -1
  8. package/dist/{CurrencyConverter-24HNX6C6.js → CurrencyConverter-BMCRLZLY.js} +6 -6
  9. package/dist/{CurrencyConverter-24HNX6C6.js.map → CurrencyConverter-BMCRLZLY.js.map} +1 -1
  10. package/dist/{Documents-GMRVVCH7.js → Documents-2TGJPV2Y.js} +8 -8
  11. package/dist/{Documents-GMRVVCH7.js.map → Documents-2TGJPV2Y.js.map} +1 -1
  12. package/dist/{Files-ITH4SVML.js → Files-Z3ONKUA6.js} +9 -9
  13. package/dist/{Files-ITH4SVML.js.map → Files-Z3ONKUA6.js.map} +1 -1
  14. package/dist/{Notepad-GE5P55TL.js → Notepad-JWZS5YKJ.js} +8 -8
  15. package/dist/{Notepad-GE5P55TL.js.map → Notepad-JWZS5YKJ.js.map} +1 -1
  16. package/dist/{PomodoroTimer-ER5STVKM.js → PomodoroTimer-DRM5W25H.js} +8 -8
  17. package/dist/{PomodoroTimer-ER5STVKM.js.map → PomodoroTimer-DRM5W25H.js.map} +1 -1
  18. package/dist/{Preview-UXVDXCDJ.js → Preview-7O7W7OMQ.js} +9 -9
  19. package/dist/{Preview-UXVDXCDJ.js.map → Preview-7O7W7OMQ.js.map} +1 -1
  20. package/dist/{Spreadsheet-B32JQVX4.js → Spreadsheet-CLTZSW3T.js} +7 -7
  21. package/dist/{Spreadsheet-B32JQVX4.js.map → Spreadsheet-CLTZSW3T.js.map} +1 -1
  22. package/dist/{Stock-FSFPFDQT.js → Stock-CO5N3N2M.js} +6 -6
  23. package/dist/{Stock-FSFPFDQT.js.map → Stock-CO5N3N2M.js.map} +1 -1
  24. package/dist/{Weather-HXOERJJV.js → Weather-IEGJX7RI.js} +6 -6
  25. package/dist/{Weather-HXOERJJV.js.map → Weather-IEGJX7RI.js.map} +1 -1
  26. package/dist/{WorldClock-2FUGLIUZ.js → WorldClock-FLW3QZYG.js} +6 -6
  27. package/dist/{WorldClock-2FUGLIUZ.js.map → WorldClock-FLW3QZYG.js.map} +1 -1
  28. package/dist/apps/index.js +17 -17
  29. package/dist/{chunk-TK6HI2U4.js → chunk-2VM2FRZJ.js} +42 -11
  30. package/dist/chunk-2VM2FRZJ.js.map +1 -0
  31. package/dist/{chunk-ECE3B3FZ.js → chunk-AXWC3332.js} +3 -3
  32. package/dist/{chunk-ECE3B3FZ.js.map → chunk-AXWC3332.js.map} +1 -1
  33. package/dist/{chunk-ZCDFNZQS.js → chunk-BLLINYDD.js} +97 -5
  34. package/dist/chunk-BLLINYDD.js.map +1 -0
  35. package/dist/{chunk-OXLLRKBC.js → chunk-CDR2Q64Q.js} +38 -22
  36. package/dist/chunk-CDR2Q64Q.js.map +1 -0
  37. package/dist/{chunk-TO6ZZHJK.js → chunk-EG3WEQBH.js} +4 -4
  38. package/dist/{chunk-TO6ZZHJK.js.map → chunk-EG3WEQBH.js.map} +1 -1
  39. package/dist/{chunk-JMESET3G.js → chunk-G7IHPEJE.js} +138 -39
  40. package/dist/chunk-G7IHPEJE.js.map +1 -0
  41. package/dist/chunk-NJDH5PHA.js +7 -0
  42. package/dist/{chunk-WCGHIJZR.js.map → chunk-NJDH5PHA.js.map} +1 -1
  43. package/dist/{chunk-LYQVLRWQ.js → chunk-RUAZJ54W.js} +3 -3
  44. package/dist/{chunk-LYQVLRWQ.js.map → chunk-RUAZJ54W.js.map} +1 -1
  45. package/dist/{chunk-CWA27IGB.js → chunk-S6K37RLY.js} +781 -344
  46. package/dist/chunk-S6K37RLY.js.map +1 -0
  47. package/dist/{chunk-IOCOH2QQ.js → chunk-TT2WNTDS.js} +4 -4
  48. package/dist/{chunk-IOCOH2QQ.js.map → chunk-TT2WNTDS.js.map} +1 -1
  49. package/dist/{chunk-3OCL3DB4.js → chunk-TT56U4GY.js} +3 -3
  50. package/dist/{chunk-3OCL3DB4.js.map → chunk-TT56U4GY.js.map} +1 -1
  51. package/dist/{index-Ka32s3Ij.d.ts → index-DVekeidu.d.ts} +258 -27
  52. package/dist/index.d.ts +2 -2
  53. package/dist/index.js +121 -35
  54. package/dist/index.js.map +1 -1
  55. package/dist/ui/index.d.ts +1 -1
  56. package/dist/ui/index.js +5 -5
  57. package/package.json +2 -2
  58. package/dist/ConfirmDialog-EEH4CWSW.js +0 -3
  59. package/dist/chunk-CWA27IGB.js.map +0 -1
  60. package/dist/chunk-JMESET3G.js.map +0 -1
  61. package/dist/chunk-OXLLRKBC.js.map +0 -1
  62. package/dist/chunk-TK6HI2U4.js.map +0 -1
  63. package/dist/chunk-WCGHIJZR.js +0 -7
  64. package/dist/chunk-ZCDFNZQS.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { Breadcrumbs } from './chunk-HNH7FOYB.js';
2
2
  import { SidebarLayout } from './chunk-YG45DAUT.js';
3
- import { useIsMobile, PopupMenu, PopupMenuItem, useShellPrefs } from './chunk-ZCDFNZQS.js';
4
- import { registerModalEscapeInterceptor, useFocusTrap, useScrollLock } from './chunk-OXLLRKBC.js';
3
+ import { useIsMobile, useShellStrings, PopupMenu, PopupMenuItem, useShellPrefs } from './chunk-BLLINYDD.js';
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 pad4 = `${leftIcon ? "pl-9" : ""} ${rightAdornment ? "pr-9" : ""}`.trim();
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: [pad4, className].filter(Boolean).join(" ") }),
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 next = { left, minWidth: rect.width, maxHeight };
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-[400] overflow-y-auto rounded-2xl py-1",
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
- minWidth: menuPos?.minWidth,
506
+ width: menuPos?.width,
506
507
  maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT,
507
508
  visibility: menuPos ? void 0 : "hidden",
508
509
  ...glassStyle()
@@ -638,6 +639,47 @@ function FormField({
638
639
  ) : hint ? /* @__PURE__ */ jsx("p", { id: htmlFor ? `${htmlFor}-hint` : void 0, className: "mt-1 text-[11px] text-gray-400", children: hint }) : null
639
640
  ] });
640
641
  }
642
+ function FormErrorSummary({ errors, title, autoFocus = true, className = "" }) {
643
+ const strings = useShellStrings();
644
+ const boxRef = useRef(null);
645
+ const hadErrors = useRef(false);
646
+ useEffect(() => {
647
+ const has = errors.length > 0;
648
+ if (has && !hadErrors.current && autoFocus) boxRef.current?.focus();
649
+ hadErrors.current = has;
650
+ }, [errors.length > 0, autoFocus]);
651
+ if (errors.length === 0) return null;
652
+ const focusField = (fieldId) => {
653
+ const el = document.getElementById(fieldId);
654
+ if (!el) return;
655
+ el.scrollIntoView({ block: "center" });
656
+ el.focus();
657
+ };
658
+ return /* @__PURE__ */ jsxs(
659
+ "div",
660
+ {
661
+ ref: boxRef,
662
+ role: "alert",
663
+ tabIndex: -1,
664
+ className: `rounded-md border border-red-300 bg-red-50 px-4 py-3 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-400 ${className}`.trim(),
665
+ children: [
666
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-red-800", children: title ?? strings.form.errorSummaryTitle }),
667
+ /* @__PURE__ */ jsx("ul", { className: "mt-1.5 space-y-1", children: errors.map((e, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
668
+ "a",
669
+ {
670
+ href: `#${e.fieldId}`,
671
+ onClick: (event) => {
672
+ event.preventDefault();
673
+ focusField(e.fieldId);
674
+ },
675
+ className: "text-sm text-red-700 underline hover:text-red-900",
676
+ children: e.message
677
+ }
678
+ ) }, `${e.fieldId}-${i}`)) })
679
+ ]
680
+ }
681
+ );
682
+ }
641
683
  function Label({ required, children, className = "", ...rest }) {
642
684
  return /* @__PURE__ */ jsxs("label", { className: `mb-1 block text-xs font-medium text-gray-600 ${className}`.trim(), ...rest, children: [
643
685
  children,
@@ -1098,6 +1140,273 @@ function MediaUploadGrid({
1098
1140
  }
1099
1141
  ) });
1100
1142
  }
1143
+ var MONTH_NAMES = [
1144
+ "January",
1145
+ "February",
1146
+ "March",
1147
+ "April",
1148
+ "May",
1149
+ "June",
1150
+ "July",
1151
+ "August",
1152
+ "September",
1153
+ "October",
1154
+ "November",
1155
+ "December"
1156
+ ];
1157
+ var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
1158
+ var DAY_SHORT = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
1159
+ var pad = (n) => String(n).padStart(2, "0");
1160
+ function toKey(d) {
1161
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
1162
+ }
1163
+ function fromKey(key) {
1164
+ if (!key) return null;
1165
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(key);
1166
+ if (!m) return null;
1167
+ const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
1168
+ return Number.isNaN(d.getTime()) ? null : d;
1169
+ }
1170
+ var monthKey = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}`;
1171
+ var YEARS_PER_PAGE = 12;
1172
+ var yearPageStart = (y) => Math.floor(y / YEARS_PER_PAGE) * YEARS_PER_PAGE;
1173
+ function monthStart(key) {
1174
+ const m = /^(\d{4})-(\d{2})$/.exec(key);
1175
+ return m ? new Date(Number(m[1]), Number(m[2]) - 1, 1) : /* @__PURE__ */ new Date();
1176
+ }
1177
+ function buildCells(view, weekStartsOn) {
1178
+ const first = new Date(view.getFullYear(), view.getMonth(), 1);
1179
+ const lead = (first.getDay() - weekStartsOn + 7) % 7;
1180
+ const start = new Date(first.getFullYear(), first.getMonth(), 1 - lead);
1181
+ return Array.from({ length: 42 }, (_, i) => new Date(start.getFullYear(), start.getMonth(), start.getDate() + i));
1182
+ }
1183
+ var addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
1184
+ var addMonths = (d, n) => {
1185
+ const target = new Date(d.getFullYear(), d.getMonth() + n, 1);
1186
+ const lastDay = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
1187
+ return new Date(target.getFullYear(), target.getMonth(), Math.min(d.getDate(), lastDay));
1188
+ };
1189
+ function Calendar({
1190
+ value,
1191
+ endValue,
1192
+ mode = "single",
1193
+ onSelect,
1194
+ min,
1195
+ max,
1196
+ month,
1197
+ defaultMonth,
1198
+ onMonthChange,
1199
+ weekStartsOn = 0,
1200
+ quickJump = true,
1201
+ "aria-label": ariaLabel,
1202
+ className = ""
1203
+ }) {
1204
+ const selected = fromKey(value);
1205
+ const today = /* @__PURE__ */ new Date();
1206
+ const todayKey = toKey(today);
1207
+ const [innerMonth, setInnerMonth] = useState(() => {
1208
+ if (defaultMonth) return defaultMonth;
1209
+ if (selected) return monthKey(selected);
1210
+ const here = monthKey(today);
1211
+ if (min && here < min.slice(0, 7)) return min.slice(0, 7);
1212
+ if (max && here > max.slice(0, 7)) return max.slice(0, 7);
1213
+ return here;
1214
+ });
1215
+ const viewMonth = month ?? innerMonth;
1216
+ const view = monthStart(viewMonth);
1217
+ const [active, setActive] = useState(() => value ?? todayKey);
1218
+ const gridRef = useRef(null);
1219
+ const shouldFocus = useRef(false);
1220
+ const [panel, setPanel] = useState("days");
1221
+ const cells = useMemo(() => buildCells(view, weekStartsOn), [viewMonth, weekStartsOn]);
1222
+ const outOfRange = (key) => !!min && key < min || !!max && key > max;
1223
+ const activeInView = cells.some((c) => toKey(c) === active);
1224
+ const fallbackActive = toKey(cells.find((c) => c.getMonth() === view.getMonth()) ?? cells[0]);
1225
+ const activeKey = activeInView ? active : fallbackActive;
1226
+ useEffect(() => {
1227
+ if (!shouldFocus.current) return;
1228
+ shouldFocus.current = false;
1229
+ gridRef.current?.querySelector('[data-active="true"]')?.focus();
1230
+ }, [activeKey, viewMonth]);
1231
+ const pageBy = (n) => {
1232
+ if (panel === "years") return new Date(view.getFullYear() + n * YEARS_PER_PAGE, view.getMonth(), 1);
1233
+ if (panel === "months") return new Date(view.getFullYear() + n, view.getMonth(), 1);
1234
+ return addMonths(view, n);
1235
+ };
1236
+ const pageBack = () => pageBy(-1);
1237
+ const pageForward = () => pageBy(1);
1238
+ const goToMonth = (next) => {
1239
+ const key = monthKey(next);
1240
+ if (month === void 0) setInnerMonth(key);
1241
+ onMonthChange?.(key);
1242
+ };
1243
+ const moveTo = (next) => {
1244
+ shouldFocus.current = true;
1245
+ setActive(toKey(next));
1246
+ if (monthKey(next) !== viewMonth) goToMonth(next);
1247
+ };
1248
+ const onKeyDown = (e) => {
1249
+ const current = fromKey(activeKey) ?? today;
1250
+ const step = {
1251
+ ArrowLeft: () => addDays(current, -1),
1252
+ ArrowRight: () => addDays(current, 1),
1253
+ ArrowUp: () => addDays(current, -7),
1254
+ ArrowDown: () => addDays(current, 7),
1255
+ // Home and End are the week, not the month: the grid's rows are weeks, and
1256
+ // this is what the ARIA date-grid pattern asks for.
1257
+ Home: () => addDays(current, -((current.getDay() - weekStartsOn + 7) % 7)),
1258
+ End: () => addDays(current, 6 - (current.getDay() - weekStartsOn + 7) % 7),
1259
+ PageUp: () => addMonths(current, e.shiftKey ? -12 : -1),
1260
+ PageDown: () => addMonths(current, e.shiftKey ? 12 : 1)
1261
+ };
1262
+ if (step[e.key]) {
1263
+ e.preventDefault();
1264
+ moveTo(step[e.key]());
1265
+ return;
1266
+ }
1267
+ if (e.key === "Enter" || e.key === " ") {
1268
+ e.preventDefault();
1269
+ if (!outOfRange(activeKey)) onSelect(activeKey);
1270
+ }
1271
+ };
1272
+ const inRange = (key) => {
1273
+ if (mode !== "range" || !value || !endValue) return false;
1274
+ return key > value && key < endValue;
1275
+ };
1276
+ const label = ariaLabel ?? `${MONTH_NAMES[view.getMonth()]} ${view.getFullYear()}`;
1277
+ return /* @__PURE__ */ jsxs("div", { className, children: [
1278
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between px-1", children: [
1279
+ /* @__PURE__ */ jsx(
1280
+ "button",
1281
+ {
1282
+ type: "button",
1283
+ "aria-label": panel === "years" ? "Previous years" : panel === "months" ? "Previous year" : "Previous month",
1284
+ onClick: () => goToMonth(pageBack()),
1285
+ className: "rounded-full p-1 text-gray-600 hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
1286
+ 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" }) })
1287
+ }
1288
+ ),
1289
+ /* @__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: [
1290
+ panel !== "years" && /* @__PURE__ */ jsx(
1291
+ "button",
1292
+ {
1293
+ type: "button",
1294
+ "aria-label": `Choose a month, currently ${MONTH_NAMES[view.getMonth()]}`,
1295
+ onClick: () => setPanel((p) => p === "months" ? "days" : "months"),
1296
+ 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",
1297
+ children: MONTH_NAMES[view.getMonth()]
1298
+ }
1299
+ ),
1300
+ /* @__PURE__ */ jsx(
1301
+ "button",
1302
+ {
1303
+ type: "button",
1304
+ "aria-label": `Choose a year, currently ${view.getFullYear()}`,
1305
+ onClick: () => setPanel((p) => p === "years" ? "days" : "years"),
1306
+ 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",
1307
+ children: view.getFullYear()
1308
+ }
1309
+ )
1310
+ ] }) : /* @__PURE__ */ jsxs("span", { children: [
1311
+ MONTH_NAMES[view.getMonth()],
1312
+ " ",
1313
+ view.getFullYear()
1314
+ ] }) }),
1315
+ /* @__PURE__ */ jsx(
1316
+ "button",
1317
+ {
1318
+ type: "button",
1319
+ "aria-label": panel === "years" ? "Next years" : panel === "months" ? "Next year" : "Next month",
1320
+ onClick: () => goToMonth(pageForward()),
1321
+ className: "rounded-full p-1 text-gray-600 hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
1322
+ 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" }) })
1323
+ }
1324
+ )
1325
+ ] }),
1326
+ 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(
1327
+ "button",
1328
+ {
1329
+ type: "button",
1330
+ "aria-pressed": m === view.getMonth(),
1331
+ onClick: () => {
1332
+ goToMonth(new Date(view.getFullYear(), m, 1));
1333
+ setPanel("days");
1334
+ },
1335
+ className: [
1336
+ "rounded-md py-4 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
1337
+ 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"
1338
+ ].join(" "),
1339
+ children: name.slice(0, 3)
1340
+ },
1341
+ name
1342
+ )) }),
1343
+ 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(
1344
+ "button",
1345
+ {
1346
+ type: "button",
1347
+ "aria-pressed": y === view.getFullYear(),
1348
+ onClick: () => {
1349
+ goToMonth(new Date(y, view.getMonth(), 1));
1350
+ setPanel("months");
1351
+ },
1352
+ className: [
1353
+ "rounded-md py-4 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400",
1354
+ 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"
1355
+ ].join(" "),
1356
+ children: y
1357
+ },
1358
+ y
1359
+ )) }),
1360
+ /* @__PURE__ */ jsxs(
1361
+ "div",
1362
+ {
1363
+ ref: gridRef,
1364
+ role: "grid",
1365
+ "aria-label": label,
1366
+ onKeyDown,
1367
+ hidden: panel !== "days",
1368
+ children: [
1369
+ /* @__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) => (
1370
+ // abbr carries the full name: "Su" is read as a word otherwise.
1371
+ /* @__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)
1372
+ )) }),
1373
+ 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) => {
1374
+ const key = toKey(cell);
1375
+ const outside = cell.getMonth() !== view.getMonth();
1376
+ const isSelected = key === value || mode === "range" && key === endValue;
1377
+ const between = inRange(key);
1378
+ const disabled = outOfRange(key);
1379
+ return /* @__PURE__ */ jsx("div", { role: "gridcell", "aria-selected": isSelected, children: /* @__PURE__ */ jsx(
1380
+ "button",
1381
+ {
1382
+ type: "button",
1383
+ "data-active": key === activeKey,
1384
+ tabIndex: key === activeKey ? 0 : -1,
1385
+ disabled,
1386
+ "aria-label": `${cell.getDate()} ${MONTH_NAMES[cell.getMonth()]} ${cell.getFullYear()}`,
1387
+ "aria-current": key === todayKey ? "date" : void 0,
1388
+ onClick: () => {
1389
+ setActive(key);
1390
+ onSelect(key);
1391
+ },
1392
+ className: [
1393
+ // 44px below `sm`, compact above it. A 32px cell is under
1394
+ // every touch-target guideline there is, and a date grid
1395
+ // is seven of them side by side — the case where missing
1396
+ // by four pixels picks the wrong day rather than nothing.
1397
+ "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",
1398
+ 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",
1399
+ key === todayKey && !isSelected ? "font-semibold text-blue-600" : ""
1400
+ ].filter(Boolean).join(" "),
1401
+ children: cell.getDate()
1402
+ }
1403
+ ) }, key);
1404
+ }) }, row))
1405
+ ]
1406
+ }
1407
+ )
1408
+ ] });
1409
+ }
1101
1410
  function useClickOutside(ref, onClose) {
1102
1411
  useEffect(() => {
1103
1412
  const handler = (e) => {
@@ -1108,10 +1417,8 @@ function useClickOutside(ref, onClose) {
1108
1417
  }, [ref, onClose]);
1109
1418
  }
1110
1419
  var PRESET_LABELS = ["Last 2 Weeks", "Last Month", "Last 3 Months", "Last 6 Months", "Last 12 Months"];
1111
- var MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
1112
- var YEARS_PER_PAGE = 12;
1113
- var yearPageStart = (y) => Math.floor(y / YEARS_PER_PAGE) * YEARS_PER_PAGE;
1114
- var pad = (n) => String(n).padStart(2, "0");
1420
+ var monthKeyOf = (d) => `${d.getFullYear()}-${pad2(d.getMonth() + 1)}`;
1421
+ var pad2 = (n) => String(n).padStart(2, "0");
1115
1422
  var EDGE_MARGIN = 8;
1116
1423
  function clipBounds(el) {
1117
1424
  for (let node = el.parentElement; node; node = node.parentElement) {
@@ -1125,7 +1432,7 @@ function clipBounds(el) {
1125
1432
  return { left: 0, right: window.innerWidth };
1126
1433
  }
1127
1434
  function toISODate(d) {
1128
- return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
1435
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
1129
1436
  }
1130
1437
  function parseDate(s) {
1131
1438
  const [y, m, d] = s.split("-").map(Number);
@@ -1151,10 +1458,7 @@ function DateRangePicker({
1151
1458
  const panelRef = useRef(null);
1152
1459
  const [align, setAlign] = useState("left");
1153
1460
  const now = /* @__PURE__ */ new Date();
1154
- const [month, setMonth] = useState(from ? parseDate(from).getMonth() : now.getMonth());
1155
- const [year, setYear] = useState(from ? parseDate(from).getFullYear() : now.getFullYear());
1156
- const [view, setView] = useState("days");
1157
- const [yearPage, setYearPage] = useState(() => yearPageStart(year));
1461
+ const [viewMonth, setViewMonth] = useState(() => monthKeyOf(from ? parseDate(from) : now));
1158
1462
  const displayDate = (s) => s ? formatDisplay(s) : "";
1159
1463
  useClickOutside(ref, useCallback(() => {
1160
1464
  if (open) setOpen(false);
@@ -1179,11 +1483,7 @@ function DateRangePicker({
1179
1483
  setTempFrom(from);
1180
1484
  setTempTo(to);
1181
1485
  setActivePreset(null);
1182
- const anchor = from ? parseDate(from) : now;
1183
- setMonth(anchor.getMonth());
1184
- setYear(anchor.getFullYear());
1185
- setYearPage(yearPageStart(anchor.getFullYear()));
1186
- setView("days");
1486
+ setViewMonth(monthKeyOf(from ? parseDate(from) : now));
1187
1487
  setOpen(true);
1188
1488
  };
1189
1489
  const handlePreset = (label) => {
@@ -1216,10 +1516,7 @@ function DateRangePicker({
1216
1516
  setTempFrom(toISODate(start));
1217
1517
  setTempTo(toISODate(end));
1218
1518
  setActivePreset(label);
1219
- setMonth(start.getMonth());
1220
- setYear(start.getFullYear());
1221
- setYearPage(yearPageStart(start.getFullYear()));
1222
- setView("days");
1519
+ setViewMonth(monthKeyOf(start));
1223
1520
  };
1224
1521
  const handleCalendarSelect = (date) => {
1225
1522
  setActivePreset("Custom");
@@ -1243,57 +1540,6 @@ function DateRangePicker({
1243
1540
  onChange("", "");
1244
1541
  setOpen(false);
1245
1542
  };
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
1543
  const displayText = from && to ? `${displayDate(from)} \u2014 ${displayDate(to)}` : from ? `From ${displayDate(from)}` : to ? `To ${displayDate(to)}` : "";
1298
1544
  return /* @__PURE__ */ jsxs("div", { className: "relative", ref, children: [
1299
1545
  /* @__PURE__ */ jsxs(
@@ -1349,85 +1595,18 @@ function DateRangePicker({
1349
1595
  ] })
1350
1596
  ] }),
1351
1597
  /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
1352
- /* @__PURE__ */ jsxs("div", { className: "w-64", children: [
1353
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2 px-1", children: [
1354
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => handleStep(-1), "aria-label": "Previous", 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: "M15 19l-7-7 7-7" }) }) }),
1355
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm font-semibold text-gray-800", children: [
1356
- view === "days" && /* @__PURE__ */ jsx(
1357
- "button",
1358
- {
1359
- type: "button",
1360
- onClick: () => setView("months"),
1361
- className: "px-1.5 py-0.5 rounded-md hover:bg-gray-100 transition-colors",
1362
- children: monthName
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
- ] }),
1598
+ /* @__PURE__ */ jsx("div", { className: "w-64", children: /* @__PURE__ */ jsx(
1599
+ Calendar,
1600
+ {
1601
+ mode: "range",
1602
+ value: tempFrom || null,
1603
+ endValue: tempTo || null,
1604
+ month: viewMonth,
1605
+ onMonthChange: setViewMonth,
1606
+ onSelect: handleCalendarSelect,
1607
+ "aria-label": "Date range"
1608
+ }
1609
+ ) }),
1431
1610
  /* @__PURE__ */ jsxs("div", { className: "border-l border-gray-200 pl-4 flex flex-col gap-1 min-w-[130px]", children: [
1432
1611
  PRESET_LABELS.map((label) => /* @__PURE__ */ jsx(
1433
1612
  "button",
@@ -1469,45 +1648,14 @@ function DateRangePicker({
1469
1648
  )
1470
1649
  ] });
1471
1650
  }
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
1651
  var TIME = /^\d{2}:\d{2}(:\d{2})?$/;
1504
- var pad2 = (n) => String(n).padStart(2, "0");
1505
- function toInputValue2(value, withSeconds) {
1652
+ var pad3 = (n) => String(n).padStart(2, "0");
1653
+ function toInputValue(value, withSeconds) {
1506
1654
  if (value === null || value === void 0 || value === "") return "";
1507
1655
  if (value instanceof Date) {
1508
1656
  if (Number.isNaN(value.getTime())) return "";
1509
- const base = `${pad2(value.getHours())}:${pad2(value.getMinutes())}`;
1510
- return withSeconds ? `${base}:${pad2(value.getSeconds())}` : base;
1657
+ const base = `${pad3(value.getHours())}:${pad3(value.getMinutes())}`;
1658
+ return withSeconds ? `${base}:${pad3(value.getSeconds())}` : base;
1511
1659
  }
1512
1660
  return TIME.test(value) ? value : "";
1513
1661
  }
@@ -1520,9 +1668,9 @@ var TimePicker = forwardRef(function TimePicker2({ value, onChange, min, max, in
1520
1668
  type: "time",
1521
1669
  step,
1522
1670
  "aria-invalid": invalid || void 0,
1523
- value: toInputValue2(value, withSeconds),
1524
- min: toInputValue2(min, withSeconds) || void 0,
1525
- max: toInputValue2(max, withSeconds) || void 0,
1671
+ value: toInputValue(value, withSeconds),
1672
+ min: toInputValue(min, withSeconds) || void 0,
1673
+ max: toInputValue(max, withSeconds) || void 0,
1526
1674
  onChange: (event) => onChange?.(TIME.test(event.target.value) ? event.target.value : null),
1527
1675
  className: inputClasses({ invalid, size, className }),
1528
1676
  ...rest
@@ -1530,10 +1678,252 @@ var TimePicker = forwardRef(function TimePicker2({ value, onChange, min, max, in
1530
1678
  );
1531
1679
  });
1532
1680
  var TimePicker_default = TimePicker;
1681
+ var POPUP_MAX_WIDTH = 448;
1682
+ var MENU_MAX_HEIGHT2 = 240;
1683
+ var MENU_GAP2 = 4;
1684
+ var VIEWPORT_MARGIN2 = 8;
1685
+ function useDropdownPosition(triggerRef, open) {
1686
+ const [pos, setPos] = useState(null);
1687
+ useLayoutEffect(() => {
1688
+ if (!open) {
1689
+ setPos(null);
1690
+ return;
1691
+ }
1692
+ let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN;
1693
+ const compute = () => {
1694
+ const rect = triggerRef.current?.getBoundingClientRect();
1695
+ if (!rect) return;
1696
+ lastLeft = rect.left;
1697
+ lastTop = rect.top;
1698
+ lastRight = rect.right;
1699
+ lastBottom = rect.bottom;
1700
+ const spaceBelow = window.innerHeight - rect.bottom - MENU_GAP2 - VIEWPORT_MARGIN2;
1701
+ const spaceAbove = rect.top - MENU_GAP2 - VIEWPORT_MARGIN2;
1702
+ const placeAbove = spaceBelow < Math.min(MENU_MAX_HEIGHT2, 160) && spaceAbove > spaceBelow;
1703
+ const maxHeight = Math.max(96, Math.min(MENU_MAX_HEIGHT2, placeAbove ? spaceAbove : spaceBelow));
1704
+ const next = { minWidth: rect.width, maxHeight };
1705
+ if (window.innerWidth - rect.left < POPUP_MAX_WIDTH) {
1706
+ next.right = Math.max(VIEWPORT_MARGIN2, window.innerWidth - rect.right);
1707
+ } else {
1708
+ next.left = Math.max(VIEWPORT_MARGIN2, rect.left);
1709
+ }
1710
+ if (placeAbove) next.bottom = window.innerHeight - rect.top + MENU_GAP2;
1711
+ else next.top = rect.bottom + MENU_GAP2;
1712
+ setPos(next);
1713
+ };
1714
+ compute();
1715
+ let raf = requestAnimationFrame(function tick() {
1716
+ const rect = triggerRef.current?.getBoundingClientRect();
1717
+ if (rect && (rect.left !== lastLeft || rect.top !== lastTop || rect.right !== lastRight || rect.bottom !== lastBottom)) {
1718
+ compute();
1719
+ }
1720
+ raf = requestAnimationFrame(tick);
1721
+ });
1722
+ window.addEventListener("scroll", compute, true);
1723
+ window.addEventListener("resize", compute);
1724
+ return () => {
1725
+ cancelAnimationFrame(raf);
1726
+ window.removeEventListener("scroll", compute, true);
1727
+ window.removeEventListener("resize", compute);
1728
+ };
1729
+ }, [open, triggerRef]);
1730
+ return pos;
1731
+ }
1732
+ var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
1733
+ var MONTH_NAMES2 = [
1734
+ "January",
1735
+ "February",
1736
+ "March",
1737
+ "April",
1738
+ "May",
1739
+ "June",
1740
+ "July",
1741
+ "August",
1742
+ "September",
1743
+ "October",
1744
+ "November",
1745
+ "December"
1746
+ ];
1747
+ function toInputValue2(value) {
1748
+ if (value === null || value === void 0 || value === "") return "";
1749
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : toISODate(value);
1750
+ if (ISO_DATE.test(value)) return value;
1751
+ const parsed = new Date(value);
1752
+ return Number.isNaN(parsed.getTime()) ? "" : toISODate(parsed);
1753
+ }
1754
+ function fromInputValue(raw) {
1755
+ if (!ISO_DATE.test(raw)) return null;
1756
+ const [year, month, day] = raw.split("-").map(Number);
1757
+ const date = new Date(year, month - 1, day);
1758
+ return date.getMonth() === month - 1 && date.getDate() === day ? date : null;
1759
+ }
1760
+ function display(key) {
1761
+ const d = fromInputValue(key);
1762
+ return d ? `${d.getDate()} ${MONTH_NAMES2[d.getMonth()]} ${d.getFullYear()}` : "";
1763
+ }
1764
+ var DatePicker = forwardRef(function DatePicker2({
1765
+ value,
1766
+ onChange,
1767
+ min,
1768
+ max,
1769
+ invalid,
1770
+ size,
1771
+ native,
1772
+ weekStartsOn,
1773
+ className = "",
1774
+ "aria-label": ariaLabel,
1775
+ "aria-describedby": describedBy,
1776
+ id,
1777
+ name,
1778
+ disabled,
1779
+ placeholder,
1780
+ ...rest
1781
+ }, ref) {
1782
+ const current = toInputValue2(value);
1783
+ const lo = toInputValue2(min);
1784
+ const hi = toInputValue2(max);
1785
+ const [open, setOpen] = useState(false);
1786
+ const wrapRef = useRef(null);
1787
+ const triggerRef = useRef(null);
1788
+ const panelRef = useRef(null);
1789
+ const panelId = useId();
1790
+ const pos = useDropdownPosition(triggerRef, open);
1791
+ useEffect(() => {
1792
+ if (!open) return;
1793
+ const onPointerDown = (e) => {
1794
+ const target = e.target;
1795
+ if (wrapRef.current?.contains(target) || panelRef.current?.contains(target)) return;
1796
+ setOpen(false);
1797
+ };
1798
+ document.addEventListener("pointerdown", onPointerDown, true);
1799
+ return () => document.removeEventListener("pointerdown", onPointerDown, true);
1800
+ }, [open]);
1801
+ useEffect(() => {
1802
+ if (!open) return;
1803
+ return registerModalEscapeInterceptor((event) => {
1804
+ if (event.key !== "Escape") return false;
1805
+ setOpen(false);
1806
+ triggerRef.current?.focus();
1807
+ return true;
1808
+ });
1809
+ }, [open]);
1810
+ if (native) {
1811
+ return /* @__PURE__ */ jsx(
1812
+ "input",
1813
+ {
1814
+ ref,
1815
+ type: "date",
1816
+ id,
1817
+ name,
1818
+ disabled,
1819
+ "aria-label": ariaLabel,
1820
+ "aria-describedby": describedBy,
1821
+ "aria-invalid": invalid || void 0,
1822
+ value: current,
1823
+ min: lo || void 0,
1824
+ max: hi || void 0,
1825
+ onChange: (event) => onChange?.(fromInputValue(event.target.value)),
1826
+ className: inputClasses({ invalid, size, className }),
1827
+ ...rest
1828
+ }
1829
+ );
1830
+ }
1831
+ return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: "relative", children: [
1832
+ /* @__PURE__ */ jsx("input", { ref, type: "hidden", name, value: current }),
1833
+ /* @__PURE__ */ jsxs(
1834
+ "button",
1835
+ {
1836
+ ref: triggerRef,
1837
+ type: "button",
1838
+ id,
1839
+ disabled,
1840
+ "aria-haspopup": "dialog",
1841
+ "aria-expanded": open,
1842
+ "aria-controls": open ? panelId : void 0,
1843
+ "aria-describedby": describedBy,
1844
+ "aria-invalid": invalid || void 0,
1845
+ "aria-label": ariaLabel ? `${ariaLabel}${current ? `, ${display(current)}` : ""}` : void 0,
1846
+ onClick: () => setOpen((o) => !o),
1847
+ className: `${inputClasses({ invalid, size, className })} flex items-center justify-between text-left`,
1848
+ children: [
1849
+ /* @__PURE__ */ jsx("span", { className: current ? "text-gray-900" : "text-gray-400", children: current ? display(current) : placeholder ?? "Select a date" }),
1850
+ /* @__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" }) })
1851
+ ]
1852
+ }
1853
+ ),
1854
+ open && createPortal(
1855
+ /* @__PURE__ */ jsxs(
1856
+ "div",
1857
+ {
1858
+ ref: panelRef,
1859
+ id: panelId,
1860
+ role: "dialog",
1861
+ "aria-label": ariaLabel ?? "Choose a date",
1862
+ className: "fixed z-[400] w-72 rounded-xl border border-gray-200 bg-white p-3 shadow-lg",
1863
+ style: {
1864
+ left: pos?.left,
1865
+ right: pos?.right,
1866
+ top: pos?.top,
1867
+ bottom: pos?.bottom,
1868
+ // Hidden for the first paint until the layout effect measures the
1869
+ // trigger, so the panel never flashes at (0,0).
1870
+ visibility: pos ? void 0 : "hidden"
1871
+ },
1872
+ children: [
1873
+ /* @__PURE__ */ jsx(
1874
+ Calendar,
1875
+ {
1876
+ value: current || null,
1877
+ min: lo || null,
1878
+ max: hi || null,
1879
+ weekStartsOn,
1880
+ onSelect: (key) => {
1881
+ setOpen(false);
1882
+ triggerRef.current?.focus();
1883
+ onChange?.(fromInputValue(key));
1884
+ }
1885
+ }
1886
+ ),
1887
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-between border-t border-gray-100 pt-2", children: [
1888
+ /* @__PURE__ */ jsx(
1889
+ "button",
1890
+ {
1891
+ type: "button",
1892
+ onClick: () => {
1893
+ setOpen(false);
1894
+ triggerRef.current?.focus();
1895
+ onChange?.(null);
1896
+ },
1897
+ className: "rounded-md px-2 py-1 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-700",
1898
+ children: "Clear"
1899
+ }
1900
+ ),
1901
+ /* @__PURE__ */ jsx(
1902
+ "button",
1903
+ {
1904
+ type: "button",
1905
+ onClick: () => {
1906
+ setOpen(false);
1907
+ triggerRef.current?.focus();
1908
+ onChange?.(/* @__PURE__ */ new Date());
1909
+ },
1910
+ className: "rounded-md px-2 py-1 text-sm font-medium text-blue-600 hover:bg-blue-50",
1911
+ children: "Today"
1912
+ }
1913
+ )
1914
+ ] })
1915
+ ]
1916
+ }
1917
+ ),
1918
+ document.body
1919
+ )
1920
+ ] });
1921
+ });
1922
+ var DatePicker_default = DatePicker;
1533
1923
  var ISO_LOCAL = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/;
1534
- var pad3 = (n) => String(n).padStart(2, "0");
1924
+ var pad4 = (n) => String(n).padStart(2, "0");
1535
1925
  function serialise(date) {
1536
- return `${date.getFullYear()}-${pad3(date.getMonth() + 1)}-${pad3(date.getDate())}T${pad3(date.getHours())}:${pad3(date.getMinutes())}`;
1926
+ return `${date.getFullYear()}-${pad4(date.getMonth() + 1)}-${pad4(date.getDate())}T${pad4(date.getHours())}:${pad4(date.getMinutes())}`;
1537
1927
  }
1538
1928
  function toInputValue3(value) {
1539
1929
  if (value === null || value === void 0 || value === "") return "";
@@ -1677,8 +2067,8 @@ function Segmented({
1677
2067
  className = ""
1678
2068
  }) {
1679
2069
  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" : ""}`;
2070
+ 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();
2071
+ 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
2072
  if (name) {
1683
2073
  return /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": label, className: track, children: options.map((opt) => {
1684
2074
  const id = `${groupId}-${opt.value}`;
@@ -2029,58 +2419,7 @@ function FilePicker({
2029
2419
  error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-red-600", children: error })
2030
2420
  ] });
2031
2421
  }
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
- function ClearButton({ onClear, ariaLabel = "Clear selection" }) {
2422
+ function ClearButton({ onClear, ariaLabel }) {
2084
2423
  return /* @__PURE__ */ jsx(
2085
2424
  "button",
2086
2425
  {
@@ -2101,7 +2440,7 @@ function SearchableSelect({
2101
2440
  onChange,
2102
2441
  options,
2103
2442
  placeholder,
2104
- emptyOptionLabel = "\u2014 None \u2014",
2443
+ emptyOptionLabel,
2105
2444
  className = "",
2106
2445
  disabled,
2107
2446
  id,
@@ -2111,6 +2450,8 @@ function SearchableSelect({
2111
2450
  }) {
2112
2451
  const [open, setOpen] = useState(false);
2113
2452
  const [search, setSearchState] = useState("");
2453
+ const strings = useShellStrings();
2454
+ const noneLabel = emptyOptionLabel ?? strings.select.none;
2114
2455
  const setSearch = (next) => {
2115
2456
  setSearchState(next);
2116
2457
  onSearchChange?.(next);
@@ -2212,13 +2553,13 @@ function SearchableSelect({
2212
2553
  setSearch("");
2213
2554
  }
2214
2555
  },
2215
- placeholder: placeholder || (emptyOptionLabel || "Select\u2026"),
2556
+ placeholder: placeholder || noneLabel,
2216
2557
  className: `${INPUT_BASE} ${className} ${value ? "pr-8" : ""} ${disabled ? "bg-gray-50 text-gray-400 cursor-not-allowed" : ""} truncate`,
2217
2558
  style: adornPad ? { paddingRight: adornPad } : void 0,
2218
2559
  disabled
2219
2560
  }
2220
2561
  ),
2221
- value && !disabled && /* @__PURE__ */ jsx(ClearButton, { onClear: () => {
2562
+ value && !disabled && /* @__PURE__ */ jsx(ClearButton, { ariaLabel: strings.select.clear, onClear: () => {
2222
2563
  onChange("");
2223
2564
  setOpen(false);
2224
2565
  setSearch("");
@@ -2229,7 +2570,7 @@ function SearchableSelect({
2229
2570
  "div",
2230
2571
  {
2231
2572
  ref: menuRef,
2232
- className: "fixed z-[400] rounded-2xl overflow-hidden",
2573
+ className: "fixed z-[10000] rounded-2xl overflow-hidden",
2233
2574
  style: {
2234
2575
  left: menuPos?.left,
2235
2576
  right: menuPos?.right,
@@ -2243,7 +2584,7 @@ function SearchableSelect({
2243
2584
  visibility: menuPos ? void 0 : "hidden",
2244
2585
  ...glassStyle()
2245
2586
  },
2246
- children: /* @__PURE__ */ jsx("div", { className: "overflow-y-auto", style: { maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT2 }, children: filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-3 text-sm text-gray-400 text-center", children: "No matches" }) : filtered.map((o) => /* @__PURE__ */ jsxs(
2587
+ children: /* @__PURE__ */ jsx("div", { className: "overflow-y-auto", style: { maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT2 }, children: filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-3 text-sm text-gray-400 text-center", children: strings.select.noMatches }) : filtered.map((o) => /* @__PURE__ */ jsxs(
2247
2588
  "button",
2248
2589
  {
2249
2590
  type: "button",
@@ -2279,6 +2620,7 @@ function TagInput({
2279
2620
  }) {
2280
2621
  const [open, setOpen] = useState(false);
2281
2622
  const [search, setSearch] = useState("");
2623
+ const strings = useShellStrings();
2282
2624
  const wrapRef = useRef(null);
2283
2625
  const inputRef = useRef(null);
2284
2626
  const menuRef = useRef(null);
@@ -2342,7 +2684,7 @@ function TagInput({
2342
2684
  "button",
2343
2685
  {
2344
2686
  type: "button",
2345
- "aria-label": `Remove ${labelFor(v)}`,
2687
+ "aria-label": `${strings.select.remove} ${labelFor(v)}`,
2346
2688
  onClick: () => remove(v),
2347
2689
  className: "text-blue-400 hover:text-red-500 focus:outline-none focus-visible:ring-1 focus-visible:ring-blue-500 rounded leading-none",
2348
2690
  children: "\xD7"
@@ -2398,7 +2740,7 @@ function TagInput({
2398
2740
  "div",
2399
2741
  {
2400
2742
  ref: menuRef,
2401
- className: "fixed z-[400] rounded-2xl overflow-hidden",
2743
+ className: "fixed z-[10000] rounded-2xl overflow-hidden",
2402
2744
  style: {
2403
2745
  left: menuPos?.left,
2404
2746
  right: menuPos?.right,
@@ -2412,7 +2754,7 @@ function TagInput({
2412
2754
  visibility: menuPos ? void 0 : "hidden",
2413
2755
  ...glassStyle()
2414
2756
  },
2415
- children: /* @__PURE__ */ jsx("div", { className: "overflow-y-auto", style: { maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT2 }, children: available.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-3 text-sm text-gray-400 text-center", children: options.length > 0 && value.length >= options.length ? "All options selected" : "No matches" }) : available.map((o) => /* @__PURE__ */ jsx(
2757
+ children: /* @__PURE__ */ jsx("div", { className: "overflow-y-auto", style: { maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT2 }, children: available.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-3 text-sm text-gray-400 text-center", children: options.length > 0 && value.length >= options.length ? strings.select.allSelected : strings.select.noMatches }) : available.map((o) => /* @__PURE__ */ jsx(
2416
2758
  "button",
2417
2759
  {
2418
2760
  type: "button",
@@ -2714,23 +3056,23 @@ function DescriptionList({
2714
3056
  const resolved = typeof columns === "number" ? { base: columns } : columns;
2715
3057
  const base = resolved.base ?? 1;
2716
3058
  const widest = Math.max(base, resolved.sm ?? 0, resolved.lg ?? 0);
2717
- const pad4 = size === "sm" ? "px-3 py-2" : "px-4 py-3";
3059
+ const pad5 = size === "sm" ? "px-3 py-2" : "px-4 py-3";
2718
3060
  const text = size === "sm" ? "text-xs" : "text-sm";
2719
3061
  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: `${pad4} ${bordered ? "border-b border-gray-100" : ""} text-sm font-semibold text-gray-900`.trim(), children: title }),
3062
+ title && /* @__PURE__ */ jsx("div", { className: `${pad5} ${bordered ? "border-b border-gray-100" : ""} text-sm font-semibold text-gray-900`.trim(), children: title }),
2721
3063
  /* @__PURE__ */ jsx("dl", { className: [
2722
3064
  "grid",
2723
3065
  COLS2[base],
2724
3066
  resolved.sm ? SM[resolved.sm] : "",
2725
3067
  resolved.lg ? LG[resolved.lg] : "",
2726
3068
  bordered ? "" : "gap-x-6 gap-y-3",
2727
- bordered ? "" : pad4 === "px-4 py-3" ? "py-1" : ""
3069
+ bordered ? "" : pad5 === "px-4 py-3" ? "py-1" : ""
2728
3070
  ].filter(Boolean).join(" "), children: items.map((item, i) => /* @__PURE__ */ jsxs(
2729
3071
  "div",
2730
3072
  {
2731
3073
  className: [
2732
3074
  item.span ? SPAN[widest] : "",
2733
- bordered ? `${pad4} border-b border-gray-100 last:border-b-0` : ""
3075
+ bordered ? `${pad5} border-b border-gray-100 last:border-b-0` : ""
2734
3076
  ].filter(Boolean).join(" "),
2735
3077
  children: [
2736
3078
  /* @__PURE__ */ jsx("dt", { className: `${text} text-gray-500`, children: item.label }),
@@ -4143,8 +4485,9 @@ function HelpCenter({
4143
4485
  onNew,
4144
4486
  onEdit,
4145
4487
  renderBody,
4146
- emptyMessage = "No help articles yet."
4488
+ emptyMessage
4147
4489
  }) {
4490
+ const strings = useShellStrings();
4148
4491
  const [query, setQuery] = useState("");
4149
4492
  const [selectedSlug, setSelectedSlug] = useState(null);
4150
4493
  const [expanded, setExpanded] = useState({});
@@ -4177,8 +4520,8 @@ function HelpCenter({
4177
4520
  return /* @__PURE__ */ jsxs("div", { className: "flex h-full gap-4 px-4 py-3 min-h-0", children: [
4178
4521
  /* @__PURE__ */ jsxs("aside", { className: "w-64 shrink-0 flex flex-col bg-white rounded-lg shadow overflow-hidden", children: [
4179
4522
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-gray-200 bg-gray-50 shrink-0", children: [
4180
- /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-gray-900", children: "Help" }),
4181
- canEdit && onNew && /* @__PURE__ */ jsx("button", { type: "button", onClick: onNew, className: "text-xs text-blue-600 hover:underline", children: "+ New" })
4523
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-gray-900", children: strings.help.title }),
4524
+ canEdit && onNew && /* @__PURE__ */ jsx("button", { type: "button", onClick: onNew, className: "text-xs text-blue-600 hover:underline", children: strings.help.newArticle })
4182
4525
  ] }),
4183
4526
  /* @__PURE__ */ jsx("div", { className: "px-2.5 py-2 border-b border-gray-100 shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4184
4527
  /* @__PURE__ */ jsx(
@@ -4204,12 +4547,12 @@ function HelpCenter({
4204
4547
  type: "text",
4205
4548
  value: query,
4206
4549
  onChange: (e) => setQuery(e.target.value),
4207
- placeholder: "Search help\u2026",
4550
+ placeholder: strings.help.searchPlaceholder,
4208
4551
  className: "w-full rounded-md border border-gray-300 bg-white py-1.5 pl-8 pr-2 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
4209
4552
  }
4210
4553
  )
4211
4554
  ] }) }),
4212
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto py-1", children: loading ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-gray-400", children: "Loading\u2026" }) : visibleGroups.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-gray-500", children: q ? "No articles match your search." : emptyMessage }) : visibleGroups.map((group) => {
4555
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto py-1", children: loading ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-gray-400", children: strings.help.loading }) : visibleGroups.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-gray-500", children: q ? strings.help.noResults : emptyMessage ?? strings.help.empty }) : visibleGroups.map((group) => {
4213
4556
  const open = isGroupOpen(group.key);
4214
4557
  return /* @__PURE__ */ jsxs("div", { className: "py-0.5", children: [
4215
4558
  /* @__PURE__ */ jsxs(
@@ -4234,7 +4577,7 @@ function HelpCenter({
4234
4577
  className: `w-full text-left pl-8 pr-3 py-1.5 text-sm flex items-center gap-1.5 transition-colors ${active ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
4235
4578
  children: [
4236
4579
  /* @__PURE__ */ jsx("span", { className: "truncate", children: doc.title }),
4237
- doc.is_published === false && /* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 text-[10px] text-amber-600", children: "Draft" })
4580
+ doc.is_published === false && /* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 text-[10px] text-amber-600", children: strings.help.draft })
4238
4581
  ]
4239
4582
  },
4240
4583
  doc.slug
@@ -4249,7 +4592,10 @@ function HelpCenter({
4249
4592
  /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900 truncate", children: selected.title }),
4250
4593
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 mt-0.5", children: [
4251
4594
  selected.category_label,
4252
- selected.is_published === false && /* @__PURE__ */ jsx("span", { className: "ml-2 text-amber-600", children: "\xB7 Draft" })
4595
+ selected.is_published === false && /* @__PURE__ */ jsxs("span", { className: "ml-2 text-amber-600", children: [
4596
+ "\xB7 ",
4597
+ strings.help.draft
4598
+ ] })
4253
4599
  ] })
4254
4600
  ] }),
4255
4601
  canEdit && onEdit && /* @__PURE__ */ jsx(
@@ -4258,12 +4604,12 @@ function HelpCenter({
4258
4604
  type: "button",
4259
4605
  onClick: () => onEdit(selected),
4260
4606
  className: "shrink-0 text-sm text-blue-600 hover:underline",
4261
- children: "Edit"
4607
+ children: strings.help.edit
4262
4608
  }
4263
4609
  )
4264
4610
  ] }),
4265
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto px-5 py-4", children: renderBody ? renderBody(selected) : selected.body ? /* @__PURE__ */ jsx(Markdown, { children: selected.body }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 italic", children: "This article has no body yet." }) })
4266
- ] }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center px-6 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: loading ? "Loading\u2026" : "Pick a help article from the left." }) }) })
4611
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto px-5 py-4", children: renderBody ? renderBody(selected) : selected.body ? /* @__PURE__ */ jsx(Markdown, { children: selected.body }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 italic", children: strings.help.noBody }) })
4612
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center px-6 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: loading ? strings.help.loading : strings.help.pickArticle }) }) })
4267
4613
  ] });
4268
4614
  }
4269
4615
  var VARIANTS = {
@@ -4484,12 +4830,28 @@ function DropdownMenu({
4484
4830
  )
4485
4831
  ] });
4486
4832
  }
4487
- var SIZE_PX2 = { sm: 320, md: 448, lg: 640 };
4833
+ var SIZE_CLASS = {
4834
+ sm: "sm:w-[320px]",
4835
+ md: "sm:w-[448px]",
4836
+ lg: "sm:w-[640px]"
4837
+ };
4488
4838
  var SIDE_POSITION = {
4489
4839
  right: "inset-y-0 right-0",
4490
4840
  left: "inset-y-0 left-0",
4491
4841
  bottom: "inset-x-0 bottom-0"
4492
4842
  };
4843
+ function CloseButton({ onClose }) {
4844
+ return /* @__PURE__ */ jsx(
4845
+ "button",
4846
+ {
4847
+ type: "button",
4848
+ onClick: onClose,
4849
+ "aria-label": "Close",
4850
+ 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",
4851
+ 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" }) })
4852
+ }
4853
+ );
4854
+ }
4493
4855
  function Drawer({
4494
4856
  open,
4495
4857
  onClose,
@@ -4500,10 +4862,12 @@ function Drawer({
4500
4862
  children,
4501
4863
  blocking = false,
4502
4864
  initialFocus,
4865
+ "aria-label": ariaLabel,
4503
4866
  className = ""
4504
4867
  }) {
4505
4868
  const panelRef = useRef(null);
4506
4869
  const bodyId = useId();
4870
+ const titleId = useId();
4507
4871
  useFocusTrap(panelRef, open, initialFocus);
4508
4872
  useScrollLock(open);
4509
4873
  useEffect(() => {
@@ -4516,7 +4880,7 @@ function Drawer({
4516
4880
  }, [open, blocking, onClose]);
4517
4881
  if (!open) return null;
4518
4882
  const isBottom = side === "bottom";
4519
- const panelStyle = isBottom ? { maxHeight: "85vh" } : { width: SIZE_PX2[size], maxWidth: "100vw" };
4883
+ const panelStyle = isBottom ? { maxHeight: "85vh" } : void 0;
4520
4884
  return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[9999]", role: "presentation", children: [
4521
4885
  /* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black/30", onClick: blocking ? void 0 : onClose, "aria-hidden": "true" }),
4522
4886
  /* @__PURE__ */ jsxs(
@@ -4525,29 +4889,27 @@ function Drawer({
4525
4889
  ref: panelRef,
4526
4890
  role: "dialog",
4527
4891
  "aria-modal": "true",
4528
- "aria-label": typeof title === "string" ? title : void 0,
4892
+ "aria-labelledby": title ? titleId : void 0,
4893
+ "aria-label": title ? void 0 : ariaLabel,
4529
4894
  "aria-describedby": children ? bodyId : void 0,
4530
4895
  style: panelStyle,
4531
4896
  className: [
4532
4897
  "fixed flex flex-col bg-white shadow-xl",
4898
+ // Full width on a phone, the asked-for width from `sm` up. A 320px
4899
+ // drawer on a 375px screen leaves a 55px strip of scrim: too narrow
4900
+ // to aim at, too wide to read as an edge, and it makes the panel look
4901
+ // like a desktop rail that was squeezed rather than a sheet built for
4902
+ // the screen it is on.
4903
+ isBottom ? "" : `w-full max-w-full ${SIZE_CLASS[size]}`,
4533
4904
  SIDE_POSITION[side],
4534
4905
  isBottom ? "rounded-t-xl" : "",
4535
4906
  className
4536
4907
  ].filter(Boolean).join(" "),
4537
4908
  children: [
4538
- (title || !blocking) && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between gap-4 border-b border-gray-100 px-4 py-3", children: [
4539
- title ? /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-gray-900", children: title }) : /* @__PURE__ */ jsx("span", {}),
4540
- !blocking && /* @__PURE__ */ jsx(
4541
- "button",
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
- ] }),
4909
+ title ? /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between gap-4 border-b border-gray-100 px-4 py-3", children: [
4910
+ /* @__PURE__ */ jsx("h2", { id: titleId, className: "text-base font-semibold text-gray-900", children: title }),
4911
+ !blocking && /* @__PURE__ */ jsx(CloseButton, { onClose })
4912
+ ] }) : !blocking && /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 z-10", children: /* @__PURE__ */ jsx(CloseButton, { onClose }) }),
4551
4913
  /* @__PURE__ */ jsx("div", { id: bodyId, className: "min-h-0 flex-1 overflow-y-auto px-4 py-4", children }),
4552
4914
  footer && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 justify-end gap-3 border-t border-gray-100 px-4 py-3", children: footer })
4553
4915
  ]
@@ -4957,11 +5319,14 @@ function DataTable({
4957
5319
  minWidth,
4958
5320
  rowClassName,
4959
5321
  onRow,
4960
- emptyText = "Nothing to show",
5322
+ emptyText,
5323
+ selection,
4961
5324
  footer,
4962
5325
  virtualized,
4963
5326
  className = ""
4964
5327
  }) {
5328
+ const strings = useShellStrings();
5329
+ const emptyContent = emptyText ?? strings.table.empty;
4965
5330
  const keyOf = (row, i) => typeof rowKey === "function" ? rowKey(row, i) : String(row[rowKey]);
4966
5331
  const [startRow, setStartRow] = useState(0);
4967
5332
  const overscan = virtualized?.overscan ?? 6;
@@ -4995,6 +5360,27 @@ function DataTable({
4995
5360
  };
4996
5361
  const leaves = columns.flatMap((h) => isGroup(h) ? h.columns : [h]);
4997
5362
  const grouped = columns.some(isGroup);
5363
+ const selectedSet = new Set(selection?.selected ?? []);
5364
+ const pageKeys = selection ? data.map((row, i) => keyOf(row, i)) : [];
5365
+ const allSelected = pageKeys.length > 0 && pageKeys.every((k) => selectedSet.has(k));
5366
+ const someSelected = pageKeys.some((k) => selectedSet.has(k));
5367
+ const toggleRow = (key) => {
5368
+ if (!selection) return;
5369
+ selection.onChange(
5370
+ selectedSet.has(key) ? selection.selected.filter((k) => k !== key) : [...selection.selected, key]
5371
+ );
5372
+ };
5373
+ const toggleAll = () => {
5374
+ if (!selection) return;
5375
+ const page = new Set(pageKeys);
5376
+ selection.onChange(
5377
+ allSelected ? selection.selected.filter((k) => !page.has(k)) : [...selection.selected, ...pageKeys.filter((k) => !selectedSet.has(k))]
5378
+ );
5379
+ };
5380
+ const SELECT_W = 36;
5381
+ const selOffset = selection ? SELECT_W : 0;
5382
+ const colCount = leaves.length + (selection ? 1 : 0);
5383
+ const hasPinned = leaves.some((c) => c.fixed === "left");
4998
5384
  const cellBase = `${PAD[size]} ${size === "sm" ? "text-xs" : "text-sm"}`;
4999
5385
  const headerCell = (col, ci, rowSpan, topOffset = 0) => {
5000
5386
  const dir = directionFor(col);
@@ -5008,7 +5394,7 @@ function DataTable({
5008
5394
  "aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : col.sortable && onSortChange ? "none" : void 0,
5009
5395
  style: {
5010
5396
  width: col.width,
5011
- ...pinned ? { left: offsets[ci] ?? 0 } : {},
5397
+ ...pinned ? { left: (offsets[ci] ?? 0) + selOffset } : {},
5012
5398
  // A virtualized header pins to the top of the vertical scroll; one
5013
5399
  // sticky box can hold both axes, so a pinned column's header corner
5014
5400
  // stays put in both directions.
@@ -5058,45 +5444,73 @@ function DataTable({
5058
5444
  // page around under the user.
5059
5445
  /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-20 flex items-start justify-center bg-white/60 pt-8", role: "status", "aria-live": "polite", children: [
5060
5446
  /* @__PURE__ */ jsx("span", { className: "h-6 w-6 animate-spin rounded-full border-2 border-gray-200 border-t-blue-600" }),
5061
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading" })
5447
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: strings.table.loading })
5062
5448
  ] }),
5063
5449
  /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse tabular-nums", style: minWidth ? { minWidth } : void 0, children: [
5064
5450
  caption && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
5065
5451
  /* @__PURE__ */ jsxs("thead", { children: [
5066
- /* @__PURE__ */ jsx("tr", { ref: headRowRef, className: "border-b border-gray-200 bg-gray-50", children: columns.map((h, hi) => {
5067
- if (isGroup(h)) {
5068
- return /* @__PURE__ */ jsx(
5069
- "th",
5070
- {
5071
- scope: "colgroup",
5072
- colSpan: h.columns.length,
5073
- style: virtualized ? { top: 0 } : void 0,
5074
- className: [
5075
- cellBase,
5076
- "text-center",
5077
- "font-semibold uppercase tracking-wide text-gray-500",
5078
- size === "sm" ? "text-[10px]" : "text-xs",
5079
- "border-b border-gray-200",
5080
- virtualized ? "sticky z-10 bg-gray-50" : "",
5081
- h.headerClassName ?? ""
5082
- ].filter(Boolean).join(" "),
5083
- children: h.title
5084
- },
5085
- h.key ?? `group-${hi}`
5086
- );
5087
- }
5088
- return headerCell(h, leaves.indexOf(h), grouped ? 2 : 1);
5089
- }) }),
5452
+ /* @__PURE__ */ jsxs("tr", { ref: headRowRef, className: "border-b border-gray-200 bg-gray-50", children: [
5453
+ selection && /* @__PURE__ */ jsx(
5454
+ "th",
5455
+ {
5456
+ scope: "col",
5457
+ rowSpan: grouped ? 2 : void 0,
5458
+ style: { width: SELECT_W, ...virtualized ? { top: 0 } : {} },
5459
+ className: [
5460
+ cellBase,
5461
+ hasPinned || virtualized ? "sticky z-20 bg-gray-50" : "",
5462
+ hasPinned ? "left-0" : ""
5463
+ ].filter(Boolean).join(" "),
5464
+ children: /* @__PURE__ */ jsx(
5465
+ "input",
5466
+ {
5467
+ type: "checkbox",
5468
+ "aria-label": strings.table.selectAll,
5469
+ checked: allSelected,
5470
+ ref: (el) => {
5471
+ if (el) el.indeterminate = someSelected && !allSelected;
5472
+ },
5473
+ onChange: toggleAll,
5474
+ className: "h-4 w-4 rounded border-gray-300 text-blue-600"
5475
+ }
5476
+ )
5477
+ }
5478
+ ),
5479
+ columns.map((h, hi) => {
5480
+ if (isGroup(h)) {
5481
+ return /* @__PURE__ */ jsx(
5482
+ "th",
5483
+ {
5484
+ scope: "colgroup",
5485
+ colSpan: h.columns.length,
5486
+ style: virtualized ? { top: 0 } : void 0,
5487
+ className: [
5488
+ cellBase,
5489
+ "text-center",
5490
+ "font-semibold uppercase tracking-wide text-gray-500",
5491
+ size === "sm" ? "text-[10px]" : "text-xs",
5492
+ "border-b border-gray-200",
5493
+ virtualized ? "sticky z-10 bg-gray-50" : "",
5494
+ h.headerClassName ?? ""
5495
+ ].filter(Boolean).join(" "),
5496
+ children: h.title
5497
+ },
5498
+ h.key ?? `group-${hi}`
5499
+ );
5500
+ }
5501
+ return headerCell(h, leaves.indexOf(h), grouped ? 2 : 1);
5502
+ })
5503
+ ] }),
5090
5504
  grouped && /* @__PURE__ */ jsx("tr", { className: "border-b border-gray-200 bg-gray-50", children: columns.flatMap((h) => isGroup(h) ? h.columns : []).map(
5091
5505
  (col) => headerCell(col, leaves.indexOf(col), 1, headRowH)
5092
5506
  ) })
5093
5507
  ] }),
5094
- /* @__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 }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5095
- topPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: leaves.length, style: { height: topPad, padding: 0, border: 0 } }) }),
5508
+ /* @__PURE__ */ jsx("tbody", { children: data.length === 0 && !loading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: colCount, className: `${cellBase} py-10 text-center text-gray-500`, children: emptyContent }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5509
+ topPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: topPad, padding: 0, border: 0 } }) }),
5096
5510
  data.slice(start, end).map((row, si) => {
5097
5511
  const i = start + si;
5098
5512
  const rowProps = onRow?.(row, i);
5099
- return /* @__PURE__ */ jsx(
5513
+ return /* @__PURE__ */ jsxs(
5100
5514
  "tr",
5101
5515
  {
5102
5516
  style: virtualized ? { height: virtualized.rowHeight } : void 0,
@@ -5116,32 +5530,55 @@ function DataTable({
5116
5530
  rowClassName?.(row, i) ?? "",
5117
5531
  rowProps?.className ?? ""
5118
5532
  ].filter(Boolean).join(" "),
5119
- children: leaves.map((col, ci) => {
5120
- const pinned = col.fixed === "left";
5121
- return /* @__PURE__ */ jsx(
5122
- "td",
5123
- {
5124
- style: pinned ? { left: offsets[ci] ?? 0 } : void 0,
5125
- className: [
5126
- cellBase,
5127
- ALIGN2[col.align ?? (col.numeric ? "right" : "left")],
5128
- col.numeric ? "font-mono" : "",
5129
- "text-gray-900",
5130
- col.ellipsis ? "max-w-0 truncate" : "",
5131
- // A pinned cell needs its own background or the
5132
- // scrolling columns show through it.
5133
- pinned ? "sticky z-10 bg-white" : ""
5134
- ].filter(Boolean).join(" "),
5135
- children: col.render ? col.render(row, i) : col.dataIndex ? row[col.dataIndex] : null
5136
- },
5137
- col.key
5138
- );
5139
- })
5533
+ children: [
5534
+ selection && (() => {
5535
+ const key = keyOf(row, i);
5536
+ return /* @__PURE__ */ jsx(
5537
+ "td",
5538
+ {
5539
+ style: { width: SELECT_W },
5540
+ onClick: (e) => e.stopPropagation(),
5541
+ className: [cellBase, hasPinned ? "sticky left-0 z-10 bg-white" : ""].filter(Boolean).join(" "),
5542
+ children: /* @__PURE__ */ jsx(
5543
+ "input",
5544
+ {
5545
+ type: "checkbox",
5546
+ "aria-label": strings.table.selectRow,
5547
+ checked: selectedSet.has(key),
5548
+ onChange: () => toggleRow(key),
5549
+ className: "h-4 w-4 rounded border-gray-300 text-blue-600"
5550
+ }
5551
+ )
5552
+ }
5553
+ );
5554
+ })(),
5555
+ leaves.map((col, ci) => {
5556
+ const pinned = col.fixed === "left";
5557
+ return /* @__PURE__ */ jsx(
5558
+ "td",
5559
+ {
5560
+ style: pinned ? { left: (offsets[ci] ?? 0) + selOffset } : void 0,
5561
+ className: [
5562
+ cellBase,
5563
+ ALIGN2[col.align ?? (col.numeric ? "right" : "left")],
5564
+ col.numeric ? "font-mono" : "",
5565
+ "text-gray-900",
5566
+ col.ellipsis ? "max-w-0 truncate" : "",
5567
+ // A pinned cell needs its own background or the
5568
+ // scrolling columns show through it.
5569
+ pinned ? "sticky z-10 bg-white" : ""
5570
+ ].filter(Boolean).join(" "),
5571
+ children: col.render ? col.render(row, i) : col.dataIndex ? row[col.dataIndex] : null
5572
+ },
5573
+ col.key
5574
+ );
5575
+ })
5576
+ ]
5140
5577
  },
5141
5578
  keyOf(row, i)
5142
5579
  );
5143
5580
  }),
5144
- bottomPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: leaves.length, style: { height: bottomPad, padding: 0, border: 0 } }) })
5581
+ bottomPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: bottomPad, padding: 0, border: 0 } }) })
5145
5582
  ] }) })
5146
5583
  ] }),
5147
5584
  footer
@@ -5204,8 +5641,8 @@ function Sparkline({
5204
5641
  const max = Math.max(...data);
5205
5642
  const min = Math.min(...data);
5206
5643
  const span = max - min || 1;
5207
- const pad4 = strokeWidth + (showDots ? 2 : 0);
5208
- const y = (v) => height - pad4 - (v - min) / span * (height - pad4 * 2);
5644
+ const pad5 = strokeWidth + (showDots ? 2 : 0);
5645
+ const y = (v) => height - pad5 - (v - min) / span * (height - pad5 * 2);
5209
5646
  const pts = data.length === 1 ? [[0, height / 2], [width, height / 2]] : data.map((v, i) => [i * width / (data.length - 1), y(v)]);
5210
5647
  const line = pts.map(([x, yy], i) => `${i === 0 ? "M" : "L"}${x.toFixed(2)},${yy.toFixed(2)}`).join(" ");
5211
5648
  const area = `${line} L${width.toFixed(2)},${height} L0,${height} Z`;
@@ -6107,6 +6544,6 @@ var ALT_SHIFT_D = isMac ? "\u2325\u21E7D" : "Alt+Shift+D";
6107
6544
  var ALT_SHIFT_E = isMac ? "\u2325\u21E7E" : "Alt+Shift+E";
6108
6545
  var ALT_SHIFT_N = isMac ? "\u2325\u21E7N" : "Alt+Shift+N";
6109
6546
 
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-CWA27IGB.js.map
6112
- //# sourceMappingURL=chunk-CWA27IGB.js.map
6547
+ 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, FormErrorSummary, 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 };
6548
+ //# sourceMappingURL=chunk-S6K37RLY.js.map
6549
+ //# sourceMappingURL=chunk-S6K37RLY.js.map