@estiva-app/ui 0.38.0 → 0.39.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/AppShell.d.ts +5 -2
- package/dist/AppShell.d.ts.map +1 -1
- package/dist/Sidebar.d.ts +7 -1
- package/dist/Sidebar.d.ts.map +1 -1
- package/dist/TopBar.d.ts +5 -2
- package/dist/TopBar.d.ts.map +1 -1
- package/dist/index.js +467 -462
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/registry.json +8 -6
- package/src/AppShell.mdx +11 -3
- package/src/AppShell.stories.tsx +19 -0
- package/src/AppShell.test.tsx +20 -0
- package/src/AppShell.tsx +43 -24
- package/src/Sidebar.tsx +10 -2
- package/src/TopBar.mdx +6 -4
- package/src/TopBar.tsx +6 -3
package/dist/index.js
CHANGED
|
@@ -35,16 +35,110 @@ function cn(...inputs) {
|
|
|
35
35
|
return twMerge(clsx(inputs));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// src/Link.tsx
|
|
39
|
+
import { jsx } from "react/jsx-runtime";
|
|
40
|
+
var VARIANT_CLASSES = {
|
|
41
|
+
text: "text-info-default underline underline-offset-2 hover:opacity-80",
|
|
42
|
+
quiet: "hover:underline",
|
|
43
|
+
underlined: "underline underline-offset-2 hover:text-text-primary",
|
|
44
|
+
plain: ""
|
|
45
|
+
};
|
|
46
|
+
function Link({ href, variant = "text", external = false, truncate = false, className, children, ...props }) {
|
|
47
|
+
return /* @__PURE__ */ jsx(
|
|
48
|
+
"a",
|
|
49
|
+
{
|
|
50
|
+
href,
|
|
51
|
+
...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
52
|
+
className: cn(VARIANT_CLASSES[variant], truncate && "truncate", className),
|
|
53
|
+
...props,
|
|
54
|
+
children
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/Card.tsx
|
|
60
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
61
|
+
var FILL_CLASSES = {
|
|
62
|
+
surface: "bg-bg-surface border-border-default",
|
|
63
|
+
elevated: "bg-bg-elevated border-border-default",
|
|
64
|
+
inset: "bg-bg-inset border-border-subtle",
|
|
65
|
+
none: "border-border-subtle"
|
|
66
|
+
};
|
|
67
|
+
var HAIRLINE_HOVER_CLASSES = {
|
|
68
|
+
surface: "hover:border-border-strong",
|
|
69
|
+
elevated: "hover:border-border-strong",
|
|
70
|
+
inset: "hover:border-border-default",
|
|
71
|
+
none: "hover:border-border-default"
|
|
72
|
+
};
|
|
73
|
+
var HAIRLINE_HELD_CLASSES = {
|
|
74
|
+
surface: "border-border-strong",
|
|
75
|
+
elevated: "border-border-strong",
|
|
76
|
+
inset: "border-border-default",
|
|
77
|
+
none: "border-border-default"
|
|
78
|
+
};
|
|
79
|
+
var ATTENTION_CLASSES = {
|
|
80
|
+
accent: "border-accent-muted hover:border-accent-muted",
|
|
81
|
+
warning: "border-warning-muted hover:border-warning-muted"
|
|
82
|
+
};
|
|
83
|
+
function Card({
|
|
84
|
+
fill = "surface",
|
|
85
|
+
href,
|
|
86
|
+
hover = href ? "hairline" : "none",
|
|
87
|
+
quietUntilHover = false,
|
|
88
|
+
hovered = false,
|
|
89
|
+
selected = false,
|
|
90
|
+
active = false,
|
|
91
|
+
attention,
|
|
92
|
+
unreadable = false,
|
|
93
|
+
clip = false,
|
|
94
|
+
className,
|
|
95
|
+
children,
|
|
96
|
+
...props
|
|
97
|
+
}) {
|
|
98
|
+
const still = selected || active;
|
|
99
|
+
const classes = cn(
|
|
100
|
+
"rounded-lg border",
|
|
101
|
+
// A card that never changes has nothing to ease between, and the apps' still cards carry no transition.
|
|
102
|
+
hover !== "none" && "transition-colors",
|
|
103
|
+
FILL_CLASSES[fill],
|
|
104
|
+
quietUntilHover && "border-transparent",
|
|
105
|
+
!still && hover === "hairline" && HAIRLINE_HOVER_CLASSES[fill],
|
|
106
|
+
!still && hover === "fill" && "hover:bg-bg-hover hover:border-border-default",
|
|
107
|
+
!still && hovered && hover === "hairline" && HAIRLINE_HELD_CLASSES[fill],
|
|
108
|
+
!still && hovered && hover === "fill" && "bg-bg-hover border-border-default",
|
|
109
|
+
// The one you are on can still be clicked (it opens again); the one being changed cannot.
|
|
110
|
+
!active && hover !== "none" && !href && props.onClick && "cursor-pointer",
|
|
111
|
+
selected && "bg-bg-selected border-border-subtle",
|
|
112
|
+
active && "bg-bg-selected border-accent-primary",
|
|
113
|
+
!active && attention && ATTENTION_CLASSES[attention],
|
|
114
|
+
unreadable && "border-dashed",
|
|
115
|
+
clip && "overflow-hidden",
|
|
116
|
+
href && "block",
|
|
117
|
+
className
|
|
118
|
+
);
|
|
119
|
+
if (href !== void 0) {
|
|
120
|
+
const { ref, ...anchorProps } = props;
|
|
121
|
+
return (
|
|
122
|
+
// @estiva-escape(no-copied-look, no-restyled-part): a card that leads somewhere is drawn on Link's anchor (UIG-27 ruling 1), so this frame is Card's own look, not Link restyled
|
|
123
|
+
/* @__PURE__ */ jsx2(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return (
|
|
127
|
+
// @estiva-escape(no-copied-look): N6 (Katerina, 24 September: leave alone): a card that cuts its content to its corners shares four words with the palette's window by coincidence
|
|
128
|
+
/* @__PURE__ */ jsx2("div", { className: classes, ...props, children })
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
38
132
|
// src/ScrollArea.tsx
|
|
39
133
|
import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
|
|
40
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
134
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
41
135
|
var BAR = "z-10 flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
|
|
42
136
|
var THUMB = "rounded-full bg-border-strong";
|
|
43
137
|
function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, viewportRef, onScroll, children }) {
|
|
44
138
|
const vertical = orientation !== "horizontal";
|
|
45
139
|
const horizontal = orientation !== "vertical";
|
|
46
140
|
return /* @__PURE__ */ jsxs(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
|
|
47
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ jsx3(
|
|
48
142
|
BaseScrollArea.Viewport,
|
|
49
143
|
{
|
|
50
144
|
ref: viewportRef,
|
|
@@ -53,17 +147,33 @@ function ScrollArea({ orientation = "vertical", className, viewportClassName, co
|
|
|
53
147
|
"h-full w-full outline-none data-[has-overflow-x]:overscroll-x-contain data-[has-overflow-y]:overscroll-y-contain",
|
|
54
148
|
viewportClassName
|
|
55
149
|
),
|
|
56
|
-
children: /* @__PURE__ */
|
|
150
|
+
children: /* @__PURE__ */ jsx3(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children })
|
|
57
151
|
}
|
|
58
152
|
),
|
|
59
|
-
vertical && /* @__PURE__ */
|
|
60
|
-
horizontal && /* @__PURE__ */
|
|
61
|
-
vertical && horizontal && /* @__PURE__ */
|
|
153
|
+
vertical && /* @__PURE__ */ jsx3(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5 data-[has-overflow-y]:opacity-100"), children: /* @__PURE__ */ jsx3(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
|
|
154
|
+
horizontal && /* @__PURE__ */ jsx3(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5 data-[has-overflow-x]:opacity-100"), children: /* @__PURE__ */ jsx3(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
|
|
155
|
+
vertical && horizontal && /* @__PURE__ */ jsx3(BaseScrollArea.Corner, {})
|
|
62
156
|
] });
|
|
63
157
|
}
|
|
64
158
|
|
|
159
|
+
// src/Sidebar.tsx
|
|
160
|
+
import { createContext, useContext } from "react";
|
|
161
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
162
|
+
var SidebarOnGround = createContext(false);
|
|
163
|
+
function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
|
|
164
|
+
const onGround = useContext(SidebarOnGround);
|
|
165
|
+
return /* @__PURE__ */ jsx4(
|
|
166
|
+
"nav",
|
|
167
|
+
{
|
|
168
|
+
"aria-label": ariaLabel,
|
|
169
|
+
className: cn("flex w-60 shrink-0 flex-col", !onGround && "border-r border-border-default bg-bg-surface", className),
|
|
170
|
+
children: /* @__PURE__ */ jsx4(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
65
175
|
// src/TopBar.tsx
|
|
66
|
-
import { jsx as
|
|
176
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
67
177
|
function TopBar({ variant = "solid", menu, logo, search, right, className }) {
|
|
68
178
|
const floating = variant === "floating";
|
|
69
179
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -71,25 +181,26 @@ function TopBar({ variant = "solid", menu, logo, search, right, className }) {
|
|
|
71
181
|
{
|
|
72
182
|
className: cn(
|
|
73
183
|
"flex h-[52px] items-center pl-5 pr-[26px]",
|
|
74
|
-
floating ? "pointer-events-none absolute left-0 right-0 top-0 z-10" : "shrink-0 gap-4 border-b border-border-default bg-bg-surface",
|
|
184
|
+
floating ? "pointer-events-none absolute left-0 right-0 top-0 z-10" : cn("shrink-0 gap-4", variant === "solid" && "border-b border-border-default bg-bg-surface"),
|
|
75
185
|
className
|
|
76
186
|
),
|
|
77
187
|
children: [
|
|
78
188
|
(menu || logo) && /* @__PURE__ */ jsxs2("div", { className: cn("flex shrink-0 items-center gap-2", floating && "pointer-events-auto"), children: [
|
|
79
189
|
menu,
|
|
80
|
-
logo && /* @__PURE__ */
|
|
190
|
+
logo && /* @__PURE__ */ jsx5("div", { className: "flex items-center text-body-2-strong text-text-primary", children: logo })
|
|
81
191
|
] }),
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ jsx5("div", { className: cn("flex min-w-0 flex-1 items-center justify-center", floating && "pointer-events-auto"), children: search }),
|
|
193
|
+
/* @__PURE__ */ jsx5("div", { className: cn("flex shrink-0 items-center gap-[6px]", floating && "pointer-events-auto"), children: right })
|
|
84
194
|
]
|
|
85
195
|
}
|
|
86
196
|
);
|
|
87
197
|
}
|
|
88
198
|
|
|
89
199
|
// src/AppShell.tsx
|
|
90
|
-
import { jsx as
|
|
200
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
91
201
|
function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav, children }) {
|
|
92
|
-
const bar = /* @__PURE__ */
|
|
202
|
+
const bar = /* @__PURE__ */ jsx6(TopBar, { variant, menu, logo, search, right: identity });
|
|
203
|
+
const inset = variant === "inset";
|
|
93
204
|
if (variant === "floating") {
|
|
94
205
|
return (
|
|
95
206
|
// `signal-canvas`: in the Signal theme, the preset draws the control-room dot
|
|
@@ -108,7 +219,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
108
219
|
),
|
|
109
220
|
children: [
|
|
110
221
|
banner,
|
|
111
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ jsx6("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children })
|
|
112
223
|
]
|
|
113
224
|
}
|
|
114
225
|
)
|
|
@@ -116,6 +227,10 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
116
227
|
] })
|
|
117
228
|
);
|
|
118
229
|
}
|
|
230
|
+
const column = /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
231
|
+
banner,
|
|
232
|
+
/* @__PURE__ */ jsx6(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex min-h-full flex-col", children: /* @__PURE__ */ jsx6("main", { className: "flex min-w-0 flex-1 flex-col", children }) })
|
|
233
|
+
] });
|
|
119
234
|
return (
|
|
120
235
|
/* `relative overflow-hidden` is the seal the floating manner already has
|
|
121
236
|
(and the ScrollArea's own root is `relative`, so an absolutely placed
|
|
@@ -129,11 +244,8 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
129
244
|
/* @__PURE__ */ jsxs3("div", { className: "relative flex h-full min-h-0 flex-col overflow-hidden bg-bg-base text-text-primary", children: [
|
|
130
245
|
bar,
|
|
131
246
|
/* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 flex-1", children: [
|
|
132
|
-
nav,
|
|
133
|
-
/* @__PURE__ */
|
|
134
|
-
banner,
|
|
135
|
-
/* @__PURE__ */ jsx3(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex min-h-full flex-col", children: /* @__PURE__ */ jsx3("main", { className: "flex min-w-0 flex-1 flex-col", children }) })
|
|
136
|
-
] })
|
|
247
|
+
/* @__PURE__ */ jsx6(SidebarOnGround.Provider, { value: inset, children: nav }),
|
|
248
|
+
inset ? /* @__PURE__ */ jsx6(Card, { fill: "surface", clip: true, className: "mb-4 mr-4 flex min-h-0 min-w-0 flex-1 flex-col", children: column }) : /* @__PURE__ */ jsx6("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: column })
|
|
137
249
|
] })
|
|
138
250
|
] })
|
|
139
251
|
);
|
|
@@ -160,117 +272,23 @@ import {
|
|
|
160
272
|
IconX as IconX2
|
|
161
273
|
} from "@tabler/icons-react";
|
|
162
274
|
|
|
163
|
-
// src/Link.tsx
|
|
164
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
165
|
-
var VARIANT_CLASSES = {
|
|
166
|
-
text: "text-info-default underline underline-offset-2 hover:opacity-80",
|
|
167
|
-
quiet: "hover:underline",
|
|
168
|
-
underlined: "underline underline-offset-2 hover:text-text-primary",
|
|
169
|
-
plain: ""
|
|
170
|
-
};
|
|
171
|
-
function Link({ href, variant = "text", external = false, truncate = false, className, children, ...props }) {
|
|
172
|
-
return /* @__PURE__ */ jsx4(
|
|
173
|
-
"a",
|
|
174
|
-
{
|
|
175
|
-
href,
|
|
176
|
-
...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
177
|
-
className: cn(VARIANT_CLASSES[variant], truncate && "truncate", className),
|
|
178
|
-
...props,
|
|
179
|
-
children
|
|
180
|
-
}
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// src/Card.tsx
|
|
185
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
186
|
-
var FILL_CLASSES = {
|
|
187
|
-
surface: "bg-bg-surface border-border-default",
|
|
188
|
-
elevated: "bg-bg-elevated border-border-default",
|
|
189
|
-
inset: "bg-bg-inset border-border-subtle",
|
|
190
|
-
none: "border-border-subtle"
|
|
191
|
-
};
|
|
192
|
-
var HAIRLINE_HOVER_CLASSES = {
|
|
193
|
-
surface: "hover:border-border-strong",
|
|
194
|
-
elevated: "hover:border-border-strong",
|
|
195
|
-
inset: "hover:border-border-default",
|
|
196
|
-
none: "hover:border-border-default"
|
|
197
|
-
};
|
|
198
|
-
var HAIRLINE_HELD_CLASSES = {
|
|
199
|
-
surface: "border-border-strong",
|
|
200
|
-
elevated: "border-border-strong",
|
|
201
|
-
inset: "border-border-default",
|
|
202
|
-
none: "border-border-default"
|
|
203
|
-
};
|
|
204
|
-
var ATTENTION_CLASSES = {
|
|
205
|
-
accent: "border-accent-muted hover:border-accent-muted",
|
|
206
|
-
warning: "border-warning-muted hover:border-warning-muted"
|
|
207
|
-
};
|
|
208
|
-
function Card({
|
|
209
|
-
fill = "surface",
|
|
210
|
-
href,
|
|
211
|
-
hover = href ? "hairline" : "none",
|
|
212
|
-
quietUntilHover = false,
|
|
213
|
-
hovered = false,
|
|
214
|
-
selected = false,
|
|
215
|
-
active = false,
|
|
216
|
-
attention,
|
|
217
|
-
unreadable = false,
|
|
218
|
-
clip = false,
|
|
219
|
-
className,
|
|
220
|
-
children,
|
|
221
|
-
...props
|
|
222
|
-
}) {
|
|
223
|
-
const still = selected || active;
|
|
224
|
-
const classes = cn(
|
|
225
|
-
"rounded-lg border",
|
|
226
|
-
// A card that never changes has nothing to ease between, and the apps' still cards carry no transition.
|
|
227
|
-
hover !== "none" && "transition-colors",
|
|
228
|
-
FILL_CLASSES[fill],
|
|
229
|
-
quietUntilHover && "border-transparent",
|
|
230
|
-
!still && hover === "hairline" && HAIRLINE_HOVER_CLASSES[fill],
|
|
231
|
-
!still && hover === "fill" && "hover:bg-bg-hover hover:border-border-default",
|
|
232
|
-
!still && hovered && hover === "hairline" && HAIRLINE_HELD_CLASSES[fill],
|
|
233
|
-
!still && hovered && hover === "fill" && "bg-bg-hover border-border-default",
|
|
234
|
-
// The one you are on can still be clicked (it opens again); the one being changed cannot.
|
|
235
|
-
!active && hover !== "none" && !href && props.onClick && "cursor-pointer",
|
|
236
|
-
selected && "bg-bg-selected border-border-subtle",
|
|
237
|
-
active && "bg-bg-selected border-accent-primary",
|
|
238
|
-
!active && attention && ATTENTION_CLASSES[attention],
|
|
239
|
-
unreadable && "border-dashed",
|
|
240
|
-
clip && "overflow-hidden",
|
|
241
|
-
href && "block",
|
|
242
|
-
className
|
|
243
|
-
);
|
|
244
|
-
if (href !== void 0) {
|
|
245
|
-
const { ref, ...anchorProps } = props;
|
|
246
|
-
return (
|
|
247
|
-
// @estiva-escape(no-copied-look, no-restyled-part): a card that leads somewhere is drawn on Link's anchor (UIG-27 ruling 1), so this frame is Card's own look, not Link restyled
|
|
248
|
-
/* @__PURE__ */ jsx5(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
return (
|
|
252
|
-
// @estiva-escape(no-copied-look): N6 (Katerina, 24 September: leave alone): a card that cuts its content to its corners shares four words with the palette's window by coincidence
|
|
253
|
-
/* @__PURE__ */ jsx5("div", { className: classes, ...props, children })
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
275
|
// src/IconButton.tsx
|
|
258
276
|
import { Button as BaseButton } from "@base-ui/react/button";
|
|
259
277
|
|
|
260
278
|
// src/formBusy.ts
|
|
261
|
-
import { createContext, useContext } from "react";
|
|
262
|
-
var FormBusyContext =
|
|
279
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
280
|
+
var FormBusyContext = createContext2(false);
|
|
263
281
|
function useFormBusy() {
|
|
264
|
-
return
|
|
282
|
+
return useContext2(FormBusyContext);
|
|
265
283
|
}
|
|
266
284
|
|
|
267
285
|
// src/Tooltip.tsx
|
|
268
286
|
import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
|
|
269
287
|
|
|
270
288
|
// src/Kbd.tsx
|
|
271
|
-
import { jsx as
|
|
289
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
272
290
|
function Kbd({ children, className, tone = "default" }) {
|
|
273
|
-
return /* @__PURE__ */
|
|
291
|
+
return /* @__PURE__ */ jsx7(
|
|
274
292
|
"kbd",
|
|
275
293
|
{
|
|
276
294
|
className: cn(
|
|
@@ -302,21 +320,21 @@ var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:fon
|
|
|
302
320
|
var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
|
|
303
321
|
|
|
304
322
|
// src/Tooltip.tsx
|
|
305
|
-
import { jsx as
|
|
323
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
306
324
|
var OPEN_DELAY = 300;
|
|
307
325
|
function TooltipProvider({ delay = OPEN_DELAY, closeDelay, timeout, children }) {
|
|
308
|
-
return /* @__PURE__ */
|
|
326
|
+
return /* @__PURE__ */ jsx8(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
|
|
309
327
|
}
|
|
310
328
|
function Tooltip({ label, shortcut, className, ...props }) {
|
|
311
329
|
return /* @__PURE__ */ jsxs4("div", { role: "tooltip", className: cn(FLOATING_SURFACE_CLASSES, "border-border-tooltip bg-bg-tooltip", "min-h-[30px] max-w-80 flex items-center justify-center gap-1.5 px-2 py-1", className), ...props, children: [
|
|
312
|
-
/* @__PURE__ */
|
|
313
|
-
shortcut && /* @__PURE__ */
|
|
330
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 text-caption text-text-tooltip break-words", children: label }),
|
|
331
|
+
shortcut && /* @__PURE__ */ jsx8(Kbd, { tone: "tooltip", children: shortcut })
|
|
314
332
|
] });
|
|
315
333
|
}
|
|
316
334
|
var GAP = 6;
|
|
317
335
|
var VIEWPORT_PAD = 8;
|
|
318
336
|
function TooltipSurface({ label, shortcut, placement }) {
|
|
319
|
-
return /* @__PURE__ */
|
|
337
|
+
return /* @__PURE__ */ jsx8(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx8(
|
|
320
338
|
BaseTooltip.Positioner,
|
|
321
339
|
{
|
|
322
340
|
side: placement,
|
|
@@ -325,10 +343,10 @@ function TooltipSurface({ label, shortcut, placement }) {
|
|
|
325
343
|
collisionPadding: VIEWPORT_PAD,
|
|
326
344
|
positionMethod: "fixed",
|
|
327
345
|
className: "pointer-events-none z-[9999]",
|
|
328
|
-
children: /* @__PURE__ */
|
|
346
|
+
children: /* @__PURE__ */ jsx8(
|
|
329
347
|
BaseTooltip.Popup,
|
|
330
348
|
{
|
|
331
|
-
render: /* @__PURE__ */
|
|
349
|
+
render: /* @__PURE__ */ jsx8(Tooltip, { label, shortcut }),
|
|
332
350
|
className: cn(
|
|
333
351
|
"transition-[opacity,transform] duration-[120ms] ease-out motion-reduce:transition-none",
|
|
334
352
|
"data-[ending-style]:duration-[80ms] data-[instant]:duration-0",
|
|
@@ -344,19 +362,19 @@ function TooltipSurface({ label, shortcut, placement }) {
|
|
|
344
362
|
function WithTooltip({ label, shortcut, placement = "top", wrapperClassName, inline = false, children }) {
|
|
345
363
|
const Wrapper = inline ? "span" : "div";
|
|
346
364
|
return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
|
|
347
|
-
/* @__PURE__ */
|
|
348
|
-
/* @__PURE__ */
|
|
365
|
+
/* @__PURE__ */ jsx8(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: /* @__PURE__ */ jsx8(Wrapper, { className: cn("inline-flex shrink-0", inline && "align-top", wrapperClassName) }), children }),
|
|
366
|
+
/* @__PURE__ */ jsx8(TooltipSurface, { label, shortcut, placement })
|
|
349
367
|
] });
|
|
350
368
|
}
|
|
351
369
|
function TooltipTrigger({ label, shortcut, placement = "top", children }) {
|
|
352
370
|
return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
|
|
353
|
-
/* @__PURE__ */
|
|
354
|
-
/* @__PURE__ */
|
|
371
|
+
/* @__PURE__ */ jsx8(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: children }),
|
|
372
|
+
/* @__PURE__ */ jsx8(TooltipSurface, { label, shortcut, placement })
|
|
355
373
|
] });
|
|
356
374
|
}
|
|
357
375
|
|
|
358
376
|
// src/IconButton.tsx
|
|
359
|
-
import { jsx as
|
|
377
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
360
378
|
function IconButton({
|
|
361
379
|
variant = "muted",
|
|
362
380
|
pressed,
|
|
@@ -407,7 +425,7 @@ function IconButton({
|
|
|
407
425
|
off && "cursor-not-allowed",
|
|
408
426
|
className
|
|
409
427
|
);
|
|
410
|
-
const button = href && !unusable ? /* @__PURE__ */
|
|
428
|
+
const button = href && !unusable ? /* @__PURE__ */ jsx9("a", { href, className: look(false), ...props, children }) : /* @__PURE__ */ jsx9(
|
|
411
429
|
BaseButton,
|
|
412
430
|
{
|
|
413
431
|
type,
|
|
@@ -421,7 +439,7 @@ function IconButton({
|
|
|
421
439
|
);
|
|
422
440
|
const label = disabledReason ?? tooltip;
|
|
423
441
|
if (label) {
|
|
424
|
-
return /* @__PURE__ */
|
|
442
|
+
return /* @__PURE__ */ jsx9(TooltipTrigger, { label, shortcut: disabledReason ? void 0 : tooltipShortcut, placement: tooltipPlacement, children: button });
|
|
425
443
|
}
|
|
426
444
|
return button;
|
|
427
445
|
}
|
|
@@ -430,10 +448,10 @@ function IconButton({
|
|
|
430
448
|
import { useRef } from "react";
|
|
431
449
|
import { Dialog } from "@base-ui/react/dialog";
|
|
432
450
|
import { IconX } from "@tabler/icons-react";
|
|
433
|
-
import { jsx as
|
|
451
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
434
452
|
function Lightbox({ src, alt, onClose, className }) {
|
|
435
453
|
const popupRef = useRef(null);
|
|
436
|
-
return /* @__PURE__ */
|
|
454
|
+
return /* @__PURE__ */ jsx10(
|
|
437
455
|
Dialog.Root,
|
|
438
456
|
{
|
|
439
457
|
open: true,
|
|
@@ -441,7 +459,7 @@ function Lightbox({ src, alt, onClose, className }) {
|
|
|
441
459
|
if (!open) onClose();
|
|
442
460
|
},
|
|
443
461
|
children: /* @__PURE__ */ jsxs5(Dialog.Portal, { children: [
|
|
444
|
-
/* @__PURE__ */
|
|
462
|
+
/* @__PURE__ */ jsx10(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim-strong" }),
|
|
445
463
|
/* @__PURE__ */ jsxs5(
|
|
446
464
|
Dialog.Popup,
|
|
447
465
|
{
|
|
@@ -451,7 +469,7 @@ function Lightbox({ src, alt, onClose, className }) {
|
|
|
451
469
|
className: "fixed inset-0 z-50 flex items-center justify-center p-8 outline-none",
|
|
452
470
|
onClick: onClose,
|
|
453
471
|
children: [
|
|
454
|
-
/* @__PURE__ */
|
|
472
|
+
/* @__PURE__ */ jsx10(
|
|
455
473
|
"img",
|
|
456
474
|
{
|
|
457
475
|
src,
|
|
@@ -460,12 +478,12 @@ function Lightbox({ src, alt, onClose, className }) {
|
|
|
460
478
|
className: cn("max-w-full max-h-full object-contain rounded-lg", className)
|
|
461
479
|
}
|
|
462
480
|
),
|
|
463
|
-
/* @__PURE__ */
|
|
481
|
+
/* @__PURE__ */ jsx10(
|
|
464
482
|
Dialog.Close,
|
|
465
483
|
{
|
|
466
484
|
"aria-label": "Close",
|
|
467
485
|
className: "absolute top-4 right-4 size-8 rounded-full bg-bg-tooltip border border-border-tooltip-key flex items-center justify-center text-text-tooltip-key hover:text-text-tooltip",
|
|
468
|
-
children: /* @__PURE__ */
|
|
486
|
+
children: /* @__PURE__ */ jsx10(IconX, { size: 16, stroke: 1.5 })
|
|
469
487
|
}
|
|
470
488
|
)
|
|
471
489
|
]
|
|
@@ -477,7 +495,7 @@ function Lightbox({ src, alt, onClose, className }) {
|
|
|
477
495
|
}
|
|
478
496
|
|
|
479
497
|
// src/AttachmentCard.tsx
|
|
480
|
-
import { Fragment, jsx as
|
|
498
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
481
499
|
var ICON_BY_EXTENSION = {
|
|
482
500
|
pdf: IconFileTypePdf,
|
|
483
501
|
doc: IconFileTypeDocx,
|
|
@@ -511,7 +529,7 @@ var NAME_CLASSES = "text-caption font-medium text-text-primary truncate";
|
|
|
511
529
|
var NOTE_CLASSES = "text-small tracking-wide leading-tight truncate";
|
|
512
530
|
function TypeIcon({ name }) {
|
|
513
531
|
const Icon = ICON_BY_EXTENSION[extensionOf(name)] ?? IconFile;
|
|
514
|
-
return /* @__PURE__ */
|
|
532
|
+
return /* @__PURE__ */ jsx11(Icon, { size: 20, stroke: 1.5 });
|
|
515
533
|
}
|
|
516
534
|
function Truncating({ text, hint, className, wrapperClassName, placement }) {
|
|
517
535
|
const ref = useRef2(null);
|
|
@@ -533,9 +551,9 @@ function Truncating({ text, hint, className, wrapperClassName, placement }) {
|
|
|
533
551
|
observer.disconnect();
|
|
534
552
|
};
|
|
535
553
|
}, [text, cut]);
|
|
536
|
-
const line = /* @__PURE__ */
|
|
554
|
+
const line = /* @__PURE__ */ jsx11("span", { ref, className, children: text });
|
|
537
555
|
if (!hint && !cut) return line;
|
|
538
|
-
return /* @__PURE__ */
|
|
556
|
+
return /* @__PURE__ */ jsx11(WithTooltip, { label: hint ?? text, placement, wrapperClassName: cn("min-w-0 flex-col", wrapperClassName), children: line });
|
|
539
557
|
}
|
|
540
558
|
function useRemoteImage(url, fetchImage) {
|
|
541
559
|
const [result, setResult] = useState({});
|
|
@@ -614,7 +632,7 @@ function AttachmentCard({
|
|
|
614
632
|
const full = useRemoteImage(opened ? remoteFullSrc : void 0, fetchImage);
|
|
615
633
|
const openable = image && !!picture && !pending;
|
|
616
634
|
const openPicture = onOpen ?? (openable ? () => setOpened(true) : void 0);
|
|
617
|
-
const viewer = opened && picture ? /* @__PURE__ */
|
|
635
|
+
const viewer = opened && picture ? /* @__PURE__ */ jsx11(Lightbox, { src: full.src ?? picture, alt: alt ?? name, onClose: () => setOpened(false) }) : null;
|
|
618
636
|
const saveHere = download ? () => {
|
|
619
637
|
const source = remoteFullSrc ?? remoteSrc;
|
|
620
638
|
if (source && fetchImage) {
|
|
@@ -643,10 +661,10 @@ function AttachmentCard({
|
|
|
643
661
|
className: cn("group relative flex items-center gap-2 w-[200px] p-1.5 pr-3", failed ? "border-error-default" : warning && "border-warning-default", className),
|
|
644
662
|
...props,
|
|
645
663
|
children: [
|
|
646
|
-
/* @__PURE__ */
|
|
664
|
+
/* @__PURE__ */ jsx11("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx11(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx11(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx11(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx11("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx11("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
|
|
647
665
|
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
|
|
648
|
-
/* @__PURE__ */
|
|
649
|
-
/* @__PURE__ */
|
|
666
|
+
/* @__PURE__ */ jsx11(Truncating, { text: name, className: NAME_CLASSES, placement: onRemove ? "bottom" : void 0 }),
|
|
667
|
+
/* @__PURE__ */ jsx11(
|
|
650
668
|
Truncating,
|
|
651
669
|
{
|
|
652
670
|
text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
|
|
@@ -655,7 +673,7 @@ function AttachmentCard({
|
|
|
655
673
|
}
|
|
656
674
|
)
|
|
657
675
|
] }),
|
|
658
|
-
onRemove && /* @__PURE__ */
|
|
676
|
+
onRemove && /* @__PURE__ */ jsx11(
|
|
659
677
|
BaseButton2,
|
|
660
678
|
{
|
|
661
679
|
type: "button",
|
|
@@ -665,7 +683,7 @@ function AttachmentCard({
|
|
|
665
683
|
event.stopPropagation();
|
|
666
684
|
onRemove();
|
|
667
685
|
},
|
|
668
|
-
children: /* @__PURE__ */
|
|
686
|
+
children: /* @__PURE__ */ jsx11(IconX2, { size: 11, stroke: 1.75 })
|
|
669
687
|
}
|
|
670
688
|
)
|
|
671
689
|
]
|
|
@@ -675,7 +693,7 @@ function AttachmentCard({
|
|
|
675
693
|
}
|
|
676
694
|
const downloadControl = saving ? (
|
|
677
695
|
// @estiva-escape(no-restyled-part): Download shows when its card is pointed at or focused, AttachmentCard's own action; IconButton has no reveal on its card's hover (UIG-9, Katerina 17 September)
|
|
678
|
-
/* @__PURE__ */
|
|
696
|
+
/* @__PURE__ */ jsx11(
|
|
679
697
|
IconButton,
|
|
680
698
|
{
|
|
681
699
|
variant: "muted",
|
|
@@ -686,7 +704,7 @@ function AttachmentCard({
|
|
|
686
704
|
event.stopPropagation();
|
|
687
705
|
saving();
|
|
688
706
|
},
|
|
689
|
-
children: /* @__PURE__ */
|
|
707
|
+
children: /* @__PURE__ */ jsx11(IconDownload, { size: 16, stroke: 1.5 })
|
|
690
708
|
}
|
|
691
709
|
)
|
|
692
710
|
) : null;
|
|
@@ -695,26 +713,26 @@ function AttachmentCard({
|
|
|
695
713
|
// `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
|
|
696
714
|
// status says what it is doing — loading — to a reader that cannot see the pulse.
|
|
697
715
|
// @estiva-escape(no-restyled-part): the loading pulse is AttachmentCard's own state; Card has no loading state (UIG-9, Katerina 17 September)
|
|
698
|
-
/* @__PURE__ */
|
|
716
|
+
/* @__PURE__ */ jsx11(Card, { role: "status", fill: "inset", "aria-busy": "true", "aria-label": `Loading ${name}`, className: cn("w-[180px] h-28 animate-pulse", className), ...props, children: null })
|
|
699
717
|
);
|
|
700
718
|
}
|
|
701
719
|
if (drawnState === "unreadable") {
|
|
702
720
|
return (
|
|
703
721
|
// @estiva-escape(no-restyled-part): a file that could not be read is faded as well as dashed, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
|
|
704
722
|
/* @__PURE__ */ jsxs6(Card, { fill: "inset", unreadable: true, className: cn("flex items-center gap-2 w-[240px] p-1.5 opacity-70", className), ...props, children: [
|
|
705
|
-
/* @__PURE__ */
|
|
723
|
+
/* @__PURE__ */ jsx11("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx11(TypeIcon, { name }) }),
|
|
706
724
|
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
725
|
+
/* @__PURE__ */ jsx11(Truncating, { text: name, className: NAME_CLASSES }),
|
|
726
|
+
/* @__PURE__ */ jsx11("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
|
|
709
727
|
] })
|
|
710
728
|
] })
|
|
711
729
|
);
|
|
712
730
|
}
|
|
713
731
|
if (image && picture) {
|
|
714
|
-
const thumbnail = /* @__PURE__ */
|
|
715
|
-
return /* @__PURE__ */ jsxs6(
|
|
732
|
+
const thumbnail = /* @__PURE__ */ jsx11("img", { src: picture, alt: alt ?? name, className: "w-full h-28 object-cover" });
|
|
733
|
+
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
716
734
|
/* @__PURE__ */ jsxs6(Card, { fill: "inset", hover: "hairline", clip: true, className: cn("group relative flex flex-col w-[180px]", className), ...props, children: [
|
|
717
|
-
openPicture ? /* @__PURE__ */
|
|
735
|
+
openPicture ? /* @__PURE__ */ jsx11(
|
|
718
736
|
BaseButton2,
|
|
719
737
|
{
|
|
720
738
|
type: "button",
|
|
@@ -726,26 +744,26 @@ function AttachmentCard({
|
|
|
726
744
|
},
|
|
727
745
|
children: thumbnail
|
|
728
746
|
}
|
|
729
|
-
) : /* @__PURE__ */
|
|
747
|
+
) : /* @__PURE__ */ jsx11("div", { className: "block w-full", children: thumbnail }),
|
|
730
748
|
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 pl-2 pr-1 py-1 min-w-0", children: [
|
|
731
|
-
/* @__PURE__ */
|
|
749
|
+
/* @__PURE__ */ jsx11(Truncating, { text: name, className: "flex-1 text-caption text-text-primary truncate", wrapperClassName: "flex-1" }),
|
|
732
750
|
downloadControl
|
|
733
751
|
] })
|
|
734
752
|
] }),
|
|
735
753
|
viewer
|
|
736
754
|
] });
|
|
737
755
|
}
|
|
738
|
-
const body = /* @__PURE__ */ jsxs6(
|
|
739
|
-
/* @__PURE__ */
|
|
756
|
+
const body = /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
757
|
+
/* @__PURE__ */ jsx11("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx11(TypeIcon, { name }) }),
|
|
740
758
|
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
|
|
741
|
-
/* @__PURE__ */
|
|
742
|
-
/* @__PURE__ */
|
|
759
|
+
/* @__PURE__ */ jsx11(Truncating, { text: name, className: NAME_CLASSES }),
|
|
760
|
+
/* @__PURE__ */ jsx11("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
|
|
743
761
|
] })
|
|
744
762
|
] });
|
|
745
763
|
return (
|
|
746
764
|
// @estiva-escape(no-restyled-part): a file that cannot be opened is faded, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
|
|
747
765
|
/* @__PURE__ */ jsxs6(Card, { fill: "inset", hover: address ? "hairline" : "none", className: cn("group flex items-center gap-2 w-[240px] p-1.5 pr-1", !address && "opacity-70", className), ...props, children: [
|
|
748
|
-
address ? /* @__PURE__ */
|
|
766
|
+
address ? /* @__PURE__ */ jsx11(Link, { href: address, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
|
|
749
767
|
downloadControl
|
|
750
768
|
] })
|
|
751
769
|
);
|
|
@@ -754,7 +772,7 @@ function AttachmentCard({
|
|
|
754
772
|
// src/Avatar.tsx
|
|
755
773
|
import { Avatar as BaseAvatar } from "@base-ui/react/avatar";
|
|
756
774
|
import { IconUserFilled } from "@tabler/icons-react";
|
|
757
|
-
import { jsx as
|
|
775
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
758
776
|
var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
|
|
759
777
|
var hueFor = (key) => {
|
|
760
778
|
let h = 0;
|
|
@@ -771,12 +789,12 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
771
789
|
return /* @__PURE__ */ jsxs7(
|
|
772
790
|
BaseAvatar.Root,
|
|
773
791
|
{
|
|
774
|
-
render: /* @__PURE__ */
|
|
792
|
+
render: /* @__PURE__ */ jsx12("div", {}),
|
|
775
793
|
...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
|
|
776
794
|
className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
|
|
777
795
|
style: { width: size, height: size },
|
|
778
796
|
children: [
|
|
779
|
-
src && /* @__PURE__ */
|
|
797
|
+
src && /* @__PURE__ */ jsx12(
|
|
780
798
|
BaseAvatar.Image,
|
|
781
799
|
{
|
|
782
800
|
src,
|
|
@@ -785,10 +803,10 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
785
803
|
className: "w-full h-full object-cover data-[error]:hidden"
|
|
786
804
|
}
|
|
787
805
|
),
|
|
788
|
-
label ? /* @__PURE__ */
|
|
806
|
+
label ? /* @__PURE__ */ jsx12(
|
|
789
807
|
BaseAvatar.Fallback,
|
|
790
808
|
{
|
|
791
|
-
render: /* @__PURE__ */
|
|
809
|
+
render: /* @__PURE__ */ jsx12("div", {}),
|
|
792
810
|
className: "w-full h-full flex items-center justify-center font-semibold leading-none",
|
|
793
811
|
style: {
|
|
794
812
|
/* eslint-disable no-restricted-syntax -- @estiva-escape: the per-person palette (the note at
|
|
@@ -802,32 +820,32 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
802
820
|
background: `linear-gradient(160deg, color-mix(in srgb, ${hueFor(label)} 92%, #fff) 0%, color-mix(in srgb, ${hueFor(label)} 70%, #0b0d11) 100%)`
|
|
803
821
|
/* eslint-enable no-restricted-syntax */
|
|
804
822
|
},
|
|
805
|
-
children: /* @__PURE__ */
|
|
823
|
+
children: /* @__PURE__ */ jsx12("span", { className: "[text-box:trim-both_cap_alphabetic]", children: initialsFor(label) })
|
|
806
824
|
}
|
|
807
|
-
) : /* @__PURE__ */
|
|
825
|
+
) : /* @__PURE__ */ jsx12(BaseAvatar.Fallback, { render: /* @__PURE__ */ jsx12("div", {}), className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx12(IconUserFilled, { size: Math.round(size * 0.5) }) })
|
|
808
826
|
]
|
|
809
827
|
}
|
|
810
828
|
);
|
|
811
829
|
}
|
|
812
830
|
|
|
813
831
|
// src/AvatarGroup.tsx
|
|
814
|
-
import { jsx as
|
|
832
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
815
833
|
function AvatarGroup({ members, size = 24 }) {
|
|
816
834
|
const visible = members.slice(0, 3);
|
|
817
835
|
const overlap = Math.round(size / 3);
|
|
818
836
|
const ring = size / 12;
|
|
819
|
-
return /* @__PURE__ */
|
|
837
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
|
|
820
838
|
/*
|
|
821
839
|
The wrapper carries the overlap and the ring; the face carries
|
|
822
840
|
neither. It must never clip — see the note at the top of the file —
|
|
823
841
|
so it has the avatar's own radius and no overflow of its own.
|
|
824
842
|
*/
|
|
825
|
-
/* @__PURE__ */
|
|
843
|
+
/* @__PURE__ */ jsx13(
|
|
826
844
|
"span",
|
|
827
845
|
{
|
|
828
846
|
className: "relative flex rounded-sm",
|
|
829
847
|
style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
|
|
830
|
-
children: /* @__PURE__ */
|
|
848
|
+
children: /* @__PURE__ */ jsx13(Avatar, { size, name: member.name, src: member.picture, label: member.name })
|
|
831
849
|
},
|
|
832
850
|
i
|
|
833
851
|
)
|
|
@@ -839,7 +857,7 @@ import { IconX as IconX3 } from "@tabler/icons-react";
|
|
|
839
857
|
|
|
840
858
|
// src/Button.tsx
|
|
841
859
|
import { Button as BaseButton3 } from "@base-ui/react/button";
|
|
842
|
-
import { jsx as
|
|
860
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
843
861
|
function Button({
|
|
844
862
|
variant = "muted",
|
|
845
863
|
size = "default",
|
|
@@ -901,11 +919,11 @@ function Button({
|
|
|
901
919
|
]
|
|
902
920
|
}
|
|
903
921
|
);
|
|
904
|
-
return disabledReason ? /* @__PURE__ */
|
|
922
|
+
return disabledReason ? /* @__PURE__ */ jsx14(TooltipTrigger, { label: disabledReason, children: button }) : button;
|
|
905
923
|
}
|
|
906
924
|
|
|
907
925
|
// src/Banner.tsx
|
|
908
|
-
import { jsx as
|
|
926
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
909
927
|
var TONE_STYLES = {
|
|
910
928
|
ok: "bg-success-muted text-success-default",
|
|
911
929
|
error: "bg-error-muted text-error-default",
|
|
@@ -915,14 +933,14 @@ var TONE_STYLES = {
|
|
|
915
933
|
function Banner({ tone, children, icon, action, onDismiss, dismissLabel = "Dismiss", className }) {
|
|
916
934
|
const role = tone === "error" ? "alert" : "status";
|
|
917
935
|
if (!onDismiss && !icon && !action) {
|
|
918
|
-
return /* @__PURE__ */
|
|
936
|
+
return /* @__PURE__ */ jsx15("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
|
|
919
937
|
}
|
|
920
938
|
const oneLine = Boolean(icon || action);
|
|
921
939
|
return /* @__PURE__ */ jsxs9("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
|
|
922
|
-
icon && /* @__PURE__ */
|
|
923
|
-
/* @__PURE__ */
|
|
924
|
-
action && /* @__PURE__ */
|
|
925
|
-
onDismiss && /* @__PURE__ */
|
|
940
|
+
icon && /* @__PURE__ */ jsx15("span", { className: "flex shrink-0", children: icon }),
|
|
941
|
+
/* @__PURE__ */ jsx15("span", { className: cn("min-w-0 flex-1", oneLine && "truncate"), children }),
|
|
942
|
+
action && /* @__PURE__ */ jsx15(Button, { variant: "muted", size: "small", className: "shrink-0", onClick: action.onClick, children: action.label }),
|
|
943
|
+
onDismiss && /* @__PURE__ */ jsx15(IconButton, { variant: "current", "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0", children: /* @__PURE__ */ jsx15(IconX3, { size: 16, stroke: 1.5 }) })
|
|
926
944
|
] });
|
|
927
945
|
}
|
|
928
946
|
|
|
@@ -930,7 +948,7 @@ function Banner({ tone, children, icon, action, onDismiss, dismissLabel = "Dismi
|
|
|
930
948
|
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
|
|
931
949
|
import { Field as BaseField } from "@base-ui/react/field";
|
|
932
950
|
import { IconCheck } from "@tabler/icons-react";
|
|
933
|
-
import { jsx as
|
|
951
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
934
952
|
function squareClasses(checked, disabled, interactive, className) {
|
|
935
953
|
return cn(
|
|
936
954
|
"inline-flex items-center justify-center size-4 shrink-0 rounded-sm border transition-colors",
|
|
@@ -947,14 +965,14 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row
|
|
|
947
965
|
const formBusy = useFormBusy();
|
|
948
966
|
const disabled = ownDisabled || formBusy;
|
|
949
967
|
if (!onChange) {
|
|
950
|
-
const picture = /* @__PURE__ */
|
|
968
|
+
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 }) }) });
|
|
951
969
|
if (label === void 0) return picture;
|
|
952
970
|
return /* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-2", children: [
|
|
953
971
|
picture,
|
|
954
|
-
/* @__PURE__ */
|
|
972
|
+
/* @__PURE__ */ jsx16("span", { className: WORDS_CLASSES, children: label })
|
|
955
973
|
] });
|
|
956
974
|
}
|
|
957
|
-
const box = /* @__PURE__ */
|
|
975
|
+
const box = /* @__PURE__ */ jsx16(
|
|
958
976
|
BaseCheckbox.Root,
|
|
959
977
|
{
|
|
960
978
|
checked,
|
|
@@ -964,25 +982,25 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row
|
|
|
964
982
|
onCheckedChange: (next) => onChange(next),
|
|
965
983
|
onClick: (e) => e.stopPropagation(),
|
|
966
984
|
className: (state) => squareClasses(state.checked, state.disabled, true, className),
|
|
967
|
-
children: /* @__PURE__ */
|
|
985
|
+
children: /* @__PURE__ */ jsx16(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx16(IconCheck, { size: 12, stroke: 3 }) })
|
|
968
986
|
}
|
|
969
987
|
);
|
|
970
988
|
if (label === void 0) return box;
|
|
971
989
|
if (row) {
|
|
972
|
-
return /* @__PURE__ */
|
|
990
|
+
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: [
|
|
973
991
|
leading,
|
|
974
|
-
/* @__PURE__ */
|
|
992
|
+
/* @__PURE__ */ jsx16("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
|
|
975
993
|
box
|
|
976
994
|
] }) });
|
|
977
995
|
}
|
|
978
|
-
return /* @__PURE__ */
|
|
996
|
+
return /* @__PURE__ */ jsx16(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs10(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
|
|
979
997
|
box,
|
|
980
|
-
/* @__PURE__ */
|
|
998
|
+
/* @__PURE__ */ jsx16("span", { className: WORDS_CLASSES, children: label })
|
|
981
999
|
] }) });
|
|
982
1000
|
}
|
|
983
1001
|
|
|
984
1002
|
// src/Chip.tsx
|
|
985
|
-
import { jsx as
|
|
1003
|
+
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
986
1004
|
var typeStyles = {
|
|
987
1005
|
neutral: "bg-bg-inset text-text-primary",
|
|
988
1006
|
brand: "bg-accent-muted text-accent-primary signal:border signal:border-accent-outline",
|
|
@@ -993,7 +1011,7 @@ var typeStyles = {
|
|
|
993
1011
|
};
|
|
994
1012
|
function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className }) {
|
|
995
1013
|
return /* @__PURE__ */ jsxs11("div", { className: 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), children: [
|
|
996
|
-
leadingIcon && /* @__PURE__ */
|
|
1014
|
+
leadingIcon && /* @__PURE__ */ jsx17("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
|
|
997
1015
|
label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
|
|
998
1016
|
// of growing past it — Ship's project chip on an issue row
|
|
999
1017
|
// (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
|
|
@@ -1002,15 +1020,15 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
|
|
|
1002
1020
|
// the screenshot diff caught every descender cut off. `clip` is the
|
|
1003
1021
|
// one overflow that leaves the other axis visible. A chip with no cap
|
|
1004
1022
|
// draws exactly as before.
|
|
1005
|
-
/* @__PURE__ */
|
|
1006
|
-
trailingIcon && /* @__PURE__ */
|
|
1023
|
+
/* @__PURE__ */ jsx17("span", { className: cn("min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide", CHIP_TEXT_CLASSES), children: label }),
|
|
1024
|
+
trailingIcon && /* @__PURE__ */ jsx17("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
1007
1025
|
] });
|
|
1008
1026
|
}
|
|
1009
1027
|
|
|
1010
1028
|
// src/CommandPalette.tsx
|
|
1011
1029
|
import {
|
|
1012
|
-
createContext as
|
|
1013
|
-
useContext as
|
|
1030
|
+
createContext as createContext5,
|
|
1031
|
+
useContext as useContext5,
|
|
1014
1032
|
useEffect as useEffect2,
|
|
1015
1033
|
useLayoutEffect as useLayoutEffect3,
|
|
1016
1034
|
useMemo as useMemo2,
|
|
@@ -1028,17 +1046,17 @@ import { Combobox } from "@base-ui/react/combobox";
|
|
|
1028
1046
|
import { IconX as IconX4 } from "@tabler/icons-react";
|
|
1029
1047
|
|
|
1030
1048
|
// src/Menu.tsx
|
|
1031
|
-
import { createContext as
|
|
1049
|
+
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
1032
1050
|
import { IconChevronRight } from "@tabler/icons-react";
|
|
1033
1051
|
import { Menu as BaseMenu } from "@base-ui/react/menu";
|
|
1034
1052
|
|
|
1035
1053
|
// src/Divider.tsx
|
|
1036
|
-
import { createContext as
|
|
1054
|
+
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
1037
1055
|
import { Separator } from "@base-ui/react/separator";
|
|
1038
|
-
import { jsx as
|
|
1039
|
-
var DividerInPanel =
|
|
1056
|
+
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1057
|
+
var DividerInPanel = createContext3(false);
|
|
1040
1058
|
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
1041
|
-
const inset =
|
|
1059
|
+
const inset = useContext3(DividerInPanel) ? "mx-0" : "mx-3";
|
|
1042
1060
|
if (label && orientation === "horizontal") {
|
|
1043
1061
|
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
1044
1062
|
return /* @__PURE__ */ jsxs12(
|
|
@@ -1048,14 +1066,14 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
|
|
|
1048
1066
|
"aria-label": label,
|
|
1049
1067
|
className: cn("flex shrink-0 items-center gap-2", inset, className),
|
|
1050
1068
|
children: [
|
|
1051
|
-
/* @__PURE__ */
|
|
1052
|
-
/* @__PURE__ */
|
|
1053
|
-
/* @__PURE__ */
|
|
1069
|
+
/* @__PURE__ */ jsx18("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
1070
|
+
/* @__PURE__ */ jsx18("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
1071
|
+
/* @__PURE__ */ jsx18("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
1054
1072
|
]
|
|
1055
1073
|
}
|
|
1056
1074
|
);
|
|
1057
1075
|
}
|
|
1058
|
-
return /* @__PURE__ */
|
|
1076
|
+
return /* @__PURE__ */ jsx18(
|
|
1059
1077
|
Separator,
|
|
1060
1078
|
{
|
|
1061
1079
|
orientation,
|
|
@@ -1071,14 +1089,14 @@ function triggerDisabled(trigger) {
|
|
|
1071
1089
|
}
|
|
1072
1090
|
|
|
1073
1091
|
// src/SectionLabel.tsx
|
|
1074
|
-
import { jsx as
|
|
1092
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
1075
1093
|
function SectionLabel({
|
|
1076
1094
|
children,
|
|
1077
1095
|
tone = "primary",
|
|
1078
1096
|
truncate = false,
|
|
1079
1097
|
className
|
|
1080
1098
|
}) {
|
|
1081
|
-
return /* @__PURE__ */
|
|
1099
|
+
return /* @__PURE__ */ jsx19(
|
|
1082
1100
|
"span",
|
|
1083
1101
|
{
|
|
1084
1102
|
className: cn(
|
|
@@ -1095,10 +1113,10 @@ function SectionLabel({
|
|
|
1095
1113
|
}
|
|
1096
1114
|
|
|
1097
1115
|
// src/Menu.tsx
|
|
1098
|
-
import { Fragment as
|
|
1099
|
-
var MenuContext =
|
|
1116
|
+
import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1117
|
+
var MenuContext = createContext4(null);
|
|
1100
1118
|
function MenuPanel({ children, className, ...props }) {
|
|
1101
|
-
return /* @__PURE__ */
|
|
1119
|
+
return /* @__PURE__ */ jsx20(
|
|
1102
1120
|
"div",
|
|
1103
1121
|
{
|
|
1104
1122
|
className: cn(
|
|
@@ -1137,7 +1155,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1137
1155
|
actionsRef,
|
|
1138
1156
|
modal: false,
|
|
1139
1157
|
children: [
|
|
1140
|
-
/* @__PURE__ */
|
|
1158
|
+
/* @__PURE__ */ jsx20(
|
|
1141
1159
|
BaseMenu.Trigger,
|
|
1142
1160
|
{
|
|
1143
1161
|
render: trigger,
|
|
@@ -1147,7 +1165,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1147
1165
|
closeDelay: HOVER_CLOSE_DELAY
|
|
1148
1166
|
}
|
|
1149
1167
|
),
|
|
1150
|
-
/* @__PURE__ */
|
|
1168
|
+
/* @__PURE__ */ jsx20(BaseMenu.Portal, { children: /* @__PURE__ */ jsx20(
|
|
1151
1169
|
BaseMenu.Positioner,
|
|
1152
1170
|
{
|
|
1153
1171
|
side: "bottom",
|
|
@@ -1155,13 +1173,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1155
1173
|
sideOffset: GAP2,
|
|
1156
1174
|
collisionPadding: VIEWPORT_PAD2,
|
|
1157
1175
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1158
|
-
children: /* @__PURE__ */
|
|
1176
|
+
children: /* @__PURE__ */ jsx20(
|
|
1159
1177
|
BaseMenu.Popup,
|
|
1160
1178
|
{
|
|
1161
1179
|
"data-interactive": true,
|
|
1162
1180
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
1163
|
-
render: /* @__PURE__ */
|
|
1164
|
-
children: /* @__PURE__ */
|
|
1181
|
+
render: /* @__PURE__ */ jsx20(MenuPanel, {}),
|
|
1182
|
+
children: /* @__PURE__ */ jsx20(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col p-2", contentClassName), children: /* @__PURE__ */ jsx20(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx20(DividerInPanel.Provider, { value: true, children }) }) })
|
|
1165
1183
|
}
|
|
1166
1184
|
)
|
|
1167
1185
|
}
|
|
@@ -1171,26 +1189,26 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
1171
1189
|
);
|
|
1172
1190
|
}
|
|
1173
1191
|
function MenuSub({ label, leading, selected, children, className }) {
|
|
1174
|
-
const menu =
|
|
1192
|
+
const menu = useContext4(MenuContext);
|
|
1175
1193
|
if (!isProduction() && menu?.openOnHover) {
|
|
1176
1194
|
console.error(
|
|
1177
1195
|
'[@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".'
|
|
1178
1196
|
);
|
|
1179
1197
|
}
|
|
1180
1198
|
return /* @__PURE__ */ jsxs13(BaseMenu.SubmenuRoot, { children: [
|
|
1181
|
-
/* @__PURE__ */
|
|
1199
|
+
/* @__PURE__ */ jsx20(
|
|
1182
1200
|
BaseMenu.SubmenuTrigger,
|
|
1183
1201
|
{
|
|
1184
1202
|
openOnHover: true,
|
|
1185
1203
|
delay: 0,
|
|
1186
1204
|
closeDelay: 150,
|
|
1187
1205
|
nativeButton: true,
|
|
1188
|
-
render: /* @__PURE__ */
|
|
1206
|
+
render: /* @__PURE__ */ jsx20("button", { type: "button" }),
|
|
1189
1207
|
className: menuItemClassName({ size: "default", selected }),
|
|
1190
|
-
children: /* @__PURE__ */
|
|
1208
|
+
children: /* @__PURE__ */ jsx20(MenuItemBody, { label, leading, submenu: true })
|
|
1191
1209
|
}
|
|
1192
1210
|
),
|
|
1193
|
-
/* @__PURE__ */
|
|
1211
|
+
/* @__PURE__ */ jsx20(BaseMenu.Portal, { children: /* @__PURE__ */ jsx20(
|
|
1194
1212
|
BaseMenu.Positioner,
|
|
1195
1213
|
{
|
|
1196
1214
|
side: "inline-end",
|
|
@@ -1198,7 +1216,7 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
1198
1216
|
sideOffset: GAP2,
|
|
1199
1217
|
collisionPadding: VIEWPORT_PAD2,
|
|
1200
1218
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1201
|
-
children: /* @__PURE__ */
|
|
1219
|
+
children: /* @__PURE__ */ jsx20(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx20(MenuPanel, {}), children })
|
|
1202
1220
|
}
|
|
1203
1221
|
) })
|
|
1204
1222
|
] });
|
|
@@ -1233,25 +1251,25 @@ function menuItemClassName({ size, selected, className }) {
|
|
|
1233
1251
|
);
|
|
1234
1252
|
}
|
|
1235
1253
|
function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
|
|
1236
|
-
const edge = trailing ?? (shortcut ? /* @__PURE__ */
|
|
1237
|
-
return /* @__PURE__ */ jsxs13(
|
|
1238
|
-
leading && /* @__PURE__ */
|
|
1254
|
+
const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx20(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx20(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
|
|
1255
|
+
return /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1256
|
+
leading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1239
1257
|
children ?? /* @__PURE__ */ jsxs13("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
|
|
1240
|
-
/* @__PURE__ */
|
|
1241
|
-
description && /* @__PURE__ */
|
|
1258
|
+
/* @__PURE__ */ jsx20("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
|
|
1259
|
+
description && /* @__PURE__ */ jsx20("span", { className: "truncate text-caption text-text-secondary", children: description })
|
|
1242
1260
|
] }),
|
|
1243
1261
|
(edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
|
|
1244
1262
|
// the wider of the two and never changes, so revealing the hint moves
|
|
1245
1263
|
// nothing. No transition here either — the hint switches on the same
|
|
1246
1264
|
// :hover / `selected` as the fill, in the same frame.
|
|
1247
1265
|
/* @__PURE__ */ jsxs13("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
|
|
1248
|
-
edge && /* @__PURE__ */
|
|
1249
|
-
hint && /* @__PURE__ */
|
|
1266
|
+
edge && /* @__PURE__ */ jsx20("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
|
|
1267
|
+
hint && /* @__PURE__ */ jsx20("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
|
|
1250
1268
|
] })
|
|
1251
1269
|
] });
|
|
1252
1270
|
}
|
|
1253
1271
|
function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
|
|
1254
|
-
const body = /* @__PURE__ */
|
|
1272
|
+
const body = /* @__PURE__ */ jsx20(
|
|
1255
1273
|
MenuItemBody,
|
|
1256
1274
|
{
|
|
1257
1275
|
label,
|
|
@@ -1268,14 +1286,14 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1268
1286
|
}
|
|
1269
1287
|
);
|
|
1270
1288
|
const rowClassName = menuItemClassName({ size, selected, className });
|
|
1271
|
-
if (!
|
|
1272
|
-
return /* @__PURE__ */
|
|
1289
|
+
if (!useContext4(MenuContext)) {
|
|
1290
|
+
return /* @__PURE__ */ jsx20("button", { type: "button", className: rowClassName, ...props, children: body });
|
|
1273
1291
|
}
|
|
1274
|
-
return /* @__PURE__ */
|
|
1292
|
+
return /* @__PURE__ */ jsx20(
|
|
1275
1293
|
BaseMenu.Item,
|
|
1276
1294
|
{
|
|
1277
1295
|
nativeButton: true,
|
|
1278
|
-
render: /* @__PURE__ */
|
|
1296
|
+
render: /* @__PURE__ */ jsx20("button", { type: "button" }),
|
|
1279
1297
|
className: rowClassName,
|
|
1280
1298
|
...props,
|
|
1281
1299
|
children: body
|
|
@@ -1284,13 +1302,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1284
1302
|
}
|
|
1285
1303
|
function EnterHint({ target }) {
|
|
1286
1304
|
return /* @__PURE__ */ jsxs13("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
target && /* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx20(Kbd, { children: "\u21A9 Enter" }),
|
|
1306
|
+
target && /* @__PURE__ */ jsx20("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider leaf:font-mono leaf:text-small leaf:tracking-wider", children: target })
|
|
1289
1307
|
] });
|
|
1290
1308
|
}
|
|
1291
1309
|
function MenuSection({ label, children, className }) {
|
|
1292
|
-
const inMenu =
|
|
1293
|
-
const heading = /* @__PURE__ */
|
|
1310
|
+
const inMenu = useContext4(MenuContext) !== null;
|
|
1311
|
+
const heading = /* @__PURE__ */ jsx20("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx20(SectionLabel, { tone: "secondary", children: label }) });
|
|
1294
1312
|
if (!inMenu) {
|
|
1295
1313
|
return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col", children: [
|
|
1296
1314
|
heading,
|
|
@@ -1298,19 +1316,19 @@ function MenuSection({ label, children, className }) {
|
|
|
1298
1316
|
] });
|
|
1299
1317
|
}
|
|
1300
1318
|
return /* @__PURE__ */ jsxs13(BaseMenu.Group, { className: "flex flex-col", children: [
|
|
1301
|
-
/* @__PURE__ */
|
|
1319
|
+
/* @__PURE__ */ jsx20(BaseMenu.GroupLabel, { render: heading }),
|
|
1302
1320
|
children
|
|
1303
1321
|
] });
|
|
1304
1322
|
}
|
|
1305
1323
|
function MenuSeparator() {
|
|
1306
|
-
return /* @__PURE__ */
|
|
1324
|
+
return /* @__PURE__ */ jsx20(Divider, { className: "my-1" });
|
|
1307
1325
|
}
|
|
1308
1326
|
function MenuRow({ children, className }) {
|
|
1309
|
-
return /* @__PURE__ */
|
|
1327
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
|
|
1310
1328
|
}
|
|
1311
1329
|
|
|
1312
1330
|
// src/ChipInput.tsx
|
|
1313
|
-
import { jsx as
|
|
1331
|
+
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1314
1332
|
var CHIP_BOX = (
|
|
1315
1333
|
// Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
|
|
1316
1334
|
// rounded-sm corners — never a forced circle — and the chip's corner
|
|
@@ -1322,9 +1340,9 @@ var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg
|
|
|
1322
1340
|
var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
|
|
1323
1341
|
function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
|
|
1324
1342
|
return /* @__PURE__ */ jsxs14("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
|
|
1325
|
-
leading && /* @__PURE__ */
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
onRemove && /* @__PURE__ */
|
|
1343
|
+
leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1344
|
+
/* @__PURE__ */ jsx21("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
|
|
1345
|
+
onRemove && /* @__PURE__ */ jsx21(
|
|
1328
1346
|
BaseButton4,
|
|
1329
1347
|
{
|
|
1330
1348
|
type: "button",
|
|
@@ -1334,7 +1352,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
|
|
|
1334
1352
|
},
|
|
1335
1353
|
className: cn(CHIP_REMOVE, truncate && "shrink-0"),
|
|
1336
1354
|
"aria-label": removeLabel ?? `Remove ${label}`,
|
|
1337
|
-
children: /* @__PURE__ */
|
|
1355
|
+
children: /* @__PURE__ */ jsx21(IconX4, { size: 10, stroke: 1.5 })
|
|
1338
1356
|
}
|
|
1339
1357
|
)
|
|
1340
1358
|
] });
|
|
@@ -1406,11 +1424,11 @@ function ChipInput({
|
|
|
1406
1424
|
children: [
|
|
1407
1425
|
/* @__PURE__ */ jsxs14(Combobox.Chips, { ref: setBox, className: cn(FIELD_SHELL_CLASSES, "focus-within:border-border-focus focus-within:hover: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: [
|
|
1408
1426
|
value.map((option) => /* @__PURE__ */ jsxs14(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
|
|
1409
|
-
chipLeading && /* @__PURE__ */
|
|
1410
|
-
/* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1427
|
+
chipLeading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
|
|
1428
|
+
/* @__PURE__ */ jsx21("span", { className: CHIP_LABEL, children: option.label }),
|
|
1429
|
+
/* @__PURE__ */ jsx21(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx21(IconX4, { size: 10, stroke: 1.5 }) })
|
|
1412
1430
|
] }, option.id)),
|
|
1413
|
-
/* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ jsx21(
|
|
1414
1432
|
Combobox.Input,
|
|
1415
1433
|
{
|
|
1416
1434
|
autoFocus,
|
|
@@ -1422,18 +1440,18 @@ function ChipInput({
|
|
|
1422
1440
|
}
|
|
1423
1441
|
)
|
|
1424
1442
|
] }),
|
|
1425
|
-
/* @__PURE__ */
|
|
1443
|
+
/* @__PURE__ */ jsx21(Combobox.Portal, { children: /* @__PURE__ */ jsx21(
|
|
1426
1444
|
Combobox.Positioner,
|
|
1427
1445
|
{
|
|
1428
1446
|
anchor: box,
|
|
1429
1447
|
sideOffset: GAP3,
|
|
1430
1448
|
collisionPadding: VIEWPORT_PAD3,
|
|
1431
1449
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1432
|
-
children: /* @__PURE__ */
|
|
1450
|
+
children: /* @__PURE__ */ jsx21(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx21(MenuPanel, {}), children: /* @__PURE__ */ jsx21(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx21(Combobox.List, { children: (option) => /* @__PURE__ */ jsx21(
|
|
1433
1451
|
Combobox.Item,
|
|
1434
1452
|
{
|
|
1435
1453
|
value: option,
|
|
1436
|
-
render: /* @__PURE__ */
|
|
1454
|
+
render: /* @__PURE__ */ jsx21(
|
|
1437
1455
|
MenuItem,
|
|
1438
1456
|
{
|
|
1439
1457
|
size: "tall",
|
|
@@ -1456,22 +1474,22 @@ var VIEWPORT_PAD3 = 8;
|
|
|
1456
1474
|
|
|
1457
1475
|
// src/EmptyState.tsx
|
|
1458
1476
|
import { IconMessage2 } from "@tabler/icons-react";
|
|
1459
|
-
import { jsx as
|
|
1477
|
+
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1460
1478
|
function EmptyState({ icon, message, scope = "page", action, className }) {
|
|
1461
1479
|
if (scope === "section") {
|
|
1462
|
-
return /* @__PURE__ */
|
|
1480
|
+
return /* @__PURE__ */ jsx22("p", { className: cn("text-caption text-text-muted", className), children: message });
|
|
1463
1481
|
}
|
|
1464
1482
|
return /* @__PURE__ */ jsxs15("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
/* @__PURE__ */
|
|
1467
|
-
action && /* @__PURE__ */
|
|
1483
|
+
/* @__PURE__ */ jsx22("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx22(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1484
|
+
/* @__PURE__ */ jsx22("p", { className: "text-body-2 text-text-secondary text-center", children: message }),
|
|
1485
|
+
action && /* @__PURE__ */ jsx22(Button, { variant: "outlined", className: "mt-2", onClick: action.onClick, children: action.label })
|
|
1468
1486
|
] });
|
|
1469
1487
|
}
|
|
1470
1488
|
|
|
1471
1489
|
// src/Field.tsx
|
|
1472
1490
|
import { cloneElement, isValidElement } from "react";
|
|
1473
1491
|
import { Field as BaseField2 } from "@base-ui/react/field";
|
|
1474
|
-
import { jsx as
|
|
1492
|
+
import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1475
1493
|
var LINE_STYLES = {
|
|
1476
1494
|
helper: "text-caption text-text-muted",
|
|
1477
1495
|
warning: "text-caption text-warning-default",
|
|
@@ -1484,23 +1502,23 @@ function Field({ label, required = false, helper, error, children }) {
|
|
|
1484
1502
|
return /* @__PURE__ */ jsxs16(BaseField2.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
|
|
1485
1503
|
/* @__PURE__ */ jsxs16(BaseField2.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1486
1504
|
label,
|
|
1487
|
-
required && /* @__PURE__ */
|
|
1505
|
+
required && /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1488
1506
|
] }),
|
|
1489
1507
|
/* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1.5", children: [
|
|
1490
1508
|
control,
|
|
1491
|
-
error != null ? /* @__PURE__ */
|
|
1509
|
+
error != null ? /* @__PURE__ */ jsx23(BaseField2.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx23(BaseField2.Description, { className: LINE_STYLES.helper, children: helper }) : null
|
|
1492
1510
|
] })
|
|
1493
1511
|
] });
|
|
1494
1512
|
}
|
|
1495
1513
|
function FieldLine({ tone = "helper", children, className }) {
|
|
1496
|
-
return /* @__PURE__ */
|
|
1514
|
+
return /* @__PURE__ */ jsx23("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
|
|
1497
1515
|
}
|
|
1498
1516
|
|
|
1499
1517
|
// src/Form.tsx
|
|
1500
1518
|
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
|
|
1501
1519
|
import { Fieldset } from "@base-ui/react/fieldset";
|
|
1502
1520
|
import { Form as BaseForm } from "@base-ui/react/form";
|
|
1503
|
-
import { jsx as
|
|
1521
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1504
1522
|
var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
|
|
1505
1523
|
var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1506
1524
|
function usable(element) {
|
|
@@ -1559,7 +1577,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
|
|
|
1559
1577
|
const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
|
|
1560
1578
|
if (enterSends && oneLine) form.current?.requestSubmit();
|
|
1561
1579
|
};
|
|
1562
|
-
return /* @__PURE__ */
|
|
1580
|
+
return /* @__PURE__ */ jsx24(
|
|
1563
1581
|
BaseForm,
|
|
1564
1582
|
{
|
|
1565
1583
|
ref: form,
|
|
@@ -1582,32 +1600,32 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
|
|
|
1582
1600
|
if (busyNow.current) return;
|
|
1583
1601
|
void onSubmit();
|
|
1584
1602
|
},
|
|
1585
|
-
children: /* @__PURE__ */
|
|
1603
|
+
children: /* @__PURE__ */ jsx24(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx24(FormBusyContext.Provider, { value: busy, children }) })
|
|
1586
1604
|
}
|
|
1587
1605
|
);
|
|
1588
1606
|
}
|
|
1589
1607
|
|
|
1590
1608
|
// src/Skeleton.tsx
|
|
1591
|
-
import { jsx as
|
|
1609
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1592
1610
|
function SkeletonBar({ className, style }) {
|
|
1593
|
-
return /* @__PURE__ */
|
|
1611
|
+
return /* @__PURE__ */ jsx25("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1594
1612
|
}
|
|
1595
1613
|
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1596
1614
|
function SkeletonRow({ barWidth = 130 }) {
|
|
1597
1615
|
return /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1598
|
-
/* @__PURE__ */
|
|
1599
|
-
/* @__PURE__ */
|
|
1616
|
+
/* @__PURE__ */ jsx25(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1617
|
+
/* @__PURE__ */ jsx25(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1600
1618
|
] });
|
|
1601
1619
|
}
|
|
1602
1620
|
function SkeletonList({ rows = 8, className }) {
|
|
1603
|
-
return /* @__PURE__ */
|
|
1621
|
+
return /* @__PURE__ */ jsx25("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx25(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
|
|
1604
1622
|
}
|
|
1605
1623
|
|
|
1606
1624
|
// src/CommandPalette.tsx
|
|
1607
|
-
import { Fragment as
|
|
1608
|
-
var PaletteContext =
|
|
1625
|
+
import { Fragment as Fragment4, jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1626
|
+
var PaletteContext = createContext5(null);
|
|
1609
1627
|
function usePalette(part) {
|
|
1610
|
-
const palette =
|
|
1628
|
+
const palette = useContext5(PaletteContext);
|
|
1611
1629
|
if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
|
|
1612
1630
|
return palette;
|
|
1613
1631
|
}
|
|
@@ -1630,9 +1648,9 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1630
1648
|
return () => cancelAnimationFrame(frame);
|
|
1631
1649
|
});
|
|
1632
1650
|
const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
|
|
1633
|
-
return /* @__PURE__ */
|
|
1634
|
-
/* @__PURE__ */
|
|
1635
|
-
/* @__PURE__ */
|
|
1651
|
+
return /* @__PURE__ */ jsx26(Dialog2.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs18(Dialog2.Portal, { children: [
|
|
1652
|
+
/* @__PURE__ */ jsx26(Dialog2.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1653
|
+
/* @__PURE__ */ jsx26(Dialog2.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx26(
|
|
1636
1654
|
Dialog2.Popup,
|
|
1637
1655
|
{
|
|
1638
1656
|
ref: popupRef,
|
|
@@ -1642,13 +1660,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1642
1660
|
if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
|
|
1643
1661
|
},
|
|
1644
1662
|
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",
|
|
1645
|
-
children: /* @__PURE__ */
|
|
1663
|
+
children: /* @__PURE__ */ jsx26(PaletteContext.Provider, { value: context, children })
|
|
1646
1664
|
}
|
|
1647
1665
|
) })
|
|
1648
1666
|
] }) });
|
|
1649
1667
|
}
|
|
1650
1668
|
function LevelChip({ chip, onBack }) {
|
|
1651
|
-
return /* @__PURE__ */
|
|
1669
|
+
return /* @__PURE__ */ jsx26(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
|
|
1652
1670
|
}
|
|
1653
1671
|
function useBack(chip, popupRef) {
|
|
1654
1672
|
return () => {
|
|
@@ -1660,9 +1678,9 @@ function useBack(chip, popupRef) {
|
|
|
1660
1678
|
function Footer({ keys }) {
|
|
1661
1679
|
const { where } = usePalette("The footer");
|
|
1662
1680
|
return /* @__PURE__ */ jsxs18("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: [
|
|
1663
|
-
/* @__PURE__ */
|
|
1681
|
+
/* @__PURE__ */ jsx26("span", { className: "min-w-0 flex-1 truncate", children: where }),
|
|
1664
1682
|
keys.map(([key, word]) => /* @__PURE__ */ jsxs18("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
1665
|
-
/* @__PURE__ */
|
|
1683
|
+
/* @__PURE__ */ jsx26(Kbd, { children: key }),
|
|
1666
1684
|
" ",
|
|
1667
1685
|
word
|
|
1668
1686
|
] }, key))
|
|
@@ -1763,9 +1781,9 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1763
1781
|
},
|
|
1764
1782
|
children: [
|
|
1765
1783
|
/* @__PURE__ */ jsxs18("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1766
|
-
/* @__PURE__ */
|
|
1767
|
-
chip && /* @__PURE__ */
|
|
1768
|
-
/* @__PURE__ */
|
|
1784
|
+
/* @__PURE__ */ jsx26(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
|
|
1785
|
+
chip && /* @__PURE__ */ jsx26(LevelChip, { chip, onBack: back }),
|
|
1786
|
+
/* @__PURE__ */ jsx26(
|
|
1769
1787
|
Autocomplete.Input,
|
|
1770
1788
|
{
|
|
1771
1789
|
ref: inputRef,
|
|
@@ -1778,42 +1796,42 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1778
1796
|
)
|
|
1779
1797
|
] }),
|
|
1780
1798
|
/* @__PURE__ */ jsxs18(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
|
|
1781
|
-
children != null && /* @__PURE__ */
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
/* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
1799
|
+
children != null && /* @__PURE__ */ jsx26("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
|
|
1800
|
+
/* @__PURE__ */ jsx26(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs18(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
|
|
1801
|
+
/* @__PURE__ */ jsx26(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx26(SectionLabel, { tone: "secondary", children: group.value }) }),
|
|
1802
|
+
/* @__PURE__ */ jsx26(Autocomplete.Collection, { children: (row) => (
|
|
1785
1803
|
/* The menu row, as the list's own option — the way Select
|
|
1786
1804
|
puts it on `Select.Item`. One row, two parts. */
|
|
1787
|
-
/* @__PURE__ */
|
|
1805
|
+
/* @__PURE__ */ jsx26(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx26(
|
|
1788
1806
|
MenuItemBody,
|
|
1789
1807
|
{
|
|
1790
1808
|
size: "tall",
|
|
1791
1809
|
label: row.label,
|
|
1792
1810
|
description: row.description,
|
|
1793
|
-
leading: /* @__PURE__ */
|
|
1811
|
+
leading: /* @__PURE__ */ jsx26(RowLeading, { row }),
|
|
1794
1812
|
submenu: !!row.onGoIn,
|
|
1795
|
-
hint: row.onGoIn ? /* @__PURE__ */
|
|
1813
|
+
hint: row.onGoIn ? /* @__PURE__ */ jsx26(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx26(EnterHint, {})
|
|
1796
1814
|
}
|
|
1797
1815
|
) }, row.id)
|
|
1798
1816
|
) })
|
|
1799
1817
|
] }, group.value) }),
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
1818
|
+
/* @__PURE__ */ jsx26(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs18(Fragment4, { children: [
|
|
1819
|
+
/* @__PURE__ */ jsx26(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
|
|
1820
|
+
/* @__PURE__ */ jsx26("span", { className: "text-caption text-text-muted", children: pending })
|
|
1803
1821
|
] }) }),
|
|
1804
|
-
notes.map((note) => /* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
1822
|
+
notes.map((note) => /* @__PURE__ */ jsx26("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx26(FieldLine, { children: note }) }, note)),
|
|
1823
|
+
/* @__PURE__ */ jsx26(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx26(EmptyState, { scope: "section", message: empty }) })
|
|
1806
1824
|
] }),
|
|
1807
|
-
/* @__PURE__ */
|
|
1825
|
+
/* @__PURE__ */ jsx26(Footer, { keys })
|
|
1808
1826
|
]
|
|
1809
1827
|
}
|
|
1810
1828
|
);
|
|
1811
1829
|
}
|
|
1812
1830
|
function RowLeading({ row }) {
|
|
1813
1831
|
if (row.icon != null) {
|
|
1814
|
-
return /* @__PURE__ */
|
|
1832
|
+
return /* @__PURE__ */ jsx26("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
|
|
1815
1833
|
}
|
|
1816
|
-
return /* @__PURE__ */
|
|
1834
|
+
return /* @__PURE__ */ jsx26("span", { className: "flex size-8 items-center justify-center", children: row.leading });
|
|
1817
1835
|
}
|
|
1818
1836
|
var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1819
1837
|
function isTextField(el) {
|
|
@@ -1857,54 +1875,54 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
|
|
|
1857
1875
|
];
|
|
1858
1876
|
return /* @__PURE__ */ jsxs18("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
|
|
1859
1877
|
/* @__PURE__ */ jsxs18("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1860
|
-
icon != null && /* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
1878
|
+
icon != null && /* @__PURE__ */ jsx26("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
|
|
1879
|
+
/* @__PURE__ */ jsx26(LevelChip, { chip, onBack: back })
|
|
1862
1880
|
] }),
|
|
1863
1881
|
/* @__PURE__ */ jsxs18(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
|
|
1864
|
-
/* @__PURE__ */
|
|
1882
|
+
/* @__PURE__ */ jsx26(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx26("div", { className: "flex flex-col gap-4", children }) }),
|
|
1865
1883
|
/* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
|
|
1866
|
-
/* @__PURE__ */
|
|
1867
|
-
/* @__PURE__ */
|
|
1884
|
+
/* @__PURE__ */ jsx26("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx26(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx26(FieldLine, { tone: "error", children: error }) : null }),
|
|
1885
|
+
/* @__PURE__ */ jsx26(
|
|
1868
1886
|
Button,
|
|
1869
1887
|
{
|
|
1870
1888
|
type: "submit",
|
|
1871
1889
|
variant: "primary",
|
|
1872
1890
|
disabled: busy,
|
|
1873
1891
|
disabledReason: busy ? void 0 : submitWaits,
|
|
1874
|
-
leadingIcon: busy ? /* @__PURE__ */
|
|
1892
|
+
leadingIcon: busy ? /* @__PURE__ */ jsx26(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
|
|
1875
1893
|
children: working ? working.button : submitLabel
|
|
1876
1894
|
}
|
|
1877
1895
|
)
|
|
1878
1896
|
] })
|
|
1879
1897
|
] }),
|
|
1880
|
-
/* @__PURE__ */
|
|
1898
|
+
/* @__PURE__ */ jsx26(Footer, { keys })
|
|
1881
1899
|
] });
|
|
1882
1900
|
}
|
|
1883
1901
|
var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
|
|
1884
1902
|
function CommandPaletteWorking({ children, bars = 2 }) {
|
|
1885
1903
|
return /* @__PURE__ */ jsxs18("div", { role: "status", className: "flex flex-col gap-2", children: [
|
|
1886
1904
|
/* @__PURE__ */ jsxs18("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
|
|
1887
|
-
/* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ jsx26(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
|
|
1888
1906
|
children
|
|
1889
1907
|
] }),
|
|
1890
|
-
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */
|
|
1908
|
+
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx26(SkeletonBar, { className: cn("h-3", width) }, width))
|
|
1891
1909
|
] });
|
|
1892
1910
|
}
|
|
1893
1911
|
function CommandPaletteAnswer({ children, note }) {
|
|
1894
1912
|
const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
|
|
1895
1913
|
return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-2", children: [
|
|
1896
|
-
paragraphs.map((paragraph, i) => /* @__PURE__ */
|
|
1897
|
-
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */
|
|
1914
|
+
paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx26("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
|
|
1915
|
+
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx26("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
|
|
1898
1916
|
) }, i)),
|
|
1899
|
-
note && /* @__PURE__ */
|
|
1917
|
+
note && /* @__PURE__ */ jsx26(FieldLine, { children: note })
|
|
1900
1918
|
] });
|
|
1901
1919
|
}
|
|
1902
1920
|
function CommandPaletteQuote({ children }) {
|
|
1903
|
-
return /* @__PURE__ */
|
|
1921
|
+
return /* @__PURE__ */ jsx26("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
|
|
1904
1922
|
}
|
|
1905
1923
|
|
|
1906
1924
|
// src/InlineChip.tsx
|
|
1907
|
-
import { Fragment as
|
|
1925
|
+
import { Fragment as Fragment5, jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1908
1926
|
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";
|
|
1909
1927
|
var INLINE_CHIP_TONE_CLASSES = {
|
|
1910
1928
|
/** A thing or a place — anything that is not a person. */
|
|
@@ -1926,30 +1944,30 @@ function inlineChipClassName(tone, className) {
|
|
|
1926
1944
|
return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
|
|
1927
1945
|
}
|
|
1928
1946
|
function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
|
|
1929
|
-
const body = /* @__PURE__ */ jsxs19(
|
|
1930
|
-
icon && /* @__PURE__ */
|
|
1947
|
+
const body = /* @__PURE__ */ jsxs19(Fragment5, { children: [
|
|
1948
|
+
icon && /* @__PURE__ */ jsx27("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
|
|
1931
1949
|
children
|
|
1932
1950
|
] });
|
|
1933
1951
|
const classes = inlineChipClassName(tone, className);
|
|
1934
1952
|
if (href === void 0) {
|
|
1935
|
-
return /* @__PURE__ */
|
|
1953
|
+
return /* @__PURE__ */ jsx27("span", { className: classes, ...props, children: body });
|
|
1936
1954
|
}
|
|
1937
|
-
return /* @__PURE__ */
|
|
1955
|
+
return /* @__PURE__ */ jsx27("a", { href, className: classes, ...props, children: body });
|
|
1938
1956
|
}
|
|
1939
1957
|
|
|
1940
1958
|
// src/IdentityMenu.tsx
|
|
1941
1959
|
import { useCallback, useRef as useRef5 } from "react";
|
|
1942
1960
|
|
|
1943
1961
|
// src/Person.tsx
|
|
1944
|
-
import { jsx as
|
|
1962
|
+
import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1945
1963
|
function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
1946
1964
|
return (
|
|
1947
1965
|
// gap-2: the face-to-name distance is one rule (8px) wherever a person
|
|
1948
1966
|
// appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
|
|
1949
1967
|
// row agree by construction.
|
|
1950
1968
|
/* @__PURE__ */ jsxs20("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
|
|
1951
|
-
/* @__PURE__ */
|
|
1952
|
-
/* @__PURE__ */
|
|
1969
|
+
/* @__PURE__ */ jsx28(Avatar, { name, src: picture, size }),
|
|
1970
|
+
/* @__PURE__ */ jsx28("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
|
|
1953
1971
|
] })
|
|
1954
1972
|
);
|
|
1955
1973
|
}
|
|
@@ -1957,10 +1975,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
|
1957
1975
|
// src/PersonTrigger.tsx
|
|
1958
1976
|
import { Button as BaseButton5 } from "@base-ui/react/button";
|
|
1959
1977
|
import { IconChevronDown } from "@tabler/icons-react";
|
|
1960
|
-
import { jsx as
|
|
1978
|
+
import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1961
1979
|
function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
|
|
1962
1980
|
if (compact) {
|
|
1963
|
-
return /* @__PURE__ */
|
|
1981
|
+
return /* @__PURE__ */ jsx29(
|
|
1964
1982
|
BaseButton5,
|
|
1965
1983
|
{
|
|
1966
1984
|
type: "button",
|
|
@@ -1969,7 +1987,7 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1969
1987
|
"aria-label": props["aria-label"] ?? name ?? fallback,
|
|
1970
1988
|
className: cn("cursor-pointer rounded-full", className),
|
|
1971
1989
|
...props,
|
|
1972
|
-
children: /* @__PURE__ */
|
|
1990
|
+
children: /* @__PURE__ */ jsx29(Avatar, { name, src: picture, size: size ?? 36 })
|
|
1973
1991
|
}
|
|
1974
1992
|
);
|
|
1975
1993
|
}
|
|
@@ -1993,8 +2011,8 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1993
2011
|
),
|
|
1994
2012
|
...props,
|
|
1995
2013
|
children: [
|
|
1996
|
-
/* @__PURE__ */
|
|
1997
|
-
/* @__PURE__ */
|
|
2014
|
+
/* @__PURE__ */ jsx29(Person, { name, picture, fallback, size: size ?? 22 }),
|
|
2015
|
+
/* @__PURE__ */ jsx29(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
|
|
1998
2016
|
]
|
|
1999
2017
|
}
|
|
2000
2018
|
)
|
|
@@ -2002,10 +2020,10 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
2002
2020
|
}
|
|
2003
2021
|
|
|
2004
2022
|
// src/IdentityMenu.tsx
|
|
2005
|
-
import { Fragment as
|
|
2023
|
+
import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2006
2024
|
function IdentityPanel({ className, onClose = () => {
|
|
2007
2025
|
}, ...rest }) {
|
|
2008
|
-
return /* @__PURE__ */
|
|
2026
|
+
return /* @__PURE__ */ jsx30(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx30(IdentityRows, { ...rest, onClose }) });
|
|
2009
2027
|
}
|
|
2010
2028
|
function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
|
|
2011
2029
|
const act = (action) => () => {
|
|
@@ -2013,36 +2031,36 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
|
|
|
2013
2031
|
action();
|
|
2014
2032
|
};
|
|
2015
2033
|
const appRows = typeof children === "function" ? children(onClose) : children;
|
|
2016
|
-
return /* @__PURE__ */ jsxs22(
|
|
2034
|
+
return /* @__PURE__ */ jsxs22(Fragment6, { children: [
|
|
2017
2035
|
/* @__PURE__ */ jsxs22(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
|
|
2018
|
-
/* @__PURE__ */
|
|
2019
|
-
/* @__PURE__ */
|
|
2036
|
+
/* @__PURE__ */ jsx30(MenuRow, { children: /* @__PURE__ */ jsx30("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx30(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
|
|
2037
|
+
/* @__PURE__ */ jsx30(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." }),
|
|
2020
2038
|
me.email && /* @__PURE__ */ jsxs22(Note, { children: [
|
|
2021
2039
|
me.email,
|
|
2022
2040
|
" \xB7 known to Estiva, never published to the relay"
|
|
2023
2041
|
] })
|
|
2024
2042
|
] }),
|
|
2025
|
-
relayUrl && /* @__PURE__ */ jsxs22(
|
|
2026
|
-
/* @__PURE__ */
|
|
2043
|
+
relayUrl && /* @__PURE__ */ jsxs22(Fragment6, { children: [
|
|
2044
|
+
/* @__PURE__ */ jsx30(Divider, { className: "mx-0 my-2" }),
|
|
2027
2045
|
/* @__PURE__ */ jsxs22(MenuSection, { label: "Workspace", children: [
|
|
2028
|
-
/* @__PURE__ */
|
|
2029
|
-
/* @__PURE__ */
|
|
2046
|
+
/* @__PURE__ */ jsx30(MenuRow, { children: /* @__PURE__ */ jsx30("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
|
|
2047
|
+
/* @__PURE__ */ jsx30(Note, { children: "Everyone on this relay shares this workspace, in every app." })
|
|
2030
2048
|
] })
|
|
2031
2049
|
] }),
|
|
2032
|
-
appRows && /* @__PURE__ */ jsxs22(
|
|
2033
|
-
/* @__PURE__ */
|
|
2050
|
+
appRows && /* @__PURE__ */ jsxs22(Fragment6, { children: [
|
|
2051
|
+
/* @__PURE__ */ jsx30(Divider, { className: "mx-0 my-2" }),
|
|
2034
2052
|
appRows
|
|
2035
2053
|
] }),
|
|
2036
|
-
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */
|
|
2037
|
-
signedIn && idBase && /* @__PURE__ */
|
|
2054
|
+
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx30(Divider, { className: "mx-0 my-2" }) : null,
|
|
2055
|
+
signedIn && idBase && /* @__PURE__ */ jsx30(
|
|
2038
2056
|
MenuItem,
|
|
2039
2057
|
{
|
|
2040
2058
|
label: "Edit your profile in Estiva ID",
|
|
2041
2059
|
onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
|
|
2042
2060
|
}
|
|
2043
2061
|
),
|
|
2044
|
-
onCopyKey && /* @__PURE__ */
|
|
2045
|
-
idBase && onSignOut && /* @__PURE__ */
|
|
2062
|
+
onCopyKey && /* @__PURE__ */ jsx30(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
|
|
2063
|
+
idBase && onSignOut && /* @__PURE__ */ jsx30(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
|
|
2046
2064
|
] });
|
|
2047
2065
|
}
|
|
2048
2066
|
function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
|
|
@@ -2053,13 +2071,13 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
2053
2071
|
to be `relative`, because the panel was positioned against it; the panel
|
|
2054
2072
|
hangs from the trigger and portals now, so a positioning context here
|
|
2055
2073
|
would only be a lie about what this box does. */
|
|
2056
|
-
/* @__PURE__ */
|
|
2074
|
+
/* @__PURE__ */ jsx30("div", { className, children: /* @__PURE__ */ jsx30(
|
|
2057
2075
|
Menu,
|
|
2058
2076
|
{
|
|
2059
2077
|
align: "right",
|
|
2060
2078
|
actionsRef: actions,
|
|
2061
2079
|
className: "w-72",
|
|
2062
|
-
trigger: /* @__PURE__ */
|
|
2080
|
+
trigger: /* @__PURE__ */ jsx30(
|
|
2063
2081
|
PersonTrigger,
|
|
2064
2082
|
{
|
|
2065
2083
|
name: me.name,
|
|
@@ -2070,7 +2088,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
2070
2088
|
"aria-label": compact ? "Account menu" : void 0
|
|
2071
2089
|
}
|
|
2072
2090
|
),
|
|
2073
|
-
children: /* @__PURE__ */
|
|
2091
|
+
children: /* @__PURE__ */ jsx30(
|
|
2074
2092
|
IdentityRows,
|
|
2075
2093
|
{
|
|
2076
2094
|
me,
|
|
@@ -2088,14 +2106,14 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
2088
2106
|
);
|
|
2089
2107
|
}
|
|
2090
2108
|
function Note({ children }) {
|
|
2091
|
-
return /* @__PURE__ */
|
|
2109
|
+
return /* @__PURE__ */ jsx30("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
|
|
2092
2110
|
}
|
|
2093
2111
|
|
|
2094
2112
|
// src/FilePicker.tsx
|
|
2095
2113
|
import { forwardRef } from "react";
|
|
2096
|
-
import { jsx as
|
|
2114
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
2097
2115
|
var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
2098
|
-
return /* @__PURE__ */
|
|
2116
|
+
return /* @__PURE__ */ jsx31(
|
|
2099
2117
|
"input",
|
|
2100
2118
|
{
|
|
2101
2119
|
ref,
|
|
@@ -2116,7 +2134,7 @@ var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
|
2116
2134
|
// src/Select.tsx
|
|
2117
2135
|
import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
|
|
2118
2136
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
2119
|
-
import { jsx as
|
|
2137
|
+
import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2120
2138
|
var GAP4 = 4;
|
|
2121
2139
|
var VIEWPORT_PAD4 = 8;
|
|
2122
2140
|
function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, disabledReason, className, ...aria }) {
|
|
@@ -2155,13 +2173,13 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2155
2173
|
),
|
|
2156
2174
|
children: [
|
|
2157
2175
|
/* @__PURE__ */ jsxs23("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
|
|
2158
|
-
selected?.leading && /* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2176
|
+
selected?.leading && /* @__PURE__ */ jsx32("span", { className: "flex shrink-0 items-center", children: selected.leading }),
|
|
2177
|
+
/* @__PURE__ */ jsx32(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
|
|
2160
2178
|
] }),
|
|
2161
|
-
/* @__PURE__ */
|
|
2179
|
+
/* @__PURE__ */ jsx32(
|
|
2162
2180
|
BaseSelect.Icon,
|
|
2163
2181
|
{
|
|
2164
|
-
render: /* @__PURE__ */
|
|
2182
|
+
render: /* @__PURE__ */ jsx32(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2165
2183
|
}
|
|
2166
2184
|
)
|
|
2167
2185
|
]
|
|
@@ -2180,8 +2198,8 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2180
2198
|
disabled: disabled && !held,
|
|
2181
2199
|
modal: false,
|
|
2182
2200
|
children: [
|
|
2183
|
-
held ? /* @__PURE__ */
|
|
2184
|
-
/* @__PURE__ */
|
|
2201
|
+
held ? /* @__PURE__ */ jsx32(TooltipTrigger, { label: disabledReason ?? "", children: trigger }) : trigger,
|
|
2202
|
+
/* @__PURE__ */ jsx32(BaseSelect.Portal, { children: /* @__PURE__ */ jsx32(
|
|
2185
2203
|
BaseSelect.Positioner,
|
|
2186
2204
|
{
|
|
2187
2205
|
side: "bottom",
|
|
@@ -2190,25 +2208,25 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2190
2208
|
collisionPadding: VIEWPORT_PAD4,
|
|
2191
2209
|
alignItemWithTrigger: false,
|
|
2192
2210
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2193
|
-
children: /* @__PURE__ */
|
|
2211
|
+
children: /* @__PURE__ */ jsx32(
|
|
2194
2212
|
BaseSelect.Popup,
|
|
2195
2213
|
{
|
|
2196
|
-
render: /* @__PURE__ */
|
|
2214
|
+
render: /* @__PURE__ */ jsx32(MenuPanel, {}),
|
|
2197
2215
|
className: "min-w-[var(--anchor-width)] p-0",
|
|
2198
|
-
children: /* @__PURE__ */
|
|
2216
|
+
children: /* @__PURE__ */ jsx32(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col p-2", children: options.map((option) => /* @__PURE__ */ jsxs23(
|
|
2199
2217
|
BaseSelect.Item,
|
|
2200
2218
|
{
|
|
2201
2219
|
value: option.value,
|
|
2202
2220
|
className: cn(menuItemClassName({ size: "default" }), "justify-between data-[selected]:font-medium"),
|
|
2203
2221
|
children: [
|
|
2204
2222
|
/* @__PURE__ */ jsxs23("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2205
|
-
option.leading && /* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2223
|
+
option.leading && /* @__PURE__ */ jsx32("span", { className: "flex shrink-0 items-center", children: option.leading }),
|
|
2224
|
+
/* @__PURE__ */ jsx32(BaseSelect.ItemText, { className: "truncate text-body-2 text-text-primary", children: option.label })
|
|
2207
2225
|
] }),
|
|
2208
|
-
/* @__PURE__ */
|
|
2226
|
+
/* @__PURE__ */ jsx32(
|
|
2209
2227
|
BaseSelect.ItemIndicator,
|
|
2210
2228
|
{
|
|
2211
|
-
render: /* @__PURE__ */
|
|
2229
|
+
render: /* @__PURE__ */ jsx32(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2212
2230
|
}
|
|
2213
2231
|
)
|
|
2214
2232
|
]
|
|
@@ -2227,9 +2245,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2227
2245
|
// src/TextInput.tsx
|
|
2228
2246
|
import { forwardRef as forwardRef2 } from "react";
|
|
2229
2247
|
import { Input } from "@base-ui/react/input";
|
|
2230
|
-
import { jsx as
|
|
2248
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
2231
2249
|
var TextInput = forwardRef2(function TextInput2({ className, type = "text", size = "default", ...props }, ref) {
|
|
2232
|
-
return /* @__PURE__ */
|
|
2250
|
+
return /* @__PURE__ */ jsx33(
|
|
2233
2251
|
Input,
|
|
2234
2252
|
{
|
|
2235
2253
|
ref,
|
|
@@ -2255,13 +2273,13 @@ var TextInput = forwardRef2(function TextInput2({ className, type = "text", size
|
|
|
2255
2273
|
// src/Textarea.tsx
|
|
2256
2274
|
import { forwardRef as forwardRef3 } from "react";
|
|
2257
2275
|
import { Field as BaseField3 } from "@base-ui/react/field";
|
|
2258
|
-
import { jsx as
|
|
2276
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
2259
2277
|
var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
|
|
2260
|
-
return /* @__PURE__ */
|
|
2278
|
+
return /* @__PURE__ */ jsx34(
|
|
2261
2279
|
BaseField3.Control,
|
|
2262
2280
|
{
|
|
2263
2281
|
ref,
|
|
2264
|
-
render: /* @__PURE__ */
|
|
2282
|
+
render: /* @__PURE__ */ jsx34("textarea", {}),
|
|
2265
2283
|
className: cn(
|
|
2266
2284
|
// The border strengthens on hover, as Select's and ChipInput's do (Katerina, 16 September:
|
|
2267
2285
|
// "aren't there hover states in text input and text area?"). Focus comes after hover in
|
|
@@ -2290,24 +2308,24 @@ import { IconX as IconX5 } from "@tabler/icons-react";
|
|
|
2290
2308
|
|
|
2291
2309
|
// src/ContainerHeader.tsx
|
|
2292
2310
|
import { IconChevronDown as IconChevronDown3 } from "@tabler/icons-react";
|
|
2293
|
-
import { jsx as
|
|
2311
|
+
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2294
2312
|
function ContainerHeader({ title, chevron = false, actions, className }) {
|
|
2295
2313
|
const text = typeof title === "string";
|
|
2296
2314
|
return /* @__PURE__ */ jsxs24("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: [
|
|
2297
|
-
/* @__PURE__ */
|
|
2298
|
-
text ? /* @__PURE__ */
|
|
2299
|
-
chevron && /* @__PURE__ */
|
|
2315
|
+
/* @__PURE__ */ jsx35("div", { className: cn("flex items-center gap-2 overflow-hidden", text ? "shrink-0" : "min-w-0 flex-1"), children: /* @__PURE__ */ jsxs24("div", { className: cn("flex items-center gap-1", text ? "shrink-0" : "min-w-0 flex-1"), children: [
|
|
2316
|
+
text ? /* @__PURE__ */ jsx35("span", { className: "whitespace-nowrap text-body-2-strong text-text-primary", children: title }) : /* @__PURE__ */ jsx35("div", { className: "min-w-0 flex-1", children: title }),
|
|
2317
|
+
chevron && /* @__PURE__ */ jsx35(IconChevronDown3, { size: 12, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2300
2318
|
] }) }),
|
|
2301
|
-
actions && /* @__PURE__ */
|
|
2319
|
+
actions && /* @__PURE__ */ jsx35("div", { className: "flex shrink-0 items-center justify-end gap-3", children: /* @__PURE__ */ jsx35("div", { className: "flex shrink-0 items-center gap-1", children: actions }) })
|
|
2302
2320
|
] });
|
|
2303
2321
|
}
|
|
2304
2322
|
|
|
2305
2323
|
// src/DialogShell.tsx
|
|
2306
|
-
import { jsx as
|
|
2324
|
+
import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2307
2325
|
function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, bodyMaxHeight, width = 502, alert = false }) {
|
|
2308
2326
|
const Parts = alert ? AlertDialog : Dialog3;
|
|
2309
2327
|
const popupRef = useRef6(null);
|
|
2310
|
-
return /* @__PURE__ */
|
|
2328
|
+
return /* @__PURE__ */ jsx36(
|
|
2311
2329
|
Parts.Root,
|
|
2312
2330
|
{
|
|
2313
2331
|
open: true,
|
|
@@ -2315,8 +2333,8 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2315
2333
|
if (!open) onClose();
|
|
2316
2334
|
},
|
|
2317
2335
|
children: /* @__PURE__ */ jsxs25(Parts.Portal, { children: [
|
|
2318
|
-
/* @__PURE__ */
|
|
2319
|
-
/* @__PURE__ */
|
|
2336
|
+
/* @__PURE__ */ jsx36(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
2337
|
+
/* @__PURE__ */ jsx36("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs25(
|
|
2320
2338
|
Parts.Popup,
|
|
2321
2339
|
{
|
|
2322
2340
|
ref: popupRef,
|
|
@@ -2325,10 +2343,10 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2325
2343
|
className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
|
|
2326
2344
|
style: { width },
|
|
2327
2345
|
children: [
|
|
2328
|
-
/* @__PURE__ */
|
|
2346
|
+
/* @__PURE__ */ jsx36(
|
|
2329
2347
|
ContainerHeader,
|
|
2330
2348
|
{
|
|
2331
|
-
title: headerContent ?? /* @__PURE__ */
|
|
2349
|
+
title: headerContent ?? /* @__PURE__ */ jsx36(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx36("span", {}), children: title }),
|
|
2332
2350
|
actions: (
|
|
2333
2351
|
/*
|
|
2334
2352
|
The ✕ IS the `Close` part now, rather than a button that calls
|
|
@@ -2342,10 +2360,10 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2342
2360
|
so the ✕, Escape and the outside press are one path with one
|
|
2343
2361
|
reason attached, instead of one of the three going around.
|
|
2344
2362
|
*/
|
|
2345
|
-
/* @__PURE__ */
|
|
2363
|
+
/* @__PURE__ */ jsx36(
|
|
2346
2364
|
Parts.Close,
|
|
2347
2365
|
{
|
|
2348
|
-
render: /* @__PURE__ */
|
|
2366
|
+
render: /* @__PURE__ */ jsx36(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx36(IconX5, { size: 16, stroke: 1.5 }) })
|
|
2349
2367
|
}
|
|
2350
2368
|
)
|
|
2351
2369
|
)
|
|
@@ -2353,9 +2371,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2353
2371
|
),
|
|
2354
2372
|
bodyMaxHeight ? (
|
|
2355
2373
|
// The line above the footer on a box of the shell's own, not pushed into ScrollArea (UIG-9).
|
|
2356
|
-
/* @__PURE__ */
|
|
2357
|
-
) : /* @__PURE__ */
|
|
2358
|
-
footer != null && /* @__PURE__ */
|
|
2374
|
+
/* @__PURE__ */ jsx36("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx36(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
|
|
2375
|
+
) : /* @__PURE__ */ jsx36("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
|
|
2376
|
+
footer != null && /* @__PURE__ */ jsx36("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
|
|
2359
2377
|
]
|
|
2360
2378
|
}
|
|
2361
2379
|
) })
|
|
@@ -2365,7 +2383,7 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2365
2383
|
}
|
|
2366
2384
|
|
|
2367
2385
|
// src/ConfirmDialog.tsx
|
|
2368
|
-
import { Fragment as
|
|
2386
|
+
import { Fragment as Fragment7, jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2369
2387
|
function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
|
|
2370
2388
|
const [busy, setBusy] = useState4(false);
|
|
2371
2389
|
const confirm = async () => {
|
|
@@ -2377,17 +2395,17 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
2377
2395
|
setBusy(false);
|
|
2378
2396
|
}
|
|
2379
2397
|
};
|
|
2380
|
-
return /* @__PURE__ */
|
|
2398
|
+
return /* @__PURE__ */ jsx37(
|
|
2381
2399
|
DialogShell,
|
|
2382
2400
|
{
|
|
2383
2401
|
alert: true,
|
|
2384
2402
|
title,
|
|
2385
2403
|
onClose,
|
|
2386
|
-
footer: /* @__PURE__ */ jsxs26(
|
|
2387
|
-
/* @__PURE__ */
|
|
2388
|
-
/* @__PURE__ */
|
|
2404
|
+
footer: /* @__PURE__ */ jsxs26(Fragment7, { children: [
|
|
2405
|
+
/* @__PURE__ */ jsx37(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
2406
|
+
/* @__PURE__ */ jsx37(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
|
|
2389
2407
|
] }),
|
|
2390
|
-
children: /* @__PURE__ */
|
|
2408
|
+
children: /* @__PURE__ */ jsx37("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
|
|
2391
2409
|
}
|
|
2392
2410
|
);
|
|
2393
2411
|
}
|
|
@@ -2396,7 +2414,7 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
2396
2414
|
import { useEffect as useEffect3, useRef as useRef7, useState as useState5 } from "react";
|
|
2397
2415
|
import { Field as BaseField4 } from "@base-ui/react/field";
|
|
2398
2416
|
import { Input as Input2 } from "@base-ui/react/input";
|
|
2399
|
-
import { jsx as
|
|
2417
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2400
2418
|
function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
|
|
2401
2419
|
const [editing, setEditing] = useState5(false);
|
|
2402
2420
|
const [draft, setDraft] = useState5(value);
|
|
@@ -2454,7 +2472,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2454
2472
|
written and never read. Read-only, this is a line of text: whatever
|
|
2455
2473
|
names the region around it (a `Field`, a `Property`) names this too.
|
|
2456
2474
|
*/
|
|
2457
|
-
/* @__PURE__ */
|
|
2475
|
+
/* @__PURE__ */ jsx38(
|
|
2458
2476
|
"div",
|
|
2459
2477
|
{
|
|
2460
2478
|
className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
|
|
@@ -2464,11 +2482,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2464
2482
|
);
|
|
2465
2483
|
}
|
|
2466
2484
|
if (editing) {
|
|
2467
|
-
return multiline ? /* @__PURE__ */
|
|
2485
|
+
return multiline ? /* @__PURE__ */ jsx38(
|
|
2468
2486
|
BaseField4.Control,
|
|
2469
2487
|
{
|
|
2470
2488
|
ref: fieldRef,
|
|
2471
|
-
render: /* @__PURE__ */
|
|
2489
|
+
render: /* @__PURE__ */ jsx38("textarea", { rows: 4 }),
|
|
2472
2490
|
"aria-label": label,
|
|
2473
2491
|
value: draft,
|
|
2474
2492
|
disabled: busy,
|
|
@@ -2477,7 +2495,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2477
2495
|
onBlur: () => void commit(),
|
|
2478
2496
|
className: fieldClass
|
|
2479
2497
|
}
|
|
2480
|
-
) : /* @__PURE__ */
|
|
2498
|
+
) : /* @__PURE__ */ jsx38(
|
|
2481
2499
|
Input2,
|
|
2482
2500
|
{
|
|
2483
2501
|
ref: fieldRef,
|
|
@@ -2491,7 +2509,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2491
2509
|
}
|
|
2492
2510
|
);
|
|
2493
2511
|
}
|
|
2494
|
-
return /* @__PURE__ */
|
|
2512
|
+
return /* @__PURE__ */ jsx38(
|
|
2495
2513
|
"button",
|
|
2496
2514
|
{
|
|
2497
2515
|
type: "button",
|
|
@@ -2511,7 +2529,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2511
2529
|
// src/ErrorBoundary.tsx
|
|
2512
2530
|
import { Component } from "react";
|
|
2513
2531
|
import { IconAlertTriangle as IconAlertTriangle2 } from "@tabler/icons-react";
|
|
2514
|
-
import { jsx as
|
|
2532
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
2515
2533
|
var ErrorBoundary = class extends Component {
|
|
2516
2534
|
state = { hasError: false };
|
|
2517
2535
|
static getDerivedStateFromError() {
|
|
@@ -2522,22 +2540,22 @@ var ErrorBoundary = class extends Component {
|
|
|
2522
2540
|
}
|
|
2523
2541
|
render() {
|
|
2524
2542
|
if (!this.state.hasError) return this.props.children;
|
|
2525
|
-
const message = /* @__PURE__ */
|
|
2543
|
+
const message = /* @__PURE__ */ jsx39(
|
|
2526
2544
|
EmptyState,
|
|
2527
2545
|
{
|
|
2528
|
-
icon: /* @__PURE__ */
|
|
2546
|
+
icon: /* @__PURE__ */ jsx39(IconAlertTriangle2, { size: 16, stroke: 1.5 }),
|
|
2529
2547
|
message: `Something went wrong${this.props.label ? ` in the ${this.props.label}` : ""}. Your data is safe \u2014 try again.`,
|
|
2530
2548
|
action: { label: "Try again", onClick: () => this.setState({ hasError: false }) }
|
|
2531
2549
|
}
|
|
2532
2550
|
);
|
|
2533
2551
|
if (this.props.frame) return this.props.frame(message);
|
|
2534
|
-
return this.props.fallbackClassName ? /* @__PURE__ */
|
|
2552
|
+
return this.props.fallbackClassName ? /* @__PURE__ */ jsx39("div", { className: this.props.fallbackClassName, children: message }) : message;
|
|
2535
2553
|
}
|
|
2536
2554
|
};
|
|
2537
2555
|
|
|
2538
2556
|
// src/ProgressBar.tsx
|
|
2539
2557
|
import { Progress } from "@base-ui/react/progress";
|
|
2540
|
-
import { jsx as
|
|
2558
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
2541
2559
|
var TRACK_CLASSES = {
|
|
2542
2560
|
default: "h-1.5 w-full overflow-hidden rounded-full bg-bg-inset",
|
|
2543
2561
|
// 4px, Katerina's ruling of 14 September; Peek's own bar is 3px until it takes this one.
|
|
@@ -2550,13 +2568,13 @@ var INDICATOR_CLASSES = {
|
|
|
2550
2568
|
function ProgressBar({ value, max, label, variant = "default", className }) {
|
|
2551
2569
|
return (
|
|
2552
2570
|
// `max={0}` needs no guard: Base UI reads the 0/0 share as an empty bar.
|
|
2553
|
-
/* @__PURE__ */
|
|
2571
|
+
/* @__PURE__ */ jsx40(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx40(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx40(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
|
|
2554
2572
|
);
|
|
2555
2573
|
}
|
|
2556
2574
|
|
|
2557
2575
|
// src/Breadcrumb.tsx
|
|
2558
|
-
import { Fragment as
|
|
2559
|
-
import { jsx as
|
|
2576
|
+
import { Fragment as Fragment8, useCallback as useCallback2, useLayoutEffect as useLayoutEffect4, useRef as useRef8, useState as useState6 } from "react";
|
|
2577
|
+
import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2560
2578
|
function Breadcrumb({ items, className }) {
|
|
2561
2579
|
const navRef = useRef8(null);
|
|
2562
2580
|
const labelRefs = useRef8([]);
|
|
@@ -2576,7 +2594,7 @@ function Breadcrumb({ items, className }) {
|
|
|
2576
2594
|
observer.observe(nav);
|
|
2577
2595
|
return () => observer.disconnect();
|
|
2578
2596
|
}, [measure, items]);
|
|
2579
|
-
return /* @__PURE__ */
|
|
2597
|
+
return /* @__PURE__ */ jsx41("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) => {
|
|
2580
2598
|
const last = index === items.length - 1;
|
|
2581
2599
|
const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
|
|
2582
2600
|
const text = cn(
|
|
@@ -2597,23 +2615,23 @@ function Breadcrumb({ items, className }) {
|
|
|
2597
2615
|
// on a box around it, which the link takes them from, rather than
|
|
2598
2616
|
// pushed into it (UIG-9); the link is still the one element that
|
|
2599
2617
|
// truncates and is measured.
|
|
2600
|
-
/* @__PURE__ */
|
|
2601
|
-
) : /* @__PURE__ */
|
|
2602
|
-
return /* @__PURE__ */ jsxs27(
|
|
2603
|
-
index > 0 && /* @__PURE__ */
|
|
2604
|
-
item.icon && /* @__PURE__ */
|
|
2618
|
+
/* @__PURE__ */ jsx41("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx41(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
|
|
2619
|
+
) : /* @__PURE__ */ jsx41("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
2620
|
+
return /* @__PURE__ */ jsxs27(Fragment8, { children: [
|
|
2621
|
+
index > 0 && /* @__PURE__ */ jsx41("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
2622
|
+
item.icon && /* @__PURE__ */ jsx41("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
|
|
2605
2623
|
truncated.has(index) ? (
|
|
2606
2624
|
// `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
|
|
2607
2625
|
// must keep truncating inside it, or wrapping it would widen the
|
|
2608
2626
|
// trail and the tooltip would never be needed again.
|
|
2609
|
-
/* @__PURE__ */
|
|
2627
|
+
/* @__PURE__ */ jsx41(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
|
|
2610
2628
|
) : crumb
|
|
2611
2629
|
] }, `${item.label}-${index}`);
|
|
2612
2630
|
}) });
|
|
2613
2631
|
}
|
|
2614
2632
|
|
|
2615
2633
|
// src/NavItem.tsx
|
|
2616
|
-
import { jsx as
|
|
2634
|
+
import { jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2617
2635
|
function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
|
|
2618
2636
|
return (
|
|
2619
2637
|
// @estiva-escape(no-copied-look): N5 (Katerina, 24 September: record only): a row that fills on hover, as PersonTrigger's row also does
|
|
@@ -2632,9 +2650,9 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
2632
2650
|
),
|
|
2633
2651
|
...props,
|
|
2634
2652
|
children: [
|
|
2635
|
-
icon && /* @__PURE__ */
|
|
2636
|
-
/* @__PURE__ */
|
|
2637
|
-
count ? /* @__PURE__ */
|
|
2653
|
+
icon && /* @__PURE__ */ jsx42("span", { className: "flex shrink-0 items-center", children: icon }),
|
|
2654
|
+
/* @__PURE__ */ jsx42("span", { className: "flex-1 truncate", children: label }),
|
|
2655
|
+
count ? /* @__PURE__ */ jsx42(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx42("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
2638
2656
|
]
|
|
2639
2657
|
}
|
|
2640
2658
|
)
|
|
@@ -2644,7 +2662,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
2644
2662
|
// src/Popover.tsx
|
|
2645
2663
|
import { useMemo as useMemo3 } from "react";
|
|
2646
2664
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
2647
|
-
import { jsx as
|
|
2665
|
+
import { jsx as jsx43, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2648
2666
|
var GAP5 = 4;
|
|
2649
2667
|
var VIEWPORT_PAD5 = 8;
|
|
2650
2668
|
function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
|
|
@@ -2661,8 +2679,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2661
2679
|
actionsRef,
|
|
2662
2680
|
modal: false,
|
|
2663
2681
|
children: [
|
|
2664
|
-
trigger && /* @__PURE__ */
|
|
2665
|
-
/* @__PURE__ */
|
|
2682
|
+
trigger && /* @__PURE__ */ jsx43(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
|
|
2683
|
+
/* @__PURE__ */ jsx43(BasePopover.Portal, { children: /* @__PURE__ */ jsx43(
|
|
2666
2684
|
BasePopover.Positioner,
|
|
2667
2685
|
{
|
|
2668
2686
|
anchor: anchorTarget,
|
|
@@ -2671,20 +2689,20 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2671
2689
|
sideOffset: GAP5,
|
|
2672
2690
|
collisionPadding: VIEWPORT_PAD5,
|
|
2673
2691
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2674
|
-
children: /* @__PURE__ */
|
|
2692
|
+
children: /* @__PURE__ */ jsx43(
|
|
2675
2693
|
BasePopover.Popup,
|
|
2676
2694
|
{
|
|
2677
2695
|
"aria-label": ariaLabel,
|
|
2678
2696
|
initialFocus: trigger ? void 0 : false,
|
|
2679
2697
|
finalFocus,
|
|
2680
2698
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
2681
|
-
render: /* @__PURE__ */
|
|
2682
|
-
children: /* @__PURE__ */
|
|
2699
|
+
render: /* @__PURE__ */ jsx43(MenuPanel, {}),
|
|
2700
|
+
children: /* @__PURE__ */ jsx43(
|
|
2683
2701
|
ScrollArea,
|
|
2684
2702
|
{
|
|
2685
2703
|
viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
|
|
2686
2704
|
contentClassName: cn("flex flex-col p-2", contentClassName),
|
|
2687
|
-
children: /* @__PURE__ */
|
|
2705
|
+
children: /* @__PURE__ */ jsx43(DividerInPanel.Provider, { value: true, children })
|
|
2688
2706
|
}
|
|
2689
2707
|
)
|
|
2690
2708
|
}
|
|
@@ -2698,9 +2716,9 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2698
2716
|
|
|
2699
2717
|
// src/Toolbar.tsx
|
|
2700
2718
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
2701
|
-
import { jsx as
|
|
2719
|
+
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
2702
2720
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
2703
|
-
const strip = /* @__PURE__ */
|
|
2721
|
+
const strip = /* @__PURE__ */ jsx44(
|
|
2704
2722
|
BaseToolbar.Root,
|
|
2705
2723
|
{
|
|
2706
2724
|
"aria-label": ariaLabel,
|
|
@@ -2711,27 +2729,27 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
2711
2729
|
}
|
|
2712
2730
|
);
|
|
2713
2731
|
if (!surface) return strip;
|
|
2714
|
-
return /* @__PURE__ */
|
|
2732
|
+
return /* @__PURE__ */ jsx44(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
2715
2733
|
}
|
|
2716
2734
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
2717
|
-
return /* @__PURE__ */
|
|
2735
|
+
return /* @__PURE__ */ jsx44(
|
|
2718
2736
|
BaseToolbar.Button,
|
|
2719
2737
|
{
|
|
2720
2738
|
ref,
|
|
2721
2739
|
disabled: disabled || !!disabledReason,
|
|
2722
2740
|
focusableWhenDisabled: true,
|
|
2723
|
-
render: /* @__PURE__ */
|
|
2741
|
+
render: /* @__PURE__ */ jsx44(IconButton, { disabled, disabledReason, ...props })
|
|
2724
2742
|
}
|
|
2725
2743
|
);
|
|
2726
2744
|
}
|
|
2727
2745
|
function ToolbarLink({ ref, href, ...props }) {
|
|
2728
|
-
return /* @__PURE__ */
|
|
2746
|
+
return /* @__PURE__ */ jsx44(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx44(IconButton, { href, ...props }) });
|
|
2729
2747
|
}
|
|
2730
2748
|
function ToolbarInput({ size, ...props }) {
|
|
2731
|
-
return /* @__PURE__ */
|
|
2749
|
+
return /* @__PURE__ */ jsx44(BaseToolbar.Input, { render: /* @__PURE__ */ jsx44(TextInput, { size }), ...props });
|
|
2732
2750
|
}
|
|
2733
2751
|
function ToolbarSeparator({ className }) {
|
|
2734
|
-
return /* @__PURE__ */
|
|
2752
|
+
return /* @__PURE__ */ jsx44(
|
|
2735
2753
|
BaseToolbar.Separator,
|
|
2736
2754
|
{
|
|
2737
2755
|
orientation: "vertical",
|
|
@@ -2741,9 +2759,9 @@ function ToolbarSeparator({ className }) {
|
|
|
2741
2759
|
}
|
|
2742
2760
|
|
|
2743
2761
|
// src/ReactionPicker.tsx
|
|
2744
|
-
import { jsx as
|
|
2762
|
+
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
2745
2763
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
2746
|
-
return /* @__PURE__ */
|
|
2764
|
+
return /* @__PURE__ */ jsx45(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
2747
2765
|
/*
|
|
2748
2766
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
2749
2767
|
would become the toolbar's item and the button inside it would never
|
|
@@ -2753,14 +2771,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2753
2771
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
2754
2772
|
and both say the meaning rather than the glyph.
|
|
2755
2773
|
*/
|
|
2756
|
-
/* @__PURE__ */
|
|
2774
|
+
/* @__PURE__ */ jsx45(
|
|
2757
2775
|
ToolbarButton,
|
|
2758
2776
|
{
|
|
2759
2777
|
"aria-label": option.label,
|
|
2760
2778
|
tooltip: option.label,
|
|
2761
2779
|
onClick: () => onSelect(option.emoji),
|
|
2762
2780
|
className: "size-7",
|
|
2763
|
-
children: /* @__PURE__ */
|
|
2781
|
+
children: /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
|
|
2764
2782
|
},
|
|
2765
2783
|
option.emoji
|
|
2766
2784
|
)
|
|
@@ -2769,23 +2787,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2769
2787
|
|
|
2770
2788
|
// src/PreviewCard.tsx
|
|
2771
2789
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
2772
|
-
import { jsx as
|
|
2790
|
+
import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2773
2791
|
var GAP6 = 12;
|
|
2774
2792
|
var VIEWPORT_PAD6 = 8;
|
|
2775
2793
|
var OPEN_DELAY2 = 350;
|
|
2776
2794
|
var CLOSE_DELAY = 200;
|
|
2777
2795
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, contentClassName, wrapperClassName }) {
|
|
2778
2796
|
return /* @__PURE__ */ jsxs30(BasePreviewCard.Root, { children: [
|
|
2779
|
-
/* @__PURE__ */
|
|
2797
|
+
/* @__PURE__ */ jsx46(
|
|
2780
2798
|
BasePreviewCard.Trigger,
|
|
2781
2799
|
{
|
|
2782
2800
|
delay,
|
|
2783
2801
|
closeDelay,
|
|
2784
|
-
render: /* @__PURE__ */
|
|
2802
|
+
render: /* @__PURE__ */ jsx46("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
2785
2803
|
children
|
|
2786
2804
|
}
|
|
2787
2805
|
),
|
|
2788
|
-
/* @__PURE__ */
|
|
2806
|
+
/* @__PURE__ */ jsx46(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx46(
|
|
2789
2807
|
BasePreviewCard.Positioner,
|
|
2790
2808
|
{
|
|
2791
2809
|
side,
|
|
@@ -2793,12 +2811,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2793
2811
|
sideOffset: GAP6,
|
|
2794
2812
|
collisionPadding: VIEWPORT_PAD6,
|
|
2795
2813
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2796
|
-
children: /* @__PURE__ */
|
|
2814
|
+
children: /* @__PURE__ */ jsx46(
|
|
2797
2815
|
BasePreviewCard.Popup,
|
|
2798
2816
|
{
|
|
2799
2817
|
className: cn("w-[360px] p-0 outline-none", className),
|
|
2800
|
-
render: /* @__PURE__ */
|
|
2801
|
-
children: /* @__PURE__ */
|
|
2818
|
+
render: /* @__PURE__ */ jsx46(MenuPanel, {}),
|
|
2819
|
+
children: /* @__PURE__ */ jsx46(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
|
|
2802
2820
|
}
|
|
2803
2821
|
)
|
|
2804
2822
|
}
|
|
@@ -2807,13 +2825,13 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2807
2825
|
}
|
|
2808
2826
|
|
|
2809
2827
|
// src/Rail.tsx
|
|
2810
|
-
import { jsx as
|
|
2828
|
+
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
2811
2829
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
2812
|
-
return /* @__PURE__ */
|
|
2830
|
+
return /* @__PURE__ */ jsx47("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
2813
2831
|
}
|
|
2814
2832
|
|
|
2815
2833
|
// src/RailItem.tsx
|
|
2816
|
-
import { jsx as
|
|
2834
|
+
import { jsx as jsx48, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2817
2835
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
2818
2836
|
return /* @__PURE__ */ jsxs31(
|
|
2819
2837
|
"a",
|
|
@@ -2823,14 +2841,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
2823
2841
|
className: cn("group flex h-12 w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
2824
2842
|
...props,
|
|
2825
2843
|
children: [
|
|
2826
|
-
/* @__PURE__ */
|
|
2844
|
+
/* @__PURE__ */ jsx48(
|
|
2827
2845
|
"div",
|
|
2828
2846
|
{
|
|
2829
2847
|
className: cn(
|
|
2830
2848
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
2831
2849
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
2832
2850
|
),
|
|
2833
|
-
children: /* @__PURE__ */
|
|
2851
|
+
children: /* @__PURE__ */ jsx48(
|
|
2834
2852
|
"span",
|
|
2835
2853
|
{
|
|
2836
2854
|
className: cn(
|
|
@@ -2842,25 +2860,12 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
2842
2860
|
)
|
|
2843
2861
|
}
|
|
2844
2862
|
),
|
|
2845
|
-
/* @__PURE__ */
|
|
2863
|
+
/* @__PURE__ */ jsx48("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
2846
2864
|
]
|
|
2847
2865
|
}
|
|
2848
2866
|
);
|
|
2849
2867
|
}
|
|
2850
2868
|
|
|
2851
|
-
// src/Sidebar.tsx
|
|
2852
|
-
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
2853
|
-
function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
|
|
2854
|
-
return /* @__PURE__ */ jsx48(
|
|
2855
|
-
"nav",
|
|
2856
|
-
{
|
|
2857
|
-
"aria-label": ariaLabel,
|
|
2858
|
-
className: cn("flex w-60 shrink-0 flex-col border-r border-border-default bg-bg-surface", className),
|
|
2859
|
-
children: /* @__PURE__ */ jsx48(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
|
|
2860
|
-
}
|
|
2861
|
-
);
|
|
2862
|
-
}
|
|
2863
|
-
|
|
2864
2869
|
// src/Property.tsx
|
|
2865
2870
|
import { jsx as jsx49, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2866
2871
|
var VALUE_CLASSES = "contents";
|
|
@@ -2952,7 +2957,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2952
2957
|
// src/SectionHeader.tsx
|
|
2953
2958
|
import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
|
|
2954
2959
|
import { useRender } from "@base-ui/react/use-render";
|
|
2955
|
-
import { Fragment as
|
|
2960
|
+
import { Fragment as Fragment9, jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2956
2961
|
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", hover = "fill", render, className }) {
|
|
2957
2962
|
const titleElement = useRender({
|
|
2958
2963
|
render: render ?? (chevron ? /* @__PURE__ */ jsx52("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx52("span", {})),
|
|
@@ -2961,7 +2966,7 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2961
2966
|
// whole row up to the actions is the hit target, as it was when the
|
|
2962
2967
|
// row itself carried the click.
|
|
2963
2968
|
className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
|
|
2964
|
-
children: /* @__PURE__ */ jsxs35(
|
|
2969
|
+
children: /* @__PURE__ */ jsxs35(Fragment9, { children: [
|
|
2965
2970
|
chevron && /* @__PURE__ */ jsx52(
|
|
2966
2971
|
IconChevronRight2,
|
|
2967
2972
|
{
|
|
@@ -3157,7 +3162,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3157
3162
|
}
|
|
3158
3163
|
|
|
3159
3164
|
// src/Toast.tsx
|
|
3160
|
-
import { createContext as
|
|
3165
|
+
import { createContext as createContext6, useContext as useContext6, useMemo as useMemo4 } from "react";
|
|
3161
3166
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
3162
3167
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
3163
3168
|
import { jsx as jsx57, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
@@ -3208,7 +3213,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
|
|
|
3208
3213
|
hasAction && /* @__PURE__ */ jsx57(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
3209
3214
|
] });
|
|
3210
3215
|
}
|
|
3211
|
-
var ToastContext =
|
|
3216
|
+
var ToastContext = createContext6(null);
|
|
3212
3217
|
var VISIBLE_TOASTS = 3;
|
|
3213
3218
|
function ToastProvider({ children }) {
|
|
3214
3219
|
const manager = useMemo4(() => BaseToast.createToastManager(), []);
|
|
@@ -3264,7 +3269,7 @@ function ToastList() {
|
|
|
3264
3269
|
});
|
|
3265
3270
|
}
|
|
3266
3271
|
function useToast() {
|
|
3267
|
-
const ctx =
|
|
3272
|
+
const ctx = useContext6(ToastContext);
|
|
3268
3273
|
if (!ctx) throw new Error("useToast must be used within ToastProvider");
|
|
3269
3274
|
return ctx;
|
|
3270
3275
|
}
|