@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/README.md +13 -5
- package/dist/Checkbox.d.ts +16 -1
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/CommandPalette.d.ts.map +1 -1
- package/dist/Form.d.ts +16 -1
- package/dist/Form.d.ts.map +1 -1
- package/dist/ScrollArea.d.ts +6 -0
- package/dist/ScrollArea.d.ts.map +1 -1
- package/dist/eslint/index.d.ts +2 -0
- package/dist/eslint/index.d.ts.map +1 -1
- package/dist/eslint/index.js +459 -2
- package/dist/eslint/index.js.map +4 -4
- package/dist/eslint/no-rebuilt-behaviour.d.ts +88 -0
- package/dist/eslint/no-rebuilt-behaviour.d.ts.map +1 -0
- package/dist/index.js +208 -188
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/Checkbox.mdx +20 -1
- package/src/Checkbox.stories.tsx +44 -0
- package/src/Checkbox.test.tsx +63 -0
- package/src/Checkbox.tsx +30 -1
- package/src/CommandPalette.mdx +6 -2
- package/src/CommandPalette.stories.tsx +6 -3
- package/src/CommandPalette.test.tsx +15 -0
- package/src/CommandPalette.tsx +34 -46
- package/src/Form.mdx +12 -2
- package/src/Form.test.tsx +103 -0
- package/src/Form.tsx +64 -4
- package/src/ScrollArea.stories.tsx +18 -0
- package/src/ScrollArea.tsx +7 -1
- package/src/eslint/index.test.ts +31 -7
- package/src/eslint/index.ts +10 -3
- package/src/eslint/no-rebuilt-behaviour.test.ts +276 -0
- package/src/eslint/no-rebuilt-behaviour.ts +593 -0
- package/stories/Choosing.mdx +1 -1
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
|
-
|
|
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
|
|
828
|
+
useLayoutEffect as useLayoutEffect3,
|
|
821
829
|
useMemo as useMemo2,
|
|
822
|
-
useRef as
|
|
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
|
|
1357
|
+
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1260
1358
|
function SkeletonBar({ className, style }) {
|
|
1261
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
1267
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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__ */
|
|
1302
|
-
/* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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 =
|
|
1348
|
-
const reported =
|
|
1349
|
-
const settled =
|
|
1350
|
-
const moved =
|
|
1351
|
-
|
|
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__ */
|
|
1435
|
-
chip && /* @__PURE__ */
|
|
1436
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1450
|
-
/* @__PURE__ */
|
|
1451
|
-
/* @__PURE__ */
|
|
1452
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1559
|
+
leading: /* @__PURE__ */ jsx23(RowLeading, { row }),
|
|
1462
1560
|
submenu: !!row.onGoIn,
|
|
1463
|
-
hint: row.onGoIn ? /* @__PURE__ */
|
|
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__ */
|
|
1469
|
-
/* @__PURE__ */
|
|
1470
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1473
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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 =
|
|
1592
|
+
const frameRef = useRef3(null);
|
|
1495
1593
|
const busy = !!working;
|
|
1496
|
-
const busyRef =
|
|
1594
|
+
const busyRef = useRef3(busy);
|
|
1497
1595
|
busyRef.current = busy;
|
|
1498
|
-
const
|
|
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)
|
|
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
|
-
|
|
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__ */
|
|
1547
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1550
|
-
|
|
1551
|
-
/* @__PURE__ */
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1581
|
-
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */
|
|
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__ */
|
|
1665
|
+
note && /* @__PURE__ */ jsx23(FieldLine, { children: note })
|
|
1584
1666
|
] });
|
|
1585
1667
|
}
|
|
1586
1668
|
function CommandPaletteQuote({ children }) {
|
|
1587
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1701
|
+
return /* @__PURE__ */ jsx24("span", { className: classes, ...props, children: body });
|
|
1620
1702
|
}
|
|
1621
|
-
return /* @__PURE__ */
|
|
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
|
|
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
|
|
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__ */
|
|
1641
|
-
/* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
1665
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1708
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1818
|
+
/* @__PURE__ */ jsx28(Divider, { className: "mx-0 my-2" }),
|
|
1737
1819
|
/* @__PURE__ */ jsxs21(MenuSection, { label: "Workspace", children: [
|
|
1738
|
-
/* @__PURE__ */
|
|
1739
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1825
|
+
/* @__PURE__ */ jsx28(Divider, { className: "mx-0 my-2" }),
|
|
1744
1826
|
appRows
|
|
1745
1827
|
] }),
|
|
1746
|
-
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */
|
|
1747
|
-
signedIn && idBase && /* @__PURE__ */
|
|
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__ */
|
|
1755
|
-
idBase && onSignOut && /* @__PURE__ */
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
1888
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1807
1889
|
var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
1808
|
-
return /* @__PURE__ */
|
|
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";
|