@estiva-app/ui 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -38,7 +38,7 @@ function cn(...inputs) {
38
38
  // src/ScrollArea.tsx
39
39
  import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
40
40
  import { jsx, jsxs } from "react/jsx-runtime";
41
- var BAR = "flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
41
+ var BAR = "z-10 flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
42
42
  var THUMB = "rounded-full bg-border-strong";
43
43
  function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, viewportRef, onScroll, children }) {
44
44
  const vertical = orientation !== "horizontal";
@@ -755,7 +755,8 @@ function squareClasses(checked, disabled, interactive, className) {
755
755
  }
756
756
  var tickClasses = (checked) => cn("flex", !checked && "invisible");
757
757
  var WORDS_CLASSES = "text-body-2 text-text-primary";
758
- function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, className, ...aria }) {
758
+ var ROW_CLASSES = "flex shrink-0 items-center gap-3 h-10 px-3 rounded-lg transition-colors";
759
+ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row, leading, className, ...aria }) {
759
760
  const formBusy = useFormBusy();
760
761
  const disabled = ownDisabled || formBusy;
761
762
  if (!onChange) {
@@ -780,6 +781,13 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, cla
780
781
  }
781
782
  );
782
783
  if (label === void 0) return box;
784
+ if (row) {
785
+ return /* @__PURE__ */ jsx14(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs9(BaseField.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
786
+ leading,
787
+ /* @__PURE__ */ jsx14("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
788
+ box
789
+ ] }) });
790
+ }
783
791
  return /* @__PURE__ */ jsx14(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs9(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
784
792
  box,
785
793
  /* @__PURE__ */ jsx14("span", { className: WORDS_CLASSES, children: label })
@@ -817,9 +825,9 @@ import {
817
825
  createContext as createContext3,
818
826
  useContext as useContext3,
819
827
  useEffect,
820
- useLayoutEffect as useLayoutEffect2,
828
+ useLayoutEffect as useLayoutEffect3,
821
829
  useMemo as useMemo2,
822
- useRef as useRef2,
830
+ useRef as useRef3,
823
831
  useState as useState3
824
832
  } from "react";
825
833
  import { Dialog } from "@base-ui/react/dialog";
@@ -1255,39 +1263,129 @@ function FieldLine({ tone = "helper", children, className }) {
1255
1263
  return /* @__PURE__ */ jsx20("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1256
1264
  }
1257
1265
 
1266
+ // src/Form.tsx
1267
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
1268
+ import { Fieldset } from "@base-ui/react/fieldset";
1269
+ import { Form as BaseForm } from "@base-ui/react/form";
1270
+ import { jsx as jsx21 } from "react/jsx-runtime";
1271
+ var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
1272
+ var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
1273
+ function usable(element) {
1274
+ return element instanceof HTMLElement && element.isConnected && element.matches(CONTROL) && !element.matches(":disabled") && element.getAttribute("aria-disabled") !== "true";
1275
+ }
1276
+ function firstInvalid(form) {
1277
+ for (const marked of form.querySelectorAll("[data-invalid]")) {
1278
+ if (usable(marked)) return marked;
1279
+ const inside = Array.from(marked.querySelectorAll(CONTROL)).find(usable);
1280
+ if (inside) return inside;
1281
+ }
1282
+ return void 0;
1283
+ }
1284
+ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, children, ...props }) {
1285
+ const outerBusy = useFormBusy();
1286
+ const busy = ownBusy || outerBusy;
1287
+ const form = useRef2(null);
1288
+ const busyNow = useRef2(busy);
1289
+ busyNow.current = busy;
1290
+ const sender = useRef2(null);
1291
+ const holding = useRef2(false);
1292
+ const lastInside = useRef2(null);
1293
+ useLayoutEffect2(() => {
1294
+ const element = form.current;
1295
+ if (!element) return;
1296
+ if (busy) {
1297
+ const active = document.activeElement;
1298
+ const from = active && active !== element && element.contains(active) ? active : !active || active === document.body ? lastInside.current : null;
1299
+ if (from?.isConnected) {
1300
+ sender.current = from;
1301
+ holding.current = true;
1302
+ element.focus();
1303
+ }
1304
+ return;
1305
+ }
1306
+ if (!holding.current) return;
1307
+ holding.current = false;
1308
+ if (document.activeElement !== element && document.activeElement !== document.body) return;
1309
+ const target = firstInvalid(element) ?? (usable(sender.current) ? sender.current : Array.from(element.querySelectorAll(CONTROL)).find(usable));
1310
+ sender.current = null;
1311
+ target?.focus();
1312
+ }, [busy]);
1313
+ const onKeyDown = (event) => {
1314
+ props.onKeyDown?.(event);
1315
+ if (event.key !== "Enter" || event.defaultPrevented || event.nativeEvent.isComposing) return;
1316
+ const target = event.target;
1317
+ const inInput = target instanceof HTMLInputElement;
1318
+ if (inInput) event.preventDefault();
1319
+ if (event.altKey || event.shiftKey) return;
1320
+ if (event.ctrlKey || event.metaKey) {
1321
+ event.preventDefault();
1322
+ form.current?.requestSubmit();
1323
+ return;
1324
+ }
1325
+ if (!inInput) return;
1326
+ const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
1327
+ if (enterSends && oneLine) form.current?.requestSubmit();
1328
+ };
1329
+ return /* @__PURE__ */ jsx21(
1330
+ BaseForm,
1331
+ {
1332
+ ref: form,
1333
+ ...props,
1334
+ tabIndex: busy ? -1 : props.tabIndex,
1335
+ className: cn("outline-none", className),
1336
+ onFocus: (event) => {
1337
+ if (event.target !== form.current) lastInside.current = event.target;
1338
+ props.onFocus?.(event);
1339
+ },
1340
+ onBlur: (event) => {
1341
+ const next = event.relatedTarget;
1342
+ if (next && !form.current?.contains(next)) lastInside.current = null;
1343
+ props.onBlur?.(event);
1344
+ },
1345
+ onKeyDown,
1346
+ onSubmit: (event) => {
1347
+ event.preventDefault();
1348
+ if (busyNow.current) return;
1349
+ void onSubmit();
1350
+ },
1351
+ children: /* @__PURE__ */ jsx21(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx21(FormBusyContext.Provider, { value: busy, children }) })
1352
+ }
1353
+ );
1354
+ }
1355
+
1258
1356
  // src/Skeleton.tsx
1259
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1357
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1260
1358
  function SkeletonBar({ className, style }) {
1261
- return /* @__PURE__ */ jsx21("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1359
+ return /* @__PURE__ */ jsx22("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1262
1360
  }
1263
1361
  var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
1264
1362
  function SkeletonRow({ barWidth = 130 }) {
1265
1363
  return /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1266
- /* @__PURE__ */ jsx21(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1267
- /* @__PURE__ */ jsx21(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1364
+ /* @__PURE__ */ jsx22(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1365
+ /* @__PURE__ */ jsx22(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1268
1366
  ] });
1269
1367
  }
1270
1368
  function SkeletonList({ rows = 8, className }) {
1271
- return /* @__PURE__ */ jsx21("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx21(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1369
+ return /* @__PURE__ */ jsx22("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx22(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1272
1370
  }
1273
1371
 
1274
1372
  // src/CommandPalette.tsx
1275
- import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
1373
+ import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1276
1374
  var PaletteContext = createContext3(null);
1277
1375
  function usePalette(part) {
1278
1376
  const palette = useContext3(PaletteContext);
1279
1377
  if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
1280
1378
  return palette;
1281
1379
  }
1282
- var CONTROL = 'input:not([type="hidden"]):not([tabindex="-1"]), textarea, button:not([tabindex="-1"]), [role="combobox"]';
1380
+ var CONTROL2 = 'input:not([type="hidden"]):not([tabindex="-1"]), textarea, button:not([tabindex="-1"]), [role="combobox"]';
1283
1381
  function firstControl(popup) {
1284
1382
  if (!popup) return null;
1285
1383
  const field = popup.querySelector("[data-command-palette-field]");
1286
1384
  if (field) return field;
1287
- return popup.querySelector("[data-command-palette-fields]")?.querySelector(CONTROL) ?? null;
1385
+ return popup.querySelector("[data-command-palette-fields]")?.querySelector(CONTROL2) ?? null;
1288
1386
  }
1289
1387
  function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", children }) {
1290
- const popupRef = useRef2(null);
1388
+ const popupRef = useRef3(null);
1291
1389
  useEffect(() => {
1292
1390
  if (!open) return;
1293
1391
  const frame = requestAnimationFrame(() => {
@@ -1298,9 +1396,9 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
1298
1396
  return () => cancelAnimationFrame(frame);
1299
1397
  });
1300
1398
  const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
1301
- return /* @__PURE__ */ jsx22(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs16(Dialog.Portal, { children: [
1302
- /* @__PURE__ */ jsx22(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1303
- /* @__PURE__ */ jsx22(Dialog.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx22(
1399
+ return /* @__PURE__ */ jsx23(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs16(Dialog.Portal, { children: [
1400
+ /* @__PURE__ */ jsx23(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1401
+ /* @__PURE__ */ jsx23(Dialog.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx23(
1304
1402
  Dialog.Popup,
1305
1403
  {
1306
1404
  ref: popupRef,
@@ -1310,13 +1408,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
1310
1408
  if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
1311
1409
  },
1312
1410
  className: "flex w-[658px] max-w-[calc(100vw-32px)] flex-col overflow-hidden rounded-lg border border-border-default bg-bg-elevated shadow-lg outline-none",
1313
- children: /* @__PURE__ */ jsx22(PaletteContext.Provider, { value: context, children })
1411
+ children: /* @__PURE__ */ jsx23(PaletteContext.Provider, { value: context, children })
1314
1412
  }
1315
1413
  ) })
1316
1414
  ] }) });
1317
1415
  }
1318
1416
  function LevelChip({ chip, onBack }) {
1319
- return /* @__PURE__ */ jsx22(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
1417
+ return /* @__PURE__ */ jsx23(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
1320
1418
  }
1321
1419
  function useBack(chip, popupRef) {
1322
1420
  return () => {
@@ -1328,9 +1426,9 @@ function useBack(chip, popupRef) {
1328
1426
  function Footer({ keys }) {
1329
1427
  const { where } = usePalette("The footer");
1330
1428
  return /* @__PURE__ */ jsxs16("div", { className: "flex h-9 shrink-0 items-center gap-4 border-t border-border-subtle px-5 text-caption text-text-secondary signal:font-mono signal:text-small signal:text-text-muted", children: [
1331
- /* @__PURE__ */ jsx22("span", { className: "min-w-0 flex-1 truncate", children: where }),
1429
+ /* @__PURE__ */ jsx23("span", { className: "min-w-0 flex-1 truncate", children: where }),
1332
1430
  keys.map(([key, word]) => /* @__PURE__ */ jsxs16("span", { className: "flex shrink-0 items-center gap-1.5", children: [
1333
- /* @__PURE__ */ jsx22(Kbd, { children: key }),
1431
+ /* @__PURE__ */ jsx23(Kbd, { children: key }),
1334
1432
  " ",
1335
1433
  word
1336
1434
  ] }, key))
@@ -1344,11 +1442,11 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1344
1442
  const rows = items.flatMap((g) => g.items);
1345
1443
  const [litId, setLitId] = useState3();
1346
1444
  const lit = litId === void 0 ? void 0 : rows.find((r) => r.id === litId);
1347
- const inputRef = useRef2(null);
1348
- const reported = useRef2({});
1349
- const settled = useRef2(null);
1350
- const moved = useRef2(false);
1351
- useLayoutEffect2(() => {
1445
+ const inputRef = useRef3(null);
1446
+ const reported = useRef3({});
1447
+ const settled = useRef3(null);
1448
+ const moved = useRef3(false);
1449
+ useLayoutEffect3(() => {
1352
1450
  const before = settled.current;
1353
1451
  const now = reported.current;
1354
1452
  const sameLevel = before?.query === query && before?.level === chip?.label;
@@ -1431,9 +1529,9 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1431
1529
  },
1432
1530
  children: [
1433
1531
  /* @__PURE__ */ jsxs16("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1434
- /* @__PURE__ */ jsx22(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
1435
- chip && /* @__PURE__ */ jsx22(LevelChip, { chip, onBack: back }),
1436
- /* @__PURE__ */ jsx22(
1532
+ /* @__PURE__ */ jsx23(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
1533
+ chip && /* @__PURE__ */ jsx23(LevelChip, { chip, onBack: back }),
1534
+ /* @__PURE__ */ jsx23(
1437
1535
  Autocomplete.Input,
1438
1536
  {
1439
1537
  ref: inputRef,
@@ -1446,42 +1544,42 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1446
1544
  )
1447
1545
  ] }),
1448
1546
  /* @__PURE__ */ jsxs16(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
1449
- children != null && /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
1450
- /* @__PURE__ */ jsx22(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs16(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
1451
- /* @__PURE__ */ jsx22(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx22(SectionLabel, { className: "text-text-secondary", children: group.value }) }),
1452
- /* @__PURE__ */ jsx22(Autocomplete.Collection, { children: (row) => (
1547
+ children != null && /* @__PURE__ */ jsx23("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
1548
+ /* @__PURE__ */ jsx23(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs16(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
1549
+ /* @__PURE__ */ jsx23(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx23(SectionLabel, { className: "text-text-secondary", children: group.value }) }),
1550
+ /* @__PURE__ */ jsx23(Autocomplete.Collection, { children: (row) => (
1453
1551
  /* The menu row, as the list's own option — the way Select
1454
1552
  puts it on `Select.Item`. One row, two parts. */
1455
- /* @__PURE__ */ jsx22(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx22(
1553
+ /* @__PURE__ */ jsx23(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx23(
1456
1554
  MenuItemBody,
1457
1555
  {
1458
1556
  size: "tall",
1459
1557
  label: row.label,
1460
1558
  description: row.description,
1461
- leading: /* @__PURE__ */ jsx22(RowLeading, { row }),
1559
+ leading: /* @__PURE__ */ jsx23(RowLeading, { row }),
1462
1560
  submenu: !!row.onGoIn,
1463
- hint: row.onGoIn ? /* @__PURE__ */ jsx22(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx22(EnterHint, {})
1561
+ hint: row.onGoIn ? /* @__PURE__ */ jsx23(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx23(EnterHint, {})
1464
1562
  }
1465
1563
  ) }, row.id)
1466
1564
  ) })
1467
1565
  ] }, group.value) }),
1468
- /* @__PURE__ */ jsx22(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs16(Fragment3, { children: [
1469
- /* @__PURE__ */ jsx22(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
1470
- /* @__PURE__ */ jsx22("span", { className: "text-caption text-text-muted", children: pending })
1566
+ /* @__PURE__ */ jsx23(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs16(Fragment3, { children: [
1567
+ /* @__PURE__ */ jsx23(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
1568
+ /* @__PURE__ */ jsx23("span", { className: "text-caption text-text-muted", children: pending })
1471
1569
  ] }) }),
1472
- notes.map((note) => /* @__PURE__ */ jsx22("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx22(FieldLine, { children: note }) }, note)),
1473
- /* @__PURE__ */ jsx22(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx22(EmptyState, { scope: "section", message: empty }) })
1570
+ notes.map((note) => /* @__PURE__ */ jsx23("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx23(FieldLine, { children: note }) }, note)),
1571
+ /* @__PURE__ */ jsx23(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx23(EmptyState, { scope: "section", message: empty }) })
1474
1572
  ] }),
1475
- /* @__PURE__ */ jsx22(Footer, { keys })
1573
+ /* @__PURE__ */ jsx23(Footer, { keys })
1476
1574
  ]
1477
1575
  }
1478
1576
  );
1479
1577
  }
1480
1578
  function RowLeading({ row }) {
1481
1579
  if (row.icon != null) {
1482
- return /* @__PURE__ */ jsx22("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
1580
+ return /* @__PURE__ */ jsx23("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
1483
1581
  }
1484
- return /* @__PURE__ */ jsx22("span", { className: "flex size-8 items-center justify-center", children: row.leading });
1582
+ return /* @__PURE__ */ jsx23("span", { className: "flex size-8 items-center justify-center", children: row.leading });
1485
1583
  }
1486
1584
  var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
1487
1585
  function isTextField(el) {
@@ -1491,31 +1589,18 @@ function isTextField(el) {
1491
1589
  function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, working, error, children }) {
1492
1590
  const { modKey, popupRef } = usePalette("CommandPaletteForm");
1493
1591
  const back = useBack(chip, popupRef);
1494
- const frameRef = useRef2(null);
1592
+ const frameRef = useRef3(null);
1495
1593
  const busy = !!working;
1496
- const busyRef = useRef2(busy);
1594
+ const busyRef = useRef3(busy);
1497
1595
  busyRef.current = busy;
1498
- const returnTo = useRef2(null);
1499
- const firstInvalid = () => frameRef.current?.querySelector("[data-invalid]")?.querySelector(CONTROL) ?? null;
1596
+ const firstInvalid2 = () => frameRef.current?.querySelector("[data-invalid]")?.querySelector(CONTROL2) ?? null;
1500
1597
  const submit = () => {
1501
1598
  if (busyRef.current || submitWaits) return;
1502
- const active = document.activeElement;
1503
- returnTo.current = active instanceof HTMLElement && frameRef.current?.contains(active) ? active : null;
1504
1599
  onSubmit();
1505
1600
  requestAnimationFrame(() => {
1506
- if (!busyRef.current) firstInvalid()?.focus();
1601
+ if (!busyRef.current) firstInvalid2()?.focus();
1507
1602
  });
1508
1603
  };
1509
- useLayoutEffect2(() => {
1510
- if (busy) {
1511
- frameRef.current?.focus();
1512
- return;
1513
- }
1514
- if (document.activeElement !== frameRef.current) return;
1515
- const was = returnTo.current;
1516
- const target = firstInvalid() ?? (was?.isConnected && !was.disabled ? was : null) ?? firstControl(popupRef.current);
1517
- target?.focus();
1518
- }, [busy]);
1519
1604
  const backWorksFrom = (el) => {
1520
1605
  const frame = frameRef.current;
1521
1606
  if (!frame || busy || !el || !frame.contains(el)) return false;
@@ -1524,13 +1609,8 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
1524
1609
  };
1525
1610
  const [backNamed, setBackNamed] = useState3(false);
1526
1611
  const measure = () => setBackNamed(backWorksFrom(document.activeElement));
1527
- useLayoutEffect2(measure);
1612
+ useLayoutEffect3(measure);
1528
1613
  const onKeyDown = (e) => {
1529
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
1530
- e.preventDefault();
1531
- submit();
1532
- return;
1533
- }
1534
1614
  if (e.key === "Backspace" && !e.ctrlKey && !e.metaKey && !e.altKey && backWorksFrom(e.target)) {
1535
1615
  e.preventDefault();
1536
1616
  back();
@@ -1543,52 +1623,54 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
1543
1623
  ];
1544
1624
  return /* @__PURE__ */ jsxs16("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
1545
1625
  /* @__PURE__ */ jsxs16("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1546
- icon != null && /* @__PURE__ */ jsx22("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
1547
- /* @__PURE__ */ jsx22(LevelChip, { chip, onBack: back })
1626
+ icon != null && /* @__PURE__ */ jsx23("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
1627
+ /* @__PURE__ */ jsx23(LevelChip, { chip, onBack: back })
1548
1628
  ] }),
1549
- /* @__PURE__ */ jsx22(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx22("fieldset", { "data-command-palette-fields": "", disabled: busy, className: "contents", children: /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-4", children }) }) }),
1550
- /* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
1551
- /* @__PURE__ */ jsx22("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx22(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx22(FieldLine, { tone: "error", children: error }) : null }),
1552
- /* @__PURE__ */ jsx22(
1553
- Button,
1554
- {
1555
- variant: "primary",
1556
- onClick: submit,
1557
- disabled: busy,
1558
- disabledReason: busy ? void 0 : submitWaits,
1559
- leadingIcon: busy ? /* @__PURE__ */ jsx22(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
1560
- children: working ? working.button : submitLabel
1561
- }
1562
- )
1629
+ /* @__PURE__ */ jsxs16(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
1630
+ /* @__PURE__ */ jsx23(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx23("div", { className: "flex flex-col gap-4", children }) }),
1631
+ /* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
1632
+ /* @__PURE__ */ jsx23("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx23(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx23(FieldLine, { tone: "error", children: error }) : null }),
1633
+ /* @__PURE__ */ jsx23(
1634
+ Button,
1635
+ {
1636
+ type: "submit",
1637
+ variant: "primary",
1638
+ disabled: busy,
1639
+ disabledReason: busy ? void 0 : submitWaits,
1640
+ leadingIcon: busy ? /* @__PURE__ */ jsx23(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
1641
+ children: working ? working.button : submitLabel
1642
+ }
1643
+ )
1644
+ ] })
1563
1645
  ] }),
1564
- /* @__PURE__ */ jsx22(Footer, { keys })
1646
+ /* @__PURE__ */ jsx23(Footer, { keys })
1565
1647
  ] });
1566
1648
  }
1567
1649
  var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
1568
1650
  function CommandPaletteWorking({ children, bars = 2 }) {
1569
1651
  return /* @__PURE__ */ jsxs16("div", { role: "status", className: "flex flex-col gap-2", children: [
1570
1652
  /* @__PURE__ */ jsxs16("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
1571
- /* @__PURE__ */ jsx22(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
1653
+ /* @__PURE__ */ jsx23(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
1572
1654
  children
1573
1655
  ] }),
1574
- BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx22(SkeletonBar, { className: cn("h-3", width) }, width))
1656
+ BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx23(SkeletonBar, { className: cn("h-3", width) }, width))
1575
1657
  ] });
1576
1658
  }
1577
1659
  function CommandPaletteAnswer({ children, note }) {
1578
1660
  const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
1579
1661
  return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-2", children: [
1580
- paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx22("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
1581
- (part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx22("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
1662
+ paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx23("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
1663
+ (part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx23("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
1582
1664
  ) }, i)),
1583
- note && /* @__PURE__ */ jsx22(FieldLine, { children: note })
1665
+ note && /* @__PURE__ */ jsx23(FieldLine, { children: note })
1584
1666
  ] });
1585
1667
  }
1586
1668
  function CommandPaletteQuote({ children }) {
1587
- return /* @__PURE__ */ jsx22("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
1669
+ return /* @__PURE__ */ jsx23("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
1588
1670
  }
1589
1671
 
1590
1672
  // src/InlineChip.tsx
1591
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
1673
+ import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1592
1674
  var INLINE_CHIP_CLASSES = "inline-flex h-[1.4em] items-center gap-1 rounded-sm px-1 mx-0.5 align-top text-body-2 font-normal select-none";
1593
1675
  var INLINE_CHIP_TONE_CLASSES = {
1594
1676
  /** A thing or a place — anything that is not a person. */
@@ -1611,22 +1693,22 @@ function inlineChipClassName(tone, className) {
1611
1693
  }
1612
1694
  function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
1613
1695
  const body = /* @__PURE__ */ jsxs17(Fragment4, { children: [
1614
- icon && /* @__PURE__ */ jsx23("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
1696
+ icon && /* @__PURE__ */ jsx24("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
1615
1697
  children
1616
1698
  ] });
1617
1699
  const classes = inlineChipClassName(tone, className);
1618
1700
  if (href === void 0) {
1619
- return /* @__PURE__ */ jsx23("span", { className: classes, ...props, children: body });
1701
+ return /* @__PURE__ */ jsx24("span", { className: classes, ...props, children: body });
1620
1702
  }
1621
- return /* @__PURE__ */ jsx23("a", { href, className: classes, ...props, children: body });
1703
+ return /* @__PURE__ */ jsx24("a", { href, className: classes, ...props, children: body });
1622
1704
  }
1623
1705
 
1624
1706
  // src/IdentityMenu.tsx
1625
- import { useCallback, useRef as useRef3 } from "react";
1707
+ import { useCallback, useRef as useRef4 } from "react";
1626
1708
 
1627
1709
  // src/Divider.tsx
1628
1710
  import { Separator } from "@base-ui/react/separator";
1629
- import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
1711
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1630
1712
  function Divider({ orientation = "horizontal", label, tone = "default", className }) {
1631
1713
  if (label && orientation === "horizontal") {
1632
1714
  const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
@@ -1637,14 +1719,14 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
1637
1719
  "aria-label": label,
1638
1720
  className: cn("flex shrink-0 items-center gap-2 mx-3", className),
1639
1721
  children: [
1640
- /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1641
- /* @__PURE__ */ jsx24("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1642
- /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1722
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1723
+ /* @__PURE__ */ jsx25("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1724
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1643
1725
  ]
1644
1726
  }
1645
1727
  );
1646
1728
  }
1647
- return /* @__PURE__ */ jsx24(
1729
+ return /* @__PURE__ */ jsx25(
1648
1730
  Separator,
1649
1731
  {
1650
1732
  orientation,
@@ -1654,15 +1736,15 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
1654
1736
  }
1655
1737
 
1656
1738
  // src/Person.tsx
1657
- import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
1739
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1658
1740
  function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
1659
1741
  return (
1660
1742
  // gap-2: the face-to-name distance is one rule (8px) wherever a person
1661
1743
  // appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
1662
1744
  // row agree by construction.
1663
1745
  /* @__PURE__ */ jsxs19("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
1664
- /* @__PURE__ */ jsx25(Avatar, { name, src: picture, size }),
1665
- /* @__PURE__ */ jsx25("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
1746
+ /* @__PURE__ */ jsx26(Avatar, { name, src: picture, size }),
1747
+ /* @__PURE__ */ jsx26("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
1666
1748
  ] })
1667
1749
  );
1668
1750
  }
@@ -1670,10 +1752,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
1670
1752
  // src/PersonTrigger.tsx
1671
1753
  import { Button as BaseButton5 } from "@base-ui/react/button";
1672
1754
  import { IconChevronDown } from "@tabler/icons-react";
1673
- import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1755
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1674
1756
  function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
1675
1757
  if (compact) {
1676
- return /* @__PURE__ */ jsx26(
1758
+ return /* @__PURE__ */ jsx27(
1677
1759
  BaseButton5,
1678
1760
  {
1679
1761
  type: "button",
@@ -1682,7 +1764,7 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
1682
1764
  "aria-label": props["aria-label"] ?? name ?? fallback,
1683
1765
  className: cn("cursor-pointer rounded-full", className),
1684
1766
  ...props,
1685
- children: /* @__PURE__ */ jsx26(Avatar, { name, src: picture, size: size ?? 36 })
1767
+ children: /* @__PURE__ */ jsx27(Avatar, { name, src: picture, size: size ?? 36 })
1686
1768
  }
1687
1769
  );
1688
1770
  }
@@ -1704,18 +1786,18 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
1704
1786
  ),
1705
1787
  ...props,
1706
1788
  children: [
1707
- /* @__PURE__ */ jsx26(Person, { name, picture, fallback, size: size ?? 22 }),
1708
- /* @__PURE__ */ jsx26(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
1789
+ /* @__PURE__ */ jsx27(Person, { name, picture, fallback, size: size ?? 22 }),
1790
+ /* @__PURE__ */ jsx27(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
1709
1791
  ]
1710
1792
  }
1711
1793
  );
1712
1794
  }
1713
1795
 
1714
1796
  // src/IdentityMenu.tsx
1715
- import { Fragment as Fragment5, jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
1797
+ import { Fragment as Fragment5, jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1716
1798
  function IdentityPanel({ className, onClose = () => {
1717
1799
  }, ...rest }) {
1718
- return /* @__PURE__ */ jsx27(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx27(IdentityRows, { ...rest, onClose }) });
1800
+ return /* @__PURE__ */ jsx28(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx28(IdentityRows, { ...rest, onClose }) });
1719
1801
  }
1720
1802
  function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
1721
1803
  const act = (action) => () => {
@@ -1725,51 +1807,51 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
1725
1807
  const appRows = typeof children === "function" ? children(onClose) : children;
1726
1808
  return /* @__PURE__ */ jsxs21(Fragment5, { children: [
1727
1809
  /* @__PURE__ */ jsxs21(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
1728
- /* @__PURE__ */ jsx27(MenuRow, { children: /* @__PURE__ */ jsx27(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
1729
- /* @__PURE__ */ jsx27(Note, { children: signedIn ? "Your Estiva ID. The same person you are in every Estiva app." : "A key held by this browser only. Nobody else knows who you are." }),
1810
+ /* @__PURE__ */ jsx28(MenuRow, { children: /* @__PURE__ */ jsx28(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
1811
+ /* @__PURE__ */ jsx28(Note, { children: signedIn ? "Your Estiva ID. The same person you are in every Estiva app." : "A key held by this browser only. Nobody else knows who you are." }),
1730
1812
  me.email && /* @__PURE__ */ jsxs21(Note, { children: [
1731
1813
  me.email,
1732
1814
  " \xB7 known to Estiva, never published to the relay"
1733
1815
  ] })
1734
1816
  ] }),
1735
1817
  relayUrl && /* @__PURE__ */ jsxs21(Fragment5, { children: [
1736
- /* @__PURE__ */ jsx27(Divider, { className: "mx-0 my-2" }),
1818
+ /* @__PURE__ */ jsx28(Divider, { className: "mx-0 my-2" }),
1737
1819
  /* @__PURE__ */ jsxs21(MenuSection, { label: "Workspace", children: [
1738
- /* @__PURE__ */ jsx27(MenuRow, { children: /* @__PURE__ */ jsx27("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
1739
- /* @__PURE__ */ jsx27(Note, { children: "Everyone on this relay shares this workspace, in every app." })
1820
+ /* @__PURE__ */ jsx28(MenuRow, { children: /* @__PURE__ */ jsx28("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
1821
+ /* @__PURE__ */ jsx28(Note, { children: "Everyone on this relay shares this workspace, in every app." })
1740
1822
  ] })
1741
1823
  ] }),
1742
1824
  appRows && /* @__PURE__ */ jsxs21(Fragment5, { children: [
1743
- /* @__PURE__ */ jsx27(Divider, { className: "mx-0 my-2" }),
1825
+ /* @__PURE__ */ jsx28(Divider, { className: "mx-0 my-2" }),
1744
1826
  appRows
1745
1827
  ] }),
1746
- signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx27(Divider, { className: "mx-0 my-2" }) : null,
1747
- signedIn && idBase && /* @__PURE__ */ jsx27(
1828
+ signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx28(Divider, { className: "mx-0 my-2" }) : null,
1829
+ signedIn && idBase && /* @__PURE__ */ jsx28(
1748
1830
  MenuItem,
1749
1831
  {
1750
1832
  label: "Edit your profile in Estiva ID",
1751
1833
  onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
1752
1834
  }
1753
1835
  ),
1754
- onCopyKey && /* @__PURE__ */ jsx27(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
1755
- idBase && onSignOut && /* @__PURE__ */ jsx27(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
1836
+ onCopyKey && /* @__PURE__ */ jsx28(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
1837
+ idBase && onSignOut && /* @__PURE__ */ jsx28(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
1756
1838
  ] });
1757
1839
  }
1758
1840
  function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
1759
- const actions = useRef3(null);
1841
+ const actions = useRef4(null);
1760
1842
  const close = useCallback(() => actions.current?.close(), []);
1761
1843
  return (
1762
1844
  /* The wrapper carries the caller's `className` and nothing else. It used
1763
1845
  to be `relative`, because the panel was positioned against it; the panel
1764
1846
  hangs from the trigger and portals now, so a positioning context here
1765
1847
  would only be a lie about what this box does. */
1766
- /* @__PURE__ */ jsx27("div", { className, children: /* @__PURE__ */ jsx27(
1848
+ /* @__PURE__ */ jsx28("div", { className, children: /* @__PURE__ */ jsx28(
1767
1849
  Menu,
1768
1850
  {
1769
1851
  align: "right",
1770
1852
  actionsRef: actions,
1771
1853
  className: "w-72",
1772
- trigger: /* @__PURE__ */ jsx27(
1854
+ trigger: /* @__PURE__ */ jsx28(
1773
1855
  PersonTrigger,
1774
1856
  {
1775
1857
  name: me.name,
@@ -1780,7 +1862,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
1780
1862
  "aria-label": compact ? "Account menu" : void 0
1781
1863
  }
1782
1864
  ),
1783
- children: /* @__PURE__ */ jsx27(
1865
+ children: /* @__PURE__ */ jsx28(
1784
1866
  IdentityRows,
1785
1867
  {
1786
1868
  me,
@@ -1798,14 +1880,14 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
1798
1880
  );
1799
1881
  }
1800
1882
  function Note({ children }) {
1801
- return /* @__PURE__ */ jsx27("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
1883
+ return /* @__PURE__ */ jsx28("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
1802
1884
  }
1803
1885
 
1804
1886
  // src/FilePicker.tsx
1805
1887
  import { forwardRef } from "react";
1806
- import { jsx as jsx28 } from "react/jsx-runtime";
1888
+ import { jsx as jsx29 } from "react/jsx-runtime";
1807
1889
  var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
1808
- return /* @__PURE__ */ jsx28(
1890
+ return /* @__PURE__ */ jsx29(
1809
1891
  "input",
1810
1892
  {
1811
1893
  ref,
@@ -1823,68 +1905,6 @@ var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
1823
1905
  );
1824
1906
  });
1825
1907
 
1826
- // src/Form.tsx
1827
- import { useLayoutEffect as useLayoutEffect3, useRef as useRef4 } from "react";
1828
- import { Fieldset } from "@base-ui/react/fieldset";
1829
- import { Form as BaseForm } from "@base-ui/react/form";
1830
- import { jsx as jsx29 } from "react/jsx-runtime";
1831
- var CONTROL2 = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
1832
- function usable(element) {
1833
- return element instanceof HTMLElement && element.isConnected && element.matches(CONTROL2) && !element.matches(":disabled") && element.getAttribute("aria-disabled") !== "true";
1834
- }
1835
- function Form({ onSubmit, busy: ownBusy = false, className, children, ...props }) {
1836
- const outerBusy = useFormBusy();
1837
- const busy = ownBusy || outerBusy;
1838
- const form = useRef4(null);
1839
- const sender = useRef4(null);
1840
- const holding = useRef4(false);
1841
- const lastInside = useRef4(null);
1842
- useLayoutEffect3(() => {
1843
- const element = form.current;
1844
- if (!element) return;
1845
- if (busy) {
1846
- const active = document.activeElement;
1847
- const from = active && active !== element && element.contains(active) ? active : !active || active === document.body ? lastInside.current : null;
1848
- if (from?.isConnected) {
1849
- sender.current = from;
1850
- holding.current = true;
1851
- element.focus();
1852
- }
1853
- return;
1854
- }
1855
- if (!holding.current) return;
1856
- holding.current = false;
1857
- if (document.activeElement !== element && document.activeElement !== document.body) return;
1858
- const invalid = Array.from(element.querySelectorAll("[data-invalid]")).find(usable);
1859
- const target = invalid ?? (usable(sender.current) ? sender.current : Array.from(element.querySelectorAll(CONTROL2)).find(usable));
1860
- sender.current = null;
1861
- target?.focus();
1862
- }, [busy]);
1863
- return /* @__PURE__ */ jsx29(
1864
- BaseForm,
1865
- {
1866
- ref: form,
1867
- ...props,
1868
- tabIndex: busy ? -1 : props.tabIndex,
1869
- className: cn("outline-none", className),
1870
- onFocus: (event) => {
1871
- if (event.target !== form.current) lastInside.current = event.target;
1872
- props.onFocus?.(event);
1873
- },
1874
- onBlur: (event) => {
1875
- const next = event.relatedTarget;
1876
- if (next && !form.current?.contains(next)) lastInside.current = null;
1877
- props.onBlur?.(event);
1878
- },
1879
- onSubmit: (event) => {
1880
- event.preventDefault();
1881
- void onSubmit();
1882
- },
1883
- children: /* @__PURE__ */ jsx29(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx29(FormBusyContext.Provider, { value: busy, children }) })
1884
- }
1885
- );
1886
- }
1887
-
1888
1908
  // src/Select.tsx
1889
1909
  import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
1890
1910
  import { Select as BaseSelect } from "@base-ui/react/select";