@devalok/shilp-sutra 0.49.3 → 0.49.5

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 (329) hide show
  1. package/dist/_chunks/badge-group.js +8 -7
  2. package/dist/_chunks/badge-group.js.map +1 -1
  3. package/dist/_chunks/block-shell.js.map +1 -1
  4. package/dist/_chunks/chart-container.js.map +1 -1
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/colors.js.map +1 -1
  7. package/dist/_chunks/document-preview.js.map +1 -1
  8. package/dist/_chunks/emoji-suggestion.js.map +1 -1
  9. package/dist/_chunks/emoji.js +2 -2
  10. package/dist/_chunks/emoji.js.map +1 -1
  11. package/dist/_chunks/field-state.js.map +1 -1
  12. package/dist/_chunks/grid-lines.js.map +1 -1
  13. package/dist/_chunks/image-preview.js.map +1 -1
  14. package/dist/_chunks/keybinding.js.map +1 -1
  15. package/dist/_chunks/link-context.js.map +1 -1
  16. package/dist/_chunks/mention-suggestion.js.map +1 -1
  17. package/dist/_chunks/motion-provider.js.map +1 -1
  18. package/dist/_chunks/normalize-icon.js.map +1 -1
  19. package/dist/_chunks/oauth-button.js.map +1 -1
  20. package/dist/_chunks/popover.js.map +1 -1
  21. package/dist/_chunks/primitives.js +1123 -1153
  22. package/dist/_chunks/primitives.js.map +1 -1
  23. package/dist/_chunks/shared.js.map +1 -1
  24. package/dist/_chunks/success.js.map +1 -1
  25. package/dist/_chunks/tiptap.js +4283 -3460
  26. package/dist/_chunks/tiptap.js.map +1 -1
  27. package/dist/_chunks/tooltip.js.map +1 -1
  28. package/dist/_chunks/tree-view.js +1 -1
  29. package/dist/_chunks/tree-view.js.map +1 -1
  30. package/dist/_chunks/use-calendar.js.map +1 -1
  31. package/dist/_chunks/use-controllable-open.js.map +1 -1
  32. package/dist/_chunks/vendor-client.js +86 -59
  33. package/dist/_chunks/vendor-client.js.map +1 -1
  34. package/dist/_chunks/vendor-utils.js +555 -513
  35. package/dist/_chunks/vendor-utils.js.map +1 -1
  36. package/dist/ai/ai-command-provider.d.ts +1 -1
  37. package/dist/ai/ai-command-provider.d.ts.map +1 -1
  38. package/dist/ai/ai-command-provider.js.map +1 -1
  39. package/dist/ai/block-renderer.js.map +1 -1
  40. package/dist/ai/blocks/block-shell.d.ts +1 -1
  41. package/dist/ai/blocks/block-shell.d.ts.map +1 -1
  42. package/dist/ai/blocks/block-table.d.ts +1 -1
  43. package/dist/ai/blocks/block-table.d.ts.map +1 -1
  44. package/dist/ai/blocks/confirm.d.ts +1 -1
  45. package/dist/ai/blocks/confirm.d.ts.map +1 -1
  46. package/dist/ai/blocks/divider.d.ts +1 -1
  47. package/dist/ai/blocks/divider.d.ts.map +1 -1
  48. package/dist/ai/blocks/error.d.ts +1 -1
  49. package/dist/ai/blocks/error.d.ts.map +1 -1
  50. package/dist/ai/blocks/error.js.map +1 -1
  51. package/dist/ai/blocks/info.d.ts +1 -1
  52. package/dist/ai/blocks/info.d.ts.map +1 -1
  53. package/dist/ai/blocks/loading.d.ts +1 -1
  54. package/dist/ai/blocks/loading.d.ts.map +1 -1
  55. package/dist/ai/blocks/stat-row.d.ts +1 -1
  56. package/dist/ai/blocks/stat-row.d.ts.map +1 -1
  57. package/dist/ai/blocks/success.d.ts +1 -1
  58. package/dist/ai/blocks/success.d.ts.map +1 -1
  59. package/dist/ai/blocks/text.d.ts +1 -1
  60. package/dist/ai/blocks/text.d.ts.map +1 -1
  61. package/dist/ai/blocks/text.js.map +1 -1
  62. package/dist/ai/command-bar.js.map +1 -1
  63. package/dist/ai/conversation.js.map +1 -1
  64. package/dist/ai/devadoot-icon.d.ts +1 -1
  65. package/dist/ai/devadoot-icon.d.ts.map +1 -1
  66. package/dist/ai/index.js.map +1 -1
  67. package/dist/composed/activity-feed.js.map +1 -1
  68. package/dist/composed/avatar-group.js.map +1 -1
  69. package/dist/composed/bulk-action-bar.js.map +1 -1
  70. package/dist/composed/command-palette.js.map +1 -1
  71. package/dist/composed/confirm-dialog.js.map +1 -1
  72. package/dist/composed/content-card.js.map +1 -1
  73. package/dist/composed/date-picker/index.js.map +1 -1
  74. package/dist/composed/deadline-indicator.js.map +1 -1
  75. package/dist/composed/emoji-picker.d.ts +2 -2
  76. package/dist/composed/emoji-picker.d.ts.map +1 -1
  77. package/dist/composed/emoji-picker.js.map +1 -1
  78. package/dist/composed/empty-state.js.map +1 -1
  79. package/dist/composed/error-boundary.d.ts +1 -1
  80. package/dist/composed/error-boundary.js.map +1 -1
  81. package/dist/composed/extensions/emoji-node.js.map +1 -1
  82. package/dist/composed/file-preview/audio-preview.d.ts +2 -1
  83. package/dist/composed/file-preview/audio-preview.d.ts.map +1 -1
  84. package/dist/composed/file-preview/document-preview.d.ts +2 -1
  85. package/dist/composed/file-preview/document-preview.d.ts.map +1 -1
  86. package/dist/composed/file-preview/embed-preview.d.ts +2 -1
  87. package/dist/composed/file-preview/embed-preview.d.ts.map +1 -1
  88. package/dist/composed/file-preview/image-preview.d.ts +2 -1
  89. package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
  90. package/dist/composed/file-preview/shared.d.ts +5 -5
  91. package/dist/composed/file-preview/shared.d.ts.map +1 -1
  92. package/dist/composed/file-preview/video-preview.d.ts +2 -1
  93. package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
  94. package/dist/composed/file-preview.d.ts +1 -1
  95. package/dist/composed/file-preview.d.ts.map +1 -1
  96. package/dist/composed/file-preview.js.map +1 -1
  97. package/dist/composed/filter-bar.d.ts +2 -2
  98. package/dist/composed/filter-bar.d.ts.map +1 -1
  99. package/dist/composed/filter-bar.js.map +1 -1
  100. package/dist/composed/form-section.js.map +1 -1
  101. package/dist/composed/global-loading.js.map +1 -1
  102. package/dist/composed/inline-edit.js.map +1 -1
  103. package/dist/composed/lib/string-utils.js.map +1 -1
  104. package/dist/composed/loading-skeleton.js.map +1 -1
  105. package/dist/composed/markdown-viewer.js.map +1 -1
  106. package/dist/composed/master-detail.d.ts +3 -3
  107. package/dist/composed/master-detail.d.ts.map +1 -1
  108. package/dist/composed/master-detail.js.map +1 -1
  109. package/dist/composed/member-picker.js.map +1 -1
  110. package/dist/composed/multi-select-popover.js.map +1 -1
  111. package/dist/composed/page-header.js.map +1 -1
  112. package/dist/composed/page-skeletons.js.map +1 -1
  113. package/dist/composed/priority-indicator.js.map +1 -1
  114. package/dist/composed/responsive-modal.js +8 -4
  115. package/dist/composed/responsive-modal.js.map +1 -1
  116. package/dist/composed/rich-chat-input/attachment-strip.d.ts +2 -1
  117. package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
  118. package/dist/composed/rich-chat-input/chat-toolbar.d.ts +17 -17
  119. package/dist/composed/rich-chat-input/chat-toolbar.d.ts.map +1 -1
  120. package/dist/composed/rich-chat-input/recording-overlay.d.ts +2 -1
  121. package/dist/composed/rich-chat-input/recording-overlay.d.ts.map +1 -1
  122. package/dist/composed/rich-chat-input/reply-banner.d.ts +2 -1
  123. package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
  124. package/dist/composed/rich-chat-input/schedule-send.d.ts +4 -3
  125. package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
  126. package/dist/composed/rich-chat-input.js +2 -1
  127. package/dist/composed/rich-chat-input.js.map +1 -1
  128. package/dist/composed/rich-text-editor.js +2 -1
  129. package/dist/composed/rich-text-editor.js.map +1 -1
  130. package/dist/composed/schedule-view.js.map +1 -1
  131. package/dist/composed/simple-tooltip.js.map +1 -1
  132. package/dist/composed/status-badge.js.map +1 -1
  133. package/dist/hooks/use-color-mode.js +2 -1
  134. package/dist/hooks/use-color-mode.js.map +1 -1
  135. package/dist/hooks/use-mobile.js.map +1 -1
  136. package/dist/hooks/use-touch-device.js.map +1 -1
  137. package/dist/hooks/use-viewport-height.js.map +1 -1
  138. package/dist/motion/index.js.map +1 -1
  139. package/dist/motion/motion-provider.d.ts +1 -1
  140. package/dist/motion/motion-provider.d.ts.map +1 -1
  141. package/dist/motion/primitives-index.js.map +1 -1
  142. package/dist/shell/app-command-palette.js.map +1 -1
  143. package/dist/shell/bottom-navbar.js.map +1 -1
  144. package/dist/shell/command-registry.d.ts +1 -1
  145. package/dist/shell/command-registry.d.ts.map +1 -1
  146. package/dist/shell/command-registry.js.map +1 -1
  147. package/dist/shell/notification-center.js.map +1 -1
  148. package/dist/shell/notification-preferences.js.map +1 -1
  149. package/dist/shell/sidebar.js.map +1 -1
  150. package/dist/shell/top-bar.js.map +1 -1
  151. package/dist/ui/accordion.js.map +1 -1
  152. package/dist/ui/alert-dialog.js.map +1 -1
  153. package/dist/ui/alert.js.map +1 -1
  154. package/dist/ui/aspect-ratio.js.map +1 -1
  155. package/dist/ui/autocomplete.d.ts.map +1 -1
  156. package/dist/ui/autocomplete.js +8 -0
  157. package/dist/ui/autocomplete.js.map +1 -1
  158. package/dist/ui/avatar.d.ts +1 -1
  159. package/dist/ui/avatar.js.map +1 -1
  160. package/dist/ui/badge-group.d.ts +2 -6
  161. package/dist/ui/badge-group.d.ts.map +1 -1
  162. package/dist/ui/badge-indicator.d.ts +2 -6
  163. package/dist/ui/badge-indicator.d.ts.map +1 -1
  164. package/dist/ui/badge-indicator.js +19 -18
  165. package/dist/ui/badge-indicator.js.map +1 -1
  166. package/dist/ui/badge.d.ts +2 -4
  167. package/dist/ui/badge.d.ts.map +1 -1
  168. package/dist/ui/banner.js.map +1 -1
  169. package/dist/ui/breadcrumb.d.ts +2 -2
  170. package/dist/ui/breadcrumb.js.map +1 -1
  171. package/dist/ui/button-group.js.map +1 -1
  172. package/dist/ui/button-processing.d.ts +2 -1
  173. package/dist/ui/button-processing.d.ts.map +1 -1
  174. package/dist/ui/button-processing.js.map +1 -1
  175. package/dist/ui/button.js.map +1 -1
  176. package/dist/ui/card.js +1 -1
  177. package/dist/ui/card.js.map +1 -1
  178. package/dist/ui/charts/_internal/axes.d.ts +2 -1
  179. package/dist/ui/charts/_internal/axes.d.ts.map +1 -1
  180. package/dist/ui/charts/_internal/grid-lines.d.ts +2 -1
  181. package/dist/ui/charts/_internal/grid-lines.d.ts.map +1 -1
  182. package/dist/ui/charts/_internal/legend.d.ts +2 -1
  183. package/dist/ui/charts/_internal/legend.d.ts.map +1 -1
  184. package/dist/ui/charts/_internal/tooltip.d.ts +1 -1
  185. package/dist/ui/charts/_internal/tooltip.d.ts.map +1 -1
  186. package/dist/ui/charts/area-chart.js.map +1 -1
  187. package/dist/ui/charts/bar-chart.js.map +1 -1
  188. package/dist/ui/charts/gauge-chart.js.map +1 -1
  189. package/dist/ui/charts/line-chart.js.map +1 -1
  190. package/dist/ui/charts/pie-chart.js.map +1 -1
  191. package/dist/ui/charts/radar-chart.js.map +1 -1
  192. package/dist/ui/charts/sparkline.js +2 -2
  193. package/dist/ui/charts/sparkline.js.map +1 -1
  194. package/dist/ui/chat/date-separator.d.ts +2 -1
  195. package/dist/ui/chat/date-separator.d.ts.map +1 -1
  196. package/dist/ui/chat/message.d.ts +8 -8
  197. package/dist/ui/chat/message.d.ts.map +1 -1
  198. package/dist/ui/chat/typing-indicator.d.ts +2 -1
  199. package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
  200. package/dist/ui/chat/unread-separator.d.ts +2 -1
  201. package/dist/ui/chat/unread-separator.d.ts.map +1 -1
  202. package/dist/ui/checkbox.js.map +1 -1
  203. package/dist/ui/code.js.map +1 -1
  204. package/dist/ui/collapsible.js.map +1 -1
  205. package/dist/ui/color-input.d.ts.map +1 -1
  206. package/dist/ui/color-input.js +156 -149
  207. package/dist/ui/color-input.js.map +1 -1
  208. package/dist/ui/color-swatch.js.map +1 -1
  209. package/dist/ui/combobox.d.ts.map +1 -1
  210. package/dist/ui/combobox.js +137 -127
  211. package/dist/ui/combobox.js.map +1 -1
  212. package/dist/ui/container.js.map +1 -1
  213. package/dist/ui/context-menu.d.ts +2 -2
  214. package/dist/ui/context-menu.js.map +1 -1
  215. package/dist/ui/data-table-body.d.ts +1 -1
  216. package/dist/ui/data-table-body.d.ts.map +1 -1
  217. package/dist/ui/data-table-body.js +1 -1
  218. package/dist/ui/data-table-body.js.map +1 -1
  219. package/dist/ui/data-table-bulk-actions.d.ts +2 -1
  220. package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
  221. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  222. package/dist/ui/data-table-card.d.ts +1 -1
  223. package/dist/ui/data-table-card.d.ts.map +1 -1
  224. package/dist/ui/data-table-card.js.map +1 -1
  225. package/dist/ui/data-table-context.d.ts +1 -1
  226. package/dist/ui/data-table-context.d.ts.map +1 -1
  227. package/dist/ui/data-table-context.js.map +1 -1
  228. package/dist/ui/data-table-header.d.ts +2 -1
  229. package/dist/ui/data-table-header.d.ts.map +1 -1
  230. package/dist/ui/data-table-header.js.map +1 -1
  231. package/dist/ui/data-table-pagination.d.ts +2 -1
  232. package/dist/ui/data-table-pagination.d.ts.map +1 -1
  233. package/dist/ui/data-table-pagination.js.map +1 -1
  234. package/dist/ui/data-table-toolbar.d.ts +1 -1
  235. package/dist/ui/data-table-toolbar.d.ts.map +1 -1
  236. package/dist/ui/data-table-toolbar.js.map +1 -1
  237. package/dist/ui/data-table.d.ts +1 -1
  238. package/dist/ui/data-table.d.ts.map +1 -1
  239. package/dist/ui/data-table.js.map +1 -1
  240. package/dist/ui/devalok-grain.d.ts +2 -1
  241. package/dist/ui/devalok-grain.d.ts.map +1 -1
  242. package/dist/ui/devalok-grain.js.map +1 -1
  243. package/dist/ui/dialog.js.map +1 -1
  244. package/dist/ui/dot.js +1 -1
  245. package/dist/ui/dot.js.map +1 -1
  246. package/dist/ui/dropdown-menu.d.ts +1 -1
  247. package/dist/ui/dropdown-menu.js.map +1 -1
  248. package/dist/ui/file-upload.js.map +1 -1
  249. package/dist/ui/form.js.map +1 -1
  250. package/dist/ui/hover-card.js.map +1 -1
  251. package/dist/ui/icon-button.js.map +1 -1
  252. package/dist/ui/icon-context.d.ts +1 -1
  253. package/dist/ui/icon-context.d.ts.map +1 -1
  254. package/dist/ui/icon-context.js.map +1 -1
  255. package/dist/ui/icon-group.js.map +1 -1
  256. package/dist/ui/icon.js.map +1 -1
  257. package/dist/ui/index.js.map +1 -1
  258. package/dist/ui/input-otp.js.map +1 -1
  259. package/dist/ui/input.js.map +1 -1
  260. package/dist/ui/label.js.map +1 -1
  261. package/dist/ui/lib/bottom-sheet.d.ts +1 -1
  262. package/dist/ui/lib/bottom-sheet.d.ts.map +1 -1
  263. package/dist/ui/lib/date-utils.js.map +1 -1
  264. package/dist/ui/lib/link-context.d.ts +1 -1
  265. package/dist/ui/lib/link-context.d.ts.map +1 -1
  266. package/dist/ui/lib/motion.js.map +1 -1
  267. package/dist/ui/lib/utils.js.map +1 -1
  268. package/dist/ui/link.js.map +1 -1
  269. package/dist/ui/menubar.d.ts +1 -1
  270. package/dist/ui/menubar.js.map +1 -1
  271. package/dist/ui/navigation-menu.js +14 -9
  272. package/dist/ui/navigation-menu.js.map +1 -1
  273. package/dist/ui/number-input.d.ts.map +1 -1
  274. package/dist/ui/number-input.js +2 -1
  275. package/dist/ui/number-input.js.map +1 -1
  276. package/dist/ui/pagination.js.map +1 -1
  277. package/dist/ui/progress-ring.js.map +1 -1
  278. package/dist/ui/progress.js.map +1 -1
  279. package/dist/ui/radio.js.map +1 -1
  280. package/dist/ui/search-input.js.map +1 -1
  281. package/dist/ui/segmented-control.js.map +1 -1
  282. package/dist/ui/select.d.ts.map +1 -1
  283. package/dist/ui/select.js +1 -0
  284. package/dist/ui/select.js.map +1 -1
  285. package/dist/ui/separator.js.map +1 -1
  286. package/dist/ui/sheet.js.map +1 -1
  287. package/dist/ui/sidebar.js +1 -1
  288. package/dist/ui/sidebar.js.map +1 -1
  289. package/dist/ui/skeleton.js.map +1 -1
  290. package/dist/ui/slider.js.map +1 -1
  291. package/dist/ui/spinner.js.map +1 -1
  292. package/dist/ui/split-button.js.map +1 -1
  293. package/dist/ui/stack.js.map +1 -1
  294. package/dist/ui/stat-card.js.map +1 -1
  295. package/dist/ui/stat-flash.d.ts +2 -1
  296. package/dist/ui/stat-flash.d.ts.map +1 -1
  297. package/dist/ui/stat-flash.js +1 -1
  298. package/dist/ui/stat-flash.js.map +1 -1
  299. package/dist/ui/stepper.d.ts +1 -1
  300. package/dist/ui/stepper.d.ts.map +1 -1
  301. package/dist/ui/stepper.js +1 -1
  302. package/dist/ui/stepper.js.map +1 -1
  303. package/dist/ui/surface.js.map +1 -1
  304. package/dist/ui/switch.d.ts +1 -1
  305. package/dist/ui/switch.js.map +1 -1
  306. package/dist/ui/table-row-link.js.map +1 -1
  307. package/dist/ui/table.js.map +1 -1
  308. package/dist/ui/tabs.js.map +1 -1
  309. package/dist/ui/text.js.map +1 -1
  310. package/dist/ui/textarea.d.ts.map +1 -1
  311. package/dist/ui/textarea.js +3 -2
  312. package/dist/ui/textarea.js.map +1 -1
  313. package/dist/ui/toast-registry.js.map +1 -1
  314. package/dist/ui/toast.d.ts +4 -4
  315. package/dist/ui/toast.d.ts.map +1 -1
  316. package/dist/ui/toast.js +5 -3
  317. package/dist/ui/toast.js.map +1 -1
  318. package/dist/ui/toaster.js.map +1 -1
  319. package/dist/ui/toggle-group.js.map +1 -1
  320. package/dist/ui/toggle.js.map +1 -1
  321. package/dist/ui/tooltip.js.map +1 -1
  322. package/dist/ui/truncated-text.js.map +1 -1
  323. package/dist/ui/visually-hidden.js.map +1 -1
  324. package/docs/components/ui/data-table.md +2 -2
  325. package/llms.txt +1 -1
  326. package/mcp-manifest.json +3 -3
  327. package/package.json +21 -21
  328. package/skill/SKILL.md +1 -1
  329. package/skill/references/components.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"date-utils.js","names":[],"sources":["../../../src/ui/lib/date-utils.ts"],"sourcesContent":["// @server-safe\n/**\n * Shared relative-time formatting utility.\n */\nexport function formatRelativeTime(dateInput: Date | string): string {\n const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMin = Math.floor(diffMs / 60000)\n\n if (diffMin < 1) return 'Just now'\n if (diffMin < 60) return `${diffMin}m ago`\n\n const diffHour = Math.floor(diffMin / 60)\n if (diffHour < 24) return `${diffHour}h ago`\n\n const diffDay = Math.floor(diffHour / 24)\n if (diffDay < 7) return `${diffDay}d ago`\n\n return date.toLocaleDateString('en-IN', { month: 'short', day: 'numeric' })\n}\n"],"mappings":";AAIA,SAAgB,EAAmB,GAAkC;CACnE,IAAM,IAAO,OAAO,KAAc,WAAW,IAAI,KAAK,EAAU,GAAG,GAE7D,qBADM,IAAI,MAAM,EACH,SAAS,GAAG,EAAK,SAAS,EACvC,IAAU,KAAK,MAAM,IAAS,IAAM;AAE1C,KAAI,IAAU,EAAG,QAAO;AACxB,KAAI,IAAU,GAAI,QAAO,GAAG,EAAQ;CAEpC,IAAM,IAAW,KAAK,MAAM,IAAU,GAAG;AACzC,KAAI,IAAW,GAAI,QAAO,GAAG,EAAS;CAEtC,IAAM,IAAU,KAAK,MAAM,IAAW,GAAG;AAGzC,QAFI,IAAU,IAAU,GAAG,EAAQ,SAE5B,EAAK,mBAAmB,SAAS;EAAE,OAAO;EAAS,KAAK;EAAW,CAAC"}
1
+ {"version":3,"file":"date-utils.js","names":[],"sources":["../../../src/ui/lib/date-utils.ts"],"sourcesContent":["// @server-safe\n/**\n * Shared relative-time formatting utility.\n */\nexport function formatRelativeTime(dateInput: Date | string): string {\n const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMin = Math.floor(diffMs / 60000)\n\n if (diffMin < 1) return 'Just now'\n if (diffMin < 60) return `${diffMin}m ago`\n\n const diffHour = Math.floor(diffMin / 60)\n if (diffHour < 24) return `${diffHour}h ago`\n\n const diffDay = Math.floor(diffHour / 24)\n if (diffDay < 7) return `${diffDay}d ago`\n\n return date.toLocaleDateString('en-IN', { month: 'short', day: 'numeric' })\n}\n"],"mappings":";AAIA,SAAgB,EAAmB,GAAkC;CACnE,IAAM,IAAO,OAAO,KAAc,WAAW,IAAI,KAAK,CAAS,IAAI,GAE7D,qBAAS,IADC,KACD,EAAA,CAAI,QAAQ,IAAI,EAAK,QAAQ,GACtC,IAAU,KAAK,MAAM,IAAS,GAAK;CAEzC,IAAI,IAAU,GAAG,OAAO;CACxB,IAAI,IAAU,IAAI,OAAO,GAAG,EAAQ;CAEpC,IAAM,IAAW,KAAK,MAAM,IAAU,EAAE;CACxC,IAAI,IAAW,IAAI,OAAO,GAAG,EAAS;CAEtC,IAAM,IAAU,KAAK,MAAM,IAAW,EAAE;CAGxC,OAFI,IAAU,IAAU,GAAG,EAAQ,SAE5B,EAAK,mBAAmB,SAAS;EAAE,OAAO;EAAS,KAAK;CAAU,CAAC;AAC5E"}
@@ -7,7 +7,7 @@ export interface LinkProviderProps {
7
7
  component: LinkComponent;
8
8
  children: React.ReactNode;
9
9
  }
10
- export declare function LinkProvider({ component, children, }: LinkProviderProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function LinkProvider({ component, children, }: LinkProviderProps): React.JSX.Element;
11
11
  export declare function useLink(): LinkComponent;
12
12
  export {};
13
13
  //# sourceMappingURL=link-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"link-context.d.ts","sourceRoot":"","sources":["../../../src/ui/lib/link-context.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,KAAK,aAAa,GAAG,KAAK,CAAC,yBAAyB,CAClD,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAC1G,CAAA;AAWD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,aAAa,CAAA;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,QAAQ,GACT,EAAE,iBAAiB,2CAEnB;AAED,wBAAgB,OAAO,kBAEtB"}
1
+ {"version":3,"file":"link-context.d.ts","sourceRoot":"","sources":["../../../src/ui/lib/link-context.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,KAAK,aAAa,GAAG,KAAK,CAAC,yBAAyB,CAClD,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAC1G,CAAA;AAWD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,aAAa,CAAA;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,QAAQ,GACT,EAAE,iBAAiB,qBAEnB;AAED,wBAAgB,OAAO,kBAEtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"motion.js","names":[],"sources":["../../../src/ui/lib/motion.ts"],"sourcesContent":["// @server-safe\nimport type { Transition } from 'framer-motion'\n\n// ── Duration constants (mirrors CSS --duration-* tokens, in seconds for Framer Motion) ──\n\nexport const durations = {\n instant: 0,\n fast01: 0.07,\n fast02: 0.11,\n moderate01: 0.15,\n moderate01b: 0.2,\n moderate02: 0.24,\n slow01: 0.4,\n slow02: 0.7,\n} as const\n\nexport type DurationPreset = keyof typeof durations\n\n// ── Spring configs (spatial: position, scale, size, rotation) ──\n\nexport const springs = {\n /** Micro-interactions: buttons, hover, form inputs */\n snappy: { type: 'spring', stiffness: 500, damping: 30, mass: 0.5 } as Transition,\n /** Dialogs, sheets, panels, navigation */\n smooth: { type: 'spring', stiffness: 300, damping: 30, mass: 0.8 } as Transition,\n /** Toasts, pop-ins, celebration feedback */\n bouncy: { type: 'spring', stiffness: 400, damping: 15, mass: 0.5 } as Transition,\n /** Collapse/expand, accordion, height changes */\n gentle: { type: 'spring', stiffness: 200, damping: 25, mass: 0.8 } as Transition,\n /** AI response blocks — snappier than smooth, feels \"intelligent\" */\n responsive: { type: 'spring', stiffness: 350, damping: 28, mass: 0.6 } as Transition,\n} as const\n\n// ── Tween configs (non-spatial: opacity, color, background) ──\n\nexport const tweens = {\n /** Opacity enter/exit — matches --duration-fast-02 (110ms) */\n fade: { type: 'tween', duration: durations.fast02, ease: 'easeOut' } as Transition,\n /** Hover color, bg, border transitions — matches --duration-fast-01 (70ms) */\n colorShift: { type: 'tween', duration: durations.fast01, ease: 'easeOut' } as Transition,\n /** Greeting fade, hint crossfade — matches --duration-slow-01 (400ms) */\n elegant: { type: 'tween', duration: durations.slow01, ease: [0.25, 0.1, 0.25, 1] } as Transition,\n /** Button/element layout transitions — matches --duration-moderate-01b (200ms) */\n layout: { type: 'tween', duration: durations.moderate01b, ease: [0.25, 0.1, 0.25, 1] } as Transition,\n} as const\n\n// ── Stagger helper ──\n\nexport function stagger(delay = 0.04) {\n return {\n visible: { transition: { staggerChildren: delay } },\n hidden: { transition: { staggerChildren: delay } },\n }\n}\n\n// ── Reduced motion helper ──\n\nexport function withReducedMotion(transition: Transition): Transition {\n return { ...transition, duration: 0 }\n}\n\n// ── Preset types ──\n\nexport type SpringPreset = keyof typeof springs\nexport type TweenPreset = keyof typeof tweens\n\n// ── React ↔ Framer Motion event-handler compatibility ──\n// Framer Motion redefines several React event handlers (onDrag*, onAnimationStart,\n// etc.) with different signatures. When spreading React HTML props onto a motion.*\n// element, a type-level cast is needed to bridge the mismatch. At runtime the\n// handlers are identical DOM events — only the TS types conflict.\n\n/**\n * Cast React HTML props so they can be safely spread onto a Framer Motion\n * `motion.*` element without type conflicts on shared event-handler names.\n *\n * Returns `Record<string, unknown>` rather than `any` to keep the spread safe\n * while avoiding a full `any` leak. A truly generic passthrough (`T`) would\n * re-surface the exact type conflicts this function exists to erase, because\n * the React event-handler types on `T` still clash with Framer Motion's\n * overloaded signatures. `Record<string, unknown>` is the narrowest type that\n * satisfies both sides.\n */\nexport function motionProps<T extends Record<string, unknown>>(props: T): Record<string, unknown> {\n return props\n}\n"],"mappings":";AAKA,IAAa,IAAY;CACvB,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,QAAQ;CACR,QAAQ;CACT,EAMY,IAAU;CAErB,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;EAAK;CAElE,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;EAAK;CAElE,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;EAAK;CAElE,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;EAAK;CAElE,YAAY;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;EAAK;CACvE,EAIY,IAAS;CAEpB,MAAM;EAAE,MAAM;EAAS,UAAU,EAAU;EAAQ,MAAM;EAAW;CAEpE,YAAY;EAAE,MAAM;EAAS,UAAU,EAAU;EAAQ,MAAM;EAAW;CAE1E,SAAS;EAAE,MAAM;EAAS,UAAU,EAAU;EAAQ,MAAM;GAAC;GAAM;GAAK;GAAM;GAAE;EAAE;CAElF,QAAQ;EAAE,MAAM;EAAS,UAAU,EAAU;EAAa,MAAM;GAAC;GAAM;GAAK;GAAM;GAAE;EAAE;CACvF;AAID,SAAgB,EAAQ,IAAQ,KAAM;AACpC,QAAO;EACL,SAAS,EAAE,YAAY,EAAE,iBAAiB,GAAO,EAAE;EACnD,QAAQ,EAAE,YAAY,EAAE,iBAAiB,GAAO,EAAE;EACnD;;AAKH,SAAgB,EAAkB,GAAoC;AACpE,QAAO;EAAE,GAAG;EAAY,UAAU;EAAG;;AAyBvC,SAAgB,EAA+C,GAAmC;AAChG,QAAO"}
1
+ {"version":3,"file":"motion.js","names":[],"sources":["../../../src/ui/lib/motion.ts"],"sourcesContent":["// @server-safe\nimport type { Transition } from 'framer-motion'\n\n// ── Duration constants (mirrors CSS --duration-* tokens, in seconds for Framer Motion) ──\n\nexport const durations = {\n instant: 0,\n fast01: 0.07,\n fast02: 0.11,\n moderate01: 0.15,\n moderate01b: 0.2,\n moderate02: 0.24,\n slow01: 0.4,\n slow02: 0.7,\n} as const\n\nexport type DurationPreset = keyof typeof durations\n\n// ── Spring configs (spatial: position, scale, size, rotation) ──\n\nexport const springs = {\n /** Micro-interactions: buttons, hover, form inputs */\n snappy: { type: 'spring', stiffness: 500, damping: 30, mass: 0.5 } as Transition,\n /** Dialogs, sheets, panels, navigation */\n smooth: { type: 'spring', stiffness: 300, damping: 30, mass: 0.8 } as Transition,\n /** Toasts, pop-ins, celebration feedback */\n bouncy: { type: 'spring', stiffness: 400, damping: 15, mass: 0.5 } as Transition,\n /** Collapse/expand, accordion, height changes */\n gentle: { type: 'spring', stiffness: 200, damping: 25, mass: 0.8 } as Transition,\n /** AI response blocks — snappier than smooth, feels \"intelligent\" */\n responsive: { type: 'spring', stiffness: 350, damping: 28, mass: 0.6 } as Transition,\n} as const\n\n// ── Tween configs (non-spatial: opacity, color, background) ──\n\nexport const tweens = {\n /** Opacity enter/exit — matches --duration-fast-02 (110ms) */\n fade: { type: 'tween', duration: durations.fast02, ease: 'easeOut' } as Transition,\n /** Hover color, bg, border transitions — matches --duration-fast-01 (70ms) */\n colorShift: { type: 'tween', duration: durations.fast01, ease: 'easeOut' } as Transition,\n /** Greeting fade, hint crossfade — matches --duration-slow-01 (400ms) */\n elegant: { type: 'tween', duration: durations.slow01, ease: [0.25, 0.1, 0.25, 1] } as Transition,\n /** Button/element layout transitions — matches --duration-moderate-01b (200ms) */\n layout: { type: 'tween', duration: durations.moderate01b, ease: [0.25, 0.1, 0.25, 1] } as Transition,\n} as const\n\n// ── Stagger helper ──\n\nexport function stagger(delay = 0.04) {\n return {\n visible: { transition: { staggerChildren: delay } },\n hidden: { transition: { staggerChildren: delay } },\n }\n}\n\n// ── Reduced motion helper ──\n\nexport function withReducedMotion(transition: Transition): Transition {\n return { ...transition, duration: 0 }\n}\n\n// ── Preset types ──\n\nexport type SpringPreset = keyof typeof springs\nexport type TweenPreset = keyof typeof tweens\n\n// ── React ↔ Framer Motion event-handler compatibility ──\n// Framer Motion redefines several React event handlers (onDrag*, onAnimationStart,\n// etc.) with different signatures. When spreading React HTML props onto a motion.*\n// element, a type-level cast is needed to bridge the mismatch. At runtime the\n// handlers are identical DOM events — only the TS types conflict.\n\n/**\n * Cast React HTML props so they can be safely spread onto a Framer Motion\n * `motion.*` element without type conflicts on shared event-handler names.\n *\n * Returns `Record<string, unknown>` rather than `any` to keep the spread safe\n * while avoiding a full `any` leak. A truly generic passthrough (`T`) would\n * re-surface the exact type conflicts this function exists to erase, because\n * the React event-handler types on `T` still clash with Framer Motion's\n * overloaded signatures. `Record<string, unknown>` is the narrowest type that\n * satisfies both sides.\n */\nexport function motionProps<T extends Record<string, unknown>>(props: T): Record<string, unknown> {\n return props\n}\n"],"mappings":";AAKA,IAAa,IAAY;CACvB,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,QAAQ;CACR,QAAQ;AACV,GAMa,IAAU;CAErB,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;CAAI;CAEjE,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;CAAI;CAEjE,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;CAAI;CAEjE,QAAQ;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;CAAI;CAEjE,YAAY;EAAE,MAAM;EAAU,WAAW;EAAK,SAAS;EAAI,MAAM;CAAI;AACvE,GAIa,IAAS;CAEpB,MAAM;EAAE,MAAM;EAAS,UAAU,EAAU;EAAQ,MAAM;CAAU;CAEnE,YAAY;EAAE,MAAM;EAAS,UAAU,EAAU;EAAQ,MAAM;CAAU;CAEzE,SAAS;EAAE,MAAM;EAAS,UAAU,EAAU;EAAQ,MAAM;GAAC;GAAM;GAAK;GAAM;EAAC;CAAE;CAEjF,QAAQ;EAAE,MAAM;EAAS,UAAU,EAAU;EAAa,MAAM;GAAC;GAAM;GAAK;GAAM;EAAC;CAAE;AACvF;AAIA,SAAgB,EAAQ,IAAQ,KAAM;CACpC,OAAO;EACL,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAM,EAAE;EAClD,QAAQ,EAAE,YAAY,EAAE,iBAAiB,EAAM,EAAE;CACnD;AACF;AAIA,SAAgB,EAAkB,GAAoC;CACpE,OAAO;EAAE,GAAG;EAAY,UAAU;CAAE;AACtC;AAwBA,SAAgB,EAA+C,GAAmC;CAChG,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../../../src/ui/lib/utils.ts"],"sourcesContent":["// @server-safe\nimport { type ClassValue,clsx } from 'clsx'\nimport { extendTailwindMerge } from 'tailwind-merge'\n\nconst twMerge = extendTailwindMerge({\n extend: {\n theme: {\n spacing: ['ds-01', 'ds-02', 'ds-02b', 'ds-03', 'ds-04', 'ds-05', 'ds-05b', 'ds-06', 'ds-06b', 'ds-07', 'ds-08', 'ds-09', 'ds-10', 'ds-11', 'ds-12', 'ds-13'],\n },\n classGroups: {\n 'font-size': [{ 'text-ds': ['xs', 'sm', 'md', 'base', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl'] }],\n },\n },\n})\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":";;AAIA,IAAM,IAAU,EAAoB,EAClC,QAAQ;CACN,OAAO,EACL,SAAS;EAAC;EAAS;EAAS;EAAU;EAAS;EAAS;EAAS;EAAU;EAAS;EAAU;EAAS;EAAS;EAAS;EAAS;EAAS;EAAS;EAAQ,EAC7J;CACD,aAAa,EACX,aAAa,CAAC,EAAE,WAAW;EAAC;EAAM;EAAM;EAAM;EAAQ;EAAM;EAAM;EAAO;EAAO;EAAO;EAAO;EAAM,EAAE,CAAC,EACxG;CACF,EACF,CAAC;AAEF,SAAgB,EAAG,GAAG,GAAsB;AAC1C,QAAO,EAAQ,EAAK,EAAO,CAAC"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../../src/ui/lib/utils.ts"],"sourcesContent":["// @server-safe\nimport { type ClassValue,clsx } from 'clsx'\nimport { extendTailwindMerge } from 'tailwind-merge'\n\nconst twMerge = extendTailwindMerge({\n extend: {\n theme: {\n spacing: ['ds-01', 'ds-02', 'ds-02b', 'ds-03', 'ds-04', 'ds-05', 'ds-05b', 'ds-06', 'ds-06b', 'ds-07', 'ds-08', 'ds-09', 'ds-10', 'ds-11', 'ds-12', 'ds-13'],\n },\n classGroups: {\n 'font-size': [{ 'text-ds': ['xs', 'sm', 'md', 'base', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl'] }],\n },\n },\n})\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":";;AAIA,IAAM,IAAU,EAAoB,EAClC,QAAQ;CACN,OAAO,EACL,SAAS;EAAC;EAAS;EAAS;EAAU;EAAS;EAAS;EAAS;EAAU;EAAS;EAAU;EAAS;EAAS;EAAS;EAAS;EAAS;EAAS;CAAO,EAC7J;CACA,aAAa,EACX,aAAa,CAAC,EAAE,WAAW;EAAC;EAAM;EAAM;EAAM;EAAQ;EAAM;EAAM;EAAO;EAAO;EAAO;EAAO;CAAK,EAAE,CAAC,EACxG;AACF,EACF,CAAC;AAED,SAAgB,EAAG,GAAG,GAAsB;CAC1C,OAAO,EAAQ,EAAK,CAAM,CAAC;AAC7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","names":[],"sources":["../../src/ui/link.tsx"],"sourcesContent":["'use client'\n\nimport { Slot } from '@primitives/react-slot'\nimport * as React from 'react'\n\nimport { cn } from './lib/utils'\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n inline?: boolean\n asChild?: boolean\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, inline = true, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'a'\n\n return (\n <Comp\n ref={ref}\n className={cn(\n 'text-accent-11 underline decoration-transparent hover:decoration-current underline-offset-2',\n 'hover:text-accent-12 active:opacity-80 transition-[color,text-decoration-color,opacity] duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 rounded-control-inner',\n inline ? 'inline' : 'block',\n className,\n )}\n {...props}\n />\n )\n },\n)\nLink.displayName = 'Link'\n\nexport { Link }\n"],"mappings":";;;;;;AAYA,IAAM,IAAO,EAAM,YAChB,EAAE,cAAW,YAAS,IAAM,aAAU,IAAO,GAAG,KAAS,MAItD,kBAHW,IAAU,IAAO,KAG5B;CACO;CACL,WAAW,EACT,+FACA,qIACA,mIACA,IAAS,WAAW,SACpB,EACD;CACD,GAAI;CACJ,CAAA,CAGP;AACD,EAAK,cAAc"}
1
+ {"version":3,"file":"link.js","names":[],"sources":["../../src/ui/link.tsx"],"sourcesContent":["'use client'\n\nimport { Slot } from '@primitives/react-slot'\nimport * as React from 'react'\n\nimport { cn } from './lib/utils'\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n inline?: boolean\n asChild?: boolean\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, inline = true, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'a'\n\n return (\n <Comp\n ref={ref}\n className={cn(\n 'text-accent-11 underline decoration-transparent hover:decoration-current underline-offset-2',\n 'hover:text-accent-12 active:opacity-80 transition-[color,text-decoration-color,opacity] duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 rounded-control-inner',\n inline ? 'inline' : 'block',\n className,\n )}\n {...props}\n />\n )\n },\n)\nLink.displayName = 'Link'\n\nexport { Link }\n"],"mappings":";;;;;;AAYA,IAAM,IAAO,EAAM,YAChB,EAAE,cAAW,YAAS,IAAM,aAAU,IAAO,GAAG,KAAS,MAItD,kBAHW,IAAU,IAAO,KAG5B;CACO;CACL,WAAW,EACT,+FACA,qIACA,mIACA,IAAS,WAAW,SACpB,CACF;CACA,GAAI;AACL,CAAA,CAGP;AACA,EAAK,cAAc"}
@@ -23,7 +23,7 @@ declare const MenubarLabel: React.ForwardRefExoticComponent<Omit<MenubarPrimitiv
23
23
  } & React.RefAttributes<HTMLDivElement>>;
24
24
  declare const MenubarSeparator: React.ForwardRefExoticComponent<Omit<MenubarPrimitive.MenubarSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
25
25
  declare const MenubarShortcut: {
26
- ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): import("react/jsx-runtime").JSX.Element;
26
+ ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element;
27
27
  displayName: string;
28
28
  };
29
29
  export type MenubarContentProps = React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>;
@@ -1 +1 @@
1
- {"version":3,"file":"menubar.js","names":[],"sources":["../../src/ui/menubar.tsx"],"sourcesContent":["'use client'\n\nimport * as MenubarPrimitive from '@primitives/react-menubar'\nimport { IconCheck, IconChevronRight, IconCircle } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Internal contexts to thread open state ──\n\nconst MenubarSubOpenContext = React.createContext(false)\n\nconst MenubarMenu: React.FC<React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Menu>> = (props) => {\n // MenubarPrimitive.Menu doesn't expose open/onOpenChange directly.\n // We derive open from data-state on the trigger via a callback ref approach,\n // but the cleanest way is to use the Menubar root's value prop.\n // Since MenubarMenu doesn't have open/onOpenChange, we track via a wrapper\n // that observes the trigger's data-state.\n //\n // Alternative: MenubarPrimitive.Menu has a `value` that the root uses.\n // We'll use a simpler approach: track open via content mount state.\n return <MenubarPrimitive.Menu {...props} />\n}\nMenubarMenu.displayName = 'MenubarMenu'\n\n// For Menubar, the Menu doesn't expose open/onOpenChange. Instead, we'll use a\n// different approach: wrap Content to use a local presence state based on data-state.\n// We create a wrapper component that tracks whether content should be shown.\n\nconst MenubarGroup: typeof MenubarPrimitive.Group = MenubarPrimitive.Group\n\nconst MenubarPortal: typeof MenubarPrimitive.Portal = MenubarPrimitive.Portal\n\nconst MenubarSub: React.FC<React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Sub>> = ({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n ...props\n}) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = controlledOpen !== undefined\n const open = isControlled ? controlledOpen : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (value: boolean) => {\n if (!isControlled) setUncontrolledOpen(value)\n onOpenChange?.(value)\n },\n [isControlled, onOpenChange],\n )\n\n return (\n <MenubarSubOpenContext.Provider value={open}>\n <MenubarPrimitive.Sub open={open} onOpenChange={handleOpenChange} {...props} />\n </MenubarSubOpenContext.Provider>\n )\n}\nMenubarSub.displayName = 'MenubarSub'\n\nconst MenubarRadioGroup: typeof MenubarPrimitive.RadioGroup =\n MenubarPrimitive.RadioGroup\n\nconst Menubar = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Root\n ref={ref}\n className={cn(\n 'flex h-ds-sm-plus items-center space-x-ds-02 rounded-overlay bg-surface-overlay p-ds-02 shadow-raised',\n className,\n )}\n {...props}\n />\n))\nMenubar.displayName = MenubarPrimitive.Root.displayName\n\nconst MenubarTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center rounded-control px-ds-04 py-ds-02 text-ds-md font-medium outline-hidden transition-colors hover:bg-surface-raised-hover focus-visible:bg-surface-raised-hover data-[state=open]:bg-surface-raised-hover',\n className,\n )}\n {...props}\n />\n))\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenubarPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center gap-ds-03 rounded-control px-ds-03 py-ds-02b text-ds-md outline-hidden focus:bg-surface-raised data-[state=open]:bg-surface-raised [&_svg]:pointer-events-none [&_svg]:h-ico-sm [&_svg]:w-ico-sm [&_svg]:shrink-0',\n inset && 'pl-ds-07',\n className,\n )}\n {...props}\n >\n <span className=\"min-w-0 truncate\">{children}</span>\n <Icon icon={IconChevronRight} size=\"sm\" className=\"ml-auto shrink-0\" />\n </MenubarPrimitive.SubTrigger>\n))\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName\n\nconst MenubarSubContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\n>(({ className, children, ...props }, ref) => {\n const open = React.useContext(MenubarSubOpenContext)\n\n return (\n <AnimatePresence>\n {open && (\n <MenubarPrimitive.SubContent\n ref={ref}\n forceMount\n asChild\n {...props}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-popover min-w-[8rem] overflow-hidden rounded-overlay bg-surface-overlay p-ds-02 text-surface-fg shadow-floating',\n className,\n )}\n >\n {children}\n </motion.div>\n </MenubarPrimitive.SubContent>\n )}\n </AnimatePresence>\n )\n})\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName\n\n// For MenubarContent, since MenubarMenu doesn't expose open/onOpenChange,\n// we use a wrapper that reads presence from a callback approach.\n// The cleanest solution: use a local state tracker via onCloseAutoFocus/onOpenAutoFocus\n// or simply keep CSS-free and let Radix handle mount/unmount naturally.\n//\n// Since Menubar menus are opened by the Menubar root (which tracks which menu value is open),\n// and MenubarPrimitive.Content already handles mount/unmount, we can use a ref-based approach\n// to detect the data-state attribute. However, the simplest reliable approach is to use\n// a wrapper that detects mount via useEffect.\n\n// MenubarContent uses CSS data-state animations instead of framer-motion because\n// MenubarPrimitive.Menu doesn't expose open/onOpenChange, making AnimatePresence\n// impossible to wire up for exit animations. The popover-in/popover-out keyframes\n// are defined in the tailwind preset and triggered by Radix's data-state attribute.\nconst MenubarContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\n>(\n (\n { className, align = 'start', alignOffset = -4, sideOffset = 8, children, ...props },\n ref,\n ) => (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n ref={ref}\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n 'z-popover min-w-[12rem] rounded-overlay bg-surface-overlay p-ds-02 text-surface-fg shadow-floating',\n 'data-[state=open]:animate-popover-in data-[state=closed]:animate-popover-out',\n className,\n )}\n {...props}\n >\n {children}\n </MenubarPrimitive.Content>\n </MenubarPrimitive.Portal>\n ),\n)\nMenubarContent.displayName = MenubarPrimitive.Content.displayName\n\nconst MenubarItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center gap-ds-03 rounded-control px-ds-03 py-ds-02b text-ds-md outline-hidden transition-colors focus:bg-surface-raised focus:text-surface-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-action-disabled [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0',\n inset && 'pl-ds-07',\n className,\n )}\n {...props}\n />\n))\nMenubarItem.displayName = MenubarPrimitive.Item.displayName\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <MenubarPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-control py-ds-02b pl-ds-07 pr-ds-03 text-ds-md outline-hidden transition-colors focus:bg-surface-raised focus:text-surface-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-action-disabled',\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-ds-03 flex h-ico-sm w-ico-sm items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Icon icon={IconCheck} size=\"sm\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n))\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName\n\nconst MenubarRadioItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenubarPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-control py-ds-02b pl-ds-07 pr-ds-03 text-ds-md outline-hidden transition-colors focus:bg-surface-raised focus:text-surface-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-action-disabled',\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-ds-03 flex h-ico-sm w-ico-sm items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <IconCircle className=\"h-2 w-2 fill-current\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n <span className=\"min-w-0 truncate\">{children}</span>\n </MenubarPrimitive.RadioItem>\n))\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName\n\nconst MenubarLabel = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Label\n ref={ref}\n className={cn(\n 'px-ds-03 py-ds-02b text-ds-md font-semibold',\n inset && 'pl-ds-07',\n className,\n )}\n {...props}\n />\n))\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName\n\nconst MenubarSeparator = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Separator\n ref={ref}\n className={cn('-mx-ds-01 my-ds-02 h-px bg-surface-border', className)}\n {...props}\n />\n))\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName\n\nconst MenubarShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n 'ml-auto text-ds-sm text-surface-fg-subtle',\n className,\n )}\n {...props}\n />\n )\n}\nMenubarShortcut.displayName = 'MenubarShortcut'\n\nexport type MenubarContentProps = React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\nexport type MenubarItemProps = React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item>\n\nexport {\n Menubar,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarMenu,\n MenubarPortal,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"menubar.js","names":[],"sources":["../../src/ui/menubar.tsx"],"sourcesContent":["'use client'\n\nimport * as MenubarPrimitive from '@primitives/react-menubar'\nimport { IconCheck, IconChevronRight, IconCircle } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Internal contexts to thread open state ──\n\nconst MenubarSubOpenContext = React.createContext(false)\n\nconst MenubarMenu: React.FC<React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Menu>> = (props) => {\n // MenubarPrimitive.Menu doesn't expose open/onOpenChange directly.\n // We derive open from data-state on the trigger via a callback ref approach,\n // but the cleanest way is to use the Menubar root's value prop.\n // Since MenubarMenu doesn't have open/onOpenChange, we track via a wrapper\n // that observes the trigger's data-state.\n //\n // Alternative: MenubarPrimitive.Menu has a `value` that the root uses.\n // We'll use a simpler approach: track open via content mount state.\n return <MenubarPrimitive.Menu {...props} />\n}\nMenubarMenu.displayName = 'MenubarMenu'\n\n// For Menubar, the Menu doesn't expose open/onOpenChange. Instead, we'll use a\n// different approach: wrap Content to use a local presence state based on data-state.\n// We create a wrapper component that tracks whether content should be shown.\n\nconst MenubarGroup: typeof MenubarPrimitive.Group = MenubarPrimitive.Group\n\nconst MenubarPortal: typeof MenubarPrimitive.Portal = MenubarPrimitive.Portal\n\nconst MenubarSub: React.FC<React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Sub>> = ({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n ...props\n}) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = controlledOpen !== undefined\n const open = isControlled ? controlledOpen : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (value: boolean) => {\n if (!isControlled) setUncontrolledOpen(value)\n onOpenChange?.(value)\n },\n [isControlled, onOpenChange],\n )\n\n return (\n <MenubarSubOpenContext.Provider value={open}>\n <MenubarPrimitive.Sub open={open} onOpenChange={handleOpenChange} {...props} />\n </MenubarSubOpenContext.Provider>\n )\n}\nMenubarSub.displayName = 'MenubarSub'\n\nconst MenubarRadioGroup: typeof MenubarPrimitive.RadioGroup =\n MenubarPrimitive.RadioGroup\n\nconst Menubar = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Root\n ref={ref}\n className={cn(\n 'flex h-ds-sm-plus items-center space-x-ds-02 rounded-overlay bg-surface-overlay p-ds-02 shadow-raised',\n className,\n )}\n {...props}\n />\n))\nMenubar.displayName = MenubarPrimitive.Root.displayName\n\nconst MenubarTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center rounded-control px-ds-04 py-ds-02 text-ds-md font-medium outline-hidden transition-colors hover:bg-surface-raised-hover focus-visible:bg-surface-raised-hover data-[state=open]:bg-surface-raised-hover',\n className,\n )}\n {...props}\n />\n))\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenubarPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center gap-ds-03 rounded-control px-ds-03 py-ds-02b text-ds-md outline-hidden focus:bg-surface-raised data-[state=open]:bg-surface-raised [&_svg]:pointer-events-none [&_svg]:h-ico-sm [&_svg]:w-ico-sm [&_svg]:shrink-0',\n inset && 'pl-ds-07',\n className,\n )}\n {...props}\n >\n <span className=\"min-w-0 truncate\">{children}</span>\n <Icon icon={IconChevronRight} size=\"sm\" className=\"ml-auto shrink-0\" />\n </MenubarPrimitive.SubTrigger>\n))\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName\n\nconst MenubarSubContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\n>(({ className, children, ...props }, ref) => {\n const open = React.useContext(MenubarSubOpenContext)\n\n return (\n <AnimatePresence>\n {open && (\n <MenubarPrimitive.SubContent\n ref={ref}\n forceMount\n asChild\n {...props}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-popover min-w-[8rem] overflow-hidden rounded-overlay bg-surface-overlay p-ds-02 text-surface-fg shadow-floating',\n className,\n )}\n >\n {children}\n </motion.div>\n </MenubarPrimitive.SubContent>\n )}\n </AnimatePresence>\n )\n})\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName\n\n// For MenubarContent, since MenubarMenu doesn't expose open/onOpenChange,\n// we use a wrapper that reads presence from a callback approach.\n// The cleanest solution: use a local state tracker via onCloseAutoFocus/onOpenAutoFocus\n// or simply keep CSS-free and let Radix handle mount/unmount naturally.\n//\n// Since Menubar menus are opened by the Menubar root (which tracks which menu value is open),\n// and MenubarPrimitive.Content already handles mount/unmount, we can use a ref-based approach\n// to detect the data-state attribute. However, the simplest reliable approach is to use\n// a wrapper that detects mount via useEffect.\n\n// MenubarContent uses CSS data-state animations instead of framer-motion because\n// MenubarPrimitive.Menu doesn't expose open/onOpenChange, making AnimatePresence\n// impossible to wire up for exit animations. The popover-in/popover-out keyframes\n// are defined in the tailwind preset and triggered by Radix's data-state attribute.\nconst MenubarContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\n>(\n (\n { className, align = 'start', alignOffset = -4, sideOffset = 8, children, ...props },\n ref,\n ) => (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n ref={ref}\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n 'z-popover min-w-[12rem] rounded-overlay bg-surface-overlay p-ds-02 text-surface-fg shadow-floating',\n 'data-[state=open]:animate-popover-in data-[state=closed]:animate-popover-out',\n className,\n )}\n {...props}\n >\n {children}\n </MenubarPrimitive.Content>\n </MenubarPrimitive.Portal>\n ),\n)\nMenubarContent.displayName = MenubarPrimitive.Content.displayName\n\nconst MenubarItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center gap-ds-03 rounded-control px-ds-03 py-ds-02b text-ds-md outline-hidden transition-colors focus:bg-surface-raised focus:text-surface-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-action-disabled [&>svg]:h-ico-sm [&>svg]:w-ico-sm [&>svg]:shrink-0',\n inset && 'pl-ds-07',\n className,\n )}\n {...props}\n />\n))\nMenubarItem.displayName = MenubarPrimitive.Item.displayName\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <MenubarPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-control py-ds-02b pl-ds-07 pr-ds-03 text-ds-md outline-hidden transition-colors focus:bg-surface-raised focus:text-surface-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-action-disabled',\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-ds-03 flex h-ico-sm w-ico-sm items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Icon icon={IconCheck} size=\"sm\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n))\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName\n\nconst MenubarRadioItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenubarPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-control py-ds-02b pl-ds-07 pr-ds-03 text-ds-md outline-hidden transition-colors focus:bg-surface-raised focus:text-surface-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-action-disabled',\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-ds-03 flex h-ico-sm w-ico-sm items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <IconCircle className=\"h-2 w-2 fill-current\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n <span className=\"min-w-0 truncate\">{children}</span>\n </MenubarPrimitive.RadioItem>\n))\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName\n\nconst MenubarLabel = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Label\n ref={ref}\n className={cn(\n 'px-ds-03 py-ds-02b text-ds-md font-semibold',\n inset && 'pl-ds-07',\n className,\n )}\n {...props}\n />\n))\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName\n\nconst MenubarSeparator = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Separator\n ref={ref}\n className={cn('-mx-ds-01 my-ds-02 h-px bg-surface-border', className)}\n {...props}\n />\n))\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName\n\nconst MenubarShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n 'ml-auto text-ds-sm text-surface-fg-subtle',\n className,\n )}\n {...props}\n />\n )\n}\nMenubarShortcut.displayName = 'MenubarShortcut'\n\nexport type MenubarContentProps = React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\nexport type MenubarItemProps = React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item>\n\nexport {\n Menubar,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarMenu,\n MenubarPortal,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n}\n"],"mappings":"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"}
@@ -67,7 +67,10 @@ var x = {
67
67
  let t = e.getAttribute("data-motion");
68
68
  t && s(t);
69
69
  let n = new MutationObserver((t) => {
70
- for (let n of t) n.attributeName === "data-motion" && s(e.getAttribute("data-motion"));
70
+ for (let n of t) if (n.attributeName === "data-motion") {
71
+ let t = e.getAttribute("data-motion");
72
+ s(t);
73
+ }
71
74
  });
72
75
  return n.observe(e, {
73
76
  attributes: !0,
@@ -102,14 +105,15 @@ var C = r, w = f.forwardRef(({ className: e, ...t }, n) => {
102
105
  return f.useEffect(() => {
103
106
  let e = r.current;
104
107
  if (!e) return;
105
- o(e.getAttribute("data-state") === "open");
106
- let t = new MutationObserver((t) => {
108
+ let t = e.getAttribute("data-state");
109
+ o(t === "open");
110
+ let n = new MutationObserver((t) => {
107
111
  for (let n of t) n.attributeName === "data-state" && o(e.getAttribute("data-state") === "open");
108
112
  });
109
- return t.observe(e, {
113
+ return n.observe(e, {
110
114
  attributes: !0,
111
115
  attributeFilter: ["data-state"]
112
- }), () => t.disconnect();
116
+ }), () => n.disconnect();
113
117
  }, []), /* @__PURE__ */ m("div", {
114
118
  className: u("absolute left-0 top-full flex justify-center"),
115
119
  children: [/* @__PURE__ */ p(s, {
@@ -142,14 +146,15 @@ var T = f.forwardRef(({ className: e, ...n }, r) => {
142
146
  return f.useEffect(() => {
143
147
  let e = i.current;
144
148
  if (!e) return;
145
- s(e.getAttribute("data-state") === "visible");
146
- let t = new MutationObserver((t) => {
149
+ let t = e.getAttribute("data-state");
150
+ s(t === "visible");
151
+ let n = new MutationObserver((t) => {
147
152
  for (let n of t) n.attributeName === "data-state" && s(e.getAttribute("data-state") === "visible");
148
153
  });
149
- return t.observe(e, {
154
+ return n.observe(e, {
150
155
  attributes: !0,
151
156
  attributeFilter: ["data-state"]
152
- }), () => t.disconnect();
157
+ }), () => n.disconnect();
153
158
  }, []), /* @__PURE__ */ p(t, {
154
159
  ref: a,
155
160
  className: u("top-full z-base flex h-ds-02b items-end justify-center overflow-hidden", e),
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-menu.js","names":[],"sources":["../../src/ui/navigation-menu.tsx"],"sourcesContent":["'use client'\n\nimport * as NavigationMenuPrimitive from '@primitives/react-navigation-menu'\nimport { IconChevronDown } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst NavigationMenu = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <NavigationMenuPrimitive.Root\n ref={ref}\n className={cn(\n 'relative z-raised flex max-w-max flex-1 items-center justify-center',\n className,\n )}\n {...props}\n >\n {children}\n <NavigationMenuViewport />\n </NavigationMenuPrimitive.Root>\n))\nNavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName\n\nconst NavigationMenuList = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.List\n ref={ref}\n className={cn(\n 'group flex flex-1 list-none items-center justify-center space-x-ds-02',\n className,\n )}\n {...props}\n />\n))\nNavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName\n\nconst NavigationMenuItem = NavigationMenuPrimitive.Item\n\nconst NavigationMenuTrigger = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group inline-flex h-ds-sm-plus w-max items-center justify-center rounded-control bg-transparent px-ds-05 py-ds-03 text-ds-md font-medium transition-colors hover:bg-surface-raised-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 disabled:pointer-events-none disabled:opacity-action-disabled',\n className,\n )}\n {...props}\n >\n {children}{' '}\n <Icon icon={IconChevronDown} size=\"sm\" className=\"relative top-[1px] ml-ds-02 transition-transform duration-moderate-02 group-data-[state=open]:rotate-180\" />\n </NavigationMenuPrimitive.Trigger>\n))\nNavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName\n\n// ── NavigationMenuContent — directional slide using data-motion ──\n\nconst contentSlideVariants = {\n 'from-start': { x: '-13rem', opacity: 0 },\n 'from-end': { x: '13rem', opacity: 0 },\n 'to-start': { x: '-13rem', opacity: 0 },\n 'to-end': { x: '13rem', opacity: 0 },\n center: { x: 0, opacity: 1 },\n} as const\n\nconst NavigationMenuContent = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>\n>(({ className, ...props }, ref) => {\n const innerRef = React.useRef<HTMLDivElement>(null)\n const composedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n (innerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n },\n [ref],\n )\n\n const [motionDir, setMotionDir] = React.useState<string | null>(null)\n\n // Observe data-motion attribute changes from Radix\n React.useEffect(() => {\n const el = innerRef.current\n if (!el) return\n\n // Read initial value\n const initial = el.getAttribute('data-motion')\n if (initial) setMotionDir(initial)\n\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.attributeName === 'data-motion') {\n const val = el.getAttribute('data-motion')\n setMotionDir(val)\n }\n }\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-motion'] })\n return () => observer.disconnect()\n }, [])\n\n const initial = motionDir && motionDir.startsWith('from-')\n ? contentSlideVariants[motionDir as keyof typeof contentSlideVariants]\n : motionDir && motionDir.startsWith('to-')\n ? contentSlideVariants.center\n : { x: 0, opacity: 0 }\n\n const animate = motionDir && motionDir.startsWith('from-')\n ? contentSlideVariants.center\n : motionDir && motionDir.startsWith('to-')\n ? contentSlideVariants[motionDir as keyof typeof contentSlideVariants]\n : contentSlideVariants.center\n\n return (\n <NavigationMenuPrimitive.Content\n ref={composedRef}\n className={cn(\n 'left-0 top-0 w-full md:absolute md:w-auto',\n className,\n )}\n {...props}\n >\n <motion.div\n key={motionDir}\n initial={initial}\n animate={animate}\n transition={{ ...springs.smooth, opacity: tweens.fade }}\n className=\"w-full\"\n >\n {props.children}\n </motion.div>\n </NavigationMenuPrimitive.Content>\n )\n})\nNavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName\n\nconst NavigationMenuLink = NavigationMenuPrimitive.Link\n\n// ── NavigationMenuViewport — scale + fade with layout for size changes ──\n\nconst NavigationMenuViewport = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>\n>(({ className, ...props }, ref) => {\n const innerRef = React.useRef<HTMLDivElement>(null)\n const composedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n (innerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n },\n [ref],\n )\n\n const [isOpen, setIsOpen] = React.useState(false)\n\n React.useEffect(() => {\n const el = innerRef.current\n if (!el) return\n\n const initial = el.getAttribute('data-state')\n setIsOpen(initial === 'open')\n\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.attributeName === 'data-state') {\n setIsOpen(el.getAttribute('data-state') === 'open')\n }\n }\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n return () => observer.disconnect()\n }, [])\n\n return (\n <div className={cn('absolute left-0 top-full flex justify-center')}>\n <NavigationMenuPrimitive.Viewport\n className={cn(\n 'origin-top-center relative mt-ds-02b h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-overlay bg-surface-overlay shadow-floating md:w-[var(--radix-navigation-menu-viewport-width)]',\n className,\n )}\n ref={composedRef}\n {...props}\n />\n {/* Overlay motion element for scale+fade animation */}\n <motion.div\n aria-hidden\n className=\"absolute inset-0 pointer-events-none\"\n initial={false}\n animate={isOpen ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.95 }}\n transition={{ ...springs.smooth, opacity: tweens.fade }}\n />\n </div>\n )\n})\nNavigationMenuViewport.displayName =\n NavigationMenuPrimitive.Viewport.displayName\n\n// ── NavigationMenuIndicator — fade + layout position sliding ──\n\nconst NavigationMenuIndicator = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>\n>(({ className, ...props }, ref) => {\n const innerRef = React.useRef<HTMLDivElement>(null)\n const composedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n (innerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n },\n [ref],\n )\n\n const [isVisible, setIsVisible] = React.useState(false)\n\n React.useEffect(() => {\n const el = innerRef.current\n if (!el) return\n\n const initial = el.getAttribute('data-state')\n setIsVisible(initial === 'visible')\n\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.attributeName === 'data-state') {\n setIsVisible(el.getAttribute('data-state') === 'visible')\n }\n }\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n return () => observer.disconnect()\n }, [])\n\n return (\n <NavigationMenuPrimitive.Indicator\n ref={composedRef}\n className={cn(\n 'top-full z-base flex h-ds-02b items-end justify-center overflow-hidden',\n className,\n )}\n {...props}\n >\n <motion.div\n layout\n initial={false}\n animate={isVisible ? { opacity: 1 } : { opacity: 0 }}\n transition={tweens.fade}\n className=\"relative top-[60%] h-2 w-2 rotate-45 rounded-tl-control-inner bg-surface-border shadow-raised-hover\"\n />\n </NavigationMenuPrimitive.Indicator>\n )\n})\nNavigationMenuIndicator.displayName =\n NavigationMenuPrimitive.Indicator.displayName\n\nexport type NavigationMenuProps = React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>\nexport type NavigationMenuContentProps = React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>\n\nexport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuIndicator,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n NavigationMenuViewport,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"navigation-menu.js","names":[],"sources":["../../src/ui/navigation-menu.tsx"],"sourcesContent":["'use client'\n\nimport * as NavigationMenuPrimitive from '@primitives/react-navigation-menu'\nimport { IconChevronDown } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst NavigationMenu = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <NavigationMenuPrimitive.Root\n ref={ref}\n className={cn(\n 'relative z-raised flex max-w-max flex-1 items-center justify-center',\n className,\n )}\n {...props}\n >\n {children}\n <NavigationMenuViewport />\n </NavigationMenuPrimitive.Root>\n))\nNavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName\n\nconst NavigationMenuList = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.List\n ref={ref}\n className={cn(\n 'group flex flex-1 list-none items-center justify-center space-x-ds-02',\n className,\n )}\n {...props}\n />\n))\nNavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName\n\nconst NavigationMenuItem = NavigationMenuPrimitive.Item\n\nconst NavigationMenuTrigger = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group inline-flex h-ds-sm-plus w-max items-center justify-center rounded-control bg-transparent px-ds-05 py-ds-03 text-ds-md font-medium transition-colors hover:bg-surface-raised-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 disabled:pointer-events-none disabled:opacity-action-disabled',\n className,\n )}\n {...props}\n >\n {children}{' '}\n <Icon icon={IconChevronDown} size=\"sm\" className=\"relative top-[1px] ml-ds-02 transition-transform duration-moderate-02 group-data-[state=open]:rotate-180\" />\n </NavigationMenuPrimitive.Trigger>\n))\nNavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName\n\n// ── NavigationMenuContent — directional slide using data-motion ──\n\nconst contentSlideVariants = {\n 'from-start': { x: '-13rem', opacity: 0 },\n 'from-end': { x: '13rem', opacity: 0 },\n 'to-start': { x: '-13rem', opacity: 0 },\n 'to-end': { x: '13rem', opacity: 0 },\n center: { x: 0, opacity: 1 },\n} as const\n\nconst NavigationMenuContent = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>\n>(({ className, ...props }, ref) => {\n const innerRef = React.useRef<HTMLDivElement>(null)\n const composedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n (innerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n },\n [ref],\n )\n\n const [motionDir, setMotionDir] = React.useState<string | null>(null)\n\n // Observe data-motion attribute changes from Radix\n React.useEffect(() => {\n const el = innerRef.current\n if (!el) return\n\n // Read initial value\n const initial = el.getAttribute('data-motion')\n if (initial) setMotionDir(initial)\n\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.attributeName === 'data-motion') {\n const val = el.getAttribute('data-motion')\n setMotionDir(val)\n }\n }\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-motion'] })\n return () => observer.disconnect()\n }, [])\n\n const initial = motionDir && motionDir.startsWith('from-')\n ? contentSlideVariants[motionDir as keyof typeof contentSlideVariants]\n : motionDir && motionDir.startsWith('to-')\n ? contentSlideVariants.center\n : { x: 0, opacity: 0 }\n\n const animate = motionDir && motionDir.startsWith('from-')\n ? contentSlideVariants.center\n : motionDir && motionDir.startsWith('to-')\n ? contentSlideVariants[motionDir as keyof typeof contentSlideVariants]\n : contentSlideVariants.center\n\n return (\n <NavigationMenuPrimitive.Content\n ref={composedRef}\n className={cn(\n 'left-0 top-0 w-full md:absolute md:w-auto',\n className,\n )}\n {...props}\n >\n <motion.div\n key={motionDir}\n initial={initial}\n animate={animate}\n transition={{ ...springs.smooth, opacity: tweens.fade }}\n className=\"w-full\"\n >\n {props.children}\n </motion.div>\n </NavigationMenuPrimitive.Content>\n )\n})\nNavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName\n\nconst NavigationMenuLink = NavigationMenuPrimitive.Link\n\n// ── NavigationMenuViewport — scale + fade with layout for size changes ──\n\nconst NavigationMenuViewport = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>\n>(({ className, ...props }, ref) => {\n const innerRef = React.useRef<HTMLDivElement>(null)\n const composedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n (innerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n },\n [ref],\n )\n\n const [isOpen, setIsOpen] = React.useState(false)\n\n React.useEffect(() => {\n const el = innerRef.current\n if (!el) return\n\n const initial = el.getAttribute('data-state')\n setIsOpen(initial === 'open')\n\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.attributeName === 'data-state') {\n setIsOpen(el.getAttribute('data-state') === 'open')\n }\n }\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n return () => observer.disconnect()\n }, [])\n\n return (\n <div className={cn('absolute left-0 top-full flex justify-center')}>\n <NavigationMenuPrimitive.Viewport\n className={cn(\n 'origin-top-center relative mt-ds-02b h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-overlay bg-surface-overlay shadow-floating md:w-[var(--radix-navigation-menu-viewport-width)]',\n className,\n )}\n ref={composedRef}\n {...props}\n />\n {/* Overlay motion element for scale+fade animation */}\n <motion.div\n aria-hidden\n className=\"absolute inset-0 pointer-events-none\"\n initial={false}\n animate={isOpen ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.95 }}\n transition={{ ...springs.smooth, opacity: tweens.fade }}\n />\n </div>\n )\n})\nNavigationMenuViewport.displayName =\n NavigationMenuPrimitive.Viewport.displayName\n\n// ── NavigationMenuIndicator — fade + layout position sliding ──\n\nconst NavigationMenuIndicator = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>\n>(({ className, ...props }, ref) => {\n const innerRef = React.useRef<HTMLDivElement>(null)\n const composedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n (innerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n },\n [ref],\n )\n\n const [isVisible, setIsVisible] = React.useState(false)\n\n React.useEffect(() => {\n const el = innerRef.current\n if (!el) return\n\n const initial = el.getAttribute('data-state')\n setIsVisible(initial === 'visible')\n\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.attributeName === 'data-state') {\n setIsVisible(el.getAttribute('data-state') === 'visible')\n }\n }\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n return () => observer.disconnect()\n }, [])\n\n return (\n <NavigationMenuPrimitive.Indicator\n ref={composedRef}\n className={cn(\n 'top-full z-base flex h-ds-02b items-end justify-center overflow-hidden',\n className,\n )}\n {...props}\n >\n <motion.div\n layout\n initial={false}\n animate={isVisible ? { opacity: 1 } : { opacity: 0 }}\n transition={tweens.fade}\n className=\"relative top-[60%] h-2 w-2 rotate-45 rounded-tl-control-inner bg-surface-border shadow-raised-hover\"\n />\n </NavigationMenuPrimitive.Indicator>\n )\n})\nNavigationMenuIndicator.displayName =\n NavigationMenuPrimitive.Indicator.displayName\n\nexport type NavigationMenuProps = React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>\nexport type NavigationMenuContentProps = React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>\n\nexport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuIndicator,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n NavigationMenuViewport,\n}\n"],"mappings":";;;;;;;;;;AAWA,IAAM,IAAiB,EAAM,YAG1B,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,GAAD;CACO;CACL,WAAW,EACT,uEACA,CACF;CACA,GAAI;WANN,CAQG,GACD,kBAAC,GAAD,CAAyB,CAAA,CACG;EAC/B;AACD,EAAe,cAAA,EAA2C;AAE1D,IAAM,IAAqB,EAAM,YAG9B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD;CACO;CACL,WAAW,EACT,yEACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAmB,cAAA,EAA2C;AAE9D,IAAM,IAAqB,GAErB,IAAwB,EAAM,YAGjC,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,GAAD;CACO;CACL,WAAW,EACT,wUACA,CACF;CACA,GAAI;WANN;EAQG;EAAU;EACX,kBAAC,GAAD;GAAM,MAAM;GAAiB,MAAK;GAAK,WAAU;EAA4G,CAAA;CAC9H;EAClC;AACD,EAAsB,cAAA,EAA8C;AAIpE,IAAM,IAAuB;CAC3B,cAAc;EAAE,GAAG;EAAU,SAAS;CAAE;CACxC,YAAY;EAAE,GAAG;EAAS,SAAS;CAAE;CACrC,YAAY;EAAE,GAAG;EAAU,SAAS;CAAE;CACtC,UAAU;EAAE,GAAG;EAAS,SAAS;CAAE;CACnC,QAAQ;EAAE,GAAG;EAAG,SAAS;CAAE;AAC7B,GAEM,IAAwB,EAAM,YAGjC,EAAE,cAAW,GAAG,KAAS,MAAQ;CAClC,IAAM,IAAW,EAAM,OAAuB,IAAI,GAC5C,IAAc,EAAM,aACvB,MAAgC;EAE/B,AADA,EAA4D,UAAU,GAClE,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,MAAK,EAAuD,UAAU;CACjF,GACA,CAAC,CAAG,CACN,GAEM,CAAC,GAAW,KAAgB,EAAM,SAAwB,IAAI;CAGpE,EAAM,gBAAgB;EACpB,IAAM,IAAK,EAAS;EACpB,IAAI,CAAC,GAAI;EAGT,IAAM,IAAU,EAAG,aAAa,aAAa;EAC7C,AAAI,KAAS,EAAa,CAAO;EAEjC,IAAM,IAAW,IAAI,kBAAkB,MAAc;GACnD,KAAK,IAAM,KAAK,GACd,IAAI,EAAE,kBAAkB,eAAe;IACrC,IAAM,IAAM,EAAG,aAAa,aAAa;IACzC,EAAa,CAAG;GAClB;EAEJ,CAAC;EAED,OADA,EAAS,QAAQ,GAAI;GAAE,YAAY;GAAM,iBAAiB,CAAC,aAAa;EAAE,CAAC,SAC9D,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC;CAEL,IAAM,IAAU,KAAa,EAAU,WAAW,OAAO,IACrD,EAAqB,KACrB,KAAa,EAAU,WAAW,KAAK,IACrC,EAAqB,SACrB;EAAE,GAAG;EAAG,SAAS;CAAE,GAEnB,IAAU,KAAa,EAAU,WAAW,OAAO,IACrD,EAAqB,SACrB,KAAa,EAAU,WAAW,KAAK,IACrC,EAAqB,KACrB,EAAqB;CAE3B,OACE,kBAAC,GAAD;EACE,KAAK;EACL,WAAW,EACT,6CACA,CACF;EACA,GAAI;YAEJ,kBAAC,EAAO,KAAR;GAEW;GACA;GACT,YAAY;IAAE,GAAG,EAAQ;IAAQ,SAAS,EAAO;GAAK;GACtD,WAAU;aAET,EAAM;EACG,GAPL,CAOK;CACmB,CAAA;AAErC,CAAC;AACD,EAAsB,cAAA,EAA8C;AAEpE,IAAM,IAAqB,GAIrB,IAAyB,EAAM,YAGlC,EAAE,cAAW,GAAG,KAAS,MAAQ;CAClC,IAAM,IAAW,EAAM,OAAuB,IAAI,GAC5C,IAAc,EAAM,aACvB,MAAgC;EAE/B,AADA,EAA4D,UAAU,GAClE,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,MAAK,EAAuD,UAAU;CACjF,GACA,CAAC,CAAG,CACN,GAEM,CAAC,GAAQ,KAAa,EAAM,SAAS,EAAK;CAoBhD,OAlBA,EAAM,gBAAgB;EACpB,IAAM,IAAK,EAAS;EACpB,IAAI,CAAC,GAAI;EAET,IAAM,IAAU,EAAG,aAAa,YAAY;EAC5C,EAAU,MAAY,MAAM;EAE5B,IAAM,IAAW,IAAI,kBAAkB,MAAc;GACnD,KAAK,IAAM,KAAK,GACd,AAAI,EAAE,kBAAkB,gBACtB,EAAU,EAAG,aAAa,YAAY,MAAM,MAAM;EAGxD,CAAC;EAED,OADA,EAAS,QAAQ,GAAI;GAAE,YAAY;GAAM,iBAAiB,CAAC,YAAY;EAAE,CAAC,SAC7D,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC,GAGH,kBAAC,OAAD;EAAK,WAAW,EAAG,8CAA8C;YAAjE,CACE,kBAAC,GAAD;GACE,WAAW,EACT,sNACA,CACF;GACA,KAAK;GACL,GAAI;EACL,CAAA,GAED,kBAAC,EAAO,KAAR;GACE,eAAA;GACA,WAAU;GACV,SAAS;GACT,SAAS,IAAS;IAAE,SAAS;IAAG,OAAO;GAAE,IAAI;IAAE,SAAS;IAAG,OAAO;GAAK;GACvE,YAAY;IAAE,GAAG,EAAQ;IAAQ,SAAS,EAAO;GAAK;EACvD,CAAA,CACE;;AAET,CAAC;AACD,EAAuB,cAAA,EACY;AAInC,IAAM,IAA0B,EAAM,YAGnC,EAAE,cAAW,GAAG,KAAS,MAAQ;CAClC,IAAM,IAAW,EAAM,OAAuB,IAAI,GAC5C,IAAc,EAAM,aACvB,MAAgC;EAE/B,AADA,EAA4D,UAAU,GAClE,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,MAAK,EAAuD,UAAU;CACjF,GACA,CAAC,CAAG,CACN,GAEM,CAAC,GAAW,KAAgB,EAAM,SAAS,EAAK;CAoBtD,OAlBA,EAAM,gBAAgB;EACpB,IAAM,IAAK,EAAS;EACpB,IAAI,CAAC,GAAI;EAET,IAAM,IAAU,EAAG,aAAa,YAAY;EAC5C,EAAa,MAAY,SAAS;EAElC,IAAM,IAAW,IAAI,kBAAkB,MAAc;GACnD,KAAK,IAAM,KAAK,GACd,AAAI,EAAE,kBAAkB,gBACtB,EAAa,EAAG,aAAa,YAAY,MAAM,SAAS;EAG9D,CAAC;EAED,OADA,EAAS,QAAQ,GAAI;GAAE,YAAY;GAAM,iBAAiB,CAAC,YAAY;EAAE,CAAC,SAC7D,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC,GAGH,kBAAC,GAAD;EACE,KAAK;EACL,WAAW,EACT,0EACA,CACF;EACA,GAAI;YAEJ,kBAAC,EAAO,KAAR;GACE,QAAA;GACA,SAAS;GACT,SAAS,IAAY,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;GACnD,YAAY,EAAO;GACnB,WAAU;EACX,CAAA;CACgC,CAAA;AAEvC,CAAC;AACD,EAAwB,cAAA,EACY"}
@@ -1 +1 @@
1
- {"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../src/ui/number-input.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAA;AAGtE,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAA;AAEzC,QAAA,MAAM,0BAA0B;;8EAa/B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAkClG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IACjI,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,iDAAiD;IACjD,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,QAAA,MAAM,WAAW,2FAmHhB,CAAA;AAGD,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAA"}
1
+ {"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../src/ui/number-input.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAA;AAGtE,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAA;AAEzC,QAAA,MAAM,0BAA0B;;8EAa/B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAkClG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IACjI,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,iDAAiD;IACjD,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,QAAA,MAAM,WAAW,2FAqHhB,CAAA;AAGD,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAA"}
@@ -82,7 +82,8 @@ var u = e("flex items-center justify-between rounded-control border border-surfa
82
82
  "aria-invalid": O === "error" || void 0,
83
83
  "aria-describedby": C["aria-describedby"] ?? E.helperTextId,
84
84
  className: t("bg-transparent font-semibold border-0 text-center text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none", P),
85
- ...C
85
+ ...C,
86
+ id: C.id ?? E.inputId
86
87
  }),
87
88
  /* @__PURE__ */ o("button", {
88
89
  type: "button",
@@ -1 +1 @@
1
- {"version":3,"file":"number-input.js","names":[],"sources":["../../src/ui/number-input.tsx"],"sourcesContent":["'use client'\n\nimport { IconMinus, IconPlus } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { Icon } from './icon'\nimport type { IconSize } from './icon-context'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { cn } from './lib/utils'\n\n/** @deprecated Use `FieldState` — the shared control-state type. Kept as an alias. */\nexport type NumberInputState = FieldState\n\nconst numberInputWrapperVariants = cva(\n 'flex items-center justify-between rounded-control border border-surface-border-strong',\n {\n variants: {\n size: {\n xs: 'h-ds-xs-plus',\n sm: 'h-ds-sm',\n md: 'h-ds-md',\n lg: 'h-ds-lg',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\nexport type NumberInputSize = NonNullable<VariantProps<typeof numberInputWrapperVariants>['size']>\n\n/** Maps size to stepper button dimensions */\nconst buttonSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'h-[22px] w-[22px]',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-sm w-ds-sm',\n lg: 'h-ds-md w-ds-md',\n}\n\n/** Maps size to Icon component size */\nconst iconSizeMap: Record<NonNullable<NumberInputSize>, IconSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n}\n\n/** Maps size to input text and width classes */\nconst inputSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'text-ds-sm w-ds-06b',\n sm: 'text-ds-sm w-ds-sm-plus',\n md: 'text-ds-md w-ds-sm-plus',\n lg: 'text-ds-md w-ds-md',\n}\n\n/** Maps state to border color classes */\nconst stateColorMap: Record<NonNullable<NumberInputState>, string> = {\n default: '',\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\n/**\n * Props for NumberInput — a stepper control with \"−\" and \"+\" buttons flanking a numeric input,\n * clamped between `min` and `max`. The decrement/increment buttons are disabled when bounds are reached.\n *\n * **Controlled only:** Pass `value` + `onValueChange` for controlled usage. Uncontrolled usage is\n * possible but the buttons won't update the displayed value without `onValueChange`.\n *\n * **Step:** The `step` prop controls how much each button press increments/decrements (default 1).\n * Direct text input is also clamped to `[min, max]` on change.\n *\n * **Sizes:** `xs` (28px) | `sm` (32px) | `md` (40px, default) | `lg` (48px)\n *\n * **Validation states:** `state=\"error\"` colors the border red.\n * Use with `<FormField>` to show helper text below the input.\n *\n * @example\n * // Quantity selector with 1–99 range:\n * <NumberInput value={qty} onValueChange={setQty} min={1} max={99} />\n *\n * @example\n * // Rating input (1–10, step 1):\n * <NumberInput value={rating} onValueChange={setRating} min={1} max={10} />\n *\n * @example\n * // Fine-grained opacity control (0–100, step 5):\n * <NumberInput value={opacity} onValueChange={setOpacity} min={0} max={100} step={5} />\n *\n * @example\n * // Disabled number display (read-only-like):\n * <NumberInput value={autoCalcValue} onValueChange={() => {}} disabled />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type' | 'size'> {\n value?: number\n onValueChange?: (value: number) => void\n min?: number\n max?: number\n step?: number\n /** Size of the number input. Controls height, button sizes, text size. */\n size?: NumberInputSize\n /** Validation state controlling border color. */\n state?: FieldState\n}\n\nconst NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value = 0,\n onValueChange,\n min = Number.MIN_SAFE_INTEGER,\n max = Number.MAX_SAFE_INTEGER,\n step = 1,\n disabled = false,\n className,\n size: sizeProp = 'md',\n state: stateProp,\n 'aria-label': ariaLabelProp,\n ...rest\n },\n ref,\n ) => {\n const size = sizeProp ?? 'md'\n const fieldCtx = useFormField()\n // If no explicit aria-label and not inside a FormField (no id to associate with Label),\n // provide a sensible default\n const ariaLabel = ariaLabelProp ?? (rest.id || fieldCtx.helperTextId ? undefined : 'Numeric value')\n\n // Merge FormField context — explicit props always win (shared precedence)\n const state = resolveFieldState(stateProp, fieldCtx.state) ?? 'default'\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value.trim()\n if (raw === '' || raw === '-') {\n onValueChange?.(min >= 0 ? min : 0)\n return\n }\n const parsed = Number(raw)\n if (Number.isNaN(parsed)) return\n const clamped = Math.min(Math.max(parsed, min), max)\n onValueChange?.(clamped)\n }\n\n const handleIncrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value + step\n if (newValue <= max) {\n onValueChange?.(newValue)\n }\n }\n\n const handleDecrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value - step\n if (newValue >= min) {\n onValueChange?.(newValue)\n }\n }\n\n const resolvedButtonSize = buttonSizeMap[size]\n const resolvedIconSize = iconSizeMap[size]\n const resolvedInputSize = inputSizeMap[size]\n\n return (\n <div\n className={cn(\n numberInputWrapperVariants({ size }),\n stateColorMap[state],\n className,\n )}\n >\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={disabled || value <= min}\n aria-label=\"Decrease value\"\n title=\"Decrease\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconMinus} size={resolvedIconSize} />\n </button>\n\n <input\n ref={ref}\n type=\"number\"\n value={value}\n onChange={handleInputChange}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={rest['aria-describedby'] ?? fieldCtx.helperTextId}\n className={cn(\n 'bg-transparent font-semibold border-0 text-center text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',\n resolvedInputSize,\n )}\n {...rest}\n />\n\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={disabled || value >= max}\n aria-label=\"Increase value\"\n title=\"Increase\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconPlus} size={resolvedIconSize} />\n </button>\n </div>\n )\n },\n)\nNumberInput.displayName = 'NumberInput'\n\nexport { NumberInput, numberInputWrapperVariants }\n"],"mappings":";;;;;;;;;;AAeA,IAAM,IAA6B,EACjC,yFACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACL,EACF;CACD,iBAAiB,EAAE,MAAM,MAAM;CAChC,CACF,EAKK,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAGK,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAGK,IAA6D;CACjE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAGK,IAA+D;CACnE,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACV,EA8CK,IAAc,EAAM,YAEtB,EACE,WAAQ,GACR,kBACA,SAAM,gBACN,sBACA,UAAO,GACP,cAAW,IACX,cACA,MAAM,IAAW,MACjB,OAAO,GACP,cAAc,GACd,GAAG,KAEL,MACG;CACH,IAAM,IAAO,KAAY,MACnB,IAAW,GAAc,EAGzB,IAAY,MAAkB,EAAK,MAAM,EAAS,eAAe,KAAA,IAAY,kBAG7E,IAAQ,EAAkB,GAAW,EAAS,MAAM,IAAI,WAExD,KAAqB,MAA2C;EACpE,IAAM,IAAM,EAAE,OAAO,MAAM,MAAM;AACjC,MAAI,MAAQ,MAAM,MAAQ,KAAK;AAC7B,OAAgB,KAAO,IAAI,IAAM,EAAE;AACnC;;EAEF,IAAM,IAAS,OAAO,EAAI;AACtB,SAAO,MAAM,EAAO,IAExB,IADgB,KAAK,IAAI,KAAK,IAAI,GAAQ,EAAI,EAAE,EAAI,CAC5B;IAGpB,KAAmB,MAA2C;AAClE,IAAE,gBAAgB;EAClB,IAAM,IAAW,IAAQ;AACzB,EAAI,KAAY,KACd,IAAgB,EAAS;IAIvB,KAAmB,MAA2C;AAClE,IAAE,gBAAgB;EAClB,IAAM,IAAW,IAAQ;AACzB,EAAI,KAAY,KACd,IAAgB,EAAS;IAIvB,IAAqB,EAAc,IACnC,IAAmB,EAAY,IAC/B,IAAoB,EAAa;AAEvC,QACE,kBAAC,OAAD;EACE,WAAW,EACT,EAA2B,EAAE,SAAM,CAAC,EACpC,EAAc,IACd,EACD;YALH;GAOE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,0TACA,EACD;cAED,kBAAC,GAAD;KAAM,MAAM;KAAW,MAAM;KAAoB,CAAA;IAC1C,CAAA;GAET,kBAAC,SAAD;IACO;IACL,MAAK;IACE;IACP,UAAU;IACL;IACA;IACC;IACI;IACV,cAAY;IACZ,gBAAc,MAAU,WAAW,KAAA;IACnC,oBAAkB,EAAK,uBAAuB,EAAS;IACvD,WAAW,EACT,8QACA,EACD;IACD,GAAI;IACJ,CAAA;GAEF,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,0TACA,EACD;cAED,kBAAC,GAAD;KAAM,MAAM;KAAU,MAAM;KAAoB,CAAA;IACzC,CAAA;GACL;;EAGX;AACD,EAAY,cAAc"}
1
+ {"version":3,"file":"number-input.js","names":[],"sources":["../../src/ui/number-input.tsx"],"sourcesContent":["'use client'\n\nimport { IconMinus, IconPlus } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { Icon } from './icon'\nimport type { IconSize } from './icon-context'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { cn } from './lib/utils'\n\n/** @deprecated Use `FieldState` — the shared control-state type. Kept as an alias. */\nexport type NumberInputState = FieldState\n\nconst numberInputWrapperVariants = cva(\n 'flex items-center justify-between rounded-control border border-surface-border-strong',\n {\n variants: {\n size: {\n xs: 'h-ds-xs-plus',\n sm: 'h-ds-sm',\n md: 'h-ds-md',\n lg: 'h-ds-lg',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\nexport type NumberInputSize = NonNullable<VariantProps<typeof numberInputWrapperVariants>['size']>\n\n/** Maps size to stepper button dimensions */\nconst buttonSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'h-[22px] w-[22px]',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-sm w-ds-sm',\n lg: 'h-ds-md w-ds-md',\n}\n\n/** Maps size to Icon component size */\nconst iconSizeMap: Record<NonNullable<NumberInputSize>, IconSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n}\n\n/** Maps size to input text and width classes */\nconst inputSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'text-ds-sm w-ds-06b',\n sm: 'text-ds-sm w-ds-sm-plus',\n md: 'text-ds-md w-ds-sm-plus',\n lg: 'text-ds-md w-ds-md',\n}\n\n/** Maps state to border color classes */\nconst stateColorMap: Record<NonNullable<NumberInputState>, string> = {\n default: '',\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\n/**\n * Props for NumberInput — a stepper control with \"−\" and \"+\" buttons flanking a numeric input,\n * clamped between `min` and `max`. The decrement/increment buttons are disabled when bounds are reached.\n *\n * **Controlled only:** Pass `value` + `onValueChange` for controlled usage. Uncontrolled usage is\n * possible but the buttons won't update the displayed value without `onValueChange`.\n *\n * **Step:** The `step` prop controls how much each button press increments/decrements (default 1).\n * Direct text input is also clamped to `[min, max]` on change.\n *\n * **Sizes:** `xs` (28px) | `sm` (32px) | `md` (40px, default) | `lg` (48px)\n *\n * **Validation states:** `state=\"error\"` colors the border red.\n * Use with `<FormField>` to show helper text below the input.\n *\n * @example\n * // Quantity selector with 1–99 range:\n * <NumberInput value={qty} onValueChange={setQty} min={1} max={99} />\n *\n * @example\n * // Rating input (1–10, step 1):\n * <NumberInput value={rating} onValueChange={setRating} min={1} max={10} />\n *\n * @example\n * // Fine-grained opacity control (0–100, step 5):\n * <NumberInput value={opacity} onValueChange={setOpacity} min={0} max={100} step={5} />\n *\n * @example\n * // Disabled number display (read-only-like):\n * <NumberInput value={autoCalcValue} onValueChange={() => {}} disabled />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type' | 'size'> {\n value?: number\n onValueChange?: (value: number) => void\n min?: number\n max?: number\n step?: number\n /** Size of the number input. Controls height, button sizes, text size. */\n size?: NumberInputSize\n /** Validation state controlling border color. */\n state?: FieldState\n}\n\nconst NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value = 0,\n onValueChange,\n min = Number.MIN_SAFE_INTEGER,\n max = Number.MAX_SAFE_INTEGER,\n step = 1,\n disabled = false,\n className,\n size: sizeProp = 'md',\n state: stateProp,\n 'aria-label': ariaLabelProp,\n ...rest\n },\n ref,\n ) => {\n const size = sizeProp ?? 'md'\n const fieldCtx = useFormField()\n // If no explicit aria-label and not inside a FormField (no id to associate with Label),\n // provide a sensible default\n const ariaLabel = ariaLabelProp ?? (rest.id || fieldCtx.helperTextId ? undefined : 'Numeric value')\n\n // Merge FormField context — explicit props always win (shared precedence)\n const state = resolveFieldState(stateProp, fieldCtx.state) ?? 'default'\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value.trim()\n if (raw === '' || raw === '-') {\n onValueChange?.(min >= 0 ? min : 0)\n return\n }\n const parsed = Number(raw)\n if (Number.isNaN(parsed)) return\n const clamped = Math.min(Math.max(parsed, min), max)\n onValueChange?.(clamped)\n }\n\n const handleIncrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value + step\n if (newValue <= max) {\n onValueChange?.(newValue)\n }\n }\n\n const handleDecrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value - step\n if (newValue >= min) {\n onValueChange?.(newValue)\n }\n }\n\n const resolvedButtonSize = buttonSizeMap[size]\n const resolvedIconSize = iconSizeMap[size]\n const resolvedInputSize = inputSizeMap[size]\n\n return (\n <div\n className={cn(\n numberInputWrapperVariants({ size }),\n stateColorMap[state],\n className,\n )}\n >\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={disabled || value <= min}\n aria-label=\"Decrease value\"\n title=\"Decrease\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconMinus} size={resolvedIconSize} />\n </button>\n\n <input\n ref={ref}\n type=\"number\"\n value={value}\n onChange={handleInputChange}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={rest['aria-describedby'] ?? fieldCtx.helperTextId}\n className={cn(\n 'bg-transparent font-semibold border-0 text-center text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',\n resolvedInputSize,\n )}\n {...rest}\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves.\n id={rest.id ?? fieldCtx.inputId}\n />\n\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={disabled || value >= max}\n aria-label=\"Increase value\"\n title=\"Increase\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconPlus} size={resolvedIconSize} />\n </button>\n </div>\n )\n },\n)\nNumberInput.displayName = 'NumberInput'\n\nexport { NumberInput, numberInputWrapperVariants }\n"],"mappings":";;;;;;;;;;AAeA,IAAM,IAA6B,EACjC,yFACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF,GAKM,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA6D;CACjE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA+D;CACnE,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;AACX,GA8CM,IAAc,EAAM,YAEtB,EACE,WAAQ,GACR,kBACA,SAAM,gBACN,sBACA,UAAO,GACP,cAAW,IACX,cACA,MAAM,IAAW,MACjB,OAAO,GACP,cAAc,GACd,GAAG,KAEL,MACG;CACH,IAAM,IAAO,KAAY,MACnB,IAAW,EAAa,GAGxB,IAAY,MAAkB,EAAK,MAAM,EAAS,eAAe,KAAA,IAAY,kBAG7E,IAAQ,EAAkB,GAAW,EAAS,KAAK,KAAK,WAExD,KAAqB,MAA2C;EACpE,IAAM,IAAM,EAAE,OAAO,MAAM,KAAK;EAChC,IAAI,MAAQ,MAAM,MAAQ,KAAK;GAC7B,IAAgB,KAAO,IAAI,IAAM,CAAC;GAClC;EACF;EACA,IAAM,IAAS,OAAO,CAAG;EACrB,OAAO,MAAM,CAAM,KAEvB,IADgB,KAAK,IAAI,KAAK,IAAI,GAAQ,CAAG,GAAG,CAChC,CAAO;CACzB,GAEM,KAAmB,MAA2C;EAClE,EAAE,eAAe;EACjB,IAAM,IAAW,IAAQ;EACzB,AAAI,KAAY,KACd,IAAgB,CAAQ;CAE5B,GAEM,KAAmB,MAA2C;EAClE,EAAE,eAAe;EACjB,IAAM,IAAW,IAAQ;EACzB,AAAI,KAAY,KACd,IAAgB,CAAQ;CAE5B,GAEM,IAAqB,EAAc,IACnC,IAAmB,EAAY,IAC/B,IAAoB,EAAa;CAEvC,OACE,kBAAC,OAAD;EACE,WAAW,EACT,EAA2B,EAAE,QAAK,CAAC,GACnC,EAAc,IACd,CACF;YALF;GAOE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,0TACA,CACF;cAEA,kBAAC,GAAD;KAAM,MAAM;KAAW,MAAM;IAAmB,CAAA;GAC1C,CAAA;GAER,kBAAC,SAAD;IACO;IACL,MAAK;IACE;IACP,UAAU;IACL;IACA;IACC;IACI;IACV,cAAY;IACZ,gBAAc,MAAU,WAAW,KAAA;IACnC,oBAAkB,EAAK,uBAAuB,EAAS;IACvD,WAAW,EACT,8QACA,CACF;IACA,GAAI;IAEJ,IAAI,EAAK,MAAM,EAAS;GACzB,CAAA;GAED,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,0TACA,CACF;cAEA,kBAAC,GAAD;KAAM,MAAM;KAAU,MAAM;IAAmB,CAAA;GACzC,CAAA;EACL;;AAET,CACF;AACA,EAAY,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","names":[],"sources":["../../src/ui/pagination.tsx"],"sourcesContent":["'use client'\n\nimport { Slot } from '@primitives/react-slot'\nimport { IconChevronLeft, IconChevronRight, IconDots } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { cn } from './lib/utils'\n\nconst PaginationRoot = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'>\n>(({ className, ...props }, ref) => (\n <nav\n ref={ref}\n role=\"navigation\"\n aria-label=\"pagination\"\n className={cn('mx-auto flex w-full justify-center', className)}\n {...props}\n />\n))\nPaginationRoot.displayName = 'PaginationRoot'\n\nconst PaginationContent = React.forwardRef<\n HTMLUListElement,\n React.ComponentPropsWithoutRef<'ul'>\n>(({ className, ...props }, ref) => (\n <ul\n ref={ref}\n className={cn('flex flex-row items-center gap-ds-02', className)}\n {...props}\n />\n))\nPaginationContent.displayName = 'PaginationContent'\n\nconst PaginationItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<'li'>\n>(({ className, ...props }, ref) => (\n <li ref={ref} className={cn('', className)} {...props} />\n))\nPaginationItem.displayName = 'PaginationItem'\n\n/**\n * Props for PaginationLink — a single page number button in a pagination row.\n * When `isActive` is true, the button gets the brand interactive fill and `aria-current=\"page\"`.\n *\n * @example\n * // Active page button:\n * <PaginationLink isActive onClick={() => goToPage(3)}>3</PaginationLink>\n *\n * @example\n * // Render as a Next.js Link via asChild:\n * <PaginationLink asChild isActive={currentPage === 5}>\n * <Link href=\"/posts?page=5\">5</Link>\n * </PaginationLink>\n */\nexport interface PaginationLinkProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n isActive?: boolean\n asChild?: boolean\n}\n\nconst PaginationLink = React.forwardRef<HTMLButtonElement, PaginationLinkProps>(\n ({ className, isActive = false, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n ref={ref}\n aria-current={isActive ? 'page' : undefined}\n className={cn(\n 'inline-flex items-center justify-center h-ds-sm-plus w-ds-sm-plus rounded-control text-ds-md font-medium tabular-nums transition-colors 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 active:scale-95',\n isActive\n ? 'bg-accent-9 text-accent-fg'\n : 'hover:bg-surface-raised-hover text-surface-fg',\n className,\n )}\n {...props}\n />\n )\n },\n)\nPaginationLink.displayName = 'PaginationLink'\n\nconst PaginationPrevious = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to previous page\"\n className={cn('w-auto gap-ds-02 pl-ds-03 pr-ds-04', className)}\n {...props}\n >\n <Icon icon={IconChevronLeft} size=\"sm\" />\n <span>Previous</span>\n </PaginationLink>\n))\nPaginationPrevious.displayName = 'PaginationPrevious'\n\nconst PaginationNext = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to next page\"\n className={cn('w-auto gap-ds-02 pl-ds-04 pr-ds-03', className)}\n {...props}\n >\n <span>Next</span>\n <Icon icon={IconChevronRight} size=\"sm\" />\n </PaginationLink>\n))\nPaginationNext.displayName = 'PaginationNext'\n\nconst PaginationEllipsis = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center text-surface-fg-muted',\n className,\n )}\n {...props}\n >\n <Icon icon={IconDots} size=\"sm\" />\n <span className=\"sr-only\">More pages</span>\n </span>\n))\nPaginationEllipsis.displayName = 'PaginationEllipsis'\n\n/* ------------------------------------------------------------------ */\n/* generatePagination helper */\n/* ------------------------------------------------------------------ */\n\ntype PageItem = number | 'ellipsis'\n\n/**\n * Pure function that builds an array of page numbers and ellipsis markers.\n * Always shows first and last page, plus `siblingCount` pages around `current`.\n *\n * @example generatePagination(5, 10, 1) → [1, 'ellipsis', 4, 5, 6, 'ellipsis', 10]\n */\nfunction generatePagination(\n current: number,\n total: number,\n siblingCount: number,\n): PageItem[] {\n // When total pages fit without any ellipsis\n const totalSlots = siblingCount * 2 + 5 // first + last + current + 2*siblings + 2 ellipsis slots\n if (total <= totalSlots) {\n return Array.from({ length: total }, (_, i) => i + 1)\n }\n\n const leftSibling = Math.max(current - siblingCount, 1)\n const rightSibling = Math.min(current + siblingCount, total)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < total - 1\n\n if (!showLeftEllipsis && showRightEllipsis) {\n // e.g. [1, 2, 3, 4, 5, '...', 10]\n const leftCount = siblingCount * 2 + 3\n const leftPages = Array.from({ length: leftCount }, (_, i) => i + 1)\n return [...leftPages, 'ellipsis', total]\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n // e.g. [1, '...', 6, 7, 8, 9, 10]\n const rightCount = siblingCount * 2 + 3\n const rightPages = Array.from(\n { length: rightCount },\n (_, i) => total - rightCount + 1 + i,\n )\n return [1, 'ellipsis', ...rightPages]\n }\n\n // Both ellipses: [1, '...', 4, 5, 6, '...', 10]\n const middlePages = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i,\n )\n return [1, 'ellipsis', ...middlePages, 'ellipsis', total]\n}\n\n/* ------------------------------------------------------------------ */\n/* PaginationNav — controlled convenience wrapper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Props for PaginationNav — a fully self-contained controlled pagination component that renders\n * Previous / page numbers (with ellipsis) / Next — using `generatePagination` internally.\n *\n * **1-indexed:** `currentPage` starts at 1 (not 0). `onPageChange` also receives 1-indexed values.\n *\n * **`siblingCount`:** Number of page buttons shown on each side of the current page (default 1).\n * A wider `siblingCount` shows more page buttons before switching to ellipsis.\n *\n * @example\n * // Basic controlled pagination:\n * <PaginationNav\n * totalPages={24}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * />\n *\n * @example\n * // Wider sibling range for a results grid (shows more page context):\n * <PaginationNav\n * totalPages={100}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * siblingCount={2}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface PaginationNavProps\n extends React.HTMLAttributes<HTMLElement> {\n /** Total number of pages */\n totalPages: number\n /** Current active page (1-indexed) */\n currentPage: number\n /** Called when the user requests a different page */\n onPageChange: (page: number) => void\n /** Number of sibling page buttons shown on each side of the current page (default: 1) */\n siblingCount?: number\n}\n\nconst PaginationNav = React.forwardRef<HTMLElement, PaginationNavProps>(\n (\n {\n totalPages,\n currentPage,\n onPageChange,\n siblingCount = 1,\n className,\n ...props\n },\n ref,\n ) => {\n const pages = generatePagination(currentPage, totalPages, siblingCount)\n\n return (\n <PaginationRoot ref={ref} className={className} {...props}>\n <PaginationContent>\n <PaginationItem>\n <PaginationPrevious\n onClick={() => onPageChange(Math.max(1, currentPage - 1))}\n disabled={currentPage <= 1}\n />\n </PaginationItem>\n\n {pages.map((page, i) =>\n page === 'ellipsis' ? (\n <PaginationItem key={`e${i}`}>\n <PaginationEllipsis />\n </PaginationItem>\n ) : (\n <PaginationItem key={page}>\n <PaginationLink\n isActive={page === currentPage}\n onClick={() => onPageChange(page)}\n >\n {page}\n </PaginationLink>\n </PaginationItem>\n ),\n )}\n\n <PaginationItem>\n <PaginationNext\n onClick={() =>\n onPageChange(Math.min(totalPages, currentPage + 1))\n }\n disabled={currentPage >= totalPages}\n />\n </PaginationItem>\n </PaginationContent>\n </PaginationRoot>\n )\n },\n)\nPaginationNav.displayName = 'PaginationNav'\n\nexport {\n generatePagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNav,\n PaginationNext,\n PaginationPrevious,\n PaginationRoot,\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAAiB,EAAM,YAG1B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,OAAD;CACO;CACL,MAAK;CACL,cAAW;CACX,WAAW,EAAG,sCAAsC,EAAU;CAC9D,GAAI;CACJ,CAAA,CACF;AACF,EAAe,cAAc;AAE7B,IAAM,IAAoB,EAAM,YAG7B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,MAAD;CACO;CACL,WAAW,EAAG,wCAAwC,EAAU;CAChE,GAAI;CACJ,CAAA,CACF;AACF,EAAkB,cAAc;AAEhC,IAAM,IAAiB,EAAM,YAG1B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,MAAD;CAAS;CAAK,WAAW,EAAG,IAAI,EAAU;CAAE,GAAI;CAAS,CAAA,CACzD;AACF,EAAe,cAAc;AAsB7B,IAAM,IAAiB,EAAM,YAC1B,EAAE,cAAW,cAAW,IAAO,aAAU,IAAO,GAAG,KAAS,MAGzD,kBAFW,IAAU,IAAO,UAE5B;CACO;CACL,gBAAc,IAAW,SAAS,KAAA;CAClC,WAAW,EACT,mUACA,IACI,+BACA,iDACJ,EACD;CACD,GAAI;CACJ,CAAA,CAGP;AACD,EAAe,cAAc;AAE7B,IAAM,IAAqB,EAAM,YAG9B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD;CACO;CACL,cAAW;CACX,WAAW,EAAG,sCAAsC,EAAU;CAC9D,GAAI;WAJN,CAME,kBAAC,GAAD;EAAM,MAAM;EAAiB,MAAK;EAAO,CAAA,EACzC,kBAAC,QAAD,EAAA,UAAM,YAAe,CAAA,CACN;GACjB;AACF,EAAmB,cAAc;AAEjC,IAAM,IAAiB,EAAM,YAG1B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD;CACO;CACL,cAAW;CACX,WAAW,EAAG,sCAAsC,EAAU;CAC9D,GAAI;WAJN,CAME,kBAAC,QAAD,EAAA,UAAM,QAAW,CAAA,EACjB,kBAAC,GAAD;EAAM,MAAM;EAAkB,MAAK;EAAO,CAAA,CAC3B;GACjB;AACF,EAAe,cAAc;AAE7B,IAAM,IAAqB,EAAM,YAG9B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,QAAD;CACO;CACL,eAAY;CACZ,WAAW,EACT,oFACA,EACD;CACD,GAAI;WAPN,CASE,kBAAC,GAAD;EAAM,MAAM;EAAU,MAAK;EAAO,CAAA,EAClC,kBAAC,QAAD;EAAM,WAAU;YAAU;EAAiB,CAAA,CACtC;GACP;AACF,EAAmB,cAAc;AAcjC,SAAS,EACP,GACA,GACA,GACY;AAGZ,KAAI,KADe,IAAe,IAAI,EAEpC,QAAO,MAAM,KAAK,EAAE,QAAQ,GAAO,GAAG,GAAG,MAAM,IAAI,EAAE;CAGvD,IAAM,IAAc,KAAK,IAAI,IAAU,GAAc,EAAE,EACjD,IAAe,KAAK,IAAI,IAAU,GAAc,EAAM,EAEtD,IAAmB,IAAc,GACjC,IAAoB,IAAe,IAAQ;AAEjD,KAAI,CAAC,KAAoB,GAAmB;EAE1C,IAAM,IAAY,IAAe,IAAI;AAErC,SAAO;GAAC,GADU,MAAM,KAAK,EAAE,QAAQ,GAAW,GAAG,GAAG,MAAM,IAAI,EAAE;GAC9C;GAAY;GAAM;;AAG1C,KAAI,KAAoB,CAAC,GAAmB;EAE1C,IAAM,IAAa,IAAe,IAAI;AAKtC,SAAO;GAAC;GAAG;GAAY,GAJJ,MAAM,KACvB,EAAE,QAAQ,GAAY,GACrB,GAAG,MAAM,IAAQ,IAAa,IAAI,EACpC;GACoC;;AAQvC,QAAO;EAAC;EAAG;EAAY,GAJH,MAAM,KACxB,EAAE,QAAQ,IAAe,IAAc,GAAG,GACzC,GAAG,MAAM,IAAc,EACzB;EACsC;EAAY;EAAM;;AA8C3D,IAAM,IAAgB,EAAM,YAExB,EACE,eACA,gBACA,iBACA,kBAAe,GACf,cACA,GAAG,KAEL,MACG;CACH,IAAM,IAAQ,EAAmB,GAAa,GAAY,EAAa;AAEvE,QACE,kBAAC,GAAD;EAAqB;EAAgB;EAAW,GAAI;YAClD,kBAAC,GAAD,EAAA,UAAA;GACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,eAAe,EAAa,KAAK,IAAI,GAAG,IAAc,EAAE,CAAC;IACzD,UAAU,KAAe;IACzB,CAAA,EACa,CAAA;GAEhB,EAAM,KAAK,GAAM,MAChB,MAAS,aACP,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAsB,CAAA,EACP,EAFI,IAAI,IAER,GAEjB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,UAAU,MAAS;IACnB,eAAe,EAAa,EAAK;cAEhC;IACc,CAAA,EACF,EAPI,EAOJ,CAEpB;GAED,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,eACE,EAAa,KAAK,IAAI,GAAY,IAAc,EAAE,CAAC;IAErD,UAAU,KAAe;IACzB,CAAA,EACa,CAAA;GACC,EAAA,CAAA;EACL,CAAA;EAGtB;AACD,EAAc,cAAc"}
1
+ {"version":3,"file":"pagination.js","names":[],"sources":["../../src/ui/pagination.tsx"],"sourcesContent":["'use client'\n\nimport { Slot } from '@primitives/react-slot'\nimport { IconChevronLeft, IconChevronRight, IconDots } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { cn } from './lib/utils'\n\nconst PaginationRoot = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'>\n>(({ className, ...props }, ref) => (\n <nav\n ref={ref}\n role=\"navigation\"\n aria-label=\"pagination\"\n className={cn('mx-auto flex w-full justify-center', className)}\n {...props}\n />\n))\nPaginationRoot.displayName = 'PaginationRoot'\n\nconst PaginationContent = React.forwardRef<\n HTMLUListElement,\n React.ComponentPropsWithoutRef<'ul'>\n>(({ className, ...props }, ref) => (\n <ul\n ref={ref}\n className={cn('flex flex-row items-center gap-ds-02', className)}\n {...props}\n />\n))\nPaginationContent.displayName = 'PaginationContent'\n\nconst PaginationItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<'li'>\n>(({ className, ...props }, ref) => (\n <li ref={ref} className={cn('', className)} {...props} />\n))\nPaginationItem.displayName = 'PaginationItem'\n\n/**\n * Props for PaginationLink — a single page number button in a pagination row.\n * When `isActive` is true, the button gets the brand interactive fill and `aria-current=\"page\"`.\n *\n * @example\n * // Active page button:\n * <PaginationLink isActive onClick={() => goToPage(3)}>3</PaginationLink>\n *\n * @example\n * // Render as a Next.js Link via asChild:\n * <PaginationLink asChild isActive={currentPage === 5}>\n * <Link href=\"/posts?page=5\">5</Link>\n * </PaginationLink>\n */\nexport interface PaginationLinkProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n isActive?: boolean\n asChild?: boolean\n}\n\nconst PaginationLink = React.forwardRef<HTMLButtonElement, PaginationLinkProps>(\n ({ className, isActive = false, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n ref={ref}\n aria-current={isActive ? 'page' : undefined}\n className={cn(\n 'inline-flex items-center justify-center h-ds-sm-plus w-ds-sm-plus rounded-control text-ds-md font-medium tabular-nums transition-colors 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 active:scale-95',\n isActive\n ? 'bg-accent-9 text-accent-fg'\n : 'hover:bg-surface-raised-hover text-surface-fg',\n className,\n )}\n {...props}\n />\n )\n },\n)\nPaginationLink.displayName = 'PaginationLink'\n\nconst PaginationPrevious = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to previous page\"\n className={cn('w-auto gap-ds-02 pl-ds-03 pr-ds-04', className)}\n {...props}\n >\n <Icon icon={IconChevronLeft} size=\"sm\" />\n <span>Previous</span>\n </PaginationLink>\n))\nPaginationPrevious.displayName = 'PaginationPrevious'\n\nconst PaginationNext = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to next page\"\n className={cn('w-auto gap-ds-02 pl-ds-04 pr-ds-03', className)}\n {...props}\n >\n <span>Next</span>\n <Icon icon={IconChevronRight} size=\"sm\" />\n </PaginationLink>\n))\nPaginationNext.displayName = 'PaginationNext'\n\nconst PaginationEllipsis = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center text-surface-fg-muted',\n className,\n )}\n {...props}\n >\n <Icon icon={IconDots} size=\"sm\" />\n <span className=\"sr-only\">More pages</span>\n </span>\n))\nPaginationEllipsis.displayName = 'PaginationEllipsis'\n\n/* ------------------------------------------------------------------ */\n/* generatePagination helper */\n/* ------------------------------------------------------------------ */\n\ntype PageItem = number | 'ellipsis'\n\n/**\n * Pure function that builds an array of page numbers and ellipsis markers.\n * Always shows first and last page, plus `siblingCount` pages around `current`.\n *\n * @example generatePagination(5, 10, 1) → [1, 'ellipsis', 4, 5, 6, 'ellipsis', 10]\n */\nfunction generatePagination(\n current: number,\n total: number,\n siblingCount: number,\n): PageItem[] {\n // When total pages fit without any ellipsis\n const totalSlots = siblingCount * 2 + 5 // first + last + current + 2*siblings + 2 ellipsis slots\n if (total <= totalSlots) {\n return Array.from({ length: total }, (_, i) => i + 1)\n }\n\n const leftSibling = Math.max(current - siblingCount, 1)\n const rightSibling = Math.min(current + siblingCount, total)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < total - 1\n\n if (!showLeftEllipsis && showRightEllipsis) {\n // e.g. [1, 2, 3, 4, 5, '...', 10]\n const leftCount = siblingCount * 2 + 3\n const leftPages = Array.from({ length: leftCount }, (_, i) => i + 1)\n return [...leftPages, 'ellipsis', total]\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n // e.g. [1, '...', 6, 7, 8, 9, 10]\n const rightCount = siblingCount * 2 + 3\n const rightPages = Array.from(\n { length: rightCount },\n (_, i) => total - rightCount + 1 + i,\n )\n return [1, 'ellipsis', ...rightPages]\n }\n\n // Both ellipses: [1, '...', 4, 5, 6, '...', 10]\n const middlePages = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i,\n )\n return [1, 'ellipsis', ...middlePages, 'ellipsis', total]\n}\n\n/* ------------------------------------------------------------------ */\n/* PaginationNav — controlled convenience wrapper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Props for PaginationNav — a fully self-contained controlled pagination component that renders\n * Previous / page numbers (with ellipsis) / Next — using `generatePagination` internally.\n *\n * **1-indexed:** `currentPage` starts at 1 (not 0). `onPageChange` also receives 1-indexed values.\n *\n * **`siblingCount`:** Number of page buttons shown on each side of the current page (default 1).\n * A wider `siblingCount` shows more page buttons before switching to ellipsis.\n *\n * @example\n * // Basic controlled pagination:\n * <PaginationNav\n * totalPages={24}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * />\n *\n * @example\n * // Wider sibling range for a results grid (shows more page context):\n * <PaginationNav\n * totalPages={100}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * siblingCount={2}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface PaginationNavProps\n extends React.HTMLAttributes<HTMLElement> {\n /** Total number of pages */\n totalPages: number\n /** Current active page (1-indexed) */\n currentPage: number\n /** Called when the user requests a different page */\n onPageChange: (page: number) => void\n /** Number of sibling page buttons shown on each side of the current page (default: 1) */\n siblingCount?: number\n}\n\nconst PaginationNav = React.forwardRef<HTMLElement, PaginationNavProps>(\n (\n {\n totalPages,\n currentPage,\n onPageChange,\n siblingCount = 1,\n className,\n ...props\n },\n ref,\n ) => {\n const pages = generatePagination(currentPage, totalPages, siblingCount)\n\n return (\n <PaginationRoot ref={ref} className={className} {...props}>\n <PaginationContent>\n <PaginationItem>\n <PaginationPrevious\n onClick={() => onPageChange(Math.max(1, currentPage - 1))}\n disabled={currentPage <= 1}\n />\n </PaginationItem>\n\n {pages.map((page, i) =>\n page === 'ellipsis' ? (\n <PaginationItem key={`e${i}`}>\n <PaginationEllipsis />\n </PaginationItem>\n ) : (\n <PaginationItem key={page}>\n <PaginationLink\n isActive={page === currentPage}\n onClick={() => onPageChange(page)}\n >\n {page}\n </PaginationLink>\n </PaginationItem>\n ),\n )}\n\n <PaginationItem>\n <PaginationNext\n onClick={() =>\n onPageChange(Math.min(totalPages, currentPage + 1))\n }\n disabled={currentPage >= totalPages}\n />\n </PaginationItem>\n </PaginationContent>\n </PaginationRoot>\n )\n },\n)\nPaginationNav.displayName = 'PaginationNav'\n\nexport {\n generatePagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNav,\n PaginationNext,\n PaginationPrevious,\n PaginationRoot,\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"progress-ring.js","names":[],"sources":["../../src/ui/progress-ring.tsx"],"sourcesContent":["'use client'\n\nimport { animate, motion, useMotionValue, useReducedMotion,useTransform } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst colorMap: Record<string, string> = {\n default: 'var(--color-accent-9)',\n success: 'var(--color-success-9)',\n warning: 'var(--color-warning-9)',\n error: 'var(--color-error-9)',\n info: 'var(--color-info-9)',\n}\n\nconst sizeConfig = {\n sm: { size: 32, strokeWidth: 3, fontSize: 'text-ds-xs' },\n md: { size: 48, strokeWidth: 3.5, fontSize: 'text-ds-sm' },\n lg: { size: 64, strokeWidth: 4, fontSize: 'text-ds-md' },\n} as const\n\n/**\n * A circular progress indicator with optional label and animated fill.\n *\n * @example\n * <ProgressRing value={75} />\n * <ProgressRing value={3} max={12} size=\"lg\" color=\"warning\" showValue />\n */\nexport interface ProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n /** Current progress value */\n value: number\n /** Maximum value @default 100 */\n max?: number\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n /** @default 'default' */\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n /** Show percentage text in center */\n showValue?: boolean\n /** Accessible label */\n label?: string\n}\n\nconst ProgressRing = React.forwardRef<SVGSVGElement, ProgressRingProps>(\n ({ value, max = 100, size = 'md', color = 'default', showValue = false, label, className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const radius = (config.size - config.strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max(value / max, 0), 1)\n const offset = circumference * (1 - progress)\n const center = config.size / 2\n const percentage = Math.round(progress * 100)\n\n // Animated counter — drives from 0 → target percentage in sync with the ring fill\n const motionVal = useMotionValue(0)\n const displayValue = useTransform(motionVal, (v) => `${Math.round(v)}%`)\n\n React.useEffect(() => {\n const controls = animate(motionVal, progress * 100, prefersReducedMotion\n ? { type: 'tween', duration: 0 }\n /* Intentionally slower than springs.gentle (200/25/0.8) for smooth ring fill */\n : { stiffness: 100, damping: 30, type: 'spring' },\n )\n return () => controls.stop()\n }, [progress, motionVal, prefersReducedMotion])\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label ?? `${percentage}% progress`}\n className={cn('shrink-0', className)}\n {...props}\n >\n {/* Track */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-raised-hover)\"\n strokeWidth={config.strokeWidth}\n />\n {/* Value */}\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[color]}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n {showValue && (\n <motion.text\n x={center}\n y={center}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(config.fontSize, 'fill-surface-fg font-sans font-semibold')}\n >\n {displayValue}\n </motion.text>\n )}\n </svg>\n )\n },\n)\nProgressRing.displayName = 'ProgressRing'\n\n/**\n * Multi-ring progress display (Activity Ring style).\n *\n * @example\n * <MultiProgressRing rings={[\n * { value: 80, color: 'error', label: 'Move' },\n * { value: 60, color: 'success', label: 'Exercise' },\n * ]} size=\"lg\" />\n */\nexport interface MultiProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n rings: Array<{\n value: number\n max?: number\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n label?: string\n }>\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst MultiProgressRing = React.forwardRef<SVGSVGElement, MultiProgressRingProps>(\n ({ rings, size = 'md', className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const center = config.size / 2\n const gap = config.strokeWidth + 2\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"group\"\n aria-label=\"Progress rings\"\n className={cn('shrink-0', className)}\n {...props}\n >\n {rings.map((ring, i) => {\n const radius = (config.size - config.strokeWidth) / 2 - i * gap\n if (radius <= 0) return null\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max((ring.value) / (ring.max ?? 100), 0), 1)\n const offset = circumference * (1 - progress)\n\n return (\n <React.Fragment key={i}>\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-raised-hover)\"\n strokeWidth={config.strokeWidth}\n />\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[ring.color ?? 'default']}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n </React.Fragment>\n )\n })}\n </svg>\n )\n },\n)\nMultiProgressRing.displayName = 'MultiProgressRing'\n\nexport { MultiProgressRing,ProgressRing }\n"],"mappings":"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"}
1
+ {"version":3,"file":"progress-ring.js","names":[],"sources":["../../src/ui/progress-ring.tsx"],"sourcesContent":["'use client'\n\nimport { animate, motion, useMotionValue, useReducedMotion,useTransform } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst colorMap: Record<string, string> = {\n default: 'var(--color-accent-9)',\n success: 'var(--color-success-9)',\n warning: 'var(--color-warning-9)',\n error: 'var(--color-error-9)',\n info: 'var(--color-info-9)',\n}\n\nconst sizeConfig = {\n sm: { size: 32, strokeWidth: 3, fontSize: 'text-ds-xs' },\n md: { size: 48, strokeWidth: 3.5, fontSize: 'text-ds-sm' },\n lg: { size: 64, strokeWidth: 4, fontSize: 'text-ds-md' },\n} as const\n\n/**\n * A circular progress indicator with optional label and animated fill.\n *\n * @example\n * <ProgressRing value={75} />\n * <ProgressRing value={3} max={12} size=\"lg\" color=\"warning\" showValue />\n */\nexport interface ProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n /** Current progress value */\n value: number\n /** Maximum value @default 100 */\n max?: number\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n /** @default 'default' */\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n /** Show percentage text in center */\n showValue?: boolean\n /** Accessible label */\n label?: string\n}\n\nconst ProgressRing = React.forwardRef<SVGSVGElement, ProgressRingProps>(\n ({ value, max = 100, size = 'md', color = 'default', showValue = false, label, className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const radius = (config.size - config.strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max(value / max, 0), 1)\n const offset = circumference * (1 - progress)\n const center = config.size / 2\n const percentage = Math.round(progress * 100)\n\n // Animated counter — drives from 0 → target percentage in sync with the ring fill\n const motionVal = useMotionValue(0)\n const displayValue = useTransform(motionVal, (v) => `${Math.round(v)}%`)\n\n React.useEffect(() => {\n const controls = animate(motionVal, progress * 100, prefersReducedMotion\n ? { type: 'tween', duration: 0 }\n /* Intentionally slower than springs.gentle (200/25/0.8) for smooth ring fill */\n : { stiffness: 100, damping: 30, type: 'spring' },\n )\n return () => controls.stop()\n }, [progress, motionVal, prefersReducedMotion])\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label ?? `${percentage}% progress`}\n className={cn('shrink-0', className)}\n {...props}\n >\n {/* Track */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-raised-hover)\"\n strokeWidth={config.strokeWidth}\n />\n {/* Value */}\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[color]}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n {showValue && (\n <motion.text\n x={center}\n y={center}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(config.fontSize, 'fill-surface-fg font-sans font-semibold')}\n >\n {displayValue}\n </motion.text>\n )}\n </svg>\n )\n },\n)\nProgressRing.displayName = 'ProgressRing'\n\n/**\n * Multi-ring progress display (Activity Ring style).\n *\n * @example\n * <MultiProgressRing rings={[\n * { value: 80, color: 'error', label: 'Move' },\n * { value: 60, color: 'success', label: 'Exercise' },\n * ]} size=\"lg\" />\n */\nexport interface MultiProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n rings: Array<{\n value: number\n max?: number\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n label?: string\n }>\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst MultiProgressRing = React.forwardRef<SVGSVGElement, MultiProgressRingProps>(\n ({ rings, size = 'md', className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const center = config.size / 2\n const gap = config.strokeWidth + 2\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"group\"\n aria-label=\"Progress rings\"\n className={cn('shrink-0', className)}\n {...props}\n >\n {rings.map((ring, i) => {\n const radius = (config.size - config.strokeWidth) / 2 - i * gap\n if (radius <= 0) return null\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max((ring.value) / (ring.max ?? 100), 0), 1)\n const offset = circumference * (1 - progress)\n\n return (\n <React.Fragment key={i}>\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-raised-hover)\"\n strokeWidth={config.strokeWidth}\n />\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[ring.color ?? 'default']}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n </React.Fragment>\n )\n })}\n </svg>\n )\n },\n)\nMultiProgressRing.displayName = 'MultiProgressRing'\n\nexport { MultiProgressRing,ProgressRing }\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","names":[],"sources":["../../src/ui/progress.tsx"],"sourcesContent":["'use client'\n\nimport * as ProgressPrimitive from '@primitives/react-progress'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/* ---------------------------------------------------------------------------\n * Progress — a linear progress bar.\n *\n * Two ways to use it:\n * 1. Smart all-in-one `<Progress value={70} />` — covers the common cases\n * (value, size, color, label, %-value, auto-color, indeterminate, segments).\n * 2. Compound parts `<Progress.Root>/<Progress.Track>/<Progress.Indicator>` etc.\n * — full layout control, borrowed from Ark UI / Chakra's structure, with\n * Mantine-style `<Progress.Segment>` for multi-colour bars.\n *\n * The compound parts share a context so `value`/`max`/`size` are set once on\n * `Root` and read by Track/Indicator/Segment/Value.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressSize = 'sm' | 'md' | 'lg'\nexport type ProgressColor = 'accent' | 'success' | 'warning' | 'error'\n\nexport const progressTrackVariants = cva(\n 'relative w-full overflow-hidden rounded-pill bg-surface-raised',\n {\n variants: { size: { sm: 'h-1', md: 'h-2', lg: 'h-3' } },\n defaultVariants: { size: 'md' },\n },\n)\n\nconst COLOR_FILL: Record<ProgressColor, string> = {\n accent: 'bg-accent-9',\n success: 'bg-success-9',\n warning: 'bg-warning-9',\n error: 'bg-error-9',\n}\n\nexport const progressIndicatorVariants = cva(\n 'h-full transition-[width] duration-moderate-02 ease-expressive-standard',\n {\n variants: { color: COLOR_FILL },\n defaultVariants: { color: 'accent' },\n },\n)\n\n/** Auto-color by value: 0–59 accent, 60–84 warning, 85–100 success, >100 error. */\nfunction autoColorFor(value: number | null | undefined): ProgressColor {\n if (value == null) return 'accent'\n if (value > 100) return 'error'\n if (value >= 85) return 'success'\n if (value >= 60) return 'warning'\n return 'accent'\n}\n\nconst clampPct = (value: number, max: number) =>\n Math.max(0, Math.min(100, (value / max) * 100))\n\n/* ---------------------------------------------------------------------------\n * Context — set once on Root, read by Track / Indicator / Segment / Value.\n * ------------------------------------------------------------------------ */\n\ninterface ProgressContextValue {\n value: number | null\n max: number\n size: ProgressSize\n indeterminate: boolean\n}\n\nconst ProgressContext = React.createContext<ProgressContextValue | null>(null)\n\nfunction useProgressContext(part: string): ProgressContextValue {\n const ctx = React.useContext(ProgressContext)\n if (!ctx) {\n throw new Error(`<Progress.${part}> must be rendered inside <Progress.Root>.`)\n }\n return ctx\n}\n\n/* ---------------------------------------------------------------------------\n * Progress.Root — layout container + context. NOT the progressbar itself\n * (that's Track) so labels/value can sit outside the bar (Ark UI model).\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n /** Scale maximum. @default 100 */\n max?: number\n /** Track thickness. @default 'md' */\n size?: ProgressSize\n}\n\nconst ProgressRoot = React.forwardRef<HTMLDivElement, ProgressRootProps>(\n ({ value = null, max = 100, size = 'md', className, children, ...props }, ref) => {\n const ctx = React.useMemo<ProgressContextValue>(\n () => ({ value, max, size, indeterminate: value == null }),\n [value, max, size],\n )\n return (\n <ProgressContext.Provider value={ctx}>\n <div ref={ref} className={cn('flex w-full items-center gap-ds-03', className)} {...props}>\n {children}\n </div>\n </ProgressContext.Provider>\n )\n },\n)\nProgressRoot.displayName = 'Progress.Root'\n\n/* ---------------------------------------------------------------------------\n * Progress.Track — the aria progressbar + track visual. Holds Indicator/Segment.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressTrackProps = React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n\nconst ProgressTrack = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n ProgressTrackProps\n>(({ className, children, ...props }, ref) => {\n const { value, max, size, indeterminate } = useProgressContext('Track')\n // Accessible name comes from the consumer's aria-label / aria-labelledby (spread\n // via ...props) — no auto-wiring, so a Track never carries a dangling reference.\n return (\n <ProgressPrimitive.Root\n ref={ref}\n value={indeterminate ? null : value}\n max={max}\n className={cn(progressTrackVariants({ size }), 'flex-1', className)}\n {...props}\n >\n {children}\n </ProgressPrimitive.Root>\n )\n})\nProgressTrack.displayName = 'Progress.Track'\n\n/* ---------------------------------------------------------------------------\n * Progress.Indicator — single fill. Determinate width from context, or the\n * indeterminate sweep animation when Root has no value.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Fill colour. Omit to auto-colour by value. */\n color?: ProgressColor\n /** Force auto-colour even when `color` is unset. @default true when color unset */\n autoColor?: boolean\n}\n\nconst ProgressIndicator = React.forwardRef<HTMLDivElement, ProgressIndicatorProps>(\n ({ color, autoColor, className, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Indicator')\n const resolved = color ?? (autoColor !== false ? autoColorFor(value) : 'accent')\n\n if (indeterminate) {\n return (\n <div\n ref={ref}\n className={cn(\n progressIndicatorVariants({ color: resolved }),\n 'w-2/5 animate-progress-indeterminate motion-reduce:animate-none',\n className,\n )}\n {...props}\n />\n )\n }\n return (\n <motion.div\n ref={ref}\n className={cn(progressIndicatorVariants({ color: resolved }), 'transition-colors', className)}\n initial={false}\n animate={{ width: `${clampPct(value ?? 0, max)}%` }}\n transition={springs.smooth}\n {...(props as React.ComponentProps<typeof motion.div>)}\n />\n )\n },\n)\nProgressIndicator.displayName = 'Progress.Indicator'\n\n/* ---------------------------------------------------------------------------\n * Progress.Segment — one slice of a multi-segment bar (Mantine-style). Place\n * several inside a Track. Widths are each segment's value as a % of max.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressSegmentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** This segment's portion of `max`. */\n value: number\n color?: ProgressColor\n}\n\nconst ProgressSegment = React.forwardRef<HTMLDivElement, ProgressSegmentProps>(\n ({ value, color = 'accent', className, style, ...props }, ref) => {\n const { max } = useProgressContext('Segment')\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className={cn('h-full first:rounded-l-pill last:rounded-r-pill', COLOR_FILL[color], className)}\n style={{ width: `${clampPct(value, max)}%`, ...style }}\n {...props}\n />\n )\n },\n)\nProgressSegment.displayName = 'Progress.Segment'\n\n/* ---------------------------------------------------------------------------\n * Progress.Label — descriptive text, associated with the bar via aria.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressLabelProps = React.HTMLAttributes<HTMLSpanElement>\n\nconst ProgressLabel = React.forwardRef<HTMLSpanElement, ProgressLabelProps>(\n ({ className, ...props }, ref) => {\n useProgressContext('Label')\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-ds-sm font-medium text-surface-fg', className)}\n {...props}\n />\n )\n },\n)\nProgressLabel.displayName = 'Progress.Label'\n\n/* ---------------------------------------------------------------------------\n * Progress.Value — the \"{n}%\" readout. Custom content via children or `format`.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressValueProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** Format the percentage. Default: `${round(pct)}%`. */\n format?: (pct: number, value: number | null, max: number) => React.ReactNode\n children?: React.ReactNode\n}\n\nconst ProgressValue = React.forwardRef<HTMLSpanElement, ProgressValueProps>(\n ({ className, format, children, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Value')\n const pct = indeterminate ? 0 : clampPct(value ?? 0, max)\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-ds-xs text-surface-fg-muted tabular-nums', className)}\n {...props}\n >\n {children ?? (indeterminate ? '' : format ? format(pct, value, max) : `${Math.round(pct)}%`)}\n </span>\n )\n },\n)\nProgressValue.displayName = 'Progress.Value'\n\n/* ---------------------------------------------------------------------------\n * Progress — smart all-in-one. Composes the parts for the common cases.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof progressTrackVariants> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n max?: number\n /** Fill colour. Omit + set `autoColor` to colour by value. */\n color?: ProgressColor\n /** Auto-colour the fill by value (0–59 accent · 60–84 warning · 85–100 success · >100 error). @default false */\n autoColor?: boolean\n /** Descriptive label rendered before the bar. */\n label?: React.ReactNode\n /** Show the `{n}%` readout after the bar. */\n showValue?: boolean\n /** Multi-segment bar: each slice is `value` (portion of max) + `color`. Overrides the single indicator. */\n segments?: Array<{ value: number; color?: ProgressColor }>\n /** Class for the Track element. */\n trackClassName?: string\n /** Class for the single Indicator (ignored when `segments` is set). */\n indicatorClassName?: string\n}\n\nconst ProgressBase = React.forwardRef<HTMLDivElement, ProgressProps>(\n (\n {\n value = null, max = 100, size, color, autoColor, label, showValue, segments,\n trackClassName, indicatorClassName, className,\n 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...props\n },\n ref,\n ) => {\n const labelId = React.useId()\n const hasLabel = label != null\n return (\n <ProgressRoot ref={ref} value={value} max={max} size={size ?? 'md'} className={className} {...props}>\n {hasLabel && <ProgressLabel id={labelId}>{label}</ProgressLabel>}\n <ProgressTrack\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby ?? (hasLabel ? labelId : undefined)}\n className={cn(segments && 'flex', trackClassName)}\n >\n {segments\n ? segments.map((s, i) => <ProgressSegment key={i} value={s.value} color={s.color} />)\n : <ProgressIndicator color={color} autoColor={autoColor} className={indicatorClassName} />}\n </ProgressTrack>\n {showValue && value != null && <ProgressValue />}\n </ProgressRoot>\n )\n },\n)\nProgressBase.displayName = 'Progress'\n\nconst Progress = Object.assign(ProgressBase, {\n Root: ProgressRoot,\n Track: ProgressTrack,\n Indicator: ProgressIndicator,\n Segment: ProgressSegment,\n Label: ProgressLabel,\n Value: ProgressValue,\n})\n\nexport {\n Progress,\n ProgressIndicator,\n ProgressLabel,\n ProgressRoot,\n ProgressSegment,\n ProgressTrack,\n ProgressValue,\n}\n"],"mappings":";;;;;;;;;AA2BA,IAAa,IAAwB,EACnC,kEACA;CACE,UAAU,EAAE,MAAM;EAAE,IAAI;EAAO,IAAI;EAAO,IAAI;EAAO,EAAE;CACvD,iBAAiB,EAAE,MAAM,MAAM;CAChC,CACF,EAEK,IAA4C;CAChD,QAAQ;CACR,SAAS;CACT,SAAS;CACT,OAAO;CACR,EAEY,IAA4B,EACvC,2EACA;CACE,UAAU,EAAE,OAAO,GAAY;CAC/B,iBAAiB,EAAE,OAAO,UAAU;CACrC,CACF;AAGD,SAAS,EAAa,GAAiD;AAKrE,QAJI,KAAS,OAAa,WACtB,IAAQ,MAAY,UACpB,KAAS,KAAW,YACpB,KAAS,KAAW,YACjB;;AAGT,IAAM,KAAY,GAAe,MAC/B,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,IAAQ,IAAO,IAAI,CAAC,EAa3C,IAAkB,EAAM,cAA2C,KAAK;AAE9E,SAAS,EAAmB,GAAoC;CAC9D,IAAM,IAAM,EAAM,WAAW,EAAgB;AAC7C,KAAI,CAAC,EACH,OAAU,MAAM,aAAa,EAAK,4CAA4C;AAEhF,QAAO;;AAiBT,IAAM,IAAe,EAAM,YACxB,EAAE,WAAQ,MAAM,SAAM,KAAK,UAAO,MAAM,cAAW,aAAU,GAAG,KAAS,MAAQ;CAChF,IAAM,IAAM,EAAM,eACT;EAAE;EAAO;EAAK;EAAM,eAAe,KAAS;EAAM,GACzD;EAAC;EAAO;EAAK;EAAK,CACnB;AACD,QACE,kBAAC,EAAgB,UAAjB;EAA0B,OAAO;YAC/B,kBAAC,OAAD;GAAU;GAAK,WAAW,EAAG,sCAAsC,EAAU;GAAE,GAAI;GAChF;GACG,CAAA;EACmB,CAAA;EAGhC;AACD,EAAa,cAAc;AAQ3B,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,aAAU,GAAG,KAAS,MAAQ;CAC5C,IAAM,EAAE,UAAO,QAAK,SAAM,qBAAkB,EAAmB,QAAQ;AAGvE,QACE,kBAAC,GAAD;EACO;EACL,OAAO,IAAgB,OAAO;EACzB;EACL,WAAW,EAAG,EAAsB,EAAE,SAAM,CAAC,EAAE,UAAU,EAAU;EACnE,GAAI;EAEH;EACsB,CAAA;EAE3B;AACF,EAAc,cAAc;AAc5B,IAAM,IAAoB,EAAM,YAC7B,EAAE,UAAO,cAAW,cAAW,GAAG,KAAS,MAAQ;CAClD,IAAM,EAAE,UAAO,QAAK,qBAAkB,EAAmB,YAAY,EAC/D,IAAW,MAAU,MAAc,KAA8B,WAAtB,EAAa,EAAM;AAepE,QAbI,IAEA,kBAAC,OAAD;EACO;EACL,WAAW,EACT,EAA0B,EAAE,OAAO,GAAU,CAAC,EAC9C,mEACA,EACD;EACD,GAAI;EACJ,CAAA,GAIJ,kBAAC,EAAO,KAAR;EACO;EACL,WAAW,EAAG,EAA0B,EAAE,OAAO,GAAU,CAAC,EAAE,qBAAqB,EAAU;EAC7F,SAAS;EACT,SAAS,EAAE,OAAO,GAAG,EAAS,KAAS,GAAG,EAAI,CAAC,IAAI;EACnD,YAAY,EAAQ;EACpB,GAAK;EACL,CAAA;EAGP;AACD,EAAkB,cAAc;AAahC,IAAM,IAAkB,EAAM,YAC3B,EAAE,UAAO,WAAQ,UAAU,cAAW,UAAO,GAAG,KAAS,MAAQ;CAChE,IAAM,EAAE,WAAQ,EAAmB,UAAU;AAC7C,QACE,kBAAC,OAAD;EACO;EACL,eAAY;EACZ,WAAW,EAAG,mDAAmD,EAAW,IAAQ,EAAU;EAC9F,OAAO;GAAE,OAAO,GAAG,EAAS,GAAO,EAAI,CAAC;GAAI,GAAG;GAAO;EACtD,GAAI;EACJ,CAAA;EAGP;AACD,EAAgB,cAAc;AAQ9B,IAAM,IAAgB,EAAM,YACzB,EAAE,cAAW,GAAG,KAAS,OACxB,EAAmB,QAAQ,EAEzB,kBAAC,QAAD;CACO;CACL,WAAW,EAAG,mDAAmD,EAAU;CAC3E,GAAI;CACJ,CAAA,EAGP;AACD,EAAc,cAAc;AAY5B,IAAM,IAAgB,EAAM,YACzB,EAAE,cAAW,WAAQ,aAAU,GAAG,KAAS,MAAQ;CAClD,IAAM,EAAE,UAAO,QAAK,qBAAkB,EAAmB,QAAQ,EAC3D,IAAM,IAAgB,IAAI,EAAS,KAAS,GAAG,EAAI;AACzD,QACE,kBAAC,QAAD;EACO;EACL,WAAW,EAAG,0DAA0D,EAAU;EAClF,GAAI;YAEH,MAAa,IAAgB,KAAK,IAAS,EAAO,GAAK,GAAO,EAAI,GAAG,GAAG,KAAK,MAAM,EAAI,CAAC;EACpF,CAAA;EAGZ;AACD,EAAc,cAAc;AA4B5B,IAAM,IAAe,EAAM,YAEvB,EACE,WAAQ,MAAM,SAAM,KAAK,SAAM,UAAO,cAAW,UAAO,cAAW,aACnE,mBAAgB,uBAAoB,cACpC,cAAc,GAAW,mBAAmB,GAAgB,GAAG,KAEjE,MACG;CACH,IAAM,IAAU,EAAM,OAAO,EACvB,IAAW,KAAS;AAC1B,QACE,kBAAC,GAAD;EAAmB;EAAY;EAAY;EAAK,MAAM,KAAQ;EAAiB;EAAW,GAAI;YAA9F;GACG,KAAY,kBAAC,GAAD;IAAe,IAAI;cAAU;IAAsB,CAAA;GAChE,kBAAC,GAAD;IACE,cAAY;IACZ,mBAAiB,MAAmB,IAAW,IAAU,KAAA;IACzD,WAAW,EAAG,KAAY,QAAQ,EAAe;cAEhD,IACG,EAAS,KAAK,GAAG,MAAM,kBAAC,GAAD;KAAyB,OAAO,EAAE;KAAO,OAAO,EAAE;KAAS,EAArC,EAAqC,CAAC,GACnF,kBAAC,GAAD;KAA0B;KAAkB;KAAW,WAAW;KAAsB,CAAA;IAC9E,CAAA;GACf,KAAa,KAAS,QAAQ,kBAAC,GAAD,EAAiB,CAAA;GACnC;;EAGpB;AACD,EAAa,cAAc;AAE3B,IAAM,IAAW,OAAO,OAAO,GAAc;CAC3C,MAAM;CACN,OAAO;CACP,WAAW;CACX,SAAS;CACT,OAAO;CACP,OAAO;CACR,CAAC"}
1
+ {"version":3,"file":"progress.js","names":[],"sources":["../../src/ui/progress.tsx"],"sourcesContent":["'use client'\n\nimport * as ProgressPrimitive from '@primitives/react-progress'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/* ---------------------------------------------------------------------------\n * Progress — a linear progress bar.\n *\n * Two ways to use it:\n * 1. Smart all-in-one `<Progress value={70} />` — covers the common cases\n * (value, size, color, label, %-value, auto-color, indeterminate, segments).\n * 2. Compound parts `<Progress.Root>/<Progress.Track>/<Progress.Indicator>` etc.\n * — full layout control, borrowed from Ark UI / Chakra's structure, with\n * Mantine-style `<Progress.Segment>` for multi-colour bars.\n *\n * The compound parts share a context so `value`/`max`/`size` are set once on\n * `Root` and read by Track/Indicator/Segment/Value.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressSize = 'sm' | 'md' | 'lg'\nexport type ProgressColor = 'accent' | 'success' | 'warning' | 'error'\n\nexport const progressTrackVariants = cva(\n 'relative w-full overflow-hidden rounded-pill bg-surface-raised',\n {\n variants: { size: { sm: 'h-1', md: 'h-2', lg: 'h-3' } },\n defaultVariants: { size: 'md' },\n },\n)\n\nconst COLOR_FILL: Record<ProgressColor, string> = {\n accent: 'bg-accent-9',\n success: 'bg-success-9',\n warning: 'bg-warning-9',\n error: 'bg-error-9',\n}\n\nexport const progressIndicatorVariants = cva(\n 'h-full transition-[width] duration-moderate-02 ease-expressive-standard',\n {\n variants: { color: COLOR_FILL },\n defaultVariants: { color: 'accent' },\n },\n)\n\n/** Auto-color by value: 0–59 accent, 60–84 warning, 85–100 success, >100 error. */\nfunction autoColorFor(value: number | null | undefined): ProgressColor {\n if (value == null) return 'accent'\n if (value > 100) return 'error'\n if (value >= 85) return 'success'\n if (value >= 60) return 'warning'\n return 'accent'\n}\n\nconst clampPct = (value: number, max: number) =>\n Math.max(0, Math.min(100, (value / max) * 100))\n\n/* ---------------------------------------------------------------------------\n * Context — set once on Root, read by Track / Indicator / Segment / Value.\n * ------------------------------------------------------------------------ */\n\ninterface ProgressContextValue {\n value: number | null\n max: number\n size: ProgressSize\n indeterminate: boolean\n}\n\nconst ProgressContext = React.createContext<ProgressContextValue | null>(null)\n\nfunction useProgressContext(part: string): ProgressContextValue {\n const ctx = React.useContext(ProgressContext)\n if (!ctx) {\n throw new Error(`<Progress.${part}> must be rendered inside <Progress.Root>.`)\n }\n return ctx\n}\n\n/* ---------------------------------------------------------------------------\n * Progress.Root — layout container + context. NOT the progressbar itself\n * (that's Track) so labels/value can sit outside the bar (Ark UI model).\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n /** Scale maximum. @default 100 */\n max?: number\n /** Track thickness. @default 'md' */\n size?: ProgressSize\n}\n\nconst ProgressRoot = React.forwardRef<HTMLDivElement, ProgressRootProps>(\n ({ value = null, max = 100, size = 'md', className, children, ...props }, ref) => {\n const ctx = React.useMemo<ProgressContextValue>(\n () => ({ value, max, size, indeterminate: value == null }),\n [value, max, size],\n )\n return (\n <ProgressContext.Provider value={ctx}>\n <div ref={ref} className={cn('flex w-full items-center gap-ds-03', className)} {...props}>\n {children}\n </div>\n </ProgressContext.Provider>\n )\n },\n)\nProgressRoot.displayName = 'Progress.Root'\n\n/* ---------------------------------------------------------------------------\n * Progress.Track — the aria progressbar + track visual. Holds Indicator/Segment.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressTrackProps = React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n\nconst ProgressTrack = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n ProgressTrackProps\n>(({ className, children, ...props }, ref) => {\n const { value, max, size, indeterminate } = useProgressContext('Track')\n // Accessible name comes from the consumer's aria-label / aria-labelledby (spread\n // via ...props) — no auto-wiring, so a Track never carries a dangling reference.\n return (\n <ProgressPrimitive.Root\n ref={ref}\n value={indeterminate ? null : value}\n max={max}\n className={cn(progressTrackVariants({ size }), 'flex-1', className)}\n {...props}\n >\n {children}\n </ProgressPrimitive.Root>\n )\n})\nProgressTrack.displayName = 'Progress.Track'\n\n/* ---------------------------------------------------------------------------\n * Progress.Indicator — single fill. Determinate width from context, or the\n * indeterminate sweep animation when Root has no value.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Fill colour. Omit to auto-colour by value. */\n color?: ProgressColor\n /** Force auto-colour even when `color` is unset. @default true when color unset */\n autoColor?: boolean\n}\n\nconst ProgressIndicator = React.forwardRef<HTMLDivElement, ProgressIndicatorProps>(\n ({ color, autoColor, className, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Indicator')\n const resolved = color ?? (autoColor !== false ? autoColorFor(value) : 'accent')\n\n if (indeterminate) {\n return (\n <div\n ref={ref}\n className={cn(\n progressIndicatorVariants({ color: resolved }),\n 'w-2/5 animate-progress-indeterminate motion-reduce:animate-none',\n className,\n )}\n {...props}\n />\n )\n }\n return (\n <motion.div\n ref={ref}\n className={cn(progressIndicatorVariants({ color: resolved }), 'transition-colors', className)}\n initial={false}\n animate={{ width: `${clampPct(value ?? 0, max)}%` }}\n transition={springs.smooth}\n {...(props as React.ComponentProps<typeof motion.div>)}\n />\n )\n },\n)\nProgressIndicator.displayName = 'Progress.Indicator'\n\n/* ---------------------------------------------------------------------------\n * Progress.Segment — one slice of a multi-segment bar (Mantine-style). Place\n * several inside a Track. Widths are each segment's value as a % of max.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressSegmentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** This segment's portion of `max`. */\n value: number\n color?: ProgressColor\n}\n\nconst ProgressSegment = React.forwardRef<HTMLDivElement, ProgressSegmentProps>(\n ({ value, color = 'accent', className, style, ...props }, ref) => {\n const { max } = useProgressContext('Segment')\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className={cn('h-full first:rounded-l-pill last:rounded-r-pill', COLOR_FILL[color], className)}\n style={{ width: `${clampPct(value, max)}%`, ...style }}\n {...props}\n />\n )\n },\n)\nProgressSegment.displayName = 'Progress.Segment'\n\n/* ---------------------------------------------------------------------------\n * Progress.Label — descriptive text, associated with the bar via aria.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressLabelProps = React.HTMLAttributes<HTMLSpanElement>\n\nconst ProgressLabel = React.forwardRef<HTMLSpanElement, ProgressLabelProps>(\n ({ className, ...props }, ref) => {\n useProgressContext('Label')\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-ds-sm font-medium text-surface-fg', className)}\n {...props}\n />\n )\n },\n)\nProgressLabel.displayName = 'Progress.Label'\n\n/* ---------------------------------------------------------------------------\n * Progress.Value — the \"{n}%\" readout. Custom content via children or `format`.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressValueProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** Format the percentage. Default: `${round(pct)}%`. */\n format?: (pct: number, value: number | null, max: number) => React.ReactNode\n children?: React.ReactNode\n}\n\nconst ProgressValue = React.forwardRef<HTMLSpanElement, ProgressValueProps>(\n ({ className, format, children, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Value')\n const pct = indeterminate ? 0 : clampPct(value ?? 0, max)\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-ds-xs text-surface-fg-muted tabular-nums', className)}\n {...props}\n >\n {children ?? (indeterminate ? '' : format ? format(pct, value, max) : `${Math.round(pct)}%`)}\n </span>\n )\n },\n)\nProgressValue.displayName = 'Progress.Value'\n\n/* ---------------------------------------------------------------------------\n * Progress — smart all-in-one. Composes the parts for the common cases.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof progressTrackVariants> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n max?: number\n /** Fill colour. Omit + set `autoColor` to colour by value. */\n color?: ProgressColor\n /** Auto-colour the fill by value (0–59 accent · 60–84 warning · 85–100 success · >100 error). @default false */\n autoColor?: boolean\n /** Descriptive label rendered before the bar. */\n label?: React.ReactNode\n /** Show the `{n}%` readout after the bar. */\n showValue?: boolean\n /** Multi-segment bar: each slice is `value` (portion of max) + `color`. Overrides the single indicator. */\n segments?: Array<{ value: number; color?: ProgressColor }>\n /** Class for the Track element. */\n trackClassName?: string\n /** Class for the single Indicator (ignored when `segments` is set). */\n indicatorClassName?: string\n}\n\nconst ProgressBase = React.forwardRef<HTMLDivElement, ProgressProps>(\n (\n {\n value = null, max = 100, size, color, autoColor, label, showValue, segments,\n trackClassName, indicatorClassName, className,\n 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...props\n },\n ref,\n ) => {\n const labelId = React.useId()\n const hasLabel = label != null\n return (\n <ProgressRoot ref={ref} value={value} max={max} size={size ?? 'md'} className={className} {...props}>\n {hasLabel && <ProgressLabel id={labelId}>{label}</ProgressLabel>}\n <ProgressTrack\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby ?? (hasLabel ? labelId : undefined)}\n className={cn(segments && 'flex', trackClassName)}\n >\n {segments\n ? segments.map((s, i) => <ProgressSegment key={i} value={s.value} color={s.color} />)\n : <ProgressIndicator color={color} autoColor={autoColor} className={indicatorClassName} />}\n </ProgressTrack>\n {showValue && value != null && <ProgressValue />}\n </ProgressRoot>\n )\n },\n)\nProgressBase.displayName = 'Progress'\n\nconst Progress = Object.assign(ProgressBase, {\n Root: ProgressRoot,\n Track: ProgressTrack,\n Indicator: ProgressIndicator,\n Segment: ProgressSegment,\n Label: ProgressLabel,\n Value: ProgressValue,\n})\n\nexport {\n Progress,\n ProgressIndicator,\n ProgressLabel,\n ProgressRoot,\n ProgressSegment,\n ProgressTrack,\n ProgressValue,\n}\n"],"mappings":"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"}