@devalok/shilp-sutra 0.57.0 → 0.60.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 (288) hide show
  1. package/MIGRATION.md +163 -0
  2. package/dist/_chunks/badge-group.js +75 -188
  3. package/dist/_chunks/badge-group.js.map +1 -1
  4. package/dist/_chunks/chat.js +244 -243
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/image-preview.js +71 -70
  7. package/dist/_chunks/image-preview.js.map +1 -1
  8. package/dist/_chunks/motion-preference.js +15 -0
  9. package/dist/_chunks/motion-preference.js.map +1 -0
  10. package/dist/_chunks/motion-provider.js +1 -1
  11. package/dist/_chunks/motion-provider.js.map +1 -1
  12. package/dist/_chunks/popover.js +50 -49
  13. package/dist/_chunks/popover.js.map +1 -1
  14. package/dist/_chunks/primitives-internal.js +29 -29
  15. package/dist/_chunks/primitives-internal.js.map +1 -1
  16. package/dist/_chunks/shared.js +48 -47
  17. package/dist/_chunks/shared.js.map +1 -1
  18. package/dist/_chunks/success.js +34 -34
  19. package/dist/_chunks/tree-view.js +1 -1
  20. package/dist/_chunks/tree-view.js.map +1 -1
  21. package/dist/ai/block-renderer.js +8 -8
  22. package/dist/ai/command-bar.js +65 -65
  23. package/dist/ai/command-bar.js.map +1 -1
  24. package/dist/ai/conversation.js +35 -35
  25. package/dist/ai/conversation.js.map +1 -1
  26. package/dist/ai/index.js +4 -4
  27. package/dist/composed/activity-feed.d.ts.map +1 -1
  28. package/dist/composed/activity-feed.js +108 -107
  29. package/dist/composed/activity-feed.js.map +1 -1
  30. package/dist/composed/avatar-group.js +3 -3
  31. package/dist/composed/avatar-group.js.map +1 -1
  32. package/dist/composed/bulk-action-bar.d.ts +9 -35
  33. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  34. package/dist/composed/bulk-action-bar.js +2 -139
  35. package/dist/composed/command-palette.js +137 -137
  36. package/dist/composed/command-palette.js.map +1 -1
  37. package/dist/composed/content-card.js +1 -1
  38. package/dist/composed/content-card.js.map +1 -1
  39. package/dist/composed/date-picker/index.js +5 -5
  40. package/dist/composed/date-picker/index.js.map +1 -1
  41. package/dist/composed/empty-state.js +4 -4
  42. package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
  43. package/dist/composed/file-preview/shared.d.ts.map +1 -1
  44. package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
  45. package/dist/composed/file-preview.js +151 -150
  46. package/dist/composed/file-preview.js.map +1 -1
  47. package/dist/composed/filter-bar.d.ts.map +1 -1
  48. package/dist/composed/filter-bar.js +53 -52
  49. package/dist/composed/filter-bar.js.map +1 -1
  50. package/dist/composed/form-section.d.ts.map +1 -1
  51. package/dist/composed/form-section.js +38 -37
  52. package/dist/composed/form-section.js.map +1 -1
  53. package/dist/composed/index.js +6 -5
  54. package/dist/composed/master-detail.d.ts.map +1 -1
  55. package/dist/composed/master-detail.js +1 -1
  56. package/dist/composed/master-detail.js.map +1 -1
  57. package/dist/composed/multi-select-popover.d.ts.map +1 -1
  58. package/dist/composed/multi-select-popover.js +109 -108
  59. package/dist/composed/multi-select-popover.js.map +1 -1
  60. package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
  61. package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
  62. package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
  63. package/dist/composed/rich-chat-input.d.ts.map +1 -1
  64. package/dist/composed/rich-chat-input.js +467 -466
  65. package/dist/composed/rich-chat-input.js.map +1 -1
  66. package/dist/composed/rich-text-editor.js +3 -3
  67. package/dist/composed/rich-text-editor.js.map +1 -1
  68. package/dist/composed/schedule-view.js +2 -2
  69. package/dist/composed/schedule-view.js.map +1 -1
  70. package/dist/composed/status-badge.d.ts.map +1 -1
  71. package/dist/composed/status-badge.js +29 -28
  72. package/dist/composed/status-badge.js.map +1 -1
  73. package/dist/motion/index.d.ts +1 -0
  74. package/dist/motion/index.d.ts.map +1 -1
  75. package/dist/motion/index.js +2 -15
  76. package/dist/motion/motion-preference.d.ts +36 -0
  77. package/dist/motion/motion-preference.d.ts.map +1 -0
  78. package/dist/motion/motion-provider.d.ts +2 -1
  79. package/dist/motion/motion-provider.d.ts.map +1 -1
  80. package/dist/motion/primitives-index.js +103 -102
  81. package/dist/motion/primitives-index.js.map +1 -1
  82. package/dist/motion/primitives.d.ts.map +1 -1
  83. package/dist/shell/bottom-navbar.js +19 -19
  84. package/dist/shell/bottom-navbar.js.map +1 -1
  85. package/dist/shell/index.d.ts +1 -1
  86. package/dist/shell/index.d.ts.map +1 -1
  87. package/dist/shell/notification-center.d.ts +17 -0
  88. package/dist/shell/notification-center.d.ts.map +1 -1
  89. package/dist/shell/notification-center.js +109 -104
  90. package/dist/shell/notification-center.js.map +1 -1
  91. package/dist/shell/notification-preferences.js +1 -1
  92. package/dist/shell/notification-preferences.js.map +1 -1
  93. package/dist/shell/top-bar.js +1 -1
  94. package/dist/shell/top-bar.js.map +1 -1
  95. package/dist/tokens/index.css +1 -0
  96. package/dist/tokens/palettes.css +292 -0
  97. package/dist/tokens/semantic.css +157 -11
  98. package/dist/tokens/shilp-sutra.css +1 -0
  99. package/dist/tokens/utilities.css +10 -7
  100. package/dist/ui/accordion.d.ts.map +1 -1
  101. package/dist/ui/accordion.js +27 -26
  102. package/dist/ui/accordion.js.map +1 -1
  103. package/dist/ui/alert-dialog.d.ts.map +1 -1
  104. package/dist/ui/alert-dialog.js +60 -59
  105. package/dist/ui/alert-dialog.js.map +1 -1
  106. package/dist/ui/alert.d.ts.map +1 -1
  107. package/dist/ui/alert.js +55 -113
  108. package/dist/ui/alert.js.map +1 -1
  109. package/dist/ui/autocomplete.js +80 -80
  110. package/dist/ui/autocomplete.js.map +1 -1
  111. package/dist/ui/avatar.d.ts.map +1 -1
  112. package/dist/ui/avatar.js +71 -70
  113. package/dist/ui/avatar.js.map +1 -1
  114. package/dist/ui/badge-indicator.d.ts +4 -8
  115. package/dist/ui/badge-indicator.d.ts.map +1 -1
  116. package/dist/ui/badge-indicator.js +3 -8
  117. package/dist/ui/badge-indicator.js.map +1 -1
  118. package/dist/ui/badge.d.ts +8 -1
  119. package/dist/ui/badge.d.ts.map +1 -1
  120. package/dist/ui/banner.d.ts.map +1 -1
  121. package/dist/ui/banner.js +42 -40
  122. package/dist/ui/banner.js.map +1 -1
  123. package/dist/ui/bulk-action-bar.d.ts +59 -0
  124. package/dist/ui/bulk-action-bar.d.ts.map +1 -0
  125. package/dist/ui/bulk-action-bar.js +145 -0
  126. package/dist/ui/bulk-action-bar.js.map +1 -0
  127. package/dist/ui/button-group.d.ts.map +1 -1
  128. package/dist/ui/button-group.js +3 -23
  129. package/dist/ui/button-group.js.map +1 -1
  130. package/dist/ui/button.d.ts +10 -1
  131. package/dist/ui/button.d.ts.map +1 -1
  132. package/dist/ui/button.js +79 -212
  133. package/dist/ui/button.js.map +1 -1
  134. package/dist/ui/card.d.ts.map +1 -1
  135. package/dist/ui/card.js +75 -72
  136. package/dist/ui/card.js.map +1 -1
  137. package/dist/ui/charts/radar-chart.d.ts.map +1 -1
  138. package/dist/ui/charts/radar-chart.js +1 -1
  139. package/dist/ui/charts/radar-chart.js.map +1 -1
  140. package/dist/ui/chat/message-list.d.ts.map +1 -1
  141. package/dist/ui/chat/message.d.ts.map +1 -1
  142. package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
  143. package/dist/ui/checkbox.d.ts.map +1 -1
  144. package/dist/ui/checkbox.js +1 -1
  145. package/dist/ui/checkbox.js.map +1 -1
  146. package/dist/ui/code.js +1 -1
  147. package/dist/ui/code.js.map +1 -1
  148. package/dist/ui/color-input.d.ts.map +1 -1
  149. package/dist/ui/color-input.js +151 -150
  150. package/dist/ui/color-input.js.map +1 -1
  151. package/dist/ui/combobox.d.ts +14 -0
  152. package/dist/ui/combobox.d.ts.map +1 -1
  153. package/dist/ui/combobox.js +162 -158
  154. package/dist/ui/combobox.js.map +1 -1
  155. package/dist/ui/context-menu.d.ts.map +1 -1
  156. package/dist/ui/context-menu.js +70 -69
  157. package/dist/ui/context-menu.js.map +1 -1
  158. package/dist/ui/data-table-body.d.ts.map +1 -1
  159. package/dist/ui/data-table-body.js +4 -3
  160. package/dist/ui/data-table-body.js.map +1 -1
  161. package/dist/ui/data-table-bulk-actions.d.ts +26 -1
  162. package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
  163. package/dist/ui/data-table-bulk-actions.js +21 -46
  164. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  165. package/dist/ui/data-table-context.d.ts +36 -2
  166. package/dist/ui/data-table-context.d.ts.map +1 -1
  167. package/dist/ui/data-table-context.js +25 -21
  168. package/dist/ui/data-table-context.js.map +1 -1
  169. package/dist/ui/data-table-header.d.ts.map +1 -1
  170. package/dist/ui/data-table-header.js +42 -40
  171. package/dist/ui/data-table-header.js.map +1 -1
  172. package/dist/ui/data-table-pagination.js +2 -2
  173. package/dist/ui/data-table-pagination.js.map +1 -1
  174. package/dist/ui/dialog.d.ts.map +1 -1
  175. package/dist/ui/dialog.js +61 -60
  176. package/dist/ui/dialog.js.map +1 -1
  177. package/dist/ui/dot.d.ts.map +1 -1
  178. package/dist/ui/dot.js +10 -41
  179. package/dist/ui/dot.js.map +1 -1
  180. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  181. package/dist/ui/dropdown-menu.js +79 -78
  182. package/dist/ui/dropdown-menu.js.map +1 -1
  183. package/dist/ui/file-upload.d.ts.map +1 -1
  184. package/dist/ui/file-upload.js +116 -115
  185. package/dist/ui/file-upload.js.map +1 -1
  186. package/dist/ui/form.d.ts.map +1 -1
  187. package/dist/ui/form.js +27 -26
  188. package/dist/ui/form.js.map +1 -1
  189. package/dist/ui/hover-card.d.ts.map +1 -1
  190. package/dist/ui/hover-card.js +26 -25
  191. package/dist/ui/hover-card.js.map +1 -1
  192. package/dist/ui/icon.js +7 -7
  193. package/dist/ui/index.d.ts +3 -2
  194. package/dist/ui/index.d.ts.map +1 -1
  195. package/dist/ui/index.js +60 -59
  196. package/dist/ui/index.js.map +1 -1
  197. package/dist/ui/input.d.ts.map +1 -1
  198. package/dist/ui/input.js +7 -7
  199. package/dist/ui/input.js.map +1 -1
  200. package/dist/ui/menubar.d.ts.map +1 -1
  201. package/dist/ui/menubar.js +73 -72
  202. package/dist/ui/menubar.js.map +1 -1
  203. package/dist/ui/navigation-menu.d.ts.map +1 -1
  204. package/dist/ui/navigation-menu.js +80 -79
  205. package/dist/ui/navigation-menu.js.map +1 -1
  206. package/dist/ui/popover.d.ts.map +1 -1
  207. package/dist/ui/progress.d.ts.map +1 -1
  208. package/dist/ui/progress.js +72 -68
  209. package/dist/ui/progress.js.map +1 -1
  210. package/dist/ui/radio.d.ts.map +1 -1
  211. package/dist/ui/radio.js +35 -34
  212. package/dist/ui/radio.js.map +1 -1
  213. package/dist/ui/search-input.d.ts.map +1 -1
  214. package/dist/ui/search-input.js +28 -27
  215. package/dist/ui/search-input.js.map +1 -1
  216. package/dist/ui/select.d.ts.map +1 -1
  217. package/dist/ui/select.js +70 -69
  218. package/dist/ui/select.js.map +1 -1
  219. package/dist/ui/sidebar.d.ts.map +1 -1
  220. package/dist/ui/sidebar.js +4 -4
  221. package/dist/ui/sidebar.js.map +1 -1
  222. package/dist/ui/slider.d.ts +63 -9
  223. package/dist/ui/slider.d.ts.map +1 -1
  224. package/dist/ui/slider.js +74 -32
  225. package/dist/ui/slider.js.map +1 -1
  226. package/dist/ui/split-button.d.ts +8 -2
  227. package/dist/ui/split-button.d.ts.map +1 -1
  228. package/dist/ui/split-button.js +49 -95
  229. package/dist/ui/split-button.js.map +1 -1
  230. package/dist/ui/stat-card.d.ts.map +1 -1
  231. package/dist/ui/stat-card.js +89 -88
  232. package/dist/ui/stat-card.js.map +1 -1
  233. package/dist/ui/stat-flash.js +16 -16
  234. package/dist/ui/stepper.d.ts.map +1 -1
  235. package/dist/ui/stepper.js +63 -62
  236. package/dist/ui/stepper.js.map +1 -1
  237. package/dist/ui/switch.d.ts.map +1 -1
  238. package/dist/ui/switch.js +2 -2
  239. package/dist/ui/switch.js.map +1 -1
  240. package/dist/ui/table.d.ts.map +1 -1
  241. package/dist/ui/table.js +3 -3
  242. package/dist/ui/table.js.map +1 -1
  243. package/dist/ui/tabs.d.ts.map +1 -1
  244. package/dist/ui/tabs.js +67 -66
  245. package/dist/ui/tabs.js.map +1 -1
  246. package/dist/ui/textarea.d.ts.map +1 -1
  247. package/dist/ui/textarea.js +7 -7
  248. package/dist/ui/textarea.js.map +1 -1
  249. package/dist/ui/toast.d.ts.map +1 -1
  250. package/dist/ui/toast.js +196 -195
  251. package/dist/ui/toast.js.map +1 -1
  252. package/dist/ui/toggle.d.ts.map +1 -1
  253. package/dist/ui/toggle.js +24 -22
  254. package/dist/ui/toggle.js.map +1 -1
  255. package/dist/ui/tooltip.d.ts.map +1 -1
  256. package/dist/ui/tooltip.js +37 -36
  257. package/dist/ui/tooltip.js.map +1 -1
  258. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  259. package/docs/components/composed/bulk-action-bar.md +14 -7
  260. package/docs/components/ui/bulk-action-bar.md +72 -0
  261. package/docs/recipes/customize-brand.md +58 -0
  262. package/docs/recipes/install-astro.md +1 -1
  263. package/docs/recipes/install-next-app-router.md +1 -1
  264. package/docs/recipes/install-next-pages.md +22 -1
  265. package/docs/recipes/install-remix.md +1 -1
  266. package/docs/recipes/install-tanstack-start.md +1 -1
  267. package/docs/recipes/install-vite.md +2 -1
  268. package/docs/recipes/server-components.md +7 -4
  269. package/docs/recipes/troubleshoot.md +1 -0
  270. package/llms.txt +2 -2
  271. package/make-kit/foundations/color.md +3 -1
  272. package/mcp-manifest.json +184 -151
  273. package/package.json +8 -2
  274. package/skill/SKILL.md +1 -1
  275. package/skill/references/components.md +2 -2
  276. package/skill/references/customize-brand.md +58 -0
  277. package/skill/references/server-components.md +7 -4
  278. package/skill/references/setup-astro.md +1 -1
  279. package/skill/references/setup-next-app-router.md +1 -1
  280. package/skill/references/setup-next-pages.md +22 -1
  281. package/skill/references/setup-remix.md +1 -1
  282. package/skill/references/setup-tanstack-start.md +1 -1
  283. package/skill/references/setup-vite.md +2 -1
  284. package/skill/references/troubleshoot.md +1 -0
  285. package/dist/composed/bulk-action-bar.js.map +0 -1
  286. package/dist/motion/check-motion-provider.d.ts +0 -2
  287. package/dist/motion/check-motion-provider.d.ts.map +0 -1
  288. package/dist/motion/index.js.map +0 -1
@@ -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-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-body-md font-semibold text-surface-fg\">\n {title}\n </p>\n )}\n {description && (\n <p\n className={cn(\n 'text-body-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-body-sm font-medium text-accent-11 underline-offset-2 hover:underline hover:bg-surface-panel-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-body-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-body-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-caption tabular-nums text-surface-fg-muted\">\n {file.progress}%\n </span>\n )}\n </div>\n ) : file.status === 'complete' ? (\n <span className=\"text-body-xs text-success-11\">Done</span>\n ) : file.status === 'error' ? (\n <span className=\"max-w-[60px] truncate text-body-xs text-error-11\">\n {file.error || 'Failed'}\n </span>\n ) : (\n <span className=\"text-caption 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-body-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-caption 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;CACjB;CACA,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;CACjB;CACA,OAAO;EACL,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;CACjB;CACA,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;CACjB;CACA,MAAM;EACJ,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;CACjB;CACA,SAAS;EACP,aAAa;EACb,WAAW;EACX,MAAM;EACN,eAAe;CACjB;AACF;AAMA,SAAS,EAAS,EAChB,aACA,SACA,aAKC;CACD,IAAM,IAAS,EAAkB;CACjC,OACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GACE,WAAW,EACT,wCACA,EAAO,eACP,+BACF;GACA,OAAO;IACL,mBAAmB,GAAG,EAAS;IAC/B,oBAAoB,IAAS,WAAW;GAC1C;EACD,CAAA;CACE,CAAA;AAET;AAMA,SAAS,EAAa,EACpB,SACA,UACA,gBACA,WACA,WACA,cAAW,GACX,kBAAe,IACf,gBAAa,IACb,oBAaC;CACD,IAAM,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,IAAS,KAAW,GACpB,IAAS,EAAkB,IAC3B,IAAa,EAAO,MAGpB,IAAe,EAAM,OAAO,CAAQ,GACpC,IAAe,EAAM,OAAO,CAAC;CAEnC,EAAM,gBAAgB;EACpB,IAAI,KAAiB,QAAQ,MAAa,UAAU;EACpD,IAAI,GAAQ;GAEV,IAAM,IAAU,KAAK,IAAI,IAAI,EAAa;GAC1C,EAAa,UAAU,KAAK,IAAI,GAAG,EAAa,UAAU,CAAO;GACjE;EACF;EAEA,EAAa,UAAU,KAAK,IAAI;EAChC,IAAM,IAAQ,iBAAiB;GAC7B,EAAY,QAAQ,CAAa;EACnC,GAAG,EAAa,OAAO;EACvB,aAAa,aAAa,CAAK;CACjC,GAAG;EAAC;EAAe;EAAU;CAAM,CAAC;CAIpC,IAAM,IAAW,MAAS;CAC1B,OACE,kBAAC,EAAO,KAAR;EACE,QAAO;EACP,MAAM,IAAW,UAAU;EAC3B,aAAW,IAAW,cAAc;EACpC,eAAY;EACZ,WAAW,EACT,oGAEA,MAAS,WAAW,YACtB;EACA,oBAAoB,EAAW,EAAI;EACnC,oBAAoB,EAAW,EAAK;EACpC,sBAAsB,EAAW,EAAI;EACrC,qBAAqB,EAAW,EAAK;EACrC,YAAY,EAAQ;YAdtB;GAiBG,KAAc,EAAO,eACpB,kBAAC,OAAD,EACE,WAAW,EAAG,qCAAqC,EAAO,WAAW,EACtE,CAAA;GAIH,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,GAAD;KAAiB,MAAK;eACnB,MAAS,YACR,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;MAAI;MAClC,SAAS;OAAE,SAAS;OAAG,OAAO;MAAE;MAChC,MAAM;OAAE,SAAS;OAAG,OAAO;MAAI;MAC/B,YAAY,EAAO;MACnB,WAAU;gBAEV,kBAAC,GAAD;OAAS,MAAK;OAAK,WAAU;MAAW,CAAA;KAC9B,GARN,SAQM,IACV,IACF,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;MAAI;MAClC,SAAS;OAAE,SAAS;OAAG,OAAO;MAAE;MAChC,MAAM;OAAE,SAAS;OAAG,OAAO;MAAI;MAC/B,YAAY,EAAQ;MACpB,WAAU;gBAEV,kBAAC,GAAD;OAAM,MAAM;OAAY,MAAK;OAAK,WAAW,EAAO;MAAY,CAAA;KACtD,GARL,CAQK,IACV;IACW,CAAA,GAGjB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG,KACC,kBAAC,KAAD;OAAG,WAAU;iBACV;MACA,CAAA;MAEJ,KACC,kBAAC,KAAD;OACE,WAAW,EACT,sCACA,KAAS,QACX;iBAEC;MACA,CAAA;OAIH,KAAU,MACV,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,KACC,kBAAC,UAAD;QACE,MAAK;QACL,SAAS,EAAO;QAChB,WAAU;kBAET,EAAO;OACF,CAAA,GAET,KACC,kBAAC,UAAD;QACE,MAAK;QACL,SAAS,EAAO;QAChB,WAAU;kBAET,EAAO;OACF,CAAA,CAEP;;KAEJ;MACF;;GAGJ,KAAgB,MAAS,aACxB,kBAAC,GAAD;IAAoB;IAAgB;IAAc;GAAS,CAAA;EAEnD;;AAEhB;AAMA,IAAM,oBAAmB,IAAI,IAAI;CAC/B;CAAO;CAAQ;CAAO;CAAO;CAAQ;CAAO;CAAO;CAAO;AAC5D,CAAC;AAED,SAAS,EAAY,GAA2B;CAC9C,IAAI,EAAK,YAAY,OAAO;CAC5B,IAAM,IAAM,EAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,YAAY,KAAK;CACzD,OAAO,EAAiB,IAAI,CAAG;AACjC;AAEA,SAAS,EACP,GACgC;CAChC,QAAQ,GAAR;EACE,KAAK,YACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,EAAiB,GAAsC;CAC9D,QAAQ,EAAK,QAAb;EACE,KAAK,WACH,OAAO;EACT,KAAK,aACH,OAAO,EAAK,YAAY;EAC1B,KAAK,cACH;EACF,KAAK,YACH,OAAO;EACT,KAAK,SACH,OAAO,EAAK,YAAY;CAC5B;AACF;AAEA,SAAS,EAAe,GAAuB;CAM7C,OALI,CAAC,KAAS,IAAQ,KAAK,CAAC,OAAO,SAAS,CAAK,IAAU,QACvD,IAAQ,OAAa,GAAG,EAAM,MAC9B,IAAQ,OAAO,OAAa,IAAI,IAAQ,KAAA,CAAM,QAAQ,CAAC,EAAE,OACzD,IAAQ,OAAO,OAAO,OACjB,IAAI,KAAS,OAAO,MAAA,CAAO,QAAQ,CAAC,EAAE,OACxC,IAAI,KAAS,OAAO,OAAO,MAAA,CAAO,QAAQ,CAAC,EAAE;AACtD;AAEA,SAAS,EAAc,EACrB,SACA,YACA,eAKC;CACD,IAAM,IAAa,EAAK,WAAW,cAAc,EAAK,WAAW,SAC3D,IACJ,EAAK,WAAW,eAAe,EAAK,WAAW;CAEjD,OACE,kBAAC,EAAO,KAAR;EACE,QAAA;EACA,WAAU;EACV,SAAS;EACT,SAAS;GAAE,SAAS;GAAG,GAAG;EAAE;EAC5B,MAAM;GAAE,SAAS;GAAG,GAAG;GAAK,QAAQ;EAAE;EACtC,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;MAAI;MAClC,SAAS;OAAE,SAAS;OAAG,OAAO;MAAE;MAChC,MAAM;OAAE,SAAS;OAAG,OAAO;MAAI;MAC/B,YAAY,EAAQ;gBAEpB,kBAAC,GAAD;OAAM,MAAM;OAAW,MAAK;OAAK,WAAU;MAAmB,CAAA;KACpD,GAPN,UAOM,IACV,EAAK,WAAW,UAClB,kBAAC,EAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,OAAO;MAAI;MAClC,SAAS;OAAE,SAAS;OAAG,OAAO;MAAE;MAChC,MAAM;OAAE,SAAS;OAAG,OAAO;MAAI;MAC/B,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAM,MAAM;OAAiB,MAAK;OAAK,WAAU;MAAiB,CAAA;KACxD,GAPN,OAOM,IACV,EAAK,WAAW,eAClB,kBAAC,EAAO,KAAR;MAEE,SAAS,EAAE,SAAS,EAAE;MACtB,SAAS,EAAE,SAAS,EAAE;MACtB,MAAM,EAAE,SAAS,EAAE;MACnB,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAS,MAAK;OAAK,WAAU;MAAe,CAAA;KAClC,GAPN,YAOM,IACV,EAAY,CAAI,IAClB,kBAAC,EAAO,KAAR;MAEE,SAAS,EAAE,SAAS,EAAE;MACtB,SAAS,EAAE,SAAS,EAAE;MACtB,MAAM,EAAE,SAAS,EAAE;MACnB,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAM,MAAM;OAAW,MAAK;OAAK,WAAU;MAAyB,CAAA;KAC1D,GAPN,OAOM,IAEZ,kBAAC,EAAO,KAAR;MAEE,SAAS,EAAE,SAAS,EAAE;MACtB,SAAS,EAAE,SAAS,EAAE;MACtB,MAAM,EAAE,SAAS,EAAE;MACnB,YAAY,EAAO;gBAEnB,kBAAC,GAAD;OAAM,MAAM;OAAU,MAAK;OAAK,WAAU;MAAyB,CAAA;KACzD,GAPN,MAOM;IAEC,CAAA;GACd,CAAA;GAGL,kBAAC,QAAD;IAAM,WAAU;cACb,EAAK;GACF,CAAA;GAGL,IACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,MAAK;KACL,OAAO,EAAiB,EAAK,MAAM;KACnC,OAAO,EAAiB,CAAI;KAC5B,WAAU;IACX,CAAA,GACA,EAAK,aAAa,KAAA,KACjB,kBAAC,QAAD;KAAM,WAAU;eAAhB,CACG,EAAK,UAAS,GACX;MAEL;QACH,EAAK,WAAW,aAClB,kBAAC,QAAD;IAAM,WAAU;cAA+B;GAAU,CAAA,IACvD,EAAK,WAAW,UAClB,kBAAC,QAAD;IAAM,WAAU;cACb,EAAK,SAAS;GACX,CAAA,IAEN,kBAAC,QAAD;IAAM,WAAU;cACb,EAAe,EAAK,IAAI;GACrB,CAAA;GAIP,EAAK,WAAW,WAAW,KAC1B,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAQ,EAAK,EAAE;IAC9B,WAAU;IACV,cAAY,SAAS,EAAK;IAC1B,OAAM;cAEN,kBAAC,GAAD,EAAa,WAAU,cAAe,CAAA;GAChC,CAAA;GAET,CAAC,KAAc,KACd,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,EAAK,EAAE;IAC/B,WAAU;IACV,cAAY,UAAU,EAAK;IAC3B,OAAM;cAEN,kBAAC,GAAD,EAAO,WAAU,cAAe,CAAA;GAC1B,CAAA;EAEA;;AAEhB;AAEA,SAAS,EAAmB,EAC1B,UACA,YACA,aACA,kBACA,gBAAa,MAQZ;CACD,IAAM,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,IAAS,KAAW,GACpB,IAAgB,EAAM,QAAQ,MAAM,EAAE,WAAW,UAAU,CAAC,CAAC,QAC7D,IAAa,EAAM,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC,CAAC,QACvD,IAAc,EAAM,OACvB,MAAM,EAAE,WAAW,cAAc,EAAE,WAAW,OACjD,GAGM,IAAe,EAAM,OAAO,CAAqB,GACjD,IAAe,EAAM,OAAO,CAAC;CAEnC,EAAM,gBAAgB;EACpB,IAAI,KAAiB,QAAQ,CAAC,GAAa;EAC3C,IAAI,GAAQ;GACV,IAAM,IAAU,KAAK,IAAI,IAAI,EAAa;GAC1C,EAAa,UAAU,KAAK,IAAI,GAAG,EAAa,UAAU,CAAO;GACjE;EACF;EACA,EAAa,UAAU,KAAK,IAAI;EAChC,IAAM,IAAQ,iBAAiB;GAC7B,EAAY,QAAQ,CAAa;EACnC,GAAG,EAAa,OAAO;EACvB,aAAa,aAAa,CAAK;CACjC,GAAG;EAAC;EAAe;EAAa;CAAM,CAAC;CAEvC,IAAM,IAAc,IAChB,IAAa,IACX,eACA,iBACF,eAEE,IAA0B,IAC5B,IAAa,IACX,UACA,YACF,WAEE,IAAe,KAAe,IAAa;CACjD,OACE,kBAAC,EAAO,KAAR;EACE,QAAA;EACA,MAAM,IAAe,UAAU;EAC/B,aAAW,IAAe,cAAc;EACxC,cAAW;EACX,WAAW,EACT,oGAEA,KAAgB,YAClB;EACA,oBAAoB,EAAW,EAAI;EACnC,oBAAoB,EAAW,EAAK;EACpC,sBAAsB,EAAW,EAAI;EACrC,qBAAqB,EAAW,EAAK;EACrC,YAAY,EAAQ;YAdtB;GAiBG,KACC,kBAAC,OAAD,EAAK,WAAW,EAAG,qCAAqC,CAAW,EAAI,CAAA;GAIzE,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;QAAI;QAClC,SAAS;SAAE,SAAS;SAAG,OAAO;QAAE;QAChC,MAAM;SAAE,SAAS;SAAG,OAAO;QAAI;QAC/B,YAAY,EAAQ;kBAEpB,kBAAC,GAAD;SAAM,MAAM;SAAiB,MAAK;SAAK,WAAU;QAA0B,CAAA;OACjE,GAPN,YAOM,IAEZ,kBAAC,EAAO,KAAR;QAEE,SAAS;SAAE,SAAS;SAAG,OAAO;QAAI;QAClC,SAAS;SAAE,SAAS;SAAG,OAAO;QAAE;QAChC,MAAM;SAAE,SAAS;SAAG,OAAO;QAAI;QAC/B,YAAY,EAAQ;kBAEpB,kBAAC,GAAD;SAAM,MAAM;SAAW,MAAK;SAAK,WAAU;QAA4B,CAAA;OAC7D,GAPN,cAOM,IAGd,kBAAC,EAAO,KAAR;QAEE,SAAS,EAAE,SAAS,EAAE;QACtB,SAAS,EAAE,SAAS,EAAE;QACtB,MAAM,EAAE,SAAS,EAAE;QACnB,YAAY,EAAO;kBAEnB,kBAAC,GAAD;SAAM,MAAM;SAAY,MAAK;SAAK,WAAU;QAAkC,CAAA;OACpE,GAPN,aAOM;MAEC,CAAA,GACjB,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;MAC7D,CAAA,CACA;;KACJ,CAAC,KACA,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACG;OAAc;OAAK,EAAM;OAAO;OAChC,IAAa,KAAK,MAAM,EAAW;MACnC;;KAIL,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UACG,EAAM,KAAK,MACV,kBAAC,GAAD;OAEQ;OACG;OACC;MACX,GAJM,EAAK,EAIX,CACF,EACc,CAAA;KACd,CAAA;KAGL,kBAAC,OAAD;MAAK,WAAU;MAAU,aAAU;gBAAnC;OACG;OAAc;OAAK,EAAM;OAAO;OAChC,IAAa,KAAK,KAAK,EAAW;MAChC;;IACF;;GAGJ,KACC,kBAAC,GAAD;IACE,UAAU;IACV,MAAM;IACN,QAAQ;GACT,CAAA;EAEO;;AAEhB;AAMA,SAAS,EACP,GACA,GACe;CACf,OAAO;EACL,IAAI,GAAS;EACb,UAAU,GAAS,YAAY,KAAY;EAC3C,UAAU;EACV,YAAY,EAAE,OAAO,SAAS;CAChC;AACF;AAEA,SAAS,EACP,GACA,GACA,GACA;CACA,EAAqB;CACrB,IAAM,IAAW,GAAS,YAAY;CACtC,OAAO,EAAY,aAEf,kBAAC,GAAD;EACQ;EACN,OAAO;EACP,aAAa,GAAS;EACtB,QAAQ,GAAS;EACjB,QAAQ,GAAS;EACP;EACV,YAAY,GAAS;CACtB,CAAA,GAEH,EAAoB,GAAS,CAAQ,CACvC;AACF;AAeA,SAAS,EAAM,GAAmC,GAAwB;CACxE,OAAO,EAAiB,WAAW,GAAS,CAAO;AACrD;AAEA,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS,CAAO,GAGrD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS,CAAO,GAGrD,EAAM,SACJ,GACA,MAEO,EAAiB,SAAS,GAAS,CAAO,GAGnD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS,CAAO,GAGrD,EAAM,QACJ,GACA,MAEO,EAAiB,QAAQ,GAAS,CAAO,GAGlD,EAAM,WACJ,GACA,MAEO,EAAiB,WAAW,GAAS;CAC1C,GAAG;CACH,UAAU,GAAS,YAAY;AACjC,CAAC,GAGH,EAAM,WACJ,GACA,MAQG;CACH,IAAM,IAAK,EAAY,aAEnB,kBAAC,GAAD;EAAc,MAAK;EAAU,OAAO,EAAQ;EAAS,cAAc;CAAQ,CAAA,GAE7E;EAAE,UAAU;EAAU,UAAU;EAAM,YAAY,EAAE,OAAO,SAAS;CAAE,CACxE,GAEM,KAAe,GAAiB,MAA6B;EAIjE,EAAY,aAER,kBAAC,GAAD;GACQ;GACN,OAAO;GACP,UAAU;GACV,eAAe;EAChB,CAAA,GAEH;GAAE;GAAI,UAAU;GAAU,UAAU;GAAM,YAAY,EAAE,OAAO,SAAS;EAAE,CAC5E;CACF;CAkBA,OAhBA,EACG,MAAM,MAAS;EACd,IAAM,IACJ,OAAO,EAAQ,WAAY,aACvB,EAAQ,QAAQ,CAAI,IACpB,EAAQ;EACd,EAAY,WAAW,CAAO;CAChC,CAAC,CAAC,CACD,OAAO,MAAU;EAChB,IAAM,IACJ,OAAO,EAAQ,SAAU,aACrB,EAAQ,MAAM,CAAK,IACnB,EAAQ;EACd,EAAY,SAAS,CAAO;CAC9B,CAAC,GAEI;AACT,GAEA,EAAM,QAAQ,GAAmC,MAA8B;CAC7E,IAAM,IAAW,EAAQ,YAAY;CACrC,OAAO,EAAY,aAEf,kBAAC,GAAD;EACE,MAAK;EACL,OAAO;EACP,aAAa,EAAQ;EACrB,QAAQ;GAAE,OAAO;GAAQ,SAAS,EAAQ;EAAO;EACvC;CACX,CAAA,GAEH;EAAE;EAAU,UAAU;EAAM,YAAY,EAAE,OAAO,SAAS;CAAE,CAC9D;AACF,GAEA,EAAM,UAAU,MAAgC;CAE9C,IAAM,IAAU,EAAQ,MAAM,OAAO,KAAK,IAAI,CAAC;CAoB/C,OAlBA,EAAY,aAER,kBAAC,GAAD;EACE,OAAO,EAAQ;EACf,SAAS,EAAQ;EACjB,UAAU,EAAQ;EAClB,eAAe;EACf,YAAY,EAAQ;CACrB,CAAA,GAEH;EACE,IAAI;EACJ,UAAU;EACV,UAAU;EACV,YAAY,EAAE,OAAO,SAAS;CAChC,CACF,GAEO;AACT,GAEA,EAAM,UACJ,GACA,MAEO,EAAY,OAAO,GAAQ;CAChC,GAAG;CACH,UAAU;CACV,YAAY;EAAE,OAAO;EAAU,GAAI,GAAS;CAAsC;AACpF,CAAC,GAGH,EAAM,WAAW,MAAyB;CACxC,AAAI,MAAO,KAAA,IAGT,EAAY,QAAQ,IAFpB,EAAY,QAAQ,CAAE;AAI1B"}
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 { MotionPreference } from '../motion/motion-preference'\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 /* The countdown now runs in a visible groove rather than over bare surface,\n so the bar reads as \"time remaining\" instead of a stray rule (design\n 2026-08-24). `surface-panel-hover` is the DS's designated track fill —\n a container value here would be a no-op in light, where overlay, panel\n and base are all the same white. */\n <div className=\"absolute bottom-0 left-0 right-0 h-ds-01 overflow-hidden bg-surface-panel-hover\">\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 <MotionPreference>\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-body-md font-semibold text-surface-fg\">\n {title}\n </p>\n )}\n {description && (\n <p\n className={cn(\n 'text-body-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-body-sm font-medium text-accent-11 underline-offset-2 hover:underline hover:bg-surface-panel-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-body-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 </MotionPreference>\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 <MotionPreference>\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-body-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-caption tabular-nums text-surface-fg-muted\">\n {file.progress}%\n </span>\n )}\n </div>\n ) : file.status === 'complete' ? (\n <span className=\"text-body-xs text-success-11\">Done</span>\n ) : file.status === 'error' ? (\n <span className=\"max-w-[60px] truncate text-body-xs text-error-11\">\n {file.error || 'Failed'}\n </span>\n ) : (\n <span className=\"text-caption 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 </MotionPreference>\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 <MotionPreference>\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-body-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-caption 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 </MotionPreference>\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 +1 @@
1
- {"version":3,"file":"toggle.d.ts","sourceRoot":"","sources":["../../src/ui/toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,QAAA,MAAM,cAAc;;;;8EA4BnB,CAAA;AAED,QAAA,MAAM,MAAM;;;;yHAYV,CAAA;AAGF,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,GACnF,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;AAErC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
1
+ {"version":3,"file":"toggle.d.ts","sourceRoot":"","sources":["../../src/ui/toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,QAAA,MAAM,cAAc;;;;8EAsCnB,CAAA;AAED,QAAA,MAAM,MAAM;;;;yHAeV,CAAA;AAGF,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,GACnF,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;AAErC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
package/dist/ui/toggle.js CHANGED
@@ -1,13 +1,14 @@
1
1
  "use client";
2
2
  import { motionProps as e, springs as t } from "./lib/motion.js";
3
- import { cn as n } from "./lib/utils.js";
4
- import { Root as r } from "../_chunks/primitives/react-toggle.js";
5
- import * as i from "react";
6
- import { jsx as a } from "react/jsx-runtime";
7
- import { motion as o } from "framer-motion";
8
- import { cva as s } from "class-variance-authority";
3
+ import { MotionPreference as n } from "../_chunks/motion-preference.js";
4
+ import { cn as r } from "./lib/utils.js";
5
+ import { Root as i } from "../_chunks/primitives/react-toggle.js";
6
+ import * as a from "react";
7
+ import { jsx as o } from "react/jsx-runtime";
8
+ import { motion as s } from "framer-motion";
9
+ import { cva as c } from "class-variance-authority";
9
10
  //#region src/ui/toggle.tsx
10
- var c = o.create(r), l = s("inline-flex items-center justify-center gap-ds-03 rounded-control font-medium transition-colors duration-fast-01 ease-productive-standard focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled", {
11
+ var l = s.create(i), u = c("inline-flex items-center justify-center gap-ds-03 rounded-control font-medium transition-colors duration-fast-01 ease-productive-standard focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled", {
11
12
  variants: {
12
13
  variant: {
13
14
  default: "bg-transparent hover:bg-surface-panel-hover text-surface-fg-muted",
@@ -19,10 +20,10 @@ var c = o.create(r), l = s("inline-flex items-center justify-center gap-ds-03 ro
19
20
  lg: "h-ds-lg px-ds-05 text-body-lg"
20
21
  },
21
22
  color: {
22
- accent: "data-[state=on]:bg-accent-2 data-[state=on]:text-accent-11",
23
- error: "data-[state=on]:bg-error-2 data-[state=on]:text-error-11",
24
- success: "data-[state=on]:bg-success-2 data-[state=on]:text-success-11",
25
- neutral: "data-[state=on]:bg-surface-panel-hover data-[state=on]:text-surface-fg"
23
+ accent: "data-[state=on]:bg-palette-soft-hover data-[state=on]:text-palette-text",
24
+ error: "data-[state=on]:bg-palette-soft-hover data-[state=on]:text-palette-text",
25
+ success: "data-[state=on]:bg-palette-soft-hover data-[state=on]:text-palette-text",
26
+ neutral: "data-[state=on]:bg-palette-soft-hover data-[state=on]:text-surface-fg"
26
27
  }
27
28
  },
28
29
  defaultVariants: {
@@ -30,17 +31,18 @@ var c = o.create(r), l = s("inline-flex items-center justify-center gap-ds-03 ro
30
31
  size: "md",
31
32
  color: "accent"
32
33
  }
33
- }), u = i.forwardRef(({ className: r, variant: i, size: o, color: s, ...u }, d) => /* @__PURE__ */ a(c, {
34
- ref: d,
34
+ }), d = a.forwardRef(({ className: i, variant: a, size: s, color: c, ...d }, f) => /* @__PURE__ */ o(n, { children: /* @__PURE__ */ o(l, {
35
+ ref: f,
35
36
  whileTap: { scale: .95 },
36
37
  transition: t.snappy,
37
- className: n(l({
38
- variant: i,
39
- size: o,
40
- color: s
41
- }), r),
42
- ...e(u)
43
- }));
44
- u.displayName = r.displayName;
38
+ "data-palette": c ?? void 0,
39
+ className: r(u({
40
+ variant: a,
41
+ size: s,
42
+ color: c
43
+ }), i),
44
+ ...e(d)
45
+ }) }));
46
+ d.displayName = i.displayName;
45
47
  //#endregion
46
- export { u as Toggle, l as toggleVariants };
48
+ export { d as Toggle, u as toggleVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"toggle.js","names":[],"sources":["../../src/ui/toggle.tsx"],"sourcesContent":["'use client'\n\nimport * as TogglePrimitive from '@primitives/react-toggle'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst MotionToggleRoot = motion.create(TogglePrimitive.Root)\n\nconst toggleVariants = cva(\n 'inline-flex items-center justify-center gap-ds-03 rounded-control font-medium transition-colors duration-fast-01 ease-productive-standard focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled',\n {\n variants: {\n variant: {\n default:\n 'bg-transparent hover:bg-surface-panel-hover text-surface-fg-muted',\n outline:\n 'border border-surface-border-interactive bg-transparent hover:bg-surface-panel-hover hover:border-surface-border-interactive',\n },\n size: {\n sm: 'h-ds-sm px-ds-03 text-body-sm',\n md: 'h-ds-md px-ds-04 text-body-md',\n lg: 'h-ds-lg px-ds-05 text-body-lg',\n },\n color: {\n accent: 'data-[state=on]:bg-accent-2 data-[state=on]:text-accent-11',\n error: 'data-[state=on]:bg-error-2 data-[state=on]:text-error-11',\n success: 'data-[state=on]:bg-success-2 data-[state=on]:text-success-11',\n neutral: 'data-[state=on]:bg-surface-panel-hover data-[state=on]:text-surface-fg',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n color: 'accent',\n },\n },\n)\n\nconst Toggle = React.forwardRef<\n React.ElementRef<typeof TogglePrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &\n VariantProps<typeof toggleVariants>\n>(({ className, variant, size, color, ...props }, ref) => (\n <MotionToggleRoot\n ref={ref}\n whileTap={{ scale: 0.95 }}\n transition={springs.snappy}\n className={cn(toggleVariants({ variant, size, color }), className)}\n {...motionProps(props)}\n />\n))\nToggle.displayName = TogglePrimitive.Root.displayName\n\nexport type ToggleProps = React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &\n VariantProps<typeof toggleVariants>\n\nexport { Toggle, toggleVariants }\n"],"mappings":";;;;;;;;;AAUA,IAAM,IAAmB,EAAO,OAAO,CAAoB,GAErD,IAAiB,EACrB,qTACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,SACE;EACJ;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,OAAO;GACL,QAAQ;GACR,OAAO;GACP,SAAS;GACT,SAAS;EACX;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,OAAO;CACT;AACF,CACF,GAEM,IAAS,EAAM,YAIlB,EAAE,cAAW,YAAS,SAAM,UAAO,GAAG,KAAS,MAChD,kBAAC,GAAD;CACO;CACL,UAAU,EAAE,OAAO,IAAK;CACxB,YAAY,EAAQ;CACpB,WAAW,EAAG,EAAe;EAAE;EAAS;EAAM;CAAM,CAAC,GAAG,CAAS;CACjE,GAAI,EAAY,CAAK;AACtB,CAAA,CACF;AACD,EAAO,cAAA,EAAmC"}
1
+ {"version":3,"file":"toggle.js","names":[],"sources":["../../src/ui/toggle.tsx"],"sourcesContent":["'use client'\n\nimport * as TogglePrimitive from '@primitives/react-toggle'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { MotionPreference } from '../motion/motion-preference'\nimport { motionProps,springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst MotionToggleRoot = motion.create(TogglePrimitive.Root)\n\nconst toggleVariants = cva(\n 'inline-flex items-center justify-center gap-ds-03 rounded-control font-medium transition-colors duration-fast-01 ease-productive-standard focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled',\n {\n variants: {\n variant: {\n default:\n 'bg-transparent hover:bg-surface-panel-hover text-surface-fg-muted',\n outline:\n 'border border-surface-border-interactive bg-transparent hover:bg-surface-panel-hover hover:border-surface-border-interactive',\n },\n size: {\n sm: 'h-ds-sm px-ds-03 text-body-sm',\n md: 'h-ds-md px-ds-04 text-body-md',\n lg: 'h-ds-lg px-ds-05 text-body-lg',\n },\n // Pressed state only — an unpressed toggle carries no colour at all.\n //\n // `soft-hover`, not `subtle`: both variants hover to `surface-panel-hover`,\n // and `palette-subtle` resolves to exactly that for neutral — so a pressed\n // neutral toggle was the identical colour to a hovered unpressed one\n // (1.00:1). On accent the two were 1.01:1 apart in light, and in dark the\n // unpressed-hovered toggle was the MORE prominent of the two. `soft-hover`\n // clears the hover fill in both themes for every palette.\n color: {\n accent: 'data-[state=on]:bg-palette-soft-hover data-[state=on]:text-palette-text',\n error: 'data-[state=on]:bg-palette-soft-hover data-[state=on]:text-palette-text',\n success: 'data-[state=on]:bg-palette-soft-hover data-[state=on]:text-palette-text',\n // Neutral takes full-contrast text rather than the muted `text` role,\n // because a pressed neutral toggle has no hue to carry the emphasis.\n neutral: 'data-[state=on]:bg-palette-soft-hover data-[state=on]:text-surface-fg',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n color: 'accent',\n },\n },\n)\n\nconst Toggle = React.forwardRef<\n React.ElementRef<typeof TogglePrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &\n VariantProps<typeof toggleVariants>\n>(({ className, variant, size, color, ...props }, ref) => (\n <MotionPreference>\n <MotionToggleRoot\n ref={ref}\n whileTap={{ scale: 0.95 }}\n transition={springs.snappy}\n data-palette={color ?? undefined}\n className={cn(toggleVariants({ variant, size, color }), className)}\n {...motionProps(props)}\n />\n </MotionPreference>\n))\nToggle.displayName = TogglePrimitive.Root.displayName\n\nexport type ToggleProps = React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &\n VariantProps<typeof toggleVariants>\n\nexport { Toggle, toggleVariants }\n"],"mappings":";;;;;;;;;;AAWA,IAAM,IAAmB,EAAO,OAAO,CAAoB,GAErD,IAAiB,EACrB,qTACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,SACE;EACJ;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EASA,OAAO;GACL,QAAQ;GACR,OAAO;GACP,SAAS;GAGT,SAAS;EACX;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,OAAO;CACT;AACF,CACF,GAEM,IAAS,EAAM,YAIlB,EAAE,cAAW,YAAS,SAAM,UAAO,GAAG,KAAS,MAChD,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;CACO;CACL,UAAU,EAAE,OAAO,IAAK;CACxB,YAAY,EAAQ;CACpB,gBAAc,KAAS,KAAA;CACvB,WAAW,EAAG,EAAe;EAAE;EAAS;EAAM;CAAM,CAAC,GAAG,CAAS;CACjE,GAAI,EAAY,CAAK;AACtB,CAAA,EACe,CAAA,CACnB;AACD,EAAO,cAAA,EAAmC"}
@@ -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;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
+ {"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;AAW9B,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,gKAsClB,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,65 +1,66 @@
1
1
  "use client";
2
2
  import { springs as e, tweens as t } from "./lib/motion.js";
3
- import { cn as n } from "./lib/utils.js";
4
- import { useControllableOpen as r } from "../_chunks/use-controllable-open.js";
5
- import { Content2 as i, Portal as a, Provider as o, Root3 as s, Trigger as c } from "../_chunks/primitives/react-tooltip.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";
3
+ import { MotionPreference as n } from "../_chunks/motion-preference.js";
4
+ import { cn as r } from "./lib/utils.js";
5
+ import { useControllableOpen as i } from "../_chunks/use-controllable-open.js";
6
+ import { Content2 as a, Portal as o, Provider as s, Root3 as c, Trigger as l } from "../_chunks/primitives/react-tooltip.js";
7
+ import * as u from "react";
8
+ import { Fragment as d, jsx as f } from "react/jsx-runtime";
9
+ import { AnimatePresence as p, motion as m } from "framer-motion";
9
10
  //#region src/ui/tooltip.tsx
10
- var m = l.createContext(!1), h = ({ children: e, ...t }) => /* @__PURE__ */ d(m.Provider, {
11
+ var h = u.createContext(!1), g = ({ children: e, ...t }) => /* @__PURE__ */ f(h.Provider, {
11
12
  value: !0,
12
- children: /* @__PURE__ */ d(o, {
13
+ children: /* @__PURE__ */ f(s, {
13
14
  ...t,
14
15
  children: e
15
16
  })
16
17
  });
17
- function g({ children: e }) {
18
- return l.useContext(m) ? /* @__PURE__ */ d(u, { children: e }) : /* @__PURE__ */ d(m.Provider, {
18
+ function _({ children: e }) {
19
+ return u.useContext(h) ? /* @__PURE__ */ f(d, { children: e }) : /* @__PURE__ */ f(h.Provider, {
19
20
  value: !0,
20
- children: /* @__PURE__ */ d(o, {
21
+ children: /* @__PURE__ */ f(s, {
21
22
  delayDuration: 300,
22
23
  children: e
23
24
  })
24
25
  });
25
26
  }
26
- var _ = l.createContext({ open: !1 }), v = ({ open: e, defaultOpen: t, onOpenChange: n, ...i }) => {
27
- let { open: a, setOpen: o } = r({
27
+ var v = u.createContext({ open: !1 }), y = ({ open: e, defaultOpen: t, onOpenChange: n, ...r }) => {
28
+ let { open: a, setOpen: o } = i({
28
29
  open: e,
29
30
  defaultOpen: t,
30
31
  onOpenChange: n
31
- }), c = l.useMemo(() => ({ open: a }), [a]);
32
- return /* @__PURE__ */ d(g, { children: /* @__PURE__ */ d(_.Provider, {
33
- value: c,
34
- children: /* @__PURE__ */ d(s, {
32
+ }), s = u.useMemo(() => ({ open: a }), [a]);
33
+ return /* @__PURE__ */ f(_, { children: /* @__PURE__ */ f(v.Provider, {
34
+ value: s,
35
+ children: /* @__PURE__ */ f(c, {
35
36
  open: a,
36
37
  onOpenChange: o,
37
- ...i
38
+ ...r
38
39
  })
39
40
  }) });
40
41
  };
41
- v.displayName = "Tooltip";
42
- var y = c, b = {
42
+ y.displayName = "Tooltip";
43
+ var b = l, x = {
43
44
  top: { y: 4 },
44
45
  bottom: { y: -4 },
45
46
  left: { x: 4 },
46
47
  right: { x: -4 }
47
- }, x = l.forwardRef(({ className: r, sideOffset: o = 4, side: s = "top", children: c, ...u }, m) => {
48
- let { open: h } = l.useContext(_), g = b[s] ?? {};
49
- return /* @__PURE__ */ d(f, { children: h && /* @__PURE__ */ d(a, {
48
+ }, S = u.forwardRef(({ className: i, sideOffset: s = 4, side: c = "top", children: l, ...d }, h) => {
49
+ let { open: g } = u.useContext(v), _ = x[c] ?? {};
50
+ return /* @__PURE__ */ f(n, { children: /* @__PURE__ */ f(p, { children: g && /* @__PURE__ */ f(o, {
50
51
  forceMount: !0,
51
- children: /* @__PURE__ */ d(i, {
52
- ref: m,
52
+ children: /* @__PURE__ */ f(a, {
53
+ ref: h,
53
54
  forceMount: !0,
54
- sideOffset: o,
55
- side: s,
56
- ...u,
55
+ sideOffset: s,
56
+ side: c,
57
+ ...d,
57
58
  asChild: !0,
58
- children: /* @__PURE__ */ d(p.div, {
59
+ children: /* @__PURE__ */ f(m.div, {
59
60
  initial: {
60
61
  opacity: 0,
61
62
  scale: .95,
62
- ...g
63
+ ..._
63
64
  },
64
65
  animate: {
65
66
  opacity: 1,
@@ -70,18 +71,18 @@ var y = c, b = {
70
71
  exit: {
71
72
  opacity: 0,
72
73
  scale: .95,
73
- ...g
74
+ ..._
74
75
  },
75
76
  transition: {
76
77
  ...e.snappy,
77
78
  opacity: t.fade
78
79
  },
79
- className: n("z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-body-sm text-surface-inverted-fg shadow-floating", r),
80
- children: c
80
+ className: r("z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-body-sm text-surface-inverted-fg shadow-floating", i),
81
+ children: l
81
82
  })
82
83
  })
83
- }) });
84
+ }) }) });
84
85
  });
85
- x.displayName = i.displayName;
86
+ S.displayName = a.displayName;
86
87
  //#endregion
87
- export { v as Tooltip, x as TooltipContent, h as TooltipProvider, y as TooltipTrigger };
88
+ export { y as Tooltip, S as TooltipContent, g as TooltipProvider, b as TooltipTrigger };
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/ui/tooltip.tsx"],"sourcesContent":["'use client'\n\nimport * as TooltipPrimitive from '@primitives/react-tooltip'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs, tweens } from './lib/motion'\nimport { useControllableOpen } from './lib/use-controllable-open'\nimport { cn } from './lib/utils'\n\n// ── Auto-provider: wraps with TooltipPrimitive.Provider if none exists ──\n\nconst TooltipProviderContext = React.createContext(false)\n\nconst TooltipProvider: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>> = ({\n children,\n ...props\n}) => (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider {...props}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n)\n\nfunction AutoProvider({ children }: { children: React.ReactNode }) {\n const hasProvider = React.useContext(TooltipProviderContext)\n if (hasProvider) return <>{children}</>\n return (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider delayDuration={300}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n )\n}\n\n// ── Internal context to thread `open` state to animated children ──\n\ntype TooltipContextValue = { open: boolean }\nconst TooltipContext = React.createContext<TooltipContextValue>({ open: false })\n\nconst Tooltip: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>> = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}) => {\n const { open, setOpen } = useControllableOpen({ open: openProp, defaultOpen, onOpenChange })\n\n const contextValue = React.useMemo(() => ({ open }), [open])\n\n return (\n <AutoProvider>\n <TooltipContext.Provider value={contextValue}>\n <TooltipPrimitive.Root open={open} onOpenChange={setOpen} {...props} />\n </TooltipContext.Provider>\n </AutoProvider>\n )\n}\nTooltip.displayName = 'Tooltip'\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\n// ── Side-based slide offsets ──\n\nconst sideOffset: Record<string, { x?: number; y?: number }> = {\n top: { y: 4 },\n bottom: { y: -4 },\n left: { x: 4 },\n right: { x: -4 },\n}\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset: sideOffsetProp = 4, side = 'top', children, ...props }, ref) => {\n const { open } = React.useContext(TooltipContext)\n const slideInit = sideOffset[side] ?? {}\n\n return (\n <AnimatePresence>\n {open && (\n <TooltipPrimitive.Portal forceMount>\n <TooltipPrimitive.Content\n ref={ref}\n forceMount\n sideOffset={sideOffsetProp}\n side={side}\n {...props}\n asChild\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95, ...slideInit }}\n animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, ...slideInit }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-body-sm text-surface-inverted-fg shadow-floating',\n className,\n )}\n >\n {children}\n </motion.div>\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )}\n </AnimatePresence>\n )\n})\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n\nexport { Tooltip, TooltipContent, TooltipProvider,TooltipTrigger }\n"],"mappings":";;;;;;;;;AAYA,IAAM,IAAyB,EAAM,cAAc,EAAK,GAElD,KAA+F,EACnG,aACA,GAAG,QAEH,kBAAC,EAAuB,UAAxB;CAAiC,OAAO;WACtC,kBAAC,GAAD;EAA2B,GAAI;EAC5B;CACwB,CAAA;AACI,CAAA;AAGnC,SAAS,EAAa,EAAE,eAA2C;CAGjE,OAFoB,EAAM,WAAW,CACjC,IAAoB,kBAAA,GAAA,EAAG,YAAW,CAAA,IAEpC,kBAAC,EAAuB,UAAxB;EAAiC,OAAO;YACtC,kBAAC,GAAD;GAA2B,eAAe;GACvC;EACwB,CAAA;CACI,CAAA;AAErC;AAKA,IAAM,IAAiB,EAAM,cAAmC,EAAE,MAAM,GAAM,CAAC,GAEzE,KAAmF,EACvF,MAAM,GACN,gBACA,iBACA,GAAG,QACC;CACJ,IAAM,EAAE,SAAM,eAAY,EAAoB;EAAE,MAAM;EAAU;EAAa;CAAa,CAAC,GAErF,IAAe,EAAM,eAAe,EAAE,QAAK,IAAI,CAAC,CAAI,CAAC;CAE3D,OACE,kBAAC,GAAD,EAAA,UACE,kBAAC,EAAe,UAAhB;EAAyB,OAAO;YAC9B,kBAAC,GAAD;GAA6B;GAAM,cAAc;GAAS,GAAI;EAAQ,CAAA;CAC/C,CAAA,EACb,CAAA;AAElB;AACA,EAAQ,cAAc;AAEtB,IAAM,IAAiB,GAIjB,IAAyD;CAC7D,KAAK,EAAE,GAAG,EAAE;CACZ,QAAQ,EAAE,GAAG,GAAG;CAChB,MAAM,EAAE,GAAG,EAAE;CACb,OAAO,EAAE,GAAG,GAAG;AACjB,GAEM,IAAiB,EAAM,YAG1B,EAAE,cAAW,YAAY,IAAiB,GAAG,UAAO,OAAO,aAAU,GAAG,KAAS,MAAQ;CAC1F,IAAM,EAAE,YAAS,EAAM,WAAW,CAAc,GAC1C,IAAY,EAAW,MAAS,CAAC;CAEvC,OACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;EAAyB,YAAA;YACvB,kBAAC,GAAD;GACO;GACL,YAAA;GACA,YAAY;GACN;GACN,GAAI;GACJ,SAAA;aAEA,kBAAC,EAAO,KAAR;IACE,SAAS;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;IAAU;IACjD,SAAS;KAAE,SAAS;KAAG,OAAO;KAAG,GAAG;KAAG,GAAG;IAAE;IAC5C,MAAM;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;IAAU;IAC9C,YAAY;KAAE,GAAG,EAAQ;KAAQ,SAAS,EAAO;IAAK;IACtD,WAAW,EACT,6IACA,CACF;IAEC;GACS,CAAA;EACY,CAAA;CACH,CAAA,EAEZ,CAAA;AAErB,CAAC;AACD,EAAe,cAAA,EAAuC"}
1
+ {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/ui/tooltip.tsx"],"sourcesContent":["'use client'\n\nimport * as TooltipPrimitive from '@primitives/react-tooltip'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { MotionPreference } from '../motion/motion-preference'\nimport { springs, tweens } from './lib/motion'\nimport { useControllableOpen } from './lib/use-controllable-open'\nimport { cn } from './lib/utils'\n\n// ── Auto-provider: wraps with TooltipPrimitive.Provider if none exists ──\n\nconst TooltipProviderContext = React.createContext(false)\n\nconst TooltipProvider: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>> = ({\n children,\n ...props\n}) => (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider {...props}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n)\n\nfunction AutoProvider({ children }: { children: React.ReactNode }) {\n const hasProvider = React.useContext(TooltipProviderContext)\n if (hasProvider) return <>{children}</>\n return (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider delayDuration={300}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n )\n}\n\n// ── Internal context to thread `open` state to animated children ──\n\ntype TooltipContextValue = { open: boolean }\nconst TooltipContext = React.createContext<TooltipContextValue>({ open: false })\n\nconst Tooltip: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>> = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}) => {\n const { open, setOpen } = useControllableOpen({ open: openProp, defaultOpen, onOpenChange })\n\n const contextValue = React.useMemo(() => ({ open }), [open])\n\n return (\n <AutoProvider>\n <TooltipContext.Provider value={contextValue}>\n <TooltipPrimitive.Root open={open} onOpenChange={setOpen} {...props} />\n </TooltipContext.Provider>\n </AutoProvider>\n )\n}\nTooltip.displayName = 'Tooltip'\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\n// ── Side-based slide offsets ──\n\nconst sideOffset: Record<string, { x?: number; y?: number }> = {\n top: { y: 4 },\n bottom: { y: -4 },\n left: { x: 4 },\n right: { x: -4 },\n}\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset: sideOffsetProp = 4, side = 'top', children, ...props }, ref) => {\n const { open } = React.useContext(TooltipContext)\n const slideInit = sideOffset[side] ?? {}\n\n return (\n <MotionPreference>\n <AnimatePresence>\n {open && (\n <TooltipPrimitive.Portal forceMount>\n <TooltipPrimitive.Content\n ref={ref}\n forceMount\n sideOffset={sideOffsetProp}\n side={side}\n {...props}\n asChild\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95, ...slideInit }}\n animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, ...slideInit }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-body-sm text-surface-inverted-fg shadow-floating',\n className,\n )}\n >\n {children}\n </motion.div>\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )}\n </AnimatePresence>\n </MotionPreference>\n )\n})\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n\nexport { Tooltip, TooltipContent, TooltipProvider,TooltipTrigger }\n"],"mappings":";;;;;;;;;;AAaA,IAAM,IAAyB,EAAM,cAAc,EAAK,GAElD,KAA+F,EACnG,aACA,GAAG,QAEH,kBAAC,EAAuB,UAAxB;CAAiC,OAAO;WACtC,kBAAC,GAAD;EAA2B,GAAI;EAC5B;CACwB,CAAA;AACI,CAAA;AAGnC,SAAS,EAAa,EAAE,eAA2C;CAGjE,OAFoB,EAAM,WAAW,CACjC,IAAoB,kBAAA,GAAA,EAAG,YAAW,CAAA,IAEpC,kBAAC,EAAuB,UAAxB;EAAiC,OAAO;YACtC,kBAAC,GAAD;GAA2B,eAAe;GACvC;EACwB,CAAA;CACI,CAAA;AAErC;AAKA,IAAM,IAAiB,EAAM,cAAmC,EAAE,MAAM,GAAM,CAAC,GAEzE,KAAmF,EACvF,MAAM,GACN,gBACA,iBACA,GAAG,QACC;CACJ,IAAM,EAAE,SAAM,eAAY,EAAoB;EAAE,MAAM;EAAU;EAAa;CAAa,CAAC,GAErF,IAAe,EAAM,eAAe,EAAE,QAAK,IAAI,CAAC,CAAI,CAAC;CAE3D,OACE,kBAAC,GAAD,EAAA,UACE,kBAAC,EAAe,UAAhB;EAAyB,OAAO;YAC9B,kBAAC,GAAD;GAA6B;GAAM,cAAc;GAAS,GAAI;EAAQ,CAAA;CAC/C,CAAA,EACb,CAAA;AAElB;AACA,EAAQ,cAAc;AAEtB,IAAM,IAAiB,GAIjB,IAAyD;CAC7D,KAAK,EAAE,GAAG,EAAE;CACZ,QAAQ,EAAE,GAAG,GAAG;CAChB,MAAM,EAAE,GAAG,EAAE;CACb,OAAO,EAAE,GAAG,GAAG;AACjB,GAEM,IAAiB,EAAM,YAG1B,EAAE,cAAW,YAAY,IAAiB,GAAG,UAAO,OAAO,aAAU,GAAG,KAAS,MAAQ;CAC1F,IAAM,EAAE,YAAS,EAAM,WAAW,CAAc,GAC1C,IAAY,EAAW,MAAS,CAAC;CAEvC,OACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;EAAyB,YAAA;YACvB,kBAAC,GAAD;GACO;GACL,YAAA;GACA,YAAY;GACN;GACN,GAAI;GACJ,SAAA;aAEA,kBAAC,EAAO,KAAR;IACE,SAAS;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;IAAU;IACjD,SAAS;KAAE,SAAS;KAAG,OAAO;KAAG,GAAG;KAAG,GAAG;IAAE;IAC5C,MAAM;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;IAAU;IAC9C,YAAY;KAAE,GAAG,EAAQ;KAAQ,SAAS,EAAO;IAAK;IACtD,WAAW,EACT,6IACA,CACF;IAEC;GACS,CAAA;EACY,CAAA;CACH,CAAA,EAEZ,CAAA,EACD,CAAA;AAEtB,CAAC;AACD,EAAe,cAAA,EAAuC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tree-item.d.ts","sourceRoot":"","sources":["../../../src/ui/tree-view/tree-item.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAKlD,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,4BAA4B;IAC5B,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,wEAAwE;IACxE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,uDAAuD;IACvD,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAChC,oDAAoD;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,QAAQ,qFAqMb,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"tree-item.d.ts","sourceRoot":"","sources":["../../../src/ui/tree-view/tree-item.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAKlD,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,4BAA4B;IAC5B,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,wEAAwE;IACxE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,uDAAuD;IACvD,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAChC,oDAAoD;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,QAAQ,qFA0Mb,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -4,6 +4,13 @@
4
4
  - Server-safe: No
5
5
  - Category: composed
6
6
 
7
+ Floating selection toolbar for bulk actions — re-exported from `ui/bulk-action-bar`.
8
+
9
+ The implementation moved to `ui/bulk-action-bar` so `DataTable` could use it
10
+ (`ui/` may not import `composed/`). This path keeps working. **See
11
+ [ui/bulk-action-bar](../ui/bulk-action-bar.md) for the full reference**; it is
12
+ the canonical doc and this one only mirrors the surface.
13
+
7
14
  ## Props
8
15
  show: boolean (controls visibility)
9
16
  count: number (number of selected items — displayed in badge)
@@ -11,6 +18,7 @@
11
18
  actions: BulkActionBarAction[]
12
19
  totalCount: number (optional — total selectable items; enables "Select all")
13
20
  onSelectAll: () => void (optional — called by the "Select all" control)
21
+ placement: "bottom" | "top" | "inline" (default: "bottom")
14
22
  className: string
15
23
  ...div attributes (forwardRef to the toolbar div; HTMLAttributes spread)
16
24
 
@@ -25,7 +33,7 @@
25
33
  confirmMessage: string (optional — default "Are you sure?")
26
34
 
27
35
  ## Defaults
28
- (no optional props with defaults)
36
+ placement: "bottom"
29
37
 
30
38
  ## Example
31
39
  ```jsx
@@ -42,11 +50,10 @@
42
50
 
43
51
  ## Composability
44
52
  - **Standalone floating toolbar** — use with DataTable, TreeView, or any selection-capable UI.
45
- - **DataTable auto-integration:** DataTable's `bulkActions` prop renders this internally typically you don't render BulkActionBar directly when using DataTable.
46
- - **Data-driven actions:** `{ label, icon, onClick, color, disabled }[]`. For destructive confirmation, call ConfirmDialog from the onClick handler.
47
- - **Portal to body + fixed bottom-center z-50** — independent of parent layout. Check for other fixed elements that might overlap.
53
+ - **DataTable auto-integration:** DataTable's `bulkActions` prop renders this internally; `bulkActionsPosition` maps to `placement`.
54
+ - **Placement decides portalling** `bottom` / `top` portal to the body, `inline` renders in flow.
48
55
 
49
56
  ## Gotchas
50
- - Renders via `createPortal` into `document.body` will not appear during SSR (mounts only client-side)
51
- - Positioned fixed at bottom-center with `z-50`; ensure no other fixed elements conflict
52
- - Uses Framer Motion AnimatePresence for slide-in/out animation
57
+ - Prefer importing from `@devalok/shilp-sutra/ui/bulk-action-bar`. This path is kept so existing imports do not break.
58
+ - Portalled placements do not render during SSR; `inline` does.
59
+ - Inside a Dialog or Sheet use `placement="inline"`, or the portal escapes the overlay's stacking context.
@@ -0,0 +1,72 @@
1
+ # BulkActionBar
2
+
3
+ - Import: @devalok/shilp-sutra/ui/bulk-action-bar
4
+ - Server-safe: No
5
+ - Category: ui
6
+
7
+ Also re-exported from `@devalok/shilp-sutra/composed/bulk-action-bar`, which is
8
+ where it used to live. Both paths work. The implementation sits in `ui/` because
9
+ `DataTable` uses it and `ui/` may not import `composed/`.
10
+
11
+ ## Props
12
+ show: boolean (controls visibility)
13
+ count: number (number of selected items — displayed in badge)
14
+ onClearSelection: () => void
15
+ actions: BulkActionBarAction[]
16
+ totalCount: number (optional — total selectable items; enables "Select all")
17
+ onSelectAll: () => void (optional — called by the "Select all" control)
18
+ placement: "bottom" | "top" | "inline" (default: "bottom")
19
+ className: string
20
+ ...div attributes (forwardRef to the toolbar div; HTMLAttributes spread)
21
+
22
+ ### BulkActionBarAction
23
+ label: string
24
+ icon: IconInput (optional — any icon component or element)
25
+ onClick: () => void
26
+ color: "accent" | "error" | "success" | "warning" | "info" | "neutral" (default: "accent")
27
+ disabled: boolean (optional)
28
+ loading: boolean (optional — pending spinner on the action)
29
+ requiresConfirmation: boolean (optional — inline confirm before executing)
30
+ confirmMessage: string (optional — default "Are you sure?")
31
+
32
+ ## Defaults
33
+ placement: "bottom"
34
+
35
+ ## Example
36
+ ```jsx
37
+ <BulkActionBar
38
+ show={selected.length > 0}
39
+ count={selected.length}
40
+ onClearSelection={() => setSelected([])}
41
+ actions={[
42
+ { label: 'Archive', icon: IconArchive, onClick: archiveSelected },
43
+ {
44
+ label: 'Delete',
45
+ icon: IconTrash,
46
+ onClick: deleteSelected,
47
+ color: 'error',
48
+ requiresConfirmation: true,
49
+ },
50
+ ]}
51
+ />
52
+ ```
53
+
54
+ Inside a Dialog or Sheet, use `placement="inline"` so the bar stays within the
55
+ overlay:
56
+
57
+ ```jsx
58
+ <BulkActionBar placement="inline" show={n > 0} count={n} … />
59
+ ```
60
+
61
+ ## Composability
62
+ - **Standalone floating toolbar** — use with DataTable, TreeView, or any selection-capable UI.
63
+ - **DataTable auto-integration:** DataTable's `bulkActions` prop renders this internally, so you rarely render it directly alongside a DataTable. `bulkActionsPosition` maps to `placement`.
64
+ - **Data-driven actions:** `{ label, icon, onClick, color, disabled, loading, requiresConfirmation }[]`. Destructive confirmation is built in — set `requiresConfirmation` rather than reaching for ConfirmDialog.
65
+ - **Placement decides portalling.** `bottom` / `top` portal to `document.body` and pin to the viewport. `inline` renders in flow, in place.
66
+
67
+ ## Gotchas
68
+ - `placement="bottom"` / `"top"` render via `createPortal` into `document.body`, so they do not appear during SSR — they mount client-side only. `placement="inline"` has no portal and renders server-side normally.
69
+ - **A portal escapes its ancestors' stacking context.** Inside a Dialog or Sheet, a portalled bar floats over the page instead of belonging to the overlay — use `placement="inline"` there. This is why placement and portalling are one prop rather than two.
70
+ - Pinned placements use `z-sticky`; ensure no other fixed element conflicts.
71
+ - Follows the ARIA toolbar model: one tab stop, roving focus on Arrow / Home / End (mirrored under `dir="rtl"`), Escape to clear or to cancel a pending confirmation. If you wrap the actions in anything that also handles arrow keys, the two will fight.
72
+ - Uses Framer Motion AnimatePresence; respects `prefers-reduced-motion`.