@estiva-app/ui 0.54.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BlockHandle.d.ts +47 -0
- package/dist/BlockHandle.d.ts.map +1 -0
- package/dist/CollapsibleSection.d.ts +7 -1
- package/dist/CollapsibleSection.d.ts.map +1 -1
- package/dist/ContainerHeader.d.ts +7 -1
- package/dist/ContainerHeader.d.ts.map +1 -1
- package/dist/EditorBlockHandle.d.ts +57 -0
- package/dist/EditorBlockHandle.d.ts.map +1 -0
- package/dist/IconButton.d.ts.map +1 -1
- package/dist/ListColumn.d.ts +2 -0
- package/dist/ListColumn.d.ts.map +1 -1
- package/dist/Menu.d.ts.map +1 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/NavTree.d.ts +9 -1
- package/dist/NavTree.d.ts.map +1 -1
- package/dist/PersonTrigger.d.ts.map +1 -1
- package/dist/SectionHeader.d.ts +22 -3
- package/dist/SectionHeader.d.ts.map +1 -1
- package/dist/SectionLabel.d.ts.map +1 -1
- package/dist/editor.d.ts +1 -0
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +127 -11
- package/dist/editor.js.map +4 -4
- package/dist/gates/index.js +1 -1
- package/dist/gates/index.js.map +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +831 -624
- package/dist/index.js.map +4 -4
- package/dist/looks.d.ts +4 -0
- package/dist/looks.d.ts.map +1 -1
- package/package.json +1 -1
- package/registry.json +302 -23
- package/src/BlockHandle.mdx +58 -0
- package/src/BlockHandle.stories.tsx +44 -0
- package/src/BlockHandle.test.tsx +216 -0
- package/src/BlockHandle.tsx +220 -0
- package/src/CollapsibleSection.stories.tsx +14 -1
- package/src/CollapsibleSection.tsx +10 -4
- package/src/ContainerHeader.mdx +4 -0
- package/src/ContainerHeader.stories.tsx +14 -0
- package/src/ContainerHeader.test.tsx +8 -0
- package/src/ContainerHeader.tsx +34 -6
- package/src/EditorBlockHandle.mdx +65 -0
- package/src/EditorBlockHandle.stories.tsx +81 -0
- package/src/EditorBlockHandle.tsx +181 -0
- package/src/IconButton.tsx +2 -1
- package/src/ListColumn.tsx +4 -2
- package/src/Menu.tsx +5 -4
- package/src/NavItem.test.tsx +2 -2
- package/src/NavItem.tsx +21 -12
- package/src/NavTree.mdx +16 -1
- package/src/NavTree.stories.tsx +49 -2
- package/src/NavTree.test.tsx +7 -0
- package/src/NavTree.tsx +21 -4
- package/src/PersonTrigger.tsx +6 -5
- package/src/SectionHeader.mdx +6 -0
- package/src/SectionHeader.stories.tsx +18 -0
- package/src/SectionHeader.test.tsx +26 -0
- package/src/SectionHeader.tsx +99 -23
- package/src/SectionLabel.tsx +6 -3
- package/src/Sidebar.tsx +1 -1
- package/src/editor.ts +1 -0
- package/src/eslint/no-copied-look.test.ts +2 -2
- package/src/gates/app-checks.ts +1 -1
- package/src/index.ts +1 -0
- package/src/looks.ts +6 -0
- package/src/registry/registry.test.ts +5 -5
- package/stories/Choosing.mdx +2 -0
package/dist/index.js
CHANGED
|
@@ -168,7 +168,7 @@ function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className })
|
|
|
168
168
|
{
|
|
169
169
|
"aria-label": ariaLabel,
|
|
170
170
|
className: cn("flex w-60 shrink-0 flex-col", !onGround && "border-r border-border-default bg-bg-surface", className),
|
|
171
|
-
children: /* @__PURE__ */ jsx4(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-
|
|
171
|
+
children: /* @__PURE__ */ jsx4(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-0.5 px-2.5 py-3", children })
|
|
172
172
|
}
|
|
173
173
|
);
|
|
174
174
|
}
|
|
@@ -276,6 +276,25 @@ import {
|
|
|
276
276
|
// src/IconButton.tsx
|
|
277
277
|
import { Button as BaseButton } from "@base-ui/react/button";
|
|
278
278
|
|
|
279
|
+
// src/looks.ts
|
|
280
|
+
var FIELD_BOX_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong focus:border-border-focus group-hover/field:focus:border-border-focus rounded-lg";
|
|
281
|
+
var FIELD_TEXT_CLASSES = "text-text-primary placeholder:text-text-muted";
|
|
282
|
+
var FIELD_DISABLED_CLASSES = "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field group-hover/field:disabled:border-border-field";
|
|
283
|
+
var FIELD_FOCUS_RING_CLASSES = "signal:transition-shadow signal:focus:shadow-focus-ring";
|
|
284
|
+
var FIELD_SIZE_CLASSES = {
|
|
285
|
+
default: "px-3 py-2 text-input-value",
|
|
286
|
+
small: "h-6 min-h-6 px-2 text-caption"
|
|
287
|
+
};
|
|
288
|
+
var FIELD_SHELL_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong rounded-lg transition-colors";
|
|
289
|
+
var FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
|
|
290
|
+
var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
|
|
291
|
+
var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
|
|
292
|
+
var MUTED_CONTROL_CLASSES = "text-text-secondary hover:bg-bg-hover hover:text-text-primary";
|
|
293
|
+
var MENU_TRIGGER_CLASSES = "cursor-pointer rounded-md transition-colors hover:bg-bg-hover data-[popup-open]:bg-bg-hover";
|
|
294
|
+
var SIDEBAR_ROW_CLASSES = "rounded-lg transition-colors";
|
|
295
|
+
var SIDEBAR_ROW_TEXT_CLASSES = "text-text-secondary hover:text-text-primary";
|
|
296
|
+
var COLLAPSIBLE_PANEL_CLASSES = "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";
|
|
297
|
+
|
|
279
298
|
// src/formBusy.ts
|
|
280
299
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
281
300
|
var FormBusyContext = createContext2(false);
|
|
@@ -306,23 +325,6 @@ function Kbd({ children, className, tone = "default" }) {
|
|
|
306
325
|
);
|
|
307
326
|
}
|
|
308
327
|
|
|
309
|
-
// src/looks.ts
|
|
310
|
-
var FIELD_BOX_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong focus:border-border-focus group-hover/field:focus:border-border-focus rounded-lg";
|
|
311
|
-
var FIELD_TEXT_CLASSES = "text-text-primary placeholder:text-text-muted";
|
|
312
|
-
var FIELD_DISABLED_CLASSES = "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field group-hover/field:disabled:border-border-field";
|
|
313
|
-
var FIELD_FOCUS_RING_CLASSES = "signal:transition-shadow signal:focus:shadow-focus-ring";
|
|
314
|
-
var FIELD_SIZE_CLASSES = {
|
|
315
|
-
default: "px-3 py-2 text-input-value",
|
|
316
|
-
small: "h-6 min-h-6 px-2 text-caption"
|
|
317
|
-
};
|
|
318
|
-
var FIELD_SHELL_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong rounded-lg transition-colors";
|
|
319
|
-
var FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
|
|
320
|
-
var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
|
|
321
|
-
var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
|
|
322
|
-
var SIDEBAR_ROW_CLASSES = "rounded-lg transition-colors";
|
|
323
|
-
var SIDEBAR_ROW_TEXT_CLASSES = "text-text-secondary hover:text-text-primary";
|
|
324
|
-
var COLLAPSIBLE_PANEL_CLASSES = "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";
|
|
325
|
-
|
|
326
328
|
// src/Tooltip.tsx
|
|
327
329
|
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
328
330
|
var OPEN_DELAY = 300;
|
|
@@ -410,7 +412,7 @@ function IconButton({
|
|
|
410
412
|
// stretched and carries no `self-center` — see the note there.
|
|
411
413
|
"flex items-center justify-center p-1 rounded-lg transition-colors shrink-0 self-center cursor-pointer",
|
|
412
414
|
!off && variant === "primary" && "bg-accent-primary hover:bg-accent-hover text-text-inverse",
|
|
413
|
-
!off && (variant === "muted" || variant === "resolve") &&
|
|
415
|
+
!off && (variant === "muted" || variant === "resolve") && MUTED_CONTROL_CLASSES,
|
|
414
416
|
!off && variant === "outlined" && "border border-border-default hover:bg-bg-hover text-text-secondary",
|
|
415
417
|
!off && variant === "current" && "hover:bg-bg-hover",
|
|
416
418
|
off && variant === "primary" && "bg-bg-disabled text-text-disabled",
|
|
@@ -948,109 +950,9 @@ function Banner({ tone, children, icon, action, onDismiss, dismissLabel = "Dismi
|
|
|
948
950
|
] });
|
|
949
951
|
}
|
|
950
952
|
|
|
951
|
-
// src/
|
|
952
|
-
import {
|
|
953
|
-
import {
|
|
954
|
-
import { IconCheck } from "@tabler/icons-react";
|
|
955
|
-
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
956
|
-
function squareClasses(checked, disabled, interactive, className) {
|
|
957
|
-
return cn(
|
|
958
|
-
"inline-flex items-center justify-center size-4 shrink-0 rounded-sm border transition-colors",
|
|
959
|
-
checked ? "bg-accent-primary border-accent-primary text-text-inverse" : "bg-transparent border-border-strong hover:border-text-muted",
|
|
960
|
-
disabled && "opacity-50 pointer-events-none",
|
|
961
|
-
interactive ? "cursor-pointer" : "pointer-events-none",
|
|
962
|
-
className
|
|
963
|
-
);
|
|
964
|
-
}
|
|
965
|
-
var tickClasses = (checked) => cn("flex", !checked && "invisible");
|
|
966
|
-
var WORDS_CLASSES = "text-body-2 text-text-primary";
|
|
967
|
-
var ROW_CLASSES = "flex shrink-0 items-center gap-3 h-10 px-3 rounded-lg transition-colors";
|
|
968
|
-
function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row, leading, className, ...aria }) {
|
|
969
|
-
const formBusy = useFormBusy();
|
|
970
|
-
const disabled = ownDisabled || formBusy;
|
|
971
|
-
if (!onChange) {
|
|
972
|
-
const picture = /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx16("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx16(IconCheck, { size: 12, stroke: 3 }) }) });
|
|
973
|
-
if (label === void 0) return picture;
|
|
974
|
-
return /* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-2", children: [
|
|
975
|
-
picture,
|
|
976
|
-
/* @__PURE__ */ jsx16("span", { className: WORDS_CLASSES, children: label })
|
|
977
|
-
] });
|
|
978
|
-
}
|
|
979
|
-
const box = /* @__PURE__ */ jsx16(
|
|
980
|
-
BaseCheckbox.Root,
|
|
981
|
-
{
|
|
982
|
-
checked,
|
|
983
|
-
disabled,
|
|
984
|
-
"aria-label": aria["aria-label"],
|
|
985
|
-
"aria-required": aria["aria-required"],
|
|
986
|
-
onCheckedChange: (next) => onChange(next),
|
|
987
|
-
onClick: (e) => e.stopPropagation(),
|
|
988
|
-
className: (state) => squareClasses(state.checked, state.disabled, true, className),
|
|
989
|
-
children: /* @__PURE__ */ jsx16(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx16(IconCheck, { size: 12, stroke: 3 }) })
|
|
990
|
-
}
|
|
991
|
-
);
|
|
992
|
-
if (label === void 0) return box;
|
|
993
|
-
if (row) {
|
|
994
|
-
return /* @__PURE__ */ jsx16(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs10(BaseField.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
|
|
995
|
-
leading,
|
|
996
|
-
/* @__PURE__ */ jsx16("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
|
|
997
|
-
box
|
|
998
|
-
] }) });
|
|
999
|
-
}
|
|
1000
|
-
return /* @__PURE__ */ jsx16(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs10(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
|
|
1001
|
-
box,
|
|
1002
|
-
/* @__PURE__ */ jsx16("span", { className: WORDS_CLASSES, children: label })
|
|
1003
|
-
] }) });
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
// src/Chip.tsx
|
|
1007
|
-
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1008
|
-
var typeStyles = {
|
|
1009
|
-
neutral: "bg-bg-inset text-text-primary",
|
|
1010
|
-
brand: "bg-accent-muted text-accent-text signal:border signal:border-accent-outline",
|
|
1011
|
-
info: "bg-info-muted text-info-default signal:border signal:border-info-outline",
|
|
1012
|
-
warning: "bg-warning-muted text-warning-default signal:border signal:border-warning-outline signal:shadow-glow-warning",
|
|
1013
|
-
success: "bg-success-muted text-success-default signal:border signal:border-success-outline",
|
|
1014
|
-
error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
|
|
1015
|
-
};
|
|
1016
|
-
function Chip({ type = "neutral", label, leadingIcon, trailingIcon, href, onClick, className }) {
|
|
1017
|
-
const classes = cn("inline-flex min-w-0 items-center justify-center gap-1.5 rounded-full max-h-[20px] px-2 py-1", typeStyles[type], className);
|
|
1018
|
-
const inside = /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
1019
|
-
leadingIcon && /* @__PURE__ */ jsx17("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
|
|
1020
|
-
label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
|
|
1021
|
-
// of growing past it — Ship's project chip on an issue row
|
|
1022
|
-
// (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
|
|
1023
|
-
// `truncate`, because `truncate` is `overflow: hidden` on both axes and
|
|
1024
|
-
// the label's line box (11px under Signal) is tighter than its glyphs —
|
|
1025
|
-
// the screenshot diff caught every descender cut off. `clip` is the
|
|
1026
|
-
// one overflow that leaves the other axis visible. A chip with no cap
|
|
1027
|
-
// draws exactly as before.
|
|
1028
|
-
/* @__PURE__ */ jsx17("span", { className: cn("min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide", CHIP_TEXT_CLASSES), children: label }),
|
|
1029
|
-
trailingIcon && /* @__PURE__ */ jsx17("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
1030
|
-
] });
|
|
1031
|
-
if (href) return /* @__PURE__ */ jsx17("a", { href, onClick, className: cn("relative", classes), children: inside });
|
|
1032
|
-
return /* @__PURE__ */ jsx17("div", { className: classes, children: inside });
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
// src/CommandPalette.tsx
|
|
1036
|
-
import {
|
|
1037
|
-
createContext as createContext5,
|
|
1038
|
-
useContext as useContext5,
|
|
1039
|
-
useEffect as useEffect2,
|
|
1040
|
-
useLayoutEffect as useLayoutEffect3,
|
|
1041
|
-
useMemo as useMemo2,
|
|
1042
|
-
useRef as useRef4,
|
|
1043
|
-
useState as useState3
|
|
1044
|
-
} from "react";
|
|
1045
|
-
import { Dialog as Dialog2 } from "@base-ui/react/dialog";
|
|
1046
|
-
import { Autocomplete } from "@base-ui/react/autocomplete";
|
|
1047
|
-
import { IconLoader2 as IconLoader22, IconSearch } from "@tabler/icons-react";
|
|
1048
|
-
|
|
1049
|
-
// src/ChipInput.tsx
|
|
1050
|
-
import { useMemo, useState as useState2 } from "react";
|
|
1051
|
-
import { Button as BaseButton4 } from "@base-ui/react/button";
|
|
1052
|
-
import { Combobox } from "@base-ui/react/combobox";
|
|
1053
|
-
import { IconX as IconX4 } from "@tabler/icons-react";
|
|
953
|
+
// src/BlockHandle.tsx
|
|
954
|
+
import { useCallback, useEffect as useEffect2, useRef as useRef3, useState as useState2 } from "react";
|
|
955
|
+
import { IconGripVertical } from "@tabler/icons-react";
|
|
1054
956
|
|
|
1055
957
|
// src/Menu.tsx
|
|
1056
958
|
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
@@ -1060,27 +962,27 @@ import { Menu as BaseMenu } from "@base-ui/react/menu";
|
|
|
1060
962
|
// src/Divider.tsx
|
|
1061
963
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
1062
964
|
import { Separator } from "@base-ui/react/separator";
|
|
1063
|
-
import { jsx as
|
|
965
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1064
966
|
var DividerInPanel = createContext3(false);
|
|
1065
967
|
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
1066
968
|
const inset = useContext3(DividerInPanel) ? "mx-0" : "mx-3";
|
|
1067
969
|
if (label && orientation === "horizontal") {
|
|
1068
970
|
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
1069
|
-
return /* @__PURE__ */
|
|
971
|
+
return /* @__PURE__ */ jsxs10(
|
|
1070
972
|
Separator,
|
|
1071
973
|
{
|
|
1072
974
|
orientation: "horizontal",
|
|
1073
975
|
"aria-label": label,
|
|
1074
976
|
className: cn("flex shrink-0 items-center gap-2", inset, className),
|
|
1075
977
|
children: [
|
|
1076
|
-
/* @__PURE__ */
|
|
1077
|
-
/* @__PURE__ */
|
|
1078
|
-
/* @__PURE__ */
|
|
978
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
979
|
+
/* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
980
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
1079
981
|
]
|
|
1080
982
|
}
|
|
1081
983
|
);
|
|
1082
984
|
}
|
|
1083
|
-
return /* @__PURE__ */
|
|
985
|
+
return /* @__PURE__ */ jsx16(
|
|
1084
986
|
Separator,
|
|
1085
987
|
{
|
|
1086
988
|
orientation,
|
|
@@ -1096,7 +998,7 @@ function triggerDisabled(trigger) {
|
|
|
1096
998
|
}
|
|
1097
999
|
|
|
1098
1000
|
// src/SectionLabel.tsx
|
|
1099
|
-
import { jsx as
|
|
1001
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1100
1002
|
function SectionLabel({
|
|
1101
1003
|
children,
|
|
1102
1004
|
tone = "primary",
|
|
@@ -1104,13 +1006,16 @@ function SectionLabel({
|
|
|
1104
1006
|
folds = false,
|
|
1105
1007
|
className
|
|
1106
1008
|
}) {
|
|
1107
|
-
return /* @__PURE__ */
|
|
1009
|
+
return /* @__PURE__ */ jsx17(
|
|
1108
1010
|
"span",
|
|
1109
1011
|
{
|
|
1110
1012
|
className: cn(
|
|
1111
|
-
"text-h5 leading-3
|
|
1112
|
-
//
|
|
1113
|
-
//
|
|
1013
|
+
"text-h5 leading-3",
|
|
1014
|
+
// Ship's type in every theme but Leaf, whose section labels are the
|
|
1015
|
+
// micro-label (Katerina, 28 September) unless the group folds (2
|
|
1016
|
+
// October). Signal dropped its micro-label on 5 October: every one of
|
|
1017
|
+
// Peek's section labels is Ship's type, folding or not, so Desk's
|
|
1018
|
+
// Screener and its Urgent and Open work read as one.
|
|
1114
1019
|
!folds && "leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest",
|
|
1115
1020
|
tone === "secondary" ? "text-text-secondary" : tone === "muted" ? "text-text-muted" : "text-text-primary",
|
|
1116
1021
|
truncate && "min-w-0 truncate",
|
|
@@ -1122,14 +1027,15 @@ function SectionLabel({
|
|
|
1122
1027
|
}
|
|
1123
1028
|
|
|
1124
1029
|
// src/Menu.tsx
|
|
1125
|
-
import { Fragment as
|
|
1030
|
+
import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1126
1031
|
var MenuContext = createContext4(null);
|
|
1127
1032
|
function MenuPanel({ children, className, ...props }) {
|
|
1128
|
-
return /* @__PURE__ */
|
|
1033
|
+
return /* @__PURE__ */ jsx18(
|
|
1129
1034
|
"div",
|
|
1130
1035
|
{
|
|
1131
1036
|
className: cn(
|
|
1132
|
-
|
|
1037
|
+
// 2px between rows, as a list column's and a sidebar's (Katerina, 5 October).
|
|
1038
|
+
"flex flex-col gap-0.5 p-2",
|
|
1133
1039
|
FLOATING_SURFACE_CLASSES,
|
|
1134
1040
|
/*
|
|
1135
1041
|
* A divider in a menu runs the width of the rows it separates.
|
|
@@ -1156,7 +1062,7 @@ var VIEWPORT_PAD2 = 8;
|
|
|
1156
1062
|
var HOVER_OPEN_DELAY = 0;
|
|
1157
1063
|
var HOVER_CLOSE_DELAY = 150;
|
|
1158
1064
|
function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className, contentClassName }) {
|
|
1159
|
-
return /* @__PURE__ */
|
|
1065
|
+
return /* @__PURE__ */ jsxs11(
|
|
1160
1066
|
BaseMenu.Root,
|
|
1161
1067
|
{
|
|
1162
1068
|
open,
|
|
@@ -1164,7 +1070,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1164
1070
|
actionsRef,
|
|
1165
1071
|
modal: false,
|
|
1166
1072
|
children: [
|
|
1167
|
-
/* @__PURE__ */
|
|
1073
|
+
/* @__PURE__ */ jsx18(
|
|
1168
1074
|
BaseMenu.Trigger,
|
|
1169
1075
|
{
|
|
1170
1076
|
render: trigger,
|
|
@@ -1174,7 +1080,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1174
1080
|
closeDelay: HOVER_CLOSE_DELAY
|
|
1175
1081
|
}
|
|
1176
1082
|
),
|
|
1177
|
-
/* @__PURE__ */
|
|
1083
|
+
/* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
|
|
1178
1084
|
BaseMenu.Positioner,
|
|
1179
1085
|
{
|
|
1180
1086
|
side: "bottom",
|
|
@@ -1182,13 +1088,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1182
1088
|
sideOffset: GAP2,
|
|
1183
1089
|
collisionPadding: VIEWPORT_PAD2,
|
|
1184
1090
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1185
|
-
children: /* @__PURE__ */
|
|
1091
|
+
children: /* @__PURE__ */ jsx18(
|
|
1186
1092
|
BaseMenu.Popup,
|
|
1187
1093
|
{
|
|
1188
1094
|
"data-interactive": true,
|
|
1189
1095
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
1190
|
-
render: /* @__PURE__ */
|
|
1191
|
-
children: /* @__PURE__ */
|
|
1096
|
+
render: /* @__PURE__ */ jsx18(MenuPanel, {}),
|
|
1097
|
+
children: /* @__PURE__ */ jsx18(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col gap-0.5 p-2", contentClassName), children: /* @__PURE__ */ jsx18(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx18(DividerInPanel.Provider, { value: true, children }) }) })
|
|
1192
1098
|
}
|
|
1193
1099
|
)
|
|
1194
1100
|
}
|
|
@@ -1204,20 +1110,20 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
1204
1110
|
'[@estiva-app/ui] Menu: `openOnHover` and `MenuSub` cannot be used together \u2014 leaving the submenu panel strands the menu open. Open this menu on a press instead. See Menu.mdx, "Hover-opened menus".'
|
|
1205
1111
|
);
|
|
1206
1112
|
}
|
|
1207
|
-
return /* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1113
|
+
return /* @__PURE__ */ jsxs11(BaseMenu.SubmenuRoot, { children: [
|
|
1114
|
+
/* @__PURE__ */ jsx18(
|
|
1209
1115
|
BaseMenu.SubmenuTrigger,
|
|
1210
1116
|
{
|
|
1211
1117
|
openOnHover: true,
|
|
1212
1118
|
delay: 0,
|
|
1213
1119
|
closeDelay: 150,
|
|
1214
1120
|
nativeButton: true,
|
|
1215
|
-
render: /* @__PURE__ */
|
|
1121
|
+
render: /* @__PURE__ */ jsx18("button", { type: "button" }),
|
|
1216
1122
|
className: menuItemClassName({ size: "default", selected }),
|
|
1217
|
-
children: /* @__PURE__ */
|
|
1123
|
+
children: /* @__PURE__ */ jsx18(MenuItemBody, { label, leading, submenu: true })
|
|
1218
1124
|
}
|
|
1219
1125
|
),
|
|
1220
|
-
/* @__PURE__ */
|
|
1126
|
+
/* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
|
|
1221
1127
|
BaseMenu.Positioner,
|
|
1222
1128
|
{
|
|
1223
1129
|
side: "inline-end",
|
|
@@ -1225,7 +1131,7 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
1225
1131
|
sideOffset: GAP2,
|
|
1226
1132
|
collisionPadding: VIEWPORT_PAD2,
|
|
1227
1133
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1228
|
-
children: /* @__PURE__ */
|
|
1134
|
+
children: /* @__PURE__ */ jsx18(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx18(MenuPanel, {}), children })
|
|
1229
1135
|
}
|
|
1230
1136
|
) })
|
|
1231
1137
|
] });
|
|
@@ -1260,25 +1166,25 @@ function menuItemClassName({ size, selected, className }) {
|
|
|
1260
1166
|
);
|
|
1261
1167
|
}
|
|
1262
1168
|
function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
|
|
1263
|
-
const edge = trailing ?? (shortcut ? /* @__PURE__ */
|
|
1264
|
-
return /* @__PURE__ */
|
|
1265
|
-
leading && /* @__PURE__ */
|
|
1266
|
-
children ?? /* @__PURE__ */
|
|
1267
|
-
/* @__PURE__ */
|
|
1268
|
-
description && /* @__PURE__ */
|
|
1169
|
+
const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx18(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx18(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
|
|
1170
|
+
return /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
1171
|
+
leading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1172
|
+
children ?? /* @__PURE__ */ jsxs11("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
|
|
1173
|
+
/* @__PURE__ */ jsx18("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
|
|
1174
|
+
description && /* @__PURE__ */ jsx18("span", { className: "truncate text-caption text-text-secondary", children: description })
|
|
1269
1175
|
] }),
|
|
1270
1176
|
(edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
|
|
1271
1177
|
// the wider of the two and never changes, so revealing the hint moves
|
|
1272
1178
|
// nothing. No transition here either — the hint switches on the same
|
|
1273
1179
|
// :hover / `selected` as the fill, in the same frame.
|
|
1274
|
-
/* @__PURE__ */
|
|
1275
|
-
edge && /* @__PURE__ */
|
|
1276
|
-
hint && /* @__PURE__ */
|
|
1180
|
+
/* @__PURE__ */ jsxs11("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
|
|
1181
|
+
edge && /* @__PURE__ */ jsx18("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
|
|
1182
|
+
hint && /* @__PURE__ */ jsx18("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
|
|
1277
1183
|
] })
|
|
1278
1184
|
] });
|
|
1279
1185
|
}
|
|
1280
1186
|
function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
|
|
1281
|
-
const body = /* @__PURE__ */
|
|
1187
|
+
const body = /* @__PURE__ */ jsx18(
|
|
1282
1188
|
MenuItemBody,
|
|
1283
1189
|
{
|
|
1284
1190
|
label,
|
|
@@ -1296,13 +1202,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1296
1202
|
);
|
|
1297
1203
|
const rowClassName = menuItemClassName({ size, selected, className });
|
|
1298
1204
|
if (!useContext4(MenuContext)) {
|
|
1299
|
-
return /* @__PURE__ */
|
|
1205
|
+
return /* @__PURE__ */ jsx18("button", { type: "button", className: rowClassName, ...props, children: body });
|
|
1300
1206
|
}
|
|
1301
|
-
return /* @__PURE__ */
|
|
1207
|
+
return /* @__PURE__ */ jsx18(
|
|
1302
1208
|
BaseMenu.Item,
|
|
1303
1209
|
{
|
|
1304
1210
|
nativeButton: true,
|
|
1305
|
-
render: /* @__PURE__ */
|
|
1211
|
+
render: /* @__PURE__ */ jsx18("button", { type: "button" }),
|
|
1306
1212
|
className: rowClassName,
|
|
1307
1213
|
...props,
|
|
1308
1214
|
children: body
|
|
@@ -1310,34 +1216,275 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1310
1216
|
);
|
|
1311
1217
|
}
|
|
1312
1218
|
function EnterHint({ target }) {
|
|
1313
|
-
return /* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
target && /* @__PURE__ */
|
|
1219
|
+
return /* @__PURE__ */ jsxs11("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
|
|
1220
|
+
/* @__PURE__ */ jsx18(Kbd, { children: "\u21A9 Enter" }),
|
|
1221
|
+
target && /* @__PURE__ */ jsx18("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider leaf:font-mono leaf:text-small leaf:tracking-wider", children: target })
|
|
1316
1222
|
] });
|
|
1317
1223
|
}
|
|
1318
1224
|
function MenuSection({ label, children, className }) {
|
|
1319
1225
|
const inMenu = useContext4(MenuContext) !== null;
|
|
1320
|
-
const heading = /* @__PURE__ */
|
|
1226
|
+
const heading = /* @__PURE__ */ jsx18("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx18(SectionLabel, { tone: "secondary", children: label }) });
|
|
1321
1227
|
if (!inMenu) {
|
|
1322
|
-
return /* @__PURE__ */
|
|
1228
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-0.5", children: [
|
|
1323
1229
|
heading,
|
|
1324
1230
|
children
|
|
1325
1231
|
] });
|
|
1326
1232
|
}
|
|
1327
|
-
return /* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1233
|
+
return /* @__PURE__ */ jsxs11(BaseMenu.Group, { className: "flex flex-col gap-0.5", children: [
|
|
1234
|
+
/* @__PURE__ */ jsx18(BaseMenu.GroupLabel, { render: heading }),
|
|
1329
1235
|
children
|
|
1330
1236
|
] });
|
|
1331
1237
|
}
|
|
1332
1238
|
function MenuSeparator() {
|
|
1333
|
-
return /* @__PURE__ */
|
|
1239
|
+
return /* @__PURE__ */ jsx18(Divider, { className: "my-1" });
|
|
1334
1240
|
}
|
|
1335
1241
|
function MenuRow({ children, className }) {
|
|
1336
|
-
return /* @__PURE__ */
|
|
1242
|
+
return /* @__PURE__ */ jsx18("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
// src/BlockHandle.tsx
|
|
1246
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1247
|
+
function readId(element) {
|
|
1248
|
+
const own = element.getAttribute("data-block-id") ?? element.querySelector("[data-block-id]")?.getAttribute("data-block-id");
|
|
1249
|
+
return own || void 0;
|
|
1250
|
+
}
|
|
1251
|
+
function blockAtY(blocks, y) {
|
|
1252
|
+
let found = null;
|
|
1253
|
+
for (const block of blocks) {
|
|
1254
|
+
if (block.element.getBoundingClientRect().top > y) break;
|
|
1255
|
+
found = block;
|
|
1256
|
+
}
|
|
1257
|
+
return found ?? blocks[0] ?? null;
|
|
1258
|
+
}
|
|
1259
|
+
function readingBlocks(root) {
|
|
1260
|
+
if (!root) return [];
|
|
1261
|
+
return Array.from(root.children).filter((el) => el instanceof HTMLElement).map((element) => ({ id: readId(element), element })).filter((b) => b.id !== void 0);
|
|
1262
|
+
}
|
|
1263
|
+
var HANDLE = 24;
|
|
1264
|
+
function firstLineOffset(element) {
|
|
1265
|
+
const text = element.querySelector("p, h1, h2, h3, pre, li") ?? element;
|
|
1266
|
+
const line = parseFloat(getComputedStyle(text).lineHeight);
|
|
1267
|
+
if (!Number.isFinite(line)) return 0;
|
|
1268
|
+
const inset = text === element ? 0 : text.getBoundingClientRect().top - element.getBoundingClientRect().top;
|
|
1269
|
+
return inset + (line - HANDLE) / 2;
|
|
1270
|
+
}
|
|
1271
|
+
function BlockHandle({ actions, editing, children, className }) {
|
|
1272
|
+
const frame = useRef3(null);
|
|
1273
|
+
const content = useRef3(null);
|
|
1274
|
+
const [block, setBlock] = useState2(null);
|
|
1275
|
+
const [top, setTop] = useState2(0);
|
|
1276
|
+
const [open, setOpen] = useState2(false);
|
|
1277
|
+
const follow = useCallback(
|
|
1278
|
+
(y) => {
|
|
1279
|
+
if (!content.current || !frame.current) return;
|
|
1280
|
+
const found = editing ? editing.find(y) : blockAtY(readingBlocks(content.current.firstElementChild), y);
|
|
1281
|
+
setBlock(found);
|
|
1282
|
+
if (found) setTop(found.element.getBoundingClientRect().top - frame.current.getBoundingClientRect().top + firstLineOffset(found.element));
|
|
1283
|
+
},
|
|
1284
|
+
[editing]
|
|
1285
|
+
);
|
|
1286
|
+
useEffect2(() => {
|
|
1287
|
+
if (!editing) return;
|
|
1288
|
+
return editing.onChange(() => {
|
|
1289
|
+
if (!open) setBlock(null);
|
|
1290
|
+
});
|
|
1291
|
+
}, [editing, open]);
|
|
1292
|
+
const rows = editing && block ? editing.rows(block) : null;
|
|
1293
|
+
const own = actions && block ? actions(block) : null;
|
|
1294
|
+
const dragging = useRef3(false);
|
|
1295
|
+
const [line, setLine] = useState2(null);
|
|
1296
|
+
const inGutter = (e) => dragging.current && !!editing && !!content.current && !content.current.contains(e.target);
|
|
1297
|
+
const landing = (y) => {
|
|
1298
|
+
const target = editing?.find(y);
|
|
1299
|
+
if (!target || !frame.current) return null;
|
|
1300
|
+
const box = target.element.getBoundingClientRect();
|
|
1301
|
+
const after = y > box.top + box.height / 2;
|
|
1302
|
+
const neighbour = (after ? target.element.nextElementSibling : target.element.previousElementSibling)?.getBoundingClientRect();
|
|
1303
|
+
const edge = after ? neighbour ? (box.bottom + neighbour.top) / 2 : box.bottom : neighbour ? (neighbour.bottom + box.top) / 2 : box.top;
|
|
1304
|
+
return { target, after, top: edge - frame.current.getBoundingClientRect().top };
|
|
1305
|
+
};
|
|
1306
|
+
const endDrag = () => {
|
|
1307
|
+
dragging.current = false;
|
|
1308
|
+
setLine(null);
|
|
1309
|
+
editing?.endDrag();
|
|
1310
|
+
};
|
|
1311
|
+
return /* @__PURE__ */ jsxs12(
|
|
1312
|
+
"div",
|
|
1313
|
+
{
|
|
1314
|
+
ref: frame,
|
|
1315
|
+
className: cn("relative", className),
|
|
1316
|
+
onMouseMove: (e) => {
|
|
1317
|
+
if (!open) follow(e.clientY);
|
|
1318
|
+
},
|
|
1319
|
+
onMouseLeave: () => {
|
|
1320
|
+
if (!open) setBlock(null);
|
|
1321
|
+
},
|
|
1322
|
+
onDragOver: (e) => {
|
|
1323
|
+
if (!inGutter(e)) return setLine(null);
|
|
1324
|
+
e.preventDefault();
|
|
1325
|
+
setLine(landing(e.clientY)?.top ?? null);
|
|
1326
|
+
},
|
|
1327
|
+
onDrop: (e) => {
|
|
1328
|
+
if (inGutter(e)) {
|
|
1329
|
+
e.preventDefault();
|
|
1330
|
+
const at = landing(e.clientY);
|
|
1331
|
+
if (at) editing?.drop(at.target, at.after);
|
|
1332
|
+
}
|
|
1333
|
+
endDrag();
|
|
1334
|
+
},
|
|
1335
|
+
onDragLeave: (e) => {
|
|
1336
|
+
if (!frame.current?.contains(e.relatedTarget)) setLine(null);
|
|
1337
|
+
},
|
|
1338
|
+
children: [
|
|
1339
|
+
/* @__PURE__ */ jsx19("div", { ref: content, children }),
|
|
1340
|
+
/* @__PURE__ */ jsx19("div", { "aria-hidden": true, className: "absolute inset-y-0 -left-7 w-7" }),
|
|
1341
|
+
line !== null && /* @__PURE__ */ jsx19("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-x-0 h-px bg-accent-primary", style: { top: line } }),
|
|
1342
|
+
block && (rows || own) && // The top is the block's, measured: it depends on the document, not on a size of ours.
|
|
1343
|
+
/* @__PURE__ */ jsx19("div", { className: cn("absolute -left-7", rows && "cursor-grab active:cursor-grabbing"), style: { top }, children: /* @__PURE__ */ jsxs12(
|
|
1344
|
+
Menu,
|
|
1345
|
+
{
|
|
1346
|
+
open,
|
|
1347
|
+
onOpenChange: setOpen,
|
|
1348
|
+
trigger: /* @__PURE__ */ jsx19(
|
|
1349
|
+
IconButton,
|
|
1350
|
+
{
|
|
1351
|
+
"aria-label": "Block menu",
|
|
1352
|
+
tooltip: rows ? "Drag to move, click for the menu" : "Menu",
|
|
1353
|
+
draggable: !!rows,
|
|
1354
|
+
onMouseDown: (e) => e.preventBaseUIHandler(),
|
|
1355
|
+
onClick: (e) => {
|
|
1356
|
+
e.preventBaseUIHandler();
|
|
1357
|
+
setOpen((was) => !was);
|
|
1358
|
+
},
|
|
1359
|
+
onDragStart: (e) => {
|
|
1360
|
+
if (!editing || !rows) return;
|
|
1361
|
+
setOpen(false);
|
|
1362
|
+
dragging.current = true;
|
|
1363
|
+
editing.startDrag(block, e.nativeEvent);
|
|
1364
|
+
},
|
|
1365
|
+
onDragEnd: () => {
|
|
1366
|
+
endDrag();
|
|
1367
|
+
setBlock(null);
|
|
1368
|
+
},
|
|
1369
|
+
children: /* @__PURE__ */ jsx19(IconGripVertical, { size: 16, stroke: 1.5 })
|
|
1370
|
+
}
|
|
1371
|
+
),
|
|
1372
|
+
children: [
|
|
1373
|
+
rows,
|
|
1374
|
+
rows && own && /* @__PURE__ */ jsx19(MenuSeparator, {}),
|
|
1375
|
+
own
|
|
1376
|
+
]
|
|
1377
|
+
}
|
|
1378
|
+
) })
|
|
1379
|
+
]
|
|
1380
|
+
}
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// src/Checkbox.tsx
|
|
1385
|
+
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
|
|
1386
|
+
import { Field as BaseField } from "@base-ui/react/field";
|
|
1387
|
+
import { IconCheck } from "@tabler/icons-react";
|
|
1388
|
+
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1389
|
+
function squareClasses(checked, disabled, interactive, className) {
|
|
1390
|
+
return cn(
|
|
1391
|
+
"inline-flex items-center justify-center size-4 shrink-0 rounded-sm border transition-colors",
|
|
1392
|
+
checked ? "bg-accent-primary border-accent-primary text-text-inverse" : "bg-transparent border-border-strong hover:border-text-muted",
|
|
1393
|
+
disabled && "opacity-50 pointer-events-none",
|
|
1394
|
+
interactive ? "cursor-pointer" : "pointer-events-none",
|
|
1395
|
+
className
|
|
1396
|
+
);
|
|
1337
1397
|
}
|
|
1398
|
+
var tickClasses = (checked) => cn("flex", !checked && "invisible");
|
|
1399
|
+
var WORDS_CLASSES = "text-body-2 text-text-primary";
|
|
1400
|
+
var ROW_CLASSES = "flex shrink-0 items-center gap-3 h-10 px-3 rounded-lg transition-colors";
|
|
1401
|
+
function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row, leading, className, ...aria }) {
|
|
1402
|
+
const formBusy = useFormBusy();
|
|
1403
|
+
const disabled = ownDisabled || formBusy;
|
|
1404
|
+
if (!onChange) {
|
|
1405
|
+
const picture = /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx20("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx20(IconCheck, { size: 12, stroke: 3 }) }) });
|
|
1406
|
+
if (label === void 0) return picture;
|
|
1407
|
+
return /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2", children: [
|
|
1408
|
+
picture,
|
|
1409
|
+
/* @__PURE__ */ jsx20("span", { className: WORDS_CLASSES, children: label })
|
|
1410
|
+
] });
|
|
1411
|
+
}
|
|
1412
|
+
const box = /* @__PURE__ */ jsx20(
|
|
1413
|
+
BaseCheckbox.Root,
|
|
1414
|
+
{
|
|
1415
|
+
checked,
|
|
1416
|
+
disabled,
|
|
1417
|
+
"aria-label": aria["aria-label"],
|
|
1418
|
+
"aria-required": aria["aria-required"],
|
|
1419
|
+
onCheckedChange: (next) => onChange(next),
|
|
1420
|
+
onClick: (e) => e.stopPropagation(),
|
|
1421
|
+
className: (state) => squareClasses(state.checked, state.disabled, true, className),
|
|
1422
|
+
children: /* @__PURE__ */ jsx20(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx20(IconCheck, { size: 12, stroke: 3 }) })
|
|
1423
|
+
}
|
|
1424
|
+
);
|
|
1425
|
+
if (label === void 0) return box;
|
|
1426
|
+
if (row) {
|
|
1427
|
+
return /* @__PURE__ */ jsx20(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs13(BaseField.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
|
|
1428
|
+
leading,
|
|
1429
|
+
/* @__PURE__ */ jsx20("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
|
|
1430
|
+
box
|
|
1431
|
+
] }) });
|
|
1432
|
+
}
|
|
1433
|
+
return /* @__PURE__ */ jsx20(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs13(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
|
|
1434
|
+
box,
|
|
1435
|
+
/* @__PURE__ */ jsx20("span", { className: WORDS_CLASSES, children: label })
|
|
1436
|
+
] }) });
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// src/Chip.tsx
|
|
1440
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1441
|
+
var typeStyles = {
|
|
1442
|
+
neutral: "bg-bg-inset text-text-primary",
|
|
1443
|
+
brand: "bg-accent-muted text-accent-text signal:border signal:border-accent-outline",
|
|
1444
|
+
info: "bg-info-muted text-info-default signal:border signal:border-info-outline",
|
|
1445
|
+
warning: "bg-warning-muted text-warning-default signal:border signal:border-warning-outline signal:shadow-glow-warning",
|
|
1446
|
+
success: "bg-success-muted text-success-default signal:border signal:border-success-outline",
|
|
1447
|
+
error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
|
|
1448
|
+
};
|
|
1449
|
+
function Chip({ type = "neutral", label, leadingIcon, trailingIcon, href, onClick, className }) {
|
|
1450
|
+
const classes = cn("inline-flex min-w-0 items-center justify-center gap-1.5 rounded-full max-h-[20px] px-2 py-1", typeStyles[type], className);
|
|
1451
|
+
const inside = /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
1452
|
+
leadingIcon && /* @__PURE__ */ jsx21("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
|
|
1453
|
+
label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
|
|
1454
|
+
// of growing past it — Ship's project chip on an issue row
|
|
1455
|
+
// (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
|
|
1456
|
+
// `truncate`, because `truncate` is `overflow: hidden` on both axes and
|
|
1457
|
+
// the label's line box (11px under Signal) is tighter than its glyphs —
|
|
1458
|
+
// the screenshot diff caught every descender cut off. `clip` is the
|
|
1459
|
+
// one overflow that leaves the other axis visible. A chip with no cap
|
|
1460
|
+
// draws exactly as before.
|
|
1461
|
+
/* @__PURE__ */ jsx21("span", { className: cn("min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide", CHIP_TEXT_CLASSES), children: label }),
|
|
1462
|
+
trailingIcon && /* @__PURE__ */ jsx21("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
1463
|
+
] });
|
|
1464
|
+
if (href) return /* @__PURE__ */ jsx21("a", { href, onClick, className: cn("relative", classes), children: inside });
|
|
1465
|
+
return /* @__PURE__ */ jsx21("div", { className: classes, children: inside });
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
// src/CommandPalette.tsx
|
|
1469
|
+
import {
|
|
1470
|
+
createContext as createContext5,
|
|
1471
|
+
useContext as useContext5,
|
|
1472
|
+
useEffect as useEffect3,
|
|
1473
|
+
useLayoutEffect as useLayoutEffect3,
|
|
1474
|
+
useMemo as useMemo2,
|
|
1475
|
+
useRef as useRef5,
|
|
1476
|
+
useState as useState4
|
|
1477
|
+
} from "react";
|
|
1478
|
+
import { Dialog as Dialog2 } from "@base-ui/react/dialog";
|
|
1479
|
+
import { Autocomplete } from "@base-ui/react/autocomplete";
|
|
1480
|
+
import { IconLoader2 as IconLoader22, IconSearch } from "@tabler/icons-react";
|
|
1338
1481
|
|
|
1339
1482
|
// src/ChipInput.tsx
|
|
1340
|
-
import {
|
|
1483
|
+
import { useMemo, useState as useState3 } from "react";
|
|
1484
|
+
import { Button as BaseButton4 } from "@base-ui/react/button";
|
|
1485
|
+
import { Combobox } from "@base-ui/react/combobox";
|
|
1486
|
+
import { IconX as IconX4 } from "@tabler/icons-react";
|
|
1487
|
+
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1341
1488
|
var CHIP_BOX = (
|
|
1342
1489
|
// Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
|
|
1343
1490
|
// rounded-sm corners — never a forced circle — and the chip's corner
|
|
@@ -1348,10 +1495,10 @@ var CHIP_LABEL = "text-caption font-medium text-text-primary";
|
|
|
1348
1495
|
var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary";
|
|
1349
1496
|
var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
|
|
1350
1497
|
function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
|
|
1351
|
-
return /* @__PURE__ */
|
|
1352
|
-
leading && /* @__PURE__ */
|
|
1353
|
-
/* @__PURE__ */
|
|
1354
|
-
onRemove && /* @__PURE__ */
|
|
1498
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
|
|
1499
|
+
leading && /* @__PURE__ */ jsx22("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1500
|
+
/* @__PURE__ */ jsx22("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
|
|
1501
|
+
onRemove && /* @__PURE__ */ jsx22(
|
|
1355
1502
|
BaseButton4,
|
|
1356
1503
|
{
|
|
1357
1504
|
type: "button",
|
|
@@ -1361,7 +1508,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
|
|
|
1361
1508
|
},
|
|
1362
1509
|
className: cn(CHIP_REMOVE, truncate && "shrink-0"),
|
|
1363
1510
|
"aria-label": removeLabel ?? `Remove ${label}`,
|
|
1364
|
-
children: /* @__PURE__ */
|
|
1511
|
+
children: /* @__PURE__ */ jsx22(IconX4, { size: 10, stroke: 1.5 })
|
|
1365
1512
|
}
|
|
1366
1513
|
)
|
|
1367
1514
|
] });
|
|
@@ -1377,8 +1524,8 @@ function ChipInput({
|
|
|
1377
1524
|
rowLeading,
|
|
1378
1525
|
...aria
|
|
1379
1526
|
}) {
|
|
1380
|
-
const [query, setQuery] =
|
|
1381
|
-
const [box, setBox] =
|
|
1527
|
+
const [query, setQuery] = useState3("");
|
|
1528
|
+
const [box, setBox] = useState3(null);
|
|
1382
1529
|
const available = useMemo(() => {
|
|
1383
1530
|
const chosen = new Set(value.map((o) => o.id));
|
|
1384
1531
|
const excluded = new Set(excludeIds);
|
|
@@ -1414,7 +1561,7 @@ function ChipInput({
|
|
|
1414
1561
|
setQuery("");
|
|
1415
1562
|
}
|
|
1416
1563
|
}
|
|
1417
|
-
return /* @__PURE__ */
|
|
1564
|
+
return /* @__PURE__ */ jsxs15(
|
|
1418
1565
|
Combobox.Root,
|
|
1419
1566
|
{
|
|
1420
1567
|
multiple: true,
|
|
@@ -1431,13 +1578,13 @@ function ChipInput({
|
|
|
1431
1578
|
filter,
|
|
1432
1579
|
itemToStringLabel: (option) => option.label,
|
|
1433
1580
|
children: [
|
|
1434
|
-
/* @__PURE__ */
|
|
1435
|
-
value.map((option) => /* @__PURE__ */
|
|
1436
|
-
chipLeading && /* @__PURE__ */
|
|
1437
|
-
/* @__PURE__ */
|
|
1438
|
-
/* @__PURE__ */
|
|
1581
|
+
/* @__PURE__ */ jsxs15(Combobox.Chips, { ref: setBox, className: cn(FIELD_SHELL_CLASSES, "focus-within:border-border-focus focus-within:hover:border-border-focus group-hover/field:focus-within:border-border-focus px-3 py-1.5 flex flex-wrap items-center gap-1.5 min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring"), children: [
|
|
1582
|
+
value.map((option) => /* @__PURE__ */ jsxs15(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
|
|
1583
|
+
chipLeading && /* @__PURE__ */ jsx22("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
|
|
1584
|
+
/* @__PURE__ */ jsx22("span", { className: CHIP_LABEL, children: option.label }),
|
|
1585
|
+
/* @__PURE__ */ jsx22(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx22(IconX4, { size: 10, stroke: 1.5 }) })
|
|
1439
1586
|
] }, option.id)),
|
|
1440
|
-
/* @__PURE__ */
|
|
1587
|
+
/* @__PURE__ */ jsx22(
|
|
1441
1588
|
Combobox.Input,
|
|
1442
1589
|
{
|
|
1443
1590
|
autoFocus,
|
|
@@ -1449,18 +1596,18 @@ function ChipInput({
|
|
|
1449
1596
|
}
|
|
1450
1597
|
)
|
|
1451
1598
|
] }),
|
|
1452
|
-
/* @__PURE__ */
|
|
1599
|
+
/* @__PURE__ */ jsx22(Combobox.Portal, { children: /* @__PURE__ */ jsx22(
|
|
1453
1600
|
Combobox.Positioner,
|
|
1454
1601
|
{
|
|
1455
1602
|
anchor: box,
|
|
1456
1603
|
sideOffset: GAP3,
|
|
1457
1604
|
collisionPadding: VIEWPORT_PAD3,
|
|
1458
1605
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1459
|
-
children: /* @__PURE__ */
|
|
1606
|
+
children: /* @__PURE__ */ jsx22(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx22(MenuPanel, {}), children: /* @__PURE__ */ jsx22(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx22(Combobox.List, { children: (option) => /* @__PURE__ */ jsx22(
|
|
1460
1607
|
Combobox.Item,
|
|
1461
1608
|
{
|
|
1462
1609
|
value: option,
|
|
1463
|
-
render: /* @__PURE__ */
|
|
1610
|
+
render: /* @__PURE__ */ jsx22(
|
|
1464
1611
|
MenuItem,
|
|
1465
1612
|
{
|
|
1466
1613
|
size: "tall",
|
|
@@ -1483,22 +1630,22 @@ var VIEWPORT_PAD3 = 8;
|
|
|
1483
1630
|
|
|
1484
1631
|
// src/EmptyState.tsx
|
|
1485
1632
|
import { IconMessage2 } from "@tabler/icons-react";
|
|
1486
|
-
import { jsx as
|
|
1633
|
+
import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1487
1634
|
function EmptyState({ icon, message, scope = "page", action, className }) {
|
|
1488
1635
|
if (scope === "section") {
|
|
1489
|
-
return /* @__PURE__ */
|
|
1636
|
+
return /* @__PURE__ */ jsx23("p", { className: cn("text-caption text-text-muted", className), children: message });
|
|
1490
1637
|
}
|
|
1491
|
-
return /* @__PURE__ */
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
action && /* @__PURE__ */
|
|
1638
|
+
return /* @__PURE__ */ jsxs16("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1639
|
+
/* @__PURE__ */ jsx23("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx23(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1640
|
+
/* @__PURE__ */ jsx23("p", { className: "text-body-2 text-text-secondary text-center", children: message }),
|
|
1641
|
+
action && /* @__PURE__ */ jsx23(Button, { variant: "outlined", className: "mt-2", onClick: action.onClick, children: action.label })
|
|
1495
1642
|
] });
|
|
1496
1643
|
}
|
|
1497
1644
|
|
|
1498
1645
|
// src/Field.tsx
|
|
1499
1646
|
import { cloneElement, isValidElement } from "react";
|
|
1500
1647
|
import { Field as BaseField2 } from "@base-ui/react/field";
|
|
1501
|
-
import { jsx as
|
|
1648
|
+
import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1502
1649
|
var LINE_STYLES = {
|
|
1503
1650
|
helper: "text-caption text-text-muted",
|
|
1504
1651
|
warning: "text-caption text-warning-default",
|
|
@@ -1512,27 +1659,27 @@ function Field({ label, required = false, helper, error, children }) {
|
|
|
1512
1659
|
// `group/field`: the label, the box and the line under it are one thing under the pointer —
|
|
1513
1660
|
// anywhere in it strengthens the box's border, as hovering the box does (Katerina, 28 September).
|
|
1514
1661
|
// Before, the 8px between the label and the box was a gap where the border went out again.
|
|
1515
|
-
/* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1662
|
+
/* @__PURE__ */ jsxs17(BaseField2.Root, { invalid: !!error, className: "group/field flex flex-col gap-2", children: [
|
|
1663
|
+
/* @__PURE__ */ jsxs17(BaseField2.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1517
1664
|
label,
|
|
1518
|
-
required && /* @__PURE__ */
|
|
1665
|
+
required && /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1519
1666
|
] }),
|
|
1520
|
-
/* @__PURE__ */
|
|
1667
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-1.5", children: [
|
|
1521
1668
|
control,
|
|
1522
|
-
error != null ? /* @__PURE__ */
|
|
1669
|
+
error != null ? /* @__PURE__ */ jsx24(BaseField2.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx24(BaseField2.Description, { className: LINE_STYLES.helper, children: helper }) : null
|
|
1523
1670
|
] })
|
|
1524
1671
|
] })
|
|
1525
1672
|
);
|
|
1526
1673
|
}
|
|
1527
1674
|
function FieldLine({ tone = "helper", children, className }) {
|
|
1528
|
-
return /* @__PURE__ */
|
|
1675
|
+
return /* @__PURE__ */ jsx24("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
|
|
1529
1676
|
}
|
|
1530
1677
|
|
|
1531
1678
|
// src/Form.tsx
|
|
1532
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
1679
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef4 } from "react";
|
|
1533
1680
|
import { Fieldset } from "@base-ui/react/fieldset";
|
|
1534
1681
|
import { Form as BaseForm } from "@base-ui/react/form";
|
|
1535
|
-
import { jsx as
|
|
1682
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
1536
1683
|
var FIELDS_CLASSES = "flex flex-col gap-6";
|
|
1537
1684
|
var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
|
|
1538
1685
|
var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
@@ -1550,12 +1697,12 @@ function firstInvalid(form) {
|
|
|
1550
1697
|
function Form({ onSubmit, busy: ownBusy = false, enterSends = true, layout = "fields", className, children, ...props }) {
|
|
1551
1698
|
const outerBusy = useFormBusy();
|
|
1552
1699
|
const busy = ownBusy || outerBusy;
|
|
1553
|
-
const form =
|
|
1554
|
-
const busyNow =
|
|
1700
|
+
const form = useRef4(null);
|
|
1701
|
+
const busyNow = useRef4(busy);
|
|
1555
1702
|
busyNow.current = busy;
|
|
1556
|
-
const sender =
|
|
1557
|
-
const holding =
|
|
1558
|
-
const lastInside =
|
|
1703
|
+
const sender = useRef4(null);
|
|
1704
|
+
const holding = useRef4(false);
|
|
1705
|
+
const lastInside = useRef4(null);
|
|
1559
1706
|
useLayoutEffect2(() => {
|
|
1560
1707
|
const element = form.current;
|
|
1561
1708
|
if (!element) return;
|
|
@@ -1592,7 +1739,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, layout = "fi
|
|
|
1592
1739
|
const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
|
|
1593
1740
|
if (enterSends && oneLine) form.current?.requestSubmit();
|
|
1594
1741
|
};
|
|
1595
|
-
return /* @__PURE__ */
|
|
1742
|
+
return /* @__PURE__ */ jsx25(
|
|
1596
1743
|
BaseForm,
|
|
1597
1744
|
{
|
|
1598
1745
|
ref: form,
|
|
@@ -1615,29 +1762,29 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, layout = "fi
|
|
|
1615
1762
|
if (busyNow.current) return;
|
|
1616
1763
|
void onSubmit();
|
|
1617
1764
|
},
|
|
1618
|
-
children: /* @__PURE__ */
|
|
1765
|
+
children: /* @__PURE__ */ jsx25(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx25(FormBusyContext.Provider, { value: busy, children }) })
|
|
1619
1766
|
}
|
|
1620
1767
|
);
|
|
1621
1768
|
}
|
|
1622
1769
|
|
|
1623
1770
|
// src/Skeleton.tsx
|
|
1624
|
-
import { jsx as
|
|
1771
|
+
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1625
1772
|
function SkeletonBar({ className, style }) {
|
|
1626
|
-
return /* @__PURE__ */
|
|
1773
|
+
return /* @__PURE__ */ jsx26("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1627
1774
|
}
|
|
1628
1775
|
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1629
1776
|
function SkeletonRow({ barWidth = 130 }) {
|
|
1630
|
-
return /* @__PURE__ */
|
|
1631
|
-
/* @__PURE__ */
|
|
1632
|
-
/* @__PURE__ */
|
|
1777
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1778
|
+
/* @__PURE__ */ jsx26(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1779
|
+
/* @__PURE__ */ jsx26(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1633
1780
|
] });
|
|
1634
1781
|
}
|
|
1635
1782
|
function SkeletonList({ rows = 8, className }) {
|
|
1636
|
-
return /* @__PURE__ */
|
|
1783
|
+
return /* @__PURE__ */ jsx26("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx26(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
|
|
1637
1784
|
}
|
|
1638
1785
|
|
|
1639
1786
|
// src/CommandPalette.tsx
|
|
1640
|
-
import { Fragment as Fragment5, jsx as
|
|
1787
|
+
import { Fragment as Fragment5, jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1641
1788
|
var PaletteContext = createContext5(null);
|
|
1642
1789
|
function usePalette(part) {
|
|
1643
1790
|
const palette = useContext5(PaletteContext);
|
|
@@ -1652,8 +1799,8 @@ function firstControl(popup) {
|
|
|
1652
1799
|
return popup.querySelector("[data-command-palette-fields]")?.querySelector(CONTROL2) ?? null;
|
|
1653
1800
|
}
|
|
1654
1801
|
function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", children }) {
|
|
1655
|
-
const popupRef =
|
|
1656
|
-
|
|
1802
|
+
const popupRef = useRef5(null);
|
|
1803
|
+
useEffect3(() => {
|
|
1657
1804
|
if (!open) return;
|
|
1658
1805
|
const frame = requestAnimationFrame(() => {
|
|
1659
1806
|
const popup = popupRef.current;
|
|
@@ -1663,9 +1810,9 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1663
1810
|
return () => cancelAnimationFrame(frame);
|
|
1664
1811
|
});
|
|
1665
1812
|
const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
|
|
1666
|
-
return /* @__PURE__ */
|
|
1667
|
-
/* @__PURE__ */
|
|
1668
|
-
/* @__PURE__ */
|
|
1813
|
+
return /* @__PURE__ */ jsx27(Dialog2.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs19(Dialog2.Portal, { children: [
|
|
1814
|
+
/* @__PURE__ */ jsx27(Dialog2.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1815
|
+
/* @__PURE__ */ jsx27(Dialog2.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx27(
|
|
1669
1816
|
Dialog2.Popup,
|
|
1670
1817
|
{
|
|
1671
1818
|
ref: popupRef,
|
|
@@ -1675,13 +1822,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1675
1822
|
if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
|
|
1676
1823
|
},
|
|
1677
1824
|
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",
|
|
1678
|
-
children: /* @__PURE__ */
|
|
1825
|
+
children: /* @__PURE__ */ jsx27(PaletteContext.Provider, { value: context, children })
|
|
1679
1826
|
}
|
|
1680
1827
|
) })
|
|
1681
1828
|
] }) });
|
|
1682
1829
|
}
|
|
1683
1830
|
function LevelChip({ chip, onBack }) {
|
|
1684
|
-
return /* @__PURE__ */
|
|
1831
|
+
return /* @__PURE__ */ jsx27(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
|
|
1685
1832
|
}
|
|
1686
1833
|
function useBack(chip, popupRef) {
|
|
1687
1834
|
return () => {
|
|
@@ -1692,10 +1839,10 @@ function useBack(chip, popupRef) {
|
|
|
1692
1839
|
}
|
|
1693
1840
|
function Footer({ keys }) {
|
|
1694
1841
|
const { where } = usePalette("The footer");
|
|
1695
|
-
return /* @__PURE__ */
|
|
1696
|
-
/* @__PURE__ */
|
|
1697
|
-
keys.map(([key, word]) => /* @__PURE__ */
|
|
1698
|
-
/* @__PURE__ */
|
|
1842
|
+
return /* @__PURE__ */ jsxs19("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 leaf:font-mono leaf:text-small", children: [
|
|
1843
|
+
/* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 truncate", children: where }),
|
|
1844
|
+
keys.map(([key, word]) => /* @__PURE__ */ jsxs19("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
1845
|
+
/* @__PURE__ */ jsx27(Kbd, { children: key }),
|
|
1699
1846
|
" ",
|
|
1700
1847
|
word
|
|
1701
1848
|
] }, key))
|
|
@@ -1707,12 +1854,12 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1707
1854
|
const back = useBack(chip, popupRef);
|
|
1708
1855
|
const items = useMemo2(() => groups.filter((g) => g.rows.length > 0).map((g) => ({ value: g.label, items: g.rows })), [groups]);
|
|
1709
1856
|
const rows = items.flatMap((g) => g.items);
|
|
1710
|
-
const [litId, setLitId] =
|
|
1857
|
+
const [litId, setLitId] = useState4();
|
|
1711
1858
|
const lit = litId === void 0 ? void 0 : rows.find((r) => r.id === litId);
|
|
1712
|
-
const inputRef =
|
|
1713
|
-
const reported =
|
|
1714
|
-
const settled =
|
|
1715
|
-
const moved =
|
|
1859
|
+
const inputRef = useRef5(null);
|
|
1860
|
+
const reported = useRef5({});
|
|
1861
|
+
const settled = useRef5(null);
|
|
1862
|
+
const moved = useRef5(false);
|
|
1716
1863
|
useLayoutEffect3(() => {
|
|
1717
1864
|
const before = settled.current;
|
|
1718
1865
|
const now = reported.current;
|
|
@@ -1772,7 +1919,7 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1772
1919
|
...chip && query === "" ? [["Backspace", "back"]] : [],
|
|
1773
1920
|
["Esc", "close"]
|
|
1774
1921
|
];
|
|
1775
|
-
return /* @__PURE__ */
|
|
1922
|
+
return /* @__PURE__ */ jsxs19(
|
|
1776
1923
|
Autocomplete.Root,
|
|
1777
1924
|
{
|
|
1778
1925
|
items,
|
|
@@ -1795,10 +1942,10 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1795
1942
|
setLitId(id);
|
|
1796
1943
|
},
|
|
1797
1944
|
children: [
|
|
1798
|
-
/* @__PURE__ */
|
|
1799
|
-
/* @__PURE__ */
|
|
1800
|
-
chip && /* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1945
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1946
|
+
/* @__PURE__ */ jsx27(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
|
|
1947
|
+
chip && /* @__PURE__ */ jsx27(LevelChip, { chip, onBack: back }),
|
|
1948
|
+
/* @__PURE__ */ jsx27(
|
|
1802
1949
|
Autocomplete.Input,
|
|
1803
1950
|
{
|
|
1804
1951
|
ref: inputRef,
|
|
@@ -1810,43 +1957,43 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1810
1957
|
}
|
|
1811
1958
|
)
|
|
1812
1959
|
] }),
|
|
1813
|
-
/* @__PURE__ */
|
|
1814
|
-
children != null && /* @__PURE__ */
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
/* @__PURE__ */
|
|
1960
|
+
/* @__PURE__ */ jsxs19(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
|
|
1961
|
+
children != null && /* @__PURE__ */ jsx27("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
|
|
1962
|
+
/* @__PURE__ */ jsx27(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs19(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
|
|
1963
|
+
/* @__PURE__ */ jsx27(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx27(SectionLabel, { tone: "secondary", children: group.value }) }),
|
|
1964
|
+
/* @__PURE__ */ jsx27(Autocomplete.Collection, { children: (row) => (
|
|
1818
1965
|
/* The menu row, as the list's own option — the way Select
|
|
1819
1966
|
puts it on `Select.Item`. One row, two parts. */
|
|
1820
|
-
/* @__PURE__ */
|
|
1967
|
+
/* @__PURE__ */ jsx27(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx27(
|
|
1821
1968
|
MenuItemBody,
|
|
1822
1969
|
{
|
|
1823
1970
|
size: "tall",
|
|
1824
1971
|
label: row.label,
|
|
1825
1972
|
description: row.description,
|
|
1826
|
-
leading: /* @__PURE__ */
|
|
1973
|
+
leading: /* @__PURE__ */ jsx27(RowLeading, { row }),
|
|
1827
1974
|
submenu: !!row.onGoIn,
|
|
1828
|
-
hint: row.onGoIn ? /* @__PURE__ */
|
|
1975
|
+
hint: row.onGoIn ? /* @__PURE__ */ jsx27(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx27(EnterHint, {})
|
|
1829
1976
|
}
|
|
1830
1977
|
) }, row.id)
|
|
1831
1978
|
) })
|
|
1832
1979
|
] }, group.value) }),
|
|
1833
|
-
/* @__PURE__ */
|
|
1834
|
-
/* @__PURE__ */
|
|
1835
|
-
/* @__PURE__ */
|
|
1980
|
+
/* @__PURE__ */ jsx27(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs19(Fragment5, { children: [
|
|
1981
|
+
/* @__PURE__ */ jsx27(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
|
|
1982
|
+
/* @__PURE__ */ jsx27("span", { className: "text-caption text-text-muted", children: pending })
|
|
1836
1983
|
] }) }),
|
|
1837
|
-
notes.map((note) => /* @__PURE__ */
|
|
1838
|
-
/* @__PURE__ */
|
|
1984
|
+
notes.map((note) => /* @__PURE__ */ jsx27("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx27(FieldLine, { children: note }) }, note)),
|
|
1985
|
+
/* @__PURE__ */ jsx27(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx27(EmptyState, { scope: "section", message: empty }) })
|
|
1839
1986
|
] }),
|
|
1840
|
-
/* @__PURE__ */
|
|
1987
|
+
/* @__PURE__ */ jsx27(Footer, { keys })
|
|
1841
1988
|
]
|
|
1842
1989
|
}
|
|
1843
1990
|
);
|
|
1844
1991
|
}
|
|
1845
1992
|
function RowLeading({ row }) {
|
|
1846
1993
|
if (row.icon != null) {
|
|
1847
|
-
return /* @__PURE__ */
|
|
1994
|
+
return /* @__PURE__ */ jsx27("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
|
|
1848
1995
|
}
|
|
1849
|
-
return /* @__PURE__ */
|
|
1996
|
+
return /* @__PURE__ */ jsx27("span", { className: "flex size-8 items-center justify-center", children: row.leading });
|
|
1850
1997
|
}
|
|
1851
1998
|
var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1852
1999
|
function isTextField(el) {
|
|
@@ -1856,9 +2003,9 @@ function isTextField(el) {
|
|
|
1856
2003
|
function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, working, error, children }) {
|
|
1857
2004
|
const { modKey, popupRef } = usePalette("CommandPaletteForm");
|
|
1858
2005
|
const back = useBack(chip, popupRef);
|
|
1859
|
-
const frameRef =
|
|
2006
|
+
const frameRef = useRef5(null);
|
|
1860
2007
|
const busy = !!working;
|
|
1861
|
-
const busyRef =
|
|
2008
|
+
const busyRef = useRef5(busy);
|
|
1862
2009
|
busyRef.current = busy;
|
|
1863
2010
|
const firstInvalid2 = () => frameRef.current?.querySelector("[data-invalid]")?.querySelector(CONTROL2) ?? null;
|
|
1864
2011
|
const submit = () => {
|
|
@@ -1874,7 +2021,7 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
|
|
|
1874
2021
|
if (isTextField(el)) return el.value === "";
|
|
1875
2022
|
return ![...frame.querySelectorAll("input, textarea")].some(isTextField);
|
|
1876
2023
|
};
|
|
1877
|
-
const [backNamed, setBackNamed] =
|
|
2024
|
+
const [backNamed, setBackNamed] = useState4(false);
|
|
1878
2025
|
const measure = () => setBackNamed(backWorksFrom(document.activeElement));
|
|
1879
2026
|
useLayoutEffect3(measure);
|
|
1880
2027
|
const onKeyDown = (e) => {
|
|
@@ -1888,65 +2035,65 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
|
|
|
1888
2035
|
...backNamed ? [["Backspace", "back"]] : [],
|
|
1889
2036
|
["Esc", "close"]
|
|
1890
2037
|
];
|
|
1891
|
-
return /* @__PURE__ */
|
|
1892
|
-
/* @__PURE__ */
|
|
1893
|
-
icon != null && /* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
2038
|
+
return /* @__PURE__ */ jsxs19("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
|
|
2039
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
2040
|
+
icon != null && /* @__PURE__ */ jsx27("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
|
|
2041
|
+
/* @__PURE__ */ jsx27(LevelChip, { chip, onBack: back })
|
|
1895
2042
|
] }),
|
|
1896
|
-
/* @__PURE__ */
|
|
1897
|
-
/* @__PURE__ */
|
|
1898
|
-
/* @__PURE__ */
|
|
1899
|
-
/* @__PURE__ */
|
|
1900
|
-
/* @__PURE__ */
|
|
2043
|
+
/* @__PURE__ */ jsxs19(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, layout: "free", className: "flex min-h-0 flex-col", children: [
|
|
2044
|
+
/* @__PURE__ */ jsx27(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx27("div", { className: FIELDS_CLASSES, children }) }),
|
|
2045
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
|
|
2046
|
+
/* @__PURE__ */ jsx27("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx27(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx27(FieldLine, { tone: "error", children: error }) : null }),
|
|
2047
|
+
/* @__PURE__ */ jsx27(
|
|
1901
2048
|
Button,
|
|
1902
2049
|
{
|
|
1903
2050
|
type: "submit",
|
|
1904
2051
|
variant: "primary",
|
|
1905
2052
|
disabled: busy,
|
|
1906
2053
|
disabledReason: busy ? void 0 : submitWaits,
|
|
1907
|
-
leadingIcon: busy ? /* @__PURE__ */
|
|
2054
|
+
leadingIcon: busy ? /* @__PURE__ */ jsx27(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
|
|
1908
2055
|
children: working ? working.button : submitLabel
|
|
1909
2056
|
}
|
|
1910
2057
|
)
|
|
1911
2058
|
] })
|
|
1912
2059
|
] }),
|
|
1913
|
-
/* @__PURE__ */
|
|
2060
|
+
/* @__PURE__ */ jsx27(Footer, { keys })
|
|
1914
2061
|
] });
|
|
1915
2062
|
}
|
|
1916
2063
|
var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
|
|
1917
2064
|
function CommandPaletteWorking({ children, bars = 2 }) {
|
|
1918
|
-
return /* @__PURE__ */
|
|
1919
|
-
/* @__PURE__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
2065
|
+
return /* @__PURE__ */ jsxs19("div", { role: "status", className: "flex flex-col gap-2", children: [
|
|
2066
|
+
/* @__PURE__ */ jsxs19("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
|
|
2067
|
+
/* @__PURE__ */ jsx27(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
|
|
1921
2068
|
children
|
|
1922
2069
|
] }),
|
|
1923
|
-
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */
|
|
2070
|
+
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx27(SkeletonBar, { className: cn("h-3", width) }, width))
|
|
1924
2071
|
] });
|
|
1925
2072
|
}
|
|
1926
2073
|
function CommandPaletteAnswer({ children, note }) {
|
|
1927
2074
|
const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
|
|
1928
|
-
return /* @__PURE__ */
|
|
1929
|
-
paragraphs.map((paragraph, i) => /* @__PURE__ */
|
|
1930
|
-
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */
|
|
2075
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", children: [
|
|
2076
|
+
paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx27("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
|
|
2077
|
+
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx27("sup", { className: "ml-0.5 font-mono text-small text-accent-text", children: part.slice(1, -1) }, j) : part
|
|
1931
2078
|
) }, i)),
|
|
1932
|
-
note && /* @__PURE__ */
|
|
2079
|
+
note && /* @__PURE__ */ jsx27(FieldLine, { children: note })
|
|
1933
2080
|
] });
|
|
1934
2081
|
}
|
|
1935
2082
|
function CommandPaletteQuote({ children }) {
|
|
1936
|
-
return /* @__PURE__ */
|
|
2083
|
+
return /* @__PURE__ */ jsx27("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
|
|
1937
2084
|
}
|
|
1938
2085
|
function CommandPaletteProposal({ source, mark, children }) {
|
|
1939
|
-
return /* @__PURE__ */
|
|
1940
|
-
/* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ jsxs19(Card, { fill: "surface", className: "flex flex-col gap-1 p-3", children: [
|
|
2087
|
+
/* @__PURE__ */ jsxs19("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
|
|
1941
2088
|
mark,
|
|
1942
2089
|
source
|
|
1943
2090
|
] }),
|
|
1944
|
-
/* @__PURE__ */
|
|
2091
|
+
/* @__PURE__ */ jsx27("span", { className: "text-body-2 text-text-primary", children })
|
|
1945
2092
|
] });
|
|
1946
2093
|
}
|
|
1947
2094
|
|
|
1948
2095
|
// src/InlineChip.tsx
|
|
1949
|
-
import { Fragment as Fragment6, jsx as
|
|
2096
|
+
import { Fragment as Fragment6, jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1950
2097
|
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";
|
|
1951
2098
|
var INLINE_CHIP_TONE_CLASSES = {
|
|
1952
2099
|
/** A thing or a place — anything that is not a person. */
|
|
@@ -1968,19 +2115,19 @@ function inlineChipClassName(tone, className) {
|
|
|
1968
2115
|
return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
|
|
1969
2116
|
}
|
|
1970
2117
|
function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
|
|
1971
|
-
const body = /* @__PURE__ */
|
|
1972
|
-
icon && /* @__PURE__ */
|
|
2118
|
+
const body = /* @__PURE__ */ jsxs20(Fragment6, { children: [
|
|
2119
|
+
icon && /* @__PURE__ */ jsx28("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
|
|
1973
2120
|
children
|
|
1974
2121
|
] });
|
|
1975
2122
|
const classes = inlineChipClassName(tone, className);
|
|
1976
2123
|
if (href === void 0) {
|
|
1977
|
-
return /* @__PURE__ */
|
|
2124
|
+
return /* @__PURE__ */ jsx28("span", { className: classes, ...props, children: body });
|
|
1978
2125
|
}
|
|
1979
|
-
return /* @__PURE__ */
|
|
2126
|
+
return /* @__PURE__ */ jsx28("a", { href, className: classes, ...props, children: body });
|
|
1980
2127
|
}
|
|
1981
2128
|
|
|
1982
2129
|
// src/RichText.tsx
|
|
1983
|
-
import { Fragment as Fragment7, jsx as
|
|
2130
|
+
import { Fragment as Fragment7, jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1984
2131
|
var RICH_TEXT_CLASSES = {
|
|
1985
2132
|
base: "flex flex-col gap-1 break-words text-text-secondary",
|
|
1986
2133
|
/* A heading binds to what follows it: 12px above (8 and the 4px gap), 8px below (4 and the gap); two headings in a row, 12px apart. Level 3 keeps the text's colour, one step lower. */
|
|
@@ -2012,35 +2159,35 @@ function textWithLinks(text, renderText) {
|
|
|
2012
2159
|
return parts.map((part, i) => {
|
|
2013
2160
|
const written = part.match(WRITTEN_LINK);
|
|
2014
2161
|
if (written) {
|
|
2015
|
-
return /* @__PURE__ */
|
|
2162
|
+
return /* @__PURE__ */ jsx29("span", { className: "break-words", children: /* @__PURE__ */ jsx29(Link, { href: written[2], external: true, onClick: keepToLink, children: written[1] }) }, i);
|
|
2016
2163
|
}
|
|
2017
2164
|
const bare = i % 2 === 1 ? part.match(BARE_LINK) : null;
|
|
2018
2165
|
if (bare) {
|
|
2019
2166
|
return (
|
|
2020
2167
|
// An address has no spaces to wrap at, so it may break anywhere.
|
|
2021
|
-
/* @__PURE__ */
|
|
2022
|
-
/* @__PURE__ */
|
|
2168
|
+
/* @__PURE__ */ jsxs21("span", { className: "break-all", children: [
|
|
2169
|
+
/* @__PURE__ */ jsx29(Link, { href: bare[1], external: true, onClick: keepToLink, children: bare[1] }),
|
|
2023
2170
|
bare[2]
|
|
2024
2171
|
] }, i)
|
|
2025
2172
|
);
|
|
2026
2173
|
}
|
|
2027
|
-
return part ? /* @__PURE__ */
|
|
2174
|
+
return part ? /* @__PURE__ */ jsx29("span", { children: renderText(part) }, i) : null;
|
|
2028
2175
|
});
|
|
2029
2176
|
}
|
|
2030
2177
|
function Runs({ runs, draw }) {
|
|
2031
|
-
return /* @__PURE__ */
|
|
2032
|
-
if (run.reference) return /* @__PURE__ */
|
|
2178
|
+
return /* @__PURE__ */ jsx29(Fragment7, { children: (runs ?? []).map((run, i) => {
|
|
2179
|
+
if (run.reference) return /* @__PURE__ */ jsx29("span", { children: draw.renderReference(run.reference, run) }, i);
|
|
2033
2180
|
if (run.marks.includes("code")) {
|
|
2034
|
-
return /* @__PURE__ */
|
|
2181
|
+
return /* @__PURE__ */ jsx29("code", { children: run.text }, i);
|
|
2035
2182
|
}
|
|
2036
|
-
let node = run.text.split("\n").map((line, j) => /* @__PURE__ */
|
|
2037
|
-
j > 0 && /* @__PURE__ */
|
|
2183
|
+
let node = run.text.split("\n").map((line, j) => /* @__PURE__ */ jsxs21("span", { children: [
|
|
2184
|
+
j > 0 && /* @__PURE__ */ jsx29("br", {}),
|
|
2038
2185
|
textWithLinks(line, draw.renderText)
|
|
2039
2186
|
] }, j));
|
|
2040
|
-
if (run.marks.includes("underline")) node = /* @__PURE__ */
|
|
2041
|
-
if (run.marks.includes("italic")) node = /* @__PURE__ */
|
|
2042
|
-
if (run.marks.includes("bold")) node = /* @__PURE__ */
|
|
2043
|
-
return /* @__PURE__ */
|
|
2187
|
+
if (run.marks.includes("underline")) node = /* @__PURE__ */ jsx29("u", { children: node });
|
|
2188
|
+
if (run.marks.includes("italic")) node = /* @__PURE__ */ jsx29("em", { children: node });
|
|
2189
|
+
if (run.marks.includes("bold")) node = /* @__PURE__ */ jsx29("strong", { children: node });
|
|
2190
|
+
return /* @__PURE__ */ jsx29("span", { children: node }, i);
|
|
2044
2191
|
}) });
|
|
2045
2192
|
}
|
|
2046
2193
|
var named = (block) => block.typeName ?? block.type;
|
|
@@ -2051,15 +2198,15 @@ function Table({ block, draw }) {
|
|
|
2051
2198
|
const header = named(cell) === "tableHeader";
|
|
2052
2199
|
const Cell = header ? "th" : "td";
|
|
2053
2200
|
const { colspan, rowspan } = cell.attrs ?? {};
|
|
2054
|
-
return /* @__PURE__ */
|
|
2201
|
+
return /* @__PURE__ */ jsxs21(
|
|
2055
2202
|
Cell,
|
|
2056
2203
|
{
|
|
2057
2204
|
"data-block-id": cell.id,
|
|
2058
2205
|
colSpan: colspan && colspan > 1 ? colspan : void 0,
|
|
2059
2206
|
rowSpan: rowspan && rowspan > 1 ? rowspan : void 0,
|
|
2060
2207
|
children: [
|
|
2061
|
-
(cell.children ?? []).map((child, j) => /* @__PURE__ */
|
|
2062
|
-
/* @__PURE__ */
|
|
2208
|
+
(cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx29(Runs, { runs: child.inline, draw }, j)),
|
|
2209
|
+
/* @__PURE__ */ jsx29(Runs, { runs: cell.inline, draw })
|
|
2063
2210
|
]
|
|
2064
2211
|
},
|
|
2065
2212
|
cell.id ?? i
|
|
@@ -2067,43 +2214,43 @@ function Table({ block, draw }) {
|
|
|
2067
2214
|
});
|
|
2068
2215
|
const first = rows[0].children ?? [];
|
|
2069
2216
|
const headerRow = first.length > 0 && first.every((cell) => named(cell) === "tableHeader");
|
|
2070
|
-
return /* @__PURE__ */
|
|
2071
|
-
headerRow && /* @__PURE__ */
|
|
2072
|
-
/* @__PURE__ */
|
|
2217
|
+
return /* @__PURE__ */ jsxs21("table", { "data-block-id": block.id, children: [
|
|
2218
|
+
headerRow && /* @__PURE__ */ jsx29("thead", { children: /* @__PURE__ */ jsx29("tr", { "data-block-id": rows[0].id, children: cells(rows[0]) }) }),
|
|
2219
|
+
/* @__PURE__ */ jsx29("tbody", { children: (headerRow ? rows.slice(1) : rows).map((row, i) => /* @__PURE__ */ jsx29("tr", { "data-block-id": row.id, children: cells(row) }, row.id ?? i)) })
|
|
2073
2220
|
] });
|
|
2074
2221
|
}
|
|
2075
2222
|
function Block({ block, draw }) {
|
|
2076
2223
|
const own = draw.renderBlock?.(block);
|
|
2077
2224
|
if (own !== void 0) return own;
|
|
2078
|
-
const runs = /* @__PURE__ */
|
|
2225
|
+
const runs = /* @__PURE__ */ jsx29(Runs, { runs: block.inline, draw });
|
|
2079
2226
|
switch (block.type) {
|
|
2080
2227
|
case "heading": {
|
|
2081
|
-
if (block.level === 1) return /* @__PURE__ */
|
|
2082
|
-
if (block.level === 3) return /* @__PURE__ */
|
|
2083
|
-
return /* @__PURE__ */
|
|
2228
|
+
if (block.level === 1) return /* @__PURE__ */ jsx29("h1", { "data-block-id": block.id, children: runs });
|
|
2229
|
+
if (block.level === 3) return /* @__PURE__ */ jsx29("h3", { "data-block-id": block.id, children: runs });
|
|
2230
|
+
return /* @__PURE__ */ jsx29("h2", { "data-block-id": block.id, children: runs });
|
|
2084
2231
|
}
|
|
2085
2232
|
case "paragraph":
|
|
2086
|
-
return /* @__PURE__ */
|
|
2233
|
+
return /* @__PURE__ */ jsx29("p", { "data-block-id": block.id, children: runs });
|
|
2087
2234
|
case "bulletList":
|
|
2088
2235
|
case "orderedList": {
|
|
2089
|
-
const items = (block.children ?? []).map((item, i) => /* @__PURE__ */
|
|
2090
|
-
return block.type === "bulletList" ? /* @__PURE__ */
|
|
2236
|
+
const items = (block.children ?? []).map((item, i) => /* @__PURE__ */ jsx29("li", { "data-block-id": item.id, children: /* @__PURE__ */ jsx29(Runs, { runs: item.inline, draw }) }, item.id ?? i));
|
|
2237
|
+
return block.type === "bulletList" ? /* @__PURE__ */ jsx29("ul", { "data-block-id": block.id, children: items }) : /* @__PURE__ */ jsx29("ol", { "data-block-id": block.id, start: block.start, children: items });
|
|
2091
2238
|
}
|
|
2092
2239
|
case "blockquote":
|
|
2093
|
-
return /* @__PURE__ */
|
|
2240
|
+
return /* @__PURE__ */ jsx29("blockquote", { "data-block-id": block.id, children: runs });
|
|
2094
2241
|
case "codeBlock":
|
|
2095
|
-
return /* @__PURE__ */
|
|
2242
|
+
return /* @__PURE__ */ jsx29("pre", { "data-block-id": block.id, "data-language": block.language, children: /* @__PURE__ */ jsx29("code", { children: (block.inline ?? []).map((run) => run.text).join("") }) });
|
|
2096
2243
|
case "horizontalRule":
|
|
2097
|
-
return /* @__PURE__ */
|
|
2244
|
+
return /* @__PURE__ */ jsx29("hr", { "data-block-id": block.id });
|
|
2098
2245
|
case "table": {
|
|
2099
|
-
const table = /* @__PURE__ */
|
|
2246
|
+
const table = /* @__PURE__ */ jsx29(Table, { block, draw });
|
|
2100
2247
|
if ((block.children ?? []).some((row) => named(row) === "tableRow")) return table;
|
|
2101
2248
|
break;
|
|
2102
2249
|
}
|
|
2103
2250
|
}
|
|
2104
|
-
return /* @__PURE__ */
|
|
2251
|
+
return /* @__PURE__ */ jsxs21("div", { "data-block-id": block.id, "data-block-type": named(block), children: [
|
|
2105
2252
|
runs,
|
|
2106
|
-
(block.children ?? []).map((child, i) => /* @__PURE__ */
|
|
2253
|
+
(block.children ?? []).map((child, i) => /* @__PURE__ */ jsx29(Block, { block: child, draw }, child.id ?? i))
|
|
2107
2254
|
] });
|
|
2108
2255
|
}
|
|
2109
2256
|
function RichText({
|
|
@@ -2115,22 +2262,22 @@ function RichText({
|
|
|
2115
2262
|
}) {
|
|
2116
2263
|
if (blocks.length === 0) return null;
|
|
2117
2264
|
const draw = { renderText, renderReference, renderBlock };
|
|
2118
|
-
return /* @__PURE__ */
|
|
2265
|
+
return /* @__PURE__ */ jsx29("div", { "data-rich-text": true, className: richTextClassName(size), children: blocks.map((block, i) => /* @__PURE__ */ jsx29(Block, { block, draw }, block.id ?? i)) });
|
|
2119
2266
|
}
|
|
2120
2267
|
|
|
2121
2268
|
// src/IdentityMenu.tsx
|
|
2122
|
-
import { useCallback, useRef as
|
|
2269
|
+
import { useCallback as useCallback2, useRef as useRef6 } from "react";
|
|
2123
2270
|
|
|
2124
2271
|
// src/Person.tsx
|
|
2125
|
-
import { jsx as
|
|
2272
|
+
import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2126
2273
|
function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
2127
2274
|
return (
|
|
2128
2275
|
// gap-2: the face-to-name distance is one rule (8px) wherever a person
|
|
2129
2276
|
// appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
|
|
2130
2277
|
// row agree by construction.
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2133
|
-
/* @__PURE__ */
|
|
2278
|
+
/* @__PURE__ */ jsxs22("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
|
|
2279
|
+
/* @__PURE__ */ jsx30(Avatar, { name, src: picture, size }),
|
|
2280
|
+
/* @__PURE__ */ jsx30("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
|
|
2134
2281
|
] })
|
|
2135
2282
|
);
|
|
2136
2283
|
}
|
|
@@ -2138,10 +2285,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
|
2138
2285
|
// src/PersonTrigger.tsx
|
|
2139
2286
|
import { Button as BaseButton5 } from "@base-ui/react/button";
|
|
2140
2287
|
import { IconChevronDown } from "@tabler/icons-react";
|
|
2141
|
-
import { jsx as
|
|
2288
|
+
import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2142
2289
|
function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
|
|
2143
2290
|
if (compact) {
|
|
2144
|
-
return /* @__PURE__ */
|
|
2291
|
+
return /* @__PURE__ */ jsx31(
|
|
2145
2292
|
BaseButton5,
|
|
2146
2293
|
{
|
|
2147
2294
|
type: "button",
|
|
@@ -2150,32 +2297,32 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
2150
2297
|
"aria-label": props["aria-label"] ?? name ?? fallback,
|
|
2151
2298
|
className: cn("cursor-pointer rounded-full", className),
|
|
2152
2299
|
...props,
|
|
2153
|
-
children: /* @__PURE__ */
|
|
2300
|
+
children: /* @__PURE__ */ jsx31(Avatar, { name, src: picture, size: size ?? 36 })
|
|
2154
2301
|
}
|
|
2155
2302
|
);
|
|
2156
2303
|
}
|
|
2157
2304
|
return (
|
|
2158
2305
|
// @estiva-escape(no-copied-look): N5 (Katerina, 24 September: record only): a row that fills on hover, as NavItem also does
|
|
2159
|
-
/* @__PURE__ */
|
|
2306
|
+
/* @__PURE__ */ jsxs23(
|
|
2160
2307
|
BaseButton5,
|
|
2161
2308
|
{
|
|
2162
2309
|
type: "button",
|
|
2163
2310
|
"aria-haspopup": "menu",
|
|
2164
2311
|
"aria-expanded": open,
|
|
2165
2312
|
className: cn(
|
|
2166
|
-
"flex h-8 min-h-8
|
|
2313
|
+
"flex h-8 min-h-8 items-center gap-1.5 pl-1.5 pr-1.5 text-body-2 text-text-primary",
|
|
2314
|
+
MENU_TRIGGER_CLASSES,
|
|
2167
2315
|
open && "bg-bg-hover",
|
|
2168
2316
|
// Under a `Menu` the open state is Base UI's, not a prop: the trigger
|
|
2169
|
-
// carries `data-popup-open` while its menu is up
|
|
2170
|
-
//
|
|
2171
|
-
//
|
|
2172
|
-
"data-[popup-open]:bg-bg-hover",
|
|
2317
|
+
// carries `data-popup-open` while its menu is up (MENU_TRIGGER_CLASSES
|
|
2318
|
+
// holds the fill for it), and sets its own `aria-expanded`; `open`
|
|
2319
|
+
// holds it for a caller that drives it.
|
|
2173
2320
|
className
|
|
2174
2321
|
),
|
|
2175
2322
|
...props,
|
|
2176
2323
|
children: [
|
|
2177
|
-
/* @__PURE__ */
|
|
2178
|
-
/* @__PURE__ */
|
|
2324
|
+
/* @__PURE__ */ jsx31(Person, { name, picture, fallback, size: size ?? 22 }),
|
|
2325
|
+
/* @__PURE__ */ jsx31(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
|
|
2179
2326
|
]
|
|
2180
2327
|
}
|
|
2181
2328
|
)
|
|
@@ -2183,10 +2330,10 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
2183
2330
|
}
|
|
2184
2331
|
|
|
2185
2332
|
// src/IdentityMenu.tsx
|
|
2186
|
-
import { Fragment as Fragment8, jsx as
|
|
2333
|
+
import { Fragment as Fragment8, jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2187
2334
|
function IdentityPanel({ className, onClose = () => {
|
|
2188
2335
|
}, ...rest }) {
|
|
2189
|
-
return /* @__PURE__ */
|
|
2336
|
+
return /* @__PURE__ */ jsx32(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx32(IdentityRows, { ...rest, onClose }) });
|
|
2190
2337
|
}
|
|
2191
2338
|
function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
|
|
2192
2339
|
const act = (action) => () => {
|
|
@@ -2194,53 +2341,53 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
|
|
|
2194
2341
|
action();
|
|
2195
2342
|
};
|
|
2196
2343
|
const appRows = typeof children === "function" ? children(onClose) : children;
|
|
2197
|
-
return /* @__PURE__ */
|
|
2198
|
-
/* @__PURE__ */
|
|
2199
|
-
/* @__PURE__ */
|
|
2200
|
-
/* @__PURE__ */
|
|
2201
|
-
me.email && /* @__PURE__ */
|
|
2344
|
+
return /* @__PURE__ */ jsxs24(Fragment8, { children: [
|
|
2345
|
+
/* @__PURE__ */ jsxs24(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
|
|
2346
|
+
/* @__PURE__ */ jsx32(MenuRow, { children: /* @__PURE__ */ jsx32("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx32(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
|
|
2347
|
+
/* @__PURE__ */ jsx32(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." }),
|
|
2348
|
+
me.email && /* @__PURE__ */ jsxs24(Note, { children: [
|
|
2202
2349
|
me.email,
|
|
2203
2350
|
" \xB7 known to Estiva, never published to the relay"
|
|
2204
2351
|
] })
|
|
2205
2352
|
] }),
|
|
2206
|
-
relayUrl && /* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
/* @__PURE__ */
|
|
2210
|
-
/* @__PURE__ */
|
|
2353
|
+
relayUrl && /* @__PURE__ */ jsxs24(Fragment8, { children: [
|
|
2354
|
+
/* @__PURE__ */ jsx32(Divider, { className: "mx-0 my-2" }),
|
|
2355
|
+
/* @__PURE__ */ jsxs24(MenuSection, { label: "Workspace", children: [
|
|
2356
|
+
/* @__PURE__ */ jsx32(MenuRow, { children: /* @__PURE__ */ jsx32("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
|
|
2357
|
+
/* @__PURE__ */ jsx32(Note, { children: "Everyone on this relay shares this workspace, in every app." })
|
|
2211
2358
|
] })
|
|
2212
2359
|
] }),
|
|
2213
|
-
appRows && /* @__PURE__ */
|
|
2214
|
-
/* @__PURE__ */
|
|
2360
|
+
appRows && /* @__PURE__ */ jsxs24(Fragment8, { children: [
|
|
2361
|
+
/* @__PURE__ */ jsx32(Divider, { className: "mx-0 my-2" }),
|
|
2215
2362
|
appRows
|
|
2216
2363
|
] }),
|
|
2217
|
-
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */
|
|
2218
|
-
signedIn && idBase && /* @__PURE__ */
|
|
2364
|
+
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx32(Divider, { className: "mx-0 my-2" }) : null,
|
|
2365
|
+
signedIn && idBase && /* @__PURE__ */ jsx32(
|
|
2219
2366
|
MenuItem,
|
|
2220
2367
|
{
|
|
2221
2368
|
label: "Edit your profile in Estiva ID",
|
|
2222
2369
|
onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
|
|
2223
2370
|
}
|
|
2224
2371
|
),
|
|
2225
|
-
onCopyKey && /* @__PURE__ */
|
|
2226
|
-
idBase && onSignOut && /* @__PURE__ */
|
|
2372
|
+
onCopyKey && /* @__PURE__ */ jsx32(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
|
|
2373
|
+
idBase && onSignOut && /* @__PURE__ */ jsx32(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
|
|
2227
2374
|
] });
|
|
2228
2375
|
}
|
|
2229
2376
|
function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
|
|
2230
|
-
const actions =
|
|
2231
|
-
const close =
|
|
2377
|
+
const actions = useRef6(null);
|
|
2378
|
+
const close = useCallback2(() => actions.current?.close(), []);
|
|
2232
2379
|
return (
|
|
2233
2380
|
/* The wrapper carries the caller's `className` and nothing else. It used
|
|
2234
2381
|
to be `relative`, because the panel was positioned against it; the panel
|
|
2235
2382
|
hangs from the trigger and portals now, so a positioning context here
|
|
2236
2383
|
would only be a lie about what this box does. */
|
|
2237
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx32("div", { className, children: /* @__PURE__ */ jsx32(
|
|
2238
2385
|
Menu,
|
|
2239
2386
|
{
|
|
2240
2387
|
align: "right",
|
|
2241
2388
|
actionsRef: actions,
|
|
2242
2389
|
className: "w-72",
|
|
2243
|
-
trigger: /* @__PURE__ */
|
|
2390
|
+
trigger: /* @__PURE__ */ jsx32(
|
|
2244
2391
|
PersonTrigger,
|
|
2245
2392
|
{
|
|
2246
2393
|
name: me.name,
|
|
@@ -2251,7 +2398,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
2251
2398
|
"aria-label": compact ? "Account menu" : void 0
|
|
2252
2399
|
}
|
|
2253
2400
|
),
|
|
2254
|
-
children: /* @__PURE__ */
|
|
2401
|
+
children: /* @__PURE__ */ jsx32(
|
|
2255
2402
|
IdentityRows,
|
|
2256
2403
|
{
|
|
2257
2404
|
me,
|
|
@@ -2269,14 +2416,14 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
2269
2416
|
);
|
|
2270
2417
|
}
|
|
2271
2418
|
function Note({ children }) {
|
|
2272
|
-
return /* @__PURE__ */
|
|
2419
|
+
return /* @__PURE__ */ jsx32("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
|
|
2273
2420
|
}
|
|
2274
2421
|
|
|
2275
2422
|
// src/FilePicker.tsx
|
|
2276
2423
|
import { forwardRef } from "react";
|
|
2277
|
-
import { jsx as
|
|
2424
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
2278
2425
|
var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
2279
|
-
return /* @__PURE__ */
|
|
2426
|
+
return /* @__PURE__ */ jsx33(
|
|
2280
2427
|
"input",
|
|
2281
2428
|
{
|
|
2282
2429
|
ref,
|
|
@@ -2297,7 +2444,7 @@ var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
|
2297
2444
|
// src/Select.tsx
|
|
2298
2445
|
import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
|
|
2299
2446
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
2300
|
-
import { jsx as
|
|
2447
|
+
import { jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2301
2448
|
var GAP4 = 4;
|
|
2302
2449
|
var VIEWPORT_PAD4 = 8;
|
|
2303
2450
|
function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, disabledReason, className, ...aria }) {
|
|
@@ -2305,7 +2452,7 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2305
2452
|
const held = Boolean(disabledReason);
|
|
2306
2453
|
const trigger = (
|
|
2307
2454
|
// @estiva-escape(no-copied-look): N1 (Katerina, 24 September: record only): Select's box drops the hover while held, so it cannot take FIELD_SHELL_CLASSES as it is
|
|
2308
|
-
/* @__PURE__ */
|
|
2455
|
+
/* @__PURE__ */ jsxs25(
|
|
2309
2456
|
BaseSelect.Trigger,
|
|
2310
2457
|
{
|
|
2311
2458
|
"aria-label": ariaLabel,
|
|
@@ -2338,21 +2485,21 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2338
2485
|
className
|
|
2339
2486
|
),
|
|
2340
2487
|
children: [
|
|
2341
|
-
/* @__PURE__ */
|
|
2342
|
-
selected?.leading && /* @__PURE__ */
|
|
2343
|
-
/* @__PURE__ */
|
|
2488
|
+
/* @__PURE__ */ jsxs25("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
|
|
2489
|
+
selected?.leading && /* @__PURE__ */ jsx34("span", { className: "flex shrink-0 items-center", children: selected.leading }),
|
|
2490
|
+
/* @__PURE__ */ jsx34(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
|
|
2344
2491
|
] }),
|
|
2345
|
-
/* @__PURE__ */
|
|
2492
|
+
/* @__PURE__ */ jsx34(
|
|
2346
2493
|
BaseSelect.Icon,
|
|
2347
2494
|
{
|
|
2348
|
-
render: /* @__PURE__ */
|
|
2495
|
+
render: /* @__PURE__ */ jsx34(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2349
2496
|
}
|
|
2350
2497
|
)
|
|
2351
2498
|
]
|
|
2352
2499
|
}
|
|
2353
2500
|
)
|
|
2354
2501
|
);
|
|
2355
|
-
return /* @__PURE__ */
|
|
2502
|
+
return /* @__PURE__ */ jsxs25(
|
|
2356
2503
|
BaseSelect.Root,
|
|
2357
2504
|
{
|
|
2358
2505
|
value,
|
|
@@ -2364,8 +2511,8 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2364
2511
|
disabled: disabled && !held,
|
|
2365
2512
|
modal: false,
|
|
2366
2513
|
children: [
|
|
2367
|
-
held ? /* @__PURE__ */
|
|
2368
|
-
/* @__PURE__ */
|
|
2514
|
+
held ? /* @__PURE__ */ jsx34(TooltipTrigger, { label: disabledReason ?? "", children: trigger }) : trigger,
|
|
2515
|
+
/* @__PURE__ */ jsx34(BaseSelect.Portal, { children: /* @__PURE__ */ jsx34(
|
|
2369
2516
|
BaseSelect.Positioner,
|
|
2370
2517
|
{
|
|
2371
2518
|
side: "bottom",
|
|
@@ -2374,25 +2521,25 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2374
2521
|
collisionPadding: VIEWPORT_PAD4,
|
|
2375
2522
|
alignItemWithTrigger: false,
|
|
2376
2523
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2377
|
-
children: /* @__PURE__ */
|
|
2524
|
+
children: /* @__PURE__ */ jsx34(
|
|
2378
2525
|
BaseSelect.Popup,
|
|
2379
2526
|
{
|
|
2380
|
-
render: /* @__PURE__ */
|
|
2527
|
+
render: /* @__PURE__ */ jsx34(MenuPanel, {}),
|
|
2381
2528
|
className: "min-w-[var(--anchor-width)] p-0",
|
|
2382
|
-
children: /* @__PURE__ */
|
|
2529
|
+
children: /* @__PURE__ */ jsx34(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col p-2", children: options.map((option) => /* @__PURE__ */ jsxs25(
|
|
2383
2530
|
BaseSelect.Item,
|
|
2384
2531
|
{
|
|
2385
2532
|
value: option.value,
|
|
2386
2533
|
className: cn(menuItemClassName({ size: "default" }), "justify-between data-[selected]:font-medium"),
|
|
2387
2534
|
children: [
|
|
2388
|
-
/* @__PURE__ */
|
|
2389
|
-
option.leading && /* @__PURE__ */
|
|
2390
|
-
/* @__PURE__ */
|
|
2535
|
+
/* @__PURE__ */ jsxs25("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2536
|
+
option.leading && /* @__PURE__ */ jsx34("span", { className: "flex shrink-0 items-center", children: option.leading }),
|
|
2537
|
+
/* @__PURE__ */ jsx34(BaseSelect.ItemText, { className: "truncate text-body-2 text-text-primary", children: option.label })
|
|
2391
2538
|
] }),
|
|
2392
|
-
/* @__PURE__ */
|
|
2539
|
+
/* @__PURE__ */ jsx34(
|
|
2393
2540
|
BaseSelect.ItemIndicator,
|
|
2394
2541
|
{
|
|
2395
|
-
render: /* @__PURE__ */
|
|
2542
|
+
render: /* @__PURE__ */ jsx34(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2396
2543
|
}
|
|
2397
2544
|
)
|
|
2398
2545
|
]
|
|
@@ -2411,9 +2558,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2411
2558
|
// src/TextInput.tsx
|
|
2412
2559
|
import { forwardRef as forwardRef2 } from "react";
|
|
2413
2560
|
import { Input } from "@base-ui/react/input";
|
|
2414
|
-
import { jsx as
|
|
2561
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
2415
2562
|
var TextInput = forwardRef2(function TextInput2({ className, type = "text", size = "default", ...props }, ref) {
|
|
2416
|
-
return /* @__PURE__ */
|
|
2563
|
+
return /* @__PURE__ */ jsx35(
|
|
2417
2564
|
Input,
|
|
2418
2565
|
{
|
|
2419
2566
|
ref,
|
|
@@ -2439,13 +2586,13 @@ var TextInput = forwardRef2(function TextInput2({ className, type = "text", size
|
|
|
2439
2586
|
// src/Textarea.tsx
|
|
2440
2587
|
import { forwardRef as forwardRef3 } from "react";
|
|
2441
2588
|
import { Field as BaseField3 } from "@base-ui/react/field";
|
|
2442
|
-
import { jsx as
|
|
2589
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
2443
2590
|
var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
|
|
2444
|
-
return /* @__PURE__ */
|
|
2591
|
+
return /* @__PURE__ */ jsx36(
|
|
2445
2592
|
BaseField3.Control,
|
|
2446
2593
|
{
|
|
2447
2594
|
ref,
|
|
2448
|
-
render: /* @__PURE__ */
|
|
2595
|
+
render: /* @__PURE__ */ jsx36("textarea", {}),
|
|
2449
2596
|
className: cn(
|
|
2450
2597
|
// The border strengthens on hover, as Select's and ChipInput's do (Katerina, 16 September:
|
|
2451
2598
|
// "aren't there hover states in text input and text area?"). Focus comes after hover in
|
|
@@ -2464,43 +2611,57 @@ var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
|
|
|
2464
2611
|
});
|
|
2465
2612
|
|
|
2466
2613
|
// src/ConfirmDialog.tsx
|
|
2467
|
-
import { useState as
|
|
2614
|
+
import { useState as useState5 } from "react";
|
|
2468
2615
|
|
|
2469
2616
|
// src/DialogShell.tsx
|
|
2470
|
-
import { useRef as
|
|
2617
|
+
import { useRef as useRef7 } from "react";
|
|
2471
2618
|
import { Dialog as Dialog3 } from "@base-ui/react/dialog";
|
|
2472
2619
|
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
2473
2620
|
import { IconX as IconX5 } from "@tabler/icons-react";
|
|
2474
2621
|
|
|
2475
2622
|
// src/ContainerHeader.tsx
|
|
2476
2623
|
import { IconChevronDown as IconChevronDown3 } from "@tabler/icons-react";
|
|
2477
|
-
import {
|
|
2478
|
-
|
|
2624
|
+
import { Button as BaseButton6 } from "@base-ui/react/button";
|
|
2625
|
+
import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2626
|
+
function ContainerHeader({ title, chevron = false, titleMenu, actions, className }) {
|
|
2479
2627
|
const text = typeof title === "string";
|
|
2480
|
-
|
|
2481
|
-
/* @__PURE__ */
|
|
2482
|
-
|
|
2483
|
-
chevron && /* @__PURE__ */ jsx36(IconChevronDown3, { size: 12, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2484
|
-
] }) }),
|
|
2485
|
-
actions && /* @__PURE__ */ jsx36("div", { className: "flex shrink-0 items-center justify-end gap-3", children: /* @__PURE__ */ jsx36("div", { className: "flex shrink-0 items-center gap-1", children: actions }) })
|
|
2628
|
+
const name = /* @__PURE__ */ jsxs26("div", { className: cn("flex items-center gap-1", text ? "shrink-0" : "min-w-0 flex-1"), children: [
|
|
2629
|
+
text ? /* @__PURE__ */ jsx37("span", { className: "whitespace-nowrap text-body-2-strong text-text-primary", children: title }) : /* @__PURE__ */ jsx37("div", { className: "min-w-0 flex-1", children: title }),
|
|
2630
|
+
(chevron || titleMenu != null) && /* @__PURE__ */ jsx37(IconChevronDown3, { size: 12, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2486
2631
|
] });
|
|
2632
|
+
return (
|
|
2633
|
+
// With a title menu the bar gives the button 6px of its left padding
|
|
2634
|
+
// (pl-3.5 + the button's px-1.5 = pl-5): the words stay where a title's
|
|
2635
|
+
// are, and the fill is inside the bar — a negative margin had it clipped
|
|
2636
|
+
// (Katerina, 5 October).
|
|
2637
|
+
/* @__PURE__ */ jsxs26("div", { className: cn("flex h-12 shrink-0 items-center justify-between overflow-hidden border-b border-border-subtle py-2 pr-4", titleMenu != null ? "pl-3.5" : "pl-5", className), children: [
|
|
2638
|
+
/* @__PURE__ */ jsx37("div", { className: cn("flex items-center gap-2 overflow-hidden", text ? "shrink-0" : "min-w-0 flex-1"), children: titleMenu != null ? /* @__PURE__ */ jsx37(
|
|
2639
|
+
Menu,
|
|
2640
|
+
{
|
|
2641
|
+
trigger: /* @__PURE__ */ jsx37(BaseButton6, { type: "button", className: cn("flex min-w-0 items-center px-1.5 py-1", MENU_TRIGGER_CLASSES), children: name }),
|
|
2642
|
+
children: titleMenu
|
|
2643
|
+
}
|
|
2644
|
+
) : name }),
|
|
2645
|
+
actions && /* @__PURE__ */ jsx37("div", { className: "flex shrink-0 items-center justify-end gap-3", children: /* @__PURE__ */ jsx37("div", { className: "flex shrink-0 items-center gap-1", children: actions }) })
|
|
2646
|
+
] })
|
|
2647
|
+
);
|
|
2487
2648
|
}
|
|
2488
2649
|
|
|
2489
2650
|
// src/DialogShell.tsx
|
|
2490
|
-
import { jsx as
|
|
2651
|
+
import { jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2491
2652
|
function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, bodyMaxHeight, width = 502, alert = false }) {
|
|
2492
2653
|
const Parts = alert ? AlertDialog : Dialog3;
|
|
2493
|
-
const popupRef =
|
|
2494
|
-
return /* @__PURE__ */
|
|
2654
|
+
const popupRef = useRef7(null);
|
|
2655
|
+
return /* @__PURE__ */ jsx38(
|
|
2495
2656
|
Parts.Root,
|
|
2496
2657
|
{
|
|
2497
2658
|
open: true,
|
|
2498
2659
|
onOpenChange: (open) => {
|
|
2499
2660
|
if (!open) onClose();
|
|
2500
2661
|
},
|
|
2501
|
-
children: /* @__PURE__ */
|
|
2502
|
-
/* @__PURE__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2662
|
+
children: /* @__PURE__ */ jsxs27(Parts.Portal, { children: [
|
|
2663
|
+
/* @__PURE__ */ jsx38(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
2664
|
+
/* @__PURE__ */ jsx38("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs27(
|
|
2504
2665
|
Parts.Popup,
|
|
2505
2666
|
{
|
|
2506
2667
|
ref: popupRef,
|
|
@@ -2509,10 +2670,10 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2509
2670
|
className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
|
|
2510
2671
|
style: { width },
|
|
2511
2672
|
children: [
|
|
2512
|
-
/* @__PURE__ */
|
|
2673
|
+
/* @__PURE__ */ jsx38(
|
|
2513
2674
|
ContainerHeader,
|
|
2514
2675
|
{
|
|
2515
|
-
title: headerContent ?? /* @__PURE__ */
|
|
2676
|
+
title: headerContent ?? /* @__PURE__ */ jsx38(Parts.Title, { className: "block truncate text-h4 text-text-primary", render: /* @__PURE__ */ jsx38("span", {}), children: title }),
|
|
2516
2677
|
actions: (
|
|
2517
2678
|
/*
|
|
2518
2679
|
The ✕ IS the `Close` part now, rather than a button that calls
|
|
@@ -2526,10 +2687,10 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2526
2687
|
so the ✕, Escape and the outside press are one path with one
|
|
2527
2688
|
reason attached, instead of one of the three going around.
|
|
2528
2689
|
*/
|
|
2529
|
-
/* @__PURE__ */
|
|
2690
|
+
/* @__PURE__ */ jsx38(
|
|
2530
2691
|
Parts.Close,
|
|
2531
2692
|
{
|
|
2532
|
-
render: /* @__PURE__ */
|
|
2693
|
+
render: /* @__PURE__ */ jsx38(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx38(IconX5, { size: 16, stroke: 1.5 }) })
|
|
2533
2694
|
}
|
|
2534
2695
|
)
|
|
2535
2696
|
)
|
|
@@ -2537,9 +2698,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2537
2698
|
),
|
|
2538
2699
|
bodyMaxHeight ? (
|
|
2539
2700
|
// The line above the footer on a box of the shell's own, not pushed into ScrollArea (UIG-9).
|
|
2540
|
-
/* @__PURE__ */
|
|
2541
|
-
) : /* @__PURE__ */
|
|
2542
|
-
footer != null && /* @__PURE__ */
|
|
2701
|
+
/* @__PURE__ */ jsx38("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx38(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
|
|
2702
|
+
) : /* @__PURE__ */ jsx38("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
|
|
2703
|
+
footer != null && /* @__PURE__ */ jsx38("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
|
|
2543
2704
|
]
|
|
2544
2705
|
}
|
|
2545
2706
|
) })
|
|
@@ -2549,9 +2710,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2549
2710
|
}
|
|
2550
2711
|
|
|
2551
2712
|
// src/ConfirmDialog.tsx
|
|
2552
|
-
import { Fragment as Fragment9, jsx as
|
|
2713
|
+
import { Fragment as Fragment9, jsx as jsx39, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2553
2714
|
function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
|
|
2554
|
-
const [busy, setBusy] =
|
|
2715
|
+
const [busy, setBusy] = useState5(false);
|
|
2555
2716
|
const confirm = async () => {
|
|
2556
2717
|
setBusy(true);
|
|
2557
2718
|
try {
|
|
@@ -2561,32 +2722,32 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
2561
2722
|
setBusy(false);
|
|
2562
2723
|
}
|
|
2563
2724
|
};
|
|
2564
|
-
return /* @__PURE__ */
|
|
2725
|
+
return /* @__PURE__ */ jsx39(
|
|
2565
2726
|
DialogShell,
|
|
2566
2727
|
{
|
|
2567
2728
|
alert: true,
|
|
2568
2729
|
title,
|
|
2569
2730
|
onClose,
|
|
2570
|
-
footer: /* @__PURE__ */
|
|
2571
|
-
/* @__PURE__ */
|
|
2572
|
-
/* @__PURE__ */
|
|
2731
|
+
footer: /* @__PURE__ */ jsxs28(Fragment9, { children: [
|
|
2732
|
+
/* @__PURE__ */ jsx39(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
2733
|
+
/* @__PURE__ */ jsx39(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
|
|
2573
2734
|
] }),
|
|
2574
|
-
children: /* @__PURE__ */
|
|
2735
|
+
children: /* @__PURE__ */ jsx39("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
|
|
2575
2736
|
}
|
|
2576
2737
|
);
|
|
2577
2738
|
}
|
|
2578
2739
|
|
|
2579
2740
|
// src/EditableText.tsx
|
|
2580
|
-
import { useEffect as
|
|
2741
|
+
import { useEffect as useEffect4, useRef as useRef8, useState as useState6 } from "react";
|
|
2581
2742
|
import { Field as BaseField4 } from "@base-ui/react/field";
|
|
2582
2743
|
import { Input as Input2 } from "@base-ui/react/input";
|
|
2583
|
-
import { jsx as
|
|
2744
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
2584
2745
|
function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
|
|
2585
|
-
const [editing, setEditing] =
|
|
2586
|
-
const [draft, setDraft] =
|
|
2587
|
-
const [busy, setBusy] =
|
|
2588
|
-
const fieldRef =
|
|
2589
|
-
|
|
2746
|
+
const [editing, setEditing] = useState6(false);
|
|
2747
|
+
const [draft, setDraft] = useState6(value);
|
|
2748
|
+
const [busy, setBusy] = useState6(false);
|
|
2749
|
+
const fieldRef = useRef8(null);
|
|
2750
|
+
useEffect4(() => {
|
|
2590
2751
|
if (editing) {
|
|
2591
2752
|
fieldRef.current?.focus();
|
|
2592
2753
|
fieldRef.current?.select();
|
|
@@ -2638,7 +2799,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2638
2799
|
written and never read. Read-only, this is a line of text: whatever
|
|
2639
2800
|
names the region around it (a `Field`, a `Property`) names this too.
|
|
2640
2801
|
*/
|
|
2641
|
-
/* @__PURE__ */
|
|
2802
|
+
/* @__PURE__ */ jsx40(
|
|
2642
2803
|
"div",
|
|
2643
2804
|
{
|
|
2644
2805
|
className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
|
|
@@ -2648,11 +2809,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2648
2809
|
);
|
|
2649
2810
|
}
|
|
2650
2811
|
if (editing) {
|
|
2651
|
-
return multiline ? /* @__PURE__ */
|
|
2812
|
+
return multiline ? /* @__PURE__ */ jsx40(
|
|
2652
2813
|
BaseField4.Control,
|
|
2653
2814
|
{
|
|
2654
2815
|
ref: fieldRef,
|
|
2655
|
-
render: /* @__PURE__ */
|
|
2816
|
+
render: /* @__PURE__ */ jsx40("textarea", { rows: 4 }),
|
|
2656
2817
|
"aria-label": label,
|
|
2657
2818
|
value: draft,
|
|
2658
2819
|
disabled: busy,
|
|
@@ -2661,7 +2822,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2661
2822
|
onBlur: () => void commit(),
|
|
2662
2823
|
className: fieldClass
|
|
2663
2824
|
}
|
|
2664
|
-
) : /* @__PURE__ */
|
|
2825
|
+
) : /* @__PURE__ */ jsx40(
|
|
2665
2826
|
Input2,
|
|
2666
2827
|
{
|
|
2667
2828
|
ref: fieldRef,
|
|
@@ -2675,7 +2836,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2675
2836
|
}
|
|
2676
2837
|
);
|
|
2677
2838
|
}
|
|
2678
|
-
return /* @__PURE__ */
|
|
2839
|
+
return /* @__PURE__ */ jsx40(
|
|
2679
2840
|
"button",
|
|
2680
2841
|
{
|
|
2681
2842
|
type: "button",
|
|
@@ -2695,7 +2856,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2695
2856
|
// src/ErrorBoundary.tsx
|
|
2696
2857
|
import { Component } from "react";
|
|
2697
2858
|
import { IconAlertTriangle as IconAlertTriangle2 } from "@tabler/icons-react";
|
|
2698
|
-
import { jsx as
|
|
2859
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2699
2860
|
var ErrorBoundary = class extends Component {
|
|
2700
2861
|
state = { hasError: false };
|
|
2701
2862
|
static getDerivedStateFromError() {
|
|
@@ -2706,22 +2867,22 @@ var ErrorBoundary = class extends Component {
|
|
|
2706
2867
|
}
|
|
2707
2868
|
render() {
|
|
2708
2869
|
if (!this.state.hasError) return this.props.children;
|
|
2709
|
-
const message = /* @__PURE__ */
|
|
2870
|
+
const message = /* @__PURE__ */ jsx41(
|
|
2710
2871
|
EmptyState,
|
|
2711
2872
|
{
|
|
2712
|
-
icon: /* @__PURE__ */
|
|
2873
|
+
icon: /* @__PURE__ */ jsx41(IconAlertTriangle2, { size: 16, stroke: 1.5 }),
|
|
2713
2874
|
message: `Something went wrong${this.props.label ? ` in the ${this.props.label}` : ""}. Your data is safe \u2014 try again.`,
|
|
2714
2875
|
action: { label: "Try again", onClick: () => this.setState({ hasError: false }) }
|
|
2715
2876
|
}
|
|
2716
2877
|
);
|
|
2717
2878
|
if (this.props.frame) return this.props.frame(message);
|
|
2718
|
-
return this.props.fallbackClassName ? /* @__PURE__ */
|
|
2879
|
+
return this.props.fallbackClassName ? /* @__PURE__ */ jsx41("div", { className: this.props.fallbackClassName, children: message }) : message;
|
|
2719
2880
|
}
|
|
2720
2881
|
};
|
|
2721
2882
|
|
|
2722
2883
|
// src/ProgressBar.tsx
|
|
2723
2884
|
import { Progress } from "@base-ui/react/progress";
|
|
2724
|
-
import { jsx as
|
|
2885
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2725
2886
|
var TRACK_CLASSES = {
|
|
2726
2887
|
default: "h-1.5 w-full overflow-hidden rounded-full bg-bg-inset",
|
|
2727
2888
|
// 4px, Katerina's ruling of 14 September; Peek's own bar is 3px until it takes this one.
|
|
@@ -2734,18 +2895,18 @@ var INDICATOR_CLASSES = {
|
|
|
2734
2895
|
function ProgressBar({ value, max, label, variant = "default", className }) {
|
|
2735
2896
|
return (
|
|
2736
2897
|
// `max={0}` needs no guard: Base UI reads the 0/0 share as an empty bar.
|
|
2737
|
-
/* @__PURE__ */
|
|
2898
|
+
/* @__PURE__ */ jsx42(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx42(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx42(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
|
|
2738
2899
|
);
|
|
2739
2900
|
}
|
|
2740
2901
|
|
|
2741
2902
|
// src/Breadcrumb.tsx
|
|
2742
|
-
import { Fragment as Fragment10, useCallback as
|
|
2743
|
-
import { jsx as
|
|
2903
|
+
import { Fragment as Fragment10, useCallback as useCallback3, useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState7 } from "react";
|
|
2904
|
+
import { jsx as jsx43, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2744
2905
|
function Breadcrumb({ items, className }) {
|
|
2745
|
-
const navRef =
|
|
2746
|
-
const labelRefs =
|
|
2747
|
-
const [truncated, setTruncated] =
|
|
2748
|
-
const measure =
|
|
2906
|
+
const navRef = useRef9(null);
|
|
2907
|
+
const labelRefs = useRef9([]);
|
|
2908
|
+
const [truncated, setTruncated] = useState7(/* @__PURE__ */ new Set());
|
|
2909
|
+
const measure = useCallback3(() => {
|
|
2749
2910
|
const next = /* @__PURE__ */ new Set();
|
|
2750
2911
|
labelRefs.current.forEach((el, index) => {
|
|
2751
2912
|
if (el && el.scrollWidth > el.clientWidth) next.add(index);
|
|
@@ -2760,7 +2921,7 @@ function Breadcrumb({ items, className }) {
|
|
|
2760
2921
|
observer.observe(nav);
|
|
2761
2922
|
return () => observer.disconnect();
|
|
2762
2923
|
}, [measure, items]);
|
|
2763
|
-
return /* @__PURE__ */
|
|
2924
|
+
return /* @__PURE__ */ jsx43("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) => {
|
|
2764
2925
|
const last = index === items.length - 1;
|
|
2765
2926
|
const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
|
|
2766
2927
|
const text = cn(
|
|
@@ -2781,34 +2942,34 @@ function Breadcrumb({ items, className }) {
|
|
|
2781
2942
|
// on a box around it, which the link takes them from, rather than
|
|
2782
2943
|
// pushed into it (UIG-9); the link is still the one element that
|
|
2783
2944
|
// truncates and is measured.
|
|
2784
|
-
/* @__PURE__ */
|
|
2785
|
-
) : /* @__PURE__ */
|
|
2786
|
-
return /* @__PURE__ */
|
|
2787
|
-
index > 0 && /* @__PURE__ */
|
|
2788
|
-
item.icon && /* @__PURE__ */
|
|
2945
|
+
/* @__PURE__ */ jsx43("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx43(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
|
|
2946
|
+
) : /* @__PURE__ */ jsx43("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
2947
|
+
return /* @__PURE__ */ jsxs29(Fragment10, { children: [
|
|
2948
|
+
index > 0 && /* @__PURE__ */ jsx43("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
2949
|
+
item.icon && /* @__PURE__ */ jsx43("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
|
|
2789
2950
|
truncated.has(index) ? (
|
|
2790
2951
|
// `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
|
|
2791
2952
|
// must keep truncating inside it, or wrapping it would widen the
|
|
2792
2953
|
// trail and the tooltip would never be needed again.
|
|
2793
|
-
/* @__PURE__ */
|
|
2954
|
+
/* @__PURE__ */ jsx43(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
|
|
2794
2955
|
) : crumb
|
|
2795
2956
|
] }, `${item.label}-${index}`);
|
|
2796
2957
|
}) });
|
|
2797
2958
|
}
|
|
2798
2959
|
|
|
2799
2960
|
// src/NavItem.tsx
|
|
2800
|
-
import { useId, useState as
|
|
2961
|
+
import { useId, useState as useState8 } from "react";
|
|
2801
2962
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
2802
2963
|
import { IconAlertSquareRounded, IconChevronRight as IconChevronRight2, IconDotsVertical } from "@tabler/icons-react";
|
|
2803
2964
|
|
|
2804
2965
|
// src/UnreadDot.tsx
|
|
2805
|
-
import { jsx as
|
|
2966
|
+
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
2806
2967
|
function UnreadDot({ className }) {
|
|
2807
|
-
return /* @__PURE__ */
|
|
2968
|
+
return /* @__PURE__ */ jsx44("div", { className: cn("flex h-6 w-6 shrink-0 items-center justify-center", className), "data-unread": true, children: /* @__PURE__ */ jsx44("div", { className: "h-1.5 w-1.5 rounded-full bg-accent-primary" }) });
|
|
2808
2969
|
}
|
|
2809
2970
|
|
|
2810
2971
|
// src/NavItem.tsx
|
|
2811
|
-
import { jsx as
|
|
2972
|
+
import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2812
2973
|
function NavItem({
|
|
2813
2974
|
label,
|
|
2814
2975
|
href,
|
|
@@ -2828,7 +2989,7 @@ function NavItem({
|
|
|
2828
2989
|
className,
|
|
2829
2990
|
...props
|
|
2830
2991
|
}) {
|
|
2831
|
-
const [openState, setOpenState] =
|
|
2992
|
+
const [openState, setOpenState] = useState8(defaultOpen);
|
|
2832
2993
|
const panelId = useId();
|
|
2833
2994
|
const hasRows = children != null && children !== false;
|
|
2834
2995
|
const open = openProp ?? openState;
|
|
@@ -2837,9 +2998,9 @@ function NavItem({
|
|
|
2837
2998
|
onOpenChange?.(next);
|
|
2838
2999
|
};
|
|
2839
3000
|
const besides = menu != null || hasRows;
|
|
2840
|
-
const mark = unread ? urgent ? /* @__PURE__ */
|
|
2841
|
-
const stepsAside = menu != null && "transition-opacity group-hover/nav:opacity-0 group-focus-
|
|
2842
|
-
const row = /* @__PURE__ */
|
|
3001
|
+
const mark = unread ? urgent ? /* @__PURE__ */ jsx45(UrgentMark, {}) : /* @__PURE__ */ jsx45(UnreadDot, {}) : null;
|
|
3002
|
+
const stepsAside = menu != null && "transition-opacity group-hover/nav:opacity-0 group-has-[:focus-visible]/nav:opacity-0 group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:opacity-0";
|
|
3003
|
+
const row = /* @__PURE__ */ jsxs30(
|
|
2843
3004
|
"a",
|
|
2844
3005
|
{
|
|
2845
3006
|
href,
|
|
@@ -2860,21 +3021,21 @@ function NavItem({
|
|
|
2860
3021
|
),
|
|
2861
3022
|
...props,
|
|
2862
3023
|
children: [
|
|
2863
|
-
(icon || hasRows) && /* @__PURE__ */
|
|
3024
|
+
(icon || hasRows) && /* @__PURE__ */ jsx45(
|
|
2864
3025
|
"span",
|
|
2865
3026
|
{
|
|
2866
3027
|
className: cn(
|
|
2867
3028
|
// With rows under it the slot is kept even with no icon: the arrow lands in it.
|
|
2868
3029
|
"flex min-w-4 shrink-0 items-center",
|
|
2869
|
-
hasRows && "transition-opacity group-hover/nav:opacity-0 group-focus-
|
|
3030
|
+
hasRows && "transition-opacity group-hover/nav:opacity-0 group-has-[:focus-visible]/nav:opacity-0"
|
|
2870
3031
|
),
|
|
2871
3032
|
children: icon
|
|
2872
3033
|
}
|
|
2873
3034
|
),
|
|
2874
|
-
/* @__PURE__ */
|
|
3035
|
+
/* @__PURE__ */ jsx45("span", { className: cn("flex-1 truncate", unread && "font-medium"), children: label }),
|
|
2875
3036
|
hint != null && // Takes room only while it shows, so the label gives way to it.
|
|
2876
|
-
/* @__PURE__ */
|
|
2877
|
-
count ? /* @__PURE__ */
|
|
3037
|
+
/* @__PURE__ */ jsx45("span", { className: "hidden shrink-0 items-center group-hover/nav:flex group-has-[:focus-visible]/nav:flex", children: hint }),
|
|
3038
|
+
count ? /* @__PURE__ */ jsx45(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx45(
|
|
2878
3039
|
"span",
|
|
2879
3040
|
{
|
|
2880
3041
|
className: cn(
|
|
@@ -2885,22 +3046,27 @@ function NavItem({
|
|
|
2885
3046
|
children: count
|
|
2886
3047
|
}
|
|
2887
3048
|
) }) : null,
|
|
2888
|
-
mark ?
|
|
3049
|
+
mark ? (
|
|
3050
|
+
// `-mr-1`: the 24px slot's dot then sits on the axis of a count and
|
|
3051
|
+
// of the ⋮ (8px from the edge to the 16px box), one column with a
|
|
3052
|
+
// folder heading's dot and ⋮ (Katerina, 5 October).
|
|
3053
|
+
/* @__PURE__ */ jsx45("span", { className: cn("-mr-1 flex shrink-0", stepsAside), children: mark })
|
|
3054
|
+
) : menu != null && !count ? (
|
|
2889
3055
|
// Nothing at the right, but a menu: no room is kept at rest, so the
|
|
2890
3056
|
// label has the row's whole width; while the ⋮ shows, its 24px slot
|
|
2891
3057
|
// is kept, so a long label ends before it instead of running under it.
|
|
2892
|
-
/* @__PURE__ */
|
|
3058
|
+
/* @__PURE__ */ jsx45("span", { "aria-hidden": "true", className: "hidden w-6 shrink-0 group-hover/nav:block group-has-[:focus-visible]/nav:block group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:block" })
|
|
2893
3059
|
) : null
|
|
2894
3060
|
]
|
|
2895
3061
|
}
|
|
2896
3062
|
);
|
|
2897
3063
|
if (!besides && hint == null) return row;
|
|
2898
3064
|
const name = menuLabel ?? `More options for ${label}`;
|
|
2899
|
-
const line = /* @__PURE__ */
|
|
3065
|
+
const line = /* @__PURE__ */ jsxs30("div", { className: "group/nav relative shrink-0", children: [
|
|
2900
3066
|
row,
|
|
2901
3067
|
hasRows && // `left-1`: the 24px button's 16px arrow then sits where the icon
|
|
2902
3068
|
// sits (the row's px-2), so the icon turns into the arrow in place.
|
|
2903
|
-
/* @__PURE__ */
|
|
3069
|
+
/* @__PURE__ */ jsx45("div", { className: "absolute inset-y-0 left-1 flex items-center opacity-0 transition-opacity group-hover/nav:opacity-100 group-has-[:focus-visible]/nav:opacity-100", children: /* @__PURE__ */ jsx45(
|
|
2904
3070
|
IconButton,
|
|
2905
3071
|
{
|
|
2906
3072
|
tooltip: open ? "Collapse" : "Expand",
|
|
@@ -2908,77 +3074,95 @@ function NavItem({
|
|
|
2908
3074
|
"aria-expanded": open,
|
|
2909
3075
|
"aria-controls": panelId,
|
|
2910
3076
|
onClick: () => setOpen(!open),
|
|
2911
|
-
children: /* @__PURE__ */
|
|
3077
|
+
children: /* @__PURE__ */ jsx45(IconChevronRight2, { size: 16, stroke: 1.5, className: cn("transition-transform duration-150", open && "rotate-90") })
|
|
2912
3078
|
}
|
|
2913
3079
|
) }),
|
|
2914
|
-
menu != null && //
|
|
2915
|
-
//
|
|
2916
|
-
//
|
|
2917
|
-
//
|
|
2918
|
-
|
|
3080
|
+
menu != null && // `right-1`: the 24px button's 16px icon ends 8px from the row's
|
|
3081
|
+
// edge, where a count ends (px-2) — and where a SectionHeader's
|
|
3082
|
+
// actions and ⋮ end, so a folder's ⋮ and its rows' ⋮ are one column
|
|
3083
|
+
// (Katerina, 5 October: the rows move to the heading, not the
|
|
3084
|
+
// heading to the rows). Over a dot or the empty slot it sits 4px
|
|
3085
|
+
// right of the slot's centre.
|
|
3086
|
+
/* @__PURE__ */ jsx45("div", { "data-nav-menu": true, className: cn("absolute inset-y-0 right-1 flex items-center", "opacity-0 transition-opacity group-hover/nav:opacity-100 group-has-[:focus-visible]/nav:opacity-100 has-[[aria-expanded=true]]:opacity-100"), children: /* @__PURE__ */ jsx45(
|
|
2919
3087
|
Menu,
|
|
2920
3088
|
{
|
|
2921
3089
|
align: "right",
|
|
2922
|
-
trigger: /* @__PURE__ */
|
|
3090
|
+
trigger: /* @__PURE__ */ jsx45(IconButton, { tooltip: "More options", "aria-label": name, children: /* @__PURE__ */ jsx45(IconDotsVertical, { size: 16, stroke: 1.5 }) }),
|
|
2923
3091
|
children: menu
|
|
2924
3092
|
}
|
|
2925
3093
|
) })
|
|
2926
3094
|
] });
|
|
2927
3095
|
if (!hasRows) return line;
|
|
2928
|
-
return /* @__PURE__ */
|
|
3096
|
+
return /* @__PURE__ */ jsxs30(Collapsible.Root, { open, onOpenChange: setOpen, className: "flex shrink-0 flex-col", children: [
|
|
2929
3097
|
line,
|
|
2930
|
-
/* @__PURE__ */
|
|
3098
|
+
/* @__PURE__ */ jsx45(
|
|
2931
3099
|
Collapsible.Panel,
|
|
2932
3100
|
{
|
|
2933
3101
|
id: panelId,
|
|
2934
3102
|
hiddenUntilFound: true,
|
|
2935
3103
|
className: COLLAPSIBLE_PANEL_CLASSES,
|
|
2936
|
-
children: /* @__PURE__ */
|
|
3104
|
+
children: /* @__PURE__ */ jsx45("div", { className: "flex flex-col gap-0.5 pt-0.5 pl-6", children })
|
|
2937
3105
|
}
|
|
2938
3106
|
)
|
|
2939
3107
|
] });
|
|
2940
3108
|
}
|
|
2941
3109
|
function UrgentMark() {
|
|
2942
|
-
return /* @__PURE__ */
|
|
3110
|
+
return /* @__PURE__ */ jsx45("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center", "data-urgent": true, children: /* @__PURE__ */ jsx45("div", { className: "flex items-center rounded-full bg-warning-muted p-0.5 signal:shadow-glow-warning", children: /* @__PURE__ */ jsx45(IconAlertSquareRounded, { size: 12, stroke: 2.5, className: "text-warning-default" }) }) });
|
|
2943
3111
|
}
|
|
2944
3112
|
|
|
2945
3113
|
// src/NavTree.tsx
|
|
2946
|
-
import { useEffect as
|
|
3114
|
+
import { useEffect as useEffect5, useRef as useRef10 } from "react";
|
|
2947
3115
|
|
|
2948
3116
|
// src/CollapsibleSection.tsx
|
|
2949
|
-
import { useState as
|
|
3117
|
+
import { useState as useState9 } from "react";
|
|
2950
3118
|
import { Collapsible as Collapsible2 } from "@base-ui/react/collapsible";
|
|
2951
3119
|
|
|
2952
3120
|
// src/SectionHeader.tsx
|
|
2953
|
-
import {
|
|
3121
|
+
import { isValidElement as isValidElement2 } from "react";
|
|
3122
|
+
import { IconChevronRight as IconChevronRight3, IconDotsVertical as IconDotsVertical2 } from "@tabler/icons-react";
|
|
2954
3123
|
import { useRender } from "@base-ui/react/use-render";
|
|
2955
|
-
import { Fragment as Fragment11, jsx as
|
|
2956
|
-
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", hover = "fill", look = "heading", render, className }) {
|
|
3124
|
+
import { Fragment as Fragment11, jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3125
|
+
function SectionHeader({ title, chevron = false, icon, isExpanded = true, onToggle, trailing, actions, menu, menuLabel, showActions = "hover", hover = "fill", look = "heading", render, className }) {
|
|
2957
3126
|
const row = look === "row";
|
|
3127
|
+
const acts = actions && actions.length > 0 || menu != null;
|
|
3128
|
+
const dot = isValidElement2(trailing) && trailing.type === UnreadDot;
|
|
3129
|
+
const shared = acts && showActions === "hover" && dot;
|
|
3130
|
+
const reveal = showActions === "hover" && "opacity-0 transition-opacity group-hover:opacity-100 has-[:focus-visible]:opacity-100 has-[[aria-expanded=true]]:opacity-100";
|
|
2958
3131
|
const titleElement = useRender({
|
|
2959
|
-
render: render ?? (chevron ? /* @__PURE__ */
|
|
3132
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx46("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx46("span", {})),
|
|
2960
3133
|
props: {
|
|
2961
3134
|
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
2962
3135
|
// whole row up to the actions is the hit target, as it was when the
|
|
2963
3136
|
// row itself carried the click.
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
3137
|
+
// An icon is a row's: NavItem's 8px after it.
|
|
3138
|
+
className: cn("flex h-full min-w-0 flex-1 items-center text-left", row || chevron || icon != null ? "gap-2" : "gap-1"),
|
|
3139
|
+
children: /* @__PURE__ */ jsxs31(Fragment11, { children: [
|
|
3140
|
+
icon != null ? /* @__PURE__ */ jsxs31("span", { className: "relative flex size-4 shrink-0 items-center justify-center text-text-secondary", children: [
|
|
3141
|
+
/* @__PURE__ */ jsx46("span", { className: cn("flex", chevron && "transition-opacity group-hover:opacity-0 group-has-[:focus-visible]:opacity-0"), children: icon }),
|
|
3142
|
+
chevron && /* @__PURE__ */ jsx46(
|
|
3143
|
+
IconChevronRight3,
|
|
3144
|
+
{
|
|
3145
|
+
size: 16,
|
|
3146
|
+
stroke: 1.5,
|
|
3147
|
+
className: cn("absolute opacity-0 transition-[opacity,transform] duration-150 group-hover:opacity-100 group-has-[:focus-visible]:opacity-100", isExpanded && "rotate-90")
|
|
3148
|
+
}
|
|
3149
|
+
)
|
|
3150
|
+
] }) : chevron && /* @__PURE__ */ jsx46(
|
|
2967
3151
|
IconChevronRight3,
|
|
2968
3152
|
{
|
|
2969
|
-
size:
|
|
3153
|
+
size: 16,
|
|
2970
3154
|
stroke: 1.5,
|
|
2971
3155
|
className: cn("shrink-0 transition-transform duration-150", !row && "text-text-secondary", isExpanded && "rotate-90")
|
|
2972
3156
|
}
|
|
2973
3157
|
),
|
|
2974
|
-
look === "quiet" ? /* @__PURE__ */
|
|
3158
|
+
look === "quiet" ? /* @__PURE__ */ jsx46("span", { className: "min-w-0 truncate text-caption text-text-muted", children: title }) : row ? (
|
|
2975
3159
|
// A row's words: NavItem's size and colour, brightening under the pointer with the row.
|
|
2976
|
-
/* @__PURE__ */
|
|
2977
|
-
) : /* @__PURE__ */
|
|
3160
|
+
/* @__PURE__ */ jsx46("span", { className: "min-w-0 flex-1 truncate text-body-2", children: title })
|
|
3161
|
+
) : /* @__PURE__ */ jsx46(SectionLabel, { folds: chevron, children: title })
|
|
2978
3162
|
] })
|
|
2979
3163
|
}
|
|
2980
3164
|
});
|
|
2981
|
-
return /* @__PURE__ */
|
|
3165
|
+
return /* @__PURE__ */ jsxs31(
|
|
2982
3166
|
"div",
|
|
2983
3167
|
{
|
|
2984
3168
|
className: cn(
|
|
@@ -2990,20 +3174,37 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2990
3174
|
// lights up, a fixed heading over rows does not (2026-09-09, the
|
|
2991
3175
|
// Sidebar's fixed group).
|
|
2992
3176
|
// A quiet label never lights up: it is a label; its button does.
|
|
2993
|
-
hover === "fill" && look !== "quiet" && (chevron ||
|
|
3177
|
+
hover === "fill" && look !== "quiet" && (chevron || acts) && "hover:bg-bg-hover",
|
|
3178
|
+
// While its menu is open the pointer is on the menu, not the row: the
|
|
3179
|
+
// row keeps its hover look, as a NavItem's does.
|
|
3180
|
+
hover === "fill" && look !== "quiet" && menu != null && "has-[[data-section-menu]_[aria-expanded=true]]:bg-bg-hover",
|
|
2994
3181
|
className
|
|
2995
3182
|
),
|
|
2996
3183
|
children: [
|
|
2997
3184
|
titleElement,
|
|
2998
|
-
trailing != null &&
|
|
2999
|
-
|
|
3185
|
+
trailing != null && !shared && // A dot with no buttons to share a place with still sits on their
|
|
3186
|
+
// axis — the rows' dots and ⋮ (`-mr-1`, as the buttons are pulled).
|
|
3187
|
+
/* @__PURE__ */ jsx46("div", { className: cn("flex shrink-0 items-center", dot && !acts && "-mr-1"), children: trailing }),
|
|
3188
|
+
acts && /* @__PURE__ */ jsxs31(
|
|
3000
3189
|
"div",
|
|
3001
3190
|
{
|
|
3002
|
-
className:
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3191
|
+
className: "group/acts relative -mr-1 flex shrink-0 items-center",
|
|
3192
|
+
children: [
|
|
3193
|
+
/* @__PURE__ */ jsxs31("div", { className: cn("flex items-center gap-1", reveal), children: [
|
|
3194
|
+
actions?.map((action) => /* @__PURE__ */ jsx46(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip)),
|
|
3195
|
+
menu != null && /* @__PURE__ */ jsx46("div", { "data-section-menu": true, className: "flex items-center", children: /* @__PURE__ */ jsx46(
|
|
3196
|
+
Menu,
|
|
3197
|
+
{
|
|
3198
|
+
align: "right",
|
|
3199
|
+
trigger: /* @__PURE__ */ jsx46(IconButton, { tooltip: "More options", "aria-label": menuLabel ?? `More options for ${title}`, children: /* @__PURE__ */ jsx46(IconDotsVertical2, { size: 16, stroke: 1.5 }) }),
|
|
3200
|
+
children: menu
|
|
3201
|
+
}
|
|
3202
|
+
) })
|
|
3203
|
+
] }),
|
|
3204
|
+
shared && // The dot in the last button's 24px place, on the axis of its icon;
|
|
3205
|
+
// gone while the buttons show.
|
|
3206
|
+
/* @__PURE__ */ jsx46("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex w-6 items-center justify-center transition-opacity group-hover:opacity-0 group-has-[:focus-visible]/acts:opacity-0 group-has-[[aria-expanded=true]]/acts:opacity-0", children: trailing })
|
|
3207
|
+
]
|
|
3007
3208
|
}
|
|
3008
3209
|
)
|
|
3009
3210
|
]
|
|
@@ -3012,7 +3213,7 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
3012
3213
|
}
|
|
3013
3214
|
|
|
3014
3215
|
// src/CollapsibleSection.tsx
|
|
3015
|
-
import { jsx as
|
|
3216
|
+
import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3016
3217
|
var OPEN = "open";
|
|
3017
3218
|
var CLOSED = "closed";
|
|
3018
3219
|
function readStored(key) {
|
|
@@ -3031,39 +3232,39 @@ function writeStored(key, open) {
|
|
|
3031
3232
|
} catch {
|
|
3032
3233
|
}
|
|
3033
3234
|
}
|
|
3034
|
-
function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, trailing, actions, showActions, look = "heading", indent = false, children, className, contentClassName }) {
|
|
3035
|
-
const [openState, setOpenState] =
|
|
3235
|
+
function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, icon, trailing, actions, menu, menuLabel, showActions, look = "heading", indent = false, children, className, contentClassName }) {
|
|
3236
|
+
const [openState, setOpenState] = useState9(() => readStored(storageKey) ?? defaultOpen);
|
|
3036
3237
|
const open = openProp ?? openState;
|
|
3037
3238
|
const setOpen = (next) => {
|
|
3038
3239
|
setOpenState(next);
|
|
3039
3240
|
writeStored(storageKey, next);
|
|
3040
3241
|
onOpenChange?.(next);
|
|
3041
3242
|
};
|
|
3042
|
-
return /* @__PURE__ */
|
|
3043
|
-
/* @__PURE__ */
|
|
3044
|
-
/* @__PURE__ */
|
|
3243
|
+
return /* @__PURE__ */ jsxs32(Collapsible2.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
3244
|
+
/* @__PURE__ */ jsx47(SectionHeader, { title, chevron: true, icon, isExpanded: open, trailing, actions, menu, menuLabel, showActions, look, className: "shrink-0", render: /* @__PURE__ */ jsx47(Collapsible2.Trigger, {}) }),
|
|
3245
|
+
/* @__PURE__ */ jsx47(
|
|
3045
3246
|
Collapsible2.Panel,
|
|
3046
3247
|
{
|
|
3047
3248
|
hiddenUntilFound: true,
|
|
3048
3249
|
className: COLLAPSIBLE_PANEL_CLASSES,
|
|
3049
|
-
children: /* @__PURE__ */
|
|
3250
|
+
children: /* @__PURE__ */ jsx47("div", { className: cn("flex flex-col pt-0.5", (look === "row" || indent) && "pl-6", contentClassName), children })
|
|
3050
3251
|
}
|
|
3051
3252
|
)
|
|
3052
3253
|
] });
|
|
3053
3254
|
}
|
|
3054
3255
|
|
|
3055
3256
|
// src/NavTree.tsx
|
|
3056
|
-
import { Fragment as Fragment12, jsx as
|
|
3257
|
+
import { Fragment as Fragment12, jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3057
3258
|
var NAV_TREE_INTENT_MS = 150;
|
|
3058
3259
|
function holds(nodes, id) {
|
|
3059
3260
|
return !!nodes && id !== void 0 && nodes.some((node) => node.id === id || holds(node.children ?? null, id));
|
|
3060
3261
|
}
|
|
3061
3262
|
function Line({ message }) {
|
|
3062
|
-
return /* @__PURE__ */
|
|
3263
|
+
return /* @__PURE__ */ jsx48("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx48(EmptyState, { scope: "section", message }) });
|
|
3063
3264
|
}
|
|
3064
3265
|
function Row({ node, selected, onSelect }) {
|
|
3065
|
-
const under = node.childrenMessage !== void 0 ? /* @__PURE__ */
|
|
3066
|
-
return /* @__PURE__ */
|
|
3266
|
+
const under = node.childrenMessage !== void 0 ? /* @__PURE__ */ jsx48(Line, { message: node.childrenMessage }) : node.children?.length ? node.children.map((child) => /* @__PURE__ */ jsx48(Row, { node: child, selected, onSelect }, child.id)) : node.children === null || node.hasChildren && node.children === void 0 ? /* @__PURE__ */ jsx48(SkeletonList, { rows: 2 }) : void 0;
|
|
3267
|
+
return /* @__PURE__ */ jsx48(
|
|
3067
3268
|
NavItem,
|
|
3068
3269
|
{
|
|
3069
3270
|
href: node.href,
|
|
@@ -3085,7 +3286,7 @@ function Row({ node, selected, onSelect }) {
|
|
|
3085
3286
|
);
|
|
3086
3287
|
}
|
|
3087
3288
|
function Group({ group, selected, onSelect, storageKey }) {
|
|
3088
|
-
return /* @__PURE__ */
|
|
3289
|
+
return /* @__PURE__ */ jsx48(
|
|
3089
3290
|
NavTreeSection,
|
|
3090
3291
|
{
|
|
3091
3292
|
id: group.id,
|
|
@@ -3094,23 +3295,25 @@ function Group({ group, selected, onSelect, storageKey }) {
|
|
|
3094
3295
|
loading: group.nodes === null,
|
|
3095
3296
|
trailing: group.trailing,
|
|
3096
3297
|
actions: group.actions,
|
|
3298
|
+
menu: group.menu,
|
|
3299
|
+
icon: group.icon,
|
|
3097
3300
|
defaultOpen: group.defaultOpen ?? holds(group.nodes, selected),
|
|
3098
3301
|
open: group.open,
|
|
3099
3302
|
onOpenChange: group.onOpenChange,
|
|
3100
3303
|
storageKey: storageKey ? `${storageKey}.${group.id}` : void 0,
|
|
3101
3304
|
onIntent: group.onIntent,
|
|
3102
|
-
children: group.nodes?.map((node) => /* @__PURE__ */
|
|
3305
|
+
children: group.nodes?.map((node) => /* @__PURE__ */ jsx48(Row, { node, selected, onSelect }, node.id))
|
|
3103
3306
|
}
|
|
3104
3307
|
);
|
|
3105
3308
|
}
|
|
3106
|
-
function NavTreeSection({ id, title, message, loading = false, trailing, actions, defaultOpen = true, open, onOpenChange, storageKey, onIntent, children }) {
|
|
3107
|
-
const timer =
|
|
3108
|
-
|
|
3309
|
+
function NavTreeSection({ id, title, message, loading = false, trailing, actions, menu, icon, defaultOpen = true, open, onOpenChange, storageKey, onIntent, children }) {
|
|
3310
|
+
const timer = useRef10(void 0);
|
|
3311
|
+
useEffect5(() => () => clearTimeout(timer.current), []);
|
|
3109
3312
|
const intent = onIntent;
|
|
3110
|
-
return /* @__PURE__ */
|
|
3313
|
+
return /* @__PURE__ */ jsx48(
|
|
3111
3314
|
"div",
|
|
3112
3315
|
{
|
|
3113
|
-
className: "shrink-0",
|
|
3316
|
+
className: "mt-1 shrink-0 first:mt-0",
|
|
3114
3317
|
"data-nav-group": id,
|
|
3115
3318
|
onPointerEnter: intent ? () => {
|
|
3116
3319
|
clearTimeout(timer.current);
|
|
@@ -3118,7 +3321,7 @@ function NavTreeSection({ id, title, message, loading = false, trailing, actions
|
|
|
3118
3321
|
} : void 0,
|
|
3119
3322
|
onPointerLeave: intent ? () => clearTimeout(timer.current) : void 0,
|
|
3120
3323
|
onFocus: intent,
|
|
3121
|
-
children: /* @__PURE__ */
|
|
3324
|
+
children: /* @__PURE__ */ jsx48(
|
|
3122
3325
|
CollapsibleSection,
|
|
3123
3326
|
{
|
|
3124
3327
|
title,
|
|
@@ -3129,28 +3332,30 @@ function NavTreeSection({ id, title, message, loading = false, trailing, actions
|
|
|
3129
3332
|
storageKey,
|
|
3130
3333
|
trailing,
|
|
3131
3334
|
actions,
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3335
|
+
menu,
|
|
3336
|
+
icon,
|
|
3337
|
+
className: "shrink-0",
|
|
3338
|
+
contentClassName: "gap-0.5",
|
|
3339
|
+
children: message !== void 0 ? /* @__PURE__ */ jsx48(Line, { message }) : loading ? /* @__PURE__ */ jsx48(SkeletonList, { rows: 3 }) : children
|
|
3135
3340
|
}
|
|
3136
3341
|
)
|
|
3137
3342
|
}
|
|
3138
3343
|
);
|
|
3139
3344
|
}
|
|
3140
3345
|
function NavTree({ title, titleActions, groups, children, selected, onSelect, emptyMessage = "", storageKey }) {
|
|
3141
|
-
return /* @__PURE__ */
|
|
3142
|
-
title && /* @__PURE__ */
|
|
3143
|
-
groups === void 0 ? children : groups === null ? /* @__PURE__ */
|
|
3346
|
+
return /* @__PURE__ */ jsxs33(Fragment12, { children: [
|
|
3347
|
+
title && /* @__PURE__ */ jsx48(SectionHeader, { title, look: "quiet", showActions: "always", actions: titleActions, className: "mt-4 shrink-0" }),
|
|
3348
|
+
groups === void 0 ? children : groups === null ? /* @__PURE__ */ jsx48(SkeletonList, { rows: 5 }) : groups.length === 0 ? (
|
|
3144
3349
|
// No words, no line: an app that says nothing when it has no groups.
|
|
3145
|
-
emptyMessage ? /* @__PURE__ */
|
|
3146
|
-
) : groups.map((group) => /* @__PURE__ */
|
|
3350
|
+
emptyMessage ? /* @__PURE__ */ jsx48(Line, { message: emptyMessage }) : null
|
|
3351
|
+
) : groups.map((group) => /* @__PURE__ */ jsx48(Group, { group, selected, onSelect, storageKey }, group.id))
|
|
3147
3352
|
] });
|
|
3148
3353
|
}
|
|
3149
3354
|
|
|
3150
3355
|
// src/Popover.tsx
|
|
3151
3356
|
import { useMemo as useMemo3 } from "react";
|
|
3152
3357
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
3153
|
-
import { jsx as
|
|
3358
|
+
import { jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3154
3359
|
var GAP5 = 4;
|
|
3155
3360
|
var VIEWPORT_PAD5 = 8;
|
|
3156
3361
|
function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
|
|
@@ -3159,7 +3364,7 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3159
3364
|
if (anchor instanceof Element) return anchor;
|
|
3160
3365
|
return { getBoundingClientRect: () => anchor };
|
|
3161
3366
|
}, [anchor]);
|
|
3162
|
-
return /* @__PURE__ */
|
|
3367
|
+
return /* @__PURE__ */ jsxs34(
|
|
3163
3368
|
BasePopover.Root,
|
|
3164
3369
|
{
|
|
3165
3370
|
open,
|
|
@@ -3167,8 +3372,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3167
3372
|
actionsRef,
|
|
3168
3373
|
modal: false,
|
|
3169
3374
|
children: [
|
|
3170
|
-
trigger && /* @__PURE__ */
|
|
3171
|
-
/* @__PURE__ */
|
|
3375
|
+
trigger && /* @__PURE__ */ jsx49(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
|
|
3376
|
+
/* @__PURE__ */ jsx49(BasePopover.Portal, { children: /* @__PURE__ */ jsx49(
|
|
3172
3377
|
BasePopover.Positioner,
|
|
3173
3378
|
{
|
|
3174
3379
|
anchor: anchorTarget,
|
|
@@ -3177,20 +3382,20 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3177
3382
|
sideOffset: GAP5,
|
|
3178
3383
|
collisionPadding: VIEWPORT_PAD5,
|
|
3179
3384
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
3180
|
-
children: /* @__PURE__ */
|
|
3385
|
+
children: /* @__PURE__ */ jsx49(
|
|
3181
3386
|
BasePopover.Popup,
|
|
3182
3387
|
{
|
|
3183
3388
|
"aria-label": ariaLabel,
|
|
3184
3389
|
initialFocus: trigger ? void 0 : false,
|
|
3185
3390
|
finalFocus,
|
|
3186
3391
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
3187
|
-
render: /* @__PURE__ */
|
|
3188
|
-
children: /* @__PURE__ */
|
|
3392
|
+
render: /* @__PURE__ */ jsx49(MenuPanel, {}),
|
|
3393
|
+
children: /* @__PURE__ */ jsx49(
|
|
3189
3394
|
ScrollArea,
|
|
3190
3395
|
{
|
|
3191
3396
|
viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
|
|
3192
3397
|
contentClassName: cn("flex flex-col p-2", contentClassName),
|
|
3193
|
-
children: /* @__PURE__ */
|
|
3398
|
+
children: /* @__PURE__ */ jsx49(DividerInPanel.Provider, { value: true, children })
|
|
3194
3399
|
}
|
|
3195
3400
|
)
|
|
3196
3401
|
}
|
|
@@ -3203,18 +3408,18 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3203
3408
|
}
|
|
3204
3409
|
|
|
3205
3410
|
// src/SuggestionMenu.tsx
|
|
3206
|
-
import { useCallback as
|
|
3207
|
-
import { jsx as
|
|
3411
|
+
import { useCallback as useCallback4, useEffect as useEffect6, useId as useId2, useImperativeHandle, useMemo as useMemo4, useRef as useRef11, useState as useState10 } from "react";
|
|
3412
|
+
import { jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3208
3413
|
function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sections, itemKey, row, onSelect, handle }) {
|
|
3209
3414
|
const shown = useMemo4(() => sections.filter((section) => section.items.length > 0), [sections]);
|
|
3210
3415
|
const items = useMemo4(() => shown.flatMap((section) => section.items), [shown]);
|
|
3211
3416
|
const keys = items.map(itemKey).join("\n");
|
|
3212
|
-
const [highlight, setHighlight] =
|
|
3417
|
+
const [highlight, setHighlight] = useState10(0);
|
|
3213
3418
|
const base = useId2();
|
|
3214
3419
|
const listboxId = `${base}-list`;
|
|
3215
|
-
const chosen =
|
|
3216
|
-
|
|
3217
|
-
|
|
3420
|
+
const chosen = useRef11(null);
|
|
3421
|
+
useEffect6(() => void (chosen.current = highlight > 0 ? keys.split("\n")[highlight] ?? null : null), [highlight]);
|
|
3422
|
+
useEffect6(() => {
|
|
3218
3423
|
const at = chosen.current ? keys.split("\n").indexOf(chosen.current) : -1;
|
|
3219
3424
|
setHighlight(at > 0 ? at : 0);
|
|
3220
3425
|
}, [keys]);
|
|
@@ -3239,7 +3444,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3239
3444
|
}
|
|
3240
3445
|
}), [items, highlight, onSelect]);
|
|
3241
3446
|
const open = rect !== null && items.length > 0;
|
|
3242
|
-
|
|
3447
|
+
useEffect6(() => {
|
|
3243
3448
|
if (!editorElement || !open) return;
|
|
3244
3449
|
editorElement.setAttribute("aria-autocomplete", "list");
|
|
3245
3450
|
editorElement.setAttribute("aria-haspopup", "listbox");
|
|
@@ -3248,11 +3453,11 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3248
3453
|
for (const name of ["aria-autocomplete", "aria-haspopup", "aria-controls", "aria-activedescendant"]) editorElement.removeAttribute(name);
|
|
3249
3454
|
};
|
|
3250
3455
|
}, [editorElement, open, listboxId]);
|
|
3251
|
-
|
|
3456
|
+
useEffect6(() => {
|
|
3252
3457
|
if (!editorElement || !open) return;
|
|
3253
3458
|
editorElement.setAttribute("aria-activedescendant", `${base}-${highlight}`);
|
|
3254
3459
|
}, [editorElement, open, base, highlight]);
|
|
3255
|
-
const scrollRef =
|
|
3460
|
+
const scrollRef = useCallback4((el) => {
|
|
3256
3461
|
el?.scrollIntoView({ block: "nearest" });
|
|
3257
3462
|
}, []);
|
|
3258
3463
|
if (items.length === 0) return null;
|
|
@@ -3262,7 +3467,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3262
3467
|
const { label, description, leading, shortcut, hint, size } = row(item);
|
|
3263
3468
|
return (
|
|
3264
3469
|
// A row of a list the editor drives from its caret: focus stays in the text, so the row is no Tab stop.
|
|
3265
|
-
/* @__PURE__ */
|
|
3470
|
+
/* @__PURE__ */ jsx50(
|
|
3266
3471
|
MenuItem,
|
|
3267
3472
|
{
|
|
3268
3473
|
role: "option",
|
|
@@ -3287,17 +3492,17 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3287
3492
|
)
|
|
3288
3493
|
);
|
|
3289
3494
|
};
|
|
3290
|
-
return /* @__PURE__ */
|
|
3291
|
-
i > 0 && /* @__PURE__ */
|
|
3292
|
-
section.label ? /* @__PURE__ */
|
|
3495
|
+
return /* @__PURE__ */ jsx50(Popover, { anchor: rect, open: rect !== null, side: "top", align: "left", className: width, maxHeight, ariaLabel, children: /* @__PURE__ */ jsx50("div", { id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "flex flex-col", children: shown.map((section, i) => /* @__PURE__ */ jsxs35("div", { className: "contents", children: [
|
|
3496
|
+
i > 0 && /* @__PURE__ */ jsx50(MenuSeparator, {}),
|
|
3497
|
+
section.label ? /* @__PURE__ */ jsx50("div", { role: "group", "aria-label": section.label, children: /* @__PURE__ */ jsx50(MenuSection, { label: section.label, className: section.className, children: section.items.map(drawRow) }) }) : section.items.map(drawRow)
|
|
3293
3498
|
] }, section.label ?? i)) }) });
|
|
3294
3499
|
}
|
|
3295
3500
|
|
|
3296
3501
|
// src/Toolbar.tsx
|
|
3297
3502
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
3298
|
-
import { jsx as
|
|
3503
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
3299
3504
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
3300
|
-
const strip = /* @__PURE__ */
|
|
3505
|
+
const strip = /* @__PURE__ */ jsx51(
|
|
3301
3506
|
BaseToolbar.Root,
|
|
3302
3507
|
{
|
|
3303
3508
|
"aria-label": ariaLabel,
|
|
@@ -3308,27 +3513,27 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
3308
3513
|
}
|
|
3309
3514
|
);
|
|
3310
3515
|
if (!surface) return strip;
|
|
3311
|
-
return /* @__PURE__ */
|
|
3516
|
+
return /* @__PURE__ */ jsx51(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
3312
3517
|
}
|
|
3313
3518
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
3314
|
-
return /* @__PURE__ */
|
|
3519
|
+
return /* @__PURE__ */ jsx51(
|
|
3315
3520
|
BaseToolbar.Button,
|
|
3316
3521
|
{
|
|
3317
3522
|
ref,
|
|
3318
3523
|
disabled: disabled || !!disabledReason,
|
|
3319
3524
|
focusableWhenDisabled: true,
|
|
3320
|
-
render: /* @__PURE__ */
|
|
3525
|
+
render: /* @__PURE__ */ jsx51(IconButton, { disabled, disabledReason, ...props })
|
|
3321
3526
|
}
|
|
3322
3527
|
);
|
|
3323
3528
|
}
|
|
3324
3529
|
function ToolbarLink({ ref, href, ...props }) {
|
|
3325
|
-
return /* @__PURE__ */
|
|
3530
|
+
return /* @__PURE__ */ jsx51(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx51(IconButton, { href, ...props }) });
|
|
3326
3531
|
}
|
|
3327
3532
|
function ToolbarInput({ size, ...props }) {
|
|
3328
|
-
return /* @__PURE__ */
|
|
3533
|
+
return /* @__PURE__ */ jsx51(BaseToolbar.Input, { render: /* @__PURE__ */ jsx51(TextInput, { size }), ...props });
|
|
3329
3534
|
}
|
|
3330
3535
|
function ToolbarSeparator({ className }) {
|
|
3331
|
-
return /* @__PURE__ */
|
|
3536
|
+
return /* @__PURE__ */ jsx51(
|
|
3332
3537
|
BaseToolbar.Separator,
|
|
3333
3538
|
{
|
|
3334
3539
|
orientation: "vertical",
|
|
@@ -3338,9 +3543,9 @@ function ToolbarSeparator({ className }) {
|
|
|
3338
3543
|
}
|
|
3339
3544
|
|
|
3340
3545
|
// src/ReactionPicker.tsx
|
|
3341
|
-
import { jsx as
|
|
3546
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
3342
3547
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
3343
|
-
return /* @__PURE__ */
|
|
3548
|
+
return /* @__PURE__ */ jsx52(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
3344
3549
|
/*
|
|
3345
3550
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
3346
3551
|
would become the toolbar's item and the button inside it would never
|
|
@@ -3350,14 +3555,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
3350
3555
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
3351
3556
|
and both say the meaning rather than the glyph.
|
|
3352
3557
|
*/
|
|
3353
|
-
/* @__PURE__ */
|
|
3558
|
+
/* @__PURE__ */ jsx52(
|
|
3354
3559
|
ToolbarButton,
|
|
3355
3560
|
{
|
|
3356
3561
|
"aria-label": option.label,
|
|
3357
3562
|
tooltip: option.label,
|
|
3358
3563
|
onClick: () => onSelect(option.emoji),
|
|
3359
3564
|
className: "size-7",
|
|
3360
|
-
children: /* @__PURE__ */
|
|
3565
|
+
children: /* @__PURE__ */ jsx52("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
|
|
3361
3566
|
},
|
|
3362
3567
|
option.emoji
|
|
3363
3568
|
)
|
|
@@ -3366,23 +3571,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
3366
3571
|
|
|
3367
3572
|
// src/PreviewCard.tsx
|
|
3368
3573
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
3369
|
-
import { jsx as
|
|
3574
|
+
import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3370
3575
|
var GAP6 = 12;
|
|
3371
3576
|
var VIEWPORT_PAD6 = 8;
|
|
3372
3577
|
var OPEN_DELAY2 = 350;
|
|
3373
3578
|
var CLOSE_DELAY = 200;
|
|
3374
3579
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, contentClassName, wrapperClassName }) {
|
|
3375
|
-
return /* @__PURE__ */
|
|
3376
|
-
/* @__PURE__ */
|
|
3580
|
+
return /* @__PURE__ */ jsxs36(BasePreviewCard.Root, { children: [
|
|
3581
|
+
/* @__PURE__ */ jsx53(
|
|
3377
3582
|
BasePreviewCard.Trigger,
|
|
3378
3583
|
{
|
|
3379
3584
|
delay,
|
|
3380
3585
|
closeDelay,
|
|
3381
|
-
render: /* @__PURE__ */
|
|
3586
|
+
render: /* @__PURE__ */ jsx53("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
3382
3587
|
children
|
|
3383
3588
|
}
|
|
3384
3589
|
),
|
|
3385
|
-
/* @__PURE__ */
|
|
3590
|
+
/* @__PURE__ */ jsx53(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx53(
|
|
3386
3591
|
BasePreviewCard.Positioner,
|
|
3387
3592
|
{
|
|
3388
3593
|
side,
|
|
@@ -3390,12 +3595,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
3390
3595
|
sideOffset: GAP6,
|
|
3391
3596
|
collisionPadding: VIEWPORT_PAD6,
|
|
3392
3597
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
3393
|
-
children: /* @__PURE__ */
|
|
3598
|
+
children: /* @__PURE__ */ jsx53(
|
|
3394
3599
|
BasePreviewCard.Popup,
|
|
3395
3600
|
{
|
|
3396
3601
|
className: cn("w-[360px] p-0 outline-none", className),
|
|
3397
|
-
render: /* @__PURE__ */
|
|
3398
|
-
children: /* @__PURE__ */
|
|
3602
|
+
render: /* @__PURE__ */ jsx53(MenuPanel, {}),
|
|
3603
|
+
children: /* @__PURE__ */ jsx53(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
|
|
3399
3604
|
}
|
|
3400
3605
|
)
|
|
3401
3606
|
}
|
|
@@ -3404,15 +3609,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
3404
3609
|
}
|
|
3405
3610
|
|
|
3406
3611
|
// src/Rail.tsx
|
|
3407
|
-
import { jsx as
|
|
3612
|
+
import { jsx as jsx54 } from "react/jsx-runtime";
|
|
3408
3613
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
3409
|
-
return /* @__PURE__ */
|
|
3614
|
+
return /* @__PURE__ */ jsx54("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
3410
3615
|
}
|
|
3411
3616
|
|
|
3412
3617
|
// src/RailItem.tsx
|
|
3413
|
-
import { jsx as
|
|
3618
|
+
import { jsx as jsx55, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3414
3619
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
3415
|
-
return /* @__PURE__ */
|
|
3620
|
+
return /* @__PURE__ */ jsxs37(
|
|
3416
3621
|
"a",
|
|
3417
3622
|
{
|
|
3418
3623
|
href,
|
|
@@ -3420,14 +3625,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
3420
3625
|
className: cn("group flex h-12 w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
3421
3626
|
...props,
|
|
3422
3627
|
children: [
|
|
3423
|
-
/* @__PURE__ */
|
|
3628
|
+
/* @__PURE__ */ jsx55(
|
|
3424
3629
|
"div",
|
|
3425
3630
|
{
|
|
3426
3631
|
className: cn(
|
|
3427
3632
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
3428
3633
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
3429
3634
|
),
|
|
3430
|
-
children: /* @__PURE__ */
|
|
3635
|
+
children: /* @__PURE__ */ jsx55(
|
|
3431
3636
|
"span",
|
|
3432
3637
|
{
|
|
3433
3638
|
className: cn(
|
|
@@ -3439,14 +3644,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
3439
3644
|
)
|
|
3440
3645
|
}
|
|
3441
3646
|
),
|
|
3442
|
-
/* @__PURE__ */
|
|
3647
|
+
/* @__PURE__ */ jsx55("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
3443
3648
|
]
|
|
3444
3649
|
}
|
|
3445
3650
|
);
|
|
3446
3651
|
}
|
|
3447
3652
|
|
|
3448
3653
|
// src/Property.tsx
|
|
3449
|
-
import { jsx as
|
|
3654
|
+
import { jsx as jsx56, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3450
3655
|
var VALUE_CLASSES = "contents";
|
|
3451
3656
|
function Property({ label, layout = "row", children, className }) {
|
|
3452
3657
|
if (layout === "stacked") {
|
|
@@ -3454,25 +3659,25 @@ function Property({ label, layout = "row", children, className }) {
|
|
|
3454
3659
|
// gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
|
|
3455
3660
|
// Peek's topic-details sections already sit at 12px, Ship's rail was
|
|
3456
3661
|
// 6px, and unifying means the bigger, calmer one.
|
|
3457
|
-
/* @__PURE__ */
|
|
3458
|
-
/* @__PURE__ */
|
|
3459
|
-
/* @__PURE__ */
|
|
3662
|
+
/* @__PURE__ */ jsxs38("dl", { className: cn("flex flex-col gap-3", className), children: [
|
|
3663
|
+
/* @__PURE__ */ jsx56("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
|
|
3664
|
+
/* @__PURE__ */ jsx56("dd", { className: VALUE_CLASSES, children })
|
|
3460
3665
|
] })
|
|
3461
3666
|
);
|
|
3462
3667
|
}
|
|
3463
|
-
return /* @__PURE__ */
|
|
3464
|
-
/* @__PURE__ */
|
|
3465
|
-
/* @__PURE__ */
|
|
3668
|
+
return /* @__PURE__ */ jsxs38("dl", { className: cn("flex items-center gap-2", className), children: [
|
|
3669
|
+
/* @__PURE__ */ jsx56("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
|
|
3670
|
+
/* @__PURE__ */ jsx56("dd", { className: VALUE_CLASSES, children })
|
|
3466
3671
|
] });
|
|
3467
3672
|
}
|
|
3468
3673
|
|
|
3469
3674
|
// src/Reaction.tsx
|
|
3470
3675
|
import { Toggle } from "@base-ui/react/toggle";
|
|
3471
|
-
import { jsx as
|
|
3676
|
+
import { jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3472
3677
|
function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
3473
3678
|
return (
|
|
3474
3679
|
// @estiva-escape(no-copied-look): W1 (Katerina, 24 September: leave alone): a reaction pill shares four words with a field's box by coincidence
|
|
3475
|
-
/* @__PURE__ */
|
|
3680
|
+
/* @__PURE__ */ jsxs39(
|
|
3476
3681
|
Toggle,
|
|
3477
3682
|
{
|
|
3478
3683
|
pressed,
|
|
@@ -3494,8 +3699,8 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
3494
3699
|
),
|
|
3495
3700
|
...props,
|
|
3496
3701
|
children: [
|
|
3497
|
-
/* @__PURE__ */
|
|
3498
|
-
/* @__PURE__ */
|
|
3702
|
+
/* @__PURE__ */ jsx57("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
|
|
3703
|
+
/* @__PURE__ */ jsx57("span", { className: CHIP_TEXT_CLASSES, children: count })
|
|
3499
3704
|
]
|
|
3500
3705
|
}
|
|
3501
3706
|
)
|
|
@@ -3505,9 +3710,9 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
3505
3710
|
// src/SearchInput.tsx
|
|
3506
3711
|
import "react";
|
|
3507
3712
|
import { Input as Input3 } from "@base-ui/react/input";
|
|
3508
|
-
import { jsx as
|
|
3713
|
+
import { jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3509
3714
|
function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
|
|
3510
|
-
return /* @__PURE__ */
|
|
3715
|
+
return /* @__PURE__ */ jsxs40(
|
|
3511
3716
|
"div",
|
|
3512
3717
|
{
|
|
3513
3718
|
className: cn(
|
|
@@ -3519,7 +3724,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3519
3724
|
className
|
|
3520
3725
|
),
|
|
3521
3726
|
children: [
|
|
3522
|
-
/* @__PURE__ */
|
|
3727
|
+
/* @__PURE__ */ jsx58(
|
|
3523
3728
|
Input3,
|
|
3524
3729
|
{
|
|
3525
3730
|
className: cn("flex-1 min-w-0 text-input-value", BARE_INPUT_CLASSES),
|
|
@@ -3527,42 +3732,42 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3527
3732
|
...props
|
|
3528
3733
|
}
|
|
3529
3734
|
),
|
|
3530
|
-
shortcut && /* @__PURE__ */
|
|
3735
|
+
shortcut && /* @__PURE__ */ jsx58(Kbd, { children: shortcut })
|
|
3531
3736
|
]
|
|
3532
3737
|
}
|
|
3533
3738
|
);
|
|
3534
3739
|
}
|
|
3535
3740
|
|
|
3536
3741
|
// src/Panel.tsx
|
|
3537
|
-
import { jsx as
|
|
3742
|
+
import { jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3538
3743
|
function Frame({ title, chevron = false, actions, children, footer, bodyClassName, bodyRef, onBodyScroll, className, broken = false }) {
|
|
3539
|
-
return /* @__PURE__ */
|
|
3540
|
-
/* @__PURE__ */
|
|
3744
|
+
return /* @__PURE__ */ jsxs41("div", { className: cn("flex h-full min-h-0 flex-1 flex-col", className), children: [
|
|
3745
|
+
/* @__PURE__ */ jsx59(ContainerHeader, { title, chevron, actions }),
|
|
3541
3746
|
broken ? (
|
|
3542
3747
|
// The message takes the room the body had and centres itself in it.
|
|
3543
|
-
/* @__PURE__ */
|
|
3544
|
-
) : /* @__PURE__ */
|
|
3545
|
-
!broken && footer && /* @__PURE__ */
|
|
3748
|
+
/* @__PURE__ */ jsx59("div", { className: "flex min-h-0 flex-1 flex-col px-4", children })
|
|
3749
|
+
) : /* @__PURE__ */ jsx59(ScrollArea, { className: "min-h-0 flex-1", contentClassName: bodyClassName, viewportRef: bodyRef, onScroll: onBodyScroll, children }),
|
|
3750
|
+
!broken && footer && /* @__PURE__ */ jsx59("div", { className: "shrink-0", children: footer })
|
|
3546
3751
|
] });
|
|
3547
3752
|
}
|
|
3548
3753
|
function Panel(props) {
|
|
3549
|
-
return /* @__PURE__ */
|
|
3754
|
+
return /* @__PURE__ */ jsx59(
|
|
3550
3755
|
ErrorBoundary,
|
|
3551
3756
|
{
|
|
3552
3757
|
label: "panel",
|
|
3553
3758
|
frame: (message) => (
|
|
3554
3759
|
// Only the name comes back with the message: the actions and the footer may be what threw.
|
|
3555
|
-
/* @__PURE__ */
|
|
3760
|
+
/* @__PURE__ */ jsx59(Frame, { title: props.title, chevron: props.chevron, className: props.className, broken: true, children: message })
|
|
3556
3761
|
),
|
|
3557
|
-
children: /* @__PURE__ */
|
|
3762
|
+
children: /* @__PURE__ */ jsx59(Frame, { ...props })
|
|
3558
3763
|
}
|
|
3559
3764
|
);
|
|
3560
3765
|
}
|
|
3561
3766
|
|
|
3562
3767
|
// src/ListColumn.tsx
|
|
3563
|
-
import { jsx as
|
|
3564
|
-
function Column({ title, chevron = false, actions, above, collapsed = false, children, className, broken = false }) {
|
|
3565
|
-
return /* @__PURE__ */
|
|
3768
|
+
import { jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3769
|
+
function Column({ title, chevron = false, titleMenu, actions, above, collapsed = false, children, className, broken = false }) {
|
|
3770
|
+
return /* @__PURE__ */ jsxs42(
|
|
3566
3771
|
"div",
|
|
3567
3772
|
{
|
|
3568
3773
|
className: cn(
|
|
@@ -3573,35 +3778,35 @@ function Column({ title, chevron = false, actions, above, collapsed = false, chi
|
|
|
3573
3778
|
),
|
|
3574
3779
|
"data-collapsed": collapsed || void 0,
|
|
3575
3780
|
children: [
|
|
3576
|
-
/* @__PURE__ */
|
|
3781
|
+
/* @__PURE__ */ jsx60(ContainerHeader, { title, chevron, titleMenu, actions }),
|
|
3577
3782
|
above,
|
|
3578
3783
|
broken ? (
|
|
3579
3784
|
// The message takes the room the list had and centres itself in it (Katerina, 19 September).
|
|
3580
|
-
/* @__PURE__ */
|
|
3581
|
-
) : /* @__PURE__ */
|
|
3785
|
+
/* @__PURE__ */ jsx60("div", { className: "flex min-h-0 flex-1 flex-col px-3", children })
|
|
3786
|
+
) : /* @__PURE__ */ jsx60(ScrollArea, { className: "flex-1", contentClassName: "flex flex-col gap-0.5 px-3 pt-4 pb-3", children })
|
|
3582
3787
|
]
|
|
3583
3788
|
}
|
|
3584
3789
|
);
|
|
3585
3790
|
}
|
|
3586
3791
|
function ListColumn(props) {
|
|
3587
|
-
return /* @__PURE__ */
|
|
3792
|
+
return /* @__PURE__ */ jsx60(
|
|
3588
3793
|
ErrorBoundary,
|
|
3589
3794
|
{
|
|
3590
3795
|
label: "list panel",
|
|
3591
3796
|
frame: (message) => (
|
|
3592
3797
|
// Only the name comes back with the message: the actions and the row above may be what threw.
|
|
3593
|
-
/* @__PURE__ */
|
|
3798
|
+
/* @__PURE__ */ jsx60(Column, { title: props.title, chevron: props.chevron, collapsed: props.collapsed, className: props.className, broken: true, children: message })
|
|
3594
3799
|
),
|
|
3595
|
-
children: /* @__PURE__ */
|
|
3800
|
+
children: /* @__PURE__ */ jsx60(Column, { ...props })
|
|
3596
3801
|
}
|
|
3597
3802
|
);
|
|
3598
3803
|
}
|
|
3599
3804
|
|
|
3600
3805
|
// src/Tabs.tsx
|
|
3601
3806
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
3602
|
-
import { jsx as
|
|
3807
|
+
import { jsx as jsx61, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
3603
3808
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
3604
|
-
return /* @__PURE__ */
|
|
3809
|
+
return /* @__PURE__ */ jsx61(
|
|
3605
3810
|
BaseTabs.Root,
|
|
3606
3811
|
{
|
|
3607
3812
|
value: active,
|
|
@@ -3609,14 +3814,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3609
3814
|
if (details.reason === "none") onChange(value);
|
|
3610
3815
|
},
|
|
3611
3816
|
className,
|
|
3612
|
-
children: /* @__PURE__ */
|
|
3817
|
+
children: /* @__PURE__ */ jsx61(
|
|
3613
3818
|
BaseTabs.List,
|
|
3614
3819
|
{
|
|
3615
3820
|
activateOnFocus: true,
|
|
3616
3821
|
"aria-label": aria["aria-label"],
|
|
3617
3822
|
"aria-labelledby": aria["aria-labelledby"],
|
|
3618
3823
|
className: "flex items-center gap-2",
|
|
3619
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
3824
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs43(
|
|
3620
3825
|
BaseTabs.Tab,
|
|
3621
3826
|
{
|
|
3622
3827
|
value: tab.id,
|
|
@@ -3629,9 +3834,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3629
3834
|
),
|
|
3630
3835
|
children: [
|
|
3631
3836
|
tab.icon,
|
|
3632
|
-
/* @__PURE__ */
|
|
3837
|
+
/* @__PURE__ */ jsxs43("span", { className: "flex items-baseline", children: [
|
|
3633
3838
|
tab.label,
|
|
3634
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
3839
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx61("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
3635
3840
|
] })
|
|
3636
3841
|
]
|
|
3637
3842
|
},
|
|
@@ -3647,7 +3852,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3647
3852
|
import { createContext as createContext6, useContext as useContext6, useMemo as useMemo5 } from "react";
|
|
3648
3853
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
3649
3854
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
3650
|
-
import { jsx as
|
|
3855
|
+
import { jsx as jsx62, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
3651
3856
|
var SURFACE_STYLES = {
|
|
3652
3857
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
|
|
3653
3858
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
|
|
@@ -3683,16 +3888,16 @@ var pillClassName = (type, hasAction, className) => cn(
|
|
|
3683
3888
|
);
|
|
3684
3889
|
function LeadingIcon({ type }) {
|
|
3685
3890
|
const Icon = ICONS[type];
|
|
3686
|
-
return /* @__PURE__ */
|
|
3891
|
+
return /* @__PURE__ */ jsx62(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
|
|
3687
3892
|
}
|
|
3688
3893
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
3689
3894
|
const hasAction = !!(actionLabel && onAction);
|
|
3690
|
-
return /* @__PURE__ */
|
|
3691
|
-
/* @__PURE__ */
|
|
3692
|
-
leadingIcon && /* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3895
|
+
return /* @__PURE__ */ jsxs44("div", { className: pillClassName(type, hasAction, className), children: [
|
|
3896
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3897
|
+
leadingIcon && /* @__PURE__ */ jsx62(LeadingIcon, { type }),
|
|
3898
|
+
/* @__PURE__ */ jsx62("span", { className: LABEL_CLASSES, children: label })
|
|
3694
3899
|
] }),
|
|
3695
|
-
hasAction && /* @__PURE__ */
|
|
3900
|
+
hasAction && /* @__PURE__ */ jsx62(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
3696
3901
|
] });
|
|
3697
3902
|
}
|
|
3698
3903
|
var ToastContext = createContext6(null);
|
|
@@ -3713,9 +3918,9 @@ function ToastProvider({ children }) {
|
|
|
3713
3918
|
}),
|
|
3714
3919
|
[manager]
|
|
3715
3920
|
);
|
|
3716
|
-
return /* @__PURE__ */
|
|
3921
|
+
return /* @__PURE__ */ jsx62(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs44(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
|
|
3717
3922
|
children,
|
|
3718
|
-
/* @__PURE__ */
|
|
3923
|
+
/* @__PURE__ */ jsx62(BaseToast.Portal, { children: /* @__PURE__ */ jsx62(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx62(ToastList, {}) }) })
|
|
3719
3924
|
] }) });
|
|
3720
3925
|
}
|
|
3721
3926
|
function ToastList() {
|
|
@@ -3723,25 +3928,25 @@ function ToastList() {
|
|
|
3723
3928
|
return toasts.map((toast) => {
|
|
3724
3929
|
const type = toast.type ?? "neutral";
|
|
3725
3930
|
const { leadingIcon = true, actionLabel, onAction } = toast.data ?? {};
|
|
3726
|
-
return /* @__PURE__ */
|
|
3931
|
+
return /* @__PURE__ */ jsxs44(
|
|
3727
3932
|
BaseToast.Root,
|
|
3728
3933
|
{
|
|
3729
3934
|
toast,
|
|
3730
3935
|
swipeDirection: ["left", "down"],
|
|
3731
3936
|
className: pillClassName(type, !!actionLabel, "pointer-events-auto data-[limited]:hidden"),
|
|
3732
3937
|
children: [
|
|
3733
|
-
/* @__PURE__ */
|
|
3734
|
-
leadingIcon && /* @__PURE__ */
|
|
3735
|
-
/* @__PURE__ */
|
|
3938
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3939
|
+
leadingIcon && /* @__PURE__ */ jsx62(LeadingIcon, { type }),
|
|
3940
|
+
/* @__PURE__ */ jsx62(BaseToast.Title, { render: /* @__PURE__ */ jsx62("span", {}), className: LABEL_CLASSES })
|
|
3736
3941
|
] }),
|
|
3737
|
-
actionLabel && /* @__PURE__ */
|
|
3942
|
+
actionLabel && /* @__PURE__ */ jsx62(
|
|
3738
3943
|
BaseToast.Action,
|
|
3739
3944
|
{
|
|
3740
3945
|
onClick: () => {
|
|
3741
3946
|
onAction?.();
|
|
3742
3947
|
close(toast.id);
|
|
3743
3948
|
},
|
|
3744
|
-
render: /* @__PURE__ */
|
|
3949
|
+
render: /* @__PURE__ */ jsx62(Button, { variant: "outlined", size: "small", children: actionLabel })
|
|
3745
3950
|
}
|
|
3746
3951
|
)
|
|
3747
3952
|
]
|
|
@@ -3774,6 +3979,7 @@ export {
|
|
|
3774
3979
|
Avatar,
|
|
3775
3980
|
AvatarGroup,
|
|
3776
3981
|
Banner,
|
|
3982
|
+
BlockHandle,
|
|
3777
3983
|
Breadcrumb,
|
|
3778
3984
|
Button,
|
|
3779
3985
|
Card,
|
|
@@ -3858,6 +4064,7 @@ export {
|
|
|
3858
4064
|
TopBar,
|
|
3859
4065
|
UnreadDot,
|
|
3860
4066
|
WithTooltip,
|
|
4067
|
+
blockAtY,
|
|
3861
4068
|
cn,
|
|
3862
4069
|
hueFor,
|
|
3863
4070
|
initialsFor,
|