@devalok/shilp-sutra 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/AGENTS.md +151 -0
  2. package/MIGRATION.md +255 -0
  3. package/README.md +3 -0
  4. package/dist/_chunks/badge-group.js +76 -75
  5. package/dist/_chunks/badge-group.js.map +1 -1
  6. package/dist/_chunks/chart-container.js +50 -0
  7. package/dist/_chunks/chart-container.js.map +1 -0
  8. package/dist/_chunks/chat.js +236 -228
  9. package/dist/_chunks/chat.js.map +1 -1
  10. package/dist/_chunks/colors.js +30 -0
  11. package/dist/_chunks/colors.js.map +1 -0
  12. package/dist/_chunks/document-preview.js +2 -2
  13. package/dist/_chunks/document-preview.js.map +1 -1
  14. package/dist/_chunks/emoji-data.js +45 -0
  15. package/dist/_chunks/emoji-data.js.map +1 -0
  16. package/dist/_chunks/grid-lines.js +72 -0
  17. package/dist/_chunks/grid-lines.js.map +1 -0
  18. package/dist/_chunks/image-preview.js +2 -2
  19. package/dist/_chunks/image-preview.js.map +1 -1
  20. package/dist/_chunks/mention-suggestion.js +35 -263
  21. package/dist/_chunks/mention-suggestion.js.map +1 -1
  22. package/dist/_chunks/normalize-icon.js +18 -0
  23. package/dist/_chunks/normalize-icon.js.map +1 -0
  24. package/dist/_chunks/oauth-button.js +227 -0
  25. package/dist/_chunks/oauth-button.js.map +1 -0
  26. package/dist/_chunks/popover.js +3 -3
  27. package/dist/_chunks/popover.js.map +1 -1
  28. package/dist/_chunks/primitives.js +107 -107
  29. package/dist/_chunks/primitives.js.map +1 -1
  30. package/dist/_chunks/shared.js +5 -5
  31. package/dist/_chunks/shared.js.map +1 -1
  32. package/dist/_chunks/{text.js → success.js} +26 -63
  33. package/dist/_chunks/success.js.map +1 -0
  34. package/dist/_chunks/tiptap.js +1952 -1949
  35. package/dist/_chunks/tiptap.js.map +1 -1
  36. package/dist/_chunks/tooltip.js +58 -0
  37. package/dist/_chunks/tooltip.js.map +1 -0
  38. package/dist/_chunks/tree-view.js +101 -96
  39. package/dist/_chunks/tree-view.js.map +1 -1
  40. package/dist/_chunks/use-calendar.js +5 -5
  41. package/dist/_chunks/use-calendar.js.map +1 -1
  42. package/dist/ai/ai-command-provider.d.ts +3 -2
  43. package/dist/ai/ai-command-provider.d.ts.map +1 -1
  44. package/dist/ai/ai-command-provider.js.map +1 -1
  45. package/dist/ai/block-renderer.js +11 -9
  46. package/dist/ai/block-renderer.js.map +1 -1
  47. package/dist/ai/blocks/error.js +31 -0
  48. package/dist/ai/blocks/error.js.map +1 -0
  49. package/dist/ai/blocks/index.d.ts +0 -2
  50. package/dist/ai/blocks/index.d.ts.map +1 -1
  51. package/dist/ai/blocks/index.js +2 -2
  52. package/dist/ai/blocks/text.js +19 -0
  53. package/dist/ai/blocks/text.js.map +1 -0
  54. package/dist/ai/command-bar.d.ts.map +1 -1
  55. package/dist/ai/command-bar.js +198 -193
  56. package/dist/ai/command-bar.js.map +1 -1
  57. package/dist/ai/conversation.d.ts +2 -1
  58. package/dist/ai/conversation.d.ts.map +1 -1
  59. package/dist/ai/conversation.js +92 -87
  60. package/dist/ai/conversation.js.map +1 -1
  61. package/dist/ai/index.d.ts +0 -4
  62. package/dist/ai/index.d.ts.map +1 -1
  63. package/dist/ai/index.js +45 -46
  64. package/dist/ai/index.js.map +1 -1
  65. package/dist/composed/activity-feed.d.ts +2 -1
  66. package/dist/composed/activity-feed.d.ts.map +1 -1
  67. package/dist/composed/activity-feed.js +5 -5
  68. package/dist/composed/activity-feed.js.map +1 -1
  69. package/dist/composed/avatar-group.js +4 -4
  70. package/dist/composed/avatar-group.js.map +1 -1
  71. package/dist/composed/bulk-action-bar.d.ts +2 -2
  72. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  73. package/dist/composed/bulk-action-bar.js +12 -12
  74. package/dist/composed/bulk-action-bar.js.map +1 -1
  75. package/dist/composed/command-palette.d.ts +2 -1
  76. package/dist/composed/command-palette.d.ts.map +1 -1
  77. package/dist/composed/command-palette.js +106 -101
  78. package/dist/composed/command-palette.js.map +1 -1
  79. package/dist/composed/content-card.js +1 -1
  80. package/dist/composed/content-card.js.map +1 -1
  81. package/dist/composed/date-picker/index.js +747 -3
  82. package/dist/composed/date-picker/index.js.map +1 -0
  83. package/dist/composed/emoji-picker.js +4 -4
  84. package/dist/composed/emoji-picker.js.map +1 -1
  85. package/dist/composed/empty-state.d.ts +3 -3
  86. package/dist/composed/empty-state.d.ts.map +1 -1
  87. package/dist/composed/empty-state.js +40 -31
  88. package/dist/composed/empty-state.js.map +1 -1
  89. package/dist/composed/error-boundary.js +3 -3
  90. package/dist/composed/error-boundary.js.map +1 -1
  91. package/dist/composed/extensions/emoji-node.js +81 -0
  92. package/dist/composed/extensions/emoji-node.js.map +1 -0
  93. package/dist/composed/extensions/emoji-suggestion.js +117 -0
  94. package/dist/composed/extensions/emoji-suggestion.js.map +1 -0
  95. package/dist/composed/file-preview.js +498 -2
  96. package/dist/composed/file-preview.js.map +1 -0
  97. package/dist/composed/filter-bar.js +1 -1
  98. package/dist/composed/filter-bar.js.map +1 -1
  99. package/dist/composed/index.d.ts +0 -15
  100. package/dist/composed/index.d.ts.map +1 -1
  101. package/dist/composed/index.js +16 -24
  102. package/dist/composed/inline-edit.js +1 -1
  103. package/dist/composed/inline-edit.js.map +1 -1
  104. package/dist/composed/loading-skeleton.js +9 -9
  105. package/dist/composed/loading-skeleton.js.map +1 -1
  106. package/dist/composed/markdown-viewer.js +3 -3
  107. package/dist/composed/markdown-viewer.js.map +1 -1
  108. package/dist/composed/multi-select-popover.js +1 -1
  109. package/dist/composed/multi-select-popover.js.map +1 -1
  110. package/dist/composed/page-header.js +1 -1
  111. package/dist/composed/page-header.js.map +1 -1
  112. package/dist/composed/page-skeletons.js +15 -15
  113. package/dist/composed/page-skeletons.js.map +1 -1
  114. package/dist/composed/priority-indicator.js +3 -3
  115. package/dist/composed/priority-indicator.js.map +1 -1
  116. package/dist/composed/rich-chat-input.js +2073 -2
  117. package/dist/composed/rich-chat-input.js.map +1 -0
  118. package/dist/composed/rich-text-editor.js +75 -72
  119. package/dist/composed/rich-text-editor.js.map +1 -1
  120. package/dist/composed/schedule-view.js +3 -3
  121. package/dist/composed/schedule-view.js.map +1 -1
  122. package/dist/composed/status-badge.d.ts +3 -2
  123. package/dist/composed/status-badge.d.ts.map +1 -1
  124. package/dist/composed/status-badge.js +58 -53
  125. package/dist/composed/status-badge.js.map +1 -1
  126. package/dist/shell/app-command-palette.d.ts +2 -1
  127. package/dist/shell/app-command-palette.d.ts.map +1 -1
  128. package/dist/shell/app-command-palette.js.map +1 -1
  129. package/dist/shell/bottom-navbar.d.ts +3 -1
  130. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  131. package/dist/shell/bottom-navbar.js +94 -86
  132. package/dist/shell/bottom-navbar.js.map +1 -1
  133. package/dist/shell/command-registry.d.ts +2 -1
  134. package/dist/shell/command-registry.d.ts.map +1 -1
  135. package/dist/shell/command-registry.js.map +1 -1
  136. package/dist/shell/notification-center.js +8 -8
  137. package/dist/shell/notification-center.js.map +1 -1
  138. package/dist/shell/notification-preferences.js +1 -1
  139. package/dist/shell/notification-preferences.js.map +1 -1
  140. package/dist/shell/sidebar.d.ts +7 -4
  141. package/dist/shell/sidebar.d.ts.map +1 -1
  142. package/dist/shell/sidebar.js +148 -134
  143. package/dist/shell/sidebar.js.map +1 -1
  144. package/dist/shell/top-bar.d.ts +4 -3
  145. package/dist/shell/top-bar.d.ts.map +1 -1
  146. package/dist/shell/top-bar.js +116 -108
  147. package/dist/shell/top-bar.js.map +1 -1
  148. package/dist/tokens/semantic.css +82 -9
  149. package/dist/ui/accordion.js +1 -1
  150. package/dist/ui/accordion.js.map +1 -1
  151. package/dist/ui/alert-dialog.js +3 -3
  152. package/dist/ui/alert-dialog.js.map +1 -1
  153. package/dist/ui/alert.js +2 -2
  154. package/dist/ui/alert.js.map +1 -1
  155. package/dist/ui/autocomplete.js +2 -2
  156. package/dist/ui/autocomplete.js.map +1 -1
  157. package/dist/ui/avatar.js +11 -11
  158. package/dist/ui/avatar.js.map +1 -1
  159. package/dist/ui/badge-indicator.js +1 -1
  160. package/dist/ui/badge-indicator.js.map +1 -1
  161. package/dist/ui/badge.d.ts +3 -2
  162. package/dist/ui/badge.d.ts.map +1 -1
  163. package/dist/ui/banner.js +1 -1
  164. package/dist/ui/banner.js.map +1 -1
  165. package/dist/ui/breadcrumb.js +1 -1
  166. package/dist/ui/breadcrumb.js.map +1 -1
  167. package/dist/ui/button.d.ts +5 -4
  168. package/dist/ui/button.d.ts.map +1 -1
  169. package/dist/ui/button.js +66 -65
  170. package/dist/ui/button.js.map +1 -1
  171. package/dist/ui/card.js +5 -5
  172. package/dist/ui/card.js.map +1 -1
  173. package/dist/ui/charts/area-chart.js +177 -0
  174. package/dist/ui/charts/area-chart.js.map +1 -0
  175. package/dist/ui/charts/bar-chart.js +127 -0
  176. package/dist/ui/charts/bar-chart.js.map +1 -0
  177. package/dist/ui/charts/chart-container.js +3 -0
  178. package/dist/ui/charts/gauge-chart.js +72 -0
  179. package/dist/ui/charts/gauge-chart.js.map +1 -0
  180. package/dist/ui/charts/index.js +10 -1035
  181. package/dist/ui/charts/line-chart.js +135 -0
  182. package/dist/ui/charts/line-chart.js.map +1 -0
  183. package/dist/ui/charts/pie-chart.js +111 -0
  184. package/dist/ui/charts/pie-chart.js.map +1 -0
  185. package/dist/ui/charts/radar-chart.js +170 -0
  186. package/dist/ui/charts/radar-chart.js.map +1 -0
  187. package/dist/ui/charts/sparkline.js +119 -0
  188. package/dist/ui/charts/sparkline.js.map +1 -0
  189. package/dist/ui/chat/message.d.ts +3 -3
  190. package/dist/ui/chat/message.d.ts.map +1 -1
  191. package/dist/ui/chat/system-message.d.ts +2 -1
  192. package/dist/ui/chat/system-message.d.ts.map +1 -1
  193. package/dist/ui/checkbox.js +1 -1
  194. package/dist/ui/checkbox.js.map +1 -1
  195. package/dist/ui/code.js +2 -2
  196. package/dist/ui/code.js.map +1 -1
  197. package/dist/ui/color-input.js +10 -10
  198. package/dist/ui/color-input.js.map +1 -1
  199. package/dist/ui/color-swatch.js +3 -3
  200. package/dist/ui/color-swatch.js.map +1 -1
  201. package/dist/ui/combobox.d.ts +2 -1
  202. package/dist/ui/combobox.d.ts.map +1 -1
  203. package/dist/ui/combobox.js +100 -95
  204. package/dist/ui/combobox.js.map +1 -1
  205. package/dist/ui/container.d.ts +6 -1
  206. package/dist/ui/container.d.ts.map +1 -1
  207. package/dist/ui/container.js +2 -1
  208. package/dist/ui/container.js.map +1 -1
  209. package/dist/ui/context-menu.js +6 -6
  210. package/dist/ui/context-menu.js.map +1 -1
  211. package/dist/ui/data-table-body.js +1 -1
  212. package/dist/ui/data-table-body.js.map +1 -1
  213. package/dist/ui/data-table-bulk-actions.js +2 -2
  214. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  215. package/dist/ui/data-table-card.js +2 -2
  216. package/dist/ui/data-table-card.js.map +1 -1
  217. package/dist/ui/data-table-header.js +2 -2
  218. package/dist/ui/data-table-header.js.map +1 -1
  219. package/dist/ui/data-table-pagination.js +3 -3
  220. package/dist/ui/data-table-pagination.js.map +1 -1
  221. package/dist/ui/data-table-toolbar.js +1 -1
  222. package/dist/ui/data-table-toolbar.js.map +1 -1
  223. package/dist/ui/data-table.js +1 -1
  224. package/dist/ui/data-table.js.map +1 -1
  225. package/dist/ui/devalok-grain.d.ts +1 -1
  226. package/dist/ui/devalok-grain.js.map +1 -1
  227. package/dist/ui/dialog.js +2 -2
  228. package/dist/ui/dialog.js.map +1 -1
  229. package/dist/ui/dropdown-menu.js +6 -6
  230. package/dist/ui/dropdown-menu.js.map +1 -1
  231. package/dist/ui/file-upload.js +4 -4
  232. package/dist/ui/file-upload.js.map +1 -1
  233. package/dist/ui/hover-card.js +1 -1
  234. package/dist/ui/hover-card.js.map +1 -1
  235. package/dist/ui/icon-button.d.ts +9 -2
  236. package/dist/ui/icon-button.d.ts.map +1 -1
  237. package/dist/ui/icon-button.js +14 -13
  238. package/dist/ui/icon-button.js.map +1 -1
  239. package/dist/ui/index.d.ts +1 -3
  240. package/dist/ui/index.d.ts.map +1 -1
  241. package/dist/ui/index.js +31 -33
  242. package/dist/ui/index.js.map +1 -1
  243. package/dist/ui/input-otp.js +1 -1
  244. package/dist/ui/input-otp.js.map +1 -1
  245. package/dist/ui/input.js +2 -2
  246. package/dist/ui/input.js.map +1 -1
  247. package/dist/ui/lib/icon-input.d.ts +42 -0
  248. package/dist/ui/lib/icon-input.d.ts.map +1 -0
  249. package/dist/ui/lib/normalize-icon.d.ts +39 -0
  250. package/dist/ui/lib/normalize-icon.d.ts.map +1 -0
  251. package/dist/ui/link.js +1 -1
  252. package/dist/ui/link.js.map +1 -1
  253. package/dist/ui/menubar.js +8 -8
  254. package/dist/ui/menubar.js.map +1 -1
  255. package/dist/ui/navigation-menu.js +3 -3
  256. package/dist/ui/navigation-menu.js.map +1 -1
  257. package/dist/ui/number-input.js +3 -3
  258. package/dist/ui/number-input.js.map +1 -1
  259. package/dist/ui/oauth-button/index.d.ts +3 -0
  260. package/dist/ui/oauth-button/index.d.ts.map +1 -0
  261. package/dist/ui/oauth-button/index.js +3 -0
  262. package/dist/ui/oauth-button/oauth-button.d.ts +208 -0
  263. package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -0
  264. package/dist/ui/pagination.js +1 -1
  265. package/dist/ui/pagination.js.map +1 -1
  266. package/dist/ui/progress.js +2 -2
  267. package/dist/ui/progress.js.map +1 -1
  268. package/dist/ui/radio.js +1 -1
  269. package/dist/ui/radio.js.map +1 -1
  270. package/dist/ui/segmented-control.d.ts +3 -4
  271. package/dist/ui/segmented-control.d.ts.map +1 -1
  272. package/dist/ui/segmented-control.js +53 -45
  273. package/dist/ui/segmented-control.js.map +1 -1
  274. package/dist/ui/select.js +3 -3
  275. package/dist/ui/select.js.map +1 -1
  276. package/dist/ui/sheet.js +2 -2
  277. package/dist/ui/sheet.js.map +1 -1
  278. package/dist/ui/sidebar.js +11 -11
  279. package/dist/ui/sidebar.js.map +1 -1
  280. package/dist/ui/skeleton.js +9 -9
  281. package/dist/ui/skeleton.js.map +1 -1
  282. package/dist/ui/slider.js +2 -2
  283. package/dist/ui/slider.js.map +1 -1
  284. package/dist/ui/split-button.js +7 -7
  285. package/dist/ui/split-button.js.map +1 -1
  286. package/dist/ui/stack.d.ts +6 -1
  287. package/dist/ui/stack.d.ts.map +1 -1
  288. package/dist/ui/stack.js +2 -1
  289. package/dist/ui/stack.js.map +1 -1
  290. package/dist/ui/stat-card.d.ts +2 -3
  291. package/dist/ui/stat-card.d.ts.map +1 -1
  292. package/dist/ui/stat-card.js +118 -116
  293. package/dist/ui/stat-card.js.map +1 -1
  294. package/dist/ui/status-dot.js +2 -2
  295. package/dist/ui/status-dot.js.map +1 -1
  296. package/dist/ui/stepper.d.ts +2 -1
  297. package/dist/ui/stepper.d.ts.map +1 -1
  298. package/dist/ui/stepper.js +74 -69
  299. package/dist/ui/stepper.js.map +1 -1
  300. package/dist/ui/switch.js +2 -2
  301. package/dist/ui/switch.js.map +1 -1
  302. package/dist/ui/tabs.js +3 -3
  303. package/dist/ui/tabs.js.map +1 -1
  304. package/dist/ui/text.d.ts +7 -2
  305. package/dist/ui/text.d.ts.map +1 -1
  306. package/dist/ui/text.js +2 -1
  307. package/dist/ui/text.js.map +1 -1
  308. package/dist/ui/textarea.js +1 -1
  309. package/dist/ui/textarea.js.map +1 -1
  310. package/dist/ui/toast.js +8 -8
  311. package/dist/ui/toast.js.map +1 -1
  312. package/dist/ui/toaster.d.ts +11 -2
  313. package/dist/ui/toaster.d.ts.map +1 -1
  314. package/dist/ui/toaster.js.map +1 -1
  315. package/dist/ui/toggle.js +1 -1
  316. package/dist/ui/toggle.js.map +1 -1
  317. package/dist/ui/tooltip.js +12 -12
  318. package/dist/ui/tooltip.js.map +1 -1
  319. package/dist/ui/tree-view/tree-item.d.ts +3 -2
  320. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  321. package/dist/ui/tree-view/use-tree.d.ts +2 -1
  322. package/dist/ui/tree-view/use-tree.d.ts.map +1 -1
  323. package/docs/components/_header.md +90 -1
  324. package/docs/components/ui/oauth-button.md +86 -0
  325. package/docs/recipes/customize-brand.md +100 -4
  326. package/docs/recipes/index.md +5 -1
  327. package/docs/recipes/install-astro.md +15 -0
  328. package/docs/recipes/install-next-app-router.md +21 -5
  329. package/docs/recipes/install-next-pages.md +2 -0
  330. package/docs/recipes/install-remix.md +15 -0
  331. package/docs/recipes/install-tanstack-start.md +15 -0
  332. package/docs/recipes/install-vite.md +15 -0
  333. package/docs/recipes/troubleshoot.md +22 -0
  334. package/llms-full.txt +177 -2
  335. package/llms-quick.txt +247 -0
  336. package/llms.txt +116 -3
  337. package/package.json +80 -2
  338. package/scripts/welcome.mjs +219 -0
  339. package/skill/README.md +99 -0
  340. package/skill/SKILL.md +163 -0
  341. package/skill/install.sh +59 -0
  342. package/skill/references/components-full.md +7083 -0
  343. package/skill/references/components.md +778 -0
  344. package/skill/references/customize-brand.md +314 -0
  345. package/skill/references/server-components.md +211 -0
  346. package/skill/references/setup-astro.md +195 -0
  347. package/skill/references/setup-next-app-router.md +248 -0
  348. package/skill/references/setup-next-pages.md +127 -0
  349. package/skill/references/setup-remix.md +188 -0
  350. package/skill/references/setup-tanstack-start.md +160 -0
  351. package/skill/references/setup-vite.md +187 -0
  352. package/skill/references/troubleshoot.md +241 -0
  353. package/dist/_chunks/date-picker.js +0 -748
  354. package/dist/_chunks/date-picker.js.map +0 -1
  355. package/dist/_chunks/file-preview.js +0 -499
  356. package/dist/_chunks/file-preview.js.map +0 -1
  357. package/dist/_chunks/rich-chat-input.js +0 -2071
  358. package/dist/_chunks/rich-chat-input.js.map +0 -1
  359. package/dist/_chunks/text.js.map +0 -1
  360. package/dist/ui/charts/index.js.map +0 -1
  361. /package/{LICENSE → skill/LICENSE} +0 -0
package/dist/ui/button.js CHANGED
@@ -6,14 +6,15 @@ import { t as r } from "../_chunks/vendor-utils.js";
6
6
  import { cn as i } from "./lib/utils.js";
7
7
  import { Spinner as a } from "./spinner.js";
8
8
  import { Icon as te } from "./icon.js";
9
- import { getGroupPositionStyle as o, useButtonGroup as ne, useButtonGroupItem as re } from "./button-group.js";
10
- import { ProcessingOverlay as ie } from "./button-processing.js";
9
+ import { t as o } from "../_chunks/normalize-icon.js";
10
+ import { getGroupPositionStyle as ne, useButtonGroup as re, useButtonGroupItem as ie } from "./button-group.js";
11
+ import { ProcessingOverlay as ae } from "./button-processing.js";
11
12
  import * as s from "react";
12
- import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
13
- import { IconCheck as ae, IconX as oe } from "@tabler/icons-react";
14
- import { motion as se, useReducedMotion as ce } from "framer-motion";
13
+ import { Fragment as oe, jsx as c, jsxs as l } from "react/jsx-runtime";
14
+ import { IconCheck as se, IconX as ce } from "@tabler/icons-react";
15
+ import { motion as le, useReducedMotion as ue } from "framer-motion";
15
16
  //#region src/ui/button.tsx
16
- var d = r("relative inline-flex items-center justify-center whitespace-nowrap font-sans select-none overflow-hidden isolate 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 disabled:cursor-not-allowed disabled:saturate-[0.3] [&>span:not([data-grain])]:relative [&>span:not([data-grain])]:z-[2]", {
17
+ var u = r("relative inline-flex items-center justify-center whitespace-nowrap font-sans select-none overflow-hidden isolate 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 disabled:cursor-not-allowed disabled:saturate-[0.3] [&>span:not([data-grain])]:relative [&>span:not([data-grain])]:z-[2]", {
17
18
  variants: {
18
19
  variant: {
19
20
  solid: "",
@@ -34,18 +35,18 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
34
35
  normal: "font-normal"
35
36
  },
36
37
  size: {
37
- xs: "h-ds-xs-plus rounded-ds-md px-ds-03 text-ds-sm gap-ds-02",
38
- sm: "h-ds-sm rounded-ds-md px-ds-04 text-ds-sm gap-ds-02b",
39
- md: "h-ds-md rounded-ds-lg px-ds-05 text-ds-md gap-ds-03",
40
- lg: "h-ds-lg rounded-ds-xl px-ds-06 text-ds-base gap-2.5",
41
- "compact-xs": "rounded-ds-md px-ds-02 py-[3px] text-ds-sm gap-ds-02",
42
- "compact-sm": "rounded-ds-md px-ds-03 py-[5px] text-ds-sm gap-ds-02b",
43
- "compact-md": "rounded-ds-lg px-ds-04 py-ds-03 text-ds-md gap-ds-03",
44
- icon: "h-ds-md w-ds-md rounded-ds-md",
45
- "icon-xs": "h-ds-xs-plus w-ds-xs-plus rounded-ds-sm",
46
- "icon-sm": "h-ds-sm w-ds-sm rounded-ds-md",
47
- "icon-md": "h-ds-md w-ds-md rounded-ds-md",
48
- "icon-lg": "h-ds-lg w-ds-lg rounded-ds-lg"
38
+ xs: "h-ds-xs-plus rounded-control px-ds-03 text-ds-sm gap-ds-02",
39
+ sm: "h-ds-sm rounded-control px-ds-04 text-ds-sm gap-ds-02b",
40
+ md: "h-ds-md rounded-control px-ds-05 text-ds-md gap-ds-03",
41
+ lg: "h-ds-lg rounded-control px-ds-06 text-ds-base gap-2.5",
42
+ "compact-xs": "rounded-control px-ds-02 py-[3px] text-ds-sm gap-ds-02",
43
+ "compact-sm": "rounded-control px-ds-03 py-[5px] text-ds-sm gap-ds-02b",
44
+ "compact-md": "rounded-control px-ds-04 py-ds-03 text-ds-md gap-ds-03",
45
+ icon: "h-ds-md w-ds-md rounded-control",
46
+ "icon-xs": "h-ds-xs-plus w-ds-xs-plus rounded-control",
47
+ "icon-sm": "h-ds-sm w-ds-sm rounded-control",
48
+ "icon-md": "h-ds-md w-ds-md rounded-control",
49
+ "icon-lg": "h-ds-lg w-ds-lg rounded-control"
49
50
  }
50
51
  },
51
52
  compoundVariants: [
@@ -181,7 +182,7 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
181
182
  weight: "semibold",
182
183
  size: "md"
183
184
  }
184
- }), f = {
185
+ }), d = {
185
186
  xs: "px-ds-04",
186
187
  sm: "px-ds-05",
187
188
  md: "px-ds-06",
@@ -189,7 +190,7 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
189
190
  "compact-xs": "px-ds-03",
190
191
  "compact-sm": "px-ds-04",
191
192
  "compact-md": "px-ds-05"
192
- }, le = {
193
+ }, de = {
193
194
  xs: {
194
195
  start: "-ml-0.5",
195
196
  end: "-mr-0.5"
@@ -238,7 +239,7 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
238
239
  start: "",
239
240
  end: ""
240
241
  }
241
- }, p = {
242
+ }, f = {
242
243
  xs: "sm",
243
244
  sm: "sm",
244
245
  md: "sm",
@@ -251,7 +252,7 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
251
252
  "icon-sm": "sm",
252
253
  "icon-md": "sm",
253
254
  "icon-lg": "md"
254
- }, ue = {
255
+ }, fe = {
255
256
  xs: "xs",
256
257
  sm: "sm",
257
258
  md: "md",
@@ -264,8 +265,8 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
264
265
  "icon-sm": "sm",
265
266
  "icon-md": "md",
266
267
  "icon-lg": "lg"
267
- }, m = s.forwardRef(({ className: r, variant: m, color: de, weight: fe, size: pe, asChild: me = !1, shape: he, startIcon: h, endIcon: g, loading: ge = !1, loadingPosition: _ = "start", fullWidth: v = !1, disabled: _e, onClick: ve, onClickAsync: y, asyncFeedbackDuration: b = 1500, processing: x, processingColor: ye, processingDisabled: S = !0, children: C, ...w }, T) => {
268
- let E = ne(), D = re(), O = m ?? E.variant, k = de ?? E.color, A = fe ?? E.weight ?? "semibold", j = he ?? E.shape ?? "default", M = pe ?? E.size ?? "md", N = _e ?? E.disabled, P = D && E.attached !== !1 ? o(D.position, E.orientation ?? "horizontal") : void 0, F = E._stretch ?? !1, I = ce(), L = s.useRef(null), R = s.useRef(null), z = s.useRef(void 0);
268
+ }, p = s.forwardRef(({ className: r, variant: p, color: m, weight: pe, size: me, asChild: he = !1, shape: ge, startIcon: h, endIcon: g, loading: _e = !1, loadingPosition: _ = "start", fullWidth: v = !1, disabled: ve, onClick: ye, onClickAsync: y, asyncFeedbackDuration: b = 1500, processing: x, processingColor: be, processingDisabled: S = !0, children: C, ...w }, T) => {
269
+ let E = re(), D = ie(), O = p ?? E.variant, k = m ?? E.color, A = pe ?? E.weight ?? "semibold", j = ge ?? E.shape ?? "default", M = me ?? E.size ?? "md", N = ve ?? E.disabled, P = D && E.attached !== !1 ? ne(D.position, E.orientation ?? "horizontal") : void 0, F = E._stretch ?? !1, I = ue(), L = s.useRef(null), R = s.useRef(null), z = s.useRef(void 0);
269
270
  s.useEffect(() => {
270
271
  let e = R.current, t = L.current;
271
272
  if (!(!e || !t || v || F || I)) return z.current = requestAnimationFrame(() => {
@@ -280,7 +281,7 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
280
281
  s.useEffect(() => () => {
281
282
  U.current = !1, clearTimeout(H.current);
282
283
  }, []);
283
- let be = (e) => {
284
+ let xe = (e) => {
284
285
  !y || B !== "idle" || (V("loading"), y(e).then(() => {
285
286
  U.current && V("success");
286
287
  }).catch(() => {
@@ -290,106 +291,106 @@ var d = r("relative inline-flex items-center justify-center whitespace-nowrap fo
290
291
  U.current && V("idle");
291
292
  }, b));
292
293
  }));
293
- }, W = !!y, G = W ? B === "loading" : ge, K = B === "success" || B === "error", q = K ? void 0 : x === !0 ? "working" : x === !1 || !x ? W && B === "loading" && !x ? "working" : void 0 : x, J = !!q, xe = ye ?? k ?? "accent";
294
- if (me) return /* @__PURE__ */ l(e, {
295
- className: i(d({
294
+ }, W = !!y, G = W ? B === "loading" : _e, K = B === "success" || B === "error", q = K ? void 0 : x === !0 ? "working" : x === !1 || !x ? W && B === "loading" && !x ? "working" : void 0 : x, J = !!q, Se = be ?? k ?? "accent";
295
+ if (he) return /* @__PURE__ */ c(e, {
296
+ className: i(u({
296
297
  variant: O,
297
298
  color: k,
298
299
  weight: A,
299
300
  size: M
300
- }), j === "pill" && "rounded-full", j === "pill" && f[M], (v || F) && "w-full", r),
301
+ }), j === "pill" && "rounded-pill", j === "pill" && d[M], (v || F) && "w-full", r),
301
302
  ref: T,
302
303
  disabled: N || G,
303
304
  "aria-busy": G || void 0,
304
305
  ...w,
305
- children: /* @__PURE__ */ l(t, { children: C })
306
+ children: /* @__PURE__ */ c(t, { children: C })
306
307
  });
307
- let Y = le[M] ?? {
308
+ let Y = de[M] ?? {
308
309
  start: "",
309
310
  end: ""
310
- }, X = O === "solid" || O === "soft" || O === "outline", Z = () => G && _ === "start" ? /* @__PURE__ */ l("span", {
311
+ }, X = O === "solid" || O === "soft" || O === "outline", Z = () => G && _ === "start" ? /* @__PURE__ */ c("span", {
311
312
  className: i("inline-flex shrink-0 items-center justify-center", h && Y.start),
312
- children: /* @__PURE__ */ l(a, {
313
- size: p[M],
313
+ children: /* @__PURE__ */ c(a, {
314
+ size: f[M],
314
315
  variant: "bare"
315
316
  })
316
- }) : h ? /* @__PURE__ */ l("span", {
317
+ }) : h ? /* @__PURE__ */ c("span", {
317
318
  className: i("inline-flex shrink-0 items-center justify-center pointer-events-none", Y.start, X && "opacity-90"),
318
- children: h
319
- }) : null, Se = () => G && _ === "end" ? /* @__PURE__ */ l("span", {
319
+ children: o(h)
320
+ }) : null, Ce = () => G && _ === "end" ? /* @__PURE__ */ c("span", {
320
321
  className: i("inline-flex shrink-0 items-center justify-center", g && Y.end),
321
- children: /* @__PURE__ */ l(a, {
322
- size: p[M],
322
+ children: /* @__PURE__ */ c(a, {
323
+ size: f[M],
323
324
  variant: "bare"
324
325
  })
325
- }) : g ? /* @__PURE__ */ l("span", {
326
+ }) : g ? /* @__PURE__ */ c("span", {
326
327
  className: i("inline-flex shrink-0 items-center justify-center pointer-events-none", Y.end, X && "opacity-90"),
327
- children: g
328
- }) : null, Ce = s.Children.toArray(C), Q = [], $ = [];
329
- Ce.forEach((e) => {
328
+ children: o(g)
329
+ }) : null, we = s.Children.toArray(C), Q = [], $ = [];
330
+ we.forEach((e) => {
330
331
  s.isValidElement(e) && e.type?.displayName === "DevalokGrain" ? Q.push(e) : $.push(e);
331
332
  });
332
- let we = () => G && _ === "center" ? /* @__PURE__ */ u("span", {
333
+ let Te = () => G && _ === "center" ? /* @__PURE__ */ l("span", {
333
334
  className: "relative inline-flex items-center justify-center",
334
- children: [/* @__PURE__ */ l("span", {
335
+ children: [/* @__PURE__ */ c("span", {
335
336
  className: "invisible",
336
337
  children: $
337
- }), /* @__PURE__ */ l("span", {
338
+ }), /* @__PURE__ */ c("span", {
338
339
  className: "absolute inset-0 flex items-center justify-center",
339
- children: /* @__PURE__ */ l(a, {
340
- size: p[M],
340
+ children: /* @__PURE__ */ c(a, {
341
+ size: f[M],
341
342
  variant: "bare"
342
343
  })
343
344
  })]
344
- }) : Q.length > 0 ? /* @__PURE__ */ l("span", { children: $ }) : /* @__PURE__ */ l(c, { children: $ }), Te = K ? B === "success" ? "bg-success-9 text-success-fg border-transparent hover:bg-success-9" : "bg-error-9 text-error-fg border-transparent hover:bg-error-9" : void 0, Ee = K ? /* @__PURE__ */ l("span", {
345
+ }) : Q.length > 0 ? /* @__PURE__ */ c("span", { children: $ }) : /* @__PURE__ */ c(oe, { children: $ }), Ee = K ? B === "success" ? "bg-success-9 text-success-fg border-transparent hover:bg-success-9" : "bg-error-9 text-error-fg border-transparent hover:bg-error-9" : void 0, De = K ? /* @__PURE__ */ c("span", {
345
346
  className: i("inline-flex shrink-0 items-center justify-center pointer-events-none", h && Y.start),
346
- children: /* @__PURE__ */ l(te, {
347
- icon: B === "success" ? ae : oe,
347
+ children: /* @__PURE__ */ c(te, {
348
+ icon: B === "success" ? se : ce,
348
349
  animate: "draw"
349
350
  })
350
- }) : null, De = ue[M] ?? "md", Oe = /* @__PURE__ */ u(se.button, {
351
+ }) : null, Oe = fe[M] ?? "md", ke = /* @__PURE__ */ l(le.button, {
351
352
  ...ee(w),
352
353
  style: {
353
354
  ...w.style,
354
355
  ...P
355
356
  },
356
- className: i(d({
357
+ className: i(u({
357
358
  variant: J && !K && O !== "ghost" && O !== "outline" && O !== "link" ? "soft" : O,
358
359
  color: k,
359
360
  weight: A,
360
361
  size: M
361
- }), j === "pill" && "rounded-full", j === "pill" && f[M], (v || F) && "w-full", !G && !K && "transition-[color,background-color,border-color,box-shadow,transform,filter] duration-moderate-01 ease-productive-exit", !G && !K && "hover:duration-fast-02 hover:ease-productive-entrance", !G && !K && "active:scale-[0.95] active:brightness-[0.92] active:saturate-[1.1] active:duration-[0ms]", Te, K && "transition-colors duration-moderate-01 ease-productive-standard", J && S && "pointer-events-none cursor-default", r),
362
+ }), j === "pill" && "rounded-pill", j === "pill" && d[M], (v || F) && "w-full", !G && !K && "transition-[color,background-color,border-color,box-shadow,transform,filter] duration-moderate-01 ease-productive-exit", !G && !K && "hover:duration-fast-02 hover:ease-productive-entrance", !G && !K && "active:scale-[0.95] active:brightness-[0.92] active:saturate-[1.1] active:duration-[0ms]", Ee, K && "transition-colors duration-moderate-01 ease-productive-standard", J && S && "pointer-events-none cursor-default", r),
362
363
  ref: (e) => {
363
364
  R.current = e, typeof T == "function" ? T(e) : T && (T.current = e);
364
365
  },
365
366
  disabled: N || G && !J,
366
367
  "aria-busy": G || J || void 0,
367
368
  "aria-disabled": J && S || void 0,
368
- onClick: W ? be : J && S ? void 0 : ve,
369
+ onClick: W ? xe : J && S ? void 0 : ye,
369
370
  children: [
370
371
  Q,
371
- K ? Ee : Z(),
372
- K ? $ : we(),
373
- K ? null : Se()
372
+ K ? De : Z(),
373
+ K ? $ : Te(),
374
+ K ? null : Ce()
374
375
  ]
375
376
  });
376
- return /* @__PURE__ */ l(n, {
377
- size: De,
378
- children: /* @__PURE__ */ u("span", {
377
+ return /* @__PURE__ */ c(n, {
378
+ size: Oe,
379
+ children: /* @__PURE__ */ l("span", {
379
380
  ref: L,
380
381
  className: i("relative inline-flex", v && "w-full"),
381
382
  style: {
382
383
  ...v || F || I ? void 0 : { transition: "width 0.2s cubic-bezier(0.25, 0.1, 0.25, 1)" },
383
384
  ...P
384
385
  },
385
- children: [Oe, /* @__PURE__ */ l(ie, {
386
+ children: [ke, /* @__PURE__ */ c(ae, {
386
387
  active: J,
387
388
  speed: q ?? "working",
388
- color: xe
389
+ color: Se
389
390
  })]
390
391
  })
391
392
  });
392
393
  });
393
- m.displayName = "Button";
394
+ p.displayName = "Button";
394
395
  //#endregion
395
- export { m as Button, d as buttonVariants };
396
+ export { p as Button, u as buttonVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","names":[],"sources":["../../src/ui/button.tsx"],"sourcesContent":["'use client'\n\nimport { Slot, Slottable } from '@primitives/react-slot'\nimport { IconCheck, IconX } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { getGroupPositionStyle,useButtonGroup, useButtonGroupItem } from './button-group'\nimport type { ProcessingSpeed } from './button-processing'\nimport { ProcessingOverlay } from './button-processing'\nimport { Icon } from './icon'\nimport type { IconSize } from './icon-context'\nimport { IconProvider } from './icon-context'\nimport { motionProps,springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\nimport { Spinner } from './spinner'\n\nexport const buttonVariants = cva(\n 'relative inline-flex items-center justify-center whitespace-nowrap font-sans select-none overflow-hidden isolate 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 disabled:cursor-not-allowed disabled:saturate-[0.3] [&>span:not([data-grain])]:relative [&>span:not([data-grain])]:z-[2]',\n {\n variants: {\n variant: {\n solid: '',\n soft: '',\n outline: 'border',\n ghost: '',\n link: 'underline-offset-4 hover:underline active:opacity-80',\n },\n color: {\n accent: '',\n error: '',\n success: '',\n warning: '',\n neutral: '',\n },\n weight: {\n semibold: 'font-semibold',\n normal: 'font-normal',\n },\n size: {\n xs: 'h-ds-xs-plus rounded-ds-md px-ds-03 text-ds-sm gap-ds-02',\n sm: 'h-ds-sm rounded-ds-md px-ds-04 text-ds-sm gap-ds-02b',\n md: 'h-ds-md rounded-ds-lg px-ds-05 text-ds-md gap-ds-03',\n lg: 'h-ds-lg rounded-ds-xl px-ds-06 text-ds-base gap-2.5', /* 10px — no exact DS token */\n 'compact-xs': 'rounded-ds-md px-ds-02 py-[3px] text-ds-sm gap-ds-02',\n 'compact-sm': 'rounded-ds-md px-ds-03 py-[5px] text-ds-sm gap-ds-02b',\n 'compact-md': 'rounded-ds-lg px-ds-04 py-ds-03 text-ds-md gap-ds-03',\n icon: 'h-ds-md w-ds-md rounded-ds-md',\n 'icon-xs': 'h-ds-xs-plus w-ds-xs-plus rounded-ds-sm',\n 'icon-sm': 'h-ds-sm w-ds-sm rounded-ds-md',\n 'icon-md': 'h-ds-md w-ds-md rounded-ds-md',\n 'icon-lg': 'h-ds-lg w-ds-lg rounded-ds-lg',\n },\n },\n compoundVariants: [\n // ============ SOLID ============ (colored hover shadows — shadow tints with the button's own hue)\n { variant: 'solid', color: 'accent', className: 'bg-accent-9 text-accent-fg hover:bg-accent-10 shadow-raised hover:shadow-brand' },\n { variant: 'solid', color: 'error', className: 'bg-error-9 text-error-fg hover:bg-error-10 shadow-raised hover:shadow-error' },\n { variant: 'solid', color: 'success', className: 'bg-success-9 text-success-fg hover:bg-success-10 shadow-raised hover:shadow-success' },\n { variant: 'solid', color: 'warning', className: 'bg-warning-9 text-warning-fg hover:bg-warning-10 shadow-raised hover:shadow-warning' },\n { variant: 'solid', color: 'neutral', className: 'bg-neutral-5 text-surface-fg hover:bg-neutral-7 shadow-raised' },\n\n // ============ SOFT ============\n { variant: 'soft', color: 'accent', className: 'bg-accent-3 text-accent-11 hover:bg-accent-4 active:bg-accent-5' },\n { variant: 'soft', color: 'error', className: 'bg-error-3 text-error-11 hover:bg-error-4 active:bg-error-5' },\n { variant: 'soft', color: 'success', className: 'bg-success-3 text-success-11 hover:bg-success-4 active:bg-success-5' },\n { variant: 'soft', color: 'warning', className: 'bg-warning-3 text-warning-11 hover:bg-warning-4 active:bg-warning-5' },\n { variant: 'soft', color: 'neutral', className: 'bg-surface-raised-hover text-surface-fg-muted hover:bg-surface-raised-active active:bg-neutral-5' },\n\n // ============ OUTLINE ============\n { variant: 'outline', color: 'accent', className: 'bg-transparent text-accent-11 border-accent-7 hover:bg-accent-3 active:bg-accent-4' },\n { variant: 'outline', color: 'error', className: 'bg-transparent text-error-11 border-error-7 hover:bg-error-3 active:bg-error-4' },\n { variant: 'outline', color: 'success', className: 'bg-transparent text-success-11 border-success-7 hover:bg-success-3 active:bg-success-4' },\n { variant: 'outline', color: 'warning', className: 'bg-transparent text-warning-11 border-warning-7 hover:bg-warning-3 active:bg-warning-4' },\n { variant: 'outline', color: 'neutral', className: 'bg-transparent text-surface-fg border-surface-border-strong hover:bg-surface-raised-hover active:bg-surface-raised-active' },\n\n // ============ GHOST ============\n // ghost+accent uses neutral look for backward compat (most common ghost is toolbar/icon ghost)\n { variant: 'ghost', color: 'accent', className: 'bg-transparent text-surface-fg-muted hover:bg-surface-raised-hover hover:text-surface-fg active:bg-surface-raised-active' },\n { variant: 'ghost', color: 'error', className: 'bg-transparent text-error-11 hover:bg-error-3 active:bg-error-4' },\n { variant: 'ghost', color: 'success', className: 'bg-transparent text-success-11 hover:bg-success-3 active:bg-success-4' },\n { variant: 'ghost', color: 'warning', className: 'bg-transparent text-warning-11 hover:bg-warning-3 active:bg-warning-4' },\n { variant: 'ghost', color: 'neutral', className: 'bg-transparent text-surface-fg-muted hover:bg-surface-raised-hover hover:text-surface-fg active:bg-surface-raised-active' },\n\n // ============ LINK ============\n { variant: 'link', color: 'accent', className: 'text-accent-11' },\n { variant: 'link', color: 'error', className: 'text-error-11' },\n { variant: 'link', color: 'success', className: 'text-success-11' },\n { variant: 'link', color: 'warning', className: 'text-warning-11' },\n { variant: 'link', color: 'neutral', className: 'text-surface-fg-muted' },\n ],\n defaultVariants: {\n variant: 'solid',\n color: 'accent',\n weight: 'semibold',\n size: 'md',\n },\n },\n)\n\n/** Extra horizontal padding for pill shape — rounded ends eat into visual space */\nconst pillPaddingClass: Record<string, string> = {\n xs: 'px-ds-04',\n sm: 'px-ds-05',\n md: 'px-ds-06',\n lg: 'px-ds-07',\n 'compact-xs': 'px-ds-03',\n 'compact-sm': 'px-ds-04',\n 'compact-md': 'px-ds-05',\n}\n\n/** Negative margin to tighten icon side padding — pulls icon closer to button edge */\nconst iconInsetClass: Record<string, { start: string; end: string }> = {\n xs: { start: '-ml-0.5', end: '-mr-0.5' },\n sm: { start: '-ml-1', end: '-mr-1' },\n md: { start: '-ml-1.5', end: '-mr-1.5' },\n lg: { start: '-ml-2', end: '-mr-2' },\n 'compact-xs': { start: '-ml-0.5', end: '-mr-0.5' },\n 'compact-sm': { start: '-ml-0.5', end: '-mr-0.5' },\n 'compact-md': { start: '-ml-1', end: '-mr-1' },\n icon: { start: '', end: '' },\n 'icon-xs': { start: '', end: '' },\n 'icon-sm': { start: '', end: '' },\n 'icon-md': { start: '', end: '' },\n 'icon-lg': { start: '', end: '' },\n}\n\n/** Map button size to spinner size */\nconst BUTTON_TO_SPINNER_SIZE: Record<string, 'sm' | 'md'> = {\n xs: 'sm',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n 'compact-xs': 'sm',\n 'compact-sm': 'sm',\n 'compact-md': 'sm',\n icon: 'sm',\n 'icon-xs': 'sm',\n 'icon-sm': 'sm',\n 'icon-md': 'sm',\n 'icon-lg': 'md',\n}\n\n/** Map button size to Icon context size */\nconst BUTTON_TO_ICON_SIZE: Record<string, IconSize> = {\n xs: 'xs', sm: 'sm', md: 'md', lg: 'lg',\n 'compact-xs': 'xs', 'compact-sm': 'sm', 'compact-md': 'md',\n icon: 'md', 'icon-xs': 'xs', 'icon-sm': 'sm', 'icon-md': 'md', 'icon-lg': 'lg',\n}\n\n/**\n * Props for Button — the primary action component with a two-axis variant system,\n * multiple size options, icon slots, and a built-in loading state.\n *\n * **Two axes:**\n * - `variant` controls **visual style**: `\"solid\"` (default, filled) | `\"soft\"` (tinted bg) |\n * `\"outline\"` (bordered) | `\"ghost\"` (transparent, for toolbars) | `\"link\"` (underline, inline)\n * - `color` controls **semantic intent**: `\"accent\"` (default, brand) | `\"error\"` (destructive) |\n * `\"success\"` | `\"warning\"` | `\"neutral\"` (subdued)\n *\n * **Sizes:** `xs` | `sm` | `md` (default) | `lg` for text buttons;\n * `compact-xs` | `compact-sm` | `compact-md` for height-less inline buttons;\n * `icon` | `icon-xs` | `icon-sm` | `icon-md` | `icon-lg` for square icon-only buttons.\n *\n * **Shape:** `\"default\"` uses per-size border-radius; `\"pill\"` applies `rounded-full`.\n *\n * **Weight:** `\"semibold\"` (default) | `\"normal\"` for lighter labels.\n *\n * **Note:** `ghost` + `accent` renders with neutral styling for backward compat —\n * most ghost buttons are toolbar/icon actions where neutral is expected.\n *\n * **Loading:** When `loading={true}` the button is disabled and aria-busy is set.\n * Use `loadingPosition` to control where the spinner appears.\n *\n * @example\n * // Primary save action (default variant + color):\n * <Button onClick={handleSave}>Save changes</Button>\n *\n * @example\n * // Soft success feedback:\n * <Button variant=\"soft\" color=\"success\" startIcon={<Icon icon={IconCheck} />}>\n * Approved\n * </Button>\n *\n * @example\n * // Destructive delete with loading state:\n * <Button variant=\"solid\" color=\"error\" startIcon={<Icon icon={IconTrash} />} loading={isDeleting}>\n * Delete project\n * </Button>\n *\n * @example\n * // Compact pill tag:\n * <Button variant=\"soft\" color=\"warning\" size=\"compact-sm\" shape=\"pill\">\n * Overdue\n * </Button>\n *\n * @example\n * // Ghost toolbar action:\n * <Button variant=\"ghost\" size=\"sm\" startIcon={<Icon icon={IconEdit} />}>\n * Edit\n * </Button>\n */\nexport interface ButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'color'>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n /** Button shape — 'pill' applies rounded-full for chip/tag-like buttons */\n shape?: 'default' | 'pill'\n /** Icon element rendered before children — use <Icon icon={...} /> */\n startIcon?: React.ReactElement | null\n /** Icon element rendered after children — use <Icon icon={...} /> */\n endIcon?: React.ReactElement | null\n /** Show loading spinner and disable button */\n loading?: boolean\n /** Where to render the spinner: replaces startIcon, endIcon, or centers over children */\n loadingPosition?: 'start' | 'end' | 'center'\n /** Stretch to full width of parent */\n fullWidth?: boolean\n /**\n * Async click handler — auto-manages loading → success/error states.\n * When provided, the button shows a spinner while the promise is pending,\n * then briefly flashes green (success) or red (error) before reverting.\n * Overrides `onClick` and `loading` when active.\n */\n onClickAsync?: (e: React.MouseEvent<HTMLButtonElement>) => Promise<void>\n /** How long (ms) to show the success/error state before reverting. Default: 1500 */\n asyncFeedbackDuration?: number\n\n /**\n * Show processing animation — animated border/glow while content stays visible.\n * `true` = \"working\" speed. Semantic speeds:\n * - `\"ambient\"` (3s) — background sync, file upload\n * - `\"working\"` (2s) — standard API call, generation\n * - `\"urgent\"` (1s) — retry, nearly done\n */\n processing?: boolean | 'ambient' | 'working' | 'urgent'\n\n /** Override processing animation color. Defaults to button's own color. */\n processingColor?: 'accent' | 'error' | 'success' | 'warning' | 'neutral'\n\n /** Disable button during processing. Default: true. Set false for cancel-by-click patterns. */\n processingDisabled?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n color,\n weight,\n size,\n asChild = false,\n shape,\n startIcon,\n endIcon,\n loading: loadingProp = false,\n loadingPosition = 'start',\n fullWidth = false,\n disabled,\n onClick,\n onClickAsync,\n asyncFeedbackDuration = 1500,\n processing: processingProp,\n processingColor,\n processingDisabled = true,\n children,\n ...props\n },\n ref,\n ) => {\n const group = useButtonGroup()\n const groupItem = useButtonGroupItem()\n const resolvedVariant = variant ?? group.variant\n const resolvedColor = color ?? group.color\n const resolvedWeight = weight ?? group.weight ?? 'semibold'\n const resolvedShape = shape ?? group.shape ?? 'default'\n const resolvedSize = size ?? group.size ?? 'md'\n // ButtonGroup can propagate disabled to all children\n const resolvedDisabled = disabled ?? group.disabled\n\n // When inside an attached ButtonGroup, adjust border-radius based on position\n const groupRadiusStyle = groupItem && group.attached !== false\n ? getGroupPositionStyle(groupItem.position, group.orientation ?? 'horizontal')\n : undefined\n // Stretch to fill when inside a vertical or fullWidth ButtonGroup\n const groupStretch = group._stretch ?? false\n\n const prefersReduced = useReducedMotion()\n\n // Refs + effect for smooth width transitions (must be before any early returns)\n const wrapperRef = React.useRef<HTMLSpanElement>(null)\n const btnRef = React.useRef<HTMLButtonElement | null>(null)\n const rafRef = React.useRef<number | undefined>(undefined)\n\n \n React.useEffect(() => {\n const btn = btnRef.current\n const wrapper = wrapperRef.current\n if (!btn || !wrapper || fullWidth || groupStretch || prefersReduced) return\n\n rafRef.current = requestAnimationFrame(() => {\n wrapper.style.width = 'auto'\n const w = btn.offsetWidth\n if (w > 0) {\n wrapper.getBoundingClientRect()\n wrapper.style.width = `${w}px`\n }\n })\n return () => { if (rafRef.current) cancelAnimationFrame(rafRef.current) }\n }) // run on every render to catch content changes\n\n // Async state machine: idle → loading → success | error → idle\n type AsyncState = 'idle' | 'loading' | 'success' | 'error'\n const [asyncState, setAsyncState] = React.useState<AsyncState>('idle')\n const timeoutRef = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const isMountedRef = React.useRef(true)\n\n React.useEffect(() => () => {\n isMountedRef.current = false\n clearTimeout(timeoutRef.current)\n }, [])\n\n const handleAsyncClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!onClickAsync || asyncState !== 'idle') return\n setAsyncState('loading')\n onClickAsync(e)\n .then(() => { if (isMountedRef.current) setAsyncState('success') })\n .catch(() => { if (isMountedRef.current) setAsyncState('error') })\n .finally(() => {\n if (isMountedRef.current) {\n timeoutRef.current = setTimeout(() => {\n if (isMountedRef.current) setAsyncState('idle')\n }, asyncFeedbackDuration)\n }\n })\n }\n\n const isAsync = !!onClickAsync\n const loading = isAsync ? asyncState === 'loading' : loadingProp\n const isAsyncFeedback = asyncState === 'success' || asyncState === 'error'\n\n // Processing: explicit prop takes priority, otherwise auto-processing during onClickAsync.\n // Processing is always OFF during async feedback (success/error) so the feedback colors show.\n const autoProcessing = isAsync && asyncState === 'loading' && !processingProp\n const processingSpeed: ProcessingSpeed | undefined = isAsyncFeedback ? undefined\n : processingProp === true ? 'working'\n : processingProp === false || !processingProp\n ? (autoProcessing ? 'working' : undefined)\n : processingProp\n const isProcessing = !!processingSpeed\n const resolvedProcessingColor = processingColor ?? resolvedColor ?? 'accent'\n\n if (asChild) {\n // Slot merges all props into the child element via cloneElement at runtime.\n // We cast here because SlotProps only types React.HTMLAttributes<HTMLElement>,\n // which excludes button-specific attrs like `disabled`.\n const slotProps = {\n className: cn(\n buttonVariants({ variant: resolvedVariant, color: resolvedColor, weight: resolvedWeight, size: resolvedSize }),\n resolvedShape === 'pill' && 'rounded-full',\n resolvedShape === 'pill' && pillPaddingClass[resolvedSize],\n (fullWidth || groupStretch) && 'w-full',\n className,\n ),\n ref,\n disabled: resolvedDisabled || loading,\n 'aria-busy': loading || undefined,\n ...props,\n } as React.ComponentPropsWithRef<typeof Slot>\n return (\n <Slot {...slotProps}>\n <Slottable>{children}</Slottable>\n </Slot>\n )\n }\n\n const inset = iconInsetClass[resolvedSize] ?? { start: '', end: '' }\n // Dim icons on filled variants (Radix pattern — icon is decorative, text is primary)\n const dimIcon = resolvedVariant === 'solid' || resolvedVariant === 'soft' || resolvedVariant === 'outline'\n\n const renderStartSlot = () => {\n if (loading && loadingPosition === 'start') {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center', startIcon && inset.start)}>\n <Spinner size={BUTTON_TO_SPINNER_SIZE[resolvedSize]} variant=\"bare\" />\n </span>\n )\n }\n if (startIcon) {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center pointer-events-none', inset.start, dimIcon && 'opacity-90')}>\n {startIcon}\n </span>\n )\n }\n return null\n }\n\n const renderEndSlot = () => {\n if (loading && loadingPosition === 'end') {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center', endIcon && inset.end)}>\n <Spinner size={BUTTON_TO_SPINNER_SIZE[resolvedSize]} variant=\"bare\" />\n </span>\n )\n }\n if (endIcon) {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center pointer-events-none', inset.end, dimIcon && 'opacity-90')}>\n {endIcon}\n </span>\n )\n }\n return null\n }\n\n // Separate DevalokGrain elements (need to be direct button children for absolute positioning)\n // from text/other content (needs z-elevation above grain)\n const childArray = React.Children.toArray(children)\n const grainElements: React.ReactNode[] = []\n const contentElements: React.ReactNode[] = []\n childArray.forEach((child) => {\n if (React.isValidElement(child) && (child.type as { displayName?: string })?.displayName === 'DevalokGrain') {\n grainElements.push(child)\n } else {\n contentElements.push(child)\n }\n })\n\n const renderChildren = () => {\n if (loading && loadingPosition === 'center') {\n return (\n <span className=\"relative inline-flex items-center justify-center\">\n <span className=\"invisible\">{contentElements}</span>\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <Spinner size={BUTTON_TO_SPINNER_SIZE[resolvedSize]} variant=\"bare\" />\n </span>\n </span>\n )\n }\n // Only wrap in z-elevated span when grain is present (to sit above grain layers).\n // Without grain, render children directly to preserve flex layout.\n if (grainElements.length > 0) {\n return <span>{contentElements}</span>\n }\n return <>{contentElements}</>\n }\n\n // Async feedback: override color to show green/red\n const feedbackColorClass = isAsyncFeedback\n ? asyncState === 'success'\n ? 'bg-success-9 text-success-fg border-transparent hover:bg-success-9'\n : 'bg-error-9 text-error-fg border-transparent hover:bg-error-9'\n : undefined\n\n // Async feedback icon — uses Icon's draw animation for pen-stroke effect\n const asyncFeedbackIcon = isAsyncFeedback ? (\n <span className={cn('inline-flex shrink-0 items-center justify-center pointer-events-none', startIcon && inset.start)}>\n <Icon icon={asyncState === 'success' ? IconCheck : IconX} animate=\"draw\" />\n </span>\n ) : null\n\n const iconSize = BUTTON_TO_ICON_SIZE[resolvedSize] ?? 'md'\n\n const buttonEl = (\n <motion.button\n {...motionProps(props)}\n style={{ ...props.style, ...groupRadiusStyle }}\n className={cn(\n buttonVariants({\n // When processing (and not showing async feedback), force soft variant so ants pop\n variant: isProcessing && !isAsyncFeedback && resolvedVariant !== 'ghost' && resolvedVariant !== 'outline' && resolvedVariant !== 'link' ? 'soft' : resolvedVariant,\n color: resolvedColor,\n weight: resolvedWeight,\n size: resolvedSize,\n }),\n resolvedShape === 'pill' && 'rounded-full',\n resolvedShape === 'pill' && pillPaddingClass[resolvedSize],\n (fullWidth || groupStretch) && 'w-full',\n // Asymmetric timing: hover-out is slow+relaxed, hover-in is fast+snappy (applied via hover: override)\n !loading && !isAsyncFeedback && 'transition-[color,background-color,border-color,box-shadow,transform,filter] duration-moderate-01 ease-productive-exit',\n !loading && !isAsyncFeedback && 'hover:duration-fast-02 hover:ease-productive-entrance',\n !loading && !isAsyncFeedback && 'active:scale-[0.95] active:brightness-[0.92] active:saturate-[1.1] active:duration-[0ms]',\n feedbackColorClass,\n isAsyncFeedback && 'transition-colors duration-moderate-01 ease-productive-standard',\n isProcessing && processingDisabled && 'pointer-events-none cursor-default',\n className,\n )}\n ref={(el: HTMLButtonElement | null) => {\n btnRef.current = el\n if (typeof ref === 'function') ref(el)\n else if (ref) (ref as React.MutableRefObject<HTMLButtonElement | null>).current = el\n }}\n disabled={resolvedDisabled || (loading && !isProcessing)}\n aria-busy={loading || isProcessing || undefined}\n aria-disabled={isProcessing && processingDisabled || undefined}\n onClick={isAsync ? handleAsyncClick : (isProcessing && processingDisabled ? undefined : onClick)}\n >\n {/* Grain layers render as direct children (need absolute positioning) */}\n {grainElements}\n {/* Content renders above grain via z-[2] span wrapper */}\n {isAsyncFeedback ? asyncFeedbackIcon : renderStartSlot()}\n {isAsyncFeedback ? contentElements : renderChildren()}\n {isAsyncFeedback ? null : renderEndSlot()}\n </motion.button>\n )\n\n // Always wrap in a positioned container so the overlay can render\n // as a sibling OUTSIDE the button (not affected by disabled opacity).\n // Keeping the wrapper always-on prevents React unmount/remount on\n // processing toggle, enabling smooth CSS transitions between states.\n return (\n <IconProvider size={iconSize}>\n <span\n ref={wrapperRef}\n className={cn('relative inline-flex', fullWidth && 'w-full')}\n style={{\n ...(fullWidth || groupStretch || prefersReduced ? undefined : { transition: 'width 0.2s cubic-bezier(0.25, 0.1, 0.25, 1)' }),\n ...groupRadiusStyle,\n }}\n >\n {buttonEl}\n <ProcessingOverlay\n active={isProcessing}\n speed={processingSpeed ?? 'working'}\n color={resolvedProcessingColor}\n />\n </span>\n </IconProvider>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { Button }\n"],"mappings":"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"}
1
+ {"version":3,"file":"button.js","names":[],"sources":["../../src/ui/button.tsx"],"sourcesContent":["'use client'\n\nimport { Slot, Slottable } from '@primitives/react-slot'\nimport { IconCheck, IconX } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { getGroupPositionStyle,useButtonGroup, useButtonGroupItem } from './button-group'\nimport type { ProcessingSpeed } from './button-processing'\nimport { ProcessingOverlay } from './button-processing'\nimport { Icon } from './icon'\nimport type { IconSize } from './icon-context'\nimport { IconProvider } from './icon-context'\nimport type { IconInput } from './lib/icon-input'\nimport { normalizeIcon } from './lib/normalize-icon'\nimport { motionProps,springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\nimport { Spinner } from './spinner'\n\nexport const buttonVariants = cva(\n 'relative inline-flex items-center justify-center whitespace-nowrap font-sans select-none overflow-hidden isolate 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 disabled:cursor-not-allowed disabled:saturate-[0.3] [&>span:not([data-grain])]:relative [&>span:not([data-grain])]:z-[2]',\n {\n variants: {\n variant: {\n solid: '',\n soft: '',\n outline: 'border',\n ghost: '',\n link: 'underline-offset-4 hover:underline active:opacity-80',\n },\n color: {\n accent: '',\n error: '',\n success: '',\n warning: '',\n neutral: '',\n },\n weight: {\n semibold: 'font-semibold',\n normal: 'font-normal',\n },\n size: {\n xs: 'h-ds-xs-plus rounded-control px-ds-03 text-ds-sm gap-ds-02',\n sm: 'h-ds-sm rounded-control px-ds-04 text-ds-sm gap-ds-02b',\n md: 'h-ds-md rounded-control px-ds-05 text-ds-md gap-ds-03',\n lg: 'h-ds-lg rounded-control px-ds-06 text-ds-base gap-2.5',\n 'compact-xs': 'rounded-control px-ds-02 py-[3px] text-ds-sm gap-ds-02',\n 'compact-sm': 'rounded-control px-ds-03 py-[5px] text-ds-sm gap-ds-02b',\n 'compact-md': 'rounded-control px-ds-04 py-ds-03 text-ds-md gap-ds-03',\n icon: 'h-ds-md w-ds-md rounded-control',\n 'icon-xs': 'h-ds-xs-plus w-ds-xs-plus rounded-control',\n 'icon-sm': 'h-ds-sm w-ds-sm rounded-control',\n 'icon-md': 'h-ds-md w-ds-md rounded-control',\n 'icon-lg': 'h-ds-lg w-ds-lg rounded-control',\n },\n },\n compoundVariants: [\n // ============ SOLID ============ (colored hover shadows — shadow tints with the button's own hue)\n { variant: 'solid', color: 'accent', className: 'bg-accent-9 text-accent-fg hover:bg-accent-10 shadow-raised hover:shadow-brand' },\n { variant: 'solid', color: 'error', className: 'bg-error-9 text-error-fg hover:bg-error-10 shadow-raised hover:shadow-error' },\n { variant: 'solid', color: 'success', className: 'bg-success-9 text-success-fg hover:bg-success-10 shadow-raised hover:shadow-success' },\n { variant: 'solid', color: 'warning', className: 'bg-warning-9 text-warning-fg hover:bg-warning-10 shadow-raised hover:shadow-warning' },\n { variant: 'solid', color: 'neutral', className: 'bg-neutral-5 text-surface-fg hover:bg-neutral-7 shadow-raised' },\n\n // ============ SOFT ============\n { variant: 'soft', color: 'accent', className: 'bg-accent-3 text-accent-11 hover:bg-accent-4 active:bg-accent-5' },\n { variant: 'soft', color: 'error', className: 'bg-error-3 text-error-11 hover:bg-error-4 active:bg-error-5' },\n { variant: 'soft', color: 'success', className: 'bg-success-3 text-success-11 hover:bg-success-4 active:bg-success-5' },\n { variant: 'soft', color: 'warning', className: 'bg-warning-3 text-warning-11 hover:bg-warning-4 active:bg-warning-5' },\n { variant: 'soft', color: 'neutral', className: 'bg-surface-raised-hover text-surface-fg-muted hover:bg-surface-raised-active active:bg-neutral-5' },\n\n // ============ OUTLINE ============\n { variant: 'outline', color: 'accent', className: 'bg-transparent text-accent-11 border-accent-7 hover:bg-accent-3 active:bg-accent-4' },\n { variant: 'outline', color: 'error', className: 'bg-transparent text-error-11 border-error-7 hover:bg-error-3 active:bg-error-4' },\n { variant: 'outline', color: 'success', className: 'bg-transparent text-success-11 border-success-7 hover:bg-success-3 active:bg-success-4' },\n { variant: 'outline', color: 'warning', className: 'bg-transparent text-warning-11 border-warning-7 hover:bg-warning-3 active:bg-warning-4' },\n { variant: 'outline', color: 'neutral', className: 'bg-transparent text-surface-fg border-surface-border-strong hover:bg-surface-raised-hover active:bg-surface-raised-active' },\n\n // ============ GHOST ============\n // ghost+accent uses neutral look for backward compat (most common ghost is toolbar/icon ghost)\n { variant: 'ghost', color: 'accent', className: 'bg-transparent text-surface-fg-muted hover:bg-surface-raised-hover hover:text-surface-fg active:bg-surface-raised-active' },\n { variant: 'ghost', color: 'error', className: 'bg-transparent text-error-11 hover:bg-error-3 active:bg-error-4' },\n { variant: 'ghost', color: 'success', className: 'bg-transparent text-success-11 hover:bg-success-3 active:bg-success-4' },\n { variant: 'ghost', color: 'warning', className: 'bg-transparent text-warning-11 hover:bg-warning-3 active:bg-warning-4' },\n { variant: 'ghost', color: 'neutral', className: 'bg-transparent text-surface-fg-muted hover:bg-surface-raised-hover hover:text-surface-fg active:bg-surface-raised-active' },\n\n // ============ LINK ============\n { variant: 'link', color: 'accent', className: 'text-accent-11' },\n { variant: 'link', color: 'error', className: 'text-error-11' },\n { variant: 'link', color: 'success', className: 'text-success-11' },\n { variant: 'link', color: 'warning', className: 'text-warning-11' },\n { variant: 'link', color: 'neutral', className: 'text-surface-fg-muted' },\n ],\n defaultVariants: {\n variant: 'solid',\n color: 'accent',\n weight: 'semibold',\n size: 'md',\n },\n },\n)\n\n/** Extra horizontal padding for pill shape — rounded ends eat into visual space */\nconst pillPaddingClass: Record<string, string> = {\n xs: 'px-ds-04',\n sm: 'px-ds-05',\n md: 'px-ds-06',\n lg: 'px-ds-07',\n 'compact-xs': 'px-ds-03',\n 'compact-sm': 'px-ds-04',\n 'compact-md': 'px-ds-05',\n}\n\n/** Negative margin to tighten icon side padding — pulls icon closer to button edge */\nconst iconInsetClass: Record<string, { start: string; end: string }> = {\n xs: { start: '-ml-0.5', end: '-mr-0.5' },\n sm: { start: '-ml-1', end: '-mr-1' },\n md: { start: '-ml-1.5', end: '-mr-1.5' },\n lg: { start: '-ml-2', end: '-mr-2' },\n 'compact-xs': { start: '-ml-0.5', end: '-mr-0.5' },\n 'compact-sm': { start: '-ml-0.5', end: '-mr-0.5' },\n 'compact-md': { start: '-ml-1', end: '-mr-1' },\n icon: { start: '', end: '' },\n 'icon-xs': { start: '', end: '' },\n 'icon-sm': { start: '', end: '' },\n 'icon-md': { start: '', end: '' },\n 'icon-lg': { start: '', end: '' },\n}\n\n/** Map button size to spinner size */\nconst BUTTON_TO_SPINNER_SIZE: Record<string, 'sm' | 'md'> = {\n xs: 'sm',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n 'compact-xs': 'sm',\n 'compact-sm': 'sm',\n 'compact-md': 'sm',\n icon: 'sm',\n 'icon-xs': 'sm',\n 'icon-sm': 'sm',\n 'icon-md': 'sm',\n 'icon-lg': 'md',\n}\n\n/** Map button size to Icon context size */\nconst BUTTON_TO_ICON_SIZE: Record<string, IconSize> = {\n xs: 'xs', sm: 'sm', md: 'md', lg: 'lg',\n 'compact-xs': 'xs', 'compact-sm': 'sm', 'compact-md': 'md',\n icon: 'md', 'icon-xs': 'xs', 'icon-sm': 'sm', 'icon-md': 'md', 'icon-lg': 'lg',\n}\n\n/**\n * Props for Button — the primary action component with a two-axis variant system,\n * multiple size options, icon slots, and a built-in loading state.\n *\n * **Two axes:**\n * - `variant` controls **visual style**: `\"solid\"` (default, filled) | `\"soft\"` (tinted bg) |\n * `\"outline\"` (bordered) | `\"ghost\"` (transparent, for toolbars) | `\"link\"` (underline, inline)\n * - `color` controls **semantic intent**: `\"accent\"` (default, brand) | `\"error\"` (destructive) |\n * `\"success\"` | `\"warning\"` | `\"neutral\"` (subdued)\n *\n * **Sizes:** `xs` | `sm` | `md` (default) | `lg` for text buttons;\n * `compact-xs` | `compact-sm` | `compact-md` for height-less inline buttons;\n * `icon` | `icon-xs` | `icon-sm` | `icon-md` | `icon-lg` for square icon-only buttons.\n *\n * **Shape:** `\"default\"` uses the `--radius-control` token; `\"pill\"` applies `rounded-pill` (fully-rounded).\n *\n * **Weight:** `\"semibold\"` (default) | `\"normal\"` for lighter labels.\n *\n * **Note:** `ghost` + `accent` renders with neutral styling for backward compat —\n * most ghost buttons are toolbar/icon actions where neutral is expected.\n *\n * **Loading:** When `loading={true}` the button is disabled and aria-busy is set.\n * Use `loadingPosition` to control where the spinner appears.\n *\n * @example\n * // Primary save action (default variant + color):\n * <Button onClick={handleSave}>Save changes</Button>\n *\n * @example\n * // Soft success feedback:\n * <Button variant=\"soft\" color=\"success\" startIcon={<Icon icon={IconCheck} />}>\n * Approved\n * </Button>\n *\n * @example\n * // Destructive delete with loading state:\n * <Button variant=\"solid\" color=\"error\" startIcon={<Icon icon={IconTrash} />} loading={isDeleting}>\n * Delete project\n * </Button>\n *\n * @example\n * // Compact pill tag:\n * <Button variant=\"soft\" color=\"warning\" size=\"compact-sm\" shape=\"pill\">\n * Overdue\n * </Button>\n *\n * @example\n * // Ghost toolbar action:\n * <Button variant=\"ghost\" size=\"sm\" startIcon={<Icon icon={IconEdit} />}>\n * Edit\n * </Button>\n */\nexport interface ButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'color'>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n /** Button shape — 'pill' applies rounded-pill for chip/tag-like buttons */\n shape?: 'default' | 'pill'\n /** Icon element rendered before children — use <Icon icon={...} /> */\n startIcon?: IconInput\n /** Icon element rendered after children — use <Icon icon={...} /> */\n endIcon?: IconInput\n /** Show loading spinner and disable button */\n loading?: boolean\n /** Where to render the spinner: replaces startIcon, endIcon, or centers over children */\n loadingPosition?: 'start' | 'end' | 'center'\n /** Stretch to full width of parent */\n fullWidth?: boolean\n /**\n * Async click handler — auto-manages loading → success/error states.\n * When provided, the button shows a spinner while the promise is pending,\n * then briefly flashes green (success) or red (error) before reverting.\n * Overrides `onClick` and `loading` when active.\n */\n onClickAsync?: (e: React.MouseEvent<HTMLButtonElement>) => Promise<void>\n /** How long (ms) to show the success/error state before reverting. Default: 1500 */\n asyncFeedbackDuration?: number\n\n /**\n * Show processing animation — animated border/glow while content stays visible.\n * `true` = \"working\" speed. Semantic speeds:\n * - `\"ambient\"` (3s) — background sync, file upload\n * - `\"working\"` (2s) — standard API call, generation\n * - `\"urgent\"` (1s) — retry, nearly done\n */\n processing?: boolean | 'ambient' | 'working' | 'urgent'\n\n /** Override processing animation color. Defaults to button's own color. */\n processingColor?: 'accent' | 'error' | 'success' | 'warning' | 'neutral'\n\n /** Disable button during processing. Default: true. Set false for cancel-by-click patterns. */\n processingDisabled?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n color,\n weight,\n size,\n asChild = false,\n shape,\n startIcon,\n endIcon,\n loading: loadingProp = false,\n loadingPosition = 'start',\n fullWidth = false,\n disabled,\n onClick,\n onClickAsync,\n asyncFeedbackDuration = 1500,\n processing: processingProp,\n processingColor,\n processingDisabled = true,\n children,\n ...props\n },\n ref,\n ) => {\n const group = useButtonGroup()\n const groupItem = useButtonGroupItem()\n const resolvedVariant = variant ?? group.variant\n const resolvedColor = color ?? group.color\n const resolvedWeight = weight ?? group.weight ?? 'semibold'\n const resolvedShape = shape ?? group.shape ?? 'default'\n const resolvedSize = size ?? group.size ?? 'md'\n // ButtonGroup can propagate disabled to all children\n const resolvedDisabled = disabled ?? group.disabled\n\n // When inside an attached ButtonGroup, adjust border-radius based on position\n const groupRadiusStyle = groupItem && group.attached !== false\n ? getGroupPositionStyle(groupItem.position, group.orientation ?? 'horizontal')\n : undefined\n // Stretch to fill when inside a vertical or fullWidth ButtonGroup\n const groupStretch = group._stretch ?? false\n\n const prefersReduced = useReducedMotion()\n\n // Refs + effect for smooth width transitions (must be before any early returns)\n const wrapperRef = React.useRef<HTMLSpanElement>(null)\n const btnRef = React.useRef<HTMLButtonElement | null>(null)\n const rafRef = React.useRef<number | undefined>(undefined)\n\n \n React.useEffect(() => {\n const btn = btnRef.current\n const wrapper = wrapperRef.current\n if (!btn || !wrapper || fullWidth || groupStretch || prefersReduced) return\n\n rafRef.current = requestAnimationFrame(() => {\n wrapper.style.width = 'auto'\n const w = btn.offsetWidth\n if (w > 0) {\n wrapper.getBoundingClientRect()\n wrapper.style.width = `${w}px`\n }\n })\n return () => { if (rafRef.current) cancelAnimationFrame(rafRef.current) }\n }) // run on every render to catch content changes\n\n // Async state machine: idle → loading → success | error → idle\n type AsyncState = 'idle' | 'loading' | 'success' | 'error'\n const [asyncState, setAsyncState] = React.useState<AsyncState>('idle')\n const timeoutRef = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const isMountedRef = React.useRef(true)\n\n React.useEffect(() => () => {\n isMountedRef.current = false\n clearTimeout(timeoutRef.current)\n }, [])\n\n const handleAsyncClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!onClickAsync || asyncState !== 'idle') return\n setAsyncState('loading')\n onClickAsync(e)\n .then(() => { if (isMountedRef.current) setAsyncState('success') })\n .catch(() => { if (isMountedRef.current) setAsyncState('error') })\n .finally(() => {\n if (isMountedRef.current) {\n timeoutRef.current = setTimeout(() => {\n if (isMountedRef.current) setAsyncState('idle')\n }, asyncFeedbackDuration)\n }\n })\n }\n\n const isAsync = !!onClickAsync\n const loading = isAsync ? asyncState === 'loading' : loadingProp\n const isAsyncFeedback = asyncState === 'success' || asyncState === 'error'\n\n // Processing: explicit prop takes priority, otherwise auto-processing during onClickAsync.\n // Processing is always OFF during async feedback (success/error) so the feedback colors show.\n const autoProcessing = isAsync && asyncState === 'loading' && !processingProp\n const processingSpeed: ProcessingSpeed | undefined = isAsyncFeedback ? undefined\n : processingProp === true ? 'working'\n : processingProp === false || !processingProp\n ? (autoProcessing ? 'working' : undefined)\n : processingProp\n const isProcessing = !!processingSpeed\n const resolvedProcessingColor = processingColor ?? resolvedColor ?? 'accent'\n\n if (asChild) {\n // Slot merges all props into the child element via cloneElement at runtime.\n // We cast here because SlotProps only types React.HTMLAttributes<HTMLElement>,\n // which excludes button-specific attrs like `disabled`.\n const slotProps = {\n className: cn(\n buttonVariants({ variant: resolvedVariant, color: resolvedColor, weight: resolvedWeight, size: resolvedSize }),\n resolvedShape === 'pill' && 'rounded-pill',\n resolvedShape === 'pill' && pillPaddingClass[resolvedSize],\n (fullWidth || groupStretch) && 'w-full',\n className,\n ),\n ref,\n disabled: resolvedDisabled || loading,\n 'aria-busy': loading || undefined,\n ...props,\n } as React.ComponentPropsWithRef<typeof Slot>\n return (\n <Slot {...slotProps}>\n <Slottable>{children}</Slottable>\n </Slot>\n )\n }\n\n const inset = iconInsetClass[resolvedSize] ?? { start: '', end: '' }\n // Dim icons on filled variants (Radix pattern — icon is decorative, text is primary)\n const dimIcon = resolvedVariant === 'solid' || resolvedVariant === 'soft' || resolvedVariant === 'outline'\n\n const renderStartSlot = () => {\n if (loading && loadingPosition === 'start') {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center', startIcon && inset.start)}>\n <Spinner size={BUTTON_TO_SPINNER_SIZE[resolvedSize]} variant=\"bare\" />\n </span>\n )\n }\n if (startIcon) {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center pointer-events-none', inset.start, dimIcon && 'opacity-90')}>\n {normalizeIcon(startIcon)}\n </span>\n )\n }\n return null\n }\n\n const renderEndSlot = () => {\n if (loading && loadingPosition === 'end') {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center', endIcon && inset.end)}>\n <Spinner size={BUTTON_TO_SPINNER_SIZE[resolvedSize]} variant=\"bare\" />\n </span>\n )\n }\n if (endIcon) {\n return (\n <span className={cn('inline-flex shrink-0 items-center justify-center pointer-events-none', inset.end, dimIcon && 'opacity-90')}>\n {normalizeIcon(endIcon)}\n </span>\n )\n }\n return null\n }\n\n // Separate DevalokGrain elements (need to be direct button children for absolute positioning)\n // from text/other content (needs z-elevation above grain)\n const childArray = React.Children.toArray(children)\n const grainElements: React.ReactNode[] = []\n const contentElements: React.ReactNode[] = []\n childArray.forEach((child) => {\n if (React.isValidElement(child) && (child.type as { displayName?: string })?.displayName === 'DevalokGrain') {\n grainElements.push(child)\n } else {\n contentElements.push(child)\n }\n })\n\n const renderChildren = () => {\n if (loading && loadingPosition === 'center') {\n return (\n <span className=\"relative inline-flex items-center justify-center\">\n <span className=\"invisible\">{contentElements}</span>\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <Spinner size={BUTTON_TO_SPINNER_SIZE[resolvedSize]} variant=\"bare\" />\n </span>\n </span>\n )\n }\n // Only wrap in z-elevated span when grain is present (to sit above grain layers).\n // Without grain, render children directly to preserve flex layout.\n if (grainElements.length > 0) {\n return <span>{contentElements}</span>\n }\n return <>{contentElements}</>\n }\n\n // Async feedback: override color to show green/red\n const feedbackColorClass = isAsyncFeedback\n ? asyncState === 'success'\n ? 'bg-success-9 text-success-fg border-transparent hover:bg-success-9'\n : 'bg-error-9 text-error-fg border-transparent hover:bg-error-9'\n : undefined\n\n // Async feedback icon — uses Icon's draw animation for pen-stroke effect\n const asyncFeedbackIcon = isAsyncFeedback ? (\n <span className={cn('inline-flex shrink-0 items-center justify-center pointer-events-none', startIcon && inset.start)}>\n <Icon icon={asyncState === 'success' ? IconCheck : IconX} animate=\"draw\" />\n </span>\n ) : null\n\n const iconSize = BUTTON_TO_ICON_SIZE[resolvedSize] ?? 'md'\n\n const buttonEl = (\n <motion.button\n {...motionProps(props)}\n style={{ ...props.style, ...groupRadiusStyle }}\n className={cn(\n buttonVariants({\n // When processing (and not showing async feedback), force soft variant so ants pop\n variant: isProcessing && !isAsyncFeedback && resolvedVariant !== 'ghost' && resolvedVariant !== 'outline' && resolvedVariant !== 'link' ? 'soft' : resolvedVariant,\n color: resolvedColor,\n weight: resolvedWeight,\n size: resolvedSize,\n }),\n resolvedShape === 'pill' && 'rounded-pill',\n resolvedShape === 'pill' && pillPaddingClass[resolvedSize],\n (fullWidth || groupStretch) && 'w-full',\n // Asymmetric timing: hover-out is slow+relaxed, hover-in is fast+snappy (applied via hover: override)\n !loading && !isAsyncFeedback && 'transition-[color,background-color,border-color,box-shadow,transform,filter] duration-moderate-01 ease-productive-exit',\n !loading && !isAsyncFeedback && 'hover:duration-fast-02 hover:ease-productive-entrance',\n !loading && !isAsyncFeedback && 'active:scale-[0.95] active:brightness-[0.92] active:saturate-[1.1] active:duration-[0ms]',\n feedbackColorClass,\n isAsyncFeedback && 'transition-colors duration-moderate-01 ease-productive-standard',\n isProcessing && processingDisabled && 'pointer-events-none cursor-default',\n className,\n )}\n ref={(el: HTMLButtonElement | null) => {\n btnRef.current = el\n if (typeof ref === 'function') ref(el)\n else if (ref) (ref as React.MutableRefObject<HTMLButtonElement | null>).current = el\n }}\n disabled={resolvedDisabled || (loading && !isProcessing)}\n aria-busy={loading || isProcessing || undefined}\n aria-disabled={isProcessing && processingDisabled || undefined}\n onClick={isAsync ? handleAsyncClick : (isProcessing && processingDisabled ? undefined : onClick)}\n >\n {/* Grain layers render as direct children (need absolute positioning) */}\n {grainElements}\n {/* Content renders above grain via z-[2] span wrapper */}\n {isAsyncFeedback ? asyncFeedbackIcon : renderStartSlot()}\n {isAsyncFeedback ? contentElements : renderChildren()}\n {isAsyncFeedback ? null : renderEndSlot()}\n </motion.button>\n )\n\n // Always wrap in a positioned container so the overlay can render\n // as a sibling OUTSIDE the button (not affected by disabled opacity).\n // Keeping the wrapper always-on prevents React unmount/remount on\n // processing toggle, enabling smooth CSS transitions between states.\n return (\n <IconProvider size={iconSize}>\n <span\n ref={wrapperRef}\n className={cn('relative inline-flex', fullWidth && 'w-full')}\n style={{\n ...(fullWidth || groupStretch || prefersReduced ? undefined : { transition: 'width 0.2s cubic-bezier(0.25, 0.1, 0.25, 1)' }),\n ...groupRadiusStyle,\n }}\n >\n {buttonEl}\n <ProcessingOverlay\n active={isProcessing}\n speed={processingSpeed ?? 'working'}\n color={resolvedProcessingColor}\n />\n </span>\n </IconProvider>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { Button }\n"],"mappings":";;;;;;;;;;;;;;;;AAoBA,IAAa,IAAiB,EAC5B,qZACA;CACE,UAAU;EACR,SAAS;GACP,OAAO;GACP,MAAM;GACN,SAAS;GACT,OAAO;GACP,MAAM;GACP;EACD,OAAO;GACL,QAAQ;GACR,OAAO;GACP,SAAS;GACT,SAAS;GACT,SAAS;GACV;EACD,QAAQ;GACN,UAAU;GACV,QAAQ;GACT;EACD,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,cAAc;GACd,cAAc;GACd,cAAc;GACd,MAAM;GACN,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACZ;EACF;CACD,kBAAkB;EAEhB;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAkF;EACnI;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAA+E;EAChI;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAuF;EACxI;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAuF;EACxI;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAiE;EAGlH;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAmE;EACnH;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAA+D;EAC/G;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAuE;EACvH;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAuE;EACvH;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAoG;EAGpJ;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;GAAsF;EACzI;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;GAAkF;EACrI;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;GAA0F;EAC7I;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;GAA0F;EAC7I;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;GAA6H;EAIhL;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAA4H;EAC7K;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAmE;EACpH;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAyE;EAC1H;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAAyE;EAC1H;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;GAA4H;EAG7K;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAkB;EAClE;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAiB;EACjE;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAmB;EACnE;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAmB;EACnE;GAAE,SAAS;GAAQ,OAAO;GAAW,WAAW;GAAyB;EAC1E;CACD,iBAAiB;EACf,SAAS;EACT,OAAO;EACP,QAAQ;EACR,MAAM;EACP;CACF,CACF,EAGK,IAA2C;CAC/C,IAAc;CACd,IAAc;CACd,IAAc;CACd,IAAc;CACd,cAAc;CACd,cAAc;CACd,cAAc;CACf,EAGK,KAAiE;CACrE,IAAc;EAAE,OAAO;EAAW,KAAK;EAAW;CAClD,IAAc;EAAE,OAAO;EAAW,KAAK;EAAS;CAChD,IAAc;EAAE,OAAO;EAAW,KAAK;EAAW;CAClD,IAAc;EAAE,OAAO;EAAW,KAAK;EAAS;CAChD,cAAc;EAAE,OAAO;EAAW,KAAK;EAAW;CAClD,cAAc;EAAE,OAAO;EAAW,KAAK;EAAW;CAClD,cAAc;EAAE,OAAO;EAAW,KAAK;EAAS;CAChD,MAAc;EAAE,OAAO;EAAI,KAAK;EAAI;CACpC,WAAc;EAAE,OAAO;EAAI,KAAK;EAAI;CACpC,WAAc;EAAE,OAAO;EAAI,KAAK;EAAI;CACpC,WAAc;EAAE,OAAO;EAAI,KAAK;EAAI;CACpC,WAAc;EAAE,OAAO;EAAI,KAAK;EAAI;CACrC,EAGK,IAAsD;CAC1D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,cAAc;CACd,cAAc;CACd,cAAc;CACd,MAAM;CACN,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACZ,EAGK,KAAgD;CACpD,IAAI;CAAM,IAAI;CAAM,IAAI;CAAM,IAAI;CAClC,cAAc;CAAM,cAAc;CAAM,cAAc;CACtD,MAAM;CAAM,WAAW;CAAM,WAAW;CAAM,WAAW;CAAM,WAAW;CAC3E,EAgGK,IAAS,EAAM,YAEjB,EACE,cACA,YACA,UACA,YACA,UACA,cAAU,IACV,WACA,cACA,YACA,SAAS,KAAc,IACvB,qBAAkB,SAClB,eAAY,IACZ,cACA,aACA,iBACA,2BAAwB,MACxB,YAAY,GACZ,qBACA,wBAAqB,IACrB,aACA,GAAG,KAEL,MACG;CACH,IAAM,IAAQ,IAAgB,EACxB,IAAY,IAAoB,EAChC,IAAkB,KAAW,EAAM,SACnC,IAAgB,KAAS,EAAM,OAC/B,IAAiB,MAAU,EAAM,UAAU,YAC3C,IAAgB,MAAS,EAAM,SAAS,WACxC,IAAe,MAAQ,EAAM,QAAQ,MAErC,IAAmB,MAAY,EAAM,UAGrC,IAAmB,KAAa,EAAM,aAAa,KACrD,GAAsB,EAAU,UAAU,EAAM,eAAe,aAAa,GAC5E,KAAA,GAEE,IAAe,EAAM,YAAY,IAEjC,IAAiB,IAAkB,EAGnC,IAAa,EAAM,OAAwB,KAAK,EAChD,IAAS,EAAM,OAAiC,KAAK,EACrD,IAAS,EAAM,OAA2B,KAAA,EAAU;AAG1D,GAAM,gBAAgB;EACpB,IAAM,IAAM,EAAO,SACb,IAAU,EAAW;AACvB,SAAC,KAAO,CAAC,KAAW,KAAa,KAAgB,GAUrD,QARA,EAAO,UAAU,4BAA4B;AAC3C,KAAQ,MAAM,QAAQ;GACtB,IAAM,IAAI,EAAI;AACd,GAAI,IAAI,MACN,EAAQ,uBAAuB,EAC/B,EAAQ,MAAM,QAAQ,GAAG,EAAE;IAE7B,QACW;AAAE,GAAI,EAAO,WAAS,qBAAqB,EAAO,QAAQ;;GACvE;CAIF,IAAM,CAAC,GAAY,KAAiB,EAAM,SAAqB,OAAO,EAChE,IAAa,EAAM,OAAkD,KAAA,EAAU,EAC/E,IAAe,EAAM,OAAO,GAAK;AAEvC,GAAM,sBAAsB;AAE1B,EADA,EAAa,UAAU,IACvB,aAAa,EAAW,QAAQ;IAC/B,EAAE,CAAC;CAEN,IAAM,MAAoB,MAA2C;AAC/D,GAAC,KAAgB,MAAe,WACpC,EAAc,UAAU,EACxB,EAAa,EAAE,CACZ,WAAW;AAAE,GAAI,EAAa,WAAS,EAAc,UAAU;IAAG,CAClE,YAAY;AAAE,GAAI,EAAa,WAAS,EAAc,QAAQ;IAAG,CACjE,cAAc;AACb,GAAI,EAAa,YACf,EAAW,UAAU,iBAAiB;AACpC,IAAI,EAAa,WAAS,EAAc,OAAO;MAC9C,EAAsB;IAE3B;IAGA,IAAU,CAAC,CAAC,GACZ,IAAU,IAAU,MAAe,YAAY,IAC/C,IAAkB,MAAe,aAAa,MAAe,SAK7D,IAA+C,IAAkB,KAAA,IACnE,MAAmB,KAAO,YAC1B,MAAmB,MAAS,CAAC,IAHV,KAAW,MAAe,aAAa,CAAC,IAIvC,YAAY,KAAA,IAC9B,GACA,IAAe,CAAC,CAAC,GACjB,KAA0B,MAAmB,KAAiB;AAEpE,KAAI,GAiBF,QACE,kBAAC,GAAD;EAbA,WAAW,EACT,EAAe;GAAE,SAAS;GAAiB,OAAO;GAAe,QAAQ;GAAgB,MAAM;GAAc,CAAC,EAC9G,MAAkB,UAAU,gBAC5B,MAAkB,UAAU,EAAiB,KAC5C,KAAa,MAAiB,UAC/B,EACD;EACD;EACA,UAAU,KAAoB;EAC9B,aAAa,KAAW,KAAA;EACxB,GAAG;YAID,kBAAC,GAAD,EAAY,aAAqB,CAAA;EAC5B,CAAA;CAIX,IAAM,IAAQ,GAAe,MAAiB;EAAE,OAAO;EAAI,KAAK;EAAI,EAE9D,IAAU,MAAoB,WAAW,MAAoB,UAAU,MAAoB,WAE3F,UACA,KAAW,MAAoB,UAE/B,kBAAC,QAAD;EAAM,WAAW,EAAG,oDAAoD,KAAa,EAAM,MAAM;YAC/F,kBAAC,GAAD;GAAS,MAAM,EAAuB;GAAe,SAAQ;GAAS,CAAA;EACjE,CAAA,GAGP,IAEA,kBAAC,QAAD;EAAM,WAAW,EAAG,wEAAwE,EAAM,OAAO,KAAW,aAAa;YAC9H,EAAc,EAAU;EACpB,CAAA,GAGJ,MAGH,WACA,KAAW,MAAoB,QAE/B,kBAAC,QAAD;EAAM,WAAW,EAAG,oDAAoD,KAAW,EAAM,IAAI;YAC3F,kBAAC,GAAD;GAAS,MAAM,EAAuB;GAAe,SAAQ;GAAS,CAAA;EACjE,CAAA,GAGP,IAEA,kBAAC,QAAD;EAAM,WAAW,EAAG,wEAAwE,EAAM,KAAK,KAAW,aAAa;YAC5H,EAAc,EAAQ;EAClB,CAAA,GAGJ,MAKH,KAAa,EAAM,SAAS,QAAQ,EAAS,EAC7C,IAAmC,EAAE,EACrC,IAAqC,EAAE;AAC7C,IAAW,SAAS,MAAU;AAC5B,EAAI,EAAM,eAAe,EAAM,IAAK,EAAM,MAAmC,gBAAgB,iBAC3F,EAAc,KAAK,EAAM,GAEzB,EAAgB,KAAK,EAAM;GAE7B;CAEF,IAAM,WACA,KAAW,MAAoB,WAE/B,kBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,kBAAC,QAAD;GAAM,WAAU;aAAa;GAAuB,CAAA,EACpD,kBAAC,QAAD;GAAM,WAAU;aACd,kBAAC,GAAD;IAAS,MAAM,EAAuB;IAAe,SAAQ;IAAS,CAAA;GACjE,CAAA,CACF;MAKP,EAAc,SAAS,IAClB,kBAAC,QAAD,EAAA,UAAO,GAAuB,CAAA,GAEhC,kBAAA,IAAA,EAAA,UAAG,GAAmB,CAAA,EAIzB,KAAqB,IACvB,MAAe,YACb,uEACA,iEACF,KAAA,GAGE,KAAoB,IACxB,kBAAC,QAAD;EAAM,WAAW,EAAG,wEAAwE,KAAa,EAAM,MAAM;YACnH,kBAAC,IAAD;GAAM,MAAM,MAAe,YAAY,KAAY;GAAO,SAAQ;GAAS,CAAA;EACtE,CAAA,GACL,MAEE,KAAW,GAAoB,MAAiB,MAEhD,KACJ,kBAAC,GAAO,QAAR;EACE,GAAI,GAAY,EAAM;EACtB,OAAO;GAAE,GAAG,EAAM;GAAO,GAAG;GAAkB;EAC9C,WAAW,EACT,EAAe;GAEb,SAAS,KAAgB,CAAC,KAAmB,MAAoB,WAAW,MAAoB,aAAa,MAAoB,SAAS,SAAS;GACnJ,OAAO;GACP,QAAQ;GACR,MAAM;GACP,CAAC,EACF,MAAkB,UAAU,gBAC5B,MAAkB,UAAU,EAAiB,KAC5C,KAAa,MAAiB,UAE/B,CAAC,KAAW,CAAC,KAAmB,0HAChC,CAAC,KAAW,CAAC,KAAmB,yDAChC,CAAC,KAAW,CAAC,KAAmB,4FAChC,IACA,KAAmB,mEACnB,KAAgB,KAAsB,sCACtC,EACD;EACD,MAAM,MAAiC;AAErC,GADA,EAAO,UAAU,GACb,OAAO,KAAQ,aAAY,EAAI,EAAG,GAC7B,MAAM,EAAyD,UAAU;;EAEpF,UAAU,KAAqB,KAAW,CAAC;EAC3C,aAAW,KAAW,KAAgB,KAAA;EACtC,iBAAe,KAAgB,KAAsB,KAAA;EACrD,SAAS,IAAU,KAAoB,KAAgB,IAAqB,KAAA,IAAY;YA/B1F;GAkCG;GAEA,IAAkB,KAAoB,GAAiB;GACvD,IAAkB,IAAkB,IAAgB;GACpD,IAAkB,OAAO,IAAe;GAC3B;;AAOlB,QACE,kBAAC,GAAD;EAAc,MAAM;YAClB,kBAAC,QAAD;GACE,KAAK;GACL,WAAW,EAAG,wBAAwB,KAAa,SAAS;GAC5D,OAAO;IACL,GAAI,KAAa,KAAgB,IAAiB,KAAA,IAAY,EAAE,YAAY,+CAA+C;IAC3H,GAAG;IACJ;aANH,CAQG,IACD,kBAAC,IAAD;IACE,QAAQ;IACR,OAAO,KAAmB;IAC1B,OAAO;IACP,CAAA,CACG;;EACM,CAAA;EAGpB;AACD,EAAO,cAAc"}
package/dist/ui/card.js CHANGED
@@ -6,7 +6,7 @@ import * as a from "react";
6
6
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
7
  import { motion as c } from "framer-motion";
8
8
  //#region src/ui/card.tsx
9
- var l = a.createContext("md"), u = r("rounded-ds-lg text-surface-fg transition-shadow duration-fast-02 ease-productive-standard", {
9
+ var l = a.createContext("md"), u = r("rounded-surface text-surface-fg transition-shadow duration-fast-02 ease-productive-standard", {
10
10
  variants: {
11
11
  variant: {
12
12
  default: "bg-surface-raised border border-surface-border shadow-raised",
@@ -67,10 +67,10 @@ var l = a.createContext("md"), u = r("rounded-ds-lg text-surface-fg transition-s
67
67
  6: "h-[6px]"
68
68
  }
69
69
  }, p = {
70
- left: "left-0 top-0 bottom-0 rounded-l-ds-lg",
71
- top: "top-0 left-0 right-0 rounded-t-ds-lg",
72
- right: "right-0 top-0 bottom-0 rounded-r-ds-lg",
73
- bottom: "bottom-0 left-0 right-0 rounded-b-ds-lg"
70
+ left: "left-0 top-0 bottom-0 rounded-l-surface",
71
+ top: "top-0 left-0 right-0 rounded-t-surface",
72
+ right: "right-0 top-0 bottom-0 rounded-r-surface",
73
+ bottom: "bottom-0 left-0 right-0 rounded-b-surface"
74
74
  };
75
75
  function m(e, t) {
76
76
  return `${p[e] ?? ""} ${f[e]?.[t] ?? ""}`;
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","names":[],"sources":["../../src/ui/card.tsx"],"sourcesContent":["'use client'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\ntype CardSize = 'sm' | 'md' | 'lg'\n\nconst CardSizeContext = React.createContext<CardSize>('md')\n\nconst cardVariants = cva(\n 'rounded-ds-lg text-surface-fg transition-shadow duration-fast-02 ease-productive-standard',\n {\n variants: {\n variant: {\n default: 'bg-surface-raised border border-surface-border shadow-raised',\n elevated: 'bg-surface-raised border border-surface-border shadow-raised-hover',\n outline: 'bg-transparent border border-surface-border-strong shadow-none',\n flat: 'bg-surface-raised border-none shadow-none',\n },\n color: {\n default: '',\n accent: 'border-accent-7',\n error: 'border-error-7',\n success: 'border-success-7',\n warning: 'border-warning-7',\n info: 'border-info-7',\n neutral: '',\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n },\n defaultVariants: { variant: 'default', color: 'default', size: 'md' },\n },\n)\n\n/**\n * Props for Card — a general-purpose content container with 4 elevation/style variants and\n * an optional interactive hover state.\n *\n * **Variants:** `default` (subtle border + shadow-raised) | `elevated` (stronger shadow-raised-hover) |\n * `outline` (2px solid border, no shadow) | `flat` (filled background, no shadow)\n *\n * **Composition:** Use sub-components `<CardHeader>`, `<CardTitle>`, `<CardDescription>`,\n * `<CardContent>`, and `<CardFooter>` for consistent internal spacing.\n *\n * **Interactive:** Pass `interactive` to enable hover shadow lift and pointer cursor —\n * useful for clickable cards in grids.\n *\n * @example\n * // Standard content card with header and body:\n * <Card>\n * <CardHeader>\n * <CardTitle>Project Alpha</CardTitle>\n * <CardDescription>Last updated 2 hours ago</CardDescription>\n * </CardHeader>\n * <CardContent>\n * <p>Sprint 4 is in progress with 12 open tasks.</p>\n * </CardContent>\n * </Card>\n *\n * @example\n * // Elevated card for a dashboard stat widget:\n * <Card variant=\"elevated\">\n * <CardContent>\n * <StatCard label=\"Revenue\" value=\"$12,400\" delta={{ value: \"+8%\", direction: \"up\" }} />\n * </CardContent>\n * </Card>\n *\n * @example\n * // Clickable card in a project grid (interactive hover effect):\n * <Card interactive onClick={() => router.push(`/projects/${id}`)}>\n * <CardHeader>\n * <CardTitle>{project.name}</CardTitle>\n * </CardHeader>\n * </Card>\n *\n * @example\n * // Flat card for a sidebar panel section (no shadow):\n * <Card variant=\"flat\" className=\"p-ds-05\">\n * <p className=\"text-surface-fg-muted text-ds-sm\">No recent activity</p>\n * </Card>\n * // These are just a few ways — feel free to combine props creatively!\n */\nconst accentColorMap: Record<string, string> = {\n default: 'var(--color-accent-9)',\n secondary: 'var(--color-secondary-9)',\n error: 'var(--color-error-9)',\n success: 'var(--color-success-9)',\n warning: 'var(--color-warning-9)',\n info: 'var(--color-info-9)',\n}\n\nexport interface CardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof cardVariants> {\n interactive?: boolean\n /** Position of the accent border strip */\n accent?: 'left' | 'top' | 'right' | 'bottom'\n /** Semantic color key or any CSS color string for the accent strip. Requires `accent` to be set. @default 'default' */\n accentColor?: 'default' | 'secondary' | 'error' | 'success' | 'warning' | 'info' | (string & {})\n /** Width of the accent strip in pixels @default 3 */\n accentWidth?: 2 | 3 | 4 | 6\n}\n\nexport type { CardSize }\n\nconst accentSizeClasses: Record<string, Record<number, string>> = {\n left: { 2: 'w-[2px]', 3: 'w-[3px]', 4: 'w-[4px]', 6: 'w-[6px]' },\n top: { 2: 'h-[2px]', 3: 'h-[3px]', 4: 'h-[4px]', 6: 'h-[6px]' },\n right: { 2: 'w-[2px]', 3: 'w-[3px]', 4: 'w-[4px]', 6: 'w-[6px]' },\n bottom: { 2: 'h-[2px]', 3: 'h-[3px]', 4: 'h-[4px]', 6: 'h-[6px]' },\n}\n\nconst accentPositionClasses: Record<string, string> = {\n left: 'left-0 top-0 bottom-0 rounded-l-ds-lg',\n top: 'top-0 left-0 right-0 rounded-t-ds-lg',\n right: 'right-0 top-0 bottom-0 rounded-r-ds-lg',\n bottom: 'bottom-0 left-0 right-0 rounded-b-ds-lg',\n}\n\nfunction getAccentPositionClasses(position: string, width: number): string {\n return `${accentPositionClasses[position] ?? ''} ${accentSizeClasses[position]?.[width] ?? ''}`\n}\n\nfunction resolveAccentColor(color: string): string {\n return accentColorMap[color] ?? color\n}\n\nconst Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant, color, size, interactive, accent, accentColor = 'default', accentWidth = 3, children, ...props }, ref) => {\n const resolvedSize: CardSize = size ?? 'md'\n const classes = cn(\n cardVariants({ variant, color, size }),\n accent && 'relative overflow-hidden',\n interactive && 'hover:shadow-raised-hover hover:border-surface-border-strong cursor-pointer transition-shadow duration-fast-02 ease-productive-standard',\n className,\n )\n\n const accentEl = accent ? (\n <motion.span\n aria-hidden=\"true\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweens.fade}\n className={cn('absolute pointer-events-none bg-[var(--card-accent-bg)]', getAccentPositionClasses(accent, accentWidth))}\n style={{ '--card-accent-bg': resolveAccentColor(accentColor) } as React.CSSProperties}\n />\n ) : null\n\n const content = (\n <CardSizeContext.Provider value={resolvedSize}>\n {accentEl}\n {children}\n </CardSizeContext.Provider>\n )\n\n if (interactive) {\n return (\n <motion.div\n ref={ref}\n whileHover={{ y: -3 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n className={classes}\n {...motionProps(props)}\n >\n {content}\n </motion.div>\n )\n }\n\n return (\n <div ref={ref} className={classes} {...props}>\n {content}\n </div>\n )\n },\n)\nCard.displayName = 'Card'\n\nconst headerSizeClasses: Record<CardSize, string> = {\n sm: 'p-ds-05',\n md: 'p-ds-06',\n lg: 'p-ds-07',\n}\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const size = React.useContext(CardSizeContext)\n return (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-ds-02b', headerSizeClasses[size], className)}\n {...props}\n />\n )\n})\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('font-sans font-semibold leading-ds-none tracking-normal text-surface-fg', className)}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-ds-md text-surface-fg-muted', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst contentSizeClasses: Record<CardSize, string> = {\n sm: 'p-ds-05 pt-0',\n md: 'p-ds-06 pt-0',\n lg: 'p-ds-07 pt-0',\n}\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const size = React.useContext(CardSizeContext)\n return (\n <div ref={ref} className={cn(contentSizeClasses[size], className)} {...props} />\n )\n})\nCardContent.displayName = 'CardContent'\n\nconst footerSizeClasses: Record<CardSize, string> = {\n sm: 'p-ds-05 pt-0',\n md: 'p-ds-06 pt-0',\n lg: 'p-ds-07 pt-0',\n}\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const size = React.useContext(CardSizeContext)\n return (\n <div\n ref={ref}\n className={cn('flex items-center', footerSizeClasses[size], className)}\n {...props}\n />\n )\n})\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardContent,CardDescription, CardFooter, CardHeader, CardTitle, cardVariants }\n"],"mappings":"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"}
1
+ {"version":3,"file":"card.js","names":[],"sources":["../../src/ui/card.tsx"],"sourcesContent":["'use client'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\ntype CardSize = 'sm' | 'md' | 'lg'\n\nconst CardSizeContext = React.createContext<CardSize>('md')\n\nconst cardVariants = cva(\n 'rounded-surface text-surface-fg transition-shadow duration-fast-02 ease-productive-standard',\n {\n variants: {\n variant: {\n default: 'bg-surface-raised border border-surface-border shadow-raised',\n elevated: 'bg-surface-raised border border-surface-border shadow-raised-hover',\n outline: 'bg-transparent border border-surface-border-strong shadow-none',\n flat: 'bg-surface-raised border-none shadow-none',\n },\n color: {\n default: '',\n accent: 'border-accent-7',\n error: 'border-error-7',\n success: 'border-success-7',\n warning: 'border-warning-7',\n info: 'border-info-7',\n neutral: '',\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n },\n defaultVariants: { variant: 'default', color: 'default', size: 'md' },\n },\n)\n\n/**\n * Props for Card — a general-purpose content container with 4 elevation/style variants and\n * an optional interactive hover state.\n *\n * **Variants:** `default` (subtle border + shadow-raised) | `elevated` (stronger shadow-raised-hover) |\n * `outline` (2px solid border, no shadow) | `flat` (filled background, no shadow)\n *\n * **Composition:** Use sub-components `<CardHeader>`, `<CardTitle>`, `<CardDescription>`,\n * `<CardContent>`, and `<CardFooter>` for consistent internal spacing.\n *\n * **Interactive:** Pass `interactive` to enable hover shadow lift and pointer cursor —\n * useful for clickable cards in grids.\n *\n * @example\n * // Standard content card with header and body:\n * <Card>\n * <CardHeader>\n * <CardTitle>Project Alpha</CardTitle>\n * <CardDescription>Last updated 2 hours ago</CardDescription>\n * </CardHeader>\n * <CardContent>\n * <p>Sprint 4 is in progress with 12 open tasks.</p>\n * </CardContent>\n * </Card>\n *\n * @example\n * // Elevated card for a dashboard stat widget:\n * <Card variant=\"elevated\">\n * <CardContent>\n * <StatCard label=\"Revenue\" value=\"$12,400\" delta={{ value: \"+8%\", direction: \"up\" }} />\n * </CardContent>\n * </Card>\n *\n * @example\n * // Clickable card in a project grid (interactive hover effect):\n * <Card interactive onClick={() => router.push(`/projects/${id}`)}>\n * <CardHeader>\n * <CardTitle>{project.name}</CardTitle>\n * </CardHeader>\n * </Card>\n *\n * @example\n * // Flat card for a sidebar panel section (no shadow):\n * <Card variant=\"flat\" className=\"p-ds-05\">\n * <p className=\"text-surface-fg-muted text-ds-sm\">No recent activity</p>\n * </Card>\n * // These are just a few ways — feel free to combine props creatively!\n */\nconst accentColorMap: Record<string, string> = {\n default: 'var(--color-accent-9)',\n secondary: 'var(--color-secondary-9)',\n error: 'var(--color-error-9)',\n success: 'var(--color-success-9)',\n warning: 'var(--color-warning-9)',\n info: 'var(--color-info-9)',\n}\n\nexport interface CardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof cardVariants> {\n interactive?: boolean\n /** Position of the accent border strip */\n accent?: 'left' | 'top' | 'right' | 'bottom'\n /** Semantic color key or any CSS color string for the accent strip. Requires `accent` to be set. @default 'default' */\n accentColor?: 'default' | 'secondary' | 'error' | 'success' | 'warning' | 'info' | (string & {})\n /** Width of the accent strip in pixels @default 3 */\n accentWidth?: 2 | 3 | 4 | 6\n}\n\nexport type { CardSize }\n\nconst accentSizeClasses: Record<string, Record<number, string>> = {\n left: { 2: 'w-[2px]', 3: 'w-[3px]', 4: 'w-[4px]', 6: 'w-[6px]' },\n top: { 2: 'h-[2px]', 3: 'h-[3px]', 4: 'h-[4px]', 6: 'h-[6px]' },\n right: { 2: 'w-[2px]', 3: 'w-[3px]', 4: 'w-[4px]', 6: 'w-[6px]' },\n bottom: { 2: 'h-[2px]', 3: 'h-[3px]', 4: 'h-[4px]', 6: 'h-[6px]' },\n}\n\nconst accentPositionClasses: Record<string, string> = {\n left: 'left-0 top-0 bottom-0 rounded-l-surface',\n top: 'top-0 left-0 right-0 rounded-t-surface',\n right: 'right-0 top-0 bottom-0 rounded-r-surface',\n bottom: 'bottom-0 left-0 right-0 rounded-b-surface',\n}\n\nfunction getAccentPositionClasses(position: string, width: number): string {\n return `${accentPositionClasses[position] ?? ''} ${accentSizeClasses[position]?.[width] ?? ''}`\n}\n\nfunction resolveAccentColor(color: string): string {\n return accentColorMap[color] ?? color\n}\n\nconst Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant, color, size, interactive, accent, accentColor = 'default', accentWidth = 3, children, ...props }, ref) => {\n const resolvedSize: CardSize = size ?? 'md'\n const classes = cn(\n cardVariants({ variant, color, size }),\n accent && 'relative overflow-hidden',\n interactive && 'hover:shadow-raised-hover hover:border-surface-border-strong cursor-pointer transition-shadow duration-fast-02 ease-productive-standard',\n className,\n )\n\n const accentEl = accent ? (\n <motion.span\n aria-hidden=\"true\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweens.fade}\n className={cn('absolute pointer-events-none bg-[var(--card-accent-bg)]', getAccentPositionClasses(accent, accentWidth))}\n style={{ '--card-accent-bg': resolveAccentColor(accentColor) } as React.CSSProperties}\n />\n ) : null\n\n const content = (\n <CardSizeContext.Provider value={resolvedSize}>\n {accentEl}\n {children}\n </CardSizeContext.Provider>\n )\n\n if (interactive) {\n return (\n <motion.div\n ref={ref}\n whileHover={{ y: -3 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n className={classes}\n {...motionProps(props)}\n >\n {content}\n </motion.div>\n )\n }\n\n return (\n <div ref={ref} className={classes} {...props}>\n {content}\n </div>\n )\n },\n)\nCard.displayName = 'Card'\n\nconst headerSizeClasses: Record<CardSize, string> = {\n sm: 'p-ds-05',\n md: 'p-ds-06',\n lg: 'p-ds-07',\n}\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const size = React.useContext(CardSizeContext)\n return (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-ds-02b', headerSizeClasses[size], className)}\n {...props}\n />\n )\n})\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('font-sans font-semibold leading-ds-none tracking-normal text-surface-fg', className)}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-ds-md text-surface-fg-muted', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst contentSizeClasses: Record<CardSize, string> = {\n sm: 'p-ds-05 pt-0',\n md: 'p-ds-06 pt-0',\n lg: 'p-ds-07 pt-0',\n}\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const size = React.useContext(CardSizeContext)\n return (\n <div ref={ref} className={cn(contentSizeClasses[size], className)} {...props} />\n )\n})\nCardContent.displayName = 'CardContent'\n\nconst footerSizeClasses: Record<CardSize, string> = {\n sm: 'p-ds-05 pt-0',\n md: 'p-ds-06 pt-0',\n lg: 'p-ds-07 pt-0',\n}\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const size = React.useContext(CardSizeContext)\n return (\n <div\n ref={ref}\n className={cn('flex items-center', footerSizeClasses[size], className)}\n {...props}\n />\n )\n})\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardContent,CardDescription, CardFooter, CardHeader, CardTitle, cardVariants }\n"],"mappings":"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"}