@estiva-app/ui 0.18.0 → 0.20.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/README.md +13 -5
- package/dist/AttachmentCard.d.ts.map +1 -1
- package/dist/Breadcrumb.d.ts.map +1 -1
- package/dist/Button.d.ts +6 -1
- package/dist/Button.d.ts.map +1 -1
- package/dist/Card.d.ts +6 -1
- package/dist/Card.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +16 -1
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/DialogShell.d.ts.map +1 -1
- package/dist/Divider.d.ts +7 -0
- package/dist/Divider.d.ts.map +1 -1
- package/dist/IconButton.d.ts +12 -2
- package/dist/IconButton.d.ts.map +1 -1
- package/dist/IdentityMenu.d.ts.map +1 -1
- package/dist/Link.d.ts +6 -1
- package/dist/Link.d.ts.map +1 -1
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Popover.d.ts.map +1 -1
- package/dist/ReactionPicker.d.ts.map +1 -1
- package/dist/ScrollArea.d.ts +6 -0
- package/dist/ScrollArea.d.ts.map +1 -1
- package/dist/SectionLabel.d.ts +6 -1
- package/dist/SectionLabel.d.ts.map +1 -1
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/eslint/index.d.ts +4 -0
- package/dist/eslint/index.d.ts.map +1 -1
- package/dist/eslint/index.js +968 -3
- package/dist/eslint/index.js.map +4 -4
- package/dist/eslint/no-rebuilt-behaviour.d.ts +88 -0
- package/dist/eslint/no-rebuilt-behaviour.d.ts.map +1 -0
- package/dist/eslint/no-restyled-part.d.ts +81 -0
- package/dist/eslint/no-restyled-part.d.ts.map +1 -0
- package/dist/index.js +300 -268
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/AttachmentCard.tsx +7 -2
- package/src/Banner.tsx +2 -2
- package/src/Breadcrumb.tsx +9 -4
- package/src/Button.mdx +7 -0
- package/src/Button.stories.tsx +4 -1
- package/src/Button.tsx +10 -2
- package/src/Card.mdx +7 -0
- package/src/Card.stories.tsx +11 -0
- package/src/Card.tsx +8 -0
- package/src/Checkbox.mdx +20 -1
- package/src/Checkbox.stories.tsx +44 -0
- package/src/Checkbox.test.tsx +63 -0
- package/src/Checkbox.tsx +30 -1
- package/src/CommandPalette.tsx +1 -1
- package/src/ConfirmDialog.tsx +2 -2
- package/src/DialogShell.tsx +6 -7
- package/src/Divider.mdx +3 -0
- package/src/Divider.tsx +12 -2
- package/src/EditableText.mdx +5 -0
- package/src/IconButton.mdx +9 -0
- package/src/IconButton.stories.tsx +10 -1
- package/src/IconButton.tsx +22 -3
- package/src/IdentityMenu.tsx +4 -1
- package/src/Link.mdx +6 -0
- package/src/Link.stories.tsx +12 -0
- package/src/Link.tsx +7 -2
- package/src/Menu.stories.tsx +1 -1
- package/src/Menu.test.tsx +2 -2
- package/src/Menu.tsx +6 -3
- package/src/Person.stories.tsx +5 -5
- package/src/Popover.test.tsx +2 -2
- package/src/Popover.tsx +3 -2
- package/src/PreviewCard.tsx +1 -1
- package/src/Property.stories.tsx +2 -2
- package/src/ReactionPicker.tsx +6 -3
- package/src/ScrollArea.stories.tsx +38 -6
- package/src/ScrollArea.tsx +7 -1
- package/src/SectionLabel.mdx +3 -2
- package/src/SectionLabel.stories.tsx +3 -0
- package/src/SectionLabel.tsx +7 -2
- package/src/Tooltip.tsx +12 -14
- package/src/eslint/index.test.ts +58 -9
- package/src/eslint/index.ts +19 -3
- package/src/eslint/no-rebuilt-behaviour.test.ts +276 -0
- package/src/eslint/no-rebuilt-behaviour.ts +593 -0
- package/src/eslint/no-restyled-part.test.ts +301 -0
- package/src/eslint/no-restyled-part.ts +647 -0
- package/stories/Choosing.mdx +1 -1
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ function cn(...inputs) {
|
|
|
38
38
|
// src/ScrollArea.tsx
|
|
39
39
|
import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
|
|
40
40
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
41
|
-
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 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
42
|
var THUMB = "rounded-full bg-border-strong";
|
|
43
43
|
function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, viewportRef, onScroll, children }) {
|
|
44
44
|
const vertical = orientation !== "horizontal";
|
|
@@ -163,13 +163,13 @@ var VARIANT_CLASSES = {
|
|
|
163
163
|
underlined: "underline underline-offset-2 hover:text-text-primary",
|
|
164
164
|
plain: ""
|
|
165
165
|
};
|
|
166
|
-
function Link({ href, variant = "text", external = false, className, children, ...props }) {
|
|
166
|
+
function Link({ href, variant = "text", external = false, truncate = false, className, children, ...props }) {
|
|
167
167
|
return /* @__PURE__ */ jsx4(
|
|
168
168
|
"a",
|
|
169
169
|
{
|
|
170
170
|
href,
|
|
171
171
|
...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
172
|
-
className: cn(VARIANT_CLASSES[variant], className),
|
|
172
|
+
className: cn(VARIANT_CLASSES[variant], truncate && "truncate", className),
|
|
173
173
|
...props,
|
|
174
174
|
children
|
|
175
175
|
}
|
|
@@ -210,6 +210,7 @@ function Card({
|
|
|
210
210
|
active = false,
|
|
211
211
|
attention,
|
|
212
212
|
unreadable = false,
|
|
213
|
+
clip = false,
|
|
213
214
|
className,
|
|
214
215
|
children,
|
|
215
216
|
...props
|
|
@@ -231,12 +232,16 @@ function Card({
|
|
|
231
232
|
active && "bg-bg-selected border-accent-primary",
|
|
232
233
|
!active && attention && ATTENTION_CLASSES[attention],
|
|
233
234
|
unreadable && "border-dashed",
|
|
235
|
+
clip && "overflow-hidden",
|
|
234
236
|
href && "block",
|
|
235
237
|
className
|
|
236
238
|
);
|
|
237
239
|
if (href !== void 0) {
|
|
238
240
|
const { ref, ...anchorProps } = props;
|
|
239
|
-
return
|
|
241
|
+
return (
|
|
242
|
+
// @estiva-escape: 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
|
|
243
|
+
/* @__PURE__ */ jsx5(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
|
|
244
|
+
);
|
|
240
245
|
}
|
|
241
246
|
return /* @__PURE__ */ jsx5("div", { className: classes, ...props, children });
|
|
242
247
|
}
|
|
@@ -298,19 +303,13 @@ function TooltipSurface({ label, shortcut, placement }) {
|
|
|
298
303
|
children: /* @__PURE__ */ jsx7(
|
|
299
304
|
BaseTooltip.Popup,
|
|
300
305
|
{
|
|
301
|
-
render: /* @__PURE__ */ jsx7(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
"data-[ending-style]:duration-[80ms] data-[instant]:duration-0",
|
|
309
|
-
"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0",
|
|
310
|
-
"data-[side=top]:data-[starting-style]:translate-y-[4px] data-[side=top]:data-[ending-style]:translate-y-[4px]",
|
|
311
|
-
"data-[side=bottom]:data-[starting-style]:-translate-y-[4px] data-[side=bottom]:data-[ending-style]:-translate-y-[4px]"
|
|
312
|
-
)
|
|
313
|
-
}
|
|
306
|
+
render: /* @__PURE__ */ jsx7(Tooltip, { label, shortcut }),
|
|
307
|
+
className: cn(
|
|
308
|
+
"transition-[opacity,transform] duration-[120ms] ease-out motion-reduce:transition-none",
|
|
309
|
+
"data-[ending-style]:duration-[80ms] data-[instant]:duration-0",
|
|
310
|
+
"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0",
|
|
311
|
+
"data-[side=top]:data-[starting-style]:translate-y-[4px] data-[side=top]:data-[ending-style]:translate-y-[4px]",
|
|
312
|
+
"data-[side=bottom]:data-[starting-style]:-translate-y-[4px] data-[side=bottom]:data-[ending-style]:-translate-y-[4px]"
|
|
314
313
|
)
|
|
315
314
|
}
|
|
316
315
|
)
|
|
@@ -334,6 +333,8 @@ function TooltipTrigger({ label, shortcut, placement = "top", children }) {
|
|
|
334
333
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
335
334
|
function IconButton({
|
|
336
335
|
variant = "muted",
|
|
336
|
+
pressed,
|
|
337
|
+
glow = false,
|
|
337
338
|
className,
|
|
338
339
|
children,
|
|
339
340
|
disabled,
|
|
@@ -365,11 +366,17 @@ function IconButton({
|
|
|
365
366
|
// stretched and carries no `self-center` — see the note there.
|
|
366
367
|
"flex items-center justify-center p-1 rounded-lg transition-colors shrink-0 self-center cursor-pointer",
|
|
367
368
|
!state.disabled && variant === "primary" && "bg-accent-primary hover:bg-accent-hover text-text-inverse",
|
|
368
|
-
!state.disabled && variant === "muted" && "text-text-secondary hover:bg-bg-hover hover:text-text-primary",
|
|
369
|
+
!state.disabled && (variant === "muted" || variant === "resolve") && "text-text-secondary hover:bg-bg-hover hover:text-text-primary",
|
|
369
370
|
!state.disabled && variant === "outlined" && "border border-border-default hover:bg-bg-hover text-text-secondary",
|
|
371
|
+
!state.disabled && variant === "current" && "hover:bg-bg-hover",
|
|
370
372
|
state.disabled && variant === "primary" && "bg-bg-disabled text-text-disabled",
|
|
371
|
-
state.disabled && variant === "muted" && "text-text-disabled",
|
|
373
|
+
state.disabled && (variant === "muted" || variant === "resolve") && "text-text-disabled",
|
|
372
374
|
state.disabled && variant === "outlined" && "border border-border-default text-text-disabled",
|
|
375
|
+
// Always, disabled too: the colour of where it sits, and Resolve's green.
|
|
376
|
+
variant === "current" && "text-current",
|
|
377
|
+
variant === "resolve" && "signal:hover:bg-success-muted signal:hover:text-success-default",
|
|
378
|
+
pressed && "bg-bg-active text-text-primary",
|
|
379
|
+
glow && "signal:shadow-glow-accent",
|
|
373
380
|
// `pointer-events-none` only where the button is truly out of reach:
|
|
374
381
|
// with a `disabledReason` the button IS the tooltip's trigger, and a
|
|
375
382
|
// trigger the pointer cannot land on never opens one. Base UI already
|
|
@@ -378,6 +385,7 @@ function IconButton({
|
|
|
378
385
|
state.disabled && "cursor-not-allowed",
|
|
379
386
|
className
|
|
380
387
|
),
|
|
388
|
+
"aria-pressed": pressed,
|
|
381
389
|
...props,
|
|
382
390
|
children
|
|
383
391
|
}
|
|
@@ -471,75 +479,85 @@ function AttachmentCard({
|
|
|
471
479
|
if (pending) {
|
|
472
480
|
const failed = state === "failed";
|
|
473
481
|
const warning = state === "warning";
|
|
474
|
-
return
|
|
475
|
-
Card,
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
/* @__PURE__ */ jsx9(
|
|
484
|
-
/* @__PURE__ */
|
|
485
|
-
Truncating,
|
|
482
|
+
return (
|
|
483
|
+
// @estiva-escape: a failed or warning file's strong hairline is AttachmentCard's own state; Card's attention hairlines are the soft ones (UIG-9, Katerina 17 September)
|
|
484
|
+
/* @__PURE__ */ jsxs5(
|
|
485
|
+
Card,
|
|
486
|
+
{
|
|
487
|
+
fill: "elevated",
|
|
488
|
+
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),
|
|
489
|
+
...props,
|
|
490
|
+
children: [
|
|
491
|
+
/* @__PURE__ */ jsx9("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx9(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx9(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx9(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx9("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx9("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
|
|
492
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
|
|
493
|
+
/* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME_CLASSES }),
|
|
494
|
+
/* @__PURE__ */ jsx9(
|
|
495
|
+
Truncating,
|
|
496
|
+
{
|
|
497
|
+
text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
|
|
498
|
+
hint: noteHint,
|
|
499
|
+
className: cn(NOTE_CLASSES, failed ? "text-error-default" : warning ? "text-warning-default" : "text-text-secondary")
|
|
500
|
+
}
|
|
501
|
+
)
|
|
502
|
+
] }),
|
|
503
|
+
onRemove && /* @__PURE__ */ jsx9(
|
|
504
|
+
BaseButton2,
|
|
486
505
|
{
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
className:
|
|
506
|
+
type: "button",
|
|
507
|
+
"aria-label": `Remove ${name}`,
|
|
508
|
+
className: "absolute -top-1.5 -right-1.5 size-5 rounded-full bg-bg-elevated border border-border-strong flex items-center justify-center text-text-secondary hover:text-text-primary opacity-0 group-hover:opacity-100 transition-opacity",
|
|
509
|
+
onClick: (event) => {
|
|
510
|
+
event.stopPropagation();
|
|
511
|
+
onRemove();
|
|
512
|
+
},
|
|
513
|
+
children: /* @__PURE__ */ jsx9(IconX, { size: 11, stroke: 1.75 })
|
|
490
514
|
}
|
|
491
515
|
)
|
|
492
|
-
]
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
{
|
|
496
|
-
type: "button",
|
|
497
|
-
"aria-label": `Remove ${name}`,
|
|
498
|
-
className: "absolute -top-1.5 -right-1.5 size-5 rounded-full bg-bg-elevated border border-border-strong flex items-center justify-center text-text-secondary hover:text-text-primary opacity-0 group-hover:opacity-100 transition-opacity",
|
|
499
|
-
onClick: (event) => {
|
|
500
|
-
event.stopPropagation();
|
|
501
|
-
onRemove();
|
|
502
|
-
},
|
|
503
|
-
children: /* @__PURE__ */ jsx9(IconX, { size: 11, stroke: 1.75 })
|
|
504
|
-
}
|
|
505
|
-
)
|
|
506
|
-
]
|
|
507
|
-
}
|
|
516
|
+
]
|
|
517
|
+
}
|
|
518
|
+
)
|
|
508
519
|
);
|
|
509
520
|
}
|
|
510
|
-
const download = onDownload ?
|
|
511
|
-
IconButton,
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
521
|
+
const download = onDownload ? (
|
|
522
|
+
// @estiva-escape: 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)
|
|
523
|
+
/* @__PURE__ */ jsx9(
|
|
524
|
+
IconButton,
|
|
525
|
+
{
|
|
526
|
+
variant: "muted",
|
|
527
|
+
tooltip: "Download",
|
|
528
|
+
"aria-label": `Download ${name}`,
|
|
529
|
+
className: "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity",
|
|
530
|
+
onClick: (event) => {
|
|
531
|
+
event.stopPropagation();
|
|
532
|
+
onDownload();
|
|
533
|
+
},
|
|
534
|
+
children: /* @__PURE__ */ jsx9(IconDownload, { size: 16, stroke: 1.5 })
|
|
535
|
+
}
|
|
536
|
+
)
|
|
523
537
|
) : null;
|
|
524
538
|
if (state === "loading") {
|
|
525
539
|
return (
|
|
526
540
|
// `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
|
|
527
541
|
// status says what it is doing — loading — to a reader that cannot see the pulse.
|
|
542
|
+
// @estiva-escape: the loading pulse is AttachmentCard's own state; Card has no loading state (UIG-9, Katerina 17 September)
|
|
528
543
|
/* @__PURE__ */ jsx9(Card, { role: "status", fill: "inset", "aria-busy": "true", "aria-label": `Loading ${name}`, className: cn("w-[180px] h-28 animate-pulse", className), ...props, children: null })
|
|
529
544
|
);
|
|
530
545
|
}
|
|
531
546
|
if (state === "unreadable") {
|
|
532
|
-
return
|
|
533
|
-
|
|
534
|
-
/* @__PURE__ */ jsxs5("
|
|
535
|
-
/* @__PURE__ */ jsx9(
|
|
536
|
-
/* @__PURE__ */
|
|
547
|
+
return (
|
|
548
|
+
// @estiva-escape: 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)
|
|
549
|
+
/* @__PURE__ */ jsxs5(Card, { fill: "inset", unreadable: true, className: cn("flex items-center gap-2 w-[240px] p-1.5 opacity-70", className), ...props, children: [
|
|
550
|
+
/* @__PURE__ */ jsx9("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx9(TypeIcon, { name }) }),
|
|
551
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
|
|
552
|
+
/* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME_CLASSES }),
|
|
553
|
+
/* @__PURE__ */ jsx9("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
|
|
554
|
+
] })
|
|
537
555
|
] })
|
|
538
|
-
|
|
556
|
+
);
|
|
539
557
|
}
|
|
540
558
|
if (image && src) {
|
|
541
559
|
const picture = /* @__PURE__ */ jsx9("img", { src, alt: name, className: "w-full h-28 object-cover" });
|
|
542
|
-
return /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: "hairline", className: cn("group relative flex flex-col w-[180px]
|
|
560
|
+
return /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: "hairline", clip: true, className: cn("group relative flex flex-col w-[180px]", className), ...props, children: [
|
|
543
561
|
onOpen ? /* @__PURE__ */ jsx9(
|
|
544
562
|
BaseButton2,
|
|
545
563
|
{
|
|
@@ -566,10 +584,13 @@ function AttachmentCard({
|
|
|
566
584
|
/* @__PURE__ */ jsx9("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
|
|
567
585
|
] })
|
|
568
586
|
] });
|
|
569
|
-
return
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
587
|
+
return (
|
|
588
|
+
// @estiva-escape: a file that cannot be opened is faded, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
|
|
589
|
+
/* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: href ? "hairline" : "none", className: cn("group flex items-center gap-2 w-[240px] p-1.5 pr-1", !href && "opacity-70", className), ...props, children: [
|
|
590
|
+
href ? /* @__PURE__ */ jsx9(Link, { href, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
|
|
591
|
+
download
|
|
592
|
+
] })
|
|
593
|
+
);
|
|
573
594
|
}
|
|
574
595
|
|
|
575
596
|
// src/Avatar.tsx
|
|
@@ -671,7 +692,7 @@ function Banner({ tone, children, onDismiss, dismissLabel = "Dismiss", className
|
|
|
671
692
|
}
|
|
672
693
|
return /* @__PURE__ */ jsxs7("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
|
|
673
694
|
/* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1", children }),
|
|
674
|
-
/* @__PURE__ */ jsx12(IconButton, { "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0
|
|
695
|
+
/* @__PURE__ */ jsx12(IconButton, { variant: "current", "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0", children: /* @__PURE__ */ jsx12(IconX2, { size: 16, stroke: 1.5 }) })
|
|
675
696
|
] });
|
|
676
697
|
}
|
|
677
698
|
|
|
@@ -715,7 +736,7 @@ function Button({
|
|
|
715
736
|
// Extra right padding beside a leading icon, for optical balance.
|
|
716
737
|
size === "default" && (hasLeadingIcon ? "pl-2 pr-3" : "px-2"),
|
|
717
738
|
size === "small" && (hasLeadingIcon ? "pl-1.5 pr-2" : "px-1.5"),
|
|
718
|
-
!state.disabled && variant === "primary" && "bg-accent-primary hover:bg-accent-hover text-text-inverse cursor-pointer signal:font-semibold",
|
|
739
|
+
!state.disabled && (variant === "primary" || variant === "resolve") && "bg-accent-primary hover:bg-accent-hover text-text-inverse cursor-pointer signal:font-semibold",
|
|
719
740
|
!state.disabled && variant === "outlined" && "border border-border-default hover:bg-bg-hover text-text-primary cursor-pointer",
|
|
720
741
|
!state.disabled && variant === "muted" && "hover:bg-bg-hover text-text-primary cursor-pointer",
|
|
721
742
|
!state.disabled && variant === "destructive" && "hover:bg-error-muted text-error-default cursor-pointer",
|
|
@@ -727,6 +748,8 @@ function Button({
|
|
|
727
748
|
// and a prevented `onClick`), so nothing else needs it.
|
|
728
749
|
state.disabled && !disabledReason && "pointer-events-none",
|
|
729
750
|
state.disabled && variant === "outlined" && "border border-border-default",
|
|
751
|
+
// Disabled too, as it always drew.
|
|
752
|
+
variant === "resolve" && "signal:bg-transparent signal:border signal:border-border-default signal:text-text-primary signal:shadow-none signal:hover:bg-success-muted signal:hover:border-success-outline signal:hover:text-success-default signal:transition-colors",
|
|
730
753
|
className
|
|
731
754
|
),
|
|
732
755
|
...props,
|
|
@@ -755,7 +778,8 @@ function squareClasses(checked, disabled, interactive, className) {
|
|
|
755
778
|
}
|
|
756
779
|
var tickClasses = (checked) => cn("flex", !checked && "invisible");
|
|
757
780
|
var WORDS_CLASSES = "text-body-2 text-text-primary";
|
|
758
|
-
|
|
781
|
+
var ROW_CLASSES = "flex shrink-0 items-center gap-3 h-10 px-3 rounded-lg transition-colors";
|
|
782
|
+
function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row, leading, className, ...aria }) {
|
|
759
783
|
const formBusy = useFormBusy();
|
|
760
784
|
const disabled = ownDisabled || formBusy;
|
|
761
785
|
if (!onChange) {
|
|
@@ -780,6 +804,13 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, cla
|
|
|
780
804
|
}
|
|
781
805
|
);
|
|
782
806
|
if (label === void 0) return box;
|
|
807
|
+
if (row) {
|
|
808
|
+
return /* @__PURE__ */ jsx14(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs9(BaseField.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
|
|
809
|
+
leading,
|
|
810
|
+
/* @__PURE__ */ jsx14("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
|
|
811
|
+
box
|
|
812
|
+
] }) });
|
|
813
|
+
}
|
|
783
814
|
return /* @__PURE__ */ jsx14(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs9(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
|
|
784
815
|
box,
|
|
785
816
|
/* @__PURE__ */ jsx14("span", { className: WORDS_CLASSES, children: label })
|
|
@@ -814,8 +845,8 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
|
|
|
814
845
|
|
|
815
846
|
// src/CommandPalette.tsx
|
|
816
847
|
import {
|
|
817
|
-
createContext as
|
|
818
|
-
useContext as
|
|
848
|
+
createContext as createContext4,
|
|
849
|
+
useContext as useContext4,
|
|
819
850
|
useEffect,
|
|
820
851
|
useLayoutEffect as useLayoutEffect3,
|
|
821
852
|
useMemo as useMemo2,
|
|
@@ -833,10 +864,42 @@ import { Combobox } from "@base-ui/react/combobox";
|
|
|
833
864
|
import { IconX as IconX3 } from "@tabler/icons-react";
|
|
834
865
|
|
|
835
866
|
// src/Menu.tsx
|
|
836
|
-
import { createContext as
|
|
867
|
+
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
837
868
|
import { IconChevronRight } from "@tabler/icons-react";
|
|
838
869
|
import { Menu as BaseMenu } from "@base-ui/react/menu";
|
|
839
870
|
|
|
871
|
+
// src/Divider.tsx
|
|
872
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
873
|
+
import { Separator } from "@base-ui/react/separator";
|
|
874
|
+
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
875
|
+
var DividerInPanel = createContext2(false);
|
|
876
|
+
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
877
|
+
const inset = useContext2(DividerInPanel) ? "mx-0" : "mx-3";
|
|
878
|
+
if (label && orientation === "horizontal") {
|
|
879
|
+
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
880
|
+
return /* @__PURE__ */ jsxs11(
|
|
881
|
+
Separator,
|
|
882
|
+
{
|
|
883
|
+
orientation: "horizontal",
|
|
884
|
+
"aria-label": label,
|
|
885
|
+
className: cn("flex shrink-0 items-center gap-2", inset, className),
|
|
886
|
+
children: [
|
|
887
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
888
|
+
/* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
889
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
890
|
+
]
|
|
891
|
+
}
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
return /* @__PURE__ */ jsx16(
|
|
895
|
+
Separator,
|
|
896
|
+
{
|
|
897
|
+
orientation,
|
|
898
|
+
className: cn("shrink-0 bg-border-subtle", orientation === "horizontal" ? cn("h-px", inset) : "w-px self-stretch", className)
|
|
899
|
+
}
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
|
|
840
903
|
// src/triggerDisabled.ts
|
|
841
904
|
function triggerDisabled(trigger) {
|
|
842
905
|
const props = trigger.props;
|
|
@@ -844,13 +907,14 @@ function triggerDisabled(trigger) {
|
|
|
844
907
|
}
|
|
845
908
|
|
|
846
909
|
// src/SectionLabel.tsx
|
|
847
|
-
import { jsx as
|
|
848
|
-
function SectionLabel({ children, className }) {
|
|
849
|
-
return /* @__PURE__ */
|
|
910
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
911
|
+
function SectionLabel({ children, tone = "primary", className }) {
|
|
912
|
+
return /* @__PURE__ */ jsx17(
|
|
850
913
|
"span",
|
|
851
914
|
{
|
|
852
915
|
className: cn(
|
|
853
|
-
"text-h5 leading-3
|
|
916
|
+
"text-h5 leading-3 signal:font-mono signal:text-small signal:uppercase signal:tracking-widest",
|
|
917
|
+
tone === "secondary" ? "text-text-secondary" : "text-text-primary",
|
|
854
918
|
className
|
|
855
919
|
),
|
|
856
920
|
children
|
|
@@ -859,10 +923,10 @@ function SectionLabel({ children, className }) {
|
|
|
859
923
|
}
|
|
860
924
|
|
|
861
925
|
// src/Menu.tsx
|
|
862
|
-
import { Fragment as Fragment2, jsx as
|
|
863
|
-
var MenuContext =
|
|
926
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
927
|
+
var MenuContext = createContext3(null);
|
|
864
928
|
function MenuPanel({ children, className, ...props }) {
|
|
865
|
-
return /* @__PURE__ */
|
|
929
|
+
return /* @__PURE__ */ jsx18(
|
|
866
930
|
"div",
|
|
867
931
|
{
|
|
868
932
|
className: cn(
|
|
@@ -892,7 +956,7 @@ var VIEWPORT_PAD2 = 8;
|
|
|
892
956
|
var HOVER_OPEN_DELAY = 0;
|
|
893
957
|
var HOVER_CLOSE_DELAY = 150;
|
|
894
958
|
function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className, contentClassName }) {
|
|
895
|
-
return /* @__PURE__ */
|
|
959
|
+
return /* @__PURE__ */ jsxs12(
|
|
896
960
|
BaseMenu.Root,
|
|
897
961
|
{
|
|
898
962
|
open,
|
|
@@ -900,7 +964,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
900
964
|
actionsRef,
|
|
901
965
|
modal: false,
|
|
902
966
|
children: [
|
|
903
|
-
/* @__PURE__ */
|
|
967
|
+
/* @__PURE__ */ jsx18(
|
|
904
968
|
BaseMenu.Trigger,
|
|
905
969
|
{
|
|
906
970
|
render: trigger,
|
|
@@ -910,7 +974,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
910
974
|
closeDelay: HOVER_CLOSE_DELAY
|
|
911
975
|
}
|
|
912
976
|
),
|
|
913
|
-
/* @__PURE__ */
|
|
977
|
+
/* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
|
|
914
978
|
BaseMenu.Positioner,
|
|
915
979
|
{
|
|
916
980
|
side: "bottom",
|
|
@@ -918,13 +982,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
918
982
|
sideOffset: GAP2,
|
|
919
983
|
collisionPadding: VIEWPORT_PAD2,
|
|
920
984
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
921
|
-
children: /* @__PURE__ */
|
|
985
|
+
children: /* @__PURE__ */ jsx18(
|
|
922
986
|
BaseMenu.Popup,
|
|
923
987
|
{
|
|
924
988
|
"data-interactive": true,
|
|
925
989
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
926
|
-
render: /* @__PURE__ */
|
|
927
|
-
children: /* @__PURE__ */
|
|
990
|
+
render: /* @__PURE__ */ jsx18(MenuPanel, {}),
|
|
991
|
+
children: /* @__PURE__ */ jsx18(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col p-2", contentClassName), children: /* @__PURE__ */ jsx18(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx18(DividerInPanel.Provider, { value: true, children }) }) })
|
|
928
992
|
}
|
|
929
993
|
)
|
|
930
994
|
}
|
|
@@ -934,26 +998,26 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
934
998
|
);
|
|
935
999
|
}
|
|
936
1000
|
function MenuSub({ label, leading, selected, children, className }) {
|
|
937
|
-
const menu =
|
|
1001
|
+
const menu = useContext3(MenuContext);
|
|
938
1002
|
if (!isProduction() && menu?.openOnHover) {
|
|
939
1003
|
console.error(
|
|
940
1004
|
'[@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".'
|
|
941
1005
|
);
|
|
942
1006
|
}
|
|
943
|
-
return /* @__PURE__ */
|
|
944
|
-
/* @__PURE__ */
|
|
1007
|
+
return /* @__PURE__ */ jsxs12(BaseMenu.SubmenuRoot, { children: [
|
|
1008
|
+
/* @__PURE__ */ jsx18(
|
|
945
1009
|
BaseMenu.SubmenuTrigger,
|
|
946
1010
|
{
|
|
947
1011
|
openOnHover: true,
|
|
948
1012
|
delay: 0,
|
|
949
1013
|
closeDelay: 150,
|
|
950
1014
|
nativeButton: true,
|
|
951
|
-
render: /* @__PURE__ */
|
|
1015
|
+
render: /* @__PURE__ */ jsx18("button", { type: "button" }),
|
|
952
1016
|
className: menuItemClassName({ size: "default", selected }),
|
|
953
|
-
children: /* @__PURE__ */
|
|
1017
|
+
children: /* @__PURE__ */ jsx18(MenuItemBody, { label, leading, submenu: true })
|
|
954
1018
|
}
|
|
955
1019
|
),
|
|
956
|
-
/* @__PURE__ */
|
|
1020
|
+
/* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
|
|
957
1021
|
BaseMenu.Positioner,
|
|
958
1022
|
{
|
|
959
1023
|
side: "inline-end",
|
|
@@ -961,7 +1025,7 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
961
1025
|
sideOffset: GAP2,
|
|
962
1026
|
collisionPadding: VIEWPORT_PAD2,
|
|
963
1027
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
964
|
-
children: /* @__PURE__ */
|
|
1028
|
+
children: /* @__PURE__ */ jsx18(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx18(MenuPanel, {}), children })
|
|
965
1029
|
}
|
|
966
1030
|
) })
|
|
967
1031
|
] });
|
|
@@ -996,25 +1060,25 @@ function menuItemClassName({ size, selected, className }) {
|
|
|
996
1060
|
);
|
|
997
1061
|
}
|
|
998
1062
|
function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
|
|
999
|
-
const edge = trailing ?? (shortcut ? /* @__PURE__ */
|
|
1000
|
-
return /* @__PURE__ */
|
|
1001
|
-
leading && /* @__PURE__ */
|
|
1002
|
-
children ?? /* @__PURE__ */
|
|
1003
|
-
/* @__PURE__ */
|
|
1004
|
-
description && /* @__PURE__ */
|
|
1063
|
+
const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx18(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx18(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
|
|
1064
|
+
return /* @__PURE__ */ jsxs12(Fragment2, { children: [
|
|
1065
|
+
leading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1066
|
+
children ?? /* @__PURE__ */ jsxs12("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
|
|
1067
|
+
/* @__PURE__ */ jsx18("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
|
|
1068
|
+
description && /* @__PURE__ */ jsx18("span", { className: "truncate text-caption text-text-secondary", children: description })
|
|
1005
1069
|
] }),
|
|
1006
1070
|
(edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
|
|
1007
1071
|
// the wider of the two and never changes, so revealing the hint moves
|
|
1008
1072
|
// nothing. No transition here either — the hint switches on the same
|
|
1009
1073
|
// :hover / `selected` as the fill, in the same frame.
|
|
1010
|
-
/* @__PURE__ */
|
|
1011
|
-
edge && /* @__PURE__ */
|
|
1012
|
-
hint && /* @__PURE__ */
|
|
1074
|
+
/* @__PURE__ */ jsxs12("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
|
|
1075
|
+
edge && /* @__PURE__ */ jsx18("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
|
|
1076
|
+
hint && /* @__PURE__ */ jsx18("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
|
|
1013
1077
|
] })
|
|
1014
1078
|
] });
|
|
1015
1079
|
}
|
|
1016
1080
|
function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
|
|
1017
|
-
const body = /* @__PURE__ */
|
|
1081
|
+
const body = /* @__PURE__ */ jsx18(
|
|
1018
1082
|
MenuItemBody,
|
|
1019
1083
|
{
|
|
1020
1084
|
label,
|
|
@@ -1031,14 +1095,14 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1031
1095
|
}
|
|
1032
1096
|
);
|
|
1033
1097
|
const rowClassName = menuItemClassName({ size, selected, className });
|
|
1034
|
-
if (!
|
|
1035
|
-
return /* @__PURE__ */
|
|
1098
|
+
if (!useContext3(MenuContext)) {
|
|
1099
|
+
return /* @__PURE__ */ jsx18("button", { type: "button", className: rowClassName, ...props, children: body });
|
|
1036
1100
|
}
|
|
1037
|
-
return /* @__PURE__ */
|
|
1101
|
+
return /* @__PURE__ */ jsx18(
|
|
1038
1102
|
BaseMenu.Item,
|
|
1039
1103
|
{
|
|
1040
1104
|
nativeButton: true,
|
|
1041
|
-
render: /* @__PURE__ */
|
|
1105
|
+
render: /* @__PURE__ */ jsx18("button", { type: "button" }),
|
|
1042
1106
|
className: rowClassName,
|
|
1043
1107
|
...props,
|
|
1044
1108
|
children: body
|
|
@@ -1046,31 +1110,31 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1046
1110
|
);
|
|
1047
1111
|
}
|
|
1048
1112
|
function EnterHint({ target }) {
|
|
1049
|
-
return /* @__PURE__ */
|
|
1050
|
-
/* @__PURE__ */
|
|
1051
|
-
target && /* @__PURE__ */
|
|
1113
|
+
return /* @__PURE__ */ jsxs12("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
|
|
1114
|
+
/* @__PURE__ */ jsx18(Kbd, { children: "\u21A9 Enter" }),
|
|
1115
|
+
target && /* @__PURE__ */ jsx18("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider", children: target })
|
|
1052
1116
|
] });
|
|
1053
1117
|
}
|
|
1054
1118
|
function MenuSection({ label, children, className }) {
|
|
1055
|
-
const inMenu =
|
|
1056
|
-
const heading = /* @__PURE__ */
|
|
1119
|
+
const inMenu = useContext3(MenuContext) !== null;
|
|
1120
|
+
const heading = /* @__PURE__ */ jsx18("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx18(SectionLabel, { tone: "secondary", children: label }) });
|
|
1057
1121
|
if (!inMenu) {
|
|
1058
|
-
return /* @__PURE__ */
|
|
1122
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col", children: [
|
|
1059
1123
|
heading,
|
|
1060
1124
|
children
|
|
1061
1125
|
] });
|
|
1062
1126
|
}
|
|
1063
|
-
return /* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1127
|
+
return /* @__PURE__ */ jsxs12(BaseMenu.Group, { className: "flex flex-col", children: [
|
|
1128
|
+
/* @__PURE__ */ jsx18(BaseMenu.GroupLabel, { render: heading }),
|
|
1065
1129
|
children
|
|
1066
1130
|
] });
|
|
1067
1131
|
}
|
|
1068
1132
|
function MenuRow({ children, className }) {
|
|
1069
|
-
return /* @__PURE__ */
|
|
1133
|
+
return /* @__PURE__ */ jsx18("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
|
|
1070
1134
|
}
|
|
1071
1135
|
|
|
1072
1136
|
// src/ChipInput.tsx
|
|
1073
|
-
import { jsx as
|
|
1137
|
+
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1074
1138
|
var CHIP_BOX = (
|
|
1075
1139
|
// Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
|
|
1076
1140
|
// rounded-sm corners — never a forced circle — and the chip's corner
|
|
@@ -1081,10 +1145,10 @@ var CHIP_LABEL = "text-caption font-medium text-text-primary";
|
|
|
1081
1145
|
var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary";
|
|
1082
1146
|
var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
|
|
1083
1147
|
function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
|
|
1084
|
-
return /* @__PURE__ */
|
|
1085
|
-
leading && /* @__PURE__ */
|
|
1086
|
-
/* @__PURE__ */
|
|
1087
|
-
onRemove && /* @__PURE__ */
|
|
1148
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
|
|
1149
|
+
leading && /* @__PURE__ */ jsx19("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1150
|
+
/* @__PURE__ */ jsx19("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
|
|
1151
|
+
onRemove && /* @__PURE__ */ jsx19(
|
|
1088
1152
|
BaseButton4,
|
|
1089
1153
|
{
|
|
1090
1154
|
type: "button",
|
|
@@ -1094,7 +1158,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
|
|
|
1094
1158
|
},
|
|
1095
1159
|
className: cn(CHIP_REMOVE, truncate && "shrink-0"),
|
|
1096
1160
|
"aria-label": removeLabel ?? `Remove ${label}`,
|
|
1097
|
-
children: /* @__PURE__ */
|
|
1161
|
+
children: /* @__PURE__ */ jsx19(IconX3, { size: 10, stroke: 1.5 })
|
|
1098
1162
|
}
|
|
1099
1163
|
)
|
|
1100
1164
|
] });
|
|
@@ -1147,7 +1211,7 @@ function ChipInput({
|
|
|
1147
1211
|
setQuery("");
|
|
1148
1212
|
}
|
|
1149
1213
|
}
|
|
1150
|
-
return /* @__PURE__ */
|
|
1214
|
+
return /* @__PURE__ */ jsxs13(
|
|
1151
1215
|
Combobox.Root,
|
|
1152
1216
|
{
|
|
1153
1217
|
multiple: true,
|
|
@@ -1164,13 +1228,13 @@ function ChipInput({
|
|
|
1164
1228
|
filter,
|
|
1165
1229
|
itemToStringLabel: (option) => option.label,
|
|
1166
1230
|
children: [
|
|
1167
|
-
/* @__PURE__ */
|
|
1168
|
-
value.map((option) => /* @__PURE__ */
|
|
1169
|
-
chipLeading && /* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1231
|
+
/* @__PURE__ */ jsxs13(Combobox.Chips, { ref: setBox, className: "bg-bg-inset border border-border-default hover:border-border-strong focus-within:border-border-focus focus-within:hover:border-border-focus rounded-lg px-3 py-1.5 flex flex-wrap items-center gap-1.5 transition-colors min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring", children: [
|
|
1232
|
+
value.map((option) => /* @__PURE__ */ jsxs13(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
|
|
1233
|
+
chipLeading && /* @__PURE__ */ jsx19("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
|
|
1234
|
+
/* @__PURE__ */ jsx19("span", { className: CHIP_LABEL, children: option.label }),
|
|
1235
|
+
/* @__PURE__ */ jsx19(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx19(IconX3, { size: 10, stroke: 1.5 }) })
|
|
1172
1236
|
] }, option.id)),
|
|
1173
|
-
/* @__PURE__ */
|
|
1237
|
+
/* @__PURE__ */ jsx19(
|
|
1174
1238
|
Combobox.Input,
|
|
1175
1239
|
{
|
|
1176
1240
|
autoFocus,
|
|
@@ -1182,18 +1246,18 @@ function ChipInput({
|
|
|
1182
1246
|
}
|
|
1183
1247
|
)
|
|
1184
1248
|
] }),
|
|
1185
|
-
/* @__PURE__ */
|
|
1249
|
+
/* @__PURE__ */ jsx19(Combobox.Portal, { children: /* @__PURE__ */ jsx19(
|
|
1186
1250
|
Combobox.Positioner,
|
|
1187
1251
|
{
|
|
1188
1252
|
anchor: box,
|
|
1189
1253
|
sideOffset: GAP3,
|
|
1190
1254
|
collisionPadding: VIEWPORT_PAD3,
|
|
1191
1255
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1192
|
-
children: /* @__PURE__ */
|
|
1256
|
+
children: /* @__PURE__ */ jsx19(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx19(MenuPanel, {}), children: /* @__PURE__ */ jsx19(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx19(Combobox.List, { children: (option) => /* @__PURE__ */ jsx19(
|
|
1193
1257
|
Combobox.Item,
|
|
1194
1258
|
{
|
|
1195
1259
|
value: option,
|
|
1196
|
-
render: /* @__PURE__ */
|
|
1260
|
+
render: /* @__PURE__ */ jsx19(
|
|
1197
1261
|
MenuItem,
|
|
1198
1262
|
{
|
|
1199
1263
|
size: "tall",
|
|
@@ -1216,21 +1280,21 @@ var VIEWPORT_PAD3 = 8;
|
|
|
1216
1280
|
|
|
1217
1281
|
// src/EmptyState.tsx
|
|
1218
1282
|
import { IconMessage2 } from "@tabler/icons-react";
|
|
1219
|
-
import { jsx as
|
|
1283
|
+
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1220
1284
|
function EmptyState({ icon, message, scope = "page", className }) {
|
|
1221
1285
|
if (scope === "section") {
|
|
1222
|
-
return /* @__PURE__ */
|
|
1286
|
+
return /* @__PURE__ */ jsx20("p", { className: cn("text-caption text-text-muted", className), children: message });
|
|
1223
1287
|
}
|
|
1224
|
-
return /* @__PURE__ */
|
|
1225
|
-
/* @__PURE__ */
|
|
1226
|
-
/* @__PURE__ */
|
|
1288
|
+
return /* @__PURE__ */ jsxs14("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1289
|
+
/* @__PURE__ */ jsx20("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx20(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1290
|
+
/* @__PURE__ */ jsx20("p", { className: "text-body-2 text-text-secondary text-center", children: message })
|
|
1227
1291
|
] });
|
|
1228
1292
|
}
|
|
1229
1293
|
|
|
1230
1294
|
// src/Field.tsx
|
|
1231
1295
|
import { cloneElement, isValidElement } from "react";
|
|
1232
1296
|
import { Field as BaseField2 } from "@base-ui/react/field";
|
|
1233
|
-
import { jsx as
|
|
1297
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1234
1298
|
var LINE_STYLES = {
|
|
1235
1299
|
helper: "text-caption text-text-muted",
|
|
1236
1300
|
warning: "text-caption text-warning-default",
|
|
@@ -1240,26 +1304,26 @@ function Field({ label, required = false, helper, error, children }) {
|
|
|
1240
1304
|
const control = required && isValidElement(children) ? cloneElement(children, {
|
|
1241
1305
|
"aria-required": children.props["aria-required"] ?? true
|
|
1242
1306
|
}) : children;
|
|
1243
|
-
return /* @__PURE__ */
|
|
1244
|
-
/* @__PURE__ */
|
|
1307
|
+
return /* @__PURE__ */ jsxs15(BaseField2.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
|
|
1308
|
+
/* @__PURE__ */ jsxs15(BaseField2.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1245
1309
|
label,
|
|
1246
|
-
required && /* @__PURE__ */
|
|
1310
|
+
required && /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1247
1311
|
] }),
|
|
1248
|
-
/* @__PURE__ */
|
|
1312
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-1.5", children: [
|
|
1249
1313
|
control,
|
|
1250
|
-
error != null ? /* @__PURE__ */
|
|
1314
|
+
error != null ? /* @__PURE__ */ jsx21(BaseField2.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx21(BaseField2.Description, { className: LINE_STYLES.helper, children: helper }) : null
|
|
1251
1315
|
] })
|
|
1252
1316
|
] });
|
|
1253
1317
|
}
|
|
1254
1318
|
function FieldLine({ tone = "helper", children, className }) {
|
|
1255
|
-
return /* @__PURE__ */
|
|
1319
|
+
return /* @__PURE__ */ jsx21("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
|
|
1256
1320
|
}
|
|
1257
1321
|
|
|
1258
1322
|
// src/Form.tsx
|
|
1259
1323
|
import { useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
|
|
1260
1324
|
import { Fieldset } from "@base-ui/react/fieldset";
|
|
1261
1325
|
import { Form as BaseForm } from "@base-ui/react/form";
|
|
1262
|
-
import { jsx as
|
|
1326
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1263
1327
|
var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
|
|
1264
1328
|
var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1265
1329
|
function usable(element) {
|
|
@@ -1318,7 +1382,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
|
|
|
1318
1382
|
const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
|
|
1319
1383
|
if (enterSends && oneLine) form.current?.requestSubmit();
|
|
1320
1384
|
};
|
|
1321
|
-
return /* @__PURE__ */
|
|
1385
|
+
return /* @__PURE__ */ jsx22(
|
|
1322
1386
|
BaseForm,
|
|
1323
1387
|
{
|
|
1324
1388
|
ref: form,
|
|
@@ -1340,32 +1404,32 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
|
|
|
1340
1404
|
if (busyNow.current) return;
|
|
1341
1405
|
void onSubmit();
|
|
1342
1406
|
},
|
|
1343
|
-
children: /* @__PURE__ */
|
|
1407
|
+
children: /* @__PURE__ */ jsx22(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx22(FormBusyContext.Provider, { value: busy, children }) })
|
|
1344
1408
|
}
|
|
1345
1409
|
);
|
|
1346
1410
|
}
|
|
1347
1411
|
|
|
1348
1412
|
// src/Skeleton.tsx
|
|
1349
|
-
import { jsx as
|
|
1413
|
+
import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1350
1414
|
function SkeletonBar({ className, style }) {
|
|
1351
|
-
return /* @__PURE__ */
|
|
1415
|
+
return /* @__PURE__ */ jsx23("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1352
1416
|
}
|
|
1353
1417
|
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1354
1418
|
function SkeletonRow({ barWidth = 130 }) {
|
|
1355
|
-
return /* @__PURE__ */
|
|
1356
|
-
/* @__PURE__ */
|
|
1357
|
-
/* @__PURE__ */
|
|
1419
|
+
return /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1420
|
+
/* @__PURE__ */ jsx23(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1421
|
+
/* @__PURE__ */ jsx23(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1358
1422
|
] });
|
|
1359
1423
|
}
|
|
1360
1424
|
function SkeletonList({ rows = 8, className }) {
|
|
1361
|
-
return /* @__PURE__ */
|
|
1425
|
+
return /* @__PURE__ */ jsx23("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx23(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
|
|
1362
1426
|
}
|
|
1363
1427
|
|
|
1364
1428
|
// src/CommandPalette.tsx
|
|
1365
|
-
import { Fragment as Fragment3, jsx as
|
|
1366
|
-
var PaletteContext =
|
|
1429
|
+
import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1430
|
+
var PaletteContext = createContext4(null);
|
|
1367
1431
|
function usePalette(part) {
|
|
1368
|
-
const palette =
|
|
1432
|
+
const palette = useContext4(PaletteContext);
|
|
1369
1433
|
if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
|
|
1370
1434
|
return palette;
|
|
1371
1435
|
}
|
|
@@ -1388,9 +1452,9 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1388
1452
|
return () => cancelAnimationFrame(frame);
|
|
1389
1453
|
});
|
|
1390
1454
|
const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
|
|
1391
|
-
return /* @__PURE__ */
|
|
1392
|
-
/* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1455
|
+
return /* @__PURE__ */ jsx24(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs17(Dialog.Portal, { children: [
|
|
1456
|
+
/* @__PURE__ */ jsx24(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1457
|
+
/* @__PURE__ */ jsx24(Dialog.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx24(
|
|
1394
1458
|
Dialog.Popup,
|
|
1395
1459
|
{
|
|
1396
1460
|
ref: popupRef,
|
|
@@ -1400,13 +1464,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1400
1464
|
if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
|
|
1401
1465
|
},
|
|
1402
1466
|
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",
|
|
1403
|
-
children: /* @__PURE__ */
|
|
1467
|
+
children: /* @__PURE__ */ jsx24(PaletteContext.Provider, { value: context, children })
|
|
1404
1468
|
}
|
|
1405
1469
|
) })
|
|
1406
1470
|
] }) });
|
|
1407
1471
|
}
|
|
1408
1472
|
function LevelChip({ chip, onBack }) {
|
|
1409
|
-
return /* @__PURE__ */
|
|
1473
|
+
return /* @__PURE__ */ jsx24(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
|
|
1410
1474
|
}
|
|
1411
1475
|
function useBack(chip, popupRef) {
|
|
1412
1476
|
return () => {
|
|
@@ -1417,10 +1481,10 @@ function useBack(chip, popupRef) {
|
|
|
1417
1481
|
}
|
|
1418
1482
|
function Footer({ keys }) {
|
|
1419
1483
|
const { where } = usePalette("The footer");
|
|
1420
|
-
return /* @__PURE__ */
|
|
1421
|
-
/* @__PURE__ */
|
|
1422
|
-
keys.map(([key, word]) => /* @__PURE__ */
|
|
1423
|
-
/* @__PURE__ */
|
|
1484
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex h-9 shrink-0 items-center gap-4 border-t border-border-subtle px-5 text-caption text-text-secondary signal:font-mono signal:text-small signal:text-text-muted", children: [
|
|
1485
|
+
/* @__PURE__ */ jsx24("span", { className: "min-w-0 flex-1 truncate", children: where }),
|
|
1486
|
+
keys.map(([key, word]) => /* @__PURE__ */ jsxs17("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
1487
|
+
/* @__PURE__ */ jsx24(Kbd, { children: key }),
|
|
1424
1488
|
" ",
|
|
1425
1489
|
word
|
|
1426
1490
|
] }, key))
|
|
@@ -1497,7 +1561,7 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1497
1561
|
...chip && query === "" ? [["Backspace", "back"]] : [],
|
|
1498
1562
|
["Esc", "close"]
|
|
1499
1563
|
];
|
|
1500
|
-
return /* @__PURE__ */
|
|
1564
|
+
return /* @__PURE__ */ jsxs17(
|
|
1501
1565
|
Autocomplete.Root,
|
|
1502
1566
|
{
|
|
1503
1567
|
items,
|
|
@@ -1520,10 +1584,10 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1520
1584
|
setLitId(id);
|
|
1521
1585
|
},
|
|
1522
1586
|
children: [
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
chip && /* @__PURE__ */
|
|
1526
|
-
/* @__PURE__ */
|
|
1587
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1588
|
+
/* @__PURE__ */ jsx24(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
|
|
1589
|
+
chip && /* @__PURE__ */ jsx24(LevelChip, { chip, onBack: back }),
|
|
1590
|
+
/* @__PURE__ */ jsx24(
|
|
1527
1591
|
Autocomplete.Input,
|
|
1528
1592
|
{
|
|
1529
1593
|
ref: inputRef,
|
|
@@ -1535,43 +1599,43 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1535
1599
|
}
|
|
1536
1600
|
)
|
|
1537
1601
|
] }),
|
|
1538
|
-
/* @__PURE__ */
|
|
1539
|
-
children != null && /* @__PURE__ */
|
|
1540
|
-
/* @__PURE__ */
|
|
1541
|
-
/* @__PURE__ */
|
|
1542
|
-
/* @__PURE__ */
|
|
1602
|
+
/* @__PURE__ */ jsxs17(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
|
|
1603
|
+
children != null && /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
|
|
1604
|
+
/* @__PURE__ */ jsx24(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs17(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
|
|
1605
|
+
/* @__PURE__ */ jsx24(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx24(SectionLabel, { tone: "secondary", children: group.value }) }),
|
|
1606
|
+
/* @__PURE__ */ jsx24(Autocomplete.Collection, { children: (row) => (
|
|
1543
1607
|
/* The menu row, as the list's own option — the way Select
|
|
1544
1608
|
puts it on `Select.Item`. One row, two parts. */
|
|
1545
|
-
/* @__PURE__ */
|
|
1609
|
+
/* @__PURE__ */ jsx24(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx24(
|
|
1546
1610
|
MenuItemBody,
|
|
1547
1611
|
{
|
|
1548
1612
|
size: "tall",
|
|
1549
1613
|
label: row.label,
|
|
1550
1614
|
description: row.description,
|
|
1551
|
-
leading: /* @__PURE__ */
|
|
1615
|
+
leading: /* @__PURE__ */ jsx24(RowLeading, { row }),
|
|
1552
1616
|
submenu: !!row.onGoIn,
|
|
1553
|
-
hint: row.onGoIn ? /* @__PURE__ */
|
|
1617
|
+
hint: row.onGoIn ? /* @__PURE__ */ jsx24(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx24(EnterHint, {})
|
|
1554
1618
|
}
|
|
1555
1619
|
) }, row.id)
|
|
1556
1620
|
) })
|
|
1557
1621
|
] }, group.value) }),
|
|
1558
|
-
/* @__PURE__ */
|
|
1559
|
-
/* @__PURE__ */
|
|
1560
|
-
/* @__PURE__ */
|
|
1622
|
+
/* @__PURE__ */ jsx24(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs17(Fragment3, { children: [
|
|
1623
|
+
/* @__PURE__ */ jsx24(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
|
|
1624
|
+
/* @__PURE__ */ jsx24("span", { className: "text-caption text-text-muted", children: pending })
|
|
1561
1625
|
] }) }),
|
|
1562
|
-
notes.map((note) => /* @__PURE__ */
|
|
1563
|
-
/* @__PURE__ */
|
|
1626
|
+
notes.map((note) => /* @__PURE__ */ jsx24("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx24(FieldLine, { children: note }) }, note)),
|
|
1627
|
+
/* @__PURE__ */ jsx24(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx24(EmptyState, { scope: "section", message: empty }) })
|
|
1564
1628
|
] }),
|
|
1565
|
-
/* @__PURE__ */
|
|
1629
|
+
/* @__PURE__ */ jsx24(Footer, { keys })
|
|
1566
1630
|
]
|
|
1567
1631
|
}
|
|
1568
1632
|
);
|
|
1569
1633
|
}
|
|
1570
1634
|
function RowLeading({ row }) {
|
|
1571
1635
|
if (row.icon != null) {
|
|
1572
|
-
return /* @__PURE__ */
|
|
1636
|
+
return /* @__PURE__ */ jsx24("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
|
|
1573
1637
|
}
|
|
1574
|
-
return /* @__PURE__ */
|
|
1638
|
+
return /* @__PURE__ */ jsx24("span", { className: "flex size-8 items-center justify-center", children: row.leading });
|
|
1575
1639
|
}
|
|
1576
1640
|
var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1577
1641
|
function isTextField(el) {
|
|
@@ -1613,56 +1677,56 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
|
|
|
1613
1677
|
...backNamed ? [["Backspace", "back"]] : [],
|
|
1614
1678
|
["Esc", "close"]
|
|
1615
1679
|
];
|
|
1616
|
-
return /* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
1618
|
-
icon != null && /* @__PURE__ */
|
|
1619
|
-
/* @__PURE__ */
|
|
1680
|
+
return /* @__PURE__ */ jsxs17("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
|
|
1681
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1682
|
+
icon != null && /* @__PURE__ */ jsx24("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
|
|
1683
|
+
/* @__PURE__ */ jsx24(LevelChip, { chip, onBack: back })
|
|
1620
1684
|
] }),
|
|
1621
|
-
/* @__PURE__ */
|
|
1622
|
-
/* @__PURE__ */
|
|
1623
|
-
/* @__PURE__ */
|
|
1624
|
-
/* @__PURE__ */
|
|
1625
|
-
/* @__PURE__ */
|
|
1685
|
+
/* @__PURE__ */ jsxs17(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
|
|
1686
|
+
/* @__PURE__ */ jsx24(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-4", children }) }),
|
|
1687
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
|
|
1688
|
+
/* @__PURE__ */ jsx24("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx24(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx24(FieldLine, { tone: "error", children: error }) : null }),
|
|
1689
|
+
/* @__PURE__ */ jsx24(
|
|
1626
1690
|
Button,
|
|
1627
1691
|
{
|
|
1628
1692
|
type: "submit",
|
|
1629
1693
|
variant: "primary",
|
|
1630
1694
|
disabled: busy,
|
|
1631
1695
|
disabledReason: busy ? void 0 : submitWaits,
|
|
1632
|
-
leadingIcon: busy ? /* @__PURE__ */
|
|
1696
|
+
leadingIcon: busy ? /* @__PURE__ */ jsx24(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
|
|
1633
1697
|
children: working ? working.button : submitLabel
|
|
1634
1698
|
}
|
|
1635
1699
|
)
|
|
1636
1700
|
] })
|
|
1637
1701
|
] }),
|
|
1638
|
-
/* @__PURE__ */
|
|
1702
|
+
/* @__PURE__ */ jsx24(Footer, { keys })
|
|
1639
1703
|
] });
|
|
1640
1704
|
}
|
|
1641
1705
|
var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
|
|
1642
1706
|
function CommandPaletteWorking({ children, bars = 2 }) {
|
|
1643
|
-
return /* @__PURE__ */
|
|
1644
|
-
/* @__PURE__ */
|
|
1645
|
-
/* @__PURE__ */
|
|
1707
|
+
return /* @__PURE__ */ jsxs17("div", { role: "status", className: "flex flex-col gap-2", children: [
|
|
1708
|
+
/* @__PURE__ */ jsxs17("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
|
|
1709
|
+
/* @__PURE__ */ jsx24(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
|
|
1646
1710
|
children
|
|
1647
1711
|
] }),
|
|
1648
|
-
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */
|
|
1712
|
+
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx24(SkeletonBar, { className: cn("h-3", width) }, width))
|
|
1649
1713
|
] });
|
|
1650
1714
|
}
|
|
1651
1715
|
function CommandPaletteAnswer({ children, note }) {
|
|
1652
1716
|
const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
|
|
1653
|
-
return /* @__PURE__ */
|
|
1654
|
-
paragraphs.map((paragraph, i) => /* @__PURE__ */
|
|
1655
|
-
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */
|
|
1717
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-2", children: [
|
|
1718
|
+
paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx24("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
|
|
1719
|
+
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx24("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
|
|
1656
1720
|
) }, i)),
|
|
1657
|
-
note && /* @__PURE__ */
|
|
1721
|
+
note && /* @__PURE__ */ jsx24(FieldLine, { children: note })
|
|
1658
1722
|
] });
|
|
1659
1723
|
}
|
|
1660
1724
|
function CommandPaletteQuote({ children }) {
|
|
1661
|
-
return /* @__PURE__ */
|
|
1725
|
+
return /* @__PURE__ */ jsx24("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
|
|
1662
1726
|
}
|
|
1663
1727
|
|
|
1664
1728
|
// src/InlineChip.tsx
|
|
1665
|
-
import { Fragment as Fragment4, jsx as
|
|
1729
|
+
import { Fragment as Fragment4, jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1666
1730
|
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";
|
|
1667
1731
|
var INLINE_CHIP_TONE_CLASSES = {
|
|
1668
1732
|
/** A thing or a place — anything that is not a person. */
|
|
@@ -1684,49 +1748,20 @@ function inlineChipClassName(tone, className) {
|
|
|
1684
1748
|
return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
|
|
1685
1749
|
}
|
|
1686
1750
|
function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
|
|
1687
|
-
const body = /* @__PURE__ */
|
|
1688
|
-
icon && /* @__PURE__ */
|
|
1751
|
+
const body = /* @__PURE__ */ jsxs18(Fragment4, { children: [
|
|
1752
|
+
icon && /* @__PURE__ */ jsx25("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
|
|
1689
1753
|
children
|
|
1690
1754
|
] });
|
|
1691
1755
|
const classes = inlineChipClassName(tone, className);
|
|
1692
1756
|
if (href === void 0) {
|
|
1693
|
-
return /* @__PURE__ */
|
|
1757
|
+
return /* @__PURE__ */ jsx25("span", { className: classes, ...props, children: body });
|
|
1694
1758
|
}
|
|
1695
|
-
return /* @__PURE__ */
|
|
1759
|
+
return /* @__PURE__ */ jsx25("a", { href, className: classes, ...props, children: body });
|
|
1696
1760
|
}
|
|
1697
1761
|
|
|
1698
1762
|
// src/IdentityMenu.tsx
|
|
1699
1763
|
import { useCallback, useRef as useRef4 } from "react";
|
|
1700
1764
|
|
|
1701
|
-
// src/Divider.tsx
|
|
1702
|
-
import { Separator } from "@base-ui/react/separator";
|
|
1703
|
-
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1704
|
-
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
1705
|
-
if (label && orientation === "horizontal") {
|
|
1706
|
-
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
1707
|
-
return /* @__PURE__ */ jsxs18(
|
|
1708
|
-
Separator,
|
|
1709
|
-
{
|
|
1710
|
-
orientation: "horizontal",
|
|
1711
|
-
"aria-label": label,
|
|
1712
|
-
className: cn("flex shrink-0 items-center gap-2 mx-3", className),
|
|
1713
|
-
children: [
|
|
1714
|
-
/* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
1715
|
-
/* @__PURE__ */ jsx25("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
1716
|
-
/* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
1717
|
-
]
|
|
1718
|
-
}
|
|
1719
|
-
);
|
|
1720
|
-
}
|
|
1721
|
-
return /* @__PURE__ */ jsx25(
|
|
1722
|
-
Separator,
|
|
1723
|
-
{
|
|
1724
|
-
orientation,
|
|
1725
|
-
className: cn("shrink-0 bg-border-subtle", orientation === "horizontal" ? "h-px mx-3" : "w-px self-stretch", className)
|
|
1726
|
-
}
|
|
1727
|
-
);
|
|
1728
|
-
}
|
|
1729
|
-
|
|
1730
1765
|
// src/Person.tsx
|
|
1731
1766
|
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1732
1767
|
function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
@@ -1799,7 +1834,7 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
|
|
|
1799
1834
|
const appRows = typeof children === "function" ? children(onClose) : children;
|
|
1800
1835
|
return /* @__PURE__ */ jsxs21(Fragment5, { children: [
|
|
1801
1836
|
/* @__PURE__ */ jsxs21(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
|
|
1802
|
-
/* @__PURE__ */ jsx28(MenuRow, { children: /* @__PURE__ */ jsx28(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28
|
|
1837
|
+
/* @__PURE__ */ jsx28(MenuRow, { children: /* @__PURE__ */ jsx28("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx28(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
|
|
1803
1838
|
/* @__PURE__ */ jsx28(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." }),
|
|
1804
1839
|
me.email && /* @__PURE__ */ jsxs21(Note, { children: [
|
|
1805
1840
|
me.email,
|
|
@@ -2090,14 +2125,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2090
2125
|
}
|
|
2091
2126
|
)
|
|
2092
2127
|
] }),
|
|
2093
|
-
bodyMaxHeight ?
|
|
2094
|
-
ScrollArea
|
|
2095
|
-
{
|
|
2096
|
-
className: cn(footer != null && "border-b border-border-subtle"),
|
|
2097
|
-
viewportClassName: bodyMaxHeight,
|
|
2098
|
-
contentClassName: cn("pl-5 pr-4 py-4", bodyClassName),
|
|
2099
|
-
children
|
|
2100
|
-
}
|
|
2128
|
+
bodyMaxHeight ? (
|
|
2129
|
+
// The line above the footer on a box of the shell's own, not pushed into ScrollArea (UIG-9).
|
|
2130
|
+
/* @__PURE__ */ jsx33("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx33(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
|
|
2101
2131
|
) : /* @__PURE__ */ jsx33("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
|
|
2102
2132
|
footer != null && /* @__PURE__ */ jsx33("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
|
|
2103
2133
|
]
|
|
@@ -2127,12 +2157,11 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
2127
2157
|
alert: true,
|
|
2128
2158
|
title,
|
|
2129
2159
|
onClose,
|
|
2130
|
-
bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
|
|
2131
2160
|
footer: /* @__PURE__ */ jsxs24(Fragment6, { children: [
|
|
2132
2161
|
/* @__PURE__ */ jsx34(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
2133
2162
|
/* @__PURE__ */ jsx34(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
|
|
2134
2163
|
] }),
|
|
2135
|
-
children
|
|
2164
|
+
children: /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
|
|
2136
2165
|
}
|
|
2137
2166
|
);
|
|
2138
2167
|
}
|
|
@@ -2311,8 +2340,11 @@ function Breadcrumb({ items, className }) {
|
|
|
2311
2340
|
const crumb = item.href ? (
|
|
2312
2341
|
// `plain` adds no look of its own: a crumb keeps the trail's size and
|
|
2313
2342
|
// tone, and brightens on hover. The package's own Link, so a trail
|
|
2314
|
-
// follows whatever a link learns to do (UIG-5).
|
|
2315
|
-
|
|
2343
|
+
// follows whatever a link learns to do (UIG-5). The size and tone are
|
|
2344
|
+
// on a box around it, which the link takes them from, rather than
|
|
2345
|
+
// pushed into it (UIG-9); the link is still the one element that
|
|
2346
|
+
// truncates and is measured.
|
|
2347
|
+
/* @__PURE__ */ jsx37("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx37(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
|
|
2316
2348
|
) : /* @__PURE__ */ jsx37("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
2317
2349
|
return /* @__PURE__ */ jsxs25(Fragment7, { children: [
|
|
2318
2350
|
index > 0 && /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
@@ -2395,8 +2427,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2395
2427
|
ScrollArea,
|
|
2396
2428
|
{
|
|
2397
2429
|
viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
|
|
2398
|
-
contentClassName: cn("flex flex-col p-2
|
|
2399
|
-
children
|
|
2430
|
+
contentClassName: cn("flex flex-col p-2", contentClassName),
|
|
2431
|
+
children: /* @__PURE__ */ jsx39(DividerInPanel.Provider, { value: true, children })
|
|
2400
2432
|
}
|
|
2401
2433
|
)
|
|
2402
2434
|
}
|
|
@@ -2468,8 +2500,8 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2468
2500
|
"aria-label": option.label,
|
|
2469
2501
|
tooltip: option.label,
|
|
2470
2502
|
onClick: () => onSelect(option.emoji),
|
|
2471
|
-
className: "size-7
|
|
2472
|
-
children: /* @__PURE__ */ jsx41("span", { "aria-hidden": "true", children: option.emoji })
|
|
2503
|
+
className: "size-7",
|
|
2504
|
+
children: /* @__PURE__ */ jsx41("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
|
|
2473
2505
|
},
|
|
2474
2506
|
option.emoji
|
|
2475
2507
|
)
|
|
@@ -2507,7 +2539,7 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2507
2539
|
{
|
|
2508
2540
|
className: cn("w-[360px] p-3 outline-none", className),
|
|
2509
2541
|
render: /* @__PURE__ */ jsx42(MenuPanel, {}),
|
|
2510
|
-
children: /* @__PURE__ */ jsx42(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3
|
|
2542
|
+
children: /* @__PURE__ */ jsx42(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3", children: content })
|
|
2511
2543
|
}
|
|
2512
2544
|
)
|
|
2513
2545
|
}
|
|
@@ -2799,7 +2831,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2799
2831
|
}
|
|
2800
2832
|
|
|
2801
2833
|
// src/Toast.tsx
|
|
2802
|
-
import { createContext as
|
|
2834
|
+
import { createContext as createContext5, useContext as useContext5, useMemo as useMemo4 } from "react";
|
|
2803
2835
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
2804
2836
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
2805
2837
|
import { jsx as jsx52, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
@@ -2850,7 +2882,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
|
|
|
2850
2882
|
hasAction && /* @__PURE__ */ jsx52(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
2851
2883
|
] });
|
|
2852
2884
|
}
|
|
2853
|
-
var ToastContext =
|
|
2885
|
+
var ToastContext = createContext5(null);
|
|
2854
2886
|
var VISIBLE_TOASTS = 3;
|
|
2855
2887
|
function ToastProvider({ children }) {
|
|
2856
2888
|
const manager = useMemo4(() => BaseToast.createToastManager(), []);
|
|
@@ -2906,7 +2938,7 @@ function ToastList() {
|
|
|
2906
2938
|
});
|
|
2907
2939
|
}
|
|
2908
2940
|
function useToast() {
|
|
2909
|
-
const ctx =
|
|
2941
|
+
const ctx = useContext5(ToastContext);
|
|
2910
2942
|
if (!ctx) throw new Error("useToast must be used within ToastProvider");
|
|
2911
2943
|
return ctx;
|
|
2912
2944
|
}
|