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