@camunda/design-system 0.59.0 → 0.61.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.
Files changed (108) hide show
  1. package/dist/carbon-compat/filterable-multi-select.d.ts.map +1 -1
  2. package/dist/carbon-compat/filterable-multi-select.js +6 -1
  3. package/dist/carbon-compat/filterable-multi-select.js.map +1 -1
  4. package/dist/carbon-compat/multi-select.d.ts.map +1 -1
  5. package/dist/carbon-compat/multi-select.js +5 -1
  6. package/dist/carbon-compat/multi-select.js.map +1 -1
  7. package/dist/src/components/ui/alert-dialog.d.ts +11 -1
  8. package/dist/src/components/ui/alert-dialog.d.ts.map +1 -1
  9. package/dist/src/components/ui/alert-dialog.js +5 -4
  10. package/dist/src/components/ui/alert-dialog.js.map +1 -1
  11. package/dist/src/components/ui/alert.d.ts +1 -1
  12. package/dist/src/components/ui/alert.d.ts.map +1 -1
  13. package/dist/src/components/ui/alert.js +3 -1
  14. package/dist/src/components/ui/alert.js.map +1 -1
  15. package/dist/src/components/ui/app-sidebar.d.ts.map +1 -1
  16. package/dist/src/components/ui/app-sidebar.js +57 -16
  17. package/dist/src/components/ui/app-sidebar.js.map +1 -1
  18. package/dist/src/components/ui/card.d.ts.map +1 -1
  19. package/dist/src/components/ui/card.js +15 -1
  20. package/dist/src/components/ui/card.js.map +1 -1
  21. package/dist/src/components/ui/code-block.d.ts.map +1 -1
  22. package/dist/src/components/ui/code-block.js +1 -13
  23. package/dist/src/components/ui/code-block.js.map +1 -1
  24. package/dist/src/components/ui/combobox.d.ts +2 -2
  25. package/dist/src/components/ui/combobox.d.ts.map +1 -1
  26. package/dist/src/components/ui/combobox.js +68 -25
  27. package/dist/src/components/ui/combobox.js.map +1 -1
  28. package/dist/src/components/ui/date-range-picker.d.ts.map +1 -1
  29. package/dist/src/components/ui/date-range-picker.js +20 -1
  30. package/dist/src/components/ui/date-range-picker.js.map +1 -1
  31. package/dist/src/components/ui/dialog.d.ts +18 -2
  32. package/dist/src/components/ui/dialog.d.ts.map +1 -1
  33. package/dist/src/components/ui/dialog.js +9 -6
  34. package/dist/src/components/ui/dialog.js.map +1 -1
  35. package/dist/src/components/ui/file-uploader.d.ts.map +1 -1
  36. package/dist/src/components/ui/file-uploader.js +21 -2
  37. package/dist/src/components/ui/file-uploader.js.map +1 -1
  38. package/dist/src/components/ui/form-error-summary.d.ts +13 -0
  39. package/dist/src/components/ui/form-error-summary.d.ts.map +1 -0
  40. package/dist/src/components/ui/form-error-summary.js +53 -0
  41. package/dist/src/components/ui/form-error-summary.js.map +1 -0
  42. package/dist/src/components/ui/inline-edit.d.ts.map +1 -1
  43. package/dist/src/components/ui/inline-edit.js +14 -1
  44. package/dist/src/components/ui/inline-edit.js.map +1 -1
  45. package/dist/src/components/ui/multi-select.d.ts +7 -0
  46. package/dist/src/components/ui/multi-select.d.ts.map +1 -1
  47. package/dist/src/components/ui/multi-select.js +79 -27
  48. package/dist/src/components/ui/multi-select.js.map +1 -1
  49. package/dist/src/components/ui/multi-step-dialog.d.ts +11 -1
  50. package/dist/src/components/ui/multi-step-dialog.d.ts.map +1 -1
  51. package/dist/src/components/ui/multi-step-dialog.js +32 -4
  52. package/dist/src/components/ui/multi-step-dialog.js.map +1 -1
  53. package/dist/src/components/ui/notifications.d.ts +14 -1
  54. package/dist/src/components/ui/notifications.d.ts.map +1 -1
  55. package/dist/src/components/ui/notifications.js +17 -6
  56. package/dist/src/components/ui/notifications.js.map +1 -1
  57. package/dist/src/components/ui/overflow-strip.d.ts +18 -0
  58. package/dist/src/components/ui/overflow-strip.d.ts.map +1 -0
  59. package/dist/src/components/ui/overflow-strip.js +103 -0
  60. package/dist/src/components/ui/overflow-strip.js.map +1 -0
  61. package/dist/src/components/ui/scorecard.d.ts.map +1 -1
  62. package/dist/src/components/ui/scorecard.js +20 -1
  63. package/dist/src/components/ui/scorecard.js.map +1 -1
  64. package/dist/src/components/ui/select.d.ts +2 -2
  65. package/dist/src/components/ui/select.d.ts.map +1 -1
  66. package/dist/src/components/ui/select.js +123 -6
  67. package/dist/src/components/ui/select.js.map +1 -1
  68. package/dist/src/components/ui/tabs.d.ts +2 -1
  69. package/dist/src/components/ui/tabs.d.ts.map +1 -1
  70. package/dist/src/components/ui/tabs.js +16 -4
  71. package/dist/src/components/ui/tabs.js.map +1 -1
  72. package/dist/src/components/ui/toast.d.ts +4 -3
  73. package/dist/src/components/ui/toast.d.ts.map +1 -1
  74. package/dist/src/components/ui/toast.js +209 -23
  75. package/dist/src/components/ui/toast.js.map +1 -1
  76. package/dist/src/components/ui/toggle-group.d.ts +7 -1
  77. package/dist/src/components/ui/toggle-group.d.ts.map +1 -1
  78. package/dist/src/components/ui/toggle-group.js +23 -4
  79. package/dist/src/components/ui/toggle-group.js.map +1 -1
  80. package/dist/src/components/ui/tree-view.d.ts.map +1 -1
  81. package/dist/src/components/ui/tree-view.js +61 -45
  82. package/dist/src/components/ui/tree-view.js.map +1 -1
  83. package/dist/src/hooks/use-is-truncated.d.ts +9 -5
  84. package/dist/src/hooks/use-is-truncated.d.ts.map +1 -1
  85. package/dist/src/hooks/use-is-truncated.js +20 -7
  86. package/dist/src/hooks/use-is-truncated.js.map +1 -1
  87. package/dist/src/index.d.ts +2 -0
  88. package/dist/src/index.d.ts.map +1 -1
  89. package/dist/src/index.js +2 -0
  90. package/dist/src/index.js.map +1 -1
  91. package/dist/src/lib/focus-visible-on-close.d.ts +28 -0
  92. package/dist/src/lib/focus-visible-on-close.d.ts.map +1 -1
  93. package/dist/src/lib/focus-visible-on-close.js +54 -1
  94. package/dist/src/lib/focus-visible-on-close.js.map +1 -1
  95. package/dist/src/lib/i18n/dictionary.d.ts +5 -0
  96. package/dist/src/lib/i18n/dictionary.d.ts.map +1 -1
  97. package/dist/src/lib/i18n/dictionary.js +5 -0
  98. package/dist/src/lib/i18n/dictionary.js.map +1 -1
  99. package/dist/src/lib/merge-refs.d.ts +8 -0
  100. package/dist/src/lib/merge-refs.d.ts.map +1 -0
  101. package/dist/src/lib/merge-refs.js +15 -0
  102. package/dist/src/lib/merge-refs.js.map +1 -0
  103. package/dist/src/lib/with-ref.d.ts +3 -1
  104. package/dist/src/lib/with-ref.d.ts.map +1 -1
  105. package/dist/src/lib/with-ref.js +0 -10
  106. package/dist/src/lib/with-ref.js.map +1 -1
  107. package/dist/styles.css +68 -6
  108. package/package.json +2 -1
@@ -4,18 +4,59 @@ import * as React from "react";
4
4
  import { Select as SelectPrimitive } from "radix-ui";
5
5
  import { cn } from "../../lib/utils.js";
6
6
  import { composeCloseAutoFocus, useDialogFocusReturn, } from "../../lib/focus-visible-on-close.js";
7
+ import { useIsTruncated } from "../../hooks/use-is-truncated.js";
7
8
  import { C4Provider } from "./c4-provider.js";
8
9
  import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "../../icons/lucide.js";
10
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
11
+ // No existing ref-merge utility in this package (single-consumer need so
12
+ // far, same reasoning as `code-block.tsx`'s own copy): the forwarded `ref`
13
+ // (an external consumer's, if passed via `...props` — SelectTrigger doesn't
14
+ // destructure it today) and the internal ref this file needs to read the
15
+ // rendered `[data-slot="select-value"]` node both have to land on the same
16
+ // `SelectPrimitive.Trigger` DOM node.
17
+ function mergeRefs(a, b) {
18
+ return (node) => {
19
+ if (typeof a === "function")
20
+ a(node);
21
+ else if (a)
22
+ a.current = node;
23
+ b.current = node;
24
+ };
25
+ }
9
26
  function Select({ ...props }) {
10
27
  return _jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
11
28
  }
12
29
  function SelectGroup({ ...props }) {
13
30
  return _jsx(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
14
31
  }
15
- function SelectValue({ ...props }) {
16
- return _jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
32
+ function SelectValue({ children, ...props }) {
33
+ // Radix's `Select.Value` destructures `className`/`style` out of props and
34
+ // never forwards them to the rendered node (see
35
+ // `@radix-ui/react-select`'s own `SelectValue` implementation) — so styling
36
+ // this node's own display/truncation can't be done via a `className` prop
37
+ // on it directly, no matter how it's computed here. `data-*` attributes
38
+ // aren't stripped, though: they land in Radix's own `...valueProps` spread
39
+ // and reach the DOM, so `SelectTrigger`'s className reaches this node via
40
+ // a `[data-slot=select-value]` DESCENDANT selector (not the `*:` direct-
41
+ // child variant the previous, broken attempt used — this node isn't
42
+ // always a direct child of the trigger; see the icon+value composition in
43
+ // `filter-bar.stories.tsx`, which nests `SelectValue` inside a consumer
44
+ // span). `data-has-children` distinguishes the two layouts that selector
45
+ // needs to produce: plain `truncate` when Radix auto-renders the selected
46
+ // item's text (no `children` passed here — the common case, and the only
47
+ // one any consumer in this repo actually uses), or `flex` when a consumer
48
+ // passes its own `children` instead of relying on that auto-text.
49
+ //
50
+ // Radix's own `hasChildren` (`children !== void 0`) gates whether it
51
+ // auto-renders the selected item's text at all: passing this component
52
+ // *any* non-undefined `children` — even conditionally, even `null` — would
53
+ // suppress that auto-text for every consumer that doesn't. So this only
54
+ // ever wraps `children` when the consumer actually supplied some; it never
55
+ // passes an empty wrapper through in the common case.
56
+ const hasChildren = children !== undefined;
57
+ return (_jsx(SelectPrimitive.Value, { "data-slot": "select-value", "data-has-children": hasChildren ? "" : undefined, ...props, children: hasChildren ? (_jsx("span", { "data-slot": "select-value-text", className: "min-w-0 truncate", children: children })) : undefined }));
17
58
  }
18
- function SelectTrigger({ className, size = "default", children, id, invalidText, helperText, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, "aria-errormessage": ariaErrorMessage, ...props }) {
59
+ function SelectTrigger({ className, size = "default", children, id, invalidText, helperText, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, "aria-errormessage": ariaErrorMessage, ref, onPointerEnter, onFocus, ...props }) {
19
60
  const generatedId = React.useId();
20
61
  const resolvedId = id ?? generatedId;
21
62
  const isInvalid = ariaInvalid === true || ariaInvalid === "true";
@@ -26,13 +67,89 @@ function SelectTrigger({ className, size = "default", children, id, invalidText,
26
67
  const errorMessageId = ariaErrorMessage ?? errorId;
27
68
  const describedBy = [errorId, helperId, ariaDescribedBy].filter(Boolean).join(" ") || undefined;
28
69
  const hasMessage = showInvalidText || showHelperText;
29
- const triggerEl = (_jsxs(SelectPrimitive.Trigger, { id: resolvedId, "data-slot": "select-trigger", "data-size": size, "aria-invalid": ariaInvalid, "aria-errormessage": errorMessageId, "aria-describedby": describedBy, className: cn("flex w-fit min-w-0 items-center justify-between gap-2 rounded-lg border border-input bg-input-background px-3 py-2 text-sm whitespace-nowrap transition-all duration-200 outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/20 dark:focus-visible:ring-ring/40 data-[focus-visible-restore]:border-ring data-[focus-visible-restore]:ring-3 data-[focus-visible-restore]:ring-ring/20 dark:data-[focus-visible-restore]:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger-foreground-subtle aria-invalid:ring-3 aria-invalid:ring-danger-foreground-subtle/20 data-placeholder:text-neutral-foreground-subtle data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:hover:bg-neutral-background-medium dark:aria-invalid:ring-danger-foreground-subtle/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDownIcon, { className: "pointer-events-none size-4 opacity-50" }) })] }));
70
+ // `SelectValue`'s content is opaque to `SelectTrigger` — it's rendered as
71
+ // `children`, an arbitrary consumer-authored subtree — so unlike the other
72
+ // 3 truncation-reveal sites there is no JSX ref to attach directly to the
73
+ // node the truncation utility clips (`data-slot="select-value"`, or its
74
+ // inner `data-slot="select-value-text"` span when `SelectValue` was given
75
+ // `children` — see the `[data-slot=select-value]` descendant selectors in
76
+ // this trigger's className below). `triggerRef` reads the rendered DOM
77
+ // instead: an ADDITIONAL internal ref alongside any consumer `ref` (merged
78
+ // via `mergeRefs`, not a replacement — `props` may still carry a consumer
79
+ // ref since it's not destructured above).
80
+ const triggerRef = React.useRef(null);
81
+ const mergedRef = React.useMemo(() => mergeRefs(ref, triggerRef), [ref, triggerRef]);
82
+ const { ref: valueRef, isTruncated, measure } = useIsTruncated();
83
+ const [tooltipText, setTooltipText] = React.useState("");
84
+ // Every commit, not just on a `children` change: which node currently
85
+ // carries `data-slot="select-value"`, and the room the trigger has, can
86
+ // both change with no reference-identity change on `children` to key on
87
+ // (e.g. picking a different option re-renders `SelectValue` under the same
88
+ // trigger). See "Truncated Text" in `docs/specs/shadcn/patterns.md`. No
89
+ // deps array is intentional (same reasoning `nav-breadcrumb.tsx` documents
90
+ // for its own equivalent effect) — the lint rule flags the direct
91
+ // `setTooltipText` call as a possible infinite-update chain, but `useState`
92
+ // bails out via `Object.is` when the computed text is unchanged, same as
93
+ // `measure()`'s own `setIsTruncated` call one layer down (which the rule
94
+ // can't see into, and so doesn't flag).
95
+ // eslint-disable-next-line react-hooks/exhaustive-deps
96
+ React.useLayoutEffect(() => {
97
+ // Prefer the inner `select-value-text` span — present only when
98
+ // `SelectValue` was given `children` — over the outer `select-value`
99
+ // node itself: that outer node is `flex` in that case (to lay out
100
+ // `children` alongside other content), and measuring `scrollWidth` /
101
+ // `clientWidth` on a flex container doesn't reflect text clipping the
102
+ // way it does on the actual `truncate`d node. See `select.tsx`'s
103
+ // `SelectValue` for why the split exists at all.
104
+ const valueEl = triggerRef.current?.querySelector('[data-slot="select-value-text"]') ??
105
+ triggerRef.current?.querySelector('[data-slot="select-value"]');
106
+ valueRef.current = valueEl ?? null;
107
+ measure();
108
+ setTooltipText(valueEl?.textContent ?? "");
109
+ });
110
+ const triggerEl = (_jsxs(SelectPrimitive.Trigger, { ref: mergedRef, id: resolvedId, "data-slot": "select-trigger", "data-size": size, "aria-invalid": ariaInvalid, "aria-errormessage": errorMessageId, "aria-describedby": describedBy,
111
+ // Composed rather than clobbered: `props` may still carry a consumer
112
+ // handler (only `ref` is destructured above, not these two), and
113
+ // `{...props}` spreads AFTER this element's own attributes — the
114
+ // opposite order from `combobox.tsx`, so the risk here is a consumer
115
+ // handler silently winning over `measure()`, not the other way round.
116
+ onPointerEnter: (e) => {
117
+ onPointerEnter?.(e);
118
+ measure();
119
+ }, onFocus: (e) => {
120
+ onFocus?.(e);
121
+ measure();
122
+ }, className: cn("flex w-fit min-w-0 items-center justify-between gap-2 rounded-lg border border-input bg-input-background px-3 py-2 text-sm whitespace-nowrap transition-all duration-200 outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/20 dark:focus-visible:ring-ring/40 data-[focus-visible-restore]:border-ring data-[focus-visible-restore]:ring-3 data-[focus-visible-restore]:ring-ring/20 dark:data-[focus-visible-restore]:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger-foreground-subtle aria-invalid:ring-3 aria-invalid:ring-danger-foreground-subtle/20 data-placeholder:text-neutral-foreground-subtle data-[size=default]:h-9 data-[size=sm]:h-8 [&_[data-slot=select-value]]:min-w-0 [&_[data-slot=select-value]:not([data-has-children])]:truncate [&_[data-slot=select-value][data-has-children]]:flex [&_[data-slot=select-value][data-has-children]]:items-center [&_[data-slot=select-value][data-has-children]]:gap-1.5 dark:hover:bg-neutral-background-medium dark:aria-invalid:ring-danger-foreground-subtle/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDownIcon, { className: "pointer-events-none size-4 opacity-50" }) })] }));
123
+ // DEVIATES from the other 3 truncation-reveal sites (and from
124
+ // `nav-breadcrumb.tsx`'s reference pattern), and empirically so — not by
125
+ // assumption: `Tooltip`/`TooltipTrigger` are mounted UNCONDITIONALLY here
126
+ // (only `TooltipContent` is conditional on `isTruncated`), instead of
127
+ // conditionally mounting the whole `Tooltip` subtree. Conditionally
128
+ // mounting the whole subtree was tried first and measurably broken —
129
+ // toggling `isTruncated` changes the JSX shape at `SelectPrimitive.Trigger`'s
130
+ // own tree position (bare element vs. wrapped in `Tooltip`), which makes
131
+ // React unmount and remount it, and with it Radix Select's own internal
132
+ // `SelectValue` registration. The remounted value node measures 0×0 on the
133
+ // commit right after the remount (confirmed with a throwaway console probe:
134
+ // `onPointerEnter`'s `measure()` read the correct 260×110 and set
135
+ // `isTruncated` true; the very next commit's layout effect then read the
136
+ // SAME query on the freshly-remounted node as 0×0 and flipped it back to
137
+ // false), so the tooltip opened and immediately closed on every hover
138
+ // instead of staying open — a real correctness bug, not a style
139
+ // preference. `SelectPrimitive.Trigger` needs a permanently stable tree
140
+ // position for its internal state to survive a truncation toggle; the
141
+ // other 3 sites don't have that constraint; the accepted cost versus
142
+ // `nav-breadcrumb.tsx`'s document (an unconditional `Tooltip` still runs
143
+ // Radix's open-request handling and touches `TooltipProvider`'s
144
+ // delay-skip state on every hover of a SHORT value too) is real but minor
145
+ // next to a tooltip that cannot stay open.
146
+ const wrappedTriggerEl = (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: triggerEl }), isTruncated ? _jsx(TooltipContent, { children: tooltipText }) : null] }));
30
147
  if (!hasMessage) {
31
- return triggerEl;
148
+ return wrappedTriggerEl;
32
149
  }
33
150
  // `w-fit` here would make a `width: 100%` trigger circular against its own
34
151
  // shrink-to-fit parent, silently dropping a `w-full` className override.
35
- return (_jsxs("div", { className: "flex w-full flex-col gap-1.5", children: [triggerEl, showInvalidText ? (_jsx("span", { id: errorId, className: "text-xs text-danger-foreground-subtle", children: invalidText })) : null, showHelperText ? (_jsx("span", { id: helperId, className: "text-xs text-neutral-foreground-subtle", children: helperText })) : null] }));
152
+ return (_jsxs("div", { className: "flex w-full flex-col gap-1.5", children: [wrappedTriggerEl, showInvalidText ? (_jsx("span", { id: errorId, className: "text-xs text-danger-foreground-subtle", children: invalidText })) : null, showHelperText ? (_jsx("span", { id: helperId, className: "text-xs text-neutral-foreground-subtle", children: helperText })) : null] }));
36
153
  }
37
154
  function SelectContent({ className, children, position = "popper", onCloseAutoFocus, restoreFocusRef, ...props }) {
38
155
  const dialogFocusReturn = useDialogFocusReturn(restoreFocusRef);
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../src/components/ui/select.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../src/components/ui/select.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,UAAU,CAAC;AAErD,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAC/B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEpE,yEAAyE;AACzE,2EAA2E;AAC3E,4EAA4E;AAC5E,yEAAyE;AACzE,2EAA2E;AAC3E,sCAAsC;AACtC,SAAS,SAAS,CAChB,CAA2B,EAC3B,CAA4B;IAE5B,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,IAAI,OAAO,CAAC,KAAK,UAAU;YAAE,CAAC,CAAC,IAAI,CAAC,CAAC;aAChC,IAAI,CAAC;YAAG,CAA+B,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5D,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,EACd,GAAG,KAAK,EAC0C;IAClD,OAAO,KAAC,eAAe,CAAC,IAAI,iBAAW,QAAQ,KAAK,KAAK,GAAI,CAAC;AAChE,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EAC2C;IACnD,OAAO,KAAC,eAAe,CAAC,KAAK,iBAAW,cAAc,KAAK,KAAK,GAAI,CAAC;AACvE,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,QAAQ,EACR,GAAG,KAAK,EAC2C;IACnD,2EAA2E;IAC3E,gDAAgD;IAChD,4EAA4E;IAC5E,0EAA0E;IAC1E,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,yEAAyE;IACzE,oEAAoE;IACpE,0EAA0E;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,kEAAkE;IAClE,EAAE;IACF,qEAAqE;IACrE,uEAAuE;IACvE,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,sDAAsD;IACtD,MAAM,WAAW,GAAG,QAAQ,KAAK,SAAS,CAAC;IAC3C,OAAO,CACL,KAAC,eAAe,CAAC,KAAK,iBACV,cAAc,uBACL,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAC3C,KAAK,YAER,WAAW,CAAC,CAAC,CAAC,CACb,4BAAgB,mBAAmB,EAAC,SAAS,EAAC,kBAAkB,YAC7D,QAAQ,GACJ,CACR,CAAC,CAAC,CAAC,SAAS,GACS,CACzB,CAAC;AACJ,CAAC;AAYD,SAAS,aAAa,CAAC,EACrB,SAAS,EACT,IAAI,GAAG,SAAS,EAChB,QAAQ,EACR,EAAE,EACF,WAAW,EACX,UAAU,EACV,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,mBAAmB,EAAE,gBAAgB,EACrC,GAAG,EACH,cAAc,EACd,OAAO,EACP,GAAG,KAAK,EACW;IACnB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,EAAE,IAAI,WAAW,CAAC;IACrC,MAAM,SAAS,GAAG,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,MAAM,CAAC;IACjE,MAAM,eAAe,GAAG,SAAS,IAAI,WAAW,KAAK,SAAS,CAAC;IAC/D,MAAM,cAAc,GAAG,CAAC,SAAS,IAAI,UAAU,KAAK,SAAS,CAAC;IAC9D,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,UAAU,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,UAAU,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,cAAc,GAAG,gBAAgB,IAAI,OAAO,CAAC;IACnD,MAAM,WAAW,GACf,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAE9E,MAAM,UAAU,GAAG,eAAe,IAAI,cAAc,CAAC;IAErD,0EAA0E;IAC1E,2EAA2E;IAC3E,0EAA0E;IAC1E,wEAAwE;IACxE,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,2EAA2E;IAC3E,0EAA0E;IAC1E,0CAA0C;IAC1C,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAoB,IAAI,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAC7B,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,EAChC,CAAC,GAAG,EAAE,UAAU,CAAC,CAClB,CAAC;IACF,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,cAAc,EAAe,CAAC;IAC9E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEzD,sEAAsE;IACtE,wEAAwE;IACxE,wEAAwE;IACxE,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,kEAAkE;IAClE,4EAA4E;IAC5E,yEAAyE;IACzE,yEAAyE;IACzE,wCAAwC;IACxC,uDAAuD;IACvD,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE;QACzB,gEAAgE;QAChE,qEAAqE;QACrE,kEAAkE;QAClE,qEAAqE;QACrE,sEAAsE;QACtE,iEAAiE;QACjE,iDAAiD;QACjD,MAAM,OAAO,GACX,UAAU,CAAC,OAAO,EAAE,aAAa,CAC/B,iCAAiC,CAClC;YACD,UAAU,CAAC,OAAO,EAAE,aAAa,CAC/B,4BAA4B,CAC7B,CAAC;QACJ,QAAQ,CAAC,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC;QACnC,OAAO,EAAE,CAAC;QACV,cAAc,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,CAChB,MAAC,eAAe,CAAC,OAAO,IACtB,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,UAAU,eACJ,gBAAgB,eACf,IAAI,kBACD,WAAW,uBACN,cAAc,sBACf,WAAW;QAC7B,qEAAqE;QACrE,iEAAiE;QACjE,iEAAiE;QACjE,qEAAqE;QACrE,sEAAsE;QACtE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;YACpB,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,EACD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACb,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACb,OAAO,EAAE,CAAC;QACZ,CAAC,EACD,SAAS,EAAE,EAAE,CACX,woCAAwoC,EACxoC,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,eAAe,CAAC,IAAI,IAAC,OAAO,kBAC3B,KAAC,eAAe,IAAC,SAAS,EAAC,uCAAuC,GAAG,GAChD,IACC,CAC3B,CAAC;IAEF,8DAA8D;IAC9D,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,oEAAoE;IACpE,qEAAqE;IACrE,8EAA8E;IAC9E,yEAAyE;IACzE,wEAAwE;IACxE,2EAA2E;IAC3E,4EAA4E;IAC5E,kEAAkE;IAClE,yEAAyE;IACzE,yEAAyE;IACzE,sEAAsE;IACtE,gEAAgE;IAChE,wEAAwE;IACxE,sEAAsE;IACtE,qEAAqE;IACrE,yEAAyE;IACzE,gEAAgE;IAChE,0EAA0E;IAC1E,2CAA2C;IAC3C,MAAM,gBAAgB,GAAG,CACvB,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBAAE,SAAS,GAAkB,EACnD,WAAW,CAAC,CAAC,CAAC,KAAC,cAAc,cAAE,WAAW,GAAkB,CAAC,CAAC,CAAC,IAAI,IAC5D,CACX,CAAC;IAEF,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,2EAA2E;IAC3E,yEAAyE;IACzE,OAAO,CACL,eAAK,SAAS,EAAC,8BAA8B,aAC1C,gBAAgB,EAChB,eAAe,CAAC,CAAC,CAAC,CACjB,eAAM,EAAE,EAAE,OAAO,EAAE,SAAS,EAAC,uCAAuC,YACjE,WAAW,GACP,CACR,CAAC,CAAC,CAAC,IAAI,EACP,cAAc,CAAC,CAAC,CAAC,CAChB,eAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAC,wCAAwC,YACnE,UAAU,GACN,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,QAAQ,GAAG,QAAQ,EACnB,gBAAgB,EAChB,eAAe,EACf,GAAG,KAAK,EAUT;IACC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,eAAe,CAAC,CAAC;IAChE,OAAO,CACL,KAAC,eAAe,CAAC,MAAM,cACrB,KAAC,UAAU,cACT,MAAC,eAAe,CAAC,OAAO,iBACZ,gBAAgB;gBAC1B,gEAAgE;gBAChE,iEAAiE;gBACjE,oDAAoD;gBACpD,oEAAoE;gBACpE,mDAAmD;gBACnD,gBAAgB,EAAE,qBAAqB,CACrC,gBAAgB,EAChB,iBAAiB,CAAC,gBAAgB,CACnC,EACD,SAAS,EAAE,EAAE,CACX,wgBAAwgB,EACxgB,QAAQ,KAAK,QAAQ;oBACnB,iIAAiI,EACnI,SAAS,CACV,EACD,QAAQ,EAAE,QAAQ,KACd,KAAK,aAET,KAAC,oBAAoB,KAAG,EACxB,KAAC,eAAe,CAAC,QAAQ,IACvB,SAAS,EAAE,EAAE,CACX,KAAK,EACL,QAAQ,KAAK,QAAQ;4BACnB,2FAA2F,CAC9F,YAEA,QAAQ,GACgB,EAC3B,KAAC,sBAAsB,KAAG,IACF,GACf,GACU,CAC1B,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EAC2C;IACnD,OAAO,CACL,KAAC,eAAe,CAAC,KAAK,iBACV,cAAc,EACxB,SAAS,EAAE,EAAE,CACX,oDAAoD,EACpD,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAC0C;IAClD,OAAO,CACL,MAAC,eAAe,CAAC,IAAI,iBACT,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,ygBAAygB,EACzgB,SAAS,CACV,KACG,KAAK,aAET,eAAM,SAAS,EAAC,4DAA4D,YAC1E,KAAC,eAAe,CAAC,aAAa,cAC5B,KAAC,SAAS,IAAC,SAAS,EAAC,oCAAoC,GAAG,GAC9B,GAC3B,EACP,KAAC,eAAe,CAAC,QAAQ,cAAE,QAAQ,GAA4B,IAC1C,CACxB,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EAC+C;IACvD,OAAO,CACL,KAAC,eAAe,CAAC,SAAS,iBACd,kBAAkB,EAC5B,SAAS,EAAE,EAAE,CAAC,+CAA+C,EAAE,SAAS,CAAC,KACrE,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACoD;IAC5D,OAAO,CACL,KAAC,eAAe,CAAC,cAAc,iBACnB,yBAAyB,EACnC,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,SAAS,CACV,KACG,KAAK,YAET,KAAC,aAAa,IAAC,SAAS,EAAC,QAAQ,GAAG,GACL,CAClC,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACsD;IAC9D,OAAO,CACL,KAAC,eAAe,CAAC,gBAAgB,iBACrB,2BAA2B,EACrC,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,SAAS,CACV,KACG,KAAK,YAET,KAAC,eAAe,IAAC,SAAS,EAAC,QAAQ,GAAG,GACL,CACpC,CAAC;AACJ,CAAC;AAED,OAAO,EACL,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,WAAW,GACZ,CAAC"}
@@ -5,7 +5,8 @@ declare function Tabs({ className, orientation, ...props }: React.ComponentProps
5
5
  declare const tabsListVariants: (props?: ({
6
6
  variant?: "line" | "default" | null | undefined;
7
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
- declare function TabsList({ className, variant, ...props }: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>): React.JSX.Element;
8
+ type TabsListProps = React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>;
9
+ declare const TabsList: React.ForwardRefExoticComponent<Omit<TabsListProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
9
10
  declare function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>): React.JSX.Element;
10
11
  declare function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>): React.JSX.Element;
11
12
  export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AAIjD,iBAAS,IAAI,CAAC,EACZ,SAAS,EACT,WAA0B,EAC1B,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,qBAYjD;AAED,QAAA,MAAM,gBAAgB;;8EAarB,CAAC;AAEF,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,OAAmB,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,GAChD,YAAY,CAAC,OAAO,gBAAgB,CAAC,qBAStC;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,qBAepD;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,qBAQpD;AAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AAOjD,iBAAS,IAAI,CAAC,EACZ,SAAS,EACT,WAA0B,EAC1B,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,qBAYjD;AAID,QAAA,MAAM,gBAAgB;;8EAarB,CAAC;AAEF,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,GAClE,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAkDxC,QAAA,MAAM,QAAQ,mGAAuD,CAAC;AAEtE,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,qBAepD;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,qBAQpD;AAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1,12 +1,17 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { Tabs as TabsPrimitive } from "radix-ui";
5
5
  import { cn } from "../../lib/utils.js";
6
+ import { withRef } from "../../lib/with-ref.js";
7
+ import { mergeRefs } from "../../lib/merge-refs.js";
8
+ import { OverflowStripArrow, useOverflowStrip } from "./overflow-strip.js";
6
9
  function Tabs({ className, orientation = "horizontal", ...props }) {
7
10
  return (_jsx(TabsPrimitive.Root, { "data-slot": "tabs", "data-orientation": orientation, className: cn("group/tabs flex gap-2 data-horizontal:flex-col", className), ...props }));
8
11
  }
9
- const tabsListVariants = cva("group/tabs-list inline-flex w-fit items-center justify-center gap-1 rounded-xl p-1 text-neutral-foreground-subtle group-data-horizontal/tabs:h-9 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none", {
12
+ // `justify-start`, not `center`: a centred flex row that overflows its scroll
13
+ // container hangs past the start edge where no scroll position can reach it.
14
+ const tabsListVariants = cva("group/tabs-list inline-flex w-fit items-center justify-start gap-1 rounded-xl p-1 text-neutral-foreground-subtle group-data-horizontal/tabs:h-9 group-data-horizontal/tabs:min-w-0 group-data-horizontal/tabs:max-w-full group-data-horizontal/tabs:overflow-x-auto group-data-horizontal/tabs:[scrollbar-width:none] group-data-horizontal/tabs:[&::-webkit-scrollbar]:hidden group-data-horizontal/tabs:motion-safe:scroll-smooth group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col group-data-vertical/tabs:overflow-visible data-[variant=line]:rounded-none", {
10
15
  variants: {
11
16
  variant: {
12
17
  default: "bg-neutral-background-medium",
@@ -17,9 +22,16 @@ const tabsListVariants = cva("group/tabs-list inline-flex w-fit items-center jus
17
22
  variant: "default",
18
23
  },
19
24
  });
20
- function TabsList({ className, variant = "default", ...props }) {
21
- return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list", "data-variant": variant, className: cn(tabsListVariants({ variant }), className), ...props }));
25
+ function TabsListImpl({ ref, className, variant = "default", ...props }) {
26
+ const { ref: scrollRef, hasMoreBefore, hasMoreAfter, scrollByStep, } = useOverflowStrip();
27
+ const listRef = React.useMemo(() => mergeRefs(ref, scrollRef), [ref, scrollRef]);
28
+ return (
29
+ // The arrows are siblings of the tablist inside this wrapper, never
30
+ // children of it — rendering them inside would count toward the tab
31
+ // total and break Radix's roving focus (Home/End, arrow-key wrap).
32
+ _jsxs("div", { "data-slot": "tabs-list-scroller", className: "flex min-w-0 max-w-full group-data-horizontal/tabs:items-center group-data-vertical/tabs:items-start", children: [hasMoreBefore && (_jsx(OverflowStripArrow, { direction: "before", onScroll: () => scrollByStep("before") })), _jsx(TabsPrimitive.List, { ref: listRef, "data-slot": "tabs-list", "data-variant": variant, className: cn(tabsListVariants({ variant }), className), ...props }), hasMoreAfter && (_jsx(OverflowStripArrow, { direction: "after", onScroll: () => scrollByStep("after") }))] }));
22
33
  }
34
+ const TabsList = withRef(TabsListImpl);
23
35
  function TabsTrigger({ className, ...props }) {
24
36
  return (_jsx(TabsPrimitive.Trigger, { "data-slot": "tabs-trigger", className: cn("relative inline-flex h-[calc(100%-2px)] flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-lg border border-transparent px-3 py-1 text-sm font-medium whitespace-nowrap text-neutral-foreground-strong transition-all duration-200 group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 dark:text-neutral-foreground-subtle group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", "not-data-active:hover:bg-neutral-background-strong", "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent", "data-active:bg-neutral-background-subtle data-active:text-neutral-foreground-strong dark:data-active:border-input dark:data-active:text-neutral-foreground-strong", "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100", className), ...props }));
25
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../../../src/components/ui/tabs.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAE/B,SAAS,IAAI,CAAC,EACZ,SAAS,EACT,WAAW,GAAG,YAAY,EAC1B,GAAG,KAAK,EACwC;IAChD,OAAO,CACL,KAAC,aAAa,CAAC,IAAI,iBACP,MAAM,sBACE,WAAW,EAC7B,SAAS,EAAE,EAAE,CACX,gDAAgD,EAChD,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,MAAM,gBAAgB,GAAG,GAAG,CAC1B,oPAAoP,EACpP;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,8BAA8B;YACvC,IAAI,EAAE,sBAAsB;SAC7B;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;KACnB;CACF,CACF,CAAC;AAEF,SAAS,QAAQ,CAAC,EAChB,SAAS,EACT,OAAO,GAAG,SAAS,EACnB,GAAG,KAAK,EAE6B;IACrC,OAAO,CACL,KAAC,aAAa,CAAC,IAAI,iBACP,WAAW,kBACP,OAAO,EACrB,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,KACnD,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EAC2C;IACnD,OAAO,CACL,KAAC,aAAa,CAAC,OAAO,iBACV,cAAc,EACxB,SAAS,EAAE,EAAE,CACX,ouBAAouB,EACpuB,oDAAoD,EACpD,+PAA+P,EAC/P,mKAAmK,EACnK,sYAAsY,EACtY,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EAC2C;IACnD,OAAO,CACL,KAAC,aAAa,CAAC,OAAO,iBACV,cAAc,EACxB,SAAS,EAAE,EAAE,CAAC,6BAA6B,EAAE,SAAS,CAAC,KACnD,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../../../src/components/ui/tabs.tsx"],"names":[],"mappings":"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"}
@@ -43,9 +43,10 @@ type ToastFn = {
43
43
  declare function Toaster({ position, dismissLabel }: ToasterProps): React.JSX.Element;
44
44
  /**
45
45
  * The callable used everywhere else — never sonner's own `toast` re-exported directly.
46
- * `options.duration` resolution uses `??`, not `||`: sonner treats a literal
47
- * `duration: 0` as falsy and silently falls back to its own ~4s default (verified in
48
- * source) — `??` is required so an explicit `0` isn't confused with "not passed".
46
+ * `options.duration` resolution (inside `toExternalToast`) uses `??`, not `||`: sonner
47
+ * treats a literal `duration: 0` as falsy and silently falls back to its own ~4s default
48
+ * (verified in source) — `??` is required so an explicit `0` isn't confused with "not
49
+ * passed".
49
50
  */
50
51
  declare const toast: ToastFn;
51
52
  export { Toaster, toast };
@@ -1 +1 @@
1
- {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAuB/B,KAAK,aAAa,GACd,UAAU,GACV,WAAW,GACX,YAAY,GACZ,aAAa,GACb,cAAc,GACd,eAAe,CAAC;AAEpB,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAE1D,KAAK,YAAY,GAAG;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,mBAAmB,CAAC,CAAC,IAAI;IAC5B,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAC1D,KAAK,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;CAChE,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;IACpE,OAAO,EAAE,CACP,OAAO,EAAE,KAAK,CAAC,SAAS,EACxB,OAAO,CAAC,EAAE,YAAY,KACnB,MAAM,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,GAAG,MAAM,CAAC;IAC5E,OAAO,EAAE,CACP,OAAO,EAAE,KAAK,CAAC,SAAS,EACxB,OAAO,CAAC,EAAE,YAAY,KACnB,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,GAAG,MAAM,CAAC;IAC7E,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAC3E,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;CACzC,CAAC;AAyMF;;;;;;;GAOG;AACH,iBAAS,OAAO,CAAC,EAAE,QAAsB,EAAE,YAAY,EAAE,EAAE,YAAY,qBAiBtE;AA+BD;;;;;GAKG;AACH,QAAA,MAAM,KAAK,EAAE,OAuCZ,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,mBAAmB,GACpB,CAAC"}
1
+ {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAyB/B,KAAK,aAAa,GACd,UAAU,GACV,WAAW,GACX,YAAY,GACZ,aAAa,GACb,cAAc,GACd,eAAe,CAAC;AAEpB,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAE1D,KAAK,YAAY,GAAG;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,mBAAmB,CAAC,CAAC,IAAI;IAC5B,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAC1D,KAAK,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;CAChE,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;IACpE,OAAO,EAAE,CACP,OAAO,EAAE,KAAK,CAAC,SAAS,EACxB,OAAO,CAAC,EAAE,YAAY,KACnB,MAAM,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,GAAG,MAAM,CAAC;IAC5E,OAAO,EAAE,CACP,OAAO,EAAE,KAAK,CAAC,SAAS,EACxB,OAAO,CAAC,EAAE,YAAY,KACnB,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,GAAG,MAAM,CAAC;IAC7E,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAC3E,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;CACzC,CAAC;AAiUF;;;;;;;GAOG;AACH,iBAAS,OAAO,CAAC,EAAE,QAAsB,EAAE,YAAY,EAAE,EAAE,YAAY,qBAiBtE;AAyID;;;;;;GAMG;AACH,QAAA,MAAM,KAAK,EAAE,OA4GZ,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,mBAAmB,GACpB,CAAC"}
@@ -1,10 +1,12 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { Toaster as SonnerToaster, toast as sonnerToast, } from "sonner";
4
4
  import { CheckCircle2, CircleAlert, Info, Loader2, TriangleAlert, X, } from "../../icons/lucide.js";
5
5
  import { cn } from "../../lib/utils.js";
6
6
  import { useC4Dictionary } from "../../lib/i18n/context.js";
7
+ import { useIsTruncated } from "../../hooks/use-is-truncated.js";
7
8
  import { buttonVariants } from "./button.js";
9
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
8
10
  import { typographyVariants } from "./typography.js";
9
11
  // ── Styling contract — neutral floating surface, icon-only kind color ──────
10
12
  //
@@ -101,18 +103,22 @@ const TOAST_CLASSNAMES = {
101
103
  // sibling, not the `~` general-sibling used for the icon/close fix above) matches
102
104
  // the actual DOM exactly: title and description are always immediate siblings
103
105
  // inside `[data-content]`, so this only reserves the gap when one is actually there.
104
- // `line-clamp-2` — long titles truncate with an ellipsis past 2 lines instead of
105
- // growing the card indefinitely (fixes #520; short titles are unaffected, this only
106
- // engages once content exceeds the clamp). Consumers should still keep titles short
107
- // (toast.specs.ts's antiPatterns) — this is a rendering backstop, not a substitute
108
- // for writing toast copy that fits a transient, glanceable notification.
109
- title: cn(typographyVariants({ variant: "label-md-strong" }), "line-clamp-2 [&:has(+[data-description])]:mb-1"),
106
+ // `line-clamp-2` used to live here, on sonner's own `[data-title]` wrapper div —
107
+ // moved onto `ToastTitleText`'s inner span instead (see below), which is what
108
+ // `useIsTruncated` needs a ref on to detect the clamp (scrollHeight > clientHeight)
109
+ // and reveal the full value via Tooltip on hover/focus (fixes #659 for the
110
+ // multi-line case; this div-level class list only carries type + spacing now).
111
+ // Consumers should still keep titles short (toast.specs.ts's antiPatterns) — the
112
+ // clamp+reveal is a backstop for when they don't, not a substitute for writing
113
+ // toast copy that fits a transient, glanceable notification.
114
+ title: cn(typographyVariants({ variant: "label-md-strong" }), "[&:has(+[data-description])]:mb-1"),
110
115
  // `text-neutral-foreground-subtle` decouples description color from the (now neutral)
111
116
  // container/title color — matches sonner's own native description color, a muted
112
117
  // gray distinct from the title, not inherited from the card.
113
- // `line-clamp-4` — same rationale as the title's, with more room since descriptions
114
- // are expected to carry more detail.
115
- description: cn(typographyVariants({ variant: "label-md" }), "text-neutral-foreground-subtle line-clamp-4"),
118
+ // `line-clamp-4` — same rationale as the title's `line-clamp-2` above (moved onto
119
+ // `ToastDescriptionText`'s inner span for the same reason) — with more room since
120
+ // descriptions are expected to carry more detail.
121
+ description: cn(typographyVariants({ variant: "label-md" }), "text-neutral-foreground-subtle"),
116
122
  // `ml-auto` keeps the button against the trailing edge whether it shares the first
117
123
  // line or has wrapped onto its own. It keeps `buttonVariants`' base `shrink-0` and
118
124
  // `whitespace-nowrap`: with wrapping available, the label stays on one line at its
@@ -159,6 +165,38 @@ const TOAST_ICONS = {
159
165
  // (Loader2 + animate-spin), colored with a semantic token instead.
160
166
  loading: (_jsx(Loader2, { className: "h-4 w-4 animate-spin text-neutral-foreground-subtle", "aria-hidden": "true" })),
161
167
  };
168
+ function ToastTitleText({ children, onRevealOpen, onRevealClose, }) {
169
+ const { ref, isTruncated, measure } = useIsTruncated();
170
+ React.useLayoutEffect(() => {
171
+ measure();
172
+ });
173
+ const span = (_jsx("span", { ref: ref, tabIndex: 0, onPointerEnter: measure, onFocus: () => {
174
+ measure();
175
+ if (isTruncated)
176
+ onRevealOpen?.();
177
+ }, onBlur: () => {
178
+ if (isTruncated)
179
+ onRevealClose?.();
180
+ }, className: "line-clamp-2 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", children: children }));
181
+ // Mounted only when clipped — see nav-breadcrumb.tsx for why an
182
+ // unconditionally-mounted Tooltip is never the right default.
183
+ return isTruncated ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: span }), _jsx(TooltipContent, { children: children })] })) : (span);
184
+ }
185
+ function ToastDescriptionText({ children, onRevealOpen, onRevealClose, }) {
186
+ const { ref, isTruncated, measure } = useIsTruncated();
187
+ React.useLayoutEffect(() => {
188
+ measure();
189
+ });
190
+ const span = (_jsx("span", { ref: ref, tabIndex: 0, onPointerEnter: measure, onFocus: () => {
191
+ measure();
192
+ if (isTruncated)
193
+ onRevealOpen?.();
194
+ }, onBlur: () => {
195
+ if (isTruncated)
196
+ onRevealClose?.();
197
+ }, className: "line-clamp-4 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", children: children }));
198
+ return isTruncated ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: span }), _jsx(TooltipContent, { children: children })] })) : (span);
199
+ }
162
200
  // ── Toaster ──────────────────────────────────────────────────────────────────
163
201
  /**
164
202
  * The one-time host, mounted once at the application's true root (inside
@@ -179,10 +217,52 @@ function Toaster({ position = "top-right", dismissLabel }) {
179
217
  } }));
180
218
  }
181
219
  // ── toast ────────────────────────────────────────────────────────────────────
182
- function toExternalToast(options, defaultDuration) {
220
+ // ── Focus-driven dismiss pause ──────────────────────────────────────────────
221
+ //
222
+ // Sonner pauses each toast's own auto-dismiss timer while the pointer is over its
223
+ // stack, or while the stack has been expanded via its Alt+T hotkey (`expanded`/
224
+ // `interacting`, set only by `onMouseEnter`/`onMouseMove`/`onPointerDown`/`onPointerUp`
225
+ // on its own <ol> — verified in sonner@2.0.8's index.mjs, ~line 1190-1204) — but never
226
+ // on focus. The <ol>'s own `onFocus` handler (~line 1182) only tracks focus-restoration
227
+ // bookkeeping, never sets `expanded`/`interacting`. So a keyboard user who Tabs onto a
228
+ // clamped title/description, opens its Tooltip reveal via focus, and starts reading,
229
+ // gets no pause at all: the toast can vanish mid-read for a default-duration (5000ms)
230
+ // toast — a WCAG 1.4.13 (Content on Hover or Focus) violation for exactly the users the
231
+ // reveal above was built to help.
232
+ //
233
+ // `makeToast` below pauses each toast's OWN dismissal (via sonner's update-by-id path —
234
+ // re-calling the same creating method with a matching `id` merges into the existing
235
+ // toast rather than creating a new one) while its title/description has focus, and
236
+ // resumes it on blur. Resuming always restarts the FULL original duration rather than
237
+ // tracking exact remaining time — the simplest defensible choice, and also what sonner
238
+ // itself does to any duration change: its `remainingTime.current = duration` effect
239
+ // resets unconditionally whenever `duration` changes, so a full restart is not a special
240
+ // case bolted on top, it's what an update naturally produces.
241
+ //
242
+ // The `id`, and the exact sonner method that created a toast, are threaded through
243
+ // deliberately: sonner's own update-by-id merge sets `title` unconditionally from the
244
+ // `message` argument (so it must be re-passed identically on every update, not omitted)
245
+ // and sets `type` unconditionally from whichever public method handled the call (the
246
+ // bare call always resets it to `undefined`) — so pausing/resuming a `success` toast
247
+ // through the bare method would silently strip its icon back to neutral. Re-dispatching
248
+ // through the exact same method avoids that. Passing the SAME already-constructed title
249
+ // element back on every update (not a freshly created one) also matters: React bails out
250
+ // of re-rendering a child subtree when the element reference itself is unchanged (same
251
+ // type, same props object), which avoids remounting `ToastTitleText` — and thus avoids
252
+ // losing focus, or worse, unmounting the very element mid-focus-event and retriggering
253
+ // another focus/blur pair — verified live via Storybook + Playwright, see the dev
254
+ // report / toast.specs.ts.
255
+ let toastIdCounter = 0;
256
+ function nextToastId() {
257
+ return `c4-toast-${++toastIdCounter}`;
258
+ }
259
+ function toExternalToast(options, defaultDuration, reveal) {
183
260
  const action = options?.action;
184
261
  return {
185
- description: options?.description,
262
+ // Wrapped only when present — sonner conditionally renders `[data-description]`
263
+ // at all based on truthiness, and `:has([data-description])` selectors elsewhere
264
+ // in TOAST_CLASSNAMES key off that same presence (see the Styling contract).
265
+ description: options?.description ? (_jsx(ToastDescriptionText, { onRevealOpen: reveal.onRevealOpen, onRevealClose: reveal.onRevealClose, children: options.description })) : undefined,
186
266
  duration: options?.duration ?? defaultDuration,
187
267
  action: action
188
268
  ? {
@@ -202,27 +282,133 @@ function toExternalToast(options, defaultDuration) {
202
282
  : undefined,
203
283
  };
204
284
  }
285
+ /**
286
+ * Builds and dispatches one toast, wiring its title/description with the
287
+ * focus-driven pause/resume above. `kind` must be the exact sonner method used to
288
+ * create it (`sonnerToast` itself for the untyped/default kind, or one of
289
+ * `.success`/`.info`/`.warning`/`.error`) — see the "Focus-driven dismiss pause"
290
+ * note for why re-dispatching through any other method would corrupt the toast's
291
+ * type/icon.
292
+ */
293
+ function makeToast(kind, message, options, defaultDuration) {
294
+ const id = nextToastId();
295
+ const duration = options?.duration ?? defaultDuration;
296
+ // `pause`/`resume` reference `titleNode` before its own declaration below —
297
+ // safe because both only ever run later, from a focus/blur event, by which
298
+ // point `titleNode`'s initializer has long since run.
299
+ const pause = () => {
300
+ if (duration === Infinity)
301
+ return; // no auto-dismiss timer exists to pause
302
+ // Same guard as `resume` below: a focus event landing in the same animation
303
+ // frame as a `toast.dismiss(id)` call must not resurrect the toast the
304
+ // consumer just closed — sonner's `create()` un-dismisses a matching id
305
+ // otherwise (index.mjs ~181-194).
306
+ if (!sonnerToast.getToasts().some((t) => t.id === id))
307
+ return;
308
+ kind(titleNode, { id, duration: Infinity });
309
+ };
310
+ const resume = () => {
311
+ if (duration === Infinity)
312
+ return;
313
+ // A toast the user already dismissed (or that auto-closed) must not be
314
+ // resurrected by a stray blur — sonner's `create()` un-dismisses a matching
315
+ // id otherwise (index.mjs ~181-194).
316
+ if (!sonnerToast.getToasts().some((t) => t.id === id))
317
+ return;
318
+ kind(titleNode, { id, duration });
319
+ };
320
+ const titleNode = (_jsx(ToastTitleText, { onRevealOpen: pause, onRevealClose: resume, children: message }));
321
+ return kind(titleNode, {
322
+ ...toExternalToast(options, defaultDuration, {
323
+ onRevealOpen: pause,
324
+ onRevealClose: resume,
325
+ }),
326
+ id,
327
+ });
328
+ }
205
329
  /**
206
330
  * The callable used everywhere else — never sonner's own `toast` re-exported directly.
207
- * `options.duration` resolution uses `??`, not `||`: sonner treats a literal
208
- * `duration: 0` as falsy and silently falls back to its own ~4s default (verified in
209
- * source) — `??` is required so an explicit `0` isn't confused with "not passed".
331
+ * `options.duration` resolution (inside `toExternalToast`) uses `??`, not `||`: sonner
332
+ * treats a literal `duration: 0` as falsy and silently falls back to its own ~4s default
333
+ * (verified in source) — `??` is required so an explicit `0` isn't confused with "not
334
+ * passed".
210
335
  */
211
- const toast = Object.assign((message, options) => sonnerToast(message, toExternalToast(options, 5000)), {
212
- success: (message, options) => sonnerToast.success(message, toExternalToast(options, 5000)),
213
- info: (message, options) => sonnerToast.info(message, toExternalToast(options, 5000)),
214
- warning: (message, options) => sonnerToast.warning(message, toExternalToast(options, 5000)),
336
+ const toast = Object.assign((message, options) => makeToast(sonnerToast, message, options, 5000), {
337
+ success: (message, options) => makeToast(sonnerToast.success, message, options, 5000),
338
+ info: (message, options) => makeToast(sonnerToast.info, message, options, 5000),
339
+ warning: (message, options) => makeToast(sonnerToast.warning, message, options, 5000),
215
340
  error: (message, options) =>
216
341
  // Default Infinity — errors persist until manually dismissed (toast.specs.ts).
217
- sonnerToast.error(message, toExternalToast(options, Infinity)),
342
+ makeToast(sonnerToast.error, message, options, Infinity),
218
343
  promise: (promise, options) => {
219
344
  // Discard sonner's own return value (string|number & { unwrap }) — the spec's
220
345
  // contract is `=> void`; the loading → success/error swap is automatic and there
221
346
  // is no toast id to combine with toast.dismiss(id).
347
+ //
348
+ // loading/success/error are wrapped in `ToastTitleText` too — they render into
349
+ // the same `[data-title]` slot (styled by the same `classNames.title`, clamped
350
+ // the same way) as every other kind, so they get the same truncation reveal.
351
+ // `success`/`error` accept a plain value or a function of the resolved
352
+ // data/caught error (PromiseToastOptions<T>'s own shape) — resolve that first,
353
+ // then wrap the result; sonner is what actually calls this function with the
354
+ // real data/error at resolve/reject time.
355
+ //
356
+ // Pause/resume: the loading phase is `type: "loading"`, which sonner's own timer
357
+ // effect excludes from auto-dismissal entirely (no timer ever starts for it —
358
+ // index.mjs ~644) — nothing to pause there. Only the resolved *success* toast can
359
+ // auto-dismiss, so it alone is wired below, with its own explicit 5000ms duration
360
+ // (sonner's own internal default for a `.promise()` resolution is 4000ms, and
361
+ // unlike `toExternalToast`'s call sites, `resume` here has no other way to learn
362
+ // what to restore). The resolved *error* toast persists until manually dismissed —
363
+ // `duration: Infinity` is set EXPLICITLY below, matching `toast.error`'s own
364
+ // default: sonner's update merge only touches keys present in the returned
365
+ // object, so omitting `duration` here does not inherit Infinity from anywhere,
366
+ // it falls back to sonner's own internal ~4000ms default instead (this was a
367
+ // real, Validator-caught bug — the error toast was silently auto-dismissing with
368
+ // no pause protection, the exact gap this whole feature exists to close). With
369
+ // `duration: Infinity` actually set, no timer ever starts, so no pause/resume is
370
+ // wired for it either.
371
+ const id = nextToastId();
372
+ const successDuration = 5000;
373
+ let successTitleNode;
374
+ const pauseSuccess = () => {
375
+ // Same guard as `resumeSuccess` below — see `makeToast`'s `pause` for why.
376
+ if (!sonnerToast.getToasts().some((t) => t.id === id))
377
+ return;
378
+ sonnerToast.success(successTitleNode, { id, duration: Infinity });
379
+ };
380
+ const resumeSuccess = () => {
381
+ if (!sonnerToast.getToasts().some((t) => t.id === id))
382
+ return;
383
+ sonnerToast.success(successTitleNode, {
384
+ id,
385
+ duration: successDuration,
386
+ });
387
+ };
222
388
  sonnerToast.promise(promise, {
223
- loading: options.loading,
224
- success: options.success,
225
- error: options.error,
389
+ id,
390
+ loading: _jsx(ToastTitleText, { children: options.loading }),
391
+ success: (data) => {
392
+ const content = typeof options.success === "function"
393
+ ? options.success(data)
394
+ : options.success;
395
+ successTitleNode = (_jsx(ToastTitleText, { onRevealOpen: pauseSuccess, onRevealClose: resumeSuccess, children: content }));
396
+ return { message: successTitleNode, duration: successDuration };
397
+ },
398
+ error: (error) => {
399
+ const content = typeof options.error === "function"
400
+ ? options.error(error)
401
+ : options.error;
402
+ // `duration: Infinity` must be explicit here — sonner's own merge only
403
+ // touches keys present in this return value, and with none supplied it
404
+ // falls back to its own internal ~4000ms default, not our Infinity intent.
405
+ // (Found by the Validator: this toast was silently auto-dismissing behind
406
+ // an unpaused timer, contradicting this file's own comment above.)
407
+ return {
408
+ message: _jsx(ToastTitleText, { children: content }),
409
+ duration: Infinity,
410
+ };
411
+ },
226
412
  });
227
413
  },
228
414
  dismiss: (id) => {