@estiva-app/ui 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AppShell.d.ts.map +1 -1
- package/dist/Breadcrumb.d.ts +7 -1
- package/dist/Breadcrumb.d.ts.map +1 -1
- package/dist/Chip.d.ts.map +1 -1
- package/dist/CollapsibleSection.d.ts +42 -0
- package/dist/CollapsibleSection.d.ts.map +1 -0
- package/dist/EmptyState.d.ts +19 -5
- package/dist/EmptyState.d.ts.map +1 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/ScrollArea.d.ts.map +1 -1
- package/dist/SectionHeader.d.ts +31 -10
- package/dist/SectionHeader.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +202 -129
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/AppShell.mdx +15 -0
- package/src/AppShell.stories.tsx +15 -0
- package/src/AppShell.test.tsx +39 -0
- package/src/AppShell.tsx +22 -7
- package/src/Breadcrumb.mdx +6 -0
- package/src/Breadcrumb.stories.tsx +12 -0
- package/src/Breadcrumb.test.tsx +10 -0
- package/src/Breadcrumb.tsx +17 -2
- package/src/Chip.tsx +10 -2
- package/src/CollapsibleSection.mdx +72 -0
- package/src/CollapsibleSection.stories.tsx +38 -0
- package/src/CollapsibleSection.test.tsx +81 -0
- package/src/CollapsibleSection.tsx +92 -0
- package/src/EmptyState.mdx +30 -10
- package/src/EmptyState.stories.tsx +7 -3
- package/src/EmptyState.test.tsx +39 -0
- package/src/EmptyState.tsx +23 -6
- package/src/NavItem.tsx +5 -1
- package/src/ScrollArea.mdx +6 -0
- package/src/ScrollArea.stories.tsx +29 -0
- package/src/ScrollArea.test.tsx +15 -0
- package/src/ScrollArea.tsx +17 -4
- package/src/SectionHeader.mdx +26 -17
- package/src/SectionHeader.stories.tsx +4 -35
- package/src/SectionHeader.test.tsx +40 -0
- package/src/SectionHeader.tsx +70 -39
- package/src/Sidebar.mdx +14 -10
- package/src/Sidebar.stories.tsx +17 -15
- package/src/index.ts +1 -0
- package/stories/Choosing.mdx +2 -1
package/dist/index.js
CHANGED
|
@@ -34,11 +34,36 @@ function cn(...inputs) {
|
|
|
34
34
|
return twMerge(clsx(inputs));
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
// src/
|
|
37
|
+
// src/ScrollArea.tsx
|
|
38
|
+
import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
|
|
38
39
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
40
|
+
var BAR = "flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
|
|
41
|
+
var THUMB = "rounded-full bg-border-strong";
|
|
42
|
+
function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, children }) {
|
|
43
|
+
const vertical = orientation !== "horizontal";
|
|
44
|
+
const horizontal = orientation !== "vertical";
|
|
45
|
+
return /* @__PURE__ */ jsxs(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
|
|
46
|
+
/* @__PURE__ */ jsx(
|
|
47
|
+
BaseScrollArea.Viewport,
|
|
48
|
+
{
|
|
49
|
+
className: cn(
|
|
50
|
+
"h-full w-full outline-none data-[has-overflow-x]:overscroll-x-contain data-[has-overflow-y]:overscroll-y-contain",
|
|
51
|
+
viewportClassName
|
|
52
|
+
),
|
|
53
|
+
children: /* @__PURE__ */ jsx(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children })
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
vertical && /* @__PURE__ */ jsx(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5"), children: /* @__PURE__ */ jsx(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
|
|
57
|
+
horizontal && /* @__PURE__ */ jsx(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5"), children: /* @__PURE__ */ jsx(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
|
|
58
|
+
vertical && horizontal && /* @__PURE__ */ jsx(BaseScrollArea.Corner, {})
|
|
59
|
+
] });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/TopBar.tsx
|
|
63
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
39
64
|
function TopBar({ variant = "solid", menu, logo, search, right, className }) {
|
|
40
65
|
const floating = variant === "floating";
|
|
41
|
-
return /* @__PURE__ */
|
|
66
|
+
return /* @__PURE__ */ jsxs2(
|
|
42
67
|
"header",
|
|
43
68
|
{
|
|
44
69
|
className: cn(
|
|
@@ -47,27 +72,27 @@ function TopBar({ variant = "solid", menu, logo, search, right, className }) {
|
|
|
47
72
|
className
|
|
48
73
|
),
|
|
49
74
|
children: [
|
|
50
|
-
(menu || logo) && /* @__PURE__ */
|
|
75
|
+
(menu || logo) && /* @__PURE__ */ jsxs2("div", { className: cn("flex shrink-0 items-center gap-2", floating && "pointer-events-auto"), children: [
|
|
51
76
|
menu,
|
|
52
|
-
logo && /* @__PURE__ */
|
|
77
|
+
logo && /* @__PURE__ */ jsx2("div", { className: "flex items-center text-body-2-strong text-text-primary", children: logo })
|
|
53
78
|
] }),
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ jsx2("div", { className: cn("flex min-w-0 flex-1 items-center justify-center", floating && "pointer-events-auto"), children: search }),
|
|
80
|
+
/* @__PURE__ */ jsx2("div", { className: cn("flex shrink-0 items-center gap-[6px]", floating && "pointer-events-auto"), children: right })
|
|
56
81
|
]
|
|
57
82
|
}
|
|
58
83
|
);
|
|
59
84
|
}
|
|
60
85
|
|
|
61
86
|
// src/AppShell.tsx
|
|
62
|
-
import { jsx as
|
|
87
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
63
88
|
function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav, children }) {
|
|
64
|
-
const bar = /* @__PURE__ */
|
|
89
|
+
const bar = /* @__PURE__ */ jsx3(TopBar, { variant, menu, logo, search, right: identity });
|
|
65
90
|
if (variant === "floating") {
|
|
66
|
-
return /* @__PURE__ */
|
|
91
|
+
return /* @__PURE__ */ jsxs3("div", { className: "relative h-full min-h-0 overflow-hidden bg-bg-base", children: [
|
|
67
92
|
bar,
|
|
68
|
-
/* @__PURE__ */
|
|
93
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex h-full pb-4 pr-4 pt-[52px]", children: [
|
|
69
94
|
nav,
|
|
70
|
-
/* @__PURE__ */
|
|
95
|
+
/* @__PURE__ */ jsxs3(
|
|
71
96
|
"div",
|
|
72
97
|
{
|
|
73
98
|
className: cn(
|
|
@@ -76,7 +101,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
76
101
|
),
|
|
77
102
|
children: [
|
|
78
103
|
banner,
|
|
79
|
-
/* @__PURE__ */
|
|
104
|
+
/* @__PURE__ */ jsx3("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children })
|
|
80
105
|
]
|
|
81
106
|
}
|
|
82
107
|
)
|
|
@@ -84,20 +109,22 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
84
109
|
] });
|
|
85
110
|
}
|
|
86
111
|
return (
|
|
87
|
-
/* `relative overflow-hidden` is the seal the floating manner already has
|
|
112
|
+
/* `relative overflow-hidden` is the seal the floating manner already has
|
|
113
|
+
(and the ScrollArea's own root is `relative`, so an absolutely placed
|
|
114
|
+
stray inside a page now belongs to the region and scrolls with it),
|
|
88
115
|
and it takes both halves: an absolutely positioned descendant with no
|
|
89
116
|
positioned ancestor belongs to the *viewport*, so a scroll container
|
|
90
117
|
never clips it and the document itself gains its position as scroll
|
|
91
118
|
range — the whole page scrolls, navigation and top bar included.
|
|
92
119
|
`relative` claims such strays for the shell; `overflow-hidden` clips
|
|
93
120
|
them at its edge. Either alone seals nothing. */
|
|
94
|
-
/* @__PURE__ */
|
|
121
|
+
/* @__PURE__ */ jsxs3("div", { className: "relative flex h-full min-h-0 flex-col overflow-hidden bg-bg-base text-text-primary", children: [
|
|
95
122
|
bar,
|
|
96
|
-
/* @__PURE__ */
|
|
123
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 flex-1", children: [
|
|
97
124
|
nav,
|
|
98
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
|
|
99
126
|
banner,
|
|
100
|
-
/* @__PURE__ */
|
|
127
|
+
/* @__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 }) })
|
|
101
128
|
] })
|
|
102
129
|
] })
|
|
103
130
|
] })
|
|
@@ -107,7 +134,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
107
134
|
// src/Avatar.tsx
|
|
108
135
|
import { useState } from "react";
|
|
109
136
|
import { IconUserFilled } from "@tabler/icons-react";
|
|
110
|
-
import { jsx as
|
|
137
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
111
138
|
var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
|
|
112
139
|
var hueFor = (key) => {
|
|
113
140
|
let h = 0;
|
|
@@ -123,13 +150,13 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
123
150
|
const [broken, setBroken] = useState(false);
|
|
124
151
|
const label = name || alt;
|
|
125
152
|
const picture = src && !broken ? src : void 0;
|
|
126
|
-
return /* @__PURE__ */
|
|
153
|
+
return /* @__PURE__ */ jsx4(
|
|
127
154
|
"div",
|
|
128
155
|
{
|
|
129
156
|
...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
|
|
130
157
|
className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
|
|
131
158
|
style: { width: size, height: size },
|
|
132
|
-
children: picture ? /* @__PURE__ */
|
|
159
|
+
children: picture ? /* @__PURE__ */ jsx4("img", { src: picture, alt: "", className: "w-full h-full object-cover", onError: () => setBroken(true) }) : label ? /* @__PURE__ */ jsx4(
|
|
133
160
|
"div",
|
|
134
161
|
{
|
|
135
162
|
className: "w-full h-full flex items-center justify-center font-semibold leading-none",
|
|
@@ -143,29 +170,29 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
143
170
|
},
|
|
144
171
|
children: initialsFor(label)
|
|
145
172
|
}
|
|
146
|
-
) : /* @__PURE__ */
|
|
173
|
+
) : /* @__PURE__ */ jsx4("div", { className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx4(IconUserFilled, { size: Math.round(size * 0.5) }) })
|
|
147
174
|
}
|
|
148
175
|
);
|
|
149
176
|
}
|
|
150
177
|
|
|
151
178
|
// src/AvatarGroup.tsx
|
|
152
|
-
import { jsx as
|
|
179
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
153
180
|
function AvatarGroup({ members, size = 24 }) {
|
|
154
181
|
const visible = members.slice(0, 3);
|
|
155
182
|
const overlap = Math.round(size / 3);
|
|
156
183
|
const ring = size / 12;
|
|
157
|
-
return /* @__PURE__ */
|
|
184
|
+
return /* @__PURE__ */ jsx5("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
|
|
158
185
|
/*
|
|
159
186
|
The wrapper carries the overlap and the ring; the face carries
|
|
160
187
|
neither. It must never clip — see the note at the top of the file —
|
|
161
188
|
so it has the avatar's own radius and no overflow of its own.
|
|
162
189
|
*/
|
|
163
|
-
/* @__PURE__ */
|
|
190
|
+
/* @__PURE__ */ jsx5(
|
|
164
191
|
"span",
|
|
165
192
|
{
|
|
166
193
|
className: "relative flex rounded-sm",
|
|
167
194
|
style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
|
|
168
|
-
children: /* @__PURE__ */
|
|
195
|
+
children: /* @__PURE__ */ jsx5(Avatar, { size, name: member.name, src: member.picture, label: member.name })
|
|
169
196
|
},
|
|
170
197
|
i
|
|
171
198
|
)
|
|
@@ -182,9 +209,9 @@ import { Button as BaseButton } from "@base-ui/react/button";
|
|
|
182
209
|
import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
|
|
183
210
|
|
|
184
211
|
// src/Kbd.tsx
|
|
185
|
-
import { jsx as
|
|
212
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
186
213
|
function Kbd({ children, className }) {
|
|
187
|
-
return /* @__PURE__ */
|
|
214
|
+
return /* @__PURE__ */ jsx6(
|
|
188
215
|
"kbd",
|
|
189
216
|
{
|
|
190
217
|
className: cn(
|
|
@@ -199,21 +226,21 @@ function Kbd({ children, className }) {
|
|
|
199
226
|
}
|
|
200
227
|
|
|
201
228
|
// src/Tooltip.tsx
|
|
202
|
-
import { jsx as
|
|
229
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
203
230
|
var OPEN_DELAY = 300;
|
|
204
231
|
function TooltipProvider({ delay = OPEN_DELAY, closeDelay, timeout, children }) {
|
|
205
|
-
return /* @__PURE__ */
|
|
232
|
+
return /* @__PURE__ */ jsx7(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
|
|
206
233
|
}
|
|
207
234
|
function Tooltip({ label, shortcut, className, ...props }) {
|
|
208
|
-
return /* @__PURE__ */
|
|
209
|
-
/* @__PURE__ */
|
|
210
|
-
shortcut && /* @__PURE__ */
|
|
235
|
+
return /* @__PURE__ */ jsxs4("div", { role: "tooltip", className: cn("bg-bg-elevated border border-border-default rounded-lg h-[30px] flex items-center justify-center gap-1.5 px-2 shadow-lg", className), ...props, children: [
|
|
236
|
+
/* @__PURE__ */ jsx7("span", { className: "text-caption text-text-primary whitespace-nowrap", children: label }),
|
|
237
|
+
shortcut && /* @__PURE__ */ jsx7(Kbd, { children: shortcut })
|
|
211
238
|
] });
|
|
212
239
|
}
|
|
213
240
|
var GAP = 6;
|
|
214
241
|
var VIEWPORT_PAD = 8;
|
|
215
242
|
function TooltipSurface({ label, shortcut, placement }) {
|
|
216
|
-
return /* @__PURE__ */
|
|
243
|
+
return /* @__PURE__ */ jsx7(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx7(
|
|
217
244
|
BaseTooltip.Positioner,
|
|
218
245
|
{
|
|
219
246
|
side: placement,
|
|
@@ -222,10 +249,10 @@ function TooltipSurface({ label, shortcut, placement }) {
|
|
|
222
249
|
collisionPadding: VIEWPORT_PAD,
|
|
223
250
|
positionMethod: "fixed",
|
|
224
251
|
className: "pointer-events-none z-[9999]",
|
|
225
|
-
children: /* @__PURE__ */
|
|
252
|
+
children: /* @__PURE__ */ jsx7(
|
|
226
253
|
BaseTooltip.Popup,
|
|
227
254
|
{
|
|
228
|
-
render: /* @__PURE__ */
|
|
255
|
+
render: /* @__PURE__ */ jsx7(
|
|
229
256
|
Tooltip,
|
|
230
257
|
{
|
|
231
258
|
label,
|
|
@@ -245,20 +272,20 @@ function TooltipSurface({ label, shortcut, placement }) {
|
|
|
245
272
|
) });
|
|
246
273
|
}
|
|
247
274
|
function WithTooltip({ label, shortcut, placement = "top", wrapperClassName, children }) {
|
|
248
|
-
return /* @__PURE__ */
|
|
249
|
-
/* @__PURE__ */
|
|
250
|
-
/* @__PURE__ */
|
|
275
|
+
return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
|
|
276
|
+
/* @__PURE__ */ jsx7(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: /* @__PURE__ */ jsx7("div", { className: cn("inline-flex shrink-0", wrapperClassName) }), children }),
|
|
277
|
+
/* @__PURE__ */ jsx7(TooltipSurface, { label, shortcut, placement })
|
|
251
278
|
] });
|
|
252
279
|
}
|
|
253
280
|
function TooltipTrigger({ label, shortcut, placement = "top", children }) {
|
|
254
|
-
return /* @__PURE__ */
|
|
255
|
-
/* @__PURE__ */
|
|
256
|
-
/* @__PURE__ */
|
|
281
|
+
return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
|
|
282
|
+
/* @__PURE__ */ jsx7(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: children }),
|
|
283
|
+
/* @__PURE__ */ jsx7(TooltipSurface, { label, shortcut, placement })
|
|
257
284
|
] });
|
|
258
285
|
}
|
|
259
286
|
|
|
260
287
|
// src/IconButton.tsx
|
|
261
|
-
import { jsx as
|
|
288
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
262
289
|
function IconButton({
|
|
263
290
|
variant = "muted",
|
|
264
291
|
className,
|
|
@@ -271,7 +298,7 @@ function IconButton({
|
|
|
271
298
|
type = "button",
|
|
272
299
|
...props
|
|
273
300
|
}) {
|
|
274
|
-
const button = /* @__PURE__ */
|
|
301
|
+
const button = /* @__PURE__ */ jsx8(
|
|
275
302
|
BaseButton,
|
|
276
303
|
{
|
|
277
304
|
type,
|
|
@@ -299,13 +326,13 @@ function IconButton({
|
|
|
299
326
|
);
|
|
300
327
|
const label = disabledReason ?? tooltip;
|
|
301
328
|
if (label) {
|
|
302
|
-
return /* @__PURE__ */
|
|
329
|
+
return /* @__PURE__ */ jsx8(TooltipTrigger, { label, shortcut: disabledReason ? void 0 : tooltipShortcut, placement: tooltipPlacement, children: button });
|
|
303
330
|
}
|
|
304
331
|
return button;
|
|
305
332
|
}
|
|
306
333
|
|
|
307
334
|
// src/Banner.tsx
|
|
308
|
-
import { jsx as
|
|
335
|
+
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
309
336
|
var TONE_STYLES = {
|
|
310
337
|
ok: "bg-success-muted text-success-default",
|
|
311
338
|
error: "bg-error-muted text-error-default",
|
|
@@ -315,17 +342,17 @@ var TONE_STYLES = {
|
|
|
315
342
|
function Banner({ tone, children, onDismiss, dismissLabel = "Dismiss", className }) {
|
|
316
343
|
const role = tone === "error" ? "alert" : "status";
|
|
317
344
|
if (!onDismiss) {
|
|
318
|
-
return /* @__PURE__ */
|
|
345
|
+
return /* @__PURE__ */ jsx9("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
|
|
319
346
|
}
|
|
320
|
-
return /* @__PURE__ */
|
|
321
|
-
/* @__PURE__ */
|
|
322
|
-
/* @__PURE__ */
|
|
347
|
+
return /* @__PURE__ */ jsxs5("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
|
|
348
|
+
/* @__PURE__ */ jsx9("span", { className: "min-w-0 flex-1", children }),
|
|
349
|
+
/* @__PURE__ */ jsx9(IconButton, { "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0 text-current hover:text-current", children: /* @__PURE__ */ jsx9(IconX, { size: 16, stroke: 1.5 }) })
|
|
323
350
|
] });
|
|
324
351
|
}
|
|
325
352
|
|
|
326
353
|
// src/Button.tsx
|
|
327
354
|
import { Button as BaseButton2 } from "@base-ui/react/button";
|
|
328
|
-
import { jsx as
|
|
355
|
+
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
329
356
|
function Button({
|
|
330
357
|
variant = "muted",
|
|
331
358
|
size = "default",
|
|
@@ -338,7 +365,7 @@ function Button({
|
|
|
338
365
|
...props
|
|
339
366
|
}) {
|
|
340
367
|
const hasLeadingIcon = !!leadingIcon;
|
|
341
|
-
const button = /* @__PURE__ */
|
|
368
|
+
const button = /* @__PURE__ */ jsxs6(
|
|
342
369
|
BaseButton2,
|
|
343
370
|
{
|
|
344
371
|
type,
|
|
@@ -372,13 +399,13 @@ function Button({
|
|
|
372
399
|
]
|
|
373
400
|
}
|
|
374
401
|
);
|
|
375
|
-
return disabledReason ? /* @__PURE__ */
|
|
402
|
+
return disabledReason ? /* @__PURE__ */ jsx10(TooltipTrigger, { label: disabledReason, children: button }) : button;
|
|
376
403
|
}
|
|
377
404
|
|
|
378
405
|
// src/Checkbox.tsx
|
|
379
406
|
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
|
|
380
407
|
import { IconCheck } from "@tabler/icons-react";
|
|
381
|
-
import { jsx as
|
|
408
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
382
409
|
function squareClasses(checked, disabled, interactive, className) {
|
|
383
410
|
return cn(
|
|
384
411
|
"inline-flex items-center justify-center size-4 shrink-0 rounded-[4px] border transition-colors",
|
|
@@ -391,9 +418,9 @@ function squareClasses(checked, disabled, interactive, className) {
|
|
|
391
418
|
var tickClasses = (checked) => cn("flex", !checked && "invisible");
|
|
392
419
|
function Checkbox({ checked, onChange, disabled = false, className, ...aria }) {
|
|
393
420
|
if (!onChange) {
|
|
394
|
-
return /* @__PURE__ */
|
|
421
|
+
return /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx11("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx11(IconCheck, { size: 12, stroke: 3 }) }) });
|
|
395
422
|
}
|
|
396
|
-
return /* @__PURE__ */
|
|
423
|
+
return /* @__PURE__ */ jsx11(
|
|
397
424
|
BaseCheckbox.Root,
|
|
398
425
|
{
|
|
399
426
|
checked,
|
|
@@ -403,13 +430,13 @@ function Checkbox({ checked, onChange, disabled = false, className, ...aria }) {
|
|
|
403
430
|
onCheckedChange: (next) => onChange(next),
|
|
404
431
|
onClick: (e) => e.stopPropagation(),
|
|
405
432
|
className: (state) => squareClasses(state.checked, state.disabled, true, className),
|
|
406
|
-
children: /* @__PURE__ */
|
|
433
|
+
children: /* @__PURE__ */ jsx11(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx11(IconCheck, { size: 12, stroke: 3 }) })
|
|
407
434
|
}
|
|
408
435
|
);
|
|
409
436
|
}
|
|
410
437
|
|
|
411
438
|
// src/Chip.tsx
|
|
412
|
-
import { jsx as
|
|
439
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
413
440
|
var typeStyles = {
|
|
414
441
|
neutral: "bg-bg-inset text-text-primary",
|
|
415
442
|
brand: "bg-accent-muted text-accent-primary signal:border signal:border-accent-outline",
|
|
@@ -419,10 +446,18 @@ var typeStyles = {
|
|
|
419
446
|
error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
|
|
420
447
|
};
|
|
421
448
|
function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className }) {
|
|
422
|
-
return /* @__PURE__ */
|
|
423
|
-
leadingIcon && /* @__PURE__ */
|
|
424
|
-
label &&
|
|
425
|
-
|
|
449
|
+
return /* @__PURE__ */ jsxs7("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: [
|
|
450
|
+
leadingIcon && /* @__PURE__ */ jsx12("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
|
|
451
|
+
label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
|
|
452
|
+
// of growing past it — Ship's project chip on an issue row
|
|
453
|
+
// (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
|
|
454
|
+
// `truncate`, because `truncate` is `overflow: hidden` on both axes and
|
|
455
|
+
// the label's line box (11px under Signal) is tighter than its glyphs —
|
|
456
|
+
// the screenshot diff caught every descender cut off. `clip` is the
|
|
457
|
+
// one overflow that leaves the other axis visible. A chip with no cap
|
|
458
|
+
// draws exactly as before.
|
|
459
|
+
/* @__PURE__ */ jsx12("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tracking-[0.02em] signal:tabular-nums", children: label }),
|
|
460
|
+
trailingIcon && /* @__PURE__ */ jsx12("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
426
461
|
] });
|
|
427
462
|
}
|
|
428
463
|
|
|
@@ -459,22 +494,6 @@ function triggerDisabled(trigger) {
|
|
|
459
494
|
return !!(props.disabled || props.disabledReason);
|
|
460
495
|
}
|
|
461
496
|
|
|
462
|
-
// src/ScrollArea.tsx
|
|
463
|
-
import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
|
|
464
|
-
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
465
|
-
var BAR = "flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
|
|
466
|
-
var THUMB = "rounded-full bg-border-strong";
|
|
467
|
-
function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, children }) {
|
|
468
|
-
const vertical = orientation !== "horizontal";
|
|
469
|
-
const horizontal = orientation !== "vertical";
|
|
470
|
-
return /* @__PURE__ */ jsxs7(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
|
|
471
|
-
/* @__PURE__ */ jsx12(BaseScrollArea.Viewport, { className: cn("h-full w-full overscroll-contain outline-none", viewportClassName), children: /* @__PURE__ */ jsx12(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children }) }),
|
|
472
|
-
vertical && /* @__PURE__ */ jsx12(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5"), children: /* @__PURE__ */ jsx12(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
|
|
473
|
-
horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5"), children: /* @__PURE__ */ jsx12(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
|
|
474
|
-
vertical && horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Corner, {})
|
|
475
|
-
] });
|
|
476
|
-
}
|
|
477
|
-
|
|
478
497
|
// src/SectionLabel.tsx
|
|
479
498
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
480
499
|
function SectionLabel({ children, className }) {
|
|
@@ -1428,8 +1447,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1428
1447
|
// src/EmptyState.tsx
|
|
1429
1448
|
import { IconMessage2 } from "@tabler/icons-react";
|
|
1430
1449
|
import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1431
|
-
function EmptyState({ icon, message, className }) {
|
|
1432
|
-
|
|
1450
|
+
function EmptyState({ icon, message, scope = "page", className }) {
|
|
1451
|
+
if (scope === "section") {
|
|
1452
|
+
return /* @__PURE__ */ jsx27("p", { className: cn("text-body-2 text-text-secondary", className), children: message });
|
|
1453
|
+
}
|
|
1454
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1433
1455
|
/* @__PURE__ */ jsx27("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx27(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1434
1456
|
/* @__PURE__ */ jsx27("p", { className: "text-body-2 text-text-secondary text-center", children: message })
|
|
1435
1457
|
] });
|
|
@@ -1475,13 +1497,14 @@ function Breadcrumb({ items, className }) {
|
|
|
1475
1497
|
}, [measure, items]);
|
|
1476
1498
|
return /* @__PURE__ */ jsx29("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-[14px] leading-[140%]", className), children: items.map((item, index) => {
|
|
1477
1499
|
const last = index === items.length - 1;
|
|
1500
|
+
const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
|
|
1478
1501
|
const text = cn(
|
|
1479
1502
|
"truncate",
|
|
1480
1503
|
// A mono crumb is a ref — the identity. It never gives up width to a
|
|
1481
1504
|
// long name beside it (the LongName story always claimed "the ref
|
|
1482
1505
|
// stays"; flexbox was squeezing it anyway until this line).
|
|
1483
1506
|
item.mono && "shrink-0 font-mono text-[12px] leading-[120%]",
|
|
1484
|
-
|
|
1507
|
+
tone
|
|
1485
1508
|
);
|
|
1486
1509
|
const setLabelRef = (el) => {
|
|
1487
1510
|
labelRefs.current[index] = el;
|
|
@@ -1489,6 +1512,7 @@ function Breadcrumb({ items, className }) {
|
|
|
1489
1512
|
const crumb = item.href ? /* @__PURE__ */ jsx29("a", { ref: setLabelRef, href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label }) : /* @__PURE__ */ jsx29("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
1490
1513
|
return /* @__PURE__ */ jsxs20(Fragment4, { children: [
|
|
1491
1514
|
index > 0 && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
1515
|
+
item.icon && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
|
|
1492
1516
|
truncated.has(index) ? (
|
|
1493
1517
|
// `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
|
|
1494
1518
|
// must keep truncating inside it, or wrapping it would widen the
|
|
@@ -1519,7 +1543,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
1519
1543
|
children: [
|
|
1520
1544
|
icon && /* @__PURE__ */ jsx30("span", { className: "flex shrink-0 items-center", children: icon }),
|
|
1521
1545
|
/* @__PURE__ */ jsx30("span", { className: "flex-1 truncate", children: label }),
|
|
1522
|
-
count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "shrink-0 font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
1546
|
+
count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
1523
1547
|
]
|
|
1524
1548
|
}
|
|
1525
1549
|
);
|
|
@@ -1818,58 +1842,106 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
1818
1842
|
}
|
|
1819
1843
|
|
|
1820
1844
|
// src/SectionHeader.tsx
|
|
1821
|
-
import { useState as useState6 } from "react";
|
|
1822
1845
|
import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
|
|
1823
|
-
import {
|
|
1824
|
-
|
|
1825
|
-
|
|
1846
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
1847
|
+
import { Fragment as Fragment5, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1848
|
+
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, actions, showActions = "hover", render, className }) {
|
|
1849
|
+
const titleElement = useRender({
|
|
1850
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx41("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx41("span", {})),
|
|
1851
|
+
props: {
|
|
1852
|
+
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
1853
|
+
// whole row up to the actions is the hit target, as it was when the
|
|
1854
|
+
// row itself carried the click.
|
|
1855
|
+
className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
|
|
1856
|
+
children: /* @__PURE__ */ jsxs28(Fragment5, { children: [
|
|
1857
|
+
chevron && /* @__PURE__ */ jsx41(
|
|
1858
|
+
IconChevronRight2,
|
|
1859
|
+
{
|
|
1860
|
+
size: 12,
|
|
1861
|
+
stroke: 1.5,
|
|
1862
|
+
className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
/* @__PURE__ */ jsx41(SectionLabel, { children: title })
|
|
1866
|
+
] })
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1826
1869
|
return /* @__PURE__ */ jsxs28(
|
|
1827
1870
|
"div",
|
|
1828
1871
|
{
|
|
1829
1872
|
className: cn(
|
|
1830
|
-
"flex h-[32px] items-center
|
|
1831
|
-
|
|
1832
|
-
|
|
1873
|
+
"group flex h-[32px] items-center gap-1 rounded-lg px-2 transition-colors",
|
|
1874
|
+
// The fill says "this does something": a row with a toggle or actions
|
|
1875
|
+
// lights up, a fixed heading over rows does not (2026-09-09, the
|
|
1876
|
+
// Sidebar's fixed group).
|
|
1877
|
+
(chevron || actions && actions.length > 0) && "hover:bg-bg-hover",
|
|
1833
1878
|
className
|
|
1834
1879
|
),
|
|
1835
|
-
onClick: chevron ? onToggle : void 0,
|
|
1836
|
-
onMouseEnter: () => setIsHovered(true),
|
|
1837
|
-
onMouseLeave: () => setIsHovered(false),
|
|
1838
1880
|
children: [
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
{
|
|
1843
|
-
size: 12,
|
|
1844
|
-
stroke: 1.5,
|
|
1845
|
-
className: cn("text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
1846
|
-
}
|
|
1847
|
-
),
|
|
1848
|
-
/* @__PURE__ */ jsx41(SectionLabel, { children: title })
|
|
1849
|
-
] }),
|
|
1850
|
-
(showActions === "always" || isHovered) && actions && actions.length > 0 && /* @__PURE__ */ jsx41("div", { className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ jsx41(
|
|
1851
|
-
IconButton,
|
|
1881
|
+
titleElement,
|
|
1882
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx41(
|
|
1883
|
+
"div",
|
|
1852
1884
|
{
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
},
|
|
1861
|
-
action.tooltip
|
|
1862
|
-
)) })
|
|
1885
|
+
className: cn(
|
|
1886
|
+
"-mr-1 flex shrink-0 items-center gap-1",
|
|
1887
|
+
showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
|
|
1888
|
+
),
|
|
1889
|
+
children: actions.map((action) => /* @__PURE__ */ jsx41(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
|
|
1890
|
+
}
|
|
1891
|
+
)
|
|
1863
1892
|
]
|
|
1864
1893
|
}
|
|
1865
1894
|
);
|
|
1866
1895
|
}
|
|
1867
1896
|
|
|
1897
|
+
// src/CollapsibleSection.tsx
|
|
1898
|
+
import { useState as useState6 } from "react";
|
|
1899
|
+
import { Collapsible } from "@base-ui/react/collapsible";
|
|
1900
|
+
import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1901
|
+
var OPEN = "open";
|
|
1902
|
+
var CLOSED = "closed";
|
|
1903
|
+
function readStored(key) {
|
|
1904
|
+
if (!key) return void 0;
|
|
1905
|
+
try {
|
|
1906
|
+
const value = window.localStorage.getItem(key);
|
|
1907
|
+
return value === OPEN ? true : value === CLOSED ? false : void 0;
|
|
1908
|
+
} catch {
|
|
1909
|
+
return void 0;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
function writeStored(key, open) {
|
|
1913
|
+
if (!key) return;
|
|
1914
|
+
try {
|
|
1915
|
+
window.localStorage.setItem(key, open ? OPEN : CLOSED);
|
|
1916
|
+
} catch {
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, actions, showActions, children, className, contentClassName }) {
|
|
1920
|
+
const [openState, setOpenState] = useState6(() => readStored(storageKey) ?? defaultOpen);
|
|
1921
|
+
const open = openProp ?? openState;
|
|
1922
|
+
const setOpen = (next) => {
|
|
1923
|
+
setOpenState(next);
|
|
1924
|
+
writeStored(storageKey, next);
|
|
1925
|
+
onOpenChange?.(next);
|
|
1926
|
+
};
|
|
1927
|
+
return /* @__PURE__ */ jsxs29(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
1928
|
+
/* @__PURE__ */ jsx42(SectionHeader, { title, chevron: true, isExpanded: open, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx42(Collapsible.Trigger, {}) }),
|
|
1929
|
+
/* @__PURE__ */ jsx42(
|
|
1930
|
+
Collapsible.Panel,
|
|
1931
|
+
{
|
|
1932
|
+
hiddenUntilFound: true,
|
|
1933
|
+
className: "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0",
|
|
1934
|
+
children: /* @__PURE__ */ jsx42("div", { className: cn("flex flex-col", contentClassName), children })
|
|
1935
|
+
}
|
|
1936
|
+
)
|
|
1937
|
+
] });
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1868
1940
|
// src/Tabs.tsx
|
|
1869
1941
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
1870
|
-
import { jsx as
|
|
1942
|
+
import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
1871
1943
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
1872
|
-
return /* @__PURE__ */
|
|
1944
|
+
return /* @__PURE__ */ jsx43(
|
|
1873
1945
|
BaseTabs.Root,
|
|
1874
1946
|
{
|
|
1875
1947
|
value: active,
|
|
@@ -1877,14 +1949,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
1877
1949
|
if (details.reason === "none") onChange(value);
|
|
1878
1950
|
},
|
|
1879
1951
|
className,
|
|
1880
|
-
children: /* @__PURE__ */
|
|
1952
|
+
children: /* @__PURE__ */ jsx43(
|
|
1881
1953
|
BaseTabs.List,
|
|
1882
1954
|
{
|
|
1883
1955
|
activateOnFocus: true,
|
|
1884
1956
|
"aria-label": aria["aria-label"],
|
|
1885
1957
|
"aria-labelledby": aria["aria-labelledby"],
|
|
1886
1958
|
className: "flex items-center gap-2",
|
|
1887
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
1959
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs30(
|
|
1888
1960
|
BaseTabs.Tab,
|
|
1889
1961
|
{
|
|
1890
1962
|
value: tab.id,
|
|
@@ -1897,9 +1969,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
1897
1969
|
),
|
|
1898
1970
|
children: [
|
|
1899
1971
|
tab.icon,
|
|
1900
|
-
/* @__PURE__ */
|
|
1972
|
+
/* @__PURE__ */ jsxs30("span", { className: "flex items-baseline", children: [
|
|
1901
1973
|
tab.label,
|
|
1902
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
1974
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx43("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
1903
1975
|
] })
|
|
1904
1976
|
]
|
|
1905
1977
|
},
|
|
@@ -1915,7 +1987,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
1915
1987
|
import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useEffect as useEffect3, useMemo as useMemo3, useState as useState7 } from "react";
|
|
1916
1988
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1917
1989
|
import { IconCircleCheck } from "@tabler/icons-react";
|
|
1918
|
-
import { jsx as
|
|
1990
|
+
import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1919
1991
|
var SURFACE_STYLES = {
|
|
1920
1992
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
|
|
1921
1993
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
|
|
@@ -1933,7 +2005,7 @@ var ACTION_BORDER_STYLES = {
|
|
|
1933
2005
|
};
|
|
1934
2006
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
1935
2007
|
const hasAction = !!(actionLabel && onAction);
|
|
1936
|
-
return /* @__PURE__ */
|
|
2008
|
+
return /* @__PURE__ */ jsxs31(
|
|
1937
2009
|
"div",
|
|
1938
2010
|
{
|
|
1939
2011
|
className: cn(
|
|
@@ -1945,11 +2017,11 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
|
|
|
1945
2017
|
className
|
|
1946
2018
|
),
|
|
1947
2019
|
children: [
|
|
1948
|
-
/* @__PURE__ */
|
|
1949
|
-
leadingIcon && /* @__PURE__ */
|
|
1950
|
-
/* @__PURE__ */
|
|
2020
|
+
/* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2021
|
+
leadingIcon && /* @__PURE__ */ jsx44(IconCircleCheck, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
|
|
2022
|
+
/* @__PURE__ */ jsx44("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
|
|
1951
2023
|
] }),
|
|
1952
|
-
hasAction && /* @__PURE__ */
|
|
2024
|
+
hasAction && /* @__PURE__ */ jsx44(
|
|
1953
2025
|
"button",
|
|
1954
2026
|
{
|
|
1955
2027
|
type: "button",
|
|
@@ -1959,7 +2031,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
|
|
|
1959
2031
|
ACTION_BORDER_STYLES[type],
|
|
1960
2032
|
type === "neutral" ? "hover:border-border-strong" : "hover:opacity-80"
|
|
1961
2033
|
),
|
|
1962
|
-
children: /* @__PURE__ */
|
|
2034
|
+
children: /* @__PURE__ */ jsx44("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
|
|
1963
2035
|
}
|
|
1964
2036
|
)
|
|
1965
2037
|
]
|
|
@@ -1986,10 +2058,10 @@ function ToastProvider({ children }) {
|
|
|
1986
2058
|
return () => clearTimeout(timer);
|
|
1987
2059
|
}, [toast]);
|
|
1988
2060
|
const value = useMemo3(() => ({ showToast, dismissToast }), [showToast, dismissToast]);
|
|
1989
|
-
return /* @__PURE__ */
|
|
2061
|
+
return /* @__PURE__ */ jsxs31(ToastContext.Provider, { value, children: [
|
|
1990
2062
|
children,
|
|
1991
2063
|
toast && createPortal2(
|
|
1992
|
-
/* @__PURE__ */
|
|
2064
|
+
/* @__PURE__ */ jsx44("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx44(
|
|
1993
2065
|
Toast,
|
|
1994
2066
|
{
|
|
1995
2067
|
className: "pointer-events-auto",
|
|
@@ -2022,6 +2094,7 @@ export {
|
|
|
2022
2094
|
Checkbox,
|
|
2023
2095
|
Chip,
|
|
2024
2096
|
ChipInput,
|
|
2097
|
+
CollapsibleSection,
|
|
2025
2098
|
ConfirmDialog,
|
|
2026
2099
|
DialogShell,
|
|
2027
2100
|
Divider,
|