@weichenlin/swell-ui 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { Check, ChevronDown, CircleAlert, CircleCheck, CircleDashed, CircleX, Copy, Eye, EyeOff, Info, LoaderCircle, Menu, Moon, Search, Sun, TriangleAlert, X } from "lucide-react";
1
+ import { ArrowDown, ArrowUp, ArrowUpDown, Check, ChevronDown, ChevronLeft, ChevronRight, CircleAlert, CircleCheck, CircleDashed, CircleX, Copy, Eye, EyeOff, Info, LoaderCircle, Menu, Moon, Search, Sun, TriangleAlert, X } from "lucide-react";
2
2
  import { clsx } from "clsx";
3
3
  import { extendTailwindMerge } from "tailwind-merge";
4
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
4
  import { cva } from "class-variance-authority";
6
5
  import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useId, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
7
6
  import { createPortal } from "react-dom";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  //#region src/lib/cn.ts
9
9
  const tone = (name) => [
10
10
  name,
@@ -45,6 +45,8 @@ const twMerge = extendTailwindMerge({ extend: { theme: {
45
45
  "input-halo-invalid-focus",
46
46
  "control-checked",
47
47
  "control-checked-fg",
48
+ "switch-handle",
49
+ "switch-handle-checked",
48
50
  "popover-bg",
49
51
  "popover-border",
50
52
  "popover-highlight",
@@ -57,15 +59,6 @@ const twMerge = extendTailwindMerge({ extend: { theme: {
57
59
  "neutral"
58
60
  ].flatMap(tone)
59
61
  ],
60
- radius: [
61
- "sharp",
62
- "sm",
63
- "md",
64
- "lg",
65
- "xl",
66
- "2xl",
67
- "3xl"
68
- ],
69
62
  shadow: [
70
63
  "input",
71
64
  "input-lift",
@@ -85,67 +78,6 @@ function cn(...inputs) {
85
78
  return twMerge(clsx(inputs));
86
79
  }
87
80
  //#endregion
88
- //#region src/components/badge/badge.tsx
89
- const toneClasses$1 = {
90
- neutral: {
91
- subtle: ["border-neutral-border bg-neutral-subtle-bg text-neutral-subtle-fg", "text-neutral"],
92
- outline: ["border-neutral-border bg-transparent text-neutral-subtle-fg", "text-neutral"],
93
- solid: ["border-neutral bg-neutral text-neutral-fg", "text-neutral-fg"]
94
- },
95
- info: {
96
- subtle: ["border-info-border bg-info-subtle-bg text-info-subtle-fg", "text-info"],
97
- outline: ["border-info-border bg-transparent text-info-subtle-fg", "text-info"],
98
- solid: ["border-info bg-info text-info-fg", "text-info-fg"]
99
- },
100
- success: {
101
- subtle: ["border-success-border bg-success-subtle-bg text-success-subtle-fg", "text-success"],
102
- outline: ["border-success-border bg-transparent text-success-subtle-fg", "text-success"],
103
- solid: ["border-success bg-success text-success-fg", "text-success-fg"]
104
- },
105
- warning: {
106
- subtle: ["border-warning-border bg-warning-subtle-bg text-warning-subtle-fg", "text-warning"],
107
- outline: ["border-warning-border bg-transparent text-warning-subtle-fg", "text-warning"],
108
- solid: ["border-warning bg-warning text-warning-fg", "text-warning-fg"]
109
- },
110
- danger: {
111
- subtle: ["border-danger-border bg-danger-subtle-bg text-danger-subtle-fg", "text-danger"],
112
- outline: ["border-danger-border bg-transparent text-danger-subtle-fg", "text-danger"],
113
- solid: ["border-danger bg-danger text-danger-fg", "text-danger-fg"]
114
- }
115
- };
116
- const sizeClasses$3 = {
117
- sm: {
118
- base: "h-5 px-1.5",
119
- withIcon: "ps-1"
120
- },
121
- md: {
122
- base: "h-6 px-2",
123
- withIcon: "ps-1.5"
124
- }
125
- };
126
- function Badge({ tone = "neutral", variant = "subtle", size = "md", icon, busy = false, context, className, children, ...props }) {
127
- const [toneClass, iconClass] = toneClasses$1[tone][variant];
128
- const hasIcon = busy || icon !== void 0 && icon !== null && icon !== false;
129
- return /* @__PURE__ */ jsxs("span", {
130
- ...props,
131
- "data-slot": "badge",
132
- className: cn("inline-flex items-center gap-1 rounded-sm border text-xs leading-none font-medium whitespace-nowrap", "forced-colors:border-[CanvasText]", sizeClasses$3[size].base, hasIcon && sizeClasses$3[size].withIcon, toneClass, className),
133
- children: [hasIcon && /* @__PURE__ */ jsx("span", {
134
- "aria-hidden": "true",
135
- "data-slot": "badge-icon",
136
- className: cn("inline-flex shrink-0 items-center [&_svg]:size-3 [&_svg]:shrink-0", iconClass),
137
- children: busy ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoaderCircle, { className: "animate-spin motion-reduce:hidden" }), /* @__PURE__ */ jsx(CircleDashed, { className: "hidden motion-reduce:block" })] }) : icon
138
- }), /* @__PURE__ */ jsxs("span", {
139
- "data-slot": "badge-label",
140
- className: "min-w-0 truncate leading-4",
141
- children: [context && /* @__PURE__ */ jsxs("span", {
142
- className: "sr-only",
143
- children: [context, ": "]
144
- }), children]
145
- })]
146
- });
147
- }
148
- //#endregion
149
81
  //#region src/hooks/use-press-feedback.ts
150
82
  const GROW_MS = 450;
151
83
  const FADE_MS = 300;
@@ -230,6 +162,61 @@ function usePressFeedback(ripple = true) {
230
162
  return ref;
231
163
  }
232
164
  //#endregion
165
+ //#region src/lib/slot.tsx
166
+ function setRef(ref, node) {
167
+ if (typeof ref === "function") return ref(node);
168
+ if (ref) ref.current = node;
169
+ }
170
+ function composeRefs(...refs) {
171
+ return (node) => {
172
+ const cleanups = refs.map((ref) => setRef(ref, node));
173
+ return () => {
174
+ for (const [i, ref] of refs.entries()) {
175
+ const cleanup = cleanups[i];
176
+ if (typeof cleanup === "function") cleanup();
177
+ else setRef(ref, null);
178
+ }
179
+ };
180
+ };
181
+ }
182
+ function mergeProps(slot, child) {
183
+ const merged = {
184
+ ...slot,
185
+ ...child
186
+ };
187
+ for (const key of Object.keys(slot)) {
188
+ const own = slot[key];
189
+ const theirs = child[key];
190
+ if (/^on[A-Z]/.test(key) && typeof own === "function" && typeof theirs === "function") merged[key] = (...args) => {
191
+ theirs(...args);
192
+ own(...args);
193
+ };
194
+ else if (key === "className") merged.className = cn(own, theirs);
195
+ else if (key === "style") merged.style = {
196
+ ...own,
197
+ ...theirs
198
+ };
199
+ }
200
+ return merged;
201
+ }
202
+ /** Applies `wrap` to an element's children, or to what a render-prop child returns. */
203
+ function wrapChildren(children, wrap) {
204
+ if (typeof children !== "function") return wrap(children);
205
+ return (...args) => wrap(children(...args));
206
+ }
207
+ /** Renders its only child with these props merged in (Radix Slot style). */
208
+ function Slot({ children, ref, ...props }) {
209
+ const child = Children.only(children);
210
+ const childProps = isValidElement(child) ? child.props : {};
211
+ const childRef = childProps.ref;
212
+ const composedRef = useMemo(() => composeRefs(ref, childRef), [ref, childRef]);
213
+ if (!isValidElement(child)) return null;
214
+ return cloneElement(child, {
215
+ ...mergeProps(props, childProps),
216
+ ref: composedRef
217
+ });
218
+ }
219
+ //#endregion
233
220
  //#region src/components/tooltip.tsx
234
221
  const OPEN_DELAY_MS = 300;
235
222
  const GAP_PX = 6;
@@ -374,7 +361,7 @@ function Tooltip({ content, side = "top", describe = true, className, children }
374
361
  }[placed]),
375
362
  children: /* @__PURE__ */ jsx("span", {
376
363
  ref: bubbleRef,
377
- className: cn("block w-max max-w-xs rounded-sm border border-border-strong bg-inverse px-2 py-1", "text-xs/snug font-medium text-inverse-fg shadow-whisper", "transition-[opacity,translate] duration-150 ease-out starting:opacity-0", {
364
+ className: cn("block w-max max-w-xs rounded-md border border-border-strong bg-inverse px-2 py-1", "text-xs/snug font-medium text-inverse-fg shadow-whisper", "transition-[opacity,translate] duration-150 ease-out starting:opacity-0", {
378
365
  top: "starting:translate-y-0.5",
379
366
  bottom: "starting:-translate-y-0.5",
380
367
  left: "starting:translate-x-0.5",
@@ -401,11 +388,11 @@ const buttonVariants = cva([
401
388
  ], {
402
389
  variants: {
403
390
  intent: {
404
- primary: "bg-primary text-primary-fg rounded-md shadow-[0_0_0_1px_var(--color-primary)] hover:not-aria-disabled:opacity-90",
405
- secondary: "bg-surface-muted text-fg-strong rounded-md shadow-[0_0_0_1px_var(--color-ring)] hover:not-aria-disabled:bg-ring",
406
- surface: "bg-surface-raised text-fg rounded-lg hover:not-aria-disabled:bg-surface-muted",
407
- dark: "bg-inverse text-inverse-fg rounded-md shadow-[0_0_0_1px_var(--color-ring)] hover:not-aria-disabled:opacity-90",
408
- ghost: "bg-transparent text-fg rounded-md hover:not-aria-disabled:bg-surface-muted"
391
+ primary: "bg-primary text-primary-fg rounded-lg shadow-[0_0_0_1px_var(--color-primary)] hover:not-aria-disabled:opacity-90",
392
+ secondary: "bg-surface-muted text-fg-strong rounded-lg shadow-[0_0_0_1px_var(--color-ring)] hover:not-aria-disabled:bg-ring",
393
+ surface: "bg-surface-raised text-fg rounded-xl hover:not-aria-disabled:bg-surface-muted",
394
+ dark: "bg-inverse text-inverse-fg rounded-lg shadow-[0_0_0_1px_var(--color-ring)] hover:not-aria-disabled:opacity-90",
395
+ ghost: "bg-transparent text-fg rounded-lg hover:not-aria-disabled:bg-surface-muted"
409
396
  },
410
397
  size: {
411
398
  sm: "h-8.5 px-3 text-sm",
@@ -523,22 +510,56 @@ function stateClass(disabled, loading) {
523
510
  if (loading) return "cursor-progress opacity-70";
524
511
  if (disabled) return "cursor-not-allowed opacity-50 forced-colors:opacity-100 forced-colors:text-[GrayText] forced-colors:after:border-[GrayText]";
525
512
  }
526
- function ButtonImpl({ className, intent, size, tone, fullWidth, square, loading = false, loadingText = "Loading", disabled = false, iconLeft, iconRight, ripple, tooltip, type = "button", onClick, children, ...props }) {
513
+ function blockActivation(e) {
514
+ e.preventDefault();
515
+ e.stopPropagation();
516
+ }
517
+ function ButtonImpl({ asChild = false, className, intent, size, tone, fullWidth, square, loading = false, loadingText = "Loading", disabled = false, iconLeft, iconRight, ripple, tooltip, type = "button", onClick, onClickCapture, onAuxClickCapture, children, ...props }) {
527
518
  const s = size ?? "md";
528
519
  const inert = disabled || loading;
520
+ const classes = cn(buttonVariants({
521
+ intent,
522
+ size,
523
+ tone,
524
+ fullWidth,
525
+ square
526
+ }), iconPadding(s, iconLeft, iconRight), stateClass(disabled, loading), className);
527
+ const content = (inner) => /* @__PURE__ */ jsx(ButtonContent, {
528
+ size: s,
529
+ ripple: ripple ?? true,
530
+ loading,
531
+ iconLeft,
532
+ iconRight,
533
+ children: inner
534
+ });
535
+ if (asChild) {
536
+ const child = Children.only(children);
537
+ if (!isValidElement(child)) return null;
538
+ const link = /* @__PURE__ */ jsx(Slot, {
539
+ ...props,
540
+ "data-slot": "button",
541
+ "aria-disabled": disabled || void 0,
542
+ className: classes,
543
+ onClick,
544
+ onClickCapture: disabled ? blockActivation : onClickCapture,
545
+ onAuxClickCapture: disabled ? blockActivation : onAuxClickCapture,
546
+ children: cloneElement(child, { children: wrapChildren(child.props.children, content) })
547
+ });
548
+ return tooltip ? /* @__PURE__ */ jsx(Tooltip, {
549
+ ...tooltip,
550
+ className: fullWidth ? "flex w-full" : void 0,
551
+ children: link
552
+ }) : link;
553
+ }
529
554
  const button = /* @__PURE__ */ jsx("button", {
530
555
  ...props,
531
556
  type,
532
557
  "data-slot": "button",
533
558
  "aria-disabled": inert || void 0,
534
559
  "aria-busy": loading || void 0,
535
- className: cn(buttonVariants({
536
- intent,
537
- size,
538
- tone,
539
- fullWidth,
540
- square
541
- }), iconPadding(s, iconLeft, iconRight), stateClass(disabled, loading), className),
560
+ className: classes,
561
+ onClickCapture,
562
+ onAuxClickCapture,
542
563
  onClick: (e) => {
543
564
  if (inert) {
544
565
  e.preventDefault();
@@ -546,14 +567,7 @@ function ButtonImpl({ className, intent, size, tone, fullWidth, square, loading
546
567
  }
547
568
  onClick?.(e);
548
569
  },
549
- children: /* @__PURE__ */ jsx(ButtonContent, {
550
- size: s,
551
- ripple: ripple ?? true,
552
- loading,
553
- iconLeft,
554
- iconRight,
555
- children
556
- })
570
+ children: content(children)
557
571
  });
558
572
  return /* @__PURE__ */ jsxs(Fragment, { children: [tooltip ? /* @__PURE__ */ jsx(Tooltip, {
559
573
  ...tooltip,
@@ -566,7 +580,7 @@ function ButtonImpl({ className, intent, size, tone, fullWidth, square, loading
566
580
  children: loading ? loadingText : ""
567
581
  })] });
568
582
  }
569
- function IconOnlyButton({ icon, tooltip = true, tooltipSide, disabledReason, className, size, ...props }) {
583
+ function IconOnlyButton({ icon, tooltip = true, tooltipSide, disabledReason, className, size, children, ...props }) {
570
584
  const reason = props.disabled ? disabledReason : void 0;
571
585
  const tip = reason ? {
572
586
  content: reason,
@@ -576,13 +590,14 @@ function IconOnlyButton({ icon, tooltip = true, tooltipSide, disabledReason, cla
576
590
  side: tooltipSide,
577
591
  describe: false
578
592
  } : disabledReason !== void 0 ? { content: void 0 } : void 0;
593
+ const child = Children.toArray(children)[0];
579
594
  return /* @__PURE__ */ jsx(ButtonImpl, {
580
595
  ...props,
581
596
  size,
582
597
  tooltip: tip,
583
598
  square: true,
584
599
  className,
585
- children: icon
600
+ children: props.asChild && isValidElement(child) ? cloneElement(child, void 0, icon) : icon
586
601
  });
587
602
  }
588
603
  function Button(props) {
@@ -595,6 +610,135 @@ function Button(props) {
595
610
  });
596
611
  }
597
612
  //#endregion
613
+ //#region src/components/alert/alert.tsx
614
+ const tones = {
615
+ neutral: {
616
+ Icon: Info,
617
+ iconClass: "text-neutral"
618
+ },
619
+ info: {
620
+ Icon: Info,
621
+ iconClass: "text-info"
622
+ },
623
+ success: {
624
+ Icon: CircleCheck,
625
+ iconClass: "text-success"
626
+ },
627
+ warning: {
628
+ Icon: TriangleAlert,
629
+ iconClass: "text-warning"
630
+ },
631
+ danger: {
632
+ Icon: CircleAlert,
633
+ iconClass: "text-danger"
634
+ }
635
+ };
636
+ /** A persistent message shown next to the content it describes. Use a live region for updates that need announcing. */
637
+ function Alert({ tone = "neutral", title, action, onDismiss, dismissLabel = "Dismiss alert", className, children, ...props }) {
638
+ const { Icon, iconClass } = tones[tone];
639
+ return /* @__PURE__ */ jsxs("div", {
640
+ ...props,
641
+ "data-slot": "alert",
642
+ "data-tone": tone,
643
+ className: cn("@container/alert flex items-start gap-3 rounded-xl border border-ring-deep px-4 py-3", "text-sm text-fg forced-colors:border-[CanvasText]", className),
644
+ children: [/* @__PURE__ */ jsxs("div", {
645
+ className: cn("grid min-w-0 flex-1 grid-cols-[1rem_minmax(0,1fr)] items-start gap-x-2.5 gap-y-3", action && "@md/alert:grid-cols-[1rem_minmax(0,1fr)_auto]"),
646
+ children: [
647
+ /* @__PURE__ */ jsx(Icon, {
648
+ "aria-hidden": "true",
649
+ "data-slot": "alert-icon",
650
+ className: cn("mt-0.5 size-4", iconClass)
651
+ }),
652
+ /* @__PURE__ */ jsxs("div", {
653
+ className: "min-w-0 space-y-0.5 wrap-anywhere",
654
+ children: [title != null && /* @__PURE__ */ jsx("div", {
655
+ "data-slot": "alert-title",
656
+ className: "font-medium",
657
+ children: title
658
+ }), children != null && /* @__PURE__ */ jsx("div", {
659
+ "data-slot": "alert-description",
660
+ className: title != null ? "text-fg-muted" : void 0,
661
+ children
662
+ })]
663
+ }),
664
+ action && /* @__PURE__ */ jsx("div", {
665
+ "data-slot": "alert-action",
666
+ className: "col-start-2 justify-self-start @md/alert:col-start-3 @md/alert:self-center",
667
+ children: action
668
+ })
669
+ ]
670
+ }), onDismiss && /* @__PURE__ */ jsx(Button, {
671
+ "aria-label": dismissLabel,
672
+ className: "-my-1.5 -me-1.5 shrink-0 text-fg-muted @md/alert:self-center",
673
+ icon: /* @__PURE__ */ jsx(X, {}),
674
+ intent: "ghost",
675
+ size: "sm",
676
+ onClick: onDismiss
677
+ })]
678
+ });
679
+ }
680
+ //#endregion
681
+ //#region src/components/badge/badge.tsx
682
+ const toneClasses$1 = {
683
+ neutral: {
684
+ subtle: ["border-neutral-border bg-neutral-subtle-bg text-neutral-subtle-fg", "text-neutral"],
685
+ outline: ["border-neutral-border bg-transparent text-neutral-subtle-fg", "text-neutral"],
686
+ solid: ["border-neutral bg-neutral text-neutral-fg", "text-neutral-fg"]
687
+ },
688
+ info: {
689
+ subtle: ["border-info-border bg-info-subtle-bg text-info-subtle-fg", "text-info"],
690
+ outline: ["border-info-border bg-transparent text-info-subtle-fg", "text-info"],
691
+ solid: ["border-info bg-info text-info-fg", "text-info-fg"]
692
+ },
693
+ success: {
694
+ subtle: ["border-success-border bg-success-subtle-bg text-success-subtle-fg", "text-success"],
695
+ outline: ["border-success-border bg-transparent text-success-subtle-fg", "text-success"],
696
+ solid: ["border-success bg-success text-success-fg", "text-success-fg"]
697
+ },
698
+ warning: {
699
+ subtle: ["border-warning-border bg-warning-subtle-bg text-warning-subtle-fg", "text-warning"],
700
+ outline: ["border-warning-border bg-transparent text-warning-subtle-fg", "text-warning"],
701
+ solid: ["border-warning bg-warning text-warning-fg", "text-warning-fg"]
702
+ },
703
+ danger: {
704
+ subtle: ["border-danger-border bg-danger-subtle-bg text-danger-subtle-fg", "text-danger"],
705
+ outline: ["border-danger-border bg-transparent text-danger-subtle-fg", "text-danger"],
706
+ solid: ["border-danger bg-danger text-danger-fg", "text-danger-fg"]
707
+ }
708
+ };
709
+ const sizeClasses$3 = {
710
+ sm: {
711
+ base: "h-5 px-1.5",
712
+ withIcon: "ps-1"
713
+ },
714
+ md: {
715
+ base: "h-6 px-2",
716
+ withIcon: "ps-1.5"
717
+ }
718
+ };
719
+ function Badge({ tone = "neutral", variant = "subtle", size = "md", icon, busy = false, context, className, children, ...props }) {
720
+ const [toneClass, iconClass] = toneClasses$1[tone][variant];
721
+ const hasIcon = busy || icon !== void 0 && icon !== null && icon !== false;
722
+ return /* @__PURE__ */ jsxs("span", {
723
+ ...props,
724
+ "data-slot": "badge",
725
+ className: cn("inline-flex items-center gap-1 rounded-md border text-xs leading-none font-medium whitespace-nowrap", "forced-colors:border-[CanvasText]", sizeClasses$3[size].base, hasIcon && sizeClasses$3[size].withIcon, toneClass, className),
726
+ children: [hasIcon && /* @__PURE__ */ jsx("span", {
727
+ "aria-hidden": "true",
728
+ "data-slot": "badge-icon",
729
+ className: cn("inline-flex shrink-0 items-center [&_svg]:size-3 [&_svg]:shrink-0", iconClass),
730
+ children: busy ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoaderCircle, { className: "animate-spin motion-reduce:hidden" }), /* @__PURE__ */ jsx(CircleDashed, { className: "hidden motion-reduce:block" })] }) : icon
731
+ }), /* @__PURE__ */ jsxs("span", {
732
+ "data-slot": "badge-label",
733
+ className: "min-w-0 truncate leading-4",
734
+ children: [context && /* @__PURE__ */ jsxs("span", {
735
+ className: "sr-only",
736
+ children: [context, ": "]
737
+ }), children]
738
+ })]
739
+ });
740
+ }
741
+ //#endregion
598
742
  //#region src/components/card/card.tsx
599
743
  const CardContext = createContext({
600
744
  titleId: "",
@@ -616,7 +760,7 @@ function Card({ as: Comp = "div", className, ...props }) {
616
760
  "aria-labelledby": (Comp === "section" || Comp === "article") && titled && !props["aria-label"] ? titleId : void 0,
617
761
  ...props,
618
762
  "data-slot": "card",
619
- className: cn("rounded-lg border border-border-strong bg-surface", className)
763
+ className: cn("rounded-xl border border-border-strong bg-surface", className)
620
764
  })
621
765
  });
622
766
  }
@@ -738,7 +882,7 @@ function Notch({ ring, size, disabled, children }) {
738
882
  const halo = ring === "halo";
739
883
  return /* @__PURE__ */ jsx("fieldset", {
740
884
  "aria-hidden": true,
741
- className: cn("pointer-events-none absolute m-0 min-w-0 p-0", "transition-[border-color] duration-200 ease-in-out motion-reduce:transition-none", notchPadding[ring][size], halo ? ["-inset-1 rounded-[calc(var(--radius-md)+3px)] border-[3px] border-(--field-halo)", "forced-colors:invisible forced-colors:group-has-[:is(input,select):is(:focus,:open)]/control:visible forced-colors:border-[Highlight]"] : ["-inset-px rounded-[inherit] border border-(--field-border)", disabled && "forced-colors:border-[GrayText]"]),
885
+ className: cn("pointer-events-none absolute m-0 min-w-0 p-0", "transition-[border-color] duration-200 ease-in-out motion-reduce:transition-none", notchPadding[ring][size], halo ? ["-inset-1 rounded-[calc(var(--radius-lg)+3px)] border-[3px] border-(--field-halo)", "forced-colors:invisible forced-colors:group-has-[:is(input,select):is(:focus,:open)]/control:visible forced-colors:border-[Highlight]"] : ["-inset-px rounded-[inherit] border border-(--field-border)", disabled && "forced-colors:border-[GrayText]"]),
742
886
  children: /* @__PURE__ */ jsx("legend", {
743
887
  className: cn("invisible float-none block w-auto max-w-[0.01px] overflow-hidden p-0 text-xs whitespace-nowrap", halo ? "h-0.75" : "h-px", "transition-[max-width] duration-50 ease-out motion-reduce:transition-none", "[[data-slot=input-control]:is([data-start],:has(input:focus),:has(input:not(:placeholder-shown)),:has(input:autofill),:has(input:-webkit-autofill),:has(select:focus),:has(select:open),:has(select):not(:has(option[value=\"\"]:checked)))_&]:max-w-full", "[[data-slot=input-control]:is([data-start],:has(input:focus),:has(input:not(:placeholder-shown)),:has(input:autofill),:has(input:-webkit-autofill),:has(select:focus),:has(select:open),:has(select):not(:has(option[value=\"\"]:checked)))_&]:delay-50", "[[data-slot=input-control]:is([data-start],:has(input:focus),:has(input:not(:placeholder-shown)),:has(input:autofill),:has(input:-webkit-autofill),:has(select:focus),:has(select:open),:has(select):not(:has(option[value=\"\"]:checked)))_&]:duration-100"),
744
888
  children: /* @__PURE__ */ jsx("span", {
@@ -805,7 +949,7 @@ function FieldShell({ label, floating = false, helperText, error, size, id: idPr
805
949
  "data-slot": "input-control",
806
950
  "data-start": hasStart ? "" : void 0,
807
951
  onMouseDown: forwardClick,
808
- className: cn("group/control relative isolate flex items-center rounded-md border", floatingLabel ? "bg-transparent" : "[--field-bg:var(--color-input-bg)] bg-(--field-bg)", "transition-[border-color,box-shadow,background-color] duration-200 ease-in-out motion-reduce:transition-none", controlHeight[size], invalid ? ["[--field-border:var(--color-danger)] [--field-halo:var(--color-input-halo-invalid)]", "has-[:is(input,select):is(:focus,:open)]:[--field-halo:var(--color-input-halo-invalid-focus)]"] : ["[--field-border:var(--color-input-border)] [--field-halo:transparent]", "has-[:is(input,select):is(:focus,:open)]:[--field-border:var(--color-input-focus)] has-[:is(input,select):is(:focus,:open)]:[--field-halo:var(--color-input-halo)]"], "[--field-lift:0_0_#0000]", !invalid && !disabled && !readOnly && [
952
+ className: cn("group/control relative isolate flex items-center rounded-lg border", floatingLabel ? "bg-transparent" : "[--field-bg:var(--color-input-bg)] bg-(--field-bg)", "transition-[border-color,box-shadow,background-color] duration-200 ease-in-out motion-reduce:transition-none", controlHeight[size], invalid ? ["[--field-border:var(--color-danger)] [--field-halo:var(--color-input-halo-invalid)]", "has-[:is(input,select):is(:focus,:open)]:[--field-halo:var(--color-input-halo-invalid-focus)]"] : ["[--field-border:var(--color-input-border)] [--field-halo:transparent]", "has-[:is(input,select):is(:focus,:open)]:[--field-border:var(--color-input-focus)] has-[:is(input,select):is(:focus,:open)]:[--field-halo:var(--color-input-halo)]"], "[--field-lift:0_0_#0000]", !invalid && !disabled && !readOnly && [
809
953
  "hover:not-has-[:is(input,select):is(:focus,:open)]:[--field-border:var(--color-input-border-hover)]",
810
954
  !floatingLabel && "hover:not-has-[:is(input,select):is(:focus,:open)]:[--field-bg:var(--color-input-bg-hover)]",
811
955
  "hover:not-has-[:is(input,select):is(:focus,:open)]:[--field-lift:var(--shadow-input-lift)]"
@@ -1006,7 +1150,7 @@ function Checkbox({ label, description, error, indeterminate = false, className,
1006
1150
  "aria-labelledby": props["aria-labelledby"] ?? row.labelledBy,
1007
1151
  "aria-describedby": row.describedBy,
1008
1152
  "aria-invalid": row.invalid ? true : ariaInvalid,
1009
- className: cn("peer col-start-1 row-start-1 m-0 size-4 cursor-pointer appearance-none rounded-sharp border outline-hidden", "disabled:cursor-not-allowed", "border-(--checkbox-border) bg-(--checkbox-bg) [box-shadow:0_0_0_3px_var(--checkbox-halo)]", "transition-[background-color,border-color,box-shadow] duration-200 ease-in-out", "[--checkbox-bg:var(--color-input-bg)] [--checkbox-halo:transparent]", "checked:[--checkbox-bg:var(--color-control-checked)] indeterminate:[--checkbox-bg:var(--color-control-checked)]", row.invalid ? [
1153
+ className: cn("peer col-start-1 row-start-1 m-0 size-4 cursor-pointer appearance-none rounded-sm border outline-hidden", "disabled:cursor-not-allowed", "border-(--checkbox-border) bg-(--checkbox-bg) [box-shadow:0_0_0_3px_var(--checkbox-halo)]", "transition-[background-color,border-color,box-shadow] duration-200 ease-in-out", "[--checkbox-bg:var(--color-input-bg)] [--checkbox-halo:transparent]", "checked:[--checkbox-bg:var(--color-control-checked)] indeterminate:[--checkbox-bg:var(--color-control-checked)]", row.invalid ? [
1010
1154
  "[--checkbox-border:var(--color-danger)] [--checkbox-halo:var(--color-input-halo-invalid)]",
1011
1155
  "focus-visible:[--checkbox-halo:var(--color-input-halo-invalid-focus)]",
1012
1156
  "not-forced-colors:checked:focus-visible:outline-danger not-forced-colors:indeterminate:focus-visible:outline-danger"
@@ -1331,7 +1475,7 @@ function Dialog({ size = "md", className, children, ...props }) {
1331
1475
  className: cn("m-auto w-[calc(100%-2rem)] max-h-[calc(100dvh-64px)] overflow-visible border-0 bg-transparent p-0 text-fg", "overscroll-contain outline-none", sizeClasses$2[size], motionClasses$1, sheetClasses, className),
1332
1476
  children: /* @__PURE__ */ jsx("div", {
1333
1477
  "data-slot": "dialog-panel",
1334
- className: cn("flex max-h-[inherit] flex-col rounded-lg border border-popover-border bg-popover-bg shadow-dialog", "forced-colors:border-[CanvasText]", "max-sm:rounded-b-none max-sm:border-b-0 max-sm:pb-[env(safe-area-inset-bottom)]"),
1478
+ className: cn("flex max-h-[inherit] flex-col rounded-xl border border-popover-border bg-popover-bg shadow-dialog", "forced-colors:border-[CanvasText]", "max-sm:rounded-b-none max-sm:border-b-0 max-sm:pb-[env(safe-area-inset-bottom)]"),
1335
1479
  children
1336
1480
  })
1337
1481
  });
@@ -1349,7 +1493,7 @@ function DialogHeader({ title, description, closeButton, className, ...props })
1349
1493
  className: "min-w-0 flex-1",
1350
1494
  children: [/* @__PURE__ */ jsx("h2", {
1351
1495
  id: context.titleId,
1352
- className: "m-0 text-xl/tight text-fg",
1496
+ className: "m-0 text-xl/tight font-medium text-fg",
1353
1497
  children: title
1354
1498
  }), hasDescription && /* @__PURE__ */ jsx("p", {
1355
1499
  id: context.descriptionId,
@@ -1455,7 +1599,7 @@ function DrawerHeader({ title, description, className, ...props }) {
1455
1599
  className: "min-w-0 flex-1",
1456
1600
  children: [/* @__PURE__ */ jsx("h2", {
1457
1601
  id: context.titleId,
1458
- className: "m-0 text-xl/tight wrap-anywhere text-fg",
1602
+ className: "m-0 text-xl/tight font-medium wrap-anywhere text-fg",
1459
1603
  children: title
1460
1604
  }), hasDescription && /* @__PURE__ */ jsx("p", {
1461
1605
  id: context.descriptionId,
@@ -1708,9 +1852,9 @@ const labelRestingWidth = {
1708
1852
  lg: "max-w-[calc(100%-50px)]"
1709
1853
  };
1710
1854
  const isGroup = (item) => "options" in item;
1711
- const pickerClasses = cn("supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[appearance:base-select]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:[appearance:base-select]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker-icon]:hidden", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:[position-area:block-end_span-inline-end]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:[position-try-fallbacks:flip-block]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:mt-1", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:min-w-[anchor-size(width)]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:max-h-[max(10rem,calc(100%-12px))]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:overflow-y-auto", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:rounded-lg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:border", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:border-popover-border", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:bg-popover-bg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:p-1", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:shadow-popover", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:text-fg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:origin-top", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:opacity-0", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:scale-96", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:transition-[opacity,scale,display,overlay]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:transition-discrete", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:duration-80", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:ease-out", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:opacity-100", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:scale-100", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:duration-120", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:starting:opacity-0", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:starting:scale-96", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:motion-reduce:[&::picker(select)]:transition-none");
1855
+ const pickerClasses = cn("supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[appearance:base-select]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:[appearance:base-select]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker-icon]:hidden", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:[position-area:block-end_span-inline-end]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:[position-try-fallbacks:flip-block]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:mt-1", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:min-w-[anchor-size(width)]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:max-h-[max(10rem,calc(100%-12px))]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:overflow-y-auto", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:rounded-xl", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:border", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:border-popover-border", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:bg-popover-bg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:p-1", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:shadow-popover", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:text-fg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:origin-top", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:opacity-0", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:scale-96", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:transition-[opacity,scale,display,overlay]", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:transition-discrete", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:duration-80", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::picker(select)]:ease-out", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:opacity-100", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:scale-100", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:duration-120", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:starting:opacity-0", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:open:[&::picker(select)]:starting:scale-96", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:motion-reduce:[&::picker(select)]:transition-none");
1712
1856
  function optionClasses(size, mono) {
1713
- return cn("bg-popover-bg text-fg checked:font-medium disabled:text-fg-subtle", textSize[size], mono && "font-mono", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:flex", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:cursor-default", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:items-center", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:gap-2", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:rounded-md", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:bg-transparent", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:px-2", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:py-1.5", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:not-disabled:hover:bg-popover-highlight", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:focus-visible:bg-popover-highlight", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:focus-visible:outline-hidden", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:disabled:text-fg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:disabled:opacity-50", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::checkmark]:order-1", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::checkmark]:ms-auto");
1857
+ return cn("bg-popover-bg text-fg checked:font-medium disabled:text-fg-subtle", textSize[size], mono && "font-mono", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:flex", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:cursor-default", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:items-center", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:gap-2", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:rounded-lg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:bg-transparent", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:px-2", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:py-1.5", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:not-disabled:hover:bg-popover-highlight", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:focus-visible:bg-popover-highlight", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:focus-visible:outline-hidden", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:disabled:text-fg", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:disabled:opacity-50", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::checkmark]:order-1", "supports-[appearance:base-select]:[@media(hover:hover)_and_(pointer:fine)]:[&::checkmark]:ms-auto");
1714
1858
  }
1715
1859
  function openPicker(select) {
1716
1860
  select.focus();
@@ -1811,61 +1955,6 @@ function Select({ options, placeholder, helperText, error, size = "md", start, m
1811
1955
  });
1812
1956
  }
1813
1957
  //#endregion
1814
- //#region src/lib/slot.tsx
1815
- function setRef(ref, node) {
1816
- if (typeof ref === "function") return ref(node);
1817
- if (ref) ref.current = node;
1818
- }
1819
- function composeRefs(...refs) {
1820
- return (node) => {
1821
- const cleanups = refs.map((ref) => setRef(ref, node));
1822
- return () => {
1823
- for (const [i, ref] of refs.entries()) {
1824
- const cleanup = cleanups[i];
1825
- if (typeof cleanup === "function") cleanup();
1826
- else setRef(ref, null);
1827
- }
1828
- };
1829
- };
1830
- }
1831
- function mergeProps(slot, child) {
1832
- const merged = {
1833
- ...slot,
1834
- ...child
1835
- };
1836
- for (const key of Object.keys(slot)) {
1837
- const own = slot[key];
1838
- const theirs = child[key];
1839
- if (/^on[A-Z]/.test(key) && typeof own === "function" && typeof theirs === "function") merged[key] = (...args) => {
1840
- theirs(...args);
1841
- own(...args);
1842
- };
1843
- else if (key === "className") merged.className = cn(own, theirs);
1844
- else if (key === "style") merged.style = {
1845
- ...own,
1846
- ...theirs
1847
- };
1848
- }
1849
- return merged;
1850
- }
1851
- /** Applies `wrap` to an element's children, or to what a render-prop child returns. */
1852
- function wrapChildren(children, wrap) {
1853
- if (typeof children !== "function") return wrap(children);
1854
- return (...args) => wrap(children(...args));
1855
- }
1856
- /** Renders its only child with these props merged in (Radix Slot style). */
1857
- function Slot({ children, ref, ...props }) {
1858
- const child = Children.only(children);
1859
- const childProps = isValidElement(child) ? child.props : {};
1860
- const childRef = childProps.ref;
1861
- const composedRef = useMemo(() => composeRefs(ref, childRef), [ref, childRef]);
1862
- if (!isValidElement(child)) return null;
1863
- return cloneElement(child, {
1864
- ...mergeProps(props, childProps),
1865
- ref: composedRef
1866
- });
1867
- }
1868
- //#endregion
1869
1958
  //#region src/components/tabs/shared.tsx
1870
1959
  const listBase = [
1871
1960
  "relative isolate max-w-full overflow-x-auto overscroll-x-contain scroll-px-6",
@@ -1882,7 +1971,7 @@ const listVariant = {
1882
1971
  "before:bottom-0 before:h-0.5 before:bg-fg before:[translate:var(--tabs-indicator-x)_0]",
1883
1972
  "before:transition-[translate,width]",
1884
1973
  "forced-colors:before:bg-[Highlight] forced-colors:before:[forced-color-adjust:none]",
1885
- "after:pointer-events-none after:absolute after:top-0 after:left-0 after:-z-1 after:rounded-md",
1974
+ "after:pointer-events-none after:absolute after:top-0 after:left-0 after:-z-1 after:rounded-lg",
1886
1975
  "after:bg-fg/7 after:opacity-0 data-hover:after:opacity-100",
1887
1976
  "after:h-(--tabs-hover-h) after:w-(--tabs-hover-w)",
1888
1977
  "after:[translate:var(--tabs-hover-x)_var(--tabs-hover-y)]",
@@ -1891,8 +1980,8 @@ const listVariant = {
1891
1980
  "data-hover-enter:after:transition-opacity"
1892
1981
  ],
1893
1982
  segmented: [
1894
- "inline-flex w-fit rounded-sm p-1 shadow-[inset_0_0_0_1px_var(--color-ring)]",
1895
- "before:top-0 before:h-(--tabs-indicator-h) before:rounded-sharp before:bg-fg/8",
1983
+ "inline-flex w-fit rounded-md p-1 shadow-[inset_0_0_0_1px_var(--color-ring)]",
1984
+ "before:top-0 before:h-(--tabs-indicator-h) before:rounded-sm before:bg-fg/8",
1896
1985
  "before:[translate:var(--tabs-indicator-x)_var(--tabs-indicator-y)]",
1897
1986
  "before:transition-[translate,width,height]",
1898
1987
  "forced-colors:before:border-2 forced-colors:before:border-[Highlight]"
@@ -1930,8 +2019,8 @@ const itemBase = [
1930
2019
  "forced-colors:aria-disabled:text-[GrayText] forced-colors:aria-disabled:opacity-100"
1931
2020
  ];
1932
2021
  const itemVariant = {
1933
- line: ["rounded-md data-selected:font-medium aria-[current=page]:font-medium"],
1934
- segmented: ["h-full rounded-sharp font-medium"]
2022
+ line: ["rounded-lg data-selected:font-medium aria-[current=page]:font-medium"],
2023
+ segmented: ["h-full rounded-sm font-medium"]
1935
2024
  };
1936
2025
  const itemSize = {
1937
2026
  line: {
@@ -2254,7 +2343,7 @@ function useHoverPill() {
2254
2343
  }
2255
2344
  const bodyClasses = [
2256
2345
  "relative isolate flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto overscroll-contain px-3 py-2",
2257
- "after:pointer-events-none after:absolute after:top-0 after:left-0 after:-z-1 after:rounded-sm",
2346
+ "after:pointer-events-none after:absolute after:top-0 after:left-0 after:-z-1 after:rounded-md",
2258
2347
  "after:bg-fg/5 after:opacity-0 data-hover:after:opacity-100",
2259
2348
  "after:h-(--sidebar-hover-h) after:w-(--sidebar-hover-w)",
2260
2349
  "after:[translate:var(--sidebar-hover-x)_var(--sidebar-hover-y)]",
@@ -2309,7 +2398,7 @@ function SidebarGroup({ label, className, children, ...props }) {
2309
2398
  });
2310
2399
  }
2311
2400
  const itemClasses = [
2312
- "flex h-9 w-full items-center gap-2 rounded-sm ps-2.5 pe-2",
2401
+ "flex h-9 w-full items-center gap-2 rounded-md ps-2.5 pe-2",
2313
2402
  "text-sm leading-5 font-medium text-fg-muted no-underline select-none",
2314
2403
  "touch-manipulation [-webkit-tap-highlight-color:transparent]",
2315
2404
  "transition-[color,background-color] duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]",
@@ -2441,13 +2530,240 @@ function Switch({ label, description, error, size = "md", loading = false, label
2441
2530
  ], "checked:focus-visible:[--switch-ring:transparent] checked:focus-visible:[--switch-halo:transparent]", "checked:focus-visible:outline-solid checked:focus-visible:outline-2 checked:focus-visible:outline-offset-2", row.invalid && "not-forced-colors:checked:focus-visible:outline-danger", "forced-colors:forced-color-adjust-none forced-colors:[box-shadow:none]", "forced-colors:border-[CanvasText] forced-colors:bg-[Canvas]", "forced-colors:checked:border-[Highlight] forced-colors:checked:bg-[Highlight]", "forced-colors:disabled:border-[GrayText] forced-colors:disabled:checked:bg-[GrayText]", "forced-colors:focus-visible:outline-[CanvasText]", inputClassName)
2442
2531
  }), /* @__PURE__ */ jsx("span", {
2443
2532
  "aria-hidden": true,
2444
- className: cn("pointer-events-none absolute inset-s-0.5 top-0.5 grid place-items-center rounded-full", "h-(--switch-thumb) w-(--switch-thumb-w) bg-control-checked-fg text-control-checked shadow-switch-thumb", "[--switch-dir:1] rtl:[--switch-dir:-1] [translate:calc(var(--switch-x)*var(--switch-dir))_0]", "[--switch-x:0px] [--switch-thumb-w:var(--switch-thumb)] peer-checked:[--switch-x:var(--switch-travel)]", "transition-[translate,width] duration-150 ease-in-out", pressable && ["peer-active:[--switch-thumb-w:calc(var(--switch-thumb)+var(--switch-stretch))]", "peer-checked:peer-active:[--switch-x:calc(var(--switch-travel)-var(--switch-stretch))]"], "peer-disabled:shadow-none", "forced-colors:forced-color-adjust-none forced-colors:shadow-none", "forced-colors:bg-[CanvasText] forced-colors:text-[Canvas]", "forced-colors:peer-checked:bg-[HighlightText] forced-colors:peer-checked:text-[Highlight]", "forced-colors:peer-disabled:bg-[GrayText] forced-colors:peer-disabled:peer-checked:bg-[Canvas]", s.icon),
2533
+ className: cn("pointer-events-none absolute inset-s-0.5 top-0.5 grid place-items-center rounded-full", "h-(--switch-thumb) w-(--switch-thumb-w) bg-switch-handle peer-checked:bg-switch-handle-checked text-control-checked shadow-switch-thumb", "[--switch-dir:1] rtl:[--switch-dir:-1] [translate:calc(var(--switch-x)*var(--switch-dir))_0]", "[--switch-x:0px] [--switch-thumb-w:var(--switch-thumb)] peer-checked:[--switch-x:var(--switch-travel)]", "transition-[translate,width] duration-150 ease-in-out", pressable && ["peer-active:[--switch-thumb-w:calc(var(--switch-thumb)+var(--switch-stretch))]", "peer-checked:peer-active:[--switch-x:calc(var(--switch-travel)-var(--switch-stretch))]"], "peer-disabled:shadow-none", "forced-colors:forced-color-adjust-none forced-colors:shadow-none", "forced-colors:bg-[CanvasText] forced-colors:text-[Canvas]", "forced-colors:peer-checked:bg-[HighlightText] forced-colors:peer-checked:text-[Highlight]", "forced-colors:peer-disabled:bg-[GrayText] forced-colors:peer-disabled:peer-checked:bg-[Canvas]", s.icon),
2445
2534
  children: loading && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoaderCircle, { className: "animate-spin motion-reduce:hidden" }), /* @__PURE__ */ jsx(CircleDashed, { className: "hidden motion-reduce:block" })] })
2446
2535
  })]
2447
2536
  })
2448
2537
  });
2449
2538
  }
2450
2539
  //#endregion
2540
+ //#region src/components/table/table.tsx
2541
+ const labels = {
2542
+ search: "Search rows",
2543
+ clearSelection: "Clear selection",
2544
+ selectPage: "Select all rows on this page",
2545
+ selectRow: (id) => `Select row ${id}`,
2546
+ selectionCount: (count) => `${count} selected`,
2547
+ scrollRegion: "Table",
2548
+ pagination: "Pagination",
2549
+ previousPage: "Previous page",
2550
+ nextPage: "Next page",
2551
+ page: (page, count) => `${page} / ${count}`,
2552
+ range: (first, last, total) => total === 0 ? "0 rows" : `${first}–${last} of ${total}`,
2553
+ emptyState: "No rows yet",
2554
+ noResults: "No matching rows"
2555
+ };
2556
+ const alignClasses = {
2557
+ start: "text-start",
2558
+ center: "text-center",
2559
+ end: "text-end"
2560
+ };
2561
+ const sortIcons = {
2562
+ asc: ArrowUp,
2563
+ desc: ArrowDown
2564
+ };
2565
+ function Table({ data, columns, getRowId, title, emptyState, noResults, filtered = false, search, sorting, pagination, selection, className, tableClassName, labels: labelOverrides, ...props }) {
2566
+ const titleId = useId();
2567
+ const scrollRef = useRef(null);
2568
+ const searchRef = useRef(null);
2569
+ const emptyRef = useRef(null);
2570
+ const text = {
2571
+ ...labels,
2572
+ ...labelOverrides
2573
+ };
2574
+ const tableName = props["aria-labelledby"] ?? (title != null && !props["aria-label"] ? titleId : void 0);
2575
+ const showEmpty = data.length === 0 && !filtered && !search?.value.trim() && (!pagination || pagination.rowCount === 0);
2576
+ const showSearch = !showEmpty && search != null;
2577
+ const hasControls = showSearch || !!selection?.ids.size;
2578
+ const hasToolbar = title != null || hasControls;
2579
+ const rows = data.map((row) => ({
2580
+ row,
2581
+ id: getRowId(row),
2582
+ canSelect: selection?.canSelectRow?.(row) ?? true
2583
+ }));
2584
+ const selectableIds = selection ? rows.filter((row) => row.canSelect).map((row) => row.id) : [];
2585
+ const selectedOnPage = selectableIds.filter((id) => selection?.ids.has(id)).length;
2586
+ const allOnPageSelected = selectableIds.length > 0 && selectedOnPage === selectableIds.length;
2587
+ const updateSelection = (ids, checked) => {
2588
+ if (!selection) return;
2589
+ const next = new Set(selection.ids);
2590
+ for (const id of ids) if (checked) next.add(id);
2591
+ else next.delete(id);
2592
+ selection.onChange(next);
2593
+ };
2594
+ return /* @__PURE__ */ jsxs("div", {
2595
+ "data-slot": "table-root",
2596
+ className: cn("w-full min-w-0 bg-surface text-fg", className),
2597
+ children: [hasToolbar && /* @__PURE__ */ jsxs("div", {
2598
+ "data-slot": "table-toolbar",
2599
+ className: "flex flex-wrap items-center justify-between gap-3 border-b border-border px-4 py-3",
2600
+ children: [title != null && /* @__PURE__ */ jsx("span", {
2601
+ id: titleId,
2602
+ className: "text-sm font-semibold",
2603
+ children: title
2604
+ }), hasControls && /* @__PURE__ */ jsxs("div", {
2605
+ className: "ms-auto flex min-w-0 flex-wrap items-center justify-end gap-x-3 gap-y-2",
2606
+ children: [
2607
+ selection && /* @__PURE__ */ jsx("output", {
2608
+ className: "text-xs text-fg-muted",
2609
+ children: selection.ids.size > 0 && text.selectionCount(selection.ids.size)
2610
+ }),
2611
+ !!selection?.ids.size && /* @__PURE__ */ jsx(Button, {
2612
+ intent: "ghost",
2613
+ size: "sm",
2614
+ ripple: false,
2615
+ onClick: () => {
2616
+ selection.onChange(/* @__PURE__ */ new Set());
2617
+ (searchRef.current ?? scrollRef.current ?? emptyRef.current)?.focus();
2618
+ },
2619
+ children: text.clearSelection
2620
+ }),
2621
+ showSearch && /* @__PURE__ */ jsx(SearchInput, {
2622
+ ref: searchRef,
2623
+ "aria-label": text.search,
2624
+ placeholder: `${text.search}…`,
2625
+ size: "sm",
2626
+ className: "w-48 max-w-full",
2627
+ value: search.value,
2628
+ onChange: (event) => search.onChange(event.currentTarget.value)
2629
+ })
2630
+ ]
2631
+ })]
2632
+ }), showEmpty ? /* @__PURE__ */ jsx("div", {
2633
+ ref: emptyRef,
2634
+ "data-slot": "table-empty",
2635
+ tabIndex: -1,
2636
+ className: "grid min-h-48 place-items-center px-4 py-8 text-center text-sm text-fg-muted outline-hidden focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus",
2637
+ children: emptyState === void 0 ? text.emptyState : emptyState
2638
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("section", {
2639
+ ref: scrollRef,
2640
+ "data-slot": "table-scroll",
2641
+ "aria-labelledby": tableName,
2642
+ "aria-label": tableName ? void 0 : props["aria-label"] ?? text.scrollRegion,
2643
+ tabIndex: 0,
2644
+ className: "relative w-full overflow-x-auto outline-hidden focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus",
2645
+ children: /* @__PURE__ */ jsxs("table", {
2646
+ ...props,
2647
+ "aria-labelledby": tableName,
2648
+ "data-slot": "table",
2649
+ className: cn("w-full border-separate border-spacing-0 text-sm", tableClassName),
2650
+ children: [/* @__PURE__ */ jsx("thead", {
2651
+ "data-slot": "table-header",
2652
+ children: /* @__PURE__ */ jsxs("tr", { children: [selection && /* @__PURE__ */ jsx("th", {
2653
+ scope: "col",
2654
+ className: "w-12 border-b border-border px-3",
2655
+ children: /* @__PURE__ */ jsx(Checkbox, {
2656
+ "aria-label": text.selectPage,
2657
+ checked: allOnPageSelected,
2658
+ indeterminate: selectedOnPage > 0 && !allOnPageSelected,
2659
+ disabled: selectableIds.length === 0,
2660
+ onChange: (event) => updateSelection(selectableIds, event.currentTarget.checked),
2661
+ className: "mx-auto justify-center"
2662
+ })
2663
+ }), columns.map((column) => {
2664
+ const direction = sorting?.value?.id === column.id ? sorting.value.direction : void 0;
2665
+ const SortIcon = direction ? sortIcons[direction] : ArrowUpDown;
2666
+ const align = column.align ?? (column.numeric ? "end" : "start");
2667
+ return /* @__PURE__ */ jsx("th", {
2668
+ scope: "col",
2669
+ "aria-sort": direction ? direction === "asc" ? "ascending" : "descending" : void 0,
2670
+ className: cn("h-10 border-b border-border px-4 text-xs font-medium whitespace-nowrap text-fg-muted", alignClasses[align], column.headerClassName),
2671
+ children: sorting && column.sortable ? /* @__PURE__ */ jsxs("button", {
2672
+ type: "button",
2673
+ className: cn("inline-flex min-h-8 cursor-pointer items-center gap-1.5 rounded-sm hover:text-fg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus pointer-coarse:min-h-11", direction && "text-fg"),
2674
+ onClick: () => sorting.onChange(direction === "desc" ? null : {
2675
+ id: column.id,
2676
+ direction: direction === "asc" ? "desc" : "asc"
2677
+ }),
2678
+ children: [column.header, /* @__PURE__ */ jsx(SortIcon, {
2679
+ "aria-hidden": true,
2680
+ className: "size-3.5 shrink-0"
2681
+ })]
2682
+ }) : column.header
2683
+ }, column.id);
2684
+ })] })
2685
+ }), /* @__PURE__ */ jsxs("tbody", {
2686
+ "data-slot": "table-body",
2687
+ className: "[&>tr:not(:last-child)>*]:border-b [&>tr>*]:border-border",
2688
+ children: [rows.map(({ row, id, canSelect }) => {
2689
+ const selected = selection?.ids.has(id) ?? false;
2690
+ return /* @__PURE__ */ jsxs("tr", {
2691
+ "data-slot": "table-row",
2692
+ "data-selected": selected || void 0,
2693
+ className: "hover:bg-surface-muted data-selected:bg-surface-muted",
2694
+ children: [selection && /* @__PURE__ */ jsx("td", {
2695
+ className: "w-12 px-3",
2696
+ children: /* @__PURE__ */ jsx(Checkbox, {
2697
+ "aria-label": text.selectRow(id),
2698
+ checked: selected,
2699
+ disabled: !canSelect,
2700
+ onChange: (event) => updateSelection([id], event.currentTarget.checked),
2701
+ className: "mx-auto justify-center"
2702
+ })
2703
+ }), columns.map((column) => {
2704
+ const Cell = column.rowHeader ? "th" : "td";
2705
+ const align = column.align ?? (column.numeric ? "end" : "start");
2706
+ return /* @__PURE__ */ jsx(Cell, {
2707
+ scope: column.rowHeader ? "row" : void 0,
2708
+ className: cn("h-13 px-4 py-2 align-middle", alignClasses[align], column.numeric && "tabular-nums", column.rowHeader && "font-medium", column.className),
2709
+ children: column.cell(row)
2710
+ }, column.id);
2711
+ })]
2712
+ }, id);
2713
+ }), rows.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
2714
+ colSpan: Math.max(1, columns.length + Number(Boolean(selection))),
2715
+ children: /* @__PURE__ */ jsx("div", {
2716
+ "data-slot": "table-no-results",
2717
+ className: "sticky inset-s-0 w-max max-w-[min(100%,18rem)] px-4 py-12 text-sm text-fg-muted",
2718
+ children: noResults === void 0 ? /* @__PURE__ */ jsx("output", { children: text.noResults }) : noResults
2719
+ })
2720
+ }) })]
2721
+ })]
2722
+ })
2723
+ }), pagination && /* @__PURE__ */ jsx(TablePagination, {
2724
+ ...pagination,
2725
+ visibleCount: rows.length,
2726
+ text
2727
+ })] })]
2728
+ });
2729
+ }
2730
+ function TablePagination({ pageIndex, pageSize, rowCount, visibleCount, onPageChange, text }) {
2731
+ const count = Math.ceil(rowCount / pageSize);
2732
+ const first = visibleCount ? pageIndex * pageSize + 1 : 0;
2733
+ const last = first ? first + visibleCount - 1 : 0;
2734
+ const canGoBack = pageIndex > 0;
2735
+ const canGoForward = pageIndex + 1 < count;
2736
+ return /* @__PURE__ */ jsxs("nav", {
2737
+ "data-slot": "table-pagination",
2738
+ "aria-label": text.pagination,
2739
+ className: "flex min-h-12 flex-wrap items-center justify-between gap-x-3 gap-y-1 border-t border-border px-4 py-1 text-xs text-fg-muted tabular-nums",
2740
+ children: [/* @__PURE__ */ jsx("output", { children: text.range(first, last, rowCount) }), /* @__PURE__ */ jsxs("span", {
2741
+ className: "flex items-center gap-2",
2742
+ children: [
2743
+ /* @__PURE__ */ jsx(Button, {
2744
+ icon: /* @__PURE__ */ jsx(ChevronLeft, { className: "rtl:rotate-180" }),
2745
+ "aria-label": text.previousPage,
2746
+ intent: "ghost",
2747
+ size: "sm",
2748
+ ripple: false,
2749
+ disabled: !canGoBack,
2750
+ onClick: () => onPageChange(pageIndex - 1)
2751
+ }),
2752
+ /* @__PURE__ */ jsx("span", { children: count === 0 ? "—" : text.page(pageIndex + 1, count) }),
2753
+ /* @__PURE__ */ jsx(Button, {
2754
+ icon: /* @__PURE__ */ jsx(ChevronRight, { className: "rtl:rotate-180" }),
2755
+ "aria-label": text.nextPage,
2756
+ intent: "ghost",
2757
+ size: "sm",
2758
+ ripple: false,
2759
+ disabled: !canGoForward,
2760
+ onClick: () => onPageChange(pageIndex + 1)
2761
+ })
2762
+ ]
2763
+ })]
2764
+ });
2765
+ }
2766
+ //#endregion
2451
2767
  //#region src/components/tabs/tab-nav.tsx
2452
2768
  const TabNavContext = createContext(null);
2453
2769
  /**
@@ -3402,7 +3718,7 @@ function ToastCard({ record, layout, total, expanded, paused, frontHeight, ownHe
3402
3718
  onPointerMove: handlePointerMove,
3403
3719
  onPointerUp: (event) => endDrag(event, false),
3404
3720
  onPointerCancel: (event) => endDrag(event, true),
3405
- className: cn("group/toast absolute inset-x-0 rounded-lg outline-none select-none", edge === "bottom" ? "bottom-0 origin-top" : "top-0 origin-bottom", "transform-[translateY(var(--toast-y))_scale(var(--toast-scale))]", "[translate:var(--toast-swipe-x,0px)_var(--toast-swipe-y,0px)]", "transition-[transform,translate,scale,opacity] duration-350 ease-[cubic-bezier(0.25,0.75,0.6,0.98)]", enterFrom[edge], "starting:opacity-0", "after:absolute after:inset-x-0 after:h-3.75", edge === "bottom" ? "after:bottom-full" : "after:top-full", "data-[visible=false]:pointer-events-none data-[visible=false]:opacity-0", "data-removed:pointer-events-none data-removed:scale-99 data-removed:opacity-0 data-removed:duration-150", "data-removed:data-swipe-out:duration-200 data-removed:data-swipe-out:ease-out", "data-[swipe-out=right]:[translate:calc(100%+24px)_0]", "data-[swipe-out=left]:[translate:calc(-100%-24px)_0]", "data-[swipe-out=bottom]:[translate:0_calc(100%+24px)]", "data-[swipe-out=top]:[translate:0_calc(-100%-24px)]", "data-swiping:transition-none", "group-data-moving/viewport:data-entered:transition-none", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus", touchAction),
3721
+ className: cn("group/toast absolute inset-x-0 rounded-xl outline-none select-none", edge === "bottom" ? "bottom-0 origin-top" : "top-0 origin-bottom", "transform-[translateY(var(--toast-y))_scale(var(--toast-scale))]", "[translate:var(--toast-swipe-x,0px)_var(--toast-swipe-y,0px)]", "transition-[transform,translate,scale,opacity] duration-350 ease-[cubic-bezier(0.25,0.75,0.6,0.98)]", enterFrom[edge], "starting:opacity-0", "after:absolute after:inset-x-0 after:h-3.75", edge === "bottom" ? "after:bottom-full" : "after:top-full", "data-[visible=false]:pointer-events-none data-[visible=false]:opacity-0", "data-removed:pointer-events-none data-removed:scale-99 data-removed:opacity-0 data-removed:duration-150", "data-removed:data-swipe-out:duration-200 data-removed:data-swipe-out:ease-out", "data-[swipe-out=right]:[translate:calc(100%+24px)_0]", "data-[swipe-out=left]:[translate:calc(-100%-24px)_0]", "data-[swipe-out=bottom]:[translate:0_calc(100%+24px)]", "data-[swipe-out=top]:[translate:0_calc(-100%-24px)]", "data-swiping:transition-none", "group-data-moving/viewport:data-entered:transition-none", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus", touchAction),
3406
3722
  children: /* @__PURE__ */ jsx("div", {
3407
3723
  "data-slot": "toast-card",
3408
3724
  style: { height },
@@ -3459,4 +3775,4 @@ function ToastCard({ record, layout, total, expanded, paused, frontHeight, ownHe
3459
3775
  });
3460
3776
  }
3461
3777
  //#endregion
3462
- export { Badge, Button, Card, CardContent, CardHeader, Checkbox, CheckboxGroup, CopyInput, Dialog, DialogBody, DialogFooter, DialogHeader, Drawer, DrawerBody, DrawerClose, DrawerFooter, DrawerHeader, Input, Meter, PasswordInput, SearchInput, Select, Sidebar, SidebarBadge, SidebarBody, SidebarFooter, SidebarGroup, SidebarHeader, SidebarIcon, SidebarItem, SidebarProvider, SidebarTrigger, Switch, Tab, TabList, TabNav, TabNavLink, TabPanel, Tabs, ThemeSwitcher, Toaster, Tooltip, cn, toast, useTheme };
3778
+ export { Alert, Badge, Button, Card, CardContent, CardHeader, Checkbox, CheckboxGroup, CopyInput, Dialog, DialogBody, DialogFooter, DialogHeader, Drawer, DrawerBody, DrawerClose, DrawerFooter, DrawerHeader, Input, Meter, PasswordInput, SearchInput, Select, Sidebar, SidebarBadge, SidebarBody, SidebarFooter, SidebarGroup, SidebarHeader, SidebarIcon, SidebarItem, SidebarProvider, SidebarTrigger, Switch, Tab, TabList, TabNav, TabNavLink, TabPanel, Table, Tabs, ThemeSwitcher, Toaster, Tooltip, cn, toast, useTheme };