@devalok/shilp-sutra 0.48.0 → 0.49.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 (185) hide show
  1. package/BREAKING.json +32 -0
  2. package/MIGRATION.md +891 -881
  3. package/dist/_chunks/badge-group.js +50 -63
  4. package/dist/_chunks/badge-group.js.map +1 -1
  5. package/dist/_chunks/chat.js +1 -1
  6. package/dist/_chunks/chat.js.map +1 -1
  7. package/dist/_chunks/field-state.js +8 -0
  8. package/dist/_chunks/field-state.js.map +1 -0
  9. package/dist/_chunks/popover.js +50 -47
  10. package/dist/_chunks/popover.js.map +1 -1
  11. package/dist/_chunks/primitives.js +155 -155
  12. package/dist/_chunks/primitives.js.map +1 -1
  13. package/dist/_chunks/shared.js +4 -4
  14. package/dist/_chunks/tiptap.js +10 -10
  15. package/dist/_chunks/use-calendar.js +1 -1
  16. package/dist/_chunks/use-calendar.js.map +1 -1
  17. package/dist/_chunks/use-controllable-open.js +15 -0
  18. package/dist/_chunks/use-controllable-open.js.map +1 -0
  19. package/dist/composed/command-palette.js +3 -3
  20. package/dist/composed/command-palette.js.map +1 -1
  21. package/dist/composed/confirm-dialog.js +3 -3
  22. package/dist/composed/confirm-dialog.js.map +1 -1
  23. package/dist/composed/date-picker/index.js +3 -3
  24. package/dist/composed/date-picker/index.js.map +1 -1
  25. package/dist/composed/error-boundary.js +1 -1
  26. package/dist/composed/error-boundary.js.map +1 -1
  27. package/dist/composed/index.d.ts +3 -1
  28. package/dist/composed/index.d.ts.map +1 -1
  29. package/dist/composed/index.js +4 -3
  30. package/dist/composed/loading-skeleton.js +15 -15
  31. package/dist/composed/loading-skeleton.js.map +1 -1
  32. package/dist/composed/page-header.d.ts.map +1 -1
  33. package/dist/composed/page-header.js +32 -45
  34. package/dist/composed/page-header.js.map +1 -1
  35. package/dist/composed/page-skeletons.js +19 -19
  36. package/dist/composed/page-skeletons.js.map +1 -1
  37. package/dist/composed/responsive-modal.d.ts +39 -0
  38. package/dist/composed/responsive-modal.d.ts.map +1 -0
  39. package/dist/composed/responsive-modal.js +212 -0
  40. package/dist/composed/responsive-modal.js.map +1 -0
  41. package/dist/composed/rich-chat-input.js +4 -4
  42. package/dist/composed/rich-text-editor.js +1 -1
  43. package/dist/composed/rich-text-editor.js.map +1 -1
  44. package/dist/composed/schedule-view.d.ts +1 -1
  45. package/dist/composed/schedule-view.d.ts.map +1 -1
  46. package/dist/composed/schedule-view.js +48 -54
  47. package/dist/composed/schedule-view.js.map +1 -1
  48. package/dist/composed/status-badge.d.ts +13 -11
  49. package/dist/composed/status-badge.d.ts.map +1 -1
  50. package/dist/composed/status-badge.js +54 -130
  51. package/dist/composed/status-badge.js.map +1 -1
  52. package/dist/shell/bottom-navbar.js +1 -1
  53. package/dist/shell/bottom-navbar.js.map +1 -1
  54. package/dist/shell/top-bar.js +1 -1
  55. package/dist/shell/top-bar.js.map +1 -1
  56. package/dist/tokens/semantic.css +8 -1
  57. package/dist/ui/accordion.js +9 -9
  58. package/dist/ui/alert-dialog.js +26 -26
  59. package/dist/ui/aspect-ratio.js +1 -1
  60. package/dist/ui/autocomplete.js +7 -7
  61. package/dist/ui/avatar.d.ts.map +1 -1
  62. package/dist/ui/avatar.js +87 -82
  63. package/dist/ui/avatar.js.map +1 -1
  64. package/dist/ui/badge.d.ts.map +1 -1
  65. package/dist/ui/breadcrumb.d.ts +0 -1
  66. package/dist/ui/breadcrumb.d.ts.map +1 -1
  67. package/dist/ui/breadcrumb.js +58 -35
  68. package/dist/ui/breadcrumb.js.map +1 -1
  69. package/dist/ui/button.js +3 -3
  70. package/dist/ui/checkbox.d.ts +4 -2
  71. package/dist/ui/checkbox.d.ts.map +1 -1
  72. package/dist/ui/checkbox.js +33 -28
  73. package/dist/ui/checkbox.js.map +1 -1
  74. package/dist/ui/collapsible.js +4 -4
  75. package/dist/ui/combobox.d.ts +3 -0
  76. package/dist/ui/combobox.d.ts.map +1 -1
  77. package/dist/ui/combobox.js +137 -132
  78. package/dist/ui/combobox.js.map +1 -1
  79. package/dist/ui/context-menu.js +46 -46
  80. package/dist/ui/dialog.d.ts.map +1 -1
  81. package/dist/ui/dialog.js +53 -50
  82. package/dist/ui/dialog.js.map +1 -1
  83. package/dist/ui/dot.d.ts +38 -0
  84. package/dist/ui/dot.d.ts.map +1 -0
  85. package/dist/ui/dot.js +92 -0
  86. package/dist/ui/dot.js.map +1 -0
  87. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  88. package/dist/ui/dropdown-menu.js +70 -65
  89. package/dist/ui/dropdown-menu.js.map +1 -1
  90. package/dist/ui/hover-card.js +11 -11
  91. package/dist/ui/index.d.ts +3 -2
  92. package/dist/ui/index.d.ts.map +1 -1
  93. package/dist/ui/index.js +67 -67
  94. package/dist/ui/index.js.map +1 -1
  95. package/dist/ui/input-otp.js +1 -1
  96. package/dist/ui/input-otp.js.map +1 -1
  97. package/dist/ui/input.d.ts +4 -2
  98. package/dist/ui/input.d.ts.map +1 -1
  99. package/dist/ui/input.js +38 -37
  100. package/dist/ui/input.js.map +1 -1
  101. package/dist/ui/label.js +1 -1
  102. package/dist/ui/lib/field-state.d.ts +21 -0
  103. package/dist/ui/lib/field-state.d.ts.map +1 -0
  104. package/dist/ui/lib/use-controllable-open.d.ts +32 -0
  105. package/dist/ui/lib/use-controllable-open.d.ts.map +1 -0
  106. package/dist/ui/link.js +1 -1
  107. package/dist/ui/number-input.d.ts +4 -2
  108. package/dist/ui/number-input.d.ts.map +1 -1
  109. package/dist/ui/number-input.js +51 -50
  110. package/dist/ui/number-input.js.map +1 -1
  111. package/dist/ui/pagination.js +1 -1
  112. package/dist/ui/popover.d.ts.map +1 -1
  113. package/dist/ui/progress.d.ts +66 -42
  114. package/dist/ui/progress.d.ts.map +1 -1
  115. package/dist/ui/progress.js +144 -40
  116. package/dist/ui/progress.js.map +1 -1
  117. package/dist/ui/radio.d.ts +6 -2
  118. package/dist/ui/radio.d.ts.map +1 -1
  119. package/dist/ui/radio.js +44 -33
  120. package/dist/ui/radio.js.map +1 -1
  121. package/dist/ui/select.d.ts +1 -1
  122. package/dist/ui/select.d.ts.map +1 -1
  123. package/dist/ui/select.js +58 -57
  124. package/dist/ui/select.js.map +1 -1
  125. package/dist/ui/separator.js +2 -2
  126. package/dist/ui/separator.js.map +1 -1
  127. package/dist/ui/sheet.d.ts.map +1 -1
  128. package/dist/ui/sheet.js +59 -56
  129. package/dist/ui/sheet.js.map +1 -1
  130. package/dist/ui/sidebar.js +5 -5
  131. package/dist/ui/sidebar.js.map +1 -1
  132. package/dist/ui/slider.js +6 -6
  133. package/dist/ui/slider.js.map +1 -1
  134. package/dist/ui/stat-card.d.ts.map +1 -1
  135. package/dist/ui/stat-card.js +122 -125
  136. package/dist/ui/stat-card.js.map +1 -1
  137. package/dist/ui/surface.js +1 -1
  138. package/dist/ui/switch.d.ts +3 -1
  139. package/dist/ui/switch.d.ts.map +1 -1
  140. package/dist/ui/switch.js +32 -27
  141. package/dist/ui/switch.js.map +1 -1
  142. package/dist/ui/textarea.d.ts +3 -3
  143. package/dist/ui/textarea.d.ts.map +1 -1
  144. package/dist/ui/textarea.js +18 -17
  145. package/dist/ui/textarea.js.map +1 -1
  146. package/dist/ui/toast.js +2 -2
  147. package/dist/ui/toast.js.map +1 -1
  148. package/dist/ui/toggle-group.js +1 -1
  149. package/dist/ui/toggle.js +1 -1
  150. package/dist/ui/tooltip.d.ts.map +1 -1
  151. package/dist/ui/tooltip.js +36 -33
  152. package/dist/ui/tooltip.js.map +1 -1
  153. package/docs/components/ai/ai-command-provider.md +46 -0
  154. package/docs/components/ai/block-renderer.md +59 -0
  155. package/docs/components/ai/command-bar.md +78 -0
  156. package/docs/components/ai/conversation.md +59 -0
  157. package/docs/components/ai/devadoot-icon.md +41 -0
  158. package/docs/components/composed/page-header.md +1 -1
  159. package/docs/components/composed/responsive-modal.md +66 -0
  160. package/docs/components/composed/schedule-view.md +6 -2
  161. package/docs/components/ui/breadcrumb.md +1 -1
  162. package/docs/components/ui/checkbox.md +4 -1
  163. package/docs/components/ui/combobox.md +4 -0
  164. package/docs/components/ui/dot.md +61 -0
  165. package/docs/components/ui/progress.md +54 -16
  166. package/docs/components/ui/radio.md +6 -2
  167. package/docs/components/ui/select.md +9 -5
  168. package/docs/components/ui/switch.md +4 -1
  169. package/docs/components/ui/table.md +2 -1
  170. package/llms.txt +11 -3
  171. package/make-kit/components/form.md +2 -2
  172. package/make-kit/components/icon.md +2 -2
  173. package/make-kit/components/overview.md +2 -2
  174. package/make-kit/components/select.md +1 -1
  175. package/make-kit/components/table.md +1 -1
  176. package/mcp-manifest.json +2656 -1068
  177. package/mcp-manifest.schema.json +18 -0
  178. package/package.json +11 -6
  179. package/skill/SKILL.md +1 -1
  180. package/skill/references/components.md +11 -3
  181. package/dist/ui/status-dot.d.ts +0 -27
  182. package/dist/ui/status-dot.d.ts.map +0 -1
  183. package/dist/ui/status-dot.js +0 -68
  184. package/dist/ui/status-dot.js.map +0 -1
  185. package/docs/components/ui/status-dot.md +0 -35
package/dist/ui/switch.js CHANGED
@@ -1,13 +1,14 @@
1
1
  "use client";
2
- import { B as e, z as t } from "../_chunks/primitives.js";
2
+ import { R as e, z as t } from "../_chunks/primitives.js";
3
3
  import { springs as n } from "./lib/motion.js";
4
4
  import { cn as r } from "./lib/utils.js";
5
5
  import { useFormField as i } from "./form.js";
6
- import * as a from "react";
7
- import { jsx as o } from "react/jsx-runtime";
8
- import { motion as s } from "framer-motion";
6
+ import { t as a } from "../_chunks/field-state.js";
7
+ import * as o from "react";
8
+ import { jsx as s } from "react/jsx-runtime";
9
+ import { motion as c } from "framer-motion";
9
10
  //#region src/ui/switch.tsx
10
- var c = {
11
+ var l = {
11
12
  sm: {
12
13
  track: "h-6 w-[38px]",
13
14
  thumb: "h-5 w-5",
@@ -23,36 +24,40 @@ var c = {
23
24
  thumb: "h-6 w-6",
24
25
  travel: 24
25
26
  }
26
- }, l = {
27
+ }, u = {
28
+ error: "border-error-7 data-[state=checked]:bg-error-9",
29
+ warning: "border-warning-7 data-[state=checked]:bg-warning-9",
30
+ success: "border-success-7 data-[state=checked]:bg-success-9"
31
+ }, d = {
27
32
  accent: "data-[state=checked]:bg-accent-9",
28
33
  success: "data-[state=checked]:bg-success-9",
29
34
  warning: "data-[state=checked]:bg-warning-9"
30
- }, u = a.forwardRef(({ className: u, error: d, size: f = "md", color: p = "accent", thumbIcon: m, checked: h, defaultChecked: g, onCheckedChange: _, ...v }, y) => {
31
- let b = i(), x = d ?? b.state === "error", S = v["aria-describedby"] ?? b.helperTextId, C = v["aria-required"] ?? b.required, [w, T] = a.useState(g ?? !1), E = h === void 0 ? w : h, { track: D, thumb: O, travel: k } = c[f], A = a.useCallback((e) => {
32
- h === void 0 && T(e), _?.(e);
33
- }, [h, _]);
34
- return /* @__PURE__ */ o(t, {
35
- className: r("touch-target peer inline-flex shrink-0 cursor-pointer items-center rounded-pill border-2 border-surface-border-strong shadow-raised transition-colors duration-fast-01 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-action-disabled data-[state=checked]:border-transparent data-[state=unchecked]:bg-surface-border-strong data-[state=unchecked]:hover:bg-surface-raised-active", D, l[p], x && "border-error-7 data-[state=checked]:bg-error-9", u),
36
- checked: h,
37
- defaultChecked: g,
38
- onCheckedChange: A,
39
- "aria-invalid": x || void 0,
40
- "aria-describedby": S,
41
- "aria-required": C || void 0,
42
- ...v,
43
- ref: y,
44
- children: /* @__PURE__ */ o(e, {
35
+ }, f = o.forwardRef(({ className: f, state: p, size: m = "md", color: h = "accent", thumbIcon: g, checked: _, defaultChecked: v, onCheckedChange: y, ...b }, x) => {
36
+ let S = i(), C = a(p, S.state), w = b["aria-describedby"] ?? S.helperTextId, T = b["aria-required"] ?? S.required, [E, D] = o.useState(v ?? !1), O = _ === void 0 ? E : _, { track: k, thumb: A, travel: j } = l[m], M = o.useCallback((e) => {
37
+ _ === void 0 && D(e), y?.(e);
38
+ }, [_, y]);
39
+ return /* @__PURE__ */ s(e, {
40
+ className: r("touch-target peer inline-flex shrink-0 cursor-pointer items-center rounded-pill border-2 border-surface-border-strong shadow-raised transition-colors duration-fast-01 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-action-disabled data-[state=checked]:border-transparent data-[state=unchecked]:bg-surface-border-strong data-[state=unchecked]:hover:bg-surface-raised-active", k, d[h], C && u[C], f),
41
+ checked: _,
42
+ defaultChecked: v,
43
+ onCheckedChange: M,
44
+ "aria-invalid": C === "error" || void 0,
45
+ "aria-describedby": w,
46
+ "aria-required": T || void 0,
47
+ ...b,
48
+ ref: x,
49
+ children: /* @__PURE__ */ s(t, {
45
50
  asChild: !0,
46
- children: /* @__PURE__ */ o(s.span, {
47
- className: r("pointer-events-none flex items-center justify-center rounded-pill bg-accent-fg shadow-raised-hover ring-0", O),
48
- animate: { x: E ? k : 0 },
51
+ children: /* @__PURE__ */ s(c.span, {
52
+ className: r("pointer-events-none flex items-center justify-center rounded-pill bg-accent-fg shadow-raised-hover ring-0", A),
53
+ animate: { x: O ? j : 0 },
49
54
  whileTap: { scale: .85 },
50
55
  transition: n.snappy,
51
- children: m
56
+ children: g
52
57
  })
53
58
  })
54
59
  });
55
60
  });
56
- u.displayName = t.displayName;
61
+ f.displayName = e.displayName;
57
62
  //#endregion
58
- export { u as Switch };
63
+ export { f as Switch };
@@ -1 +1 @@
1
- {"version":3,"file":"switch.js","names":[],"sources":["../../src/ui/switch.tsx"],"sourcesContent":["'use client'\n\nimport * as SwitchPrimitives from \"@primitives/react-switch\"\nimport { motion } from 'framer-motion'\nimport * as React from \"react\"\n\nimport { useFormField } from './form'\nimport { springs } from './lib/motion'\nimport { cn } from \"./lib/utils\"\n\nconst sizeConfig = {\n sm: { track: 'h-6 w-[38px]', thumb: 'h-5 w-5', travel: 16 },\n md: { track: 'h-6 w-11', thumb: 'h-ico-md w-ico-md', travel: 20 },\n lg: { track: 'h-7 w-[52px]', thumb: 'h-6 w-6', travel: 24 },\n} as const\n\nconst colorMap = {\n accent: 'data-[state=checked]:bg-accent-9',\n success: 'data-[state=checked]:bg-success-9',\n warning: 'data-[state=checked]:bg-warning-9',\n} as const\n\nexport interface SwitchProps extends React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root> {\n error?: boolean\n size?: 'sm' | 'md' | 'lg'\n color?: 'accent' | 'success' | 'warning'\n thumbIcon?: React.ReactNode\n}\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n SwitchProps\n>(({ className, error, size = 'md', color = 'accent', thumbIcon, checked, defaultChecked, onCheckedChange, ...props }, ref) => {\n const fieldCtx = useFormField()\n const isError = error ?? fieldCtx.state === 'error'\n const ariaDescribedBy = props['aria-describedby'] ?? fieldCtx.helperTextId\n const ariaRequired = props['aria-required'] ?? fieldCtx.required\n\n // Track checked state internally to drive Framer Motion animation\n const [internalChecked, setInternalChecked] = React.useState(defaultChecked ?? false)\n const isChecked = checked !== undefined ? checked : internalChecked\n const { track, thumb, travel } = sizeConfig[size]\n\n const handleCheckedChange = React.useCallback(\n (value: boolean) => {\n if (checked === undefined) {\n setInternalChecked(value)\n }\n onCheckedChange?.(value)\n },\n [checked, onCheckedChange],\n )\n\n return (\n <SwitchPrimitives.Root\n className={cn(\n \"touch-target peer inline-flex shrink-0 cursor-pointer items-center rounded-pill border-2 border-surface-border-strong shadow-raised transition-colors duration-fast-01 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-action-disabled data-[state=checked]:border-transparent data-[state=unchecked]:bg-surface-border-strong data-[state=unchecked]:hover:bg-surface-raised-active\",\n track,\n colorMap[color],\n isError && \"border-error-7 data-[state=checked]:bg-error-9\",\n className\n )}\n checked={checked}\n defaultChecked={defaultChecked}\n onCheckedChange={handleCheckedChange}\n aria-invalid={isError || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb asChild>\n <motion.span\n className={cn(\n \"pointer-events-none flex items-center justify-center rounded-pill bg-accent-fg shadow-raised-hover ring-0\",\n thumb\n )}\n animate={{ x: isChecked ? travel : 0 }}\n whileTap={{ scale: 0.85 }}\n transition={springs.snappy}\n >\n {thumbIcon}\n </motion.span>\n </SwitchPrimitives.Thumb>\n </SwitchPrimitives.Root>\n )\n})\nSwitch.displayName = SwitchPrimitives.Root.displayName\n\nexport { Switch }\n"],"mappings":";;;;;;;;;AAUA,IAAM,IAAa;CACjB,IAAI;EAAE,OAAO;EAAgB,OAAO;EAAW,QAAQ;EAAI;CAC3D,IAAI;EAAE,OAAO;EAAY,OAAO;EAAqB,QAAQ;EAAI;CACjE,IAAI;EAAE,OAAO;EAAgB,OAAO;EAAW,QAAQ;EAAI;CAC5D,EAEK,IAAW;CACf,QAAQ;CACR,SAAS;CACT,SAAS;CACV,EASK,IAAS,EAAM,YAGlB,EAAE,cAAW,UAAO,UAAO,MAAM,WAAQ,UAAU,cAAW,YAAS,mBAAgB,oBAAiB,GAAG,KAAS,MAAQ;CAC7H,IAAM,IAAW,GAAc,EACzB,IAAU,KAAS,EAAS,UAAU,SACtC,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS,UAGlD,CAAC,GAAiB,KAAsB,EAAM,SAAS,KAAkB,GAAM,EAC/E,IAAY,MAAY,KAAA,IAAsB,IAAV,GACpC,EAAE,UAAO,UAAO,cAAW,EAAW,IAEtC,IAAsB,EAAM,aAC/B,MAAmB;AAIlB,EAHI,MAAY,KAAA,KACd,EAAmB,EAAM,EAE3B,IAAkB,EAAM;IAE1B,CAAC,GAAS,EAAgB,CAC3B;AAED,QACE,kBAAC,GAAD;EACE,WAAW,EACT,+dACA,GACA,EAAS,IACT,KAAW,kDACX,EACD;EACQ;EACO;EAChB,iBAAiB;EACjB,gBAAc,KAAW,KAAA;EACzB,oBAAkB;EAClB,iBAAe,KAAgB,KAAA;EAC/B,GAAI;EACC;YAEL,kBAAC,GAAD;GAAwB,SAAA;aACtB,kBAAC,EAAO,MAAR;IACE,WAAW,EACT,6GACA,EACD;IACD,SAAS,EAAE,GAAG,IAAY,IAAS,GAAG;IACtC,UAAU,EAAE,OAAO,KAAM;IACzB,YAAY,EAAQ;cAEnB;IACW,CAAA;GACS,CAAA;EACH,CAAA;EAE1B;AACF,EAAO,cAAA,EAAoC"}
1
+ {"version":3,"file":"switch.js","names":[],"sources":["../../src/ui/switch.tsx"],"sourcesContent":["'use client'\n\nimport * as SwitchPrimitives from \"@primitives/react-switch\"\nimport { motion } from 'framer-motion'\nimport * as React from \"react\"\n\nimport { useFormField } from './form'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { springs } from './lib/motion'\nimport { cn } from \"./lib/utils\"\n\nconst sizeConfig = {\n sm: { track: 'h-6 w-[38px]', thumb: 'h-5 w-5', travel: 16 },\n md: { track: 'h-6 w-11', thumb: 'h-ico-md w-ico-md', travel: 20 },\n lg: { track: 'h-7 w-[52px]', thumb: 'h-6 w-6', travel: 24 },\n} as const\n\n/** Validation border + checked-track tint per state (overrides `color` when set). */\nconst stateTintClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7 data-[state=checked]:bg-error-9',\n warning: 'border-warning-7 data-[state=checked]:bg-warning-9',\n success: 'border-success-7 data-[state=checked]:bg-success-9',\n}\n\nconst colorMap = {\n accent: 'data-[state=checked]:bg-accent-9',\n success: 'data-[state=checked]:bg-success-9',\n warning: 'data-[state=checked]:bg-warning-9',\n} as const\n\nexport interface SwitchProps extends React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root> {\n /** Validation/feedback state. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. Distinct from `color` (the ON-track tint). */\n state?: FieldState\n size?: 'sm' | 'md' | 'lg'\n color?: 'accent' | 'success' | 'warning'\n thumbIcon?: React.ReactNode\n}\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n SwitchProps\n>(({ className, state: stateProp, size = 'md', color = 'accent', thumbIcon, checked, defaultChecked, onCheckedChange, ...props }, ref) => {\n const fieldCtx = useFormField()\n const state = resolveFieldState(stateProp, fieldCtx.state)\n const ariaDescribedBy = props['aria-describedby'] ?? fieldCtx.helperTextId\n const ariaRequired = props['aria-required'] ?? fieldCtx.required\n\n // Track checked state internally to drive Framer Motion animation\n const [internalChecked, setInternalChecked] = React.useState(defaultChecked ?? false)\n const isChecked = checked !== undefined ? checked : internalChecked\n const { track, thumb, travel } = sizeConfig[size]\n\n const handleCheckedChange = React.useCallback(\n (value: boolean) => {\n if (checked === undefined) {\n setInternalChecked(value)\n }\n onCheckedChange?.(value)\n },\n [checked, onCheckedChange],\n )\n\n return (\n <SwitchPrimitives.Root\n className={cn(\n \"touch-target peer inline-flex shrink-0 cursor-pointer items-center rounded-pill border-2 border-surface-border-strong shadow-raised transition-colors duration-fast-01 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-action-disabled data-[state=checked]:border-transparent data-[state=unchecked]:bg-surface-border-strong data-[state=unchecked]:hover:bg-surface-raised-active\",\n track,\n colorMap[color],\n state && stateTintClasses[state],\n className\n )}\n checked={checked}\n defaultChecked={defaultChecked}\n onCheckedChange={handleCheckedChange}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb asChild>\n <motion.span\n className={cn(\n \"pointer-events-none flex items-center justify-center rounded-pill bg-accent-fg shadow-raised-hover ring-0\",\n thumb\n )}\n animate={{ x: isChecked ? travel : 0 }}\n whileTap={{ scale: 0.85 }}\n transition={springs.snappy}\n >\n {thumbIcon}\n </motion.span>\n </SwitchPrimitives.Thumb>\n </SwitchPrimitives.Root>\n )\n})\nSwitch.displayName = SwitchPrimitives.Root.displayName\n\nexport { Switch }\n"],"mappings":";;;;;;;;;;AAWA,IAAM,IAAa;CACjB,IAAI;EAAE,OAAO;EAAgB,OAAO;EAAW,QAAQ;EAAI;CAC3D,IAAI;EAAE,OAAO;EAAY,OAAO;EAAqB,QAAQ;EAAI;CACjE,IAAI;EAAE,OAAO;EAAgB,OAAO;EAAW,QAAQ;EAAI;CAC5D,EAGK,IAAmE;CACvE,OAAO;CACP,SAAS;CACT,SAAS;CACV,EAEK,IAAW;CACf,QAAQ;CACR,SAAS;CACT,SAAS;CACV,EAUK,IAAS,EAAM,YAGlB,EAAE,cAAW,OAAO,GAAW,UAAO,MAAM,WAAQ,UAAU,cAAW,YAAS,mBAAgB,oBAAiB,GAAG,KAAS,MAAQ;CACxI,IAAM,IAAW,GAAc,EACzB,IAAQ,EAAkB,GAAW,EAAS,MAAM,EACpD,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS,UAGlD,CAAC,GAAiB,KAAsB,EAAM,SAAS,KAAkB,GAAM,EAC/E,IAAY,MAAY,KAAA,IAAsB,IAAV,GACpC,EAAE,UAAO,UAAO,cAAW,EAAW,IAEtC,IAAsB,EAAM,aAC/B,MAAmB;AAIlB,EAHI,MAAY,KAAA,KACd,EAAmB,EAAM,EAE3B,IAAkB,EAAM;IAE1B,CAAC,GAAS,EAAgB,CAC3B;AAED,QACE,kBAAC,GAAD;EACE,WAAW,EACT,+dACA,GACA,EAAS,IACT,KAAS,EAAiB,IAC1B,EACD;EACQ;EACO;EAChB,iBAAiB;EACjB,gBAAc,MAAU,WAAW,KAAA;EACnC,oBAAkB;EAClB,iBAAe,KAAgB,KAAA;EAC/B,GAAI;EACC;YAEL,kBAAC,GAAD;GAAwB,SAAA;aACtB,kBAAC,EAAO,MAAR;IACE,WAAW,EACT,6GACA,EACD;IACD,SAAS,EAAE,GAAG,IAAY,IAAS,GAAG;IACtC,UAAU,EAAE,OAAO,KAAM;IACzB,YAAY,EAAQ;cAEnB;IACW,CAAA;GACS,CAAA;EACH,CAAA;EAE1B;AACF,EAAO,cAAA,EAAoC"}
@@ -1,13 +1,13 @@
1
1
  "use client";
2
2
  import { VariantProps } from 'class-variance-authority';
3
- import { InputState } from './input';
3
+ import { FieldState } from './lib/field-state';
4
4
  import * as React from 'react';
5
5
  declare const textareaVariants: (props?: ({
6
6
  size?: "xs" | "sm" | "md" | "lg" | null | undefined;
7
7
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
8
8
  /**
9
9
  * Props for Textarea — a resizable multi-line text input with size variants and validation state coloring,
10
- * sharing the same `InputState` type as `<Input>`.
10
+ * sharing the same `FieldState` type as every form control.
11
11
  *
12
12
  * **Sizes:** `sm` (min 60px) | `md` (min 80px, default) | `lg` (min 120px) — all are vertically resizable.
13
13
  *
@@ -34,7 +34,7 @@ declare const textareaVariants: (props?: ({
34
34
  * // These are just a few ways — feel free to combine props creatively!
35
35
  */
36
36
  export interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'>, VariantProps<typeof textareaVariants> {
37
- state?: InputState;
37
+ state?: FieldState;
38
38
  }
39
39
  declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
40
40
  export { Textarea, textareaVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/ui/textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAIzC,QAAA,MAAM,gBAAgB;;8EAuBrB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,EACrE,YAAY,CAAC,OAAO,gBAAgB,CAAC;IACvC,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,QAAA,MAAM,QAAQ,2FAyBb,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA"}
1
+ {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/ui/textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAA;AAItE,QAAA,MAAM,gBAAgB;;8EAyBrB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,EACrE,YAAY,CAAC,OAAO,gBAAgB,CAAC;IACvC,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,QAAA,MAAM,QAAQ,2FAyBb,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA"}
@@ -3,11 +3,12 @@ import { motionProps as e } from "./lib/motion.js";
3
3
  import { t } from "../_chunks/vendor-utils.js";
4
4
  import { cn as n } from "./lib/utils.js";
5
5
  import { useFormField as r } from "./form.js";
6
- import * as i from "react";
7
- import { jsx as a } from "react/jsx-runtime";
8
- import { motion as o } from "framer-motion";
6
+ import { t as i } from "../_chunks/field-state.js";
7
+ import * as a from "react";
8
+ import { jsx as o } from "react/jsx-runtime";
9
+ import { motion as s } from "framer-motion";
9
10
  //#region src/ui/textarea.tsx
10
- var s = t([
11
+ var c = t([
11
12
  "flex w-full font-sans resize-y",
12
13
  "bg-surface-raised-hover text-surface-fg",
13
14
  "border border-surface-border-strong rounded-control",
@@ -19,23 +20,23 @@ var s = t([
19
20
  "read-only:bg-surface-raised read-only:cursor-default"
20
21
  ], {
21
22
  variants: { size: {
22
- xs: "min-h-[48px] text-ds-sm px-ds-02 py-ds-02",
23
+ xs: "min-h-ds-09 text-ds-sm px-ds-02 py-ds-02",
23
24
  sm: "min-h-[60px] text-ds-sm px-ds-03 py-ds-02",
24
- md: "min-h-[80px] text-ds-md px-ds-04 py-ds-03",
25
+ md: "min-h-ds-11 text-ds-md px-ds-04 py-ds-03",
25
26
  lg: "min-h-[120px] text-ds-md px-ds-05 py-ds-04"
26
27
  } },
27
28
  defaultVariants: { size: "md" }
28
- }), c = i.forwardRef(({ className: t, state: i, size: c, ...l }, u) => {
29
- let d = r(), f = i ?? (d.state === "helper" ? void 0 : d.state), p = l["aria-describedby"] ?? d.helperTextId, m = l["aria-required"] ?? d.required;
30
- return /* @__PURE__ */ a(o.textarea, {
31
- "aria-invalid": f === "error" || void 0,
32
- "aria-describedby": p,
33
- "aria-required": m || void 0,
34
- className: n(s({ size: c }), f === "error" && "border-error-7 focus-visible:ring-error-7", f === "warning" && "border-warning-7 focus-visible:ring-warning-7", f === "success" && "border-success-7 focus-visible:ring-success-7", t),
35
- ref: u,
36
- ...e(l)
29
+ }), l = a.forwardRef(({ className: t, state: a, size: l, ...u }, d) => {
30
+ let f = r(), p = i(a, f.state), m = u["aria-describedby"] ?? f.helperTextId, h = u["aria-required"] ?? f.required;
31
+ return /* @__PURE__ */ o(s.textarea, {
32
+ "aria-invalid": p === "error" || void 0,
33
+ "aria-describedby": m,
34
+ "aria-required": h || void 0,
35
+ className: n(c({ size: l }), p === "error" && "border-error-7 focus-visible:ring-error-7", p === "warning" && "border-warning-7 focus-visible:ring-warning-7", p === "success" && "border-success-7 focus-visible:ring-success-7", t),
36
+ ref: d,
37
+ ...e(u)
37
38
  });
38
39
  });
39
- c.displayName = "Textarea";
40
+ l.displayName = "Textarea";
40
41
  //#endregion
41
- export { c as Textarea, s as textareaVariants };
42
+ export { l as Textarea, c as textareaVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.js","names":[],"sources":["../../src/ui/textarea.tsx"],"sourcesContent":["'use client'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport type { InputState } from './input'\nimport { motionProps } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst textareaVariants = cva(\n [\n 'flex w-full font-sans resize-y',\n 'bg-surface-raised-hover text-surface-fg',\n 'border border-surface-border-strong rounded-control',\n 'placeholder:text-surface-fg-subtle',\n 'hover:bg-surface-raised-active',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 focus-visible:border-accent-7',\n 'disabled:cursor-not-allowed disabled:opacity-action-disabled',\n 'read-only:bg-surface-raised read-only:cursor-default',\n ],\n {\n variants: {\n size: {\n xs: 'min-h-[48px] text-ds-sm px-ds-02 py-ds-02',\n sm: 'min-h-[60px] text-ds-sm px-ds-03 py-ds-02',\n md: 'min-h-[80px] text-ds-md px-ds-04 py-ds-03',\n lg: 'min-h-[120px] text-ds-md px-ds-05 py-ds-04',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\n/**\n * Props for Textarea — a resizable multi-line text input with size variants and validation state coloring,\n * sharing the same `InputState` type as `<Input>`.\n *\n * **Sizes:** `sm` (min 60px) | `md` (min 80px, default) | `lg` (min 120px) — all are vertically resizable.\n *\n * **Validation states:** `state=\"error\"` | `\"warning\"` | `\"success\"` — changes border color and focus ring.\n * HTML's native `size` attribute is omitted; use `rows` for initial height or CSS `min-height`.\n *\n * **Pair with FormField:** Use inside `<FormField>` to get a label, helper text, and associated `state`.\n *\n * @example\n * // Basic description textarea in a form:\n * <Textarea placeholder=\"Describe the issue...\" rows={4} />\n *\n * @example\n * // Error state when validation fails:\n * <Textarea state=\"error\" value={bio} onChange={(e) => setBio(e.target.value)} />\n *\n * @example\n * // Large textarea for a full email draft composer:\n * <Textarea size=\"lg\" placeholder=\"Write your message...\" className=\"min-h-[200px]\" />\n *\n * @example\n * // Read-only view of a previously submitted note:\n * <Textarea readOnly value={submission.notes} size=\"md\" />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface TextareaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'>,\n VariantProps<typeof textareaVariants> {\n state?: InputState\n}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, state: stateProp, size, ...props }, ref) => {\n const fieldCtx = useFormField()\n // Merge FormField context — explicit props always win\n const state = stateProp ?? (fieldCtx.state === 'helper' ? undefined : fieldCtx.state as InputState | undefined)\n const ariaDescribedBy = props['aria-describedby'] ?? fieldCtx.helperTextId\n const ariaRequired = props['aria-required'] ?? fieldCtx.required\n\n return (\n <motion.textarea\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n className={cn(\n textareaVariants({ size }),\n state === 'error' && 'border-error-7 focus-visible:ring-error-7',\n state === 'warning' && 'border-warning-7 focus-visible:ring-warning-7',\n state === 'success' && 'border-success-7 focus-visible:ring-success-7',\n className,\n )}\n ref={ref}\n {...motionProps(props)}\n />\n )\n },\n)\nTextarea.displayName = 'Textarea'\n\nexport { Textarea, textareaVariants }\n"],"mappings":";;;;;;;;;AAWA,IAAM,IAAmB,EACvB;CACE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EACD;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACL,EACF;CACD,iBAAiB,EAAE,MAAM,MAAM;CAChC,CACF,EAoCK,IAAW,EAAM,YACpB,EAAE,cAAW,OAAO,GAAW,SAAM,GAAG,KAAS,MAAQ;CACxD,IAAM,IAAW,GAAc,EAEzB,IAAQ,MAAc,EAAS,UAAU,WAAW,KAAA,IAAY,EAAS,QACzE,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS;AAExD,QACE,kBAAC,EAAO,UAAR;EACE,gBAAc,MAAU,WAAW,KAAA;EACnC,oBAAkB;EAClB,iBAAe,KAAgB,KAAA;EAC/B,WAAW,EACT,EAAiB,EAAE,SAAM,CAAC,EAC1B,MAAU,WAAW,6CACrB,MAAU,aAAa,iDACvB,MAAU,aAAa,iDACvB,EACD;EACI;EACL,GAAI,EAAY,EAAM;EACtB,CAAA;EAGP;AACD,EAAS,cAAc"}
1
+ {"version":3,"file":"textarea.js","names":[],"sources":["../../src/ui/textarea.tsx"],"sourcesContent":["'use client'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { motionProps } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst textareaVariants = cva(\n [\n 'flex w-full font-sans resize-y',\n 'bg-surface-raised-hover text-surface-fg',\n 'border border-surface-border-strong rounded-control',\n 'placeholder:text-surface-fg-subtle',\n 'hover:bg-surface-raised-active',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 focus-visible:border-accent-7',\n 'disabled:cursor-not-allowed disabled:opacity-action-disabled',\n 'read-only:bg-surface-raised read-only:cursor-default',\n ],\n {\n variants: {\n // Min-height ramp 48/60/80/120: 48/80 map to spacing tokens (ds-09/ds-11);\n // 60/120 have no exact token so stay arbitrary (allowed). Rendered sizes unchanged.\n size: {\n xs: 'min-h-ds-09 text-ds-sm px-ds-02 py-ds-02',\n sm: 'min-h-[60px] text-ds-sm px-ds-03 py-ds-02',\n md: 'min-h-ds-11 text-ds-md px-ds-04 py-ds-03',\n lg: 'min-h-[120px] text-ds-md px-ds-05 py-ds-04',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\n/**\n * Props for Textarea — a resizable multi-line text input with size variants and validation state coloring,\n * sharing the same `FieldState` type as every form control.\n *\n * **Sizes:** `sm` (min 60px) | `md` (min 80px, default) | `lg` (min 120px) — all are vertically resizable.\n *\n * **Validation states:** `state=\"error\"` | `\"warning\"` | `\"success\"` — changes border color and focus ring.\n * HTML's native `size` attribute is omitted; use `rows` for initial height or CSS `min-height`.\n *\n * **Pair with FormField:** Use inside `<FormField>` to get a label, helper text, and associated `state`.\n *\n * @example\n * // Basic description textarea in a form:\n * <Textarea placeholder=\"Describe the issue...\" rows={4} />\n *\n * @example\n * // Error state when validation fails:\n * <Textarea state=\"error\" value={bio} onChange={(e) => setBio(e.target.value)} />\n *\n * @example\n * // Large textarea for a full email draft composer:\n * <Textarea size=\"lg\" placeholder=\"Write your message...\" className=\"min-h-[200px]\" />\n *\n * @example\n * // Read-only view of a previously submitted note:\n * <Textarea readOnly value={submission.notes} size=\"md\" />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface TextareaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'>,\n VariantProps<typeof textareaVariants> {\n state?: FieldState\n}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, state: stateProp, size, ...props }, ref) => {\n const fieldCtx = useFormField()\n // Merge FormField context — explicit props always win (shared precedence)\n const state = resolveFieldState(stateProp, fieldCtx.state)\n const ariaDescribedBy = props['aria-describedby'] ?? fieldCtx.helperTextId\n const ariaRequired = props['aria-required'] ?? fieldCtx.required\n\n return (\n <motion.textarea\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n className={cn(\n textareaVariants({ size }),\n state === 'error' && 'border-error-7 focus-visible:ring-error-7',\n state === 'warning' && 'border-warning-7 focus-visible:ring-warning-7',\n state === 'success' && 'border-success-7 focus-visible:ring-success-7',\n className,\n )}\n ref={ref}\n {...motionProps(props)}\n />\n )\n },\n)\nTextarea.displayName = 'Textarea'\n\nexport { Textarea, textareaVariants }\n"],"mappings":";;;;;;;;;;AAWA,IAAM,IAAmB,EACvB;CACE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EACD;CACE,UAAU,EAGR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACL,EACF;CACD,iBAAiB,EAAE,MAAM,MAAM;CAChC,CACF,EAoCK,IAAW,EAAM,YACpB,EAAE,cAAW,OAAO,GAAW,SAAM,GAAG,KAAS,MAAQ;CACxD,IAAM,IAAW,GAAc,EAEzB,IAAQ,EAAkB,GAAW,EAAS,MAAM,EACpD,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS;AAExD,QACE,kBAAC,EAAO,UAAR;EACE,gBAAc,MAAU,WAAW,KAAA;EACnC,oBAAkB;EAClB,iBAAe,KAAgB,KAAA;EAC/B,WAAW,EACT,EAAiB,EAAE,SAAM,CAAC,EAC1B,MAAU,WAAW,6CACrB,MAAU,aAAa,iDACvB,MAAU,aAAa,iDACvB,EACD;EACI;EACL,GAAI,EAAY,EAAM;EACtB,CAAA;EAGP;AACD,EAAS,cAAc"}
package/dist/ui/toast.js CHANGED
@@ -52,7 +52,7 @@ var w = 5e3, T = 8e3, E = 3e3, D = {
52
52
  function O({ duration: e, type: t, paused: r }) {
53
53
  let i = D[t];
54
54
  return /* @__PURE__ */ c("div", {
55
- className: "absolute bottom-0 left-0 right-0 h-[2px] overflow-hidden",
55
+ className: "absolute bottom-0 left-0 right-0 h-ds-01 overflow-hidden",
56
56
  children: /* @__PURE__ */ c("div", {
57
57
  className: n("h-full w-full origin-left opacity-30", i.timerBarClass, "motion-safe:animate-timer-bar"),
58
58
  style: {
@@ -195,7 +195,7 @@ function M(e) {
195
195
  switch (e) {
196
196
  case "complete": return "success";
197
197
  case "error": return "error";
198
- default: return "default";
198
+ default: return "accent";
199
199
  }
200
200
  }
201
201
  function N(e) {
@@ -1 +1 @@
1
- {"version":3,"file":"toast.js","names":[],"sources":["../../src/ui/toast.tsx"],"sourcesContent":["'use client'\n\nimport {\n IconAlertCircle,\n IconAlertTriangle,\n IconCheck,\n IconCircleCheck,\n IconCircleX,\n IconFile,\n IconInfoCircle,\n IconPhoto,\n IconRefresh,\n IconUpload,\n IconX,\n} from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\nimport { type ExternalToast,toast as sonnerToast } from 'sonner'\n\nimport { Icon } from './icon'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\nimport { Progress } from './progress'\nimport { Spinner } from './spinner'\nimport { assertToasterMounted } from './toast-registry'\nimport type {\n ToastActionOptions,\n ToastOptions,\n ToastType,\n ToastUndoOptions,\n ToastUploadOptions,\n UploadFile,\n} from './toast-types'\n\n/* ---------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------ */\n\nconst DEFAULT_DURATION = 5000\nconst UNDO_DURATION = 8000\nconst UPLOAD_COMPLETE_DELAY = 3000\n\n/* ---------------------------------------------------------------------------\n * Accent bar & icon config per toast type\n * ------------------------------------------------------------------------ */\n\nconst TOAST_TYPE_CONFIG: Record<\n ToastType,\n {\n accentClass: string\n iconClass: string\n icon: React.ForwardRefExoticComponent<any> | null\n timerBarClass: string\n }\n> = {\n message: {\n accentClass: '',\n iconClass: '',\n icon: null,\n timerBarClass: 'bg-surface-border',\n },\n success: {\n accentClass: 'bg-success-9',\n iconClass: 'text-success-11',\n icon: IconCircleCheck,\n timerBarClass: 'bg-success-9',\n },\n error: {\n accentClass: 'bg-error-9',\n iconClass: 'text-error-11',\n icon: IconCircleX,\n timerBarClass: 'bg-error-9',\n },\n warning: {\n accentClass: 'bg-warning-9',\n iconClass: 'text-warning-11',\n icon: IconAlertTriangle,\n timerBarClass: 'bg-warning-9',\n },\n info: {\n accentClass: 'bg-info-9',\n iconClass: 'text-info-11',\n icon: IconInfoCircle,\n timerBarClass: 'bg-info-9',\n },\n loading: {\n accentClass: 'bg-accent-9',\n iconClass: 'text-accent-11',\n icon: null,\n timerBarClass: 'bg-accent-9',\n },\n}\n\n/* ---------------------------------------------------------------------------\n * Timer bar — shows auto-dismiss countdown\n * ------------------------------------------------------------------------ */\n\nfunction TimerBar({\n duration,\n type,\n paused,\n}: {\n duration: number\n type: ToastType\n paused: boolean\n}) {\n const config = TOAST_TYPE_CONFIG[type]\n return (\n <div className=\"absolute bottom-0 left-0 right-0 h-[2px] overflow-hidden\">\n <div\n className={cn(\n 'h-full w-full origin-left opacity-30',\n config.timerBarClass,\n 'motion-safe:animate-timer-bar',\n )}\n style={{\n animationDuration: `${duration}ms`,\n animationPlayState: paused ? 'paused' : 'running',\n }}\n />\n </div>\n )\n}\n\n/* ---------------------------------------------------------------------------\n * Base toast UI — used by all typed toasts\n * ------------------------------------------------------------------------ */\n\nfunction ToastContent({\n type,\n title,\n description,\n action,\n cancel,\n duration = DEFAULT_DURATION,\n showTimerBar = true,\n showAccent = false,\n selfDismissId,\n}: {\n type: ToastType\n title?: React.ReactNode\n description?: React.ReactNode\n action?: ToastActionOptions\n cancel?: ToastActionOptions\n duration?: number\n showTimerBar?: boolean\n /** Render the colored left accent bar. Off by default (status = icon + timer bar). */\n showAccent?: boolean\n /** When set, this component manages its own dismiss timer (hover-aware). */\n selfDismissId?: string | number\n}) {\n const [hovered, setHovered] = React.useState(false)\n const [focused, setFocused] = React.useState(false)\n const paused = hovered || focused\n const config = TOAST_TYPE_CONFIG[type]\n const StatusIcon = config.icon\n\n // Self-managed dismiss timer that pauses on hover or keyboard focus\n const remainingRef = React.useRef(duration)\n const startTimeRef = React.useRef(0)\n\n React.useEffect(() => {\n if (selfDismissId == null || duration === Infinity) return\n if (paused) {\n // Pause: save remaining time\n const elapsed = Date.now() - startTimeRef.current\n remainingRef.current = Math.max(0, remainingRef.current - elapsed)\n return\n }\n // Start/resume timer\n startTimeRef.current = Date.now()\n const timer = setTimeout(() => {\n sonnerToast.dismiss(selfDismissId)\n }, remainingRef.current)\n return () => clearTimeout(timer)\n }, [selfDismissId, duration, paused])\n\n // Error toasts announce assertively so screen readers interrupt;\n // warnings stay polite but atomically re-read the message.\n const isUrgent = type === 'error'\n return (\n <motion.div\n layout=\"position\"\n role={isUrgent ? 'alert' : 'status'}\n aria-live={isUrgent ? 'assertive' : 'polite'}\n aria-atomic=\"true\"\n className={cn(\n 'group relative flex w-full overflow-hidden rounded-overlay-sm bg-surface-overlay shadow-floating',\n // Faint surface tint on error only — the one you must not miss.\n type === 'error' && 'bg-error-2',\n )}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onFocusCapture={() => setFocused(true)}\n onBlurCapture={() => setFocused(false)}\n transition={springs.smooth}\n >\n {/* Left accent bar — opt-in via showAccent (status is carried by icon + timer bar) */}\n {showAccent && config.accentClass && (\n <div\n className={cn('w-1 shrink-0 rounded-l-overlay-sm', config.accentClass)}\n />\n )}\n\n {/* Content */}\n <div className=\"flex min-w-0 flex-1 items-start gap-ds-03 p-ds-04\">\n {/* Status icon — animates between spinner ↔ typed icon */}\n <AnimatePresence mode=\"wait\">\n {type === 'loading' ? (\n <motion.div\n key=\"loading\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={tweens.fade}\n className=\"mt-0.5 shrink-0\"\n >\n <Spinner size=\"sm\" className=\"h-4 w-4\" />\n </motion.div>\n ) : StatusIcon ? (\n <motion.div\n key={type}\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n className=\"mt-0.5 shrink-0\"\n >\n <Icon icon={StatusIcon} size=\"sm\" className={config.iconClass} />\n </motion.div>\n ) : null}\n </AnimatePresence>\n\n {/* Text */}\n <div className=\"min-w-0 flex-1\">\n {title && (\n <p className=\"text-ds-md font-semibold text-surface-fg\">\n {title}\n </p>\n )}\n {description && (\n <p\n className={cn(\n 'text-ds-sm text-surface-fg-muted',\n title && 'mt-0.5',\n )}\n >\n {description}\n </p>\n )}\n\n {/* Action / cancel buttons */}\n {(action || cancel) && (\n <div className=\"mt-ds-03 flex items-center gap-ds-03\">\n {action && (\n <button\n type=\"button\"\n onClick={action.onClick}\n className=\"text-ds-sm font-medium text-accent-11 underline-offset-2 hover:underline hover:bg-surface-raised-hover rounded-control-inner px-ds-02 py-ds-01 transition-[color,background-color] duration-fast-01 ease-productive-standard focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:rounded-control-inner\"\n >\n {action.label}\n </button>\n )}\n {cancel && (\n <button\n type=\"button\"\n onClick={cancel.onClick}\n className=\"text-ds-sm text-surface-fg-muted hover:text-surface-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:rounded-control-inner\"\n >\n {cancel.label}\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Timer bar */}\n {showTimerBar && type !== 'loading' && (\n <TimerBar duration={duration} type={type} paused={paused} />\n )}\n </motion.div>\n )\n}\n\n/* ---------------------------------------------------------------------------\n * Upload toast UI\n * ------------------------------------------------------------------------ */\n\nconst IMAGE_EXTENSIONS = new Set([\n 'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif',\n])\n\nfunction isImageFile(file: UploadFile): boolean {\n if (file.previewUrl) return true\n const ext = file.name.split('.').pop()?.toLowerCase() ?? ''\n return IMAGE_EXTENSIONS.has(ext)\n}\n\nfunction getProgressColor(\n status: UploadFile['status'],\n): 'default' | 'success' | 'error' {\n switch (status) {\n case 'complete':\n return 'success'\n case 'error':\n return 'error'\n default:\n return 'default'\n }\n}\n\nfunction getProgressValue(file: UploadFile): number | undefined {\n switch (file.status) {\n case 'pending':\n return 0\n case 'uploading':\n return file.progress ?? 0\n case 'processing':\n return undefined\n case 'complete':\n return 100\n case 'error':\n return file.progress ?? 0\n }\n}\n\nfunction formatFileSize(bytes: number): string {\n if (!bytes || bytes < 0 || !Number.isFinite(bytes)) return '0 B'\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n\nfunction UploadFileRow({\n file,\n onRetry,\n onRemove,\n}: {\n file: UploadFile\n onRetry?: (fileId: string) => void\n onRemove?: (fileId: string) => void\n}) {\n const isTerminal = file.status === 'complete' || file.status === 'error'\n const isUploading =\n file.status === 'uploading' || file.status === 'processing'\n\n return (\n <motion.div\n layout\n className=\"flex items-center gap-ds-02 py-1\"\n initial={false}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, x: -20, height: 0 }}\n transition={springs.snappy}\n >\n {/* File icon — animates between states */}\n <div className=\"flex h-5 w-5 shrink-0 items-center justify-center\">\n <AnimatePresence mode=\"wait\">\n {file.status === 'complete' ? (\n <motion.div\n key=\"complete\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n >\n <Icon icon={IconCheck} size=\"xs\" className=\"text-success-11\" />\n </motion.div>\n ) : file.status === 'error' ? (\n <motion.div\n key=\"error\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={tweens.fade}\n >\n <Icon icon={IconAlertCircle} size=\"xs\" className=\"text-error-11\" />\n </motion.div>\n ) : file.status === 'processing' ? (\n <motion.div\n key=\"processing\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Spinner size=\"sm\" className=\"h-3.5 w-3.5\" />\n </motion.div>\n ) : isImageFile(file) ? (\n <motion.div\n key=\"image\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Icon icon={IconPhoto} size=\"xs\" className=\"text-surface-fg-muted\" />\n </motion.div>\n ) : (\n <motion.div\n key=\"file\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Icon icon={IconFile} size=\"xs\" className=\"text-surface-fg-muted\" />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n\n {/* Filename */}\n <span className=\"min-w-0 flex-1 truncate text-ds-xs text-surface-fg\">\n {file.name}\n </span>\n\n {/* Progress bar or status */}\n {isUploading ? (\n <div className=\"flex w-16 items-center gap-1\">\n <Progress\n size=\"sm\"\n color={getProgressColor(file.status)}\n value={getProgressValue(file)}\n className=\"flex-1\"\n />\n {file.progress !== undefined && (\n <span className=\"shrink-0 text-ds-xs tabular-nums text-surface-fg-muted\">\n {file.progress}%\n </span>\n )}\n </div>\n ) : file.status === 'complete' ? (\n <span className=\"text-ds-xs text-success-11\">Done</span>\n ) : file.status === 'error' ? (\n <span className=\"max-w-[60px] truncate text-ds-xs text-error-11\">\n {file.error || 'Failed'}\n </span>\n ) : (\n <span className=\"text-ds-xs text-surface-fg-muted\">\n {formatFileSize(file.size)}\n </span>\n )}\n\n {/* Actions */}\n {file.status === 'error' && onRetry && (\n <button\n type=\"button\"\n onClick={() => onRetry(file.id)}\n className=\"touch-target flex min-h-6 min-w-6 items-center justify-center rounded-control-inner text-surface-fg-muted hover:text-surface-fg\"\n aria-label={`Retry ${file.name}`}\n title=\"Retry\"\n >\n <IconRefresh className=\"h-3.5 w-3.5\" />\n </button>\n )}\n {!isTerminal && onRemove && (\n <button\n type=\"button\"\n onClick={() => onRemove(file.id)}\n className=\"touch-target flex min-h-6 min-w-6 items-center justify-center rounded-control-inner text-surface-fg-muted hover:text-surface-fg\"\n aria-label={`Cancel ${file.name}`}\n title=\"Remove\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </motion.div>\n )\n}\n\nfunction UploadToastContent({\n files,\n onRetry,\n onRemove,\n selfDismissId,\n showAccent = false,\n}: {\n files: UploadFile[]\n onRetry?: (fileId: string) => void\n onRemove?: (fileId: string) => void\n selfDismissId?: string | number\n /** Render the colored left accent bar. Off by default. */\n showAccent?: boolean\n}) {\n const [hovered, setHovered] = React.useState(false)\n const [focused, setFocused] = React.useState(false)\n const paused = hovered || focused\n const completeCount = files.filter((f) => f.status === 'complete').length\n const errorCount = files.filter((f) => f.status === 'error').length\n const allTerminal = files.every(\n (f) => f.status === 'complete' || f.status === 'error',\n )\n\n // Self-managed dismiss timer that pauses on hover or keyboard focus\n const remainingRef = React.useRef(UPLOAD_COMPLETE_DELAY)\n const startTimeRef = React.useRef(0)\n\n React.useEffect(() => {\n if (selfDismissId == null || !allTerminal) return\n if (paused) {\n const elapsed = Date.now() - startTimeRef.current\n remainingRef.current = Math.max(0, remainingRef.current - elapsed)\n return\n }\n startTimeRef.current = Date.now()\n const timer = setTimeout(() => {\n sonnerToast.dismiss(selfDismissId)\n }, remainingRef.current)\n return () => clearTimeout(timer)\n }, [selfDismissId, allTerminal, paused])\n\n const accentClass = allTerminal\n ? errorCount > 0\n ? 'bg-error-7'\n : 'bg-success-7'\n : 'bg-accent-9'\n\n const timerBarType: ToastType = allTerminal\n ? errorCount > 0\n ? 'error'\n : 'success'\n : 'loading'\n\n const uploadUrgent = allTerminal && errorCount > 0\n return (\n <motion.div\n layout\n role={uploadUrgent ? 'alert' : 'status'}\n aria-live={uploadUrgent ? 'assertive' : 'polite'}\n aria-label=\"File uploads\"\n className={cn(\n 'group relative flex w-full overflow-hidden rounded-overlay-sm bg-surface-overlay shadow-floating',\n // Faint surface tint when the batch ended with failures.\n uploadUrgent && 'bg-error-2',\n )}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onFocusCapture={() => setFocused(true)}\n onBlurCapture={() => setFocused(false)}\n transition={springs.smooth}\n >\n {/* Left accent bar — opt-in via showAccent */}\n {showAccent && (\n <div className={cn('w-1 shrink-0 rounded-l-overlay-sm', accentClass)} />\n )}\n\n {/* Content */}\n <div className=\"min-w-0 flex-1 p-ds-04\">\n {/* Header — icon morphs between upload ↔ result */}\n <div className=\"flex items-center gap-ds-02\">\n <AnimatePresence mode=\"wait\">\n {allTerminal ? (\n errorCount > 0 ? (\n <motion.div\n key=\"error-icon\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n >\n <Icon icon={IconAlertCircle} size=\"sm\" className=\"shrink-0 text-error-11\" />\n </motion.div>\n ) : (\n <motion.div\n key=\"success-icon\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n >\n <Icon icon={IconCheck} size=\"sm\" className=\"shrink-0 text-success-11\" />\n </motion.div>\n )\n ) : (\n <motion.div\n key=\"upload-icon\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Icon icon={IconUpload} size=\"sm\" className=\"shrink-0 text-surface-fg-muted\" />\n </motion.div>\n )}\n </AnimatePresence>\n <p className=\"text-ds-md font-semibold text-surface-fg\">\n {allTerminal\n ? errorCount > 0\n ? `${completeCount} of ${files.length} uploaded`\n : `${files.length} file${files.length > 1 ? 's' : ''} uploaded`\n : `Uploading ${files.length} file${files.length > 1 ? 's' : ''}`}\n </p>\n </div>\n {!allTerminal && (\n <p className=\"mt-0.5 text-ds-xs text-surface-fg-muted\">\n {completeCount} of {files.length} complete\n {errorCount > 0 && ` · ${errorCount} failed`}\n </p>\n )}\n\n {/* File list */}\n <div className=\"mt-ds-02 max-h-[140px] overflow-y-auto\">\n <AnimatePresence>\n {files.map((file) => (\n <UploadFileRow\n key={file.id}\n file={file}\n onRetry={onRetry}\n onRemove={onRemove}\n />\n ))}\n </AnimatePresence>\n </div>\n\n {/* Screen reader announcement */}\n <div className=\"sr-only\" aria-live=\"polite\">\n {completeCount} of {files.length} files uploaded\n {errorCount > 0 && `, ${errorCount} failed`}\n </div>\n </div>\n\n {/* Timer bar — only after all terminal */}\n {allTerminal && (\n <TimerBar\n duration={UPLOAD_COMPLETE_DELAY}\n type={timerBarType}\n paused={false}\n />\n )}\n </motion.div>\n )\n}\n\n/* ---------------------------------------------------------------------------\n * Toast API — wraps Sonner with our styled UI\n * ------------------------------------------------------------------------ */\n\nfunction createSonnerOptions(\n options?: ToastOptions,\n duration?: number,\n): ExternalToast {\n return {\n id: options?.id,\n duration: options?.duration ?? duration ?? DEFAULT_DURATION,\n unstyled: true,\n classNames: { toast: 'w-full' },\n }\n}\n\nfunction createTypedToast(\n type: ToastType,\n message: string | React.ReactNode,\n options?: ToastOptions,\n) {\n assertToasterMounted()\n const duration = options?.duration ?? DEFAULT_DURATION\n return sonnerToast.custom(\n () => (\n <ToastContent\n type={type}\n title={message}\n description={options?.description}\n action={options?.action}\n cancel={options?.cancel}\n duration={duration}\n showAccent={options?.showAccent}\n />\n ),\n createSonnerOptions(options, duration),\n )\n}\n\n/**\n * Toast API — imperative toast notifications with Sonner rendering engine.\n *\n * Mount `<Toaster />` once at your root layout. Then call `toast()` from anywhere.\n *\n * @example\n * toast('Something happened')\n * toast.success('Saved!')\n * toast.error('Failed to save')\n * toast.promise(saveFn(), { loading: 'Saving...', success: 'Done!', error: 'Failed' })\n * toast.undo('Deleted', { onUndo: () => restore() })\n * toast.upload({ files, onRetry, onRemove })\n */\nfunction toast(message: string | React.ReactNode, options?: ToastOptions) {\n return createTypedToast('message', message, options)\n}\n\ntoast.message = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('message', message, options)\n}\n\ntoast.success = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('success', message, options)\n}\n\ntoast.error = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('error', message, options)\n}\n\ntoast.warning = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('warning', message, options)\n}\n\ntoast.info = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('info', message, options)\n}\n\ntoast.loading = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('loading', message, {\n ...options,\n duration: options?.duration ?? Infinity,\n })\n}\n\ntoast.promise = <T,>(\n promise: Promise<T>,\n options: {\n loading: string | React.ReactNode\n success: string | React.ReactNode | ((data: T) => string | React.ReactNode)\n error:\n | string\n | React.ReactNode\n | ((error: unknown) => string | React.ReactNode)\n },\n) => {\n const id = sonnerToast.custom(\n () => (\n <ToastContent type=\"loading\" title={options.loading} showTimerBar={false} />\n ),\n { duration: Infinity, unstyled: true, classNames: { toast: 'w-full' } },\n )\n\n const replaceWith = (type: ToastType, message: React.ReactNode) => {\n // Sonner doesn't reset its auto-dismiss timer when updating a custom toast\n // in-place from duration: Infinity, so ToastContent manages its own\n // hover-aware dismiss timer via selfDismissId.\n sonnerToast.custom(\n () => (\n <ToastContent\n type={type}\n title={message}\n duration={DEFAULT_DURATION}\n selfDismissId={id}\n />\n ),\n { id, duration: Infinity, unstyled: true, classNames: { toast: 'w-full' } },\n )\n }\n\n promise\n .then((data) => {\n const message =\n typeof options.success === 'function'\n ? options.success(data)\n : options.success\n replaceWith('success', message)\n })\n .catch((error) => {\n const message =\n typeof options.error === 'function'\n ? options.error(error)\n : options.error\n replaceWith('error', message)\n })\n\n return id\n}\n\ntoast.undo = (message: string | React.ReactNode, options: ToastUndoOptions) => {\n const duration = options.duration ?? UNDO_DURATION\n return sonnerToast.custom(\n () => (\n <ToastContent\n type=\"message\"\n title={message}\n description={options.description}\n action={{ label: 'Undo', onClick: options.onUndo }}\n duration={duration}\n />\n ),\n { duration, unstyled: true, classNames: { toast: 'w-full' } },\n )\n}\n\ntoast.upload = (options: ToastUploadOptions) => {\n // Pre-determine the id so we can pass it to UploadToastContent for self-dismiss.\n const toastId = options.id ?? String(Date.now())\n\n sonnerToast.custom(\n () => (\n <UploadToastContent\n files={options.files}\n onRetry={options.onRetry}\n onRemove={options.onRemove}\n selfDismissId={toastId}\n showAccent={options.showAccent}\n />\n ),\n {\n id: toastId,\n duration: Infinity,\n unstyled: true,\n classNames: { toast: 'w-full' },\n },\n )\n\n return toastId\n}\n\ntoast.custom = (\n render: (id: string | number) => React.ReactElement,\n options?: ExternalToast,\n) => {\n return sonnerToast.custom(render, {\n ...options,\n unstyled: true,\n classNames: { toast: 'w-full', ...(options?.classNames as Record<string, string>) },\n })\n}\n\ntoast.dismiss = (id?: string | number) => {\n if (id !== undefined) {\n sonnerToast.dismiss(id)\n } else {\n sonnerToast.dismiss()\n }\n}\n\n/* ---------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------ */\n\nexport type ToastProps = ToastOptions\n\nexport {\n formatFileSize,\n TimerBar,\n toast,\n ToastContent,\n UploadFileRow,\n UploadToastContent,\n}\nexport type {\n ToastActionOptions,\n ToastOptions,\n ToastType,\n ToastUndoOptions,\n ToastUploadOptions,\n UploadFile,\n} from './toast-types'\n"],"mappings":"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"}
1
+ {"version":3,"file":"toast.js","names":[],"sources":["../../src/ui/toast.tsx"],"sourcesContent":["'use client'\n\nimport {\n IconAlertCircle,\n IconAlertTriangle,\n IconCheck,\n IconCircleCheck,\n IconCircleX,\n IconFile,\n IconInfoCircle,\n IconPhoto,\n IconRefresh,\n IconUpload,\n IconX,\n} from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\nimport { type ExternalToast,toast as sonnerToast } from 'sonner'\n\nimport { Icon } from './icon'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\nimport { Progress } from './progress'\nimport { Spinner } from './spinner'\nimport { assertToasterMounted } from './toast-registry'\nimport type {\n ToastActionOptions,\n ToastOptions,\n ToastType,\n ToastUndoOptions,\n ToastUploadOptions,\n UploadFile,\n} from './toast-types'\n\n/* ---------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------ */\n\nconst DEFAULT_DURATION = 5000\nconst UNDO_DURATION = 8000\nconst UPLOAD_COMPLETE_DELAY = 3000\n\n/* ---------------------------------------------------------------------------\n * Accent bar & icon config per toast type\n * ------------------------------------------------------------------------ */\n\nconst TOAST_TYPE_CONFIG: Record<\n ToastType,\n {\n accentClass: string\n iconClass: string\n icon: React.ForwardRefExoticComponent<any> | null\n timerBarClass: string\n }\n> = {\n message: {\n accentClass: '',\n iconClass: '',\n icon: null,\n timerBarClass: 'bg-surface-border',\n },\n success: {\n accentClass: 'bg-success-9',\n iconClass: 'text-success-11',\n icon: IconCircleCheck,\n timerBarClass: 'bg-success-9',\n },\n error: {\n accentClass: 'bg-error-9',\n iconClass: 'text-error-11',\n icon: IconCircleX,\n timerBarClass: 'bg-error-9',\n },\n warning: {\n accentClass: 'bg-warning-9',\n iconClass: 'text-warning-11',\n icon: IconAlertTriangle,\n timerBarClass: 'bg-warning-9',\n },\n info: {\n accentClass: 'bg-info-9',\n iconClass: 'text-info-11',\n icon: IconInfoCircle,\n timerBarClass: 'bg-info-9',\n },\n loading: {\n accentClass: 'bg-accent-9',\n iconClass: 'text-accent-11',\n icon: null,\n timerBarClass: 'bg-accent-9',\n },\n}\n\n/* ---------------------------------------------------------------------------\n * Timer bar — shows auto-dismiss countdown\n * ------------------------------------------------------------------------ */\n\nfunction TimerBar({\n duration,\n type,\n paused,\n}: {\n duration: number\n type: ToastType\n paused: boolean\n}) {\n const config = TOAST_TYPE_CONFIG[type]\n return (\n <div className=\"absolute bottom-0 left-0 right-0 h-ds-01 overflow-hidden\">\n <div\n className={cn(\n 'h-full w-full origin-left opacity-30',\n config.timerBarClass,\n 'motion-safe:animate-timer-bar',\n )}\n style={{\n animationDuration: `${duration}ms`,\n animationPlayState: paused ? 'paused' : 'running',\n }}\n />\n </div>\n )\n}\n\n/* ---------------------------------------------------------------------------\n * Base toast UI — used by all typed toasts\n * ------------------------------------------------------------------------ */\n\nfunction ToastContent({\n type,\n title,\n description,\n action,\n cancel,\n duration = DEFAULT_DURATION,\n showTimerBar = true,\n showAccent = false,\n selfDismissId,\n}: {\n type: ToastType\n title?: React.ReactNode\n description?: React.ReactNode\n action?: ToastActionOptions\n cancel?: ToastActionOptions\n duration?: number\n showTimerBar?: boolean\n /** Render the colored left accent bar. Off by default (status = icon + timer bar). */\n showAccent?: boolean\n /** When set, this component manages its own dismiss timer (hover-aware). */\n selfDismissId?: string | number\n}) {\n const [hovered, setHovered] = React.useState(false)\n const [focused, setFocused] = React.useState(false)\n const paused = hovered || focused\n const config = TOAST_TYPE_CONFIG[type]\n const StatusIcon = config.icon\n\n // Self-managed dismiss timer that pauses on hover or keyboard focus\n const remainingRef = React.useRef(duration)\n const startTimeRef = React.useRef(0)\n\n React.useEffect(() => {\n if (selfDismissId == null || duration === Infinity) return\n if (paused) {\n // Pause: save remaining time\n const elapsed = Date.now() - startTimeRef.current\n remainingRef.current = Math.max(0, remainingRef.current - elapsed)\n return\n }\n // Start/resume timer\n startTimeRef.current = Date.now()\n const timer = setTimeout(() => {\n sonnerToast.dismiss(selfDismissId)\n }, remainingRef.current)\n return () => clearTimeout(timer)\n }, [selfDismissId, duration, paused])\n\n // Error toasts announce assertively so screen readers interrupt;\n // warnings stay polite but atomically re-read the message.\n const isUrgent = type === 'error'\n return (\n <motion.div\n layout=\"position\"\n role={isUrgent ? 'alert' : 'status'}\n aria-live={isUrgent ? 'assertive' : 'polite'}\n aria-atomic=\"true\"\n className={cn(\n 'group relative flex w-full overflow-hidden rounded-overlay-sm bg-surface-overlay shadow-floating',\n // Faint surface tint on error only — the one you must not miss.\n type === 'error' && 'bg-error-2',\n )}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onFocusCapture={() => setFocused(true)}\n onBlurCapture={() => setFocused(false)}\n transition={springs.smooth}\n >\n {/* Left accent bar — opt-in via showAccent (status is carried by icon + timer bar) */}\n {showAccent && config.accentClass && (\n <div\n className={cn('w-1 shrink-0 rounded-l-overlay-sm', config.accentClass)}\n />\n )}\n\n {/* Content */}\n <div className=\"flex min-w-0 flex-1 items-start gap-ds-03 p-ds-04\">\n {/* Status icon — animates between spinner ↔ typed icon */}\n <AnimatePresence mode=\"wait\">\n {type === 'loading' ? (\n <motion.div\n key=\"loading\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={tweens.fade}\n className=\"mt-0.5 shrink-0\"\n >\n <Spinner size=\"sm\" className=\"h-4 w-4\" />\n </motion.div>\n ) : StatusIcon ? (\n <motion.div\n key={type}\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n className=\"mt-0.5 shrink-0\"\n >\n <Icon icon={StatusIcon} size=\"sm\" className={config.iconClass} />\n </motion.div>\n ) : null}\n </AnimatePresence>\n\n {/* Text */}\n <div className=\"min-w-0 flex-1\">\n {title && (\n <p className=\"text-ds-md font-semibold text-surface-fg\">\n {title}\n </p>\n )}\n {description && (\n <p\n className={cn(\n 'text-ds-sm text-surface-fg-muted',\n title && 'mt-0.5',\n )}\n >\n {description}\n </p>\n )}\n\n {/* Action / cancel buttons */}\n {(action || cancel) && (\n <div className=\"mt-ds-03 flex items-center gap-ds-03\">\n {action && (\n <button\n type=\"button\"\n onClick={action.onClick}\n className=\"text-ds-sm font-medium text-accent-11 underline-offset-2 hover:underline hover:bg-surface-raised-hover rounded-control-inner px-ds-02 py-ds-01 transition-[color,background-color] duration-fast-01 ease-productive-standard focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:rounded-control-inner\"\n >\n {action.label}\n </button>\n )}\n {cancel && (\n <button\n type=\"button\"\n onClick={cancel.onClick}\n className=\"text-ds-sm text-surface-fg-muted hover:text-surface-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:rounded-control-inner\"\n >\n {cancel.label}\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Timer bar */}\n {showTimerBar && type !== 'loading' && (\n <TimerBar duration={duration} type={type} paused={paused} />\n )}\n </motion.div>\n )\n}\n\n/* ---------------------------------------------------------------------------\n * Upload toast UI\n * ------------------------------------------------------------------------ */\n\nconst IMAGE_EXTENSIONS = new Set([\n 'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif',\n])\n\nfunction isImageFile(file: UploadFile): boolean {\n if (file.previewUrl) return true\n const ext = file.name.split('.').pop()?.toLowerCase() ?? ''\n return IMAGE_EXTENSIONS.has(ext)\n}\n\nfunction getProgressColor(\n status: UploadFile['status'],\n): 'accent' | 'success' | 'error' {\n switch (status) {\n case 'complete':\n return 'success'\n case 'error':\n return 'error'\n default:\n return 'accent'\n }\n}\n\nfunction getProgressValue(file: UploadFile): number | undefined {\n switch (file.status) {\n case 'pending':\n return 0\n case 'uploading':\n return file.progress ?? 0\n case 'processing':\n return undefined\n case 'complete':\n return 100\n case 'error':\n return file.progress ?? 0\n }\n}\n\nfunction formatFileSize(bytes: number): string {\n if (!bytes || bytes < 0 || !Number.isFinite(bytes)) return '0 B'\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n\nfunction UploadFileRow({\n file,\n onRetry,\n onRemove,\n}: {\n file: UploadFile\n onRetry?: (fileId: string) => void\n onRemove?: (fileId: string) => void\n}) {\n const isTerminal = file.status === 'complete' || file.status === 'error'\n const isUploading =\n file.status === 'uploading' || file.status === 'processing'\n\n return (\n <motion.div\n layout\n className=\"flex items-center gap-ds-02 py-1\"\n initial={false}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, x: -20, height: 0 }}\n transition={springs.snappy}\n >\n {/* File icon — animates between states */}\n <div className=\"flex h-5 w-5 shrink-0 items-center justify-center\">\n <AnimatePresence mode=\"wait\">\n {file.status === 'complete' ? (\n <motion.div\n key=\"complete\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n >\n <Icon icon={IconCheck} size=\"xs\" className=\"text-success-11\" />\n </motion.div>\n ) : file.status === 'error' ? (\n <motion.div\n key=\"error\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={tweens.fade}\n >\n <Icon icon={IconAlertCircle} size=\"xs\" className=\"text-error-11\" />\n </motion.div>\n ) : file.status === 'processing' ? (\n <motion.div\n key=\"processing\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Spinner size=\"sm\" className=\"h-3.5 w-3.5\" />\n </motion.div>\n ) : isImageFile(file) ? (\n <motion.div\n key=\"image\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Icon icon={IconPhoto} size=\"xs\" className=\"text-surface-fg-muted\" />\n </motion.div>\n ) : (\n <motion.div\n key=\"file\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Icon icon={IconFile} size=\"xs\" className=\"text-surface-fg-muted\" />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n\n {/* Filename */}\n <span className=\"min-w-0 flex-1 truncate text-ds-xs text-surface-fg\">\n {file.name}\n </span>\n\n {/* Progress bar or status */}\n {isUploading ? (\n <div className=\"flex w-16 items-center gap-1\">\n <Progress\n size=\"sm\"\n color={getProgressColor(file.status)}\n value={getProgressValue(file)}\n className=\"flex-1\"\n />\n {file.progress !== undefined && (\n <span className=\"shrink-0 text-ds-xs tabular-nums text-surface-fg-muted\">\n {file.progress}%\n </span>\n )}\n </div>\n ) : file.status === 'complete' ? (\n <span className=\"text-ds-xs text-success-11\">Done</span>\n ) : file.status === 'error' ? (\n <span className=\"max-w-[60px] truncate text-ds-xs text-error-11\">\n {file.error || 'Failed'}\n </span>\n ) : (\n <span className=\"text-ds-xs text-surface-fg-muted\">\n {formatFileSize(file.size)}\n </span>\n )}\n\n {/* Actions */}\n {file.status === 'error' && onRetry && (\n <button\n type=\"button\"\n onClick={() => onRetry(file.id)}\n className=\"touch-target flex min-h-6 min-w-6 items-center justify-center rounded-control-inner text-surface-fg-muted hover:text-surface-fg\"\n aria-label={`Retry ${file.name}`}\n title=\"Retry\"\n >\n <IconRefresh className=\"h-3.5 w-3.5\" />\n </button>\n )}\n {!isTerminal && onRemove && (\n <button\n type=\"button\"\n onClick={() => onRemove(file.id)}\n className=\"touch-target flex min-h-6 min-w-6 items-center justify-center rounded-control-inner text-surface-fg-muted hover:text-surface-fg\"\n aria-label={`Cancel ${file.name}`}\n title=\"Remove\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </motion.div>\n )\n}\n\nfunction UploadToastContent({\n files,\n onRetry,\n onRemove,\n selfDismissId,\n showAccent = false,\n}: {\n files: UploadFile[]\n onRetry?: (fileId: string) => void\n onRemove?: (fileId: string) => void\n selfDismissId?: string | number\n /** Render the colored left accent bar. Off by default. */\n showAccent?: boolean\n}) {\n const [hovered, setHovered] = React.useState(false)\n const [focused, setFocused] = React.useState(false)\n const paused = hovered || focused\n const completeCount = files.filter((f) => f.status === 'complete').length\n const errorCount = files.filter((f) => f.status === 'error').length\n const allTerminal = files.every(\n (f) => f.status === 'complete' || f.status === 'error',\n )\n\n // Self-managed dismiss timer that pauses on hover or keyboard focus\n const remainingRef = React.useRef(UPLOAD_COMPLETE_DELAY)\n const startTimeRef = React.useRef(0)\n\n React.useEffect(() => {\n if (selfDismissId == null || !allTerminal) return\n if (paused) {\n const elapsed = Date.now() - startTimeRef.current\n remainingRef.current = Math.max(0, remainingRef.current - elapsed)\n return\n }\n startTimeRef.current = Date.now()\n const timer = setTimeout(() => {\n sonnerToast.dismiss(selfDismissId)\n }, remainingRef.current)\n return () => clearTimeout(timer)\n }, [selfDismissId, allTerminal, paused])\n\n const accentClass = allTerminal\n ? errorCount > 0\n ? 'bg-error-7'\n : 'bg-success-7'\n : 'bg-accent-9'\n\n const timerBarType: ToastType = allTerminal\n ? errorCount > 0\n ? 'error'\n : 'success'\n : 'loading'\n\n const uploadUrgent = allTerminal && errorCount > 0\n return (\n <motion.div\n layout\n role={uploadUrgent ? 'alert' : 'status'}\n aria-live={uploadUrgent ? 'assertive' : 'polite'}\n aria-label=\"File uploads\"\n className={cn(\n 'group relative flex w-full overflow-hidden rounded-overlay-sm bg-surface-overlay shadow-floating',\n // Faint surface tint when the batch ended with failures.\n uploadUrgent && 'bg-error-2',\n )}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onFocusCapture={() => setFocused(true)}\n onBlurCapture={() => setFocused(false)}\n transition={springs.smooth}\n >\n {/* Left accent bar — opt-in via showAccent */}\n {showAccent && (\n <div className={cn('w-1 shrink-0 rounded-l-overlay-sm', accentClass)} />\n )}\n\n {/* Content */}\n <div className=\"min-w-0 flex-1 p-ds-04\">\n {/* Header — icon morphs between upload ↔ result */}\n <div className=\"flex items-center gap-ds-02\">\n <AnimatePresence mode=\"wait\">\n {allTerminal ? (\n errorCount > 0 ? (\n <motion.div\n key=\"error-icon\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n >\n <Icon icon={IconAlertCircle} size=\"sm\" className=\"shrink-0 text-error-11\" />\n </motion.div>\n ) : (\n <motion.div\n key=\"success-icon\"\n initial={{ opacity: 0, scale: 0.5 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.5 }}\n transition={springs.bouncy}\n >\n <Icon icon={IconCheck} size=\"sm\" className=\"shrink-0 text-success-11\" />\n </motion.div>\n )\n ) : (\n <motion.div\n key=\"upload-icon\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n >\n <Icon icon={IconUpload} size=\"sm\" className=\"shrink-0 text-surface-fg-muted\" />\n </motion.div>\n )}\n </AnimatePresence>\n <p className=\"text-ds-md font-semibold text-surface-fg\">\n {allTerminal\n ? errorCount > 0\n ? `${completeCount} of ${files.length} uploaded`\n : `${files.length} file${files.length > 1 ? 's' : ''} uploaded`\n : `Uploading ${files.length} file${files.length > 1 ? 's' : ''}`}\n </p>\n </div>\n {!allTerminal && (\n <p className=\"mt-0.5 text-ds-xs text-surface-fg-muted\">\n {completeCount} of {files.length} complete\n {errorCount > 0 && ` · ${errorCount} failed`}\n </p>\n )}\n\n {/* File list */}\n <div className=\"mt-ds-02 max-h-[140px] overflow-y-auto\">\n <AnimatePresence>\n {files.map((file) => (\n <UploadFileRow\n key={file.id}\n file={file}\n onRetry={onRetry}\n onRemove={onRemove}\n />\n ))}\n </AnimatePresence>\n </div>\n\n {/* Screen reader announcement */}\n <div className=\"sr-only\" aria-live=\"polite\">\n {completeCount} of {files.length} files uploaded\n {errorCount > 0 && `, ${errorCount} failed`}\n </div>\n </div>\n\n {/* Timer bar — only after all terminal */}\n {allTerminal && (\n <TimerBar\n duration={UPLOAD_COMPLETE_DELAY}\n type={timerBarType}\n paused={false}\n />\n )}\n </motion.div>\n )\n}\n\n/* ---------------------------------------------------------------------------\n * Toast API — wraps Sonner with our styled UI\n * ------------------------------------------------------------------------ */\n\nfunction createSonnerOptions(\n options?: ToastOptions,\n duration?: number,\n): ExternalToast {\n return {\n id: options?.id,\n duration: options?.duration ?? duration ?? DEFAULT_DURATION,\n unstyled: true,\n classNames: { toast: 'w-full' },\n }\n}\n\nfunction createTypedToast(\n type: ToastType,\n message: string | React.ReactNode,\n options?: ToastOptions,\n) {\n assertToasterMounted()\n const duration = options?.duration ?? DEFAULT_DURATION\n return sonnerToast.custom(\n () => (\n <ToastContent\n type={type}\n title={message}\n description={options?.description}\n action={options?.action}\n cancel={options?.cancel}\n duration={duration}\n showAccent={options?.showAccent}\n />\n ),\n createSonnerOptions(options, duration),\n )\n}\n\n/**\n * Toast API — imperative toast notifications with Sonner rendering engine.\n *\n * Mount `<Toaster />` once at your root layout. Then call `toast()` from anywhere.\n *\n * @example\n * toast('Something happened')\n * toast.success('Saved!')\n * toast.error('Failed to save')\n * toast.promise(saveFn(), { loading: 'Saving...', success: 'Done!', error: 'Failed' })\n * toast.undo('Deleted', { onUndo: () => restore() })\n * toast.upload({ files, onRetry, onRemove })\n */\nfunction toast(message: string | React.ReactNode, options?: ToastOptions) {\n return createTypedToast('message', message, options)\n}\n\ntoast.message = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('message', message, options)\n}\n\ntoast.success = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('success', message, options)\n}\n\ntoast.error = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('error', message, options)\n}\n\ntoast.warning = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('warning', message, options)\n}\n\ntoast.info = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('info', message, options)\n}\n\ntoast.loading = (\n message: string | React.ReactNode,\n options?: ToastOptions,\n) => {\n return createTypedToast('loading', message, {\n ...options,\n duration: options?.duration ?? Infinity,\n })\n}\n\ntoast.promise = <T,>(\n promise: Promise<T>,\n options: {\n loading: string | React.ReactNode\n success: string | React.ReactNode | ((data: T) => string | React.ReactNode)\n error:\n | string\n | React.ReactNode\n | ((error: unknown) => string | React.ReactNode)\n },\n) => {\n const id = sonnerToast.custom(\n () => (\n <ToastContent type=\"loading\" title={options.loading} showTimerBar={false} />\n ),\n { duration: Infinity, unstyled: true, classNames: { toast: 'w-full' } },\n )\n\n const replaceWith = (type: ToastType, message: React.ReactNode) => {\n // Sonner doesn't reset its auto-dismiss timer when updating a custom toast\n // in-place from duration: Infinity, so ToastContent manages its own\n // hover-aware dismiss timer via selfDismissId.\n sonnerToast.custom(\n () => (\n <ToastContent\n type={type}\n title={message}\n duration={DEFAULT_DURATION}\n selfDismissId={id}\n />\n ),\n { id, duration: Infinity, unstyled: true, classNames: { toast: 'w-full' } },\n )\n }\n\n promise\n .then((data) => {\n const message =\n typeof options.success === 'function'\n ? options.success(data)\n : options.success\n replaceWith('success', message)\n })\n .catch((error) => {\n const message =\n typeof options.error === 'function'\n ? options.error(error)\n : options.error\n replaceWith('error', message)\n })\n\n return id\n}\n\ntoast.undo = (message: string | React.ReactNode, options: ToastUndoOptions) => {\n const duration = options.duration ?? UNDO_DURATION\n return sonnerToast.custom(\n () => (\n <ToastContent\n type=\"message\"\n title={message}\n description={options.description}\n action={{ label: 'Undo', onClick: options.onUndo }}\n duration={duration}\n />\n ),\n { duration, unstyled: true, classNames: { toast: 'w-full' } },\n )\n}\n\ntoast.upload = (options: ToastUploadOptions) => {\n // Pre-determine the id so we can pass it to UploadToastContent for self-dismiss.\n const toastId = options.id ?? String(Date.now())\n\n sonnerToast.custom(\n () => (\n <UploadToastContent\n files={options.files}\n onRetry={options.onRetry}\n onRemove={options.onRemove}\n selfDismissId={toastId}\n showAccent={options.showAccent}\n />\n ),\n {\n id: toastId,\n duration: Infinity,\n unstyled: true,\n classNames: { toast: 'w-full' },\n },\n )\n\n return toastId\n}\n\ntoast.custom = (\n render: (id: string | number) => React.ReactElement,\n options?: ExternalToast,\n) => {\n return sonnerToast.custom(render, {\n ...options,\n unstyled: true,\n classNames: { toast: 'w-full', ...(options?.classNames as Record<string, string>) },\n })\n}\n\ntoast.dismiss = (id?: string | number) => {\n if (id !== undefined) {\n sonnerToast.dismiss(id)\n } else {\n sonnerToast.dismiss()\n }\n}\n\n/* ---------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------ */\n\nexport type ToastProps = ToastOptions\n\nexport {\n formatFileSize,\n TimerBar,\n toast,\n ToastContent,\n UploadFileRow,\n UploadToastContent,\n}\nexport type {\n ToastActionOptions,\n ToastOptions,\n ToastType,\n ToastUndoOptions,\n ToastUploadOptions,\n UploadFile,\n} from './toast-types'\n"],"mappings":";;;;;;;;;;;;;AAsCA,IAAM,IAAmB,KACnB,IAAgB,KAChB,IAAwB,KAMxB,IAQF;CACF,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;EAChB;CACD,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;EAChB;CACD,OAAO;EACL,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;EAChB;CACD,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;EAChB;CACD,MAAM;EACJ,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;EAChB;CACD,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;EAChB;CACF;AAMD,SAAS,EAAS,EAChB,aACA,SACA,aAKC;CACD,IAAM,IAAS,EAAkB;AACjC,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GACE,WAAW,EACT,wCACA,EAAO,eACP,gCACD;GACD,OAAO;IACL,mBAAmB,GAAG,EAAS;IAC/B,oBAAoB,IAAS,WAAW;IACzC;GACD,CAAA;EACE,CAAA;;AAQV,SAAS,EAAa,EACpB,SACA,UACA,gBACA,WACA,WACA,cAAW,GACX,kBAAe,IACf,gBAAa,IACb,oBAaC;CACD,IAAM,CAAC,GAAS,KAAc,EAAM,SAAS,GAAM,EAC7C,CAAC,GAAS,KAAc,EAAM,SAAS,GAAM,EAC7C,IAAS,KAAW,GACpB,IAAS,EAAkB,IAC3B,IAAa,EAAO,MAGpB,IAAe,EAAM,OAAO,EAAS,EACrC,IAAe,EAAM,OAAO,EAAE;AAEpC,GAAM,gBAAgB;AACpB,MAAI,KAAiB,QAAQ,MAAa,SAAU;AACpD,MAAI,GAAQ;GAEV,IAAM,IAAU,KAAK,KAAK,GAAG,EAAa;AAC1C,KAAa,UAAU,KAAK,IAAI,GAAG,EAAa,UAAU,EAAQ;AAClE;;AAGF,IAAa,UAAU,KAAK,KAAK;EACjC,IAAM,IAAQ,iBAAiB;AAC7B,KAAY,QAAQ,EAAc;KACjC,EAAa,QAAQ;AACxB,eAAa,aAAa,EAAM;IAC/B;EAAC;EAAe;EAAU;EAAO,CAAC;CAIrC,IAAM,IAAW,MAAS;AAC1B,QACE,kBAAC,EAAO,KAAR;EACE,QAAO;EACP,MAAM,IAAW,UAAU;EAC3B,aAAW,IAAW,cAAc;EACpC,eAAY;EACZ,WAAW,EACT,oGAEA,MAAS,WAAW,aACrB;EACD,oBAAoB,EAAW,GAAK;EACpC,oBAAoB,EAAW,GAAM;EACrC,sBAAsB,EAAW,GAAK;EACtC,qBAAqB,EAAW,GAAM;EACtC,YAAY,EAAQ;YAdtB;GAiBG,KAAc,EAAO,eACpB,kBAAC,OAAD,EACE,WAAW,EAAG,qCAAqC,EAAO,YAAY,EACtE,CAAA;GAIJ,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,GAAD;KAAiB,MAAK;eACnB,MAAS,YACR,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;OAAK;MACnC,SAAS;OAAE,SAAS;OAAG,OAAO;OAAG;MACjC,MAAM;OAAE,SAAS;OAAG,OAAO;OAAK;MAChC,YAAY,EAAO;MACnB,WAAU;gBAEV,kBAAC,GAAD;OAAS,MAAK;OAAK,WAAU;OAAY,CAAA;MAC9B,EARP,UAQO,GACX,IACF,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;OAAK;MACnC,SAAS;OAAE,SAAS;OAAG,OAAO;OAAG;MACjC,MAAM;OAAE,SAAS;OAAG,OAAO;OAAK;MAChC,YAAY,EAAQ;MACpB,WAAU;gBAEV,kBAAC,GAAD;OAAM,MAAM;OAAY,MAAK;OAAK,WAAW,EAAO;OAAa,CAAA;MACtD,EARN,EAQM,GACX;KACY,CAAA,EAGlB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG,KACC,kBAAC,KAAD;OAAG,WAAU;iBACV;OACC,CAAA;MAEL,KACC,kBAAC,KAAD;OACE,WAAW,EACT,oCACA,KAAS,SACV;iBAEA;OACC,CAAA;OAIJ,KAAU,MACV,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,KACC,kBAAC,UAAD;QACE,MAAK;QACL,SAAS,EAAO;QAChB,WAAU;kBAET,EAAO;QACD,CAAA,EAEV,KACC,kBAAC,UAAD;QACE,MAAK;QACL,SAAS,EAAO;QAChB,WAAU;kBAET,EAAO;QACD,CAAA,CAEP;;MAEJ;OACF;;GAGL,KAAgB,MAAS,aACxB,kBAAC,GAAD;IAAoB;IAAgB;IAAc;IAAU,CAAA;GAEnD;;;AAQjB,IAAM,IAAmB,IAAI,IAAI;CAC/B;CAAO;CAAQ;CAAO;CAAO;CAAQ;CAAO;CAAO;CAAO;CAC3D,CAAC;AAEF,SAAS,EAAY,GAA2B;AAC9C,KAAI,EAAK,WAAY,QAAO;CAC5B,IAAM,IAAM,EAAK,KAAK,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa,IAAI;AACzD,QAAO,EAAiB,IAAI,EAAI;;AAGlC,SAAS,EACP,GACgC;AAChC,SAAQ,GAAR;EACE,KAAK,WACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAS,EAAiB,GAAsC;AAC9D,SAAQ,EAAK,QAAb;EACE,KAAK,UACH,QAAO;EACT,KAAK,YACH,QAAO,EAAK,YAAY;EAC1B,KAAK,aACH;EACF,KAAK,WACH,QAAO;EACT,KAAK,QACH,QAAO,EAAK,YAAY;;;AAI9B,SAAS,EAAe,GAAuB;AAM7C,QALI,CAAC,KAAS,IAAQ,KAAK,CAAC,OAAO,SAAS,EAAM,GAAS,QACvD,IAAQ,OAAa,GAAG,EAAM,MAC9B,IAAQ,OAAO,OAAa,IAAI,IAAQ,MAAM,QAAQ,EAAE,CAAC,OACzD,IAAQ,OAAO,OAAO,OACjB,IAAI,KAAS,OAAO,OAAO,QAAQ,EAAE,CAAC,OACxC,IAAI,KAAS,OAAO,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAGtD,SAAS,EAAc,EACrB,SACA,YACA,eAKC;CACD,IAAM,IAAa,EAAK,WAAW,cAAc,EAAK,WAAW,SAC3D,IACJ,EAAK,WAAW,eAAe,EAAK,WAAW;AAEjD,QACE,kBAAC,EAAO,KAAR;EACE,QAAA;EACA,WAAU;EACV,SAAS;EACT,SAAS;GAAE,SAAS;GAAG,GAAG;GAAG;EAC7B,MAAM;GAAE,SAAS;GAAG,GAAG;GAAK,QAAQ;GAAG;EACvC,YAAY,EAAQ;YANtB;GASE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAiB,MAAK;eACnB,EAAK,WAAW,aACf,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;OAAK;MACnC,SAAS;OAAE,SAAS;OAAG,OAAO;OAAG;MACjC,MAAM;OAAE,SAAS;OAAG,OAAO;OAAK;MAChC,YAAY,EAAQ;gBAEpB,kBAAC,GAAD;OAAM,MAAM;OAAW,MAAK;OAAK,WAAU;OAAoB,CAAA;MACpD,EAPP,WAOO,GACX,EAAK,WAAW,UAClB,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;OAAK;MACnC,SAAS;OAAE,SAAS;OAAG,OAAO;OAAG;MACjC,MAAM;OAAE,SAAS;OAAG,OAAO;OAAK;MAChC,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAM,MAAM;OAAiB,MAAK;OAAK,WAAU;OAAkB,CAAA;MACxD,EAPP,QAOO,GACX,EAAK,WAAW,eAClB,kBAAC,EAAO,KAAR;MAEE,SAAS,EAAE,SAAS,GAAG;MACvB,SAAS,EAAE,SAAS,GAAG;MACvB,MAAM,EAAE,SAAS,GAAG;MACpB,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAS,MAAK;OAAK,WAAU;OAAgB,CAAA;MAClC,EAPP,aAOO,GACX,EAAY,EAAK,GACnB,kBAAC,EAAO,KAAR;MAEE,SAAS,EAAE,SAAS,GAAG;MACvB,SAAS,EAAE,SAAS,GAAG;MACvB,MAAM,EAAE,SAAS,GAAG;MACpB,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAM,MAAM;OAAW,MAAK;OAAK,WAAU;OAA0B,CAAA;MAC1D,EAPP,QAOO,GAEb,kBAAC,EAAO,KAAR;MAEE,SAAS,EAAE,SAAS,GAAG;MACvB,SAAS,EAAE,SAAS,GAAG;MACvB,MAAM,EAAE,SAAS,GAAG;MACpB,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAM,MAAM;OAAU,MAAK;OAAK,WAAU;OAA0B,CAAA;MACzD,EAPP,OAOO;KAEC,CAAA;IACd,CAAA;GAGN,kBAAC,QAAD;IAAM,WAAU;cACb,EAAK;IACD,CAAA;GAGN,IACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,MAAK;KACL,OAAO,EAAiB,EAAK,OAAO;KACpC,OAAO,EAAiB,EAAK;KAC7B,WAAU;KACV,CAAA,EACD,EAAK,aAAa,KAAA,KACjB,kBAAC,QAAD;KAAM,WAAU;eAAhB,CACG,EAAK,UAAS,IACV;OAEL;QACJ,EAAK,WAAW,aAClB,kBAAC,QAAD;IAAM,WAAU;cAA6B;IAAW,CAAA,GACtD,EAAK,WAAW,UAClB,kBAAC,QAAD;IAAM,WAAU;cACb,EAAK,SAAS;IACV,CAAA,GAEP,kBAAC,QAAD;IAAM,WAAU;cACb,EAAe,EAAK,KAAK;IACrB,CAAA;GAIR,EAAK,WAAW,WAAW,KAC1B,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAQ,EAAK,GAAG;IAC/B,WAAU;IACV,cAAY,SAAS,EAAK;IAC1B,OAAM;cAEN,kBAAC,GAAD,EAAa,WAAU,eAAgB,CAAA;IAChC,CAAA;GAEV,CAAC,KAAc,KACd,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,EAAK,GAAG;IAChC,WAAU;IACV,cAAY,UAAU,EAAK;IAC3B,OAAM;cAEN,kBAAC,GAAD,EAAO,WAAU,eAAgB,CAAA;IAC1B,CAAA;GAEA;;;AAIjB,SAAS,EAAmB,EAC1B,UACA,YACA,aACA,kBACA,gBAAa,MAQZ;CACD,IAAM,CAAC,GAAS,KAAc,EAAM,SAAS,GAAM,EAC7C,CAAC,GAAS,KAAc,EAAM,SAAS,GAAM,EAC7C,IAAS,KAAW,GACpB,IAAgB,EAAM,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC,QAC7D,IAAa,EAAM,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,QACvD,IAAc,EAAM,OACvB,MAAM,EAAE,WAAW,cAAc,EAAE,WAAW,QAChD,EAGK,IAAe,EAAM,OAAO,EAAsB,EAClD,IAAe,EAAM,OAAO,EAAE;AAEpC,GAAM,gBAAgB;AACpB,MAAI,KAAiB,QAAQ,CAAC,EAAa;AAC3C,MAAI,GAAQ;GACV,IAAM,IAAU,KAAK,KAAK,GAAG,EAAa;AAC1C,KAAa,UAAU,KAAK,IAAI,GAAG,EAAa,UAAU,EAAQ;AAClE;;AAEF,IAAa,UAAU,KAAK,KAAK;EACjC,IAAM,IAAQ,iBAAiB;AAC7B,KAAY,QAAQ,EAAc;KACjC,EAAa,QAAQ;AACxB,eAAa,aAAa,EAAM;IAC/B;EAAC;EAAe;EAAa;EAAO,CAAC;CAExC,IAAM,IAAc,IAChB,IAAa,IACX,eACA,iBACF,eAEE,IAA0B,IAC5B,IAAa,IACX,UACA,YACF,WAEE,IAAe,KAAe,IAAa;AACjD,QACE,kBAAC,EAAO,KAAR;EACE,QAAA;EACA,MAAM,IAAe,UAAU;EAC/B,aAAW,IAAe,cAAc;EACxC,cAAW;EACX,WAAW,EACT,oGAEA,KAAgB,aACjB;EACD,oBAAoB,EAAW,GAAK;EACpC,oBAAoB,EAAW,GAAM;EACrC,sBAAsB,EAAW,GAAK;EACtC,qBAAqB,EAAW,GAAM;EACtC,YAAY,EAAQ;YAdtB;GAiBG,KACC,kBAAC,OAAD,EAAK,WAAW,EAAG,qCAAqC,EAAY,EAAI,CAAA;GAI1E,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAiB,MAAK;iBACnB,IACC,IAAa,IACX,kBAAC,EAAO,KAAR;QAEE,SAAS;SAAE,SAAS;SAAG,OAAO;SAAK;QACnC,SAAS;SAAE,SAAS;SAAG,OAAO;SAAG;QACjC,MAAM;SAAE,SAAS;SAAG,OAAO;SAAK;QAChC,YAAY,EAAQ;kBAEpB,kBAAC,GAAD;SAAM,MAAM;SAAiB,MAAK;SAAK,WAAU;SAA2B,CAAA;QACjE,EAPP,aAOO,GAEb,kBAAC,EAAO,KAAR;QAEE,SAAS;SAAE,SAAS;SAAG,OAAO;SAAK;QACnC,SAAS;SAAE,SAAS;SAAG,OAAO;SAAG;QACjC,MAAM;SAAE,SAAS;SAAG,OAAO;SAAK;QAChC,YAAY,EAAQ;kBAEpB,kBAAC,GAAD;SAAM,MAAM;SAAW,MAAK;SAAK,WAAU;SAA6B,CAAA;QAC7D,EAPP,eAOO,GAGf,kBAAC,EAAO,KAAR;QAEE,SAAS,EAAE,SAAS,GAAG;QACvB,SAAS,EAAE,SAAS,GAAG;QACvB,MAAM,EAAE,SAAS,GAAG;QACpB,YAAY,EAAO;kBAEnB,kBAAC,GAAD;SAAM,MAAM;SAAY,MAAK;SAAK,WAAU;SAAmC,CAAA;QACpE,EAPP,cAOO;OAEC,CAAA,EAClB,kBAAC,KAAD;OAAG,WAAU;iBACV,IACG,IAAa,IACX,GAAG,EAAc,MAAM,EAAM,OAAO,aACpC,GAAG,EAAM,OAAO,OAAO,EAAM,SAAS,IAAI,MAAM,GAAG,aACrD,aAAa,EAAM,OAAO,OAAO,EAAM,SAAS,IAAI,MAAM;OAC5D,CAAA,CACA;;KACL,CAAC,KACA,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACG;OAAc;OAAK,EAAM;OAAO;OAChC,IAAa,KAAK,MAAM,EAAW;OAClC;;KAIN,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UACG,EAAM,KAAK,MACV,kBAAC,GAAD;OAEQ;OACG;OACC;OACV,EAJK,EAAK,GAIV,CACF,EACc,CAAA;MACd,CAAA;KAGN,kBAAC,OAAD;MAAK,WAAU;MAAU,aAAU;gBAAnC;OACG;OAAc;OAAK,EAAM;OAAO;OAChC,IAAa,KAAK,KAAK,EAAW;OAC/B;;KACF;;GAGL,KACC,kBAAC,GAAD;IACE,UAAU;IACV,MAAM;IACN,QAAQ;IACR,CAAA;GAEO;;;AAQjB,SAAS,EACP,GACA,GACe;AACf,QAAO;EACL,IAAI,GAAS;EACb,UAAU,GAAS,YAAY,KAAY;EAC3C,UAAU;EACV,YAAY,EAAE,OAAO,UAAU;EAChC;;AAGH,SAAS,EACP,GACA,GACA,GACA;AACA,IAAsB;CACtB,IAAM,IAAW,GAAS,YAAY;AACtC,QAAO,EAAY,aAEf,kBAAC,GAAD;EACQ;EACN,OAAO;EACP,aAAa,GAAS;EACtB,QAAQ,GAAS;EACjB,QAAQ,GAAS;EACP;EACV,YAAY,GAAS;EACrB,CAAA,EAEJ,EAAoB,GAAS,EAAS,CACvC;;AAgBH,SAAS,EAAM,GAAmC,GAAwB;AACxE,QAAO,EAAiB,WAAW,GAAS,EAAQ;;AAGtD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS,EAAQ,EAGtD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS,EAAQ,EAGtD,EAAM,SACJ,GACA,MAEO,EAAiB,SAAS,GAAS,EAAQ,EAGpD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS,EAAQ,EAGtD,EAAM,QACJ,GACA,MAEO,EAAiB,QAAQ,GAAS,EAAQ,EAGnD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS;CAC1C,GAAG;CACH,UAAU,GAAS,YAAY;CAChC,CAAC,EAGJ,EAAM,WACJ,GACA,MAQG;CACH,IAAM,IAAK,EAAY,aAEnB,kBAAC,GAAD;EAAc,MAAK;EAAU,OAAO,EAAQ;EAAS,cAAc;EAAS,CAAA,EAE9E;EAAE,UAAU;EAAU,UAAU;EAAM,YAAY,EAAE,OAAO,UAAU;EAAE,CACxE,EAEK,KAAe,GAAiB,MAA6B;AAIjE,IAAY,aAER,kBAAC,GAAD;GACQ;GACN,OAAO;GACP,UAAU;GACV,eAAe;GACf,CAAA,EAEJ;GAAE;GAAI,UAAU;GAAU,UAAU;GAAM,YAAY,EAAE,OAAO,UAAU;GAAE,CAC5E;;AAmBH,QAhBA,EACG,MAAM,MAAS;AAKd,IAAY,WAHV,OAAO,EAAQ,WAAY,aACvB,EAAQ,QAAQ,EAAK,GACrB,EAAQ,QACiB;GAC/B,CACD,OAAO,MAAU;AAKhB,IAAY,SAHV,OAAO,EAAQ,SAAU,aACrB,EAAQ,MAAM,EAAM,GACpB,EAAQ,MACe;GAC7B,EAEG;GAGT,EAAM,QAAQ,GAAmC,MAA8B;CAC7E,IAAM,IAAW,EAAQ,YAAY;AACrC,QAAO,EAAY,aAEf,kBAAC,GAAD;EACE,MAAK;EACL,OAAO;EACP,aAAa,EAAQ;EACrB,QAAQ;GAAE,OAAO;GAAQ,SAAS,EAAQ;GAAQ;EACxC;EACV,CAAA,EAEJ;EAAE;EAAU,UAAU;EAAM,YAAY,EAAE,OAAO,UAAU;EAAE,CAC9D;GAGH,EAAM,UAAU,MAAgC;CAE9C,IAAM,IAAU,EAAQ,MAAM,OAAO,KAAK,KAAK,CAAC;AAoBhD,QAlBA,EAAY,aAER,kBAAC,GAAD;EACE,OAAO,EAAQ;EACf,SAAS,EAAQ;EACjB,UAAU,EAAQ;EAClB,eAAe;EACf,YAAY,EAAQ;EACpB,CAAA,EAEJ;EACE,IAAI;EACJ,UAAU;EACV,UAAU;EACV,YAAY,EAAE,OAAO,UAAU;EAChC,CACF,EAEM;GAGT,EAAM,UACJ,GACA,MAEO,EAAY,OAAO,GAAQ;CAChC,GAAG;CACH,UAAU;CACV,YAAY;EAAE,OAAO;EAAU,GAAI,GAAS;EAAuC;CACpF,CAAC,EAGJ,EAAM,WAAW,MAAyB;AACxC,CAAI,MAAO,KAAA,IAGT,EAAY,SAAS,GAFrB,EAAY,QAAQ,EAAG"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { I as e, L as t } from "../_chunks/primitives.js";
2
+ import { F as e, I as t } from "../_chunks/primitives.js";
3
3
  import { cn as n } from "./lib/utils.js";
4
4
  import { toggleVariants as r } from "./toggle.js";
5
5
  import * as i from "react";
package/dist/ui/toggle.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { R as e } from "../_chunks/primitives.js";
2
+ import { L as e } from "../_chunks/primitives.js";
3
3
  import { motionProps as t, springs as n } from "./lib/motion.js";
4
4
  import { t as r } from "../_chunks/vendor-utils.js";
5
5
  import { cn as i } from "./lib/utils.js";
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/ui/tooltip.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,gBAAgB,MAAM,2BAA2B,CAAA;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAS/F,CAAA;AAmBD,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CA2BnF,CAAA;AAGD,QAAA,MAAM,cAAc,gHAA2B,CAAA;AAW/C,QAAA,MAAM,cAAc,gKAoClB,CAAA;AAGF,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAA;AAEjG,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAC,cAAc,EAAE,CAAA"}
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/ui/tooltip.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,gBAAgB,MAAM,2BAA2B,CAAA;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAS/F,CAAA;AAmBD,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAiBnF,CAAA;AAGD,QAAA,MAAM,cAAc,gHAA2B,CAAA;AAW/C,QAAA,MAAM,cAAc,gKAoClB,CAAA;AAGF,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAA;AAEjG,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAC,cAAc,EAAE,CAAA"}
@@ -1,62 +1,65 @@
1
1
  "use client";
2
- import { F as e, M as t, N as n, P as r, j as i } from "../_chunks/primitives.js";
2
+ import { A as e, M as t, N as n, P as r, j as i } from "../_chunks/primitives.js";
3
3
  import { springs as a, tweens as o } from "./lib/motion.js";
4
4
  import { cn as s } from "./lib/utils.js";
5
- import * as c from "react";
6
- import { Fragment as l, jsx as u } from "react/jsx-runtime";
7
- import { AnimatePresence as d, motion as f } from "framer-motion";
5
+ import { t as c } from "../_chunks/use-controllable-open.js";
6
+ import * as l from "react";
7
+ import { Fragment as u, jsx as d } from "react/jsx-runtime";
8
+ import { AnimatePresence as f, motion as p } from "framer-motion";
8
9
  //#region src/ui/tooltip.tsx
9
- var p = c.createContext(!1), m = ({ children: e, ...t }) => /* @__PURE__ */ u(p.Provider, {
10
+ var m = l.createContext(!1), h = ({ children: e, ...n }) => /* @__PURE__ */ d(m.Provider, {
10
11
  value: !0,
11
- children: /* @__PURE__ */ u(n, {
12
- ...t,
12
+ children: /* @__PURE__ */ d(t, {
13
+ ...n,
13
14
  children: e
14
15
  })
15
16
  });
16
- function h({ children: e }) {
17
- return c.useContext(p) ? /* @__PURE__ */ u(l, { children: e }) : /* @__PURE__ */ u(p.Provider, {
17
+ function g({ children: e }) {
18
+ return l.useContext(m) ? /* @__PURE__ */ d(u, { children: e }) : /* @__PURE__ */ d(m.Provider, {
18
19
  value: !0,
19
- children: /* @__PURE__ */ u(n, {
20
+ children: /* @__PURE__ */ d(t, {
20
21
  delayDuration: 300,
21
22
  children: e
22
23
  })
23
24
  });
24
25
  }
25
- var g = c.createContext({ open: !1 }), _ = ({ open: e, defaultOpen: t, onOpenChange: n, ...i }) => {
26
- let [a, o] = c.useState(t ?? !1), s = e !== void 0, l = s ? e : a, d = c.useCallback((e) => {
27
- s || o(e), n?.(e);
28
- }, [s, n]), f = c.useMemo(() => ({ open: l }), [l]);
29
- return /* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g.Provider, {
30
- value: f,
31
- children: /* @__PURE__ */ u(r, {
32
- open: l,
33
- onOpenChange: d,
26
+ var _ = l.createContext({ open: !1 }), v = ({ open: e, defaultOpen: t, onOpenChange: r, ...i }) => {
27
+ let { open: a, setOpen: o } = c({
28
+ open: e,
29
+ defaultOpen: t,
30
+ onOpenChange: r
31
+ }), s = l.useMemo(() => ({ open: a }), [a]);
32
+ return /* @__PURE__ */ d(g, { children: /* @__PURE__ */ d(_.Provider, {
33
+ value: s,
34
+ children: /* @__PURE__ */ d(n, {
35
+ open: a,
36
+ onOpenChange: o,
34
37
  ...i
35
38
  })
36
39
  }) });
37
40
  };
38
- _.displayName = "Tooltip";
39
- var v = e, y = {
41
+ v.displayName = "Tooltip";
42
+ var y = r, b = {
40
43
  top: { y: 4 },
41
44
  bottom: { y: -4 },
42
45
  left: { x: 4 },
43
46
  right: { x: -4 }
44
- }, b = c.forwardRef(({ className: e, sideOffset: n = 4, side: r = "top", children: l, ...p }, m) => {
45
- let { open: h } = c.useContext(g), _ = y[r] ?? {};
46
- return /* @__PURE__ */ u(d, { children: h && /* @__PURE__ */ u(t, {
47
+ }, x = l.forwardRef(({ className: t, sideOffset: n = 4, side: r = "top", children: c, ...u }, m) => {
48
+ let { open: h } = l.useContext(_), g = b[r] ?? {};
49
+ return /* @__PURE__ */ d(f, { children: h && /* @__PURE__ */ d(i, {
47
50
  forceMount: !0,
48
- children: /* @__PURE__ */ u(i, {
51
+ children: /* @__PURE__ */ d(e, {
49
52
  ref: m,
50
53
  forceMount: !0,
51
54
  sideOffset: n,
52
55
  side: r,
53
- ...p,
56
+ ...u,
54
57
  asChild: !0,
55
- children: /* @__PURE__ */ u(f.div, {
58
+ children: /* @__PURE__ */ d(p.div, {
56
59
  initial: {
57
60
  opacity: 0,
58
61
  scale: .95,
59
- ..._
62
+ ...g
60
63
  },
61
64
  animate: {
62
65
  opacity: 1,
@@ -67,18 +70,18 @@ var v = e, y = {
67
70
  exit: {
68
71
  opacity: 0,
69
72
  scale: .95,
70
- ..._
73
+ ...g
71
74
  },
72
75
  transition: {
73
76
  ...a.snappy,
74
77
  opacity: o.fade
75
78
  },
76
- className: s("z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-ds-sm text-surface-inverted-fg shadow-floating", e),
77
- children: l
79
+ className: s("z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-ds-sm text-surface-inverted-fg shadow-floating", t),
80
+ children: c
78
81
  })
79
82
  })
80
83
  }) });
81
84
  });
82
- b.displayName = i.displayName;
85
+ x.displayName = e.displayName;
83
86
  //#endregion
84
- export { _ as Tooltip, b as TooltipContent, m as TooltipProvider, v as TooltipTrigger };
87
+ export { v as Tooltip, x as TooltipContent, h as TooltipProvider, y as TooltipTrigger };