@estiva-app/ui 0.15.0 → 0.16.1
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/Breadcrumb.d.ts.map +1 -1
- package/dist/CommandPalette.d.ts +121 -0
- package/dist/CommandPalette.d.ts.map +1 -0
- package/dist/Menu.d.ts +4 -0
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Toast.d.ts.map +1 -1
- package/dist/eslint/has-a-page-and-a-story.d.ts +4 -0
- package/dist/eslint/has-a-page-and-a-story.d.ts.map +1 -0
- package/dist/eslint/index.d.ts +15 -1
- package/dist/eslint/index.d.ts.map +1 -1
- package/dist/eslint/index.js +176 -8
- package/dist/eslint/index.js.map +3 -3
- package/dist/eslint/no-hand-rolled-behaviour.d.ts +3 -0
- package/dist/eslint/no-hand-rolled-behaviour.d.ts.map +1 -0
- package/dist/eslint/raw-element-outside-a-wrapper.d.ts +29 -0
- package/dist/eslint/raw-element-outside-a-wrapper.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +614 -287
- package/dist/index.js.map +4 -4
- package/package.json +5 -1
- package/src/Breadcrumb.tsx +6 -2
- package/src/CommandPalette.mdx +139 -0
- package/src/CommandPalette.stories.tsx +418 -0
- package/src/CommandPalette.test.tsx +415 -0
- package/src/CommandPalette.tsx +664 -0
- package/src/Menu.tsx +4 -2
- package/src/Toast.tsx +12 -24
- package/src/eslint/has-a-page-and-a-story.test.ts +57 -0
- package/src/eslint/has-a-page-and-a-story.ts +97 -0
- package/src/eslint/index.test.ts +35 -3
- package/src/eslint/index.ts +58 -13
- package/src/eslint/no-hand-rolled-behaviour.test.ts +70 -0
- package/src/eslint/no-hand-rolled-behaviour.ts +116 -0
- package/src/eslint/raw-element-outside-a-wrapper.test.ts +82 -0
- package/src/eslint/raw-element-outside-a-wrapper.ts +85 -0
- package/src/index.ts +17 -0
- package/stories/Choosing.mdx +1 -0
package/dist/index.js
CHANGED
|
@@ -789,6 +789,20 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
|
|
|
789
789
|
] });
|
|
790
790
|
}
|
|
791
791
|
|
|
792
|
+
// src/CommandPalette.tsx
|
|
793
|
+
import {
|
|
794
|
+
createContext as createContext2,
|
|
795
|
+
useContext as useContext2,
|
|
796
|
+
useEffect,
|
|
797
|
+
useLayoutEffect as useLayoutEffect2,
|
|
798
|
+
useMemo as useMemo2,
|
|
799
|
+
useRef as useRef2,
|
|
800
|
+
useState as useState3
|
|
801
|
+
} from "react";
|
|
802
|
+
import { Dialog } from "@base-ui/react/dialog";
|
|
803
|
+
import { Autocomplete } from "@base-ui/react/autocomplete";
|
|
804
|
+
import { IconLoader2 as IconLoader22, IconSearch } from "@tabler/icons-react";
|
|
805
|
+
|
|
792
806
|
// src/ChipInput.tsx
|
|
793
807
|
import { useMemo, useState as useState2 } from "react";
|
|
794
808
|
import { Button as BaseButton4 } from "@base-ui/react/button";
|
|
@@ -1177,8 +1191,381 @@ function ChipInput({
|
|
|
1177
1191
|
var GAP3 = 4;
|
|
1178
1192
|
var VIEWPORT_PAD3 = 8;
|
|
1179
1193
|
|
|
1194
|
+
// src/EmptyState.tsx
|
|
1195
|
+
import { IconMessage2 } from "@tabler/icons-react";
|
|
1196
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1197
|
+
function EmptyState({ icon, message, scope = "page", className }) {
|
|
1198
|
+
if (scope === "section") {
|
|
1199
|
+
return /* @__PURE__ */ jsx19("p", { className: cn("text-caption text-text-muted", className), children: message });
|
|
1200
|
+
}
|
|
1201
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1202
|
+
/* @__PURE__ */ jsx19("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx19(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1203
|
+
/* @__PURE__ */ jsx19("p", { className: "text-body-2 text-text-secondary text-center", children: message })
|
|
1204
|
+
] });
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
// src/Field.tsx
|
|
1208
|
+
import { cloneElement, isValidElement } from "react";
|
|
1209
|
+
import { Field as BaseField } from "@base-ui/react/field";
|
|
1210
|
+
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1211
|
+
var LINE_STYLES = {
|
|
1212
|
+
helper: "text-caption text-text-muted",
|
|
1213
|
+
warning: "text-caption text-warning-default",
|
|
1214
|
+
error: "text-caption text-error-default"
|
|
1215
|
+
};
|
|
1216
|
+
function Field({ label, required = false, helper, error, children }) {
|
|
1217
|
+
const control = required && isValidElement(children) ? cloneElement(children, {
|
|
1218
|
+
"aria-required": children.props["aria-required"] ?? true
|
|
1219
|
+
}) : children;
|
|
1220
|
+
return /* @__PURE__ */ jsxs13(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
|
|
1221
|
+
/* @__PURE__ */ jsxs13(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1222
|
+
label,
|
|
1223
|
+
required && /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1224
|
+
] }),
|
|
1225
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-1.5", children: [
|
|
1226
|
+
control,
|
|
1227
|
+
error != null ? /* @__PURE__ */ jsx20(BaseField.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx20(BaseField.Description, { className: LINE_STYLES.helper, children: helper }) : null
|
|
1228
|
+
] })
|
|
1229
|
+
] });
|
|
1230
|
+
}
|
|
1231
|
+
function FieldLine({ tone = "helper", children, className }) {
|
|
1232
|
+
return /* @__PURE__ */ jsx20("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// src/Skeleton.tsx
|
|
1236
|
+
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1237
|
+
function SkeletonBar({ className, style }) {
|
|
1238
|
+
return /* @__PURE__ */ jsx21("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1239
|
+
}
|
|
1240
|
+
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1241
|
+
function SkeletonRow({ barWidth = 130 }) {
|
|
1242
|
+
return /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1243
|
+
/* @__PURE__ */ jsx21(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1244
|
+
/* @__PURE__ */ jsx21(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1245
|
+
] });
|
|
1246
|
+
}
|
|
1247
|
+
function SkeletonList({ rows = 8, className }) {
|
|
1248
|
+
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)) });
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// src/CommandPalette.tsx
|
|
1252
|
+
import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1253
|
+
var PaletteContext = createContext2(null);
|
|
1254
|
+
function usePalette(part) {
|
|
1255
|
+
const palette = useContext2(PaletteContext);
|
|
1256
|
+
if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
|
|
1257
|
+
return palette;
|
|
1258
|
+
}
|
|
1259
|
+
var CONTROL = 'input:not([type="hidden"]):not([tabindex="-1"]), textarea, button:not([tabindex="-1"]), [role="combobox"]';
|
|
1260
|
+
function firstControl(popup) {
|
|
1261
|
+
if (!popup) return null;
|
|
1262
|
+
const field = popup.querySelector("[data-command-palette-field]");
|
|
1263
|
+
if (field) return field;
|
|
1264
|
+
return popup.querySelector("[data-command-palette-fields]")?.querySelector(CONTROL) ?? null;
|
|
1265
|
+
}
|
|
1266
|
+
function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", children }) {
|
|
1267
|
+
const popupRef = useRef2(null);
|
|
1268
|
+
useEffect(() => {
|
|
1269
|
+
if (!open) return;
|
|
1270
|
+
const frame = requestAnimationFrame(() => {
|
|
1271
|
+
const popup = popupRef.current;
|
|
1272
|
+
const active = document.activeElement;
|
|
1273
|
+
if (popup && (!active || active === document.body || active === popup)) firstControl(popup)?.focus();
|
|
1274
|
+
});
|
|
1275
|
+
return () => cancelAnimationFrame(frame);
|
|
1276
|
+
});
|
|
1277
|
+
const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
|
|
1278
|
+
return /* @__PURE__ */ jsx22(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs15(Dialog.Portal, { children: [
|
|
1279
|
+
/* @__PURE__ */ jsx22(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1280
|
+
/* @__PURE__ */ jsx22(Dialog.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx22(
|
|
1281
|
+
Dialog.Popup,
|
|
1282
|
+
{
|
|
1283
|
+
ref: popupRef,
|
|
1284
|
+
"aria-label": label,
|
|
1285
|
+
initialFocus: () => firstControl(popupRef.current) ?? true,
|
|
1286
|
+
onFocus: (e) => {
|
|
1287
|
+
if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
|
|
1288
|
+
},
|
|
1289
|
+
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",
|
|
1290
|
+
children: /* @__PURE__ */ jsx22(PaletteContext.Provider, { value: context, children })
|
|
1291
|
+
}
|
|
1292
|
+
) })
|
|
1293
|
+
] }) });
|
|
1294
|
+
}
|
|
1295
|
+
function LevelChip({ chip, onBack }) {
|
|
1296
|
+
return /* @__PURE__ */ jsx22(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
|
|
1297
|
+
}
|
|
1298
|
+
function useBack(chip, popupRef) {
|
|
1299
|
+
return () => {
|
|
1300
|
+
if (!chip) return;
|
|
1301
|
+
chip.onBack();
|
|
1302
|
+
requestAnimationFrame(() => firstControl(popupRef.current)?.focus());
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
function Footer({ keys }) {
|
|
1306
|
+
const { where } = usePalette("The footer");
|
|
1307
|
+
return /* @__PURE__ */ jsxs15("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: [
|
|
1308
|
+
/* @__PURE__ */ jsx22("span", { className: "min-w-0 flex-1 truncate", children: where }),
|
|
1309
|
+
keys.map(([key, word]) => /* @__PURE__ */ jsxs15("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
1310
|
+
/* @__PURE__ */ jsx22(Kbd, { children: key }),
|
|
1311
|
+
" ",
|
|
1312
|
+
word
|
|
1313
|
+
] }, key))
|
|
1314
|
+
] });
|
|
1315
|
+
}
|
|
1316
|
+
var lowerFirst = (s) => s.charAt(0).toLowerCase() + s.slice(1);
|
|
1317
|
+
function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip, pending, notes = [], empty, children }) {
|
|
1318
|
+
const { modKey, popupRef } = usePalette("CommandPaletteSearch");
|
|
1319
|
+
const back = useBack(chip, popupRef);
|
|
1320
|
+
const items = useMemo2(() => groups.filter((g) => g.rows.length > 0).map((g) => ({ value: g.label, items: g.rows })), [groups]);
|
|
1321
|
+
const rows = items.flatMap((g) => g.items);
|
|
1322
|
+
const [litId, setLitId] = useState3();
|
|
1323
|
+
const lit = litId === void 0 ? void 0 : rows.find((r) => r.id === litId);
|
|
1324
|
+
const inputRef = useRef2(null);
|
|
1325
|
+
const reported = useRef2({});
|
|
1326
|
+
const settled = useRef2(null);
|
|
1327
|
+
const moved = useRef2(false);
|
|
1328
|
+
useLayoutEffect2(() => {
|
|
1329
|
+
const before = settled.current;
|
|
1330
|
+
const now = reported.current;
|
|
1331
|
+
const sameLevel = before?.query === query && before?.level === chip?.label;
|
|
1332
|
+
if (!sameLevel) moved.current = false;
|
|
1333
|
+
if (moved.current && before?.id && now.reason === "none" && now.id !== before.id && sameLevel) {
|
|
1334
|
+
const ids = rows.map((r) => r.id);
|
|
1335
|
+
const want = ids.indexOf(before.id);
|
|
1336
|
+
const at = now.id === void 0 ? -1 : ids.indexOf(now.id);
|
|
1337
|
+
const input = inputRef.current;
|
|
1338
|
+
if (input && want !== -1 && at !== -1) {
|
|
1339
|
+
const key = want > at ? "ArrowDown" : "ArrowUp";
|
|
1340
|
+
for (let step = 0; step < Math.abs(want - at); step++) {
|
|
1341
|
+
input.dispatchEvent(new KeyboardEvent("keydown", { key, bubbles: true, cancelable: true }));
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
settled.current = { id: reported.current.id, query, level: chip?.label };
|
|
1346
|
+
});
|
|
1347
|
+
const onKeyDown = (e) => {
|
|
1348
|
+
if (e.key === "Home" || e.key === "End") {
|
|
1349
|
+
e.preventBaseUIHandler();
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
const field = e.currentTarget;
|
|
1353
|
+
const collapsed = field.selectionStart === field.selectionEnd;
|
|
1354
|
+
const atStart = collapsed && field.selectionStart === 0;
|
|
1355
|
+
const atEnd = collapsed && field.selectionEnd === field.value.length;
|
|
1356
|
+
if (e.key === "Backspace" && (e.ctrlKey || e.metaKey)) {
|
|
1357
|
+
if (lit?.onForget) {
|
|
1358
|
+
e.preventDefault();
|
|
1359
|
+
lit.onForget();
|
|
1360
|
+
}
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (e.key === "Backspace" && atStart && chip && !e.shiftKey && !e.altKey) {
|
|
1364
|
+
e.preventDefault();
|
|
1365
|
+
back();
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
if (e.key === "Tab" && !e.shiftKey) {
|
|
1369
|
+
e.preventDefault();
|
|
1370
|
+
lit?.onGoIn?.();
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
if (e.key === "ArrowRight" && atEnd && lit?.onGoIn && !e.shiftKey) {
|
|
1374
|
+
e.preventDefault();
|
|
1375
|
+
lit.onGoIn();
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
const keys = [
|
|
1379
|
+
...rows.length > 1 ? [["\u2191\u2193", "move"]] : [],
|
|
1380
|
+
...lit ? [lit.onGoIn ? ["Tab", "go in"] : ["Enter", "open"]] : [],
|
|
1381
|
+
...lit?.onForget ? [[`${modKey}+Backspace`, "forget"]] : [],
|
|
1382
|
+
// Backspace goes back from the start of the field; it is named while the
|
|
1383
|
+
// field is empty, when that is what it will do.
|
|
1384
|
+
...chip && query === "" ? [["Backspace", "back"]] : [],
|
|
1385
|
+
["Esc", "close"]
|
|
1386
|
+
];
|
|
1387
|
+
return /* @__PURE__ */ jsxs15(
|
|
1388
|
+
Autocomplete.Root,
|
|
1389
|
+
{
|
|
1390
|
+
items,
|
|
1391
|
+
mode: "none",
|
|
1392
|
+
inline: true,
|
|
1393
|
+
open: true,
|
|
1394
|
+
value: query,
|
|
1395
|
+
onValueChange: (value, details) => {
|
|
1396
|
+
if (details.reason === "item-press") return;
|
|
1397
|
+
onQueryChange(value);
|
|
1398
|
+
},
|
|
1399
|
+
itemToStringValue: (row) => row.label,
|
|
1400
|
+
autoHighlight: "always",
|
|
1401
|
+
keepHighlight: true,
|
|
1402
|
+
loopFocus: false,
|
|
1403
|
+
onItemHighlighted: (row, details) => {
|
|
1404
|
+
const id = row?.id;
|
|
1405
|
+
reported.current = { id, reason: details.reason };
|
|
1406
|
+
if (details.reason !== "none") moved.current = true;
|
|
1407
|
+
setLitId(id);
|
|
1408
|
+
},
|
|
1409
|
+
children: [
|
|
1410
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1411
|
+
/* @__PURE__ */ jsx22(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
|
|
1412
|
+
chip && /* @__PURE__ */ jsx22(LevelChip, { chip, onBack: back }),
|
|
1413
|
+
/* @__PURE__ */ jsx22(
|
|
1414
|
+
Autocomplete.Input,
|
|
1415
|
+
{
|
|
1416
|
+
ref: inputRef,
|
|
1417
|
+
"data-command-palette-field": "",
|
|
1418
|
+
placeholder,
|
|
1419
|
+
"aria-label": placeholder,
|
|
1420
|
+
onKeyDown,
|
|
1421
|
+
className: "min-w-0 flex-1 bg-transparent text-input-value text-text-primary outline-none placeholder:text-text-muted"
|
|
1422
|
+
}
|
|
1423
|
+
)
|
|
1424
|
+
] }),
|
|
1425
|
+
/* @__PURE__ */ jsxs15(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
|
|
1426
|
+
children != null && /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
|
|
1427
|
+
/* @__PURE__ */ jsx22(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs15(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
|
|
1428
|
+
/* @__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 }) }),
|
|
1429
|
+
/* @__PURE__ */ jsx22(Autocomplete.Collection, { children: (row) => (
|
|
1430
|
+
/* The menu row, as the list's own option — the way Select
|
|
1431
|
+
puts it on `Select.Item`. One row, two parts. */
|
|
1432
|
+
/* @__PURE__ */ jsx22(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx22(
|
|
1433
|
+
MenuItemBody,
|
|
1434
|
+
{
|
|
1435
|
+
size: "tall",
|
|
1436
|
+
label: row.label,
|
|
1437
|
+
description: row.description,
|
|
1438
|
+
leading: /* @__PURE__ */ jsx22(RowLeading, { row }),
|
|
1439
|
+
submenu: !!row.onGoIn,
|
|
1440
|
+
hint: row.onGoIn ? /* @__PURE__ */ jsx22(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx22(EnterHint, {})
|
|
1441
|
+
}
|
|
1442
|
+
) }, row.id)
|
|
1443
|
+
) })
|
|
1444
|
+
] }, group.value) }),
|
|
1445
|
+
/* @__PURE__ */ jsx22(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
1446
|
+
/* @__PURE__ */ jsx22(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
|
|
1447
|
+
/* @__PURE__ */ jsx22("span", { className: "text-caption text-text-muted", children: pending })
|
|
1448
|
+
] }) }),
|
|
1449
|
+
notes.map((note) => /* @__PURE__ */ jsx22("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx22(FieldLine, { children: note }) }, note)),
|
|
1450
|
+
/* @__PURE__ */ jsx22(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx22(EmptyState, { scope: "section", message: empty }) })
|
|
1451
|
+
] }),
|
|
1452
|
+
/* @__PURE__ */ jsx22(Footer, { keys })
|
|
1453
|
+
]
|
|
1454
|
+
}
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
function RowLeading({ row }) {
|
|
1458
|
+
if (row.icon != null) {
|
|
1459
|
+
return /* @__PURE__ */ jsx22("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
|
|
1460
|
+
}
|
|
1461
|
+
return /* @__PURE__ */ jsx22("span", { className: "flex size-8 items-center justify-center", children: row.leading });
|
|
1462
|
+
}
|
|
1463
|
+
var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1464
|
+
function isTextField(el) {
|
|
1465
|
+
if (el instanceof HTMLTextAreaElement) return true;
|
|
1466
|
+
return el instanceof HTMLInputElement && TEXT_TYPES.has(el.getAttribute("type") ?? "") && el.getAttribute("role") !== "combobox" && el.tabIndex >= 0;
|
|
1467
|
+
}
|
|
1468
|
+
function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, working, error, children }) {
|
|
1469
|
+
const { modKey, popupRef } = usePalette("CommandPaletteForm");
|
|
1470
|
+
const back = useBack(chip, popupRef);
|
|
1471
|
+
const frameRef = useRef2(null);
|
|
1472
|
+
const busy = !!working;
|
|
1473
|
+
const busyRef = useRef2(busy);
|
|
1474
|
+
busyRef.current = busy;
|
|
1475
|
+
const returnTo = useRef2(null);
|
|
1476
|
+
const firstInvalid = () => frameRef.current?.querySelector("[data-invalid]")?.querySelector(CONTROL) ?? null;
|
|
1477
|
+
const submit = () => {
|
|
1478
|
+
if (busyRef.current || submitWaits) return;
|
|
1479
|
+
const active = document.activeElement;
|
|
1480
|
+
returnTo.current = active instanceof HTMLElement && frameRef.current?.contains(active) ? active : null;
|
|
1481
|
+
onSubmit();
|
|
1482
|
+
requestAnimationFrame(() => {
|
|
1483
|
+
if (!busyRef.current) firstInvalid()?.focus();
|
|
1484
|
+
});
|
|
1485
|
+
};
|
|
1486
|
+
useLayoutEffect2(() => {
|
|
1487
|
+
if (busy) {
|
|
1488
|
+
frameRef.current?.focus();
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
if (document.activeElement !== frameRef.current) return;
|
|
1492
|
+
const was = returnTo.current;
|
|
1493
|
+
const target = firstInvalid() ?? (was?.isConnected && !was.disabled ? was : null) ?? firstControl(popupRef.current);
|
|
1494
|
+
target?.focus();
|
|
1495
|
+
}, [busy]);
|
|
1496
|
+
const backWorksFrom = (el) => {
|
|
1497
|
+
const frame = frameRef.current;
|
|
1498
|
+
if (!frame || busy || !el || !frame.contains(el)) return false;
|
|
1499
|
+
if (isTextField(el)) return el.value === "";
|
|
1500
|
+
return ![...frame.querySelectorAll("input, textarea")].some(isTextField);
|
|
1501
|
+
};
|
|
1502
|
+
const [backNamed, setBackNamed] = useState3(false);
|
|
1503
|
+
const measure = () => setBackNamed(backWorksFrom(document.activeElement));
|
|
1504
|
+
useLayoutEffect2(measure);
|
|
1505
|
+
const onKeyDown = (e) => {
|
|
1506
|
+
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
|
1507
|
+
e.preventDefault();
|
|
1508
|
+
submit();
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
if (e.key === "Backspace" && !e.ctrlKey && !e.metaKey && !e.altKey && backWorksFrom(e.target)) {
|
|
1512
|
+
e.preventDefault();
|
|
1513
|
+
back();
|
|
1514
|
+
}
|
|
1515
|
+
};
|
|
1516
|
+
const keys = [
|
|
1517
|
+
...!busy && !submitWaits ? [[`${modKey}+Enter`, lowerFirst(submitLabel)]] : [],
|
|
1518
|
+
...backNamed ? [["Backspace", "back"]] : [],
|
|
1519
|
+
["Esc", "close"]
|
|
1520
|
+
];
|
|
1521
|
+
return /* @__PURE__ */ jsxs15("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
|
|
1522
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1523
|
+
icon != null && /* @__PURE__ */ jsx22("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
|
|
1524
|
+
/* @__PURE__ */ jsx22(LevelChip, { chip, onBack: back })
|
|
1525
|
+
] }),
|
|
1526
|
+
/* @__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 }) }) }),
|
|
1527
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
|
|
1528
|
+
/* @__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 }),
|
|
1529
|
+
/* @__PURE__ */ jsx22(
|
|
1530
|
+
Button,
|
|
1531
|
+
{
|
|
1532
|
+
variant: "primary",
|
|
1533
|
+
onClick: submit,
|
|
1534
|
+
disabled: busy,
|
|
1535
|
+
disabledReason: busy ? void 0 : submitWaits,
|
|
1536
|
+
leadingIcon: busy ? /* @__PURE__ */ jsx22(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
|
|
1537
|
+
children: working ? working.button : submitLabel
|
|
1538
|
+
}
|
|
1539
|
+
)
|
|
1540
|
+
] }),
|
|
1541
|
+
/* @__PURE__ */ jsx22(Footer, { keys })
|
|
1542
|
+
] });
|
|
1543
|
+
}
|
|
1544
|
+
var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
|
|
1545
|
+
function CommandPaletteWorking({ children, bars = 2 }) {
|
|
1546
|
+
return /* @__PURE__ */ jsxs15("div", { role: "status", className: "flex flex-col gap-2", children: [
|
|
1547
|
+
/* @__PURE__ */ jsxs15("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
|
|
1548
|
+
/* @__PURE__ */ jsx22(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
|
|
1549
|
+
children
|
|
1550
|
+
] }),
|
|
1551
|
+
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx22(SkeletonBar, { className: cn("h-3", width) }, width))
|
|
1552
|
+
] });
|
|
1553
|
+
}
|
|
1554
|
+
function CommandPaletteAnswer({ children, note }) {
|
|
1555
|
+
const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
|
|
1556
|
+
return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-2", children: [
|
|
1557
|
+
paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx22("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
|
|
1558
|
+
(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
|
|
1559
|
+
) }, i)),
|
|
1560
|
+
note && /* @__PURE__ */ jsx22(FieldLine, { children: note })
|
|
1561
|
+
] });
|
|
1562
|
+
}
|
|
1563
|
+
function CommandPaletteQuote({ children }) {
|
|
1564
|
+
return /* @__PURE__ */ jsx22("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1180
1567
|
// src/InlineChip.tsx
|
|
1181
|
-
import { Fragment as
|
|
1568
|
+
import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1182
1569
|
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";
|
|
1183
1570
|
var INLINE_CHIP_TONE_CLASSES = {
|
|
1184
1571
|
/** A thing or a place — anything that is not a person. */
|
|
@@ -1200,41 +1587,41 @@ function inlineChipClassName(tone, className) {
|
|
|
1200
1587
|
return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
|
|
1201
1588
|
}
|
|
1202
1589
|
function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
|
|
1203
|
-
const body = /* @__PURE__ */
|
|
1204
|
-
icon && /* @__PURE__ */
|
|
1590
|
+
const body = /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
1591
|
+
icon && /* @__PURE__ */ jsx23("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
|
|
1205
1592
|
children
|
|
1206
1593
|
] });
|
|
1207
1594
|
const classes = inlineChipClassName(tone, className);
|
|
1208
1595
|
if (href === void 0) {
|
|
1209
|
-
return /* @__PURE__ */
|
|
1596
|
+
return /* @__PURE__ */ jsx23("span", { className: classes, ...props, children: body });
|
|
1210
1597
|
}
|
|
1211
|
-
return /* @__PURE__ */
|
|
1598
|
+
return /* @__PURE__ */ jsx23("a", { href, className: classes, ...props, children: body });
|
|
1212
1599
|
}
|
|
1213
1600
|
|
|
1214
1601
|
// src/IdentityMenu.tsx
|
|
1215
|
-
import { useCallback, useRef as
|
|
1602
|
+
import { useCallback, useRef as useRef3 } from "react";
|
|
1216
1603
|
|
|
1217
1604
|
// src/Divider.tsx
|
|
1218
1605
|
import { Separator } from "@base-ui/react/separator";
|
|
1219
|
-
import { jsx as
|
|
1606
|
+
import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1220
1607
|
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
1221
1608
|
if (label && orientation === "horizontal") {
|
|
1222
1609
|
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
1223
|
-
return /* @__PURE__ */
|
|
1610
|
+
return /* @__PURE__ */ jsxs17(
|
|
1224
1611
|
Separator,
|
|
1225
1612
|
{
|
|
1226
1613
|
orientation: "horizontal",
|
|
1227
1614
|
"aria-label": label,
|
|
1228
1615
|
className: cn("flex shrink-0 items-center gap-2 mx-3", className),
|
|
1229
1616
|
children: [
|
|
1230
|
-
/* @__PURE__ */
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
1618
|
+
/* @__PURE__ */ jsx24("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
1619
|
+
/* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
1233
1620
|
]
|
|
1234
1621
|
}
|
|
1235
1622
|
);
|
|
1236
1623
|
}
|
|
1237
|
-
return /* @__PURE__ */
|
|
1624
|
+
return /* @__PURE__ */ jsx24(
|
|
1238
1625
|
Separator,
|
|
1239
1626
|
{
|
|
1240
1627
|
orientation,
|
|
@@ -1244,15 +1631,15 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
|
|
|
1244
1631
|
}
|
|
1245
1632
|
|
|
1246
1633
|
// src/Person.tsx
|
|
1247
|
-
import { jsx as
|
|
1634
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1248
1635
|
function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
1249
1636
|
return (
|
|
1250
1637
|
// gap-2: the face-to-name distance is one rule (8px) wherever a person
|
|
1251
1638
|
// appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
|
|
1252
1639
|
// row agree by construction.
|
|
1253
|
-
/* @__PURE__ */
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1640
|
+
/* @__PURE__ */ jsxs18("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
|
|
1641
|
+
/* @__PURE__ */ jsx25(Avatar, { name, src: picture, size }),
|
|
1642
|
+
/* @__PURE__ */ jsx25("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
|
|
1256
1643
|
] })
|
|
1257
1644
|
);
|
|
1258
1645
|
}
|
|
@@ -1260,10 +1647,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
|
1260
1647
|
// src/PersonTrigger.tsx
|
|
1261
1648
|
import { Button as BaseButton5 } from "@base-ui/react/button";
|
|
1262
1649
|
import { IconChevronDown } from "@tabler/icons-react";
|
|
1263
|
-
import { jsx as
|
|
1650
|
+
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1264
1651
|
function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
|
|
1265
1652
|
if (compact) {
|
|
1266
|
-
return /* @__PURE__ */
|
|
1653
|
+
return /* @__PURE__ */ jsx26(
|
|
1267
1654
|
BaseButton5,
|
|
1268
1655
|
{
|
|
1269
1656
|
type: "button",
|
|
@@ -1272,11 +1659,11 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1272
1659
|
"aria-label": props["aria-label"] ?? name ?? fallback,
|
|
1273
1660
|
className: cn("cursor-pointer rounded-full", className),
|
|
1274
1661
|
...props,
|
|
1275
|
-
children: /* @__PURE__ */
|
|
1662
|
+
children: /* @__PURE__ */ jsx26(Avatar, { name, src: picture, size: size ?? 36 })
|
|
1276
1663
|
}
|
|
1277
1664
|
);
|
|
1278
1665
|
}
|
|
1279
|
-
return /* @__PURE__ */
|
|
1666
|
+
return /* @__PURE__ */ jsxs19(
|
|
1280
1667
|
BaseButton5,
|
|
1281
1668
|
{
|
|
1282
1669
|
type: "button",
|
|
@@ -1294,18 +1681,18 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1294
1681
|
),
|
|
1295
1682
|
...props,
|
|
1296
1683
|
children: [
|
|
1297
|
-
/* @__PURE__ */
|
|
1298
|
-
/* @__PURE__ */
|
|
1684
|
+
/* @__PURE__ */ jsx26(Person, { name, picture, fallback, size: size ?? 22 }),
|
|
1685
|
+
/* @__PURE__ */ jsx26(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
|
|
1299
1686
|
]
|
|
1300
1687
|
}
|
|
1301
1688
|
);
|
|
1302
1689
|
}
|
|
1303
1690
|
|
|
1304
1691
|
// src/IdentityMenu.tsx
|
|
1305
|
-
import { Fragment as
|
|
1692
|
+
import { Fragment as Fragment5, jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1306
1693
|
function IdentityPanel({ className, onClose = () => {
|
|
1307
1694
|
}, ...rest }) {
|
|
1308
|
-
return /* @__PURE__ */
|
|
1695
|
+
return /* @__PURE__ */ jsx27(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx27(IdentityRows, { ...rest, onClose }) });
|
|
1309
1696
|
}
|
|
1310
1697
|
function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
|
|
1311
1698
|
const act = (action) => () => {
|
|
@@ -1313,53 +1700,53 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
|
|
|
1313
1700
|
action();
|
|
1314
1701
|
};
|
|
1315
1702
|
const appRows = typeof children === "function" ? children(onClose) : children;
|
|
1316
|
-
return /* @__PURE__ */
|
|
1317
|
-
/* @__PURE__ */
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
me.email && /* @__PURE__ */
|
|
1703
|
+
return /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
1704
|
+
/* @__PURE__ */ jsxs20(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
|
|
1705
|
+
/* @__PURE__ */ jsx27(MenuRow, { children: /* @__PURE__ */ jsx27(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
|
|
1706
|
+
/* @__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." }),
|
|
1707
|
+
me.email && /* @__PURE__ */ jsxs20(Note, { children: [
|
|
1321
1708
|
me.email,
|
|
1322
1709
|
" \xB7 known to Estiva, never published to the relay"
|
|
1323
1710
|
] })
|
|
1324
1711
|
] }),
|
|
1325
|
-
relayUrl && /* @__PURE__ */
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1329
|
-
/* @__PURE__ */
|
|
1712
|
+
relayUrl && /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
1713
|
+
/* @__PURE__ */ jsx27(Divider, { className: "mx-0 my-2" }),
|
|
1714
|
+
/* @__PURE__ */ jsxs20(MenuSection, { label: "Workspace", children: [
|
|
1715
|
+
/* @__PURE__ */ jsx27(MenuRow, { children: /* @__PURE__ */ jsx27("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
|
|
1716
|
+
/* @__PURE__ */ jsx27(Note, { children: "Everyone on this relay shares this workspace, in every app." })
|
|
1330
1717
|
] })
|
|
1331
1718
|
] }),
|
|
1332
|
-
appRows && /* @__PURE__ */
|
|
1333
|
-
/* @__PURE__ */
|
|
1719
|
+
appRows && /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
1720
|
+
/* @__PURE__ */ jsx27(Divider, { className: "mx-0 my-2" }),
|
|
1334
1721
|
appRows
|
|
1335
1722
|
] }),
|
|
1336
|
-
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */
|
|
1337
|
-
signedIn && idBase && /* @__PURE__ */
|
|
1723
|
+
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx27(Divider, { className: "mx-0 my-2" }) : null,
|
|
1724
|
+
signedIn && idBase && /* @__PURE__ */ jsx27(
|
|
1338
1725
|
MenuItem,
|
|
1339
1726
|
{
|
|
1340
1727
|
label: "Edit your profile in Estiva ID",
|
|
1341
1728
|
onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
|
|
1342
1729
|
}
|
|
1343
1730
|
),
|
|
1344
|
-
onCopyKey && /* @__PURE__ */
|
|
1345
|
-
idBase && onSignOut && /* @__PURE__ */
|
|
1731
|
+
onCopyKey && /* @__PURE__ */ jsx27(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
|
|
1732
|
+
idBase && onSignOut && /* @__PURE__ */ jsx27(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
|
|
1346
1733
|
] });
|
|
1347
1734
|
}
|
|
1348
1735
|
function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
|
|
1349
|
-
const actions =
|
|
1736
|
+
const actions = useRef3(null);
|
|
1350
1737
|
const close = useCallback(() => actions.current?.close(), []);
|
|
1351
1738
|
return (
|
|
1352
1739
|
/* The wrapper carries the caller's `className` and nothing else. It used
|
|
1353
1740
|
to be `relative`, because the panel was positioned against it; the panel
|
|
1354
1741
|
hangs from the trigger and portals now, so a positioning context here
|
|
1355
1742
|
would only be a lie about what this box does. */
|
|
1356
|
-
/* @__PURE__ */
|
|
1743
|
+
/* @__PURE__ */ jsx27("div", { className, children: /* @__PURE__ */ jsx27(
|
|
1357
1744
|
Menu,
|
|
1358
1745
|
{
|
|
1359
1746
|
align: "right",
|
|
1360
1747
|
actionsRef: actions,
|
|
1361
1748
|
className: "w-72",
|
|
1362
|
-
trigger: /* @__PURE__ */
|
|
1749
|
+
trigger: /* @__PURE__ */ jsx27(
|
|
1363
1750
|
PersonTrigger,
|
|
1364
1751
|
{
|
|
1365
1752
|
name: me.name,
|
|
@@ -1370,7 +1757,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
1370
1757
|
"aria-label": compact ? "Account menu" : void 0
|
|
1371
1758
|
}
|
|
1372
1759
|
),
|
|
1373
|
-
children: /* @__PURE__ */
|
|
1760
|
+
children: /* @__PURE__ */ jsx27(
|
|
1374
1761
|
IdentityRows,
|
|
1375
1762
|
{
|
|
1376
1763
|
me,
|
|
@@ -1388,46 +1775,18 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
1388
1775
|
);
|
|
1389
1776
|
}
|
|
1390
1777
|
function Note({ children }) {
|
|
1391
|
-
return /* @__PURE__ */
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
// src/Field.tsx
|
|
1395
|
-
import { cloneElement, isValidElement } from "react";
|
|
1396
|
-
import { Field as BaseField } from "@base-ui/react/field";
|
|
1397
|
-
import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1398
|
-
var LINE_STYLES = {
|
|
1399
|
-
helper: "text-caption text-text-muted",
|
|
1400
|
-
warning: "text-caption text-warning-default",
|
|
1401
|
-
error: "text-caption text-error-default"
|
|
1402
|
-
};
|
|
1403
|
-
function Field({ label, required = false, helper, error, children }) {
|
|
1404
|
-
const control = required && isValidElement(children) ? cloneElement(children, {
|
|
1405
|
-
"aria-required": children.props["aria-required"] ?? true
|
|
1406
|
-
}) : children;
|
|
1407
|
-
return /* @__PURE__ */ jsxs17(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
|
|
1408
|
-
/* @__PURE__ */ jsxs17(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1409
|
-
label,
|
|
1410
|
-
required && /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1411
|
-
] }),
|
|
1412
|
-
/* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-1.5", children: [
|
|
1413
|
-
control,
|
|
1414
|
-
error != null ? /* @__PURE__ */ jsx24(BaseField.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx24(BaseField.Description, { className: LINE_STYLES.helper, children: helper }) : null
|
|
1415
|
-
] })
|
|
1416
|
-
] });
|
|
1417
|
-
}
|
|
1418
|
-
function FieldLine({ tone = "helper", children, className }) {
|
|
1419
|
-
return /* @__PURE__ */ jsx24("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
|
|
1778
|
+
return /* @__PURE__ */ jsx27("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
|
|
1420
1779
|
}
|
|
1421
1780
|
|
|
1422
1781
|
// src/Select.tsx
|
|
1423
1782
|
import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
|
|
1424
1783
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
1425
|
-
import { jsx as
|
|
1784
|
+
import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1426
1785
|
var GAP4 = 4;
|
|
1427
1786
|
var VIEWPORT_PAD4 = 8;
|
|
1428
1787
|
function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, className, ...aria }) {
|
|
1429
1788
|
const selected = options.find((o) => o.value === value);
|
|
1430
|
-
return /* @__PURE__ */
|
|
1789
|
+
return /* @__PURE__ */ jsxs21(
|
|
1431
1790
|
BaseSelect.Root,
|
|
1432
1791
|
{
|
|
1433
1792
|
value,
|
|
@@ -1435,7 +1794,7 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1435
1794
|
disabled,
|
|
1436
1795
|
modal: false,
|
|
1437
1796
|
children: [
|
|
1438
|
-
/* @__PURE__ */
|
|
1797
|
+
/* @__PURE__ */ jsxs21(
|
|
1439
1798
|
BaseSelect.Trigger,
|
|
1440
1799
|
{
|
|
1441
1800
|
"aria-label": ariaLabel,
|
|
@@ -1462,20 +1821,20 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1462
1821
|
className
|
|
1463
1822
|
),
|
|
1464
1823
|
children: [
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
selected?.leading && /* @__PURE__ */
|
|
1467
|
-
/* @__PURE__ */
|
|
1824
|
+
/* @__PURE__ */ jsxs21("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
|
|
1825
|
+
selected?.leading && /* @__PURE__ */ jsx28("span", { className: "flex shrink-0 items-center", children: selected.leading }),
|
|
1826
|
+
/* @__PURE__ */ jsx28(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
|
|
1468
1827
|
] }),
|
|
1469
|
-
/* @__PURE__ */
|
|
1828
|
+
/* @__PURE__ */ jsx28(
|
|
1470
1829
|
BaseSelect.Icon,
|
|
1471
1830
|
{
|
|
1472
|
-
render: /* @__PURE__ */
|
|
1831
|
+
render: /* @__PURE__ */ jsx28(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
1473
1832
|
}
|
|
1474
1833
|
)
|
|
1475
1834
|
]
|
|
1476
1835
|
}
|
|
1477
1836
|
),
|
|
1478
|
-
/* @__PURE__ */
|
|
1837
|
+
/* @__PURE__ */ jsx28(BaseSelect.Portal, { children: /* @__PURE__ */ jsx28(
|
|
1479
1838
|
BaseSelect.Positioner,
|
|
1480
1839
|
{
|
|
1481
1840
|
side: "bottom",
|
|
@@ -1484,25 +1843,25 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1484
1843
|
collisionPadding: VIEWPORT_PAD4,
|
|
1485
1844
|
alignItemWithTrigger: false,
|
|
1486
1845
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1487
|
-
children: /* @__PURE__ */
|
|
1846
|
+
children: /* @__PURE__ */ jsx28(
|
|
1488
1847
|
BaseSelect.Popup,
|
|
1489
1848
|
{
|
|
1490
|
-
render: /* @__PURE__ */
|
|
1849
|
+
render: /* @__PURE__ */ jsx28(MenuPanel, {}),
|
|
1491
1850
|
className: "min-w-[var(--anchor-width)] p-0",
|
|
1492
|
-
children: /* @__PURE__ */
|
|
1851
|
+
children: /* @__PURE__ */ jsx28(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col p-2", children: options.map((option) => /* @__PURE__ */ jsxs21(
|
|
1493
1852
|
BaseSelect.Item,
|
|
1494
1853
|
{
|
|
1495
1854
|
value: option.value,
|
|
1496
1855
|
className: cn(menuItemClassName({ size: "default" }), "justify-between data-[selected]:font-medium"),
|
|
1497
1856
|
children: [
|
|
1498
|
-
/* @__PURE__ */
|
|
1499
|
-
option.leading && /* @__PURE__ */
|
|
1500
|
-
/* @__PURE__ */
|
|
1857
|
+
/* @__PURE__ */ jsxs21("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1858
|
+
option.leading && /* @__PURE__ */ jsx28("span", { className: "flex shrink-0 items-center", children: option.leading }),
|
|
1859
|
+
/* @__PURE__ */ jsx28(BaseSelect.ItemText, { className: "truncate text-body-2 text-text-primary", children: option.label })
|
|
1501
1860
|
] }),
|
|
1502
|
-
/* @__PURE__ */
|
|
1861
|
+
/* @__PURE__ */ jsx28(
|
|
1503
1862
|
BaseSelect.ItemIndicator,
|
|
1504
1863
|
{
|
|
1505
|
-
render: /* @__PURE__ */
|
|
1864
|
+
render: /* @__PURE__ */ jsx28(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
1506
1865
|
}
|
|
1507
1866
|
)
|
|
1508
1867
|
]
|
|
@@ -1521,9 +1880,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1521
1880
|
// src/TextInput.tsx
|
|
1522
1881
|
import { forwardRef } from "react";
|
|
1523
1882
|
import { Input } from "@base-ui/react/input";
|
|
1524
|
-
import { jsx as
|
|
1883
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1525
1884
|
var TextInput = forwardRef(function TextInput2({ className, type = "text", size = "default", ...props }, ref) {
|
|
1526
|
-
return /* @__PURE__ */
|
|
1885
|
+
return /* @__PURE__ */ jsx29(
|
|
1527
1886
|
Input,
|
|
1528
1887
|
{
|
|
1529
1888
|
ref,
|
|
@@ -1547,13 +1906,13 @@ var TextInput = forwardRef(function TextInput2({ className, type = "text", size
|
|
|
1547
1906
|
// src/Textarea.tsx
|
|
1548
1907
|
import { forwardRef as forwardRef2 } from "react";
|
|
1549
1908
|
import { Field as BaseField2 } from "@base-ui/react/field";
|
|
1550
|
-
import { jsx as
|
|
1909
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1551
1910
|
var Textarea = forwardRef2(function Textarea2({ className, ...props }, ref) {
|
|
1552
|
-
return /* @__PURE__ */
|
|
1911
|
+
return /* @__PURE__ */ jsx30(
|
|
1553
1912
|
BaseField2.Control,
|
|
1554
1913
|
{
|
|
1555
1914
|
ref,
|
|
1556
|
-
render: /* @__PURE__ */
|
|
1915
|
+
render: /* @__PURE__ */ jsx30("textarea", {}),
|
|
1557
1916
|
className: cn(
|
|
1558
1917
|
"bg-bg-inset border border-border-default focus:border-border-focus rounded-lg px-3 py-2",
|
|
1559
1918
|
"text-input-value text-text-primary placeholder:text-text-muted",
|
|
@@ -1568,27 +1927,27 @@ var Textarea = forwardRef2(function Textarea2({ className, ...props }, ref) {
|
|
|
1568
1927
|
});
|
|
1569
1928
|
|
|
1570
1929
|
// src/ConfirmDialog.tsx
|
|
1571
|
-
import { useState as
|
|
1930
|
+
import { useState as useState4 } from "react";
|
|
1572
1931
|
|
|
1573
1932
|
// src/DialogShell.tsx
|
|
1574
|
-
import { useRef as
|
|
1575
|
-
import { Dialog } from "@base-ui/react/dialog";
|
|
1933
|
+
import { useRef as useRef4 } from "react";
|
|
1934
|
+
import { Dialog as Dialog2 } from "@base-ui/react/dialog";
|
|
1576
1935
|
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
1577
1936
|
import { IconX as IconX4 } from "@tabler/icons-react";
|
|
1578
|
-
import { jsx as
|
|
1937
|
+
import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1579
1938
|
function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, bodyMaxHeight, width = 502, alert = false }) {
|
|
1580
|
-
const Parts = alert ? AlertDialog :
|
|
1581
|
-
const popupRef =
|
|
1582
|
-
return /* @__PURE__ */
|
|
1939
|
+
const Parts = alert ? AlertDialog : Dialog2;
|
|
1940
|
+
const popupRef = useRef4(null);
|
|
1941
|
+
return /* @__PURE__ */ jsx31(
|
|
1583
1942
|
Parts.Root,
|
|
1584
1943
|
{
|
|
1585
1944
|
open: true,
|
|
1586
1945
|
onOpenChange: (open) => {
|
|
1587
1946
|
if (!open) onClose();
|
|
1588
1947
|
},
|
|
1589
|
-
children: /* @__PURE__ */
|
|
1590
|
-
/* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1948
|
+
children: /* @__PURE__ */ jsxs22(Parts.Portal, { children: [
|
|
1949
|
+
/* @__PURE__ */ jsx31(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1950
|
+
/* @__PURE__ */ jsx31("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs22(
|
|
1592
1951
|
Parts.Popup,
|
|
1593
1952
|
{
|
|
1594
1953
|
ref: popupRef,
|
|
@@ -1597,16 +1956,16 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
1597
1956
|
className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
|
|
1598
1957
|
style: { width },
|
|
1599
1958
|
children: [
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
headerContent ?? /* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsxs22("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
|
|
1960
|
+
headerContent ?? /* @__PURE__ */ jsx31(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx31("span", {}), children: title }),
|
|
1961
|
+
/* @__PURE__ */ jsx31(
|
|
1603
1962
|
Parts.Close,
|
|
1604
1963
|
{
|
|
1605
|
-
render: /* @__PURE__ */
|
|
1964
|
+
render: /* @__PURE__ */ jsx31(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx31(IconX4, { size: 16, stroke: 1.5 }) })
|
|
1606
1965
|
}
|
|
1607
1966
|
)
|
|
1608
1967
|
] }),
|
|
1609
|
-
bodyMaxHeight ? /* @__PURE__ */
|
|
1968
|
+
bodyMaxHeight ? /* @__PURE__ */ jsx31(
|
|
1610
1969
|
ScrollArea,
|
|
1611
1970
|
{
|
|
1612
1971
|
className: cn(footer != null && "border-b border-border-subtle"),
|
|
@@ -1614,8 +1973,8 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
1614
1973
|
contentClassName: cn("pl-5 pr-4 py-4", bodyClassName),
|
|
1615
1974
|
children
|
|
1616
1975
|
}
|
|
1617
|
-
) : /* @__PURE__ */
|
|
1618
|
-
footer != null && /* @__PURE__ */
|
|
1976
|
+
) : /* @__PURE__ */ jsx31("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
|
|
1977
|
+
footer != null && /* @__PURE__ */ jsx31("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
|
|
1619
1978
|
]
|
|
1620
1979
|
}
|
|
1621
1980
|
) })
|
|
@@ -1625,9 +1984,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
1625
1984
|
}
|
|
1626
1985
|
|
|
1627
1986
|
// src/ConfirmDialog.tsx
|
|
1628
|
-
import { Fragment as
|
|
1987
|
+
import { Fragment as Fragment6, jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1629
1988
|
function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
|
|
1630
|
-
const [busy, setBusy] =
|
|
1989
|
+
const [busy, setBusy] = useState4(false);
|
|
1631
1990
|
const confirm = async () => {
|
|
1632
1991
|
setBusy(true);
|
|
1633
1992
|
try {
|
|
@@ -1637,16 +1996,16 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
1637
1996
|
setBusy(false);
|
|
1638
1997
|
}
|
|
1639
1998
|
};
|
|
1640
|
-
return /* @__PURE__ */
|
|
1999
|
+
return /* @__PURE__ */ jsx32(
|
|
1641
2000
|
DialogShell,
|
|
1642
2001
|
{
|
|
1643
2002
|
alert: true,
|
|
1644
2003
|
title,
|
|
1645
2004
|
onClose,
|
|
1646
2005
|
bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
|
|
1647
|
-
footer: /* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
2006
|
+
footer: /* @__PURE__ */ jsxs23(Fragment6, { children: [
|
|
2007
|
+
/* @__PURE__ */ jsx32(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
2008
|
+
/* @__PURE__ */ jsx32(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
|
|
1650
2009
|
] }),
|
|
1651
2010
|
children
|
|
1652
2011
|
}
|
|
@@ -1654,16 +2013,16 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
1654
2013
|
}
|
|
1655
2014
|
|
|
1656
2015
|
// src/EditableText.tsx
|
|
1657
|
-
import { useEffect, useRef as
|
|
2016
|
+
import { useEffect as useEffect2, useRef as useRef5, useState as useState5 } from "react";
|
|
1658
2017
|
import { Field as BaseField3 } from "@base-ui/react/field";
|
|
1659
2018
|
import { Input as Input2 } from "@base-ui/react/input";
|
|
1660
|
-
import { jsx as
|
|
2019
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
1661
2020
|
function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
|
|
1662
|
-
const [editing, setEditing] =
|
|
1663
|
-
const [draft, setDraft] =
|
|
1664
|
-
const [busy, setBusy] =
|
|
1665
|
-
const fieldRef =
|
|
1666
|
-
|
|
2021
|
+
const [editing, setEditing] = useState5(false);
|
|
2022
|
+
const [draft, setDraft] = useState5(value);
|
|
2023
|
+
const [busy, setBusy] = useState5(false);
|
|
2024
|
+
const fieldRef = useRef5(null);
|
|
2025
|
+
useEffect2(() => {
|
|
1667
2026
|
if (editing) {
|
|
1668
2027
|
fieldRef.current?.focus();
|
|
1669
2028
|
fieldRef.current?.select();
|
|
@@ -1715,7 +2074,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1715
2074
|
written and never read. Read-only, this is a line of text: whatever
|
|
1716
2075
|
names the region around it (a `Field`, a `Property`) names this too.
|
|
1717
2076
|
*/
|
|
1718
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ jsx33(
|
|
1719
2078
|
"div",
|
|
1720
2079
|
{
|
|
1721
2080
|
className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
|
|
@@ -1725,11 +2084,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1725
2084
|
);
|
|
1726
2085
|
}
|
|
1727
2086
|
if (editing) {
|
|
1728
|
-
return multiline ? /* @__PURE__ */
|
|
2087
|
+
return multiline ? /* @__PURE__ */ jsx33(
|
|
1729
2088
|
BaseField3.Control,
|
|
1730
2089
|
{
|
|
1731
2090
|
ref: fieldRef,
|
|
1732
|
-
render: /* @__PURE__ */
|
|
2091
|
+
render: /* @__PURE__ */ jsx33("textarea", { rows: 4 }),
|
|
1733
2092
|
"aria-label": label,
|
|
1734
2093
|
value: draft,
|
|
1735
2094
|
disabled: busy,
|
|
@@ -1738,7 +2097,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1738
2097
|
onBlur: () => void commit(),
|
|
1739
2098
|
className: fieldClass
|
|
1740
2099
|
}
|
|
1741
|
-
) : /* @__PURE__ */
|
|
2100
|
+
) : /* @__PURE__ */ jsx33(
|
|
1742
2101
|
Input2,
|
|
1743
2102
|
{
|
|
1744
2103
|
ref: fieldRef,
|
|
@@ -1752,7 +2111,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1752
2111
|
}
|
|
1753
2112
|
);
|
|
1754
2113
|
}
|
|
1755
|
-
return /* @__PURE__ */
|
|
2114
|
+
return /* @__PURE__ */ jsx33(
|
|
1756
2115
|
"button",
|
|
1757
2116
|
{
|
|
1758
2117
|
type: "button",
|
|
@@ -1769,22 +2128,9 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1769
2128
|
);
|
|
1770
2129
|
}
|
|
1771
2130
|
|
|
1772
|
-
// src/EmptyState.tsx
|
|
1773
|
-
import { IconMessage2 } from "@tabler/icons-react";
|
|
1774
|
-
import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1775
|
-
function EmptyState({ icon, message, scope = "page", className }) {
|
|
1776
|
-
if (scope === "section") {
|
|
1777
|
-
return /* @__PURE__ */ jsx31("p", { className: cn("text-caption text-text-muted", className), children: message });
|
|
1778
|
-
}
|
|
1779
|
-
return /* @__PURE__ */ jsxs21("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1780
|
-
/* @__PURE__ */ jsx31("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx31(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1781
|
-
/* @__PURE__ */ jsx31("p", { className: "text-body-2 text-text-secondary text-center", children: message })
|
|
1782
|
-
] });
|
|
1783
|
-
}
|
|
1784
|
-
|
|
1785
2131
|
// src/ProgressBar.tsx
|
|
1786
2132
|
import { Progress } from "@base-ui/react/progress";
|
|
1787
|
-
import { jsx as
|
|
2133
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
1788
2134
|
var TRACK_CLASSES = {
|
|
1789
2135
|
default: "h-1.5 w-full overflow-hidden rounded-full bg-bg-inset",
|
|
1790
2136
|
// 4px, Katerina's ruling of 14 September; Peek's own bar is 3px until it takes this one.
|
|
@@ -1797,33 +2143,17 @@ var INDICATOR_CLASSES = {
|
|
|
1797
2143
|
function ProgressBar({ value, max, label, variant = "default", className }) {
|
|
1798
2144
|
return (
|
|
1799
2145
|
// `max={0}` needs no guard: Base UI reads the 0/0 share as an empty bar.
|
|
1800
|
-
/* @__PURE__ */
|
|
2146
|
+
/* @__PURE__ */ jsx34(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx34(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx34(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
|
|
1801
2147
|
);
|
|
1802
2148
|
}
|
|
1803
2149
|
|
|
1804
|
-
// src/Skeleton.tsx
|
|
1805
|
-
import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1806
|
-
function SkeletonBar({ className, style }) {
|
|
1807
|
-
return /* @__PURE__ */ jsx33("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1808
|
-
}
|
|
1809
|
-
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1810
|
-
function SkeletonRow({ barWidth = 130 }) {
|
|
1811
|
-
return /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1812
|
-
/* @__PURE__ */ jsx33(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1813
|
-
/* @__PURE__ */ jsx33(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1814
|
-
] });
|
|
1815
|
-
}
|
|
1816
|
-
function SkeletonList({ rows = 8, className }) {
|
|
1817
|
-
return /* @__PURE__ */ jsx33("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx33(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
2150
|
// src/Breadcrumb.tsx
|
|
1821
|
-
import { Fragment as
|
|
1822
|
-
import { jsx as
|
|
2151
|
+
import { Fragment as Fragment7, useCallback as useCallback2, useLayoutEffect as useLayoutEffect3, useRef as useRef6, useState as useState6 } from "react";
|
|
2152
|
+
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1823
2153
|
function Breadcrumb({ items, className }) {
|
|
1824
|
-
const navRef =
|
|
1825
|
-
const labelRefs =
|
|
1826
|
-
const [truncated, setTruncated] =
|
|
2154
|
+
const navRef = useRef6(null);
|
|
2155
|
+
const labelRefs = useRef6([]);
|
|
2156
|
+
const [truncated, setTruncated] = useState6(/* @__PURE__ */ new Set());
|
|
1827
2157
|
const measure = useCallback2(() => {
|
|
1828
2158
|
const next = /* @__PURE__ */ new Set();
|
|
1829
2159
|
labelRefs.current.forEach((el, index) => {
|
|
@@ -1831,7 +2161,7 @@ function Breadcrumb({ items, className }) {
|
|
|
1831
2161
|
});
|
|
1832
2162
|
setTruncated((prev) => prev.size === next.size && [...next].every((i) => prev.has(i)) ? prev : next);
|
|
1833
2163
|
}, []);
|
|
1834
|
-
|
|
2164
|
+
useLayoutEffect3(() => {
|
|
1835
2165
|
measure();
|
|
1836
2166
|
const nav = navRef.current;
|
|
1837
2167
|
if (!nav || typeof ResizeObserver === "undefined") return;
|
|
@@ -1839,7 +2169,7 @@ function Breadcrumb({ items, className }) {
|
|
|
1839
2169
|
observer.observe(nav);
|
|
1840
2170
|
return () => observer.disconnect();
|
|
1841
2171
|
}, [measure, items]);
|
|
1842
|
-
return /* @__PURE__ */
|
|
2172
|
+
return /* @__PURE__ */ jsx35("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-body-2", className), children: items.map((item, index) => {
|
|
1843
2173
|
const last = index === items.length - 1;
|
|
1844
2174
|
const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
|
|
1845
2175
|
const text = cn(
|
|
@@ -1853,24 +2183,29 @@ function Breadcrumb({ items, className }) {
|
|
|
1853
2183
|
const setLabelRef = (el) => {
|
|
1854
2184
|
labelRefs.current[index] = el;
|
|
1855
2185
|
};
|
|
1856
|
-
const crumb = item.href ?
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2186
|
+
const crumb = item.href ? (
|
|
2187
|
+
// `plain` adds no look of its own: a crumb keeps the trail's size and
|
|
2188
|
+
// tone, and brightens on hover. The package's own Link, so a trail
|
|
2189
|
+
// follows whatever a link learns to do (UIG-5).
|
|
2190
|
+
/* @__PURE__ */ jsx35(Link, { ref: setLabelRef, variant: "plain", href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label })
|
|
2191
|
+
) : /* @__PURE__ */ jsx35("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
2192
|
+
return /* @__PURE__ */ jsxs24(Fragment7, { children: [
|
|
2193
|
+
index > 0 && /* @__PURE__ */ jsx35("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
2194
|
+
item.icon && /* @__PURE__ */ jsx35("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
|
|
1860
2195
|
truncated.has(index) ? (
|
|
1861
2196
|
// `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
|
|
1862
2197
|
// must keep truncating inside it, or wrapping it would widen the
|
|
1863
2198
|
// trail and the tooltip would never be needed again.
|
|
1864
|
-
/* @__PURE__ */
|
|
2199
|
+
/* @__PURE__ */ jsx35(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
|
|
1865
2200
|
) : crumb
|
|
1866
2201
|
] }, `${item.label}-${index}`);
|
|
1867
2202
|
}) });
|
|
1868
2203
|
}
|
|
1869
2204
|
|
|
1870
2205
|
// src/NavItem.tsx
|
|
1871
|
-
import { jsx as
|
|
2206
|
+
import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1872
2207
|
function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
|
|
1873
|
-
return /* @__PURE__ */
|
|
2208
|
+
return /* @__PURE__ */ jsxs25(
|
|
1874
2209
|
"a",
|
|
1875
2210
|
{
|
|
1876
2211
|
href,
|
|
@@ -1885,27 +2220,27 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
1885
2220
|
),
|
|
1886
2221
|
...props,
|
|
1887
2222
|
children: [
|
|
1888
|
-
icon && /* @__PURE__ */
|
|
1889
|
-
/* @__PURE__ */
|
|
1890
|
-
count ? /* @__PURE__ */
|
|
2223
|
+
icon && /* @__PURE__ */ jsx36("span", { className: "flex shrink-0 items-center", children: icon }),
|
|
2224
|
+
/* @__PURE__ */ jsx36("span", { className: "flex-1 truncate", children: label }),
|
|
2225
|
+
count ? /* @__PURE__ */ jsx36(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx36("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
1891
2226
|
]
|
|
1892
2227
|
}
|
|
1893
2228
|
);
|
|
1894
2229
|
}
|
|
1895
2230
|
|
|
1896
2231
|
// src/Popover.tsx
|
|
1897
|
-
import { useMemo as
|
|
2232
|
+
import { useMemo as useMemo3 } from "react";
|
|
1898
2233
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
1899
|
-
import { jsx as
|
|
2234
|
+
import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1900
2235
|
var GAP5 = 4;
|
|
1901
2236
|
var VIEWPORT_PAD5 = 8;
|
|
1902
2237
|
function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
|
|
1903
|
-
const anchorTarget =
|
|
2238
|
+
const anchorTarget = useMemo3(() => {
|
|
1904
2239
|
if (!anchor) return void 0;
|
|
1905
2240
|
if (anchor instanceof Element) return anchor;
|
|
1906
2241
|
return { getBoundingClientRect: () => anchor };
|
|
1907
2242
|
}, [anchor]);
|
|
1908
|
-
return /* @__PURE__ */
|
|
2243
|
+
return /* @__PURE__ */ jsxs26(
|
|
1909
2244
|
BasePopover.Root,
|
|
1910
2245
|
{
|
|
1911
2246
|
open,
|
|
@@ -1913,8 +2248,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1913
2248
|
actionsRef,
|
|
1914
2249
|
modal: false,
|
|
1915
2250
|
children: [
|
|
1916
|
-
trigger && /* @__PURE__ */
|
|
1917
|
-
/* @__PURE__ */
|
|
2251
|
+
trigger && /* @__PURE__ */ jsx37(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
|
|
2252
|
+
/* @__PURE__ */ jsx37(BasePopover.Portal, { children: /* @__PURE__ */ jsx37(
|
|
1918
2253
|
BasePopover.Positioner,
|
|
1919
2254
|
{
|
|
1920
2255
|
anchor: anchorTarget,
|
|
@@ -1923,15 +2258,15 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1923
2258
|
sideOffset: GAP5,
|
|
1924
2259
|
collisionPadding: VIEWPORT_PAD5,
|
|
1925
2260
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1926
|
-
children: /* @__PURE__ */
|
|
2261
|
+
children: /* @__PURE__ */ jsx37(
|
|
1927
2262
|
BasePopover.Popup,
|
|
1928
2263
|
{
|
|
1929
2264
|
"aria-label": ariaLabel,
|
|
1930
2265
|
initialFocus: trigger ? void 0 : false,
|
|
1931
2266
|
finalFocus,
|
|
1932
2267
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
1933
|
-
render: /* @__PURE__ */
|
|
1934
|
-
children: /* @__PURE__ */
|
|
2268
|
+
render: /* @__PURE__ */ jsx37(MenuPanel, {}),
|
|
2269
|
+
children: /* @__PURE__ */ jsx37(
|
|
1935
2270
|
ScrollArea,
|
|
1936
2271
|
{
|
|
1937
2272
|
viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
|
|
@@ -1950,9 +2285,9 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1950
2285
|
|
|
1951
2286
|
// src/Toolbar.tsx
|
|
1952
2287
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
1953
|
-
import { jsx as
|
|
2288
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
1954
2289
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
1955
|
-
const strip = /* @__PURE__ */
|
|
2290
|
+
const strip = /* @__PURE__ */ jsx38(
|
|
1956
2291
|
BaseToolbar.Root,
|
|
1957
2292
|
{
|
|
1958
2293
|
"aria-label": ariaLabel,
|
|
@@ -1963,24 +2298,24 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
1963
2298
|
}
|
|
1964
2299
|
);
|
|
1965
2300
|
if (!surface) return strip;
|
|
1966
|
-
return /* @__PURE__ */
|
|
2301
|
+
return /* @__PURE__ */ jsx38(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
1967
2302
|
}
|
|
1968
2303
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
1969
|
-
return /* @__PURE__ */
|
|
2304
|
+
return /* @__PURE__ */ jsx38(
|
|
1970
2305
|
BaseToolbar.Button,
|
|
1971
2306
|
{
|
|
1972
2307
|
ref,
|
|
1973
2308
|
disabled: disabled || !!disabledReason,
|
|
1974
2309
|
focusableWhenDisabled: true,
|
|
1975
|
-
render: /* @__PURE__ */
|
|
2310
|
+
render: /* @__PURE__ */ jsx38(IconButton, { disabled, disabledReason, ...props })
|
|
1976
2311
|
}
|
|
1977
2312
|
);
|
|
1978
2313
|
}
|
|
1979
2314
|
function ToolbarInput({ size, ...props }) {
|
|
1980
|
-
return /* @__PURE__ */
|
|
2315
|
+
return /* @__PURE__ */ jsx38(BaseToolbar.Input, { render: /* @__PURE__ */ jsx38(TextInput, { size }), ...props });
|
|
1981
2316
|
}
|
|
1982
2317
|
function ToolbarSeparator({ className }) {
|
|
1983
|
-
return /* @__PURE__ */
|
|
2318
|
+
return /* @__PURE__ */ jsx38(
|
|
1984
2319
|
BaseToolbar.Separator,
|
|
1985
2320
|
{
|
|
1986
2321
|
orientation: "vertical",
|
|
@@ -1990,9 +2325,9 @@ function ToolbarSeparator({ className }) {
|
|
|
1990
2325
|
}
|
|
1991
2326
|
|
|
1992
2327
|
// src/ReactionPicker.tsx
|
|
1993
|
-
import { jsx as
|
|
2328
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
1994
2329
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
1995
|
-
return /* @__PURE__ */
|
|
2330
|
+
return /* @__PURE__ */ jsx39(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
1996
2331
|
/*
|
|
1997
2332
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
1998
2333
|
would become the toolbar's item and the button inside it would never
|
|
@@ -2002,14 +2337,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2002
2337
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
2003
2338
|
and both say the meaning rather than the glyph.
|
|
2004
2339
|
*/
|
|
2005
|
-
/* @__PURE__ */
|
|
2340
|
+
/* @__PURE__ */ jsx39(
|
|
2006
2341
|
ToolbarButton,
|
|
2007
2342
|
{
|
|
2008
2343
|
"aria-label": option.label,
|
|
2009
2344
|
tooltip: option.label,
|
|
2010
2345
|
onClick: () => onSelect(option.emoji),
|
|
2011
2346
|
className: "size-7 text-h3 leading-none",
|
|
2012
|
-
children: /* @__PURE__ */
|
|
2347
|
+
children: /* @__PURE__ */ jsx39("span", { "aria-hidden": "true", children: option.emoji })
|
|
2013
2348
|
},
|
|
2014
2349
|
option.emoji
|
|
2015
2350
|
)
|
|
@@ -2018,23 +2353,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2018
2353
|
|
|
2019
2354
|
// src/PreviewCard.tsx
|
|
2020
2355
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
2021
|
-
import { jsx as
|
|
2356
|
+
import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2022
2357
|
var GAP6 = 12;
|
|
2023
2358
|
var VIEWPORT_PAD6 = 8;
|
|
2024
2359
|
var OPEN_DELAY2 = 350;
|
|
2025
2360
|
var CLOSE_DELAY = 200;
|
|
2026
2361
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, wrapperClassName }) {
|
|
2027
|
-
return /* @__PURE__ */
|
|
2028
|
-
/* @__PURE__ */
|
|
2362
|
+
return /* @__PURE__ */ jsxs27(BasePreviewCard.Root, { children: [
|
|
2363
|
+
/* @__PURE__ */ jsx40(
|
|
2029
2364
|
BasePreviewCard.Trigger,
|
|
2030
2365
|
{
|
|
2031
2366
|
delay,
|
|
2032
2367
|
closeDelay,
|
|
2033
|
-
render: /* @__PURE__ */
|
|
2368
|
+
render: /* @__PURE__ */ jsx40("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
2034
2369
|
children
|
|
2035
2370
|
}
|
|
2036
2371
|
),
|
|
2037
|
-
/* @__PURE__ */
|
|
2372
|
+
/* @__PURE__ */ jsx40(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx40(
|
|
2038
2373
|
BasePreviewCard.Positioner,
|
|
2039
2374
|
{
|
|
2040
2375
|
side,
|
|
@@ -2042,12 +2377,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2042
2377
|
sideOffset: GAP6,
|
|
2043
2378
|
collisionPadding: VIEWPORT_PAD6,
|
|
2044
2379
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2045
|
-
children: /* @__PURE__ */
|
|
2380
|
+
children: /* @__PURE__ */ jsx40(
|
|
2046
2381
|
BasePreviewCard.Popup,
|
|
2047
2382
|
{
|
|
2048
2383
|
className: cn("w-[360px] p-3 outline-none", className),
|
|
2049
|
-
render: /* @__PURE__ */
|
|
2050
|
-
children: /* @__PURE__ */
|
|
2384
|
+
render: /* @__PURE__ */ jsx40(MenuPanel, {}),
|
|
2385
|
+
children: /* @__PURE__ */ jsx40(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3 [&>*]:shrink-0", children: content })
|
|
2051
2386
|
}
|
|
2052
2387
|
)
|
|
2053
2388
|
}
|
|
@@ -2056,15 +2391,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2056
2391
|
}
|
|
2057
2392
|
|
|
2058
2393
|
// src/Rail.tsx
|
|
2059
|
-
import { jsx as
|
|
2394
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2060
2395
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
2061
|
-
return /* @__PURE__ */
|
|
2396
|
+
return /* @__PURE__ */ jsx41("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
2062
2397
|
}
|
|
2063
2398
|
|
|
2064
2399
|
// src/RailItem.tsx
|
|
2065
|
-
import { jsx as
|
|
2400
|
+
import { jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2066
2401
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
2067
|
-
return /* @__PURE__ */
|
|
2402
|
+
return /* @__PURE__ */ jsxs28(
|
|
2068
2403
|
"a",
|
|
2069
2404
|
{
|
|
2070
2405
|
href,
|
|
@@ -2072,14 +2407,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
2072
2407
|
className: cn("group flex w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
2073
2408
|
...props,
|
|
2074
2409
|
children: [
|
|
2075
|
-
/* @__PURE__ */
|
|
2410
|
+
/* @__PURE__ */ jsx42(
|
|
2076
2411
|
"div",
|
|
2077
2412
|
{
|
|
2078
2413
|
className: cn(
|
|
2079
2414
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
2080
2415
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
2081
2416
|
),
|
|
2082
|
-
children: /* @__PURE__ */
|
|
2417
|
+
children: /* @__PURE__ */ jsx42(
|
|
2083
2418
|
"span",
|
|
2084
2419
|
{
|
|
2085
2420
|
className: cn(
|
|
@@ -2091,27 +2426,27 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
2091
2426
|
)
|
|
2092
2427
|
}
|
|
2093
2428
|
),
|
|
2094
|
-
/* @__PURE__ */
|
|
2429
|
+
/* @__PURE__ */ jsx42("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
2095
2430
|
]
|
|
2096
2431
|
}
|
|
2097
2432
|
);
|
|
2098
2433
|
}
|
|
2099
2434
|
|
|
2100
2435
|
// src/Sidebar.tsx
|
|
2101
|
-
import { jsx as
|
|
2436
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
2102
2437
|
function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
|
|
2103
|
-
return /* @__PURE__ */
|
|
2438
|
+
return /* @__PURE__ */ jsx43(
|
|
2104
2439
|
"nav",
|
|
2105
2440
|
{
|
|
2106
2441
|
"aria-label": ariaLabel,
|
|
2107
2442
|
className: cn("flex w-60 shrink-0 flex-col border-r border-border-default bg-bg-surface", className),
|
|
2108
|
-
children: /* @__PURE__ */
|
|
2443
|
+
children: /* @__PURE__ */ jsx43(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
|
|
2109
2444
|
}
|
|
2110
2445
|
);
|
|
2111
2446
|
}
|
|
2112
2447
|
|
|
2113
2448
|
// src/Property.tsx
|
|
2114
|
-
import { jsx as
|
|
2449
|
+
import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2115
2450
|
var VALUE_CLASSES = "contents";
|
|
2116
2451
|
function Property({ label, layout = "row", children, className }) {
|
|
2117
2452
|
if (layout === "stacked") {
|
|
@@ -2119,23 +2454,23 @@ function Property({ label, layout = "row", children, className }) {
|
|
|
2119
2454
|
// gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
|
|
2120
2455
|
// Peek's topic-details sections already sit at 12px, Ship's rail was
|
|
2121
2456
|
// 6px, and unifying means the bigger, calmer one.
|
|
2122
|
-
/* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2124
|
-
/* @__PURE__ */
|
|
2457
|
+
/* @__PURE__ */ jsxs29("dl", { className: cn("flex flex-col gap-3", className), children: [
|
|
2458
|
+
/* @__PURE__ */ jsx44("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
|
|
2459
|
+
/* @__PURE__ */ jsx44("dd", { className: VALUE_CLASSES, children })
|
|
2125
2460
|
] })
|
|
2126
2461
|
);
|
|
2127
2462
|
}
|
|
2128
|
-
return /* @__PURE__ */
|
|
2129
|
-
/* @__PURE__ */
|
|
2130
|
-
/* @__PURE__ */
|
|
2463
|
+
return /* @__PURE__ */ jsxs29("dl", { className: cn("flex items-center gap-2", className), children: [
|
|
2464
|
+
/* @__PURE__ */ jsx44("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
|
|
2465
|
+
/* @__PURE__ */ jsx44("dd", { className: VALUE_CLASSES, children })
|
|
2131
2466
|
] });
|
|
2132
2467
|
}
|
|
2133
2468
|
|
|
2134
2469
|
// src/Reaction.tsx
|
|
2135
2470
|
import { Toggle } from "@base-ui/react/toggle";
|
|
2136
|
-
import { jsx as
|
|
2471
|
+
import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2137
2472
|
function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
2138
|
-
return /* @__PURE__ */
|
|
2473
|
+
return /* @__PURE__ */ jsxs30(
|
|
2139
2474
|
Toggle,
|
|
2140
2475
|
{
|
|
2141
2476
|
pressed,
|
|
@@ -2157,8 +2492,8 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
2157
2492
|
),
|
|
2158
2493
|
...props,
|
|
2159
2494
|
children: [
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2495
|
+
/* @__PURE__ */ jsx45("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
|
|
2496
|
+
/* @__PURE__ */ jsx45("span", { className: "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums", children: count })
|
|
2162
2497
|
]
|
|
2163
2498
|
}
|
|
2164
2499
|
);
|
|
@@ -2167,9 +2502,9 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
2167
2502
|
// src/SearchInput.tsx
|
|
2168
2503
|
import "react";
|
|
2169
2504
|
import { Input as Input3 } from "@base-ui/react/input";
|
|
2170
|
-
import { jsx as
|
|
2505
|
+
import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2171
2506
|
function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
|
|
2172
|
-
return /* @__PURE__ */
|
|
2507
|
+
return /* @__PURE__ */ jsxs31(
|
|
2173
2508
|
"div",
|
|
2174
2509
|
{
|
|
2175
2510
|
className: cn(
|
|
@@ -2179,7 +2514,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2179
2514
|
className
|
|
2180
2515
|
),
|
|
2181
2516
|
children: [
|
|
2182
|
-
/* @__PURE__ */
|
|
2517
|
+
/* @__PURE__ */ jsx46(
|
|
2183
2518
|
Input3,
|
|
2184
2519
|
{
|
|
2185
2520
|
className: "flex-1 min-w-0 bg-transparent text-input-value text-text-primary placeholder:text-text-muted outline-none",
|
|
@@ -2187,7 +2522,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2187
2522
|
...props
|
|
2188
2523
|
}
|
|
2189
2524
|
),
|
|
2190
|
-
shortcut && /* @__PURE__ */
|
|
2525
|
+
shortcut && /* @__PURE__ */ jsx46(Kbd, { children: shortcut })
|
|
2191
2526
|
]
|
|
2192
2527
|
}
|
|
2193
2528
|
);
|
|
@@ -2196,17 +2531,17 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2196
2531
|
// src/SectionHeader.tsx
|
|
2197
2532
|
import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
|
|
2198
2533
|
import { useRender } from "@base-ui/react/use-render";
|
|
2199
|
-
import { Fragment as
|
|
2534
|
+
import { Fragment as Fragment8, jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2200
2535
|
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", render, className }) {
|
|
2201
2536
|
const titleElement = useRender({
|
|
2202
|
-
render: render ?? (chevron ? /* @__PURE__ */
|
|
2537
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx47("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx47("span", {})),
|
|
2203
2538
|
props: {
|
|
2204
2539
|
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
2205
2540
|
// whole row up to the actions is the hit target, as it was when the
|
|
2206
2541
|
// row itself carried the click.
|
|
2207
2542
|
className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
|
|
2208
|
-
children: /* @__PURE__ */
|
|
2209
|
-
chevron && /* @__PURE__ */
|
|
2543
|
+
children: /* @__PURE__ */ jsxs32(Fragment8, { children: [
|
|
2544
|
+
chevron && /* @__PURE__ */ jsx47(
|
|
2210
2545
|
IconChevronRight2,
|
|
2211
2546
|
{
|
|
2212
2547
|
size: 12,
|
|
@@ -2214,11 +2549,11 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2214
2549
|
className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
2215
2550
|
}
|
|
2216
2551
|
),
|
|
2217
|
-
/* @__PURE__ */
|
|
2552
|
+
/* @__PURE__ */ jsx47(SectionLabel, { children: title })
|
|
2218
2553
|
] })
|
|
2219
2554
|
}
|
|
2220
2555
|
});
|
|
2221
|
-
return /* @__PURE__ */
|
|
2556
|
+
return /* @__PURE__ */ jsxs32(
|
|
2222
2557
|
"div",
|
|
2223
2558
|
{
|
|
2224
2559
|
className: cn(
|
|
@@ -2231,15 +2566,15 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2231
2566
|
),
|
|
2232
2567
|
children: [
|
|
2233
2568
|
titleElement,
|
|
2234
|
-
trailing != null && /* @__PURE__ */
|
|
2235
|
-
actions && actions.length > 0 && /* @__PURE__ */
|
|
2569
|
+
trailing != null && /* @__PURE__ */ jsx47("div", { className: "flex shrink-0 items-center", children: trailing }),
|
|
2570
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx47(
|
|
2236
2571
|
"div",
|
|
2237
2572
|
{
|
|
2238
2573
|
className: cn(
|
|
2239
2574
|
"-mr-1 flex shrink-0 items-center gap-1",
|
|
2240
2575
|
showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
|
|
2241
2576
|
),
|
|
2242
|
-
children: actions.map((action) => /* @__PURE__ */
|
|
2577
|
+
children: actions.map((action) => /* @__PURE__ */ jsx47(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
|
|
2243
2578
|
}
|
|
2244
2579
|
)
|
|
2245
2580
|
]
|
|
@@ -2248,9 +2583,9 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2248
2583
|
}
|
|
2249
2584
|
|
|
2250
2585
|
// src/CollapsibleSection.tsx
|
|
2251
|
-
import { useState as
|
|
2586
|
+
import { useState as useState7 } from "react";
|
|
2252
2587
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
2253
|
-
import { jsx as
|
|
2588
|
+
import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2254
2589
|
var OPEN = "open";
|
|
2255
2590
|
var CLOSED = "closed";
|
|
2256
2591
|
function readStored(key) {
|
|
@@ -2270,21 +2605,21 @@ function writeStored(key, open) {
|
|
|
2270
2605
|
}
|
|
2271
2606
|
}
|
|
2272
2607
|
function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, trailing, actions, showActions, children, className, contentClassName }) {
|
|
2273
|
-
const [openState, setOpenState] =
|
|
2608
|
+
const [openState, setOpenState] = useState7(() => readStored(storageKey) ?? defaultOpen);
|
|
2274
2609
|
const open = openProp ?? openState;
|
|
2275
2610
|
const setOpen = (next) => {
|
|
2276
2611
|
setOpenState(next);
|
|
2277
2612
|
writeStored(storageKey, next);
|
|
2278
2613
|
onOpenChange?.(next);
|
|
2279
2614
|
};
|
|
2280
|
-
return /* @__PURE__ */
|
|
2281
|
-
/* @__PURE__ */
|
|
2282
|
-
/* @__PURE__ */
|
|
2615
|
+
return /* @__PURE__ */ jsxs33(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
2616
|
+
/* @__PURE__ */ jsx48(SectionHeader, { title, chevron: true, isExpanded: open, trailing, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx48(Collapsible.Trigger, {}) }),
|
|
2617
|
+
/* @__PURE__ */ jsx48(
|
|
2283
2618
|
Collapsible.Panel,
|
|
2284
2619
|
{
|
|
2285
2620
|
hiddenUntilFound: true,
|
|
2286
2621
|
className: "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0",
|
|
2287
|
-
children: /* @__PURE__ */
|
|
2622
|
+
children: /* @__PURE__ */ jsx48("div", { className: cn("flex flex-col", contentClassName), children })
|
|
2288
2623
|
}
|
|
2289
2624
|
)
|
|
2290
2625
|
] });
|
|
@@ -2292,9 +2627,9 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
|
|
|
2292
2627
|
|
|
2293
2628
|
// src/Tabs.tsx
|
|
2294
2629
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
2295
|
-
import { jsx as
|
|
2630
|
+
import { jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2296
2631
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
2297
|
-
return /* @__PURE__ */
|
|
2632
|
+
return /* @__PURE__ */ jsx49(
|
|
2298
2633
|
BaseTabs.Root,
|
|
2299
2634
|
{
|
|
2300
2635
|
value: active,
|
|
@@ -2302,14 +2637,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2302
2637
|
if (details.reason === "none") onChange(value);
|
|
2303
2638
|
},
|
|
2304
2639
|
className,
|
|
2305
|
-
children: /* @__PURE__ */
|
|
2640
|
+
children: /* @__PURE__ */ jsx49(
|
|
2306
2641
|
BaseTabs.List,
|
|
2307
2642
|
{
|
|
2308
2643
|
activateOnFocus: true,
|
|
2309
2644
|
"aria-label": aria["aria-label"],
|
|
2310
2645
|
"aria-labelledby": aria["aria-labelledby"],
|
|
2311
2646
|
className: "flex items-center gap-2",
|
|
2312
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
2647
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs34(
|
|
2313
2648
|
BaseTabs.Tab,
|
|
2314
2649
|
{
|
|
2315
2650
|
value: tab.id,
|
|
@@ -2322,9 +2657,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2322
2657
|
),
|
|
2323
2658
|
children: [
|
|
2324
2659
|
tab.icon,
|
|
2325
|
-
/* @__PURE__ */
|
|
2660
|
+
/* @__PURE__ */ jsxs34("span", { className: "flex items-baseline", children: [
|
|
2326
2661
|
tab.label,
|
|
2327
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
2662
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx49("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
2328
2663
|
] })
|
|
2329
2664
|
]
|
|
2330
2665
|
},
|
|
@@ -2337,10 +2672,10 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2337
2672
|
}
|
|
2338
2673
|
|
|
2339
2674
|
// src/Toast.tsx
|
|
2340
|
-
import { createContext as
|
|
2675
|
+
import { createContext as createContext3, useContext as useContext3, useMemo as useMemo4 } from "react";
|
|
2341
2676
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
2342
2677
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
2343
|
-
import { jsx as
|
|
2678
|
+
import { jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2344
2679
|
var SURFACE_STYLES = {
|
|
2345
2680
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md",
|
|
2346
2681
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md",
|
|
@@ -2365,13 +2700,6 @@ var ICON_STYLES = {
|
|
|
2365
2700
|
// approximated here (D16).
|
|
2366
2701
|
error: "signal:text-error-default"
|
|
2367
2702
|
};
|
|
2368
|
-
var ACTION_BORDER_STYLES = {
|
|
2369
|
-
success: "signal:border signal:border-border-default signal:hover:border-border-strong",
|
|
2370
|
-
brand: "signal:border signal:border-border-default signal:hover:border-border-strong",
|
|
2371
|
-
neutral: "border border-border-default",
|
|
2372
|
-
warning: "signal:border signal:border-border-default signal:hover:border-border-strong",
|
|
2373
|
-
error: "signal:border signal:border-border-default signal:hover:border-border-strong"
|
|
2374
|
-
};
|
|
2375
2703
|
var LABEL_CLASSES = "text-body-2 text-text-primary whitespace-nowrap";
|
|
2376
2704
|
var pillClassName = (type, hasAction, className) => cn(
|
|
2377
2705
|
"inline-flex items-center min-h-[32px] pl-2 py-1 rounded-lg shadow-lg",
|
|
@@ -2381,31 +2709,25 @@ var pillClassName = (type, hasAction, className) => cn(
|
|
|
2381
2709
|
SURFACE_STYLES[type],
|
|
2382
2710
|
className
|
|
2383
2711
|
);
|
|
2384
|
-
var actionClassName = (type) => cn(
|
|
2385
|
-
"h-6 flex items-center justify-center gap-1 px-1 py-1 rounded-md shrink-0 transition-colors",
|
|
2386
|
-
ACTION_BORDER_STYLES[type],
|
|
2387
|
-
type === "neutral" ? "hover:border-border-strong" : "hover:opacity-80"
|
|
2388
|
-
);
|
|
2389
2712
|
function LeadingIcon({ type }) {
|
|
2390
2713
|
const Icon = ICONS[type];
|
|
2391
|
-
return /* @__PURE__ */
|
|
2714
|
+
return /* @__PURE__ */ jsx50(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
|
|
2392
2715
|
}
|
|
2393
|
-
var ACTION_LABEL_CLASSES = "text-btn-small text-text-primary whitespace-nowrap";
|
|
2394
2716
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
2395
2717
|
const hasAction = !!(actionLabel && onAction);
|
|
2396
|
-
return /* @__PURE__ */
|
|
2397
|
-
/* @__PURE__ */
|
|
2398
|
-
leadingIcon && /* @__PURE__ */
|
|
2399
|
-
/* @__PURE__ */
|
|
2718
|
+
return /* @__PURE__ */ jsxs35("div", { className: pillClassName(type, hasAction, className), children: [
|
|
2719
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2720
|
+
leadingIcon && /* @__PURE__ */ jsx50(LeadingIcon, { type }),
|
|
2721
|
+
/* @__PURE__ */ jsx50("span", { className: LABEL_CLASSES, children: label })
|
|
2400
2722
|
] }),
|
|
2401
|
-
hasAction && /* @__PURE__ */
|
|
2723
|
+
hasAction && /* @__PURE__ */ jsx50(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
2402
2724
|
] });
|
|
2403
2725
|
}
|
|
2404
|
-
var ToastContext =
|
|
2726
|
+
var ToastContext = createContext3(null);
|
|
2405
2727
|
var VISIBLE_TOASTS = 3;
|
|
2406
2728
|
function ToastProvider({ children }) {
|
|
2407
|
-
const manager =
|
|
2408
|
-
const value =
|
|
2729
|
+
const manager = useMemo4(() => BaseToast.createToastManager(), []);
|
|
2730
|
+
const value = useMemo4(
|
|
2409
2731
|
() => ({
|
|
2410
2732
|
showToast: ({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, durationMs = 5e3 }) => manager.add({
|
|
2411
2733
|
title: label,
|
|
@@ -2419,9 +2741,9 @@ function ToastProvider({ children }) {
|
|
|
2419
2741
|
}),
|
|
2420
2742
|
[manager]
|
|
2421
2743
|
);
|
|
2422
|
-
return /* @__PURE__ */
|
|
2744
|
+
return /* @__PURE__ */ jsx50(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs35(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
|
|
2423
2745
|
children,
|
|
2424
|
-
/* @__PURE__ */
|
|
2746
|
+
/* @__PURE__ */ jsx50(BaseToast.Portal, { children: /* @__PURE__ */ jsx50(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx50(ToastList, {}) }) })
|
|
2425
2747
|
] }) });
|
|
2426
2748
|
}
|
|
2427
2749
|
function ToastList() {
|
|
@@ -2429,26 +2751,25 @@ function ToastList() {
|
|
|
2429
2751
|
return toasts.map((toast) => {
|
|
2430
2752
|
const type = toast.type ?? "neutral";
|
|
2431
2753
|
const { leadingIcon = true, actionLabel, onAction } = toast.data ?? {};
|
|
2432
|
-
return /* @__PURE__ */
|
|
2754
|
+
return /* @__PURE__ */ jsxs35(
|
|
2433
2755
|
BaseToast.Root,
|
|
2434
2756
|
{
|
|
2435
2757
|
toast,
|
|
2436
2758
|
swipeDirection: ["left", "down"],
|
|
2437
2759
|
className: pillClassName(type, !!actionLabel, "pointer-events-auto data-[limited]:hidden"),
|
|
2438
2760
|
children: [
|
|
2439
|
-
/* @__PURE__ */
|
|
2440
|
-
leadingIcon && /* @__PURE__ */
|
|
2441
|
-
/* @__PURE__ */
|
|
2761
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2762
|
+
leadingIcon && /* @__PURE__ */ jsx50(LeadingIcon, { type }),
|
|
2763
|
+
/* @__PURE__ */ jsx50(BaseToast.Title, { render: /* @__PURE__ */ jsx50("span", {}), className: LABEL_CLASSES })
|
|
2442
2764
|
] }),
|
|
2443
|
-
actionLabel && /* @__PURE__ */
|
|
2765
|
+
actionLabel && /* @__PURE__ */ jsx50(
|
|
2444
2766
|
BaseToast.Action,
|
|
2445
2767
|
{
|
|
2446
2768
|
onClick: () => {
|
|
2447
2769
|
onAction?.();
|
|
2448
2770
|
close(toast.id);
|
|
2449
2771
|
},
|
|
2450
|
-
|
|
2451
|
-
children: /* @__PURE__ */ jsx49("span", { className: ACTION_LABEL_CLASSES, children: actionLabel })
|
|
2772
|
+
render: /* @__PURE__ */ jsx50(Button, { variant: "outlined", size: "small", children: actionLabel })
|
|
2452
2773
|
}
|
|
2453
2774
|
)
|
|
2454
2775
|
]
|
|
@@ -2458,7 +2779,7 @@ function ToastList() {
|
|
|
2458
2779
|
});
|
|
2459
2780
|
}
|
|
2460
2781
|
function useToast() {
|
|
2461
|
-
const ctx =
|
|
2782
|
+
const ctx = useContext3(ToastContext);
|
|
2462
2783
|
if (!ctx) throw new Error("useToast must be used within ToastProvider");
|
|
2463
2784
|
return ctx;
|
|
2464
2785
|
}
|
|
@@ -2475,6 +2796,12 @@ export {
|
|
|
2475
2796
|
Chip,
|
|
2476
2797
|
ChipInput,
|
|
2477
2798
|
CollapsibleSection,
|
|
2799
|
+
CommandPalette,
|
|
2800
|
+
CommandPaletteAnswer,
|
|
2801
|
+
CommandPaletteForm,
|
|
2802
|
+
CommandPaletteQuote,
|
|
2803
|
+
CommandPaletteSearch,
|
|
2804
|
+
CommandPaletteWorking,
|
|
2478
2805
|
ConfirmDialog,
|
|
2479
2806
|
DialogShell,
|
|
2480
2807
|
Divider,
|