@devalok/shilp-sutra 0.49.3 → 0.49.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/dist/_chunks/badge-group.js +8 -7
  2. package/dist/_chunks/badge-group.js.map +1 -1
  3. package/dist/_chunks/block-shell.js.map +1 -1
  4. package/dist/_chunks/chart-container.js.map +1 -1
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/colors.js.map +1 -1
  7. package/dist/_chunks/document-preview.js.map +1 -1
  8. package/dist/_chunks/emoji-suggestion.js.map +1 -1
  9. package/dist/_chunks/emoji.js +2 -2
  10. package/dist/_chunks/emoji.js.map +1 -1
  11. package/dist/_chunks/field-state.js.map +1 -1
  12. package/dist/_chunks/grid-lines.js.map +1 -1
  13. package/dist/_chunks/image-preview.js.map +1 -1
  14. package/dist/_chunks/keybinding.js.map +1 -1
  15. package/dist/_chunks/link-context.js.map +1 -1
  16. package/dist/_chunks/mention-suggestion.js.map +1 -1
  17. package/dist/_chunks/motion-provider.js.map +1 -1
  18. package/dist/_chunks/normalize-icon.js.map +1 -1
  19. package/dist/_chunks/oauth-button.js.map +1 -1
  20. package/dist/_chunks/popover.js.map +1 -1
  21. package/dist/_chunks/primitives.js +1123 -1153
  22. package/dist/_chunks/primitives.js.map +1 -1
  23. package/dist/_chunks/shared.js.map +1 -1
  24. package/dist/_chunks/success.js.map +1 -1
  25. package/dist/_chunks/tiptap.js +4283 -3460
  26. package/dist/_chunks/tiptap.js.map +1 -1
  27. package/dist/_chunks/tooltip.js.map +1 -1
  28. package/dist/_chunks/tree-view.js +1 -1
  29. package/dist/_chunks/tree-view.js.map +1 -1
  30. package/dist/_chunks/use-calendar.js.map +1 -1
  31. package/dist/_chunks/use-controllable-open.js.map +1 -1
  32. package/dist/_chunks/vendor-client.js +86 -59
  33. package/dist/_chunks/vendor-client.js.map +1 -1
  34. package/dist/_chunks/vendor-utils.js +555 -513
  35. package/dist/_chunks/vendor-utils.js.map +1 -1
  36. package/dist/ai/ai-command-provider.d.ts +1 -1
  37. package/dist/ai/ai-command-provider.d.ts.map +1 -1
  38. package/dist/ai/ai-command-provider.js.map +1 -1
  39. package/dist/ai/block-renderer.js.map +1 -1
  40. package/dist/ai/blocks/block-shell.d.ts +1 -1
  41. package/dist/ai/blocks/block-shell.d.ts.map +1 -1
  42. package/dist/ai/blocks/block-table.d.ts +1 -1
  43. package/dist/ai/blocks/block-table.d.ts.map +1 -1
  44. package/dist/ai/blocks/confirm.d.ts +1 -1
  45. package/dist/ai/blocks/confirm.d.ts.map +1 -1
  46. package/dist/ai/blocks/divider.d.ts +1 -1
  47. package/dist/ai/blocks/divider.d.ts.map +1 -1
  48. package/dist/ai/blocks/error.d.ts +1 -1
  49. package/dist/ai/blocks/error.d.ts.map +1 -1
  50. package/dist/ai/blocks/error.js.map +1 -1
  51. package/dist/ai/blocks/info.d.ts +1 -1
  52. package/dist/ai/blocks/info.d.ts.map +1 -1
  53. package/dist/ai/blocks/loading.d.ts +1 -1
  54. package/dist/ai/blocks/loading.d.ts.map +1 -1
  55. package/dist/ai/blocks/stat-row.d.ts +1 -1
  56. package/dist/ai/blocks/stat-row.d.ts.map +1 -1
  57. package/dist/ai/blocks/success.d.ts +1 -1
  58. package/dist/ai/blocks/success.d.ts.map +1 -1
  59. package/dist/ai/blocks/text.d.ts +1 -1
  60. package/dist/ai/blocks/text.d.ts.map +1 -1
  61. package/dist/ai/blocks/text.js.map +1 -1
  62. package/dist/ai/command-bar.js.map +1 -1
  63. package/dist/ai/conversation.js.map +1 -1
  64. package/dist/ai/devadoot-icon.d.ts +1 -1
  65. package/dist/ai/devadoot-icon.d.ts.map +1 -1
  66. package/dist/ai/index.js.map +1 -1
  67. package/dist/composed/activity-feed.js.map +1 -1
  68. package/dist/composed/avatar-group.js.map +1 -1
  69. package/dist/composed/bulk-action-bar.js.map +1 -1
  70. package/dist/composed/command-palette.js.map +1 -1
  71. package/dist/composed/confirm-dialog.js.map +1 -1
  72. package/dist/composed/content-card.js.map +1 -1
  73. package/dist/composed/date-picker/index.js.map +1 -1
  74. package/dist/composed/deadline-indicator.js.map +1 -1
  75. package/dist/composed/emoji-picker.d.ts +2 -2
  76. package/dist/composed/emoji-picker.d.ts.map +1 -1
  77. package/dist/composed/emoji-picker.js.map +1 -1
  78. package/dist/composed/empty-state.js.map +1 -1
  79. package/dist/composed/error-boundary.d.ts +1 -1
  80. package/dist/composed/error-boundary.js.map +1 -1
  81. package/dist/composed/extensions/emoji-node.js.map +1 -1
  82. package/dist/composed/file-preview/audio-preview.d.ts +2 -1
  83. package/dist/composed/file-preview/audio-preview.d.ts.map +1 -1
  84. package/dist/composed/file-preview/document-preview.d.ts +2 -1
  85. package/dist/composed/file-preview/document-preview.d.ts.map +1 -1
  86. package/dist/composed/file-preview/embed-preview.d.ts +2 -1
  87. package/dist/composed/file-preview/embed-preview.d.ts.map +1 -1
  88. package/dist/composed/file-preview/image-preview.d.ts +2 -1
  89. package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
  90. package/dist/composed/file-preview/shared.d.ts +5 -5
  91. package/dist/composed/file-preview/shared.d.ts.map +1 -1
  92. package/dist/composed/file-preview/video-preview.d.ts +2 -1
  93. package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
  94. package/dist/composed/file-preview.d.ts +1 -1
  95. package/dist/composed/file-preview.d.ts.map +1 -1
  96. package/dist/composed/file-preview.js.map +1 -1
  97. package/dist/composed/filter-bar.d.ts +2 -2
  98. package/dist/composed/filter-bar.d.ts.map +1 -1
  99. package/dist/composed/filter-bar.js.map +1 -1
  100. package/dist/composed/form-section.js.map +1 -1
  101. package/dist/composed/global-loading.js.map +1 -1
  102. package/dist/composed/inline-edit.js.map +1 -1
  103. package/dist/composed/lib/string-utils.js.map +1 -1
  104. package/dist/composed/loading-skeleton.js.map +1 -1
  105. package/dist/composed/markdown-viewer.js.map +1 -1
  106. package/dist/composed/master-detail.d.ts +3 -3
  107. package/dist/composed/master-detail.d.ts.map +1 -1
  108. package/dist/composed/master-detail.js.map +1 -1
  109. package/dist/composed/member-picker.js.map +1 -1
  110. package/dist/composed/multi-select-popover.js.map +1 -1
  111. package/dist/composed/page-header.js.map +1 -1
  112. package/dist/composed/page-skeletons.js.map +1 -1
  113. package/dist/composed/priority-indicator.js.map +1 -1
  114. package/dist/composed/responsive-modal.js +8 -4
  115. package/dist/composed/responsive-modal.js.map +1 -1
  116. package/dist/composed/rich-chat-input/attachment-strip.d.ts +2 -1
  117. package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
  118. package/dist/composed/rich-chat-input/chat-toolbar.d.ts +17 -17
  119. package/dist/composed/rich-chat-input/chat-toolbar.d.ts.map +1 -1
  120. package/dist/composed/rich-chat-input/recording-overlay.d.ts +2 -1
  121. package/dist/composed/rich-chat-input/recording-overlay.d.ts.map +1 -1
  122. package/dist/composed/rich-chat-input/reply-banner.d.ts +2 -1
  123. package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
  124. package/dist/composed/rich-chat-input/schedule-send.d.ts +4 -3
  125. package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
  126. package/dist/composed/rich-chat-input.js +2 -1
  127. package/dist/composed/rich-chat-input.js.map +1 -1
  128. package/dist/composed/rich-text-editor.js +2 -1
  129. package/dist/composed/rich-text-editor.js.map +1 -1
  130. package/dist/composed/schedule-view.js.map +1 -1
  131. package/dist/composed/simple-tooltip.js.map +1 -1
  132. package/dist/composed/status-badge.js.map +1 -1
  133. package/dist/hooks/use-color-mode.js +2 -1
  134. package/dist/hooks/use-color-mode.js.map +1 -1
  135. package/dist/hooks/use-mobile.js.map +1 -1
  136. package/dist/hooks/use-touch-device.js.map +1 -1
  137. package/dist/hooks/use-viewport-height.js.map +1 -1
  138. package/dist/motion/index.js.map +1 -1
  139. package/dist/motion/motion-provider.d.ts +1 -1
  140. package/dist/motion/motion-provider.d.ts.map +1 -1
  141. package/dist/motion/primitives-index.js.map +1 -1
  142. package/dist/shell/app-command-palette.js.map +1 -1
  143. package/dist/shell/bottom-navbar.js.map +1 -1
  144. package/dist/shell/command-registry.d.ts +1 -1
  145. package/dist/shell/command-registry.d.ts.map +1 -1
  146. package/dist/shell/command-registry.js.map +1 -1
  147. package/dist/shell/notification-center.js.map +1 -1
  148. package/dist/shell/notification-preferences.js.map +1 -1
  149. package/dist/shell/sidebar.js.map +1 -1
  150. package/dist/shell/top-bar.js.map +1 -1
  151. package/dist/ui/accordion.js.map +1 -1
  152. package/dist/ui/alert-dialog.js.map +1 -1
  153. package/dist/ui/alert.js.map +1 -1
  154. package/dist/ui/aspect-ratio.js.map +1 -1
  155. package/dist/ui/autocomplete.d.ts.map +1 -1
  156. package/dist/ui/autocomplete.js +8 -0
  157. package/dist/ui/autocomplete.js.map +1 -1
  158. package/dist/ui/avatar.d.ts +1 -1
  159. package/dist/ui/avatar.js.map +1 -1
  160. package/dist/ui/badge-group.d.ts +2 -6
  161. package/dist/ui/badge-group.d.ts.map +1 -1
  162. package/dist/ui/badge-indicator.d.ts +2 -6
  163. package/dist/ui/badge-indicator.d.ts.map +1 -1
  164. package/dist/ui/badge-indicator.js +19 -18
  165. package/dist/ui/badge-indicator.js.map +1 -1
  166. package/dist/ui/badge.d.ts +2 -4
  167. package/dist/ui/badge.d.ts.map +1 -1
  168. package/dist/ui/banner.js.map +1 -1
  169. package/dist/ui/breadcrumb.d.ts +2 -2
  170. package/dist/ui/breadcrumb.js.map +1 -1
  171. package/dist/ui/button-group.js.map +1 -1
  172. package/dist/ui/button-processing.d.ts +2 -1
  173. package/dist/ui/button-processing.d.ts.map +1 -1
  174. package/dist/ui/button-processing.js.map +1 -1
  175. package/dist/ui/button.js.map +1 -1
  176. package/dist/ui/card.js +1 -1
  177. package/dist/ui/card.js.map +1 -1
  178. package/dist/ui/charts/_internal/axes.d.ts +2 -1
  179. package/dist/ui/charts/_internal/axes.d.ts.map +1 -1
  180. package/dist/ui/charts/_internal/grid-lines.d.ts +2 -1
  181. package/dist/ui/charts/_internal/grid-lines.d.ts.map +1 -1
  182. package/dist/ui/charts/_internal/legend.d.ts +2 -1
  183. package/dist/ui/charts/_internal/legend.d.ts.map +1 -1
  184. package/dist/ui/charts/_internal/tooltip.d.ts +1 -1
  185. package/dist/ui/charts/_internal/tooltip.d.ts.map +1 -1
  186. package/dist/ui/charts/area-chart.js.map +1 -1
  187. package/dist/ui/charts/bar-chart.js.map +1 -1
  188. package/dist/ui/charts/gauge-chart.js.map +1 -1
  189. package/dist/ui/charts/line-chart.js.map +1 -1
  190. package/dist/ui/charts/pie-chart.js.map +1 -1
  191. package/dist/ui/charts/radar-chart.js.map +1 -1
  192. package/dist/ui/charts/sparkline.js +2 -2
  193. package/dist/ui/charts/sparkline.js.map +1 -1
  194. package/dist/ui/chat/date-separator.d.ts +2 -1
  195. package/dist/ui/chat/date-separator.d.ts.map +1 -1
  196. package/dist/ui/chat/message.d.ts +8 -8
  197. package/dist/ui/chat/message.d.ts.map +1 -1
  198. package/dist/ui/chat/typing-indicator.d.ts +2 -1
  199. package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
  200. package/dist/ui/chat/unread-separator.d.ts +2 -1
  201. package/dist/ui/chat/unread-separator.d.ts.map +1 -1
  202. package/dist/ui/checkbox.js.map +1 -1
  203. package/dist/ui/code.js.map +1 -1
  204. package/dist/ui/collapsible.js.map +1 -1
  205. package/dist/ui/color-input.d.ts.map +1 -1
  206. package/dist/ui/color-input.js +156 -149
  207. package/dist/ui/color-input.js.map +1 -1
  208. package/dist/ui/color-swatch.js.map +1 -1
  209. package/dist/ui/combobox.d.ts.map +1 -1
  210. package/dist/ui/combobox.js +137 -127
  211. package/dist/ui/combobox.js.map +1 -1
  212. package/dist/ui/container.js.map +1 -1
  213. package/dist/ui/context-menu.d.ts +2 -2
  214. package/dist/ui/context-menu.js.map +1 -1
  215. package/dist/ui/data-table-body.d.ts +1 -1
  216. package/dist/ui/data-table-body.d.ts.map +1 -1
  217. package/dist/ui/data-table-body.js +1 -1
  218. package/dist/ui/data-table-body.js.map +1 -1
  219. package/dist/ui/data-table-bulk-actions.d.ts +2 -1
  220. package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
  221. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  222. package/dist/ui/data-table-card.d.ts +1 -1
  223. package/dist/ui/data-table-card.d.ts.map +1 -1
  224. package/dist/ui/data-table-card.js.map +1 -1
  225. package/dist/ui/data-table-context.d.ts +1 -1
  226. package/dist/ui/data-table-context.d.ts.map +1 -1
  227. package/dist/ui/data-table-context.js.map +1 -1
  228. package/dist/ui/data-table-header.d.ts +2 -1
  229. package/dist/ui/data-table-header.d.ts.map +1 -1
  230. package/dist/ui/data-table-header.js.map +1 -1
  231. package/dist/ui/data-table-pagination.d.ts +2 -1
  232. package/dist/ui/data-table-pagination.d.ts.map +1 -1
  233. package/dist/ui/data-table-pagination.js.map +1 -1
  234. package/dist/ui/data-table-toolbar.d.ts +1 -1
  235. package/dist/ui/data-table-toolbar.d.ts.map +1 -1
  236. package/dist/ui/data-table-toolbar.js.map +1 -1
  237. package/dist/ui/data-table.d.ts +1 -1
  238. package/dist/ui/data-table.d.ts.map +1 -1
  239. package/dist/ui/data-table.js.map +1 -1
  240. package/dist/ui/devalok-grain.d.ts +2 -1
  241. package/dist/ui/devalok-grain.d.ts.map +1 -1
  242. package/dist/ui/devalok-grain.js.map +1 -1
  243. package/dist/ui/dialog.js.map +1 -1
  244. package/dist/ui/dot.js +1 -1
  245. package/dist/ui/dot.js.map +1 -1
  246. package/dist/ui/dropdown-menu.d.ts +1 -1
  247. package/dist/ui/dropdown-menu.js.map +1 -1
  248. package/dist/ui/file-upload.js.map +1 -1
  249. package/dist/ui/form.js.map +1 -1
  250. package/dist/ui/hover-card.js.map +1 -1
  251. package/dist/ui/icon-button.js.map +1 -1
  252. package/dist/ui/icon-context.d.ts +1 -1
  253. package/dist/ui/icon-context.d.ts.map +1 -1
  254. package/dist/ui/icon-context.js.map +1 -1
  255. package/dist/ui/icon-group.js.map +1 -1
  256. package/dist/ui/icon.js.map +1 -1
  257. package/dist/ui/index.js.map +1 -1
  258. package/dist/ui/input-otp.js.map +1 -1
  259. package/dist/ui/input.js.map +1 -1
  260. package/dist/ui/label.js.map +1 -1
  261. package/dist/ui/lib/bottom-sheet.d.ts +1 -1
  262. package/dist/ui/lib/bottom-sheet.d.ts.map +1 -1
  263. package/dist/ui/lib/date-utils.js.map +1 -1
  264. package/dist/ui/lib/link-context.d.ts +1 -1
  265. package/dist/ui/lib/link-context.d.ts.map +1 -1
  266. package/dist/ui/lib/motion.js.map +1 -1
  267. package/dist/ui/lib/utils.js.map +1 -1
  268. package/dist/ui/link.js.map +1 -1
  269. package/dist/ui/menubar.d.ts +1 -1
  270. package/dist/ui/menubar.js.map +1 -1
  271. package/dist/ui/navigation-menu.js +14 -9
  272. package/dist/ui/navigation-menu.js.map +1 -1
  273. package/dist/ui/number-input.d.ts.map +1 -1
  274. package/dist/ui/number-input.js +2 -1
  275. package/dist/ui/number-input.js.map +1 -1
  276. package/dist/ui/pagination.js.map +1 -1
  277. package/dist/ui/progress-ring.js.map +1 -1
  278. package/dist/ui/progress.js.map +1 -1
  279. package/dist/ui/radio.js.map +1 -1
  280. package/dist/ui/search-input.js.map +1 -1
  281. package/dist/ui/segmented-control.js.map +1 -1
  282. package/dist/ui/select.d.ts.map +1 -1
  283. package/dist/ui/select.js +1 -0
  284. package/dist/ui/select.js.map +1 -1
  285. package/dist/ui/separator.js.map +1 -1
  286. package/dist/ui/sheet.js.map +1 -1
  287. package/dist/ui/sidebar.js +1 -1
  288. package/dist/ui/sidebar.js.map +1 -1
  289. package/dist/ui/skeleton.js.map +1 -1
  290. package/dist/ui/slider.js.map +1 -1
  291. package/dist/ui/spinner.js.map +1 -1
  292. package/dist/ui/split-button.js.map +1 -1
  293. package/dist/ui/stack.js.map +1 -1
  294. package/dist/ui/stat-card.js.map +1 -1
  295. package/dist/ui/stat-flash.d.ts +2 -1
  296. package/dist/ui/stat-flash.d.ts.map +1 -1
  297. package/dist/ui/stat-flash.js +1 -1
  298. package/dist/ui/stat-flash.js.map +1 -1
  299. package/dist/ui/stepper.d.ts +1 -1
  300. package/dist/ui/stepper.d.ts.map +1 -1
  301. package/dist/ui/stepper.js +1 -1
  302. package/dist/ui/stepper.js.map +1 -1
  303. package/dist/ui/surface.js.map +1 -1
  304. package/dist/ui/switch.d.ts +1 -1
  305. package/dist/ui/switch.js.map +1 -1
  306. package/dist/ui/table-row-link.js.map +1 -1
  307. package/dist/ui/table.js.map +1 -1
  308. package/dist/ui/tabs.js.map +1 -1
  309. package/dist/ui/text.js.map +1 -1
  310. package/dist/ui/textarea.d.ts.map +1 -1
  311. package/dist/ui/textarea.js +3 -2
  312. package/dist/ui/textarea.js.map +1 -1
  313. package/dist/ui/toast-registry.js.map +1 -1
  314. package/dist/ui/toast.d.ts +4 -4
  315. package/dist/ui/toast.d.ts.map +1 -1
  316. package/dist/ui/toast.js +5 -3
  317. package/dist/ui/toast.js.map +1 -1
  318. package/dist/ui/toaster.js.map +1 -1
  319. package/dist/ui/toggle-group.js.map +1 -1
  320. package/dist/ui/toggle.js.map +1 -1
  321. package/dist/ui/tooltip.js.map +1 -1
  322. package/dist/ui/truncated-text.js.map +1 -1
  323. package/dist/ui/visually-hidden.js.map +1 -1
  324. package/docs/components/ui/data-table.md +2 -2
  325. package/llms.txt +1 -1
  326. package/mcp-manifest.json +3 -3
  327. package/package.json +21 -21
  328. package/skill/SKILL.md +1 -1
  329. package/skill/references/components.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"area-chart.js","names":[],"sources":["../../../src/ui/charts/area-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { ScaleLinear, ScalePoint } from 'd3-scale'\nimport { scaleLinear, scalePoint } from 'd3-scale'\nimport {\n area,\n curveLinear,\n curveMonotoneX,\n line,\n stack,\n stackOffsetNone,\n stackOrderNone,\n} from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { type AnyScale,Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { DataPoint, Series } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface AreaChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis */\n xKey: string\n /** Series definitions — each becomes an area */\n series: Series[]\n /** Use curved (monotone) interpolation */\n curved?: boolean\n /** Stack areas on top of each other */\n stacked?: boolean\n /** Fill opacity for area shapes */\n fillOpacity?: number\n /** Use vertical gradient fill */\n gradient?: boolean\n /** Stroke width for area outline */\n strokeWidth?: number\n /** Chart height */\n height?: number\n /** Show grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\n/** Type for rows fed to d3 stack — all numeric except the xKey */\ninterface StackableRow {\n [key: string]: number | string\n}\n\nexport const AreaChart = React.forwardRef<HTMLDivElement, AreaChartProps>(\n (\n {\n data,\n xKey,\n series,\n curved = false,\n stacked = false,\n fillOpacity = 0.3,\n gradient = false,\n strokeWidth = 2,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n xLabel,\n yLabel,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n // Stable unique ID for gradient definitions\n const chartId = React.useId()\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Area chart'}>\n {({ width, height: innerHeight, margin }) => {\n void margin\n\n // Determine if x-axis data is numeric or categorical\n const xValues = data.map((d) => d[xKey])\n const isNumericX = xValues.every((v) => typeof v === 'number')\n\n // Build x scale and accessor\n let xAxisScale: ScaleLinear<number, number> | ScalePoint<string>\n let getX: (d: DataPoint) => number\n let getXByIndex: (i: number) => number\n\n if (isNumericX) {\n const numericValues = xValues as number[]\n const xMin = Math.min(...numericValues)\n const xMax = Math.max(...numericValues)\n const linearX = scaleLinear<number, number>()\n .domain([xMin, xMax])\n .range([0, width])\n xAxisScale = linearX\n getX = (d: DataPoint) => linearX(Number(d[xKey]))\n getXByIndex = (i: number) => linearX(Number(data[i][xKey]))\n } else {\n const categories = xValues.map(String)\n const pointX = scalePoint<string>()\n .domain(categories)\n .range([0, width])\n .padding(0.5)\n xAxisScale = pointX\n getX = (d: DataPoint) => pointX(String(d[xKey])) ?? 0\n getXByIndex = (i: number) => pointX(String(data[i][xKey])) ?? 0\n }\n\n // Build y scale\n let yMax: number\n if (stacked) {\n yMax = Math.max(\n ...data.map((d) =>\n series.reduce((sum, s) => sum + (Number(d[s.key]) || 0), 0),\n ),\n )\n } else {\n yMax = Math.max(\n ...data.flatMap((d) =>\n series.map((s) => Number(d[s.key]) || 0),\n ),\n )\n }\n\n const yScale = scaleLinear<number, number>()\n .domain([0, yMax * 1.1])\n .range([innerHeight, 0])\n .nice()\n\n const curveType = curved ? curveMonotoneX : curveLinear\n\n // Shared tooltip render function\n const renderTooltipZones = () =>\n data.map((d, i) => {\n const cx = getX(d)\n const sliceWidth = width / Math.max(data.length - 1, 1)\n return (\n <rect\n key={`hover-${i}`}\n x={cx - sliceWidth / 2}\n y={0}\n width={sliceWidth}\n height={innerHeight}\n fill=\"transparent\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">\n {String(d[xKey])}\n </div>\n {series.map((s, sIdx) => (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {Number(d[s.key]).toLocaleString()}\n </div>\n ))}\n </div>,\n )\n }}\n onMouseLeave={hide}\n />\n )\n })\n\n // Shared gradient definitions\n const renderGradientDefs = () =>\n gradient ? (\n <defs>\n {series.map((_, sIdx) => (\n <linearGradient\n key={`grad-${sIdx}`}\n id={`${chartId}-gradient-${sIdx}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop\n offset=\"0%\"\n stopColor={colors[sIdx]}\n stopOpacity={fillOpacity}\n />\n <stop\n offset=\"100%\"\n stopColor={colors[sIdx]}\n stopOpacity={0.05}\n />\n </linearGradient>\n ))}\n </defs>\n ) : null\n\n // Shared axes\n const renderAxes = () => (\n <>\n <Axis\n scale={xAxisScale as AnyScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={yScale} orientation=\"left\" label={yLabel} />\n </>\n )\n\n // Stacked layout\n if (stacked) {\n const seriesKeys = series.map((s) => s.key)\n const stackGen = stack<StackableRow>()\n .keys(seriesKeys)\n .order(stackOrderNone)\n .offset(stackOffsetNone)\n\n // Coerce data to StackableRow (numeric values for series keys)\n const numericData: StackableRow[] = data.map((d) => {\n const row: StackableRow = { [xKey]: String(d[xKey]) }\n for (const s of series) {\n row[s.key] = Number(d[s.key]) || 0\n }\n return row\n })\n\n const stackedData = stackGen(numericData)\n\n const areaGen = area<[number, number]>()\n .curve(curveType)\n .x((_, i) => getXByIndex(i))\n .y0((d) => yScale(d[0]))\n .y1((d) => yScale(d[1]))\n\n const lineGen = line<[number, number]>()\n .curve(curveType)\n .x((_, i) => getXByIndex(i))\n .y((d) => yScale(d[1]))\n\n return (\n <>\n {renderGradientDefs()}\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Stacked areas (render in reverse so first series is on top) */}\n {[...stackedData].reverse().map((layer, reversedIdx) => {\n const seriesIdx = stackedData.length - 1 - reversedIdx\n const layerData = layer as unknown as [number, number][]\n const areaD = areaGen(layerData) ?? ''\n const lineD = lineGen(layerData) ?? ''\n const fillColor = gradient\n ? `url(#${chartId}-gradient-${seriesIdx})`\n : colors[seriesIdx]\n\n return (\n <g key={series[seriesIdx].key}>\n <path\n d={areaD}\n fill={fillColor}\n opacity={gradient ? 1 : fillOpacity}\n />\n <path\n d={lineD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </g>\n )\n })}\n\n {/* Tooltip hover zones */}\n {showTooltip && renderTooltipZones()}\n\n {renderAxes()}\n </>\n )\n }\n\n // Non-stacked areas\n const areaGen = area<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n const lineGen = line<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n return (\n <>\n {renderGradientDefs()}\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Areas (render in reverse so first series is visually on top) */}\n {[...series].reverse().map((s, reversedIdx) => {\n const seriesIdx = series.length - 1 - reversedIdx\n\n const areaPath = areaGen\n .x((d) => getX(d))\n .y0(innerHeight)\n .y1((d) => yScale(Number(d[s.key]) || 0))\n\n const linePath = lineGen\n .x((d) => getX(d))\n .y((d) => yScale(Number(d[s.key]) || 0))\n\n const areaD = areaPath(data) ?? ''\n const lineD = linePath(data) ?? ''\n\n const fillColor = gradient\n ? `url(#${chartId}-gradient-${seriesIdx})`\n : colors[seriesIdx]\n\n return (\n <g key={s.key}>\n <path\n d={areaD}\n fill={fillColor}\n opacity={gradient ? 1 : fillOpacity}\n />\n <path\n d={lineD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </g>\n )\n })}\n\n {/* Tooltip hover zones */}\n {showTooltip && renderTooltipZones()}\n\n {renderAxes()}\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && series.length > 1 && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nAreaChart.displayName = 'AreaChart'\n"],"mappings":"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"}
1
+ {"version":3,"file":"area-chart.js","names":[],"sources":["../../../src/ui/charts/area-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { ScaleLinear, ScalePoint } from 'd3-scale'\nimport { scaleLinear, scalePoint } from 'd3-scale'\nimport {\n area,\n curveLinear,\n curveMonotoneX,\n line,\n stack,\n stackOffsetNone,\n stackOrderNone,\n} from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { type AnyScale,Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { DataPoint, Series } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface AreaChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis */\n xKey: string\n /** Series definitions — each becomes an area */\n series: Series[]\n /** Use curved (monotone) interpolation */\n curved?: boolean\n /** Stack areas on top of each other */\n stacked?: boolean\n /** Fill opacity for area shapes */\n fillOpacity?: number\n /** Use vertical gradient fill */\n gradient?: boolean\n /** Stroke width for area outline */\n strokeWidth?: number\n /** Chart height */\n height?: number\n /** Show grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\n/** Type for rows fed to d3 stack — all numeric except the xKey */\ninterface StackableRow {\n [key: string]: number | string\n}\n\nexport const AreaChart = React.forwardRef<HTMLDivElement, AreaChartProps>(\n (\n {\n data,\n xKey,\n series,\n curved = false,\n stacked = false,\n fillOpacity = 0.3,\n gradient = false,\n strokeWidth = 2,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n xLabel,\n yLabel,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n // Stable unique ID for gradient definitions\n const chartId = React.useId()\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Area chart'}>\n {({ width, height: innerHeight, margin }) => {\n void margin\n\n // Determine if x-axis data is numeric or categorical\n const xValues = data.map((d) => d[xKey])\n const isNumericX = xValues.every((v) => typeof v === 'number')\n\n // Build x scale and accessor\n let xAxisScale: ScaleLinear<number, number> | ScalePoint<string>\n let getX: (d: DataPoint) => number\n let getXByIndex: (i: number) => number\n\n if (isNumericX) {\n const numericValues = xValues as number[]\n const xMin = Math.min(...numericValues)\n const xMax = Math.max(...numericValues)\n const linearX = scaleLinear<number, number>()\n .domain([xMin, xMax])\n .range([0, width])\n xAxisScale = linearX\n getX = (d: DataPoint) => linearX(Number(d[xKey]))\n getXByIndex = (i: number) => linearX(Number(data[i][xKey]))\n } else {\n const categories = xValues.map(String)\n const pointX = scalePoint<string>()\n .domain(categories)\n .range([0, width])\n .padding(0.5)\n xAxisScale = pointX\n getX = (d: DataPoint) => pointX(String(d[xKey])) ?? 0\n getXByIndex = (i: number) => pointX(String(data[i][xKey])) ?? 0\n }\n\n // Build y scale\n let yMax: number\n if (stacked) {\n yMax = Math.max(\n ...data.map((d) =>\n series.reduce((sum, s) => sum + (Number(d[s.key]) || 0), 0),\n ),\n )\n } else {\n yMax = Math.max(\n ...data.flatMap((d) =>\n series.map((s) => Number(d[s.key]) || 0),\n ),\n )\n }\n\n const yScale = scaleLinear<number, number>()\n .domain([0, yMax * 1.1])\n .range([innerHeight, 0])\n .nice()\n\n const curveType = curved ? curveMonotoneX : curveLinear\n\n // Shared tooltip render function\n const renderTooltipZones = () =>\n data.map((d, i) => {\n const cx = getX(d)\n const sliceWidth = width / Math.max(data.length - 1, 1)\n return (\n <rect\n key={`hover-${i}`}\n x={cx - sliceWidth / 2}\n y={0}\n width={sliceWidth}\n height={innerHeight}\n fill=\"transparent\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">\n {String(d[xKey])}\n </div>\n {series.map((s, sIdx) => (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {Number(d[s.key]).toLocaleString()}\n </div>\n ))}\n </div>,\n )\n }}\n onMouseLeave={hide}\n />\n )\n })\n\n // Shared gradient definitions\n const renderGradientDefs = () =>\n gradient ? (\n <defs>\n {series.map((_, sIdx) => (\n <linearGradient\n key={`grad-${sIdx}`}\n id={`${chartId}-gradient-${sIdx}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop\n offset=\"0%\"\n stopColor={colors[sIdx]}\n stopOpacity={fillOpacity}\n />\n <stop\n offset=\"100%\"\n stopColor={colors[sIdx]}\n stopOpacity={0.05}\n />\n </linearGradient>\n ))}\n </defs>\n ) : null\n\n // Shared axes\n const renderAxes = () => (\n <>\n <Axis\n scale={xAxisScale as AnyScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={yScale} orientation=\"left\" label={yLabel} />\n </>\n )\n\n // Stacked layout\n if (stacked) {\n const seriesKeys = series.map((s) => s.key)\n const stackGen = stack<StackableRow>()\n .keys(seriesKeys)\n .order(stackOrderNone)\n .offset(stackOffsetNone)\n\n // Coerce data to StackableRow (numeric values for series keys)\n const numericData: StackableRow[] = data.map((d) => {\n const row: StackableRow = { [xKey]: String(d[xKey]) }\n for (const s of series) {\n row[s.key] = Number(d[s.key]) || 0\n }\n return row\n })\n\n const stackedData = stackGen(numericData)\n\n const areaGen = area<[number, number]>()\n .curve(curveType)\n .x((_, i) => getXByIndex(i))\n .y0((d) => yScale(d[0]))\n .y1((d) => yScale(d[1]))\n\n const lineGen = line<[number, number]>()\n .curve(curveType)\n .x((_, i) => getXByIndex(i))\n .y((d) => yScale(d[1]))\n\n return (\n <>\n {renderGradientDefs()}\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Stacked areas (render in reverse so first series is on top) */}\n {[...stackedData].reverse().map((layer, reversedIdx) => {\n const seriesIdx = stackedData.length - 1 - reversedIdx\n const layerData = layer as unknown as [number, number][]\n const areaD = areaGen(layerData) ?? ''\n const lineD = lineGen(layerData) ?? ''\n const fillColor = gradient\n ? `url(#${chartId}-gradient-${seriesIdx})`\n : colors[seriesIdx]\n\n return (\n <g key={series[seriesIdx].key}>\n <path\n d={areaD}\n fill={fillColor}\n opacity={gradient ? 1 : fillOpacity}\n />\n <path\n d={lineD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </g>\n )\n })}\n\n {/* Tooltip hover zones */}\n {showTooltip && renderTooltipZones()}\n\n {renderAxes()}\n </>\n )\n }\n\n // Non-stacked areas\n const areaGen = area<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n const lineGen = line<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n return (\n <>\n {renderGradientDefs()}\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Areas (render in reverse so first series is visually on top) */}\n {[...series].reverse().map((s, reversedIdx) => {\n const seriesIdx = series.length - 1 - reversedIdx\n\n const areaPath = areaGen\n .x((d) => getX(d))\n .y0(innerHeight)\n .y1((d) => yScale(Number(d[s.key]) || 0))\n\n const linePath = lineGen\n .x((d) => getX(d))\n .y((d) => yScale(Number(d[s.key]) || 0))\n\n const areaD = areaPath(data) ?? ''\n const lineD = linePath(data) ?? ''\n\n const fillColor = gradient\n ? `url(#${chartId}-gradient-${seriesIdx})`\n : colors[seriesIdx]\n\n return (\n <g key={s.key}>\n <path\n d={areaD}\n fill={fillColor}\n opacity={gradient ? 1 : fillOpacity}\n />\n <path\n d={lineD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </g>\n )\n })}\n\n {/* Tooltip hover zones */}\n {showTooltip && renderTooltipZones()}\n\n {renderAxes()}\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && series.length > 1 && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nAreaChart.displayName = 'AreaChart'\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bar-chart.js","names":[],"sources":["../../../src/ui/charts/bar-chart.tsx"],"sourcesContent":["'use client'\n\nimport { scaleBand, scaleLinear } from 'd3-scale'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { ChartColor,DataPoint } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface BarChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'color'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis categories */\n xKey: string\n /** Key(s) for y-axis values. String for single series, array for multi-series */\n yKey: string | string[]\n /** Bar orientation */\n orientation?: 'vertical' | 'horizontal'\n /** Stack multiple series */\n stacked?: boolean\n /** Group multiple series side by side */\n grouped?: boolean\n /** Color(s) for bars */\n color?: ChartColor | ChartColor[] | string | string[]\n /** Chart height in pixels */\n height?: number\n /** Show background grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend (only for multi-series) */\n showLegend?: boolean\n /** Animate bars on mount */\n animate?: boolean\n /** Bar corner radius */\n barRadius?: number\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Series labels (for legend) */\n seriesLabels?: string[]\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const BarChart = React.forwardRef<HTMLDivElement, BarChartProps>(\n (\n {\n data,\n xKey,\n yKey,\n orientation = 'vertical',\n stacked = false,\n grouped = false,\n color,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n barRadius = 4,\n xLabel,\n yLabel,\n seriesLabels,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const isVertical = orientation === 'vertical'\n const shouldAnimate = animate && !reducedMotion\n\n // Normalize yKey to array\n const yKeys = Array.isArray(yKey) ? yKey : [yKey]\n const isMultiSeries = yKeys.length > 1\n\n // Resolve colors\n const colors = isMultiSeries\n ? yKeys.map((_, i) =>\n resolveColor(\n Array.isArray(color) ? color[i] : typeof color === 'string' ? color : undefined,\n i,\n ),\n )\n : [\n resolveColor(\n typeof color === 'string'\n ? color\n : Array.isArray(color)\n ? color[0]\n : undefined,\n 0,\n ),\n ]\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Bar chart'}>\n {({ width, height: innerHeight, margin }) => {\n // Suppress unused-var lint for margin (available for extensions)\n void margin\n\n // Category labels\n const categories = data.map((d) => String(d[xKey]))\n\n // Build data summary for screen readers\n const dataSummary = data.map((d) => {\n const cat = String(d[xKey])\n const vals = yKeys.map((k, i) => {\n const lbl = seriesLabels?.[i] ?? k\n return `${lbl}: ${Number(d[k]).toLocaleString()}`\n }).join(', ')\n return `${cat} — ${vals}`\n }).join('. ')\n\n // Calculate max value\n let maxValue: number\n if (stacked) {\n maxValue = Math.max(\n ...data.map((d) =>\n yKeys.reduce((sum, k) => sum + (Number(d[k]) || 0), 0),\n ),\n )\n } else {\n maxValue = Math.max(\n ...data.flatMap((d) => yKeys.map((k) => Number(d[k]) || 0)),\n )\n }\n\n // Build scales\n const categoryScale = scaleBand()\n .domain(categories)\n .range(isVertical ? [0, width] : [0, innerHeight])\n .padding(0.2)\n\n const valueScale = scaleLinear()\n .domain([0, maxValue * 1.1])\n .range(isVertical ? [innerHeight, 0] : [0, width])\n .nice()\n\n const barBandwidth = categoryScale.bandwidth()\n const barWidth =\n isMultiSeries && grouped\n ? barBandwidth / yKeys.length\n : barBandwidth\n\n return (\n <>\n {/* Screen-reader data summary */}\n <desc>{dataSummary}</desc>\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={isVertical ? valueScale : undefined}\n xScale={!isVertical ? valueScale : undefined}\n horizontal={isVertical}\n vertical={!isVertical}\n />\n )}\n\n {/* Bars */}\n {data.map((d) => {\n const category = String(d[xKey])\n let stackOffset = 0\n\n return yKeys.map((key, seriesIdx) => {\n const value = Number(d[key]) || 0\n const barColor = colors[seriesIdx] || colors[0]\n\n let x: number, y: number, w: number, h: number\n\n if (isVertical) {\n x =\n (categoryScale(category) ?? 0) +\n (grouped && isMultiSeries ? seriesIdx * barWidth : 0)\n y = stacked\n ? valueScale(stackOffset + value)\n : valueScale(value)\n w = barWidth\n h = stacked\n ? valueScale(stackOffset) - valueScale(stackOffset + value)\n : innerHeight - valueScale(value)\n } else {\n x = stacked ? valueScale(stackOffset) : 0\n y =\n (categoryScale(category) ?? 0) +\n (grouped && isMultiSeries ? seriesIdx * barWidth : 0)\n w = stacked\n ? valueScale(stackOffset + value) - valueScale(stackOffset)\n : valueScale(value)\n h = barWidth\n }\n\n if (stacked) stackOffset += value\n\n const seriesLabel = seriesLabels?.[seriesIdx] ?? key\n const barAriaLabel = isMultiSeries\n ? `${category}, ${seriesLabel}: ${value.toLocaleString()}`\n : `${category}: ${value.toLocaleString()}`\n\n const tooltipContent = (\n <div>\n <div className=\"font-medium\">{category}</div>\n {isMultiSeries && (\n <div className=\"text-surface-fg-muted\">\n {seriesLabel}\n </div>\n )}\n <div>{value.toLocaleString()}</div>\n </div>\n )\n\n return (\n <rect\n key={`${category}-${key}`}\n x={x}\n y={y}\n width={Math.max(0, w)}\n height={Math.max(0, h)}\n rx={barRadius}\n fill={barColor}\n className=\"transition-opacity hover:opacity-80 focus-visible:outline-hidden focus-visible:opacity-80\"\n tabIndex={showTooltip ? 0 : undefined}\n role={showTooltip ? 'graphics-symbol' : undefined}\n aria-label={barAriaLabel}\n onMouseMove={(e) => {\n if (showTooltip) {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n tooltipContent,\n )\n }\n }}\n onMouseLeave={hide}\n onFocus={(e) => {\n if (showTooltip) {\n const svgRect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const barRect = e.currentTarget.getBoundingClientRect()\n show(\n barRect.left + barRect.width / 2 - (svgRect?.left ?? 0),\n barRect.top - (svgRect?.top ?? 0),\n tooltipContent,\n )\n }\n }}\n onBlur={hide}\n />\n )\n })\n })}\n\n {/* Axes */}\n {isVertical ? (\n <>\n <Axis\n scale={categoryScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={valueScale} orientation=\"left\" label={yLabel} />\n </>\n ) : (\n <>\n <Axis\n scale={valueScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis\n scale={categoryScale}\n orientation=\"left\"\n label={yLabel}\n />\n </>\n )}\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && isMultiSeries && (\n <Legend\n items={yKeys.map((key, i) => ({\n label: seriesLabels?.[i] ?? key,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nBarChart.displayName = 'BarChart'\n"],"mappings":"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"}
1
+ {"version":3,"file":"bar-chart.js","names":[],"sources":["../../../src/ui/charts/bar-chart.tsx"],"sourcesContent":["'use client'\n\nimport { scaleBand, scaleLinear } from 'd3-scale'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { ChartColor,DataPoint } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface BarChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'color'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis categories */\n xKey: string\n /** Key(s) for y-axis values. String for single series, array for multi-series */\n yKey: string | string[]\n /** Bar orientation */\n orientation?: 'vertical' | 'horizontal'\n /** Stack multiple series */\n stacked?: boolean\n /** Group multiple series side by side */\n grouped?: boolean\n /** Color(s) for bars */\n color?: ChartColor | ChartColor[] | string | string[]\n /** Chart height in pixels */\n height?: number\n /** Show background grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend (only for multi-series) */\n showLegend?: boolean\n /** Animate bars on mount */\n animate?: boolean\n /** Bar corner radius */\n barRadius?: number\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Series labels (for legend) */\n seriesLabels?: string[]\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const BarChart = React.forwardRef<HTMLDivElement, BarChartProps>(\n (\n {\n data,\n xKey,\n yKey,\n orientation = 'vertical',\n stacked = false,\n grouped = false,\n color,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n barRadius = 4,\n xLabel,\n yLabel,\n seriesLabels,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const isVertical = orientation === 'vertical'\n const shouldAnimate = animate && !reducedMotion\n\n // Normalize yKey to array\n const yKeys = Array.isArray(yKey) ? yKey : [yKey]\n const isMultiSeries = yKeys.length > 1\n\n // Resolve colors\n const colors = isMultiSeries\n ? yKeys.map((_, i) =>\n resolveColor(\n Array.isArray(color) ? color[i] : typeof color === 'string' ? color : undefined,\n i,\n ),\n )\n : [\n resolveColor(\n typeof color === 'string'\n ? color\n : Array.isArray(color)\n ? color[0]\n : undefined,\n 0,\n ),\n ]\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Bar chart'}>\n {({ width, height: innerHeight, margin }) => {\n // Suppress unused-var lint for margin (available for extensions)\n void margin\n\n // Category labels\n const categories = data.map((d) => String(d[xKey]))\n\n // Build data summary for screen readers\n const dataSummary = data.map((d) => {\n const cat = String(d[xKey])\n const vals = yKeys.map((k, i) => {\n const lbl = seriesLabels?.[i] ?? k\n return `${lbl}: ${Number(d[k]).toLocaleString()}`\n }).join(', ')\n return `${cat} — ${vals}`\n }).join('. ')\n\n // Calculate max value\n let maxValue: number\n if (stacked) {\n maxValue = Math.max(\n ...data.map((d) =>\n yKeys.reduce((sum, k) => sum + (Number(d[k]) || 0), 0),\n ),\n )\n } else {\n maxValue = Math.max(\n ...data.flatMap((d) => yKeys.map((k) => Number(d[k]) || 0)),\n )\n }\n\n // Build scales\n const categoryScale = scaleBand()\n .domain(categories)\n .range(isVertical ? [0, width] : [0, innerHeight])\n .padding(0.2)\n\n const valueScale = scaleLinear()\n .domain([0, maxValue * 1.1])\n .range(isVertical ? [innerHeight, 0] : [0, width])\n .nice()\n\n const barBandwidth = categoryScale.bandwidth()\n const barWidth =\n isMultiSeries && grouped\n ? barBandwidth / yKeys.length\n : barBandwidth\n\n return (\n <>\n {/* Screen-reader data summary */}\n <desc>{dataSummary}</desc>\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={isVertical ? valueScale : undefined}\n xScale={!isVertical ? valueScale : undefined}\n horizontal={isVertical}\n vertical={!isVertical}\n />\n )}\n\n {/* Bars */}\n {data.map((d) => {\n const category = String(d[xKey])\n let stackOffset = 0\n\n return yKeys.map((key, seriesIdx) => {\n const value = Number(d[key]) || 0\n const barColor = colors[seriesIdx] || colors[0]\n\n let x: number, y: number, w: number, h: number\n\n if (isVertical) {\n x =\n (categoryScale(category) ?? 0) +\n (grouped && isMultiSeries ? seriesIdx * barWidth : 0)\n y = stacked\n ? valueScale(stackOffset + value)\n : valueScale(value)\n w = barWidth\n h = stacked\n ? valueScale(stackOffset) - valueScale(stackOffset + value)\n : innerHeight - valueScale(value)\n } else {\n x = stacked ? valueScale(stackOffset) : 0\n y =\n (categoryScale(category) ?? 0) +\n (grouped && isMultiSeries ? seriesIdx * barWidth : 0)\n w = stacked\n ? valueScale(stackOffset + value) - valueScale(stackOffset)\n : valueScale(value)\n h = barWidth\n }\n\n if (stacked) stackOffset += value\n\n const seriesLabel = seriesLabels?.[seriesIdx] ?? key\n const barAriaLabel = isMultiSeries\n ? `${category}, ${seriesLabel}: ${value.toLocaleString()}`\n : `${category}: ${value.toLocaleString()}`\n\n const tooltipContent = (\n <div>\n <div className=\"font-medium\">{category}</div>\n {isMultiSeries && (\n <div className=\"text-surface-fg-muted\">\n {seriesLabel}\n </div>\n )}\n <div>{value.toLocaleString()}</div>\n </div>\n )\n\n return (\n <rect\n key={`${category}-${key}`}\n x={x}\n y={y}\n width={Math.max(0, w)}\n height={Math.max(0, h)}\n rx={barRadius}\n fill={barColor}\n className=\"transition-opacity hover:opacity-80 focus-visible:outline-hidden focus-visible:opacity-80\"\n tabIndex={showTooltip ? 0 : undefined}\n role={showTooltip ? 'graphics-symbol' : undefined}\n aria-label={barAriaLabel}\n onMouseMove={(e) => {\n if (showTooltip) {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n tooltipContent,\n )\n }\n }}\n onMouseLeave={hide}\n onFocus={(e) => {\n if (showTooltip) {\n const svgRect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const barRect = e.currentTarget.getBoundingClientRect()\n show(\n barRect.left + barRect.width / 2 - (svgRect?.left ?? 0),\n barRect.top - (svgRect?.top ?? 0),\n tooltipContent,\n )\n }\n }}\n onBlur={hide}\n />\n )\n })\n })}\n\n {/* Axes */}\n {isVertical ? (\n <>\n <Axis\n scale={categoryScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={valueScale} orientation=\"left\" label={yLabel} />\n </>\n ) : (\n <>\n <Axis\n scale={valueScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis\n scale={categoryScale}\n orientation=\"left\"\n label={yLabel}\n />\n </>\n )}\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && isMultiSeries && (\n <Legend\n items={yKeys.map((key, i) => ({\n label: seriesLabels?.[i] ?? key,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nBarChart.displayName = 'BarChart'\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"gauge-chart.js","names":[],"sources":["../../../src/ui/charts/gauge-chart.tsx"],"sourcesContent":["'use client'\n\nimport { arc } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { getTransitionDuration,useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\n\nexport interface GaugeChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'color'> {\n /** Current value */\n value: number\n /** Maximum value (default: 100) */\n max?: number\n /** Minimum value (default: 0) */\n min?: number\n /** Label below the value */\n label?: string\n /** Custom value display */\n valueLabel?: string | ((value: number) => string)\n /** Arc color */\n color?: string\n /** Track (background) color */\n trackColor?: string\n /** Chart height/width (default: 200) */\n height?: number\n /** Start angle in degrees (default: -120) */\n startAngle?: number\n /** End angle in degrees (default: 120) */\n endAngle?: number\n /** Arc thickness in pixels (default: 16) */\n thickness?: number\n /** Animate the value arc */\n animate?: boolean\n className?: string\n}\n\nconst toRad = (deg: number) => (deg * Math.PI) / 180\n\nexport const GaugeChart = React.forwardRef<HTMLDivElement, GaugeChartProps>(\n (\n {\n value,\n max = 100,\n min = 0,\n label,\n valueLabel,\n color,\n trackColor = 'var(--color-surface-border)',\n height = 200,\n startAngle = -120,\n endAngle = 120,\n thickness = 16,\n animate = true,\n className,\n ...props\n },\n ref,\n ) => {\n const reducedMotion = useReducedMotion()\n const duration = getTransitionDuration(reducedMotion, animate ? 600 : 0)\n const shouldAnimate = animate && !reducedMotion\n\n const resolvedColor = resolveColor(color, 0)\n const size = height\n const radius = size / 2\n\n // Clamp value to [min, max]\n const clampedValue = Math.min(Math.max(value, min), max)\n const valueFraction = max === min ? 0 : (clampedValue - min) / (max - min)\n const valueEndAngle = startAngle + (endAngle - startAngle) * valueFraction\n\n // Display text\n const displayValue =\n typeof valueLabel === 'function'\n ? valueLabel(clampedValue)\n : typeof valueLabel === 'string'\n ? valueLabel\n : String(clampedValue)\n\n // Track arc generator\n const trackGenerator = arc<unknown>()\n .innerRadius(radius - thickness)\n .outerRadius(radius)\n .startAngle(toRad(startAngle))\n .endAngle(toRad(endAngle))\n .cornerRadius(thickness / 2)\n\n // Value arc generator\n const valueGenerator = arc<unknown>()\n .innerRadius(radius - thickness)\n .outerRadius(radius)\n .startAngle(toRad(startAngle))\n .endAngle(toRad(valueEndAngle))\n .cornerRadius(thickness / 2)\n\n const trackPath = trackGenerator(null as unknown as Record<string, never>) ?? ''\n const valuePath = valueGenerator(null as unknown as Record<string, never>) ?? ''\n\n return (\n <motion.div\n ref={ref}\n className={cn('inline-flex flex-col items-center', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n role=\"meter\"\n aria-valuenow={clampedValue}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-label={label ?? 'Gauge chart'}\n >\n <svg width={size} height={size} role=\"img\" aria-hidden=\"true\">\n <g transform={`translate(${radius},${radius})`}>\n {/* Background track */}\n <path d={trackPath} fill={trackColor} />\n\n {/* Value arc */}\n <path\n d={valuePath}\n fill={resolvedColor}\n style={\n duration > 0\n ? { transition: `d ${duration}ms ease-out` }\n : undefined\n }\n />\n\n {/* Center value text */}\n <text\n x={0}\n y={label ? -4 : 0}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-surface-fg text-ds-2xl font-semibold\"\n >\n {displayValue}\n </text>\n\n {/* Label below value */}\n {label && (\n <text\n x={0}\n y={20}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-surface-fg-muted text-ds-xs\"\n >\n {label}\n </text>\n )}\n </g>\n </svg>\n </motion.div>\n )\n },\n)\nGaugeChart.displayName = 'GaugeChart'\n"],"mappings":";;;;;;;;;AAuCA,IAAM,KAAS,MAAiB,IAAM,KAAK,KAAM,KAEpC,IAAa,EAAM,YAE5B,EACE,UACA,SAAM,KACN,SAAM,GACN,UACA,eACA,UACA,gBAAa,+BACb,YAAS,KACT,gBAAa,MACb,cAAW,KACX,eAAY,IACZ,aAAU,IACV,cACA,GAAG,KAEL,MACG;CACL,IAAM,IAAgB,GAAkB,EAClC,IAAW,EAAsB,GAAe,IAAU,MAAM,EAAE,EAClE,IAAgB,KAAW,CAAC,GAE5B,IAAgB,EAAa,GAAO,EAAE,EACtC,IAAO,GACP,IAAS,IAAO,GAGhB,IAAe,KAAK,IAAI,KAAK,IAAI,GAAO,EAAI,EAAE,EAAI,EAClD,IAAgB,MAAQ,IAAM,KAAK,IAAe,MAAQ,IAAM,IAChE,IAAgB,KAAc,IAAW,KAAc,GAGvD,IACJ,OAAO,KAAe,aAClB,EAAW,EAAa,GACxB,OAAO,KAAe,WACpB,IACA,OAAO,EAAa,EAGtB,IAAiB,GAAc,CAClC,YAAY,IAAS,EAAU,CAC/B,YAAY,EAAO,CACnB,WAAW,EAAM,EAAW,CAAC,CAC7B,SAAS,EAAM,EAAS,CAAC,CACzB,aAAa,IAAY,EAAE,EAGxB,IAAiB,GAAc,CAClC,YAAY,IAAS,EAAU,CAC/B,YAAY,EAAO,CACnB,WAAW,EAAM,EAAW,CAAC,CAC7B,SAAS,EAAM,EAAc,CAAC,CAC9B,aAAa,IAAY,EAAE,EAExB,IAAY,EAAe,KAAyC,IAAI,IACxE,IAAY,EAAe,KAAyC,IAAI;AAE9E,QACE,kBAAC,EAAO,KAAR;EACO;EACL,WAAW,EAAG,qCAAqC,EAAU;EAC7D,GAAK,IACD;GAAE,SAAS;IAAE,SAAS;IAAG,OAAO;IAAM;GAAE,SAAS;IAAE,SAAS;IAAG,OAAO;IAAG;GAAE,YAAY,EAAO;GAAM,GACpG,EAAE;EACN,GAAI,EAAY,EAAM;EACtB,MAAK;EACL,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,cAAY,KAAS;YAErB,kBAAC,OAAD;GAAK,OAAO;GAAM,QAAQ;GAAM,MAAK;GAAM,eAAY;aACrD,kBAAC,KAAD;IAAG,WAAW,aAAa,EAAO,GAAG,EAAO;cAA5C;KAEE,kBAAC,QAAD;MAAM,GAAG;MAAW,MAAM;MAAc,CAAA;KAGxC,kBAAC,QAAD;MACE,GAAG;MACH,MAAM;MACN,OACE,IAAW,IACP,EAAE,YAAY,KAAK,EAAS,cAAc,GAC1C,KAAA;MAEN,CAAA;KAGF,kBAAC,QAAD;MACE,GAAG;MACH,GAAG,IAAQ,KAAK;MAChB,YAAW;MACX,kBAAiB;MACjB,WAAU;gBAET;MACI,CAAA;KAGN,KACC,kBAAC,QAAD;MACE,GAAG;MACH,GAAG;MACH,YAAW;MACX,kBAAiB;MACjB,WAAU;gBAET;MACI,CAAA;KAEP;;GACA,CAAA;EACK,CAAA;EAGhB;AACD,EAAW,cAAc"}
1
+ {"version":3,"file":"gauge-chart.js","names":[],"sources":["../../../src/ui/charts/gauge-chart.tsx"],"sourcesContent":["'use client'\n\nimport { arc } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { getTransitionDuration,useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\n\nexport interface GaugeChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'color'> {\n /** Current value */\n value: number\n /** Maximum value (default: 100) */\n max?: number\n /** Minimum value (default: 0) */\n min?: number\n /** Label below the value */\n label?: string\n /** Custom value display */\n valueLabel?: string | ((value: number) => string)\n /** Arc color */\n color?: string\n /** Track (background) color */\n trackColor?: string\n /** Chart height/width (default: 200) */\n height?: number\n /** Start angle in degrees (default: -120) */\n startAngle?: number\n /** End angle in degrees (default: 120) */\n endAngle?: number\n /** Arc thickness in pixels (default: 16) */\n thickness?: number\n /** Animate the value arc */\n animate?: boolean\n className?: string\n}\n\nconst toRad = (deg: number) => (deg * Math.PI) / 180\n\nexport const GaugeChart = React.forwardRef<HTMLDivElement, GaugeChartProps>(\n (\n {\n value,\n max = 100,\n min = 0,\n label,\n valueLabel,\n color,\n trackColor = 'var(--color-surface-border)',\n height = 200,\n startAngle = -120,\n endAngle = 120,\n thickness = 16,\n animate = true,\n className,\n ...props\n },\n ref,\n ) => {\n const reducedMotion = useReducedMotion()\n const duration = getTransitionDuration(reducedMotion, animate ? 600 : 0)\n const shouldAnimate = animate && !reducedMotion\n\n const resolvedColor = resolveColor(color, 0)\n const size = height\n const radius = size / 2\n\n // Clamp value to [min, max]\n const clampedValue = Math.min(Math.max(value, min), max)\n const valueFraction = max === min ? 0 : (clampedValue - min) / (max - min)\n const valueEndAngle = startAngle + (endAngle - startAngle) * valueFraction\n\n // Display text\n const displayValue =\n typeof valueLabel === 'function'\n ? valueLabel(clampedValue)\n : typeof valueLabel === 'string'\n ? valueLabel\n : String(clampedValue)\n\n // Track arc generator\n const trackGenerator = arc<unknown>()\n .innerRadius(radius - thickness)\n .outerRadius(radius)\n .startAngle(toRad(startAngle))\n .endAngle(toRad(endAngle))\n .cornerRadius(thickness / 2)\n\n // Value arc generator\n const valueGenerator = arc<unknown>()\n .innerRadius(radius - thickness)\n .outerRadius(radius)\n .startAngle(toRad(startAngle))\n .endAngle(toRad(valueEndAngle))\n .cornerRadius(thickness / 2)\n\n const trackPath = trackGenerator(null as unknown as Record<string, never>) ?? ''\n const valuePath = valueGenerator(null as unknown as Record<string, never>) ?? ''\n\n return (\n <motion.div\n ref={ref}\n className={cn('inline-flex flex-col items-center', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n role=\"meter\"\n aria-valuenow={clampedValue}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-label={label ?? 'Gauge chart'}\n >\n <svg width={size} height={size} role=\"img\" aria-hidden=\"true\">\n <g transform={`translate(${radius},${radius})`}>\n {/* Background track */}\n <path d={trackPath} fill={trackColor} />\n\n {/* Value arc */}\n <path\n d={valuePath}\n fill={resolvedColor}\n style={\n duration > 0\n ? { transition: `d ${duration}ms ease-out` }\n : undefined\n }\n />\n\n {/* Center value text */}\n <text\n x={0}\n y={label ? -4 : 0}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-surface-fg text-ds-2xl font-semibold\"\n >\n {displayValue}\n </text>\n\n {/* Label below value */}\n {label && (\n <text\n x={0}\n y={20}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-surface-fg-muted text-ds-xs\"\n >\n {label}\n </text>\n )}\n </g>\n </svg>\n </motion.div>\n )\n },\n)\nGaugeChart.displayName = 'GaugeChart'\n"],"mappings":";;;;;;;;;AAuCA,IAAM,KAAS,MAAiB,IAAM,KAAK,KAAM,KAEpC,IAAa,EAAM,YAE5B,EACE,UACA,SAAM,KACN,SAAM,GACN,UACA,eACA,UACA,gBAAa,+BACb,YAAS,KACT,gBAAa,MACb,cAAW,KACX,eAAY,IACZ,aAAU,IACV,cACA,GAAG,KAEL,MACG;CACL,IAAM,IAAgB,EAAiB,GACjC,IAAW,EAAsB,GAAe,IAAU,MAAM,CAAC,GACjE,IAAgB,KAAW,CAAC,GAE5B,IAAgB,EAAa,GAAO,CAAC,GACrC,IAAO,GACP,IAAS,IAAO,GAGhB,IAAe,KAAK,IAAI,KAAK,IAAI,GAAO,CAAG,GAAG,CAAG,GACjD,IAAgB,MAAQ,IAAM,KAAK,IAAe,MAAQ,IAAM,IAChE,IAAgB,KAAc,IAAW,KAAc,GAGvD,IACJ,OAAO,KAAe,aAClB,EAAW,CAAY,IACvB,OAAO,KAAe,WACpB,IACA,OAAO,CAAY,GAGrB,IAAiB,EAAa,CAAC,CAClC,YAAY,IAAS,CAAS,CAAC,CAC/B,YAAY,CAAM,CAAC,CACnB,WAAW,EAAM,CAAU,CAAC,CAAC,CAC7B,SAAS,EAAM,CAAQ,CAAC,CAAC,CACzB,aAAa,IAAY,CAAC,GAGvB,IAAiB,EAAa,CAAC,CAClC,YAAY,IAAS,CAAS,CAAC,CAC/B,YAAY,CAAM,CAAC,CACnB,WAAW,EAAM,CAAU,CAAC,CAAC,CAC7B,SAAS,EAAM,CAAa,CAAC,CAAC,CAC9B,aAAa,IAAY,CAAC,GAEvB,IAAY,EAAe,IAAwC,KAAK,IACxE,IAAY,EAAe,IAAwC,KAAK;CAE9E,OACE,kBAAC,EAAO,KAAR;EACO;EACL,WAAW,EAAG,qCAAqC,CAAS;EAC5D,GAAK,IACD;GAAE,SAAS;IAAE,SAAS;IAAG,OAAO;GAAK;GAAG,SAAS;IAAE,SAAS;IAAG,OAAO;GAAE;GAAG,YAAY,EAAO;EAAK,IACnG,CAAC;EACL,GAAI,EAAY,CAAK;EACrB,MAAK;EACL,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,cAAY,KAAS;YAErB,kBAAC,OAAD;GAAK,OAAO;GAAM,QAAQ;GAAM,MAAK;GAAM,eAAY;aACrD,kBAAC,KAAD;IAAG,WAAW,aAAa,EAAO,GAAG,EAAO;cAA5C;KAEE,kBAAC,QAAD;MAAM,GAAG;MAAW,MAAM;KAAa,CAAA;KAGvC,kBAAC,QAAD;MACE,GAAG;MACH,MAAM;MACN,OACE,IAAW,IACP,EAAE,YAAY,KAAK,EAAS,aAAa,IACzC,KAAA;KAEP,CAAA;KAGD,kBAAC,QAAD;MACE,GAAG;MACH,GAAG,IAAQ,KAAK;MAChB,YAAW;MACX,kBAAiB;MACjB,WAAU;gBAET;KACG,CAAA;KAGL,KACC,kBAAC,QAAD;MACE,GAAG;MACH,GAAG;MACH,YAAW;MACX,kBAAiB;MACjB,WAAU;gBAET;KACG,CAAA;IAEP;;EACA,CAAA;CACK,CAAA;AAEd,CACF;AACA,EAAW,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"line-chart.js","names":[],"sources":["../../../src/ui/charts/line-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { ScaleLinear, ScalePoint } from 'd3-scale'\nimport { scaleLinear, scalePoint } from 'd3-scale'\nimport { curveLinear,curveMonotoneX, line } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { type AnyScale,Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { DataPoint, Series } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface LineChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis */\n xKey: string\n /** Series definitions — each becomes a line */\n series: Series[]\n /** Use curved (monotone) interpolation */\n curved?: boolean\n /** Show dots at data points */\n showDots?: boolean\n /** Dot radius */\n dotSize?: number\n /** Line stroke width */\n strokeWidth?: number\n /** Chart height */\n height?: number\n /** Show grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(\n (\n {\n data,\n xKey,\n series,\n curved = false,\n showDots = false,\n dotSize = 4,\n strokeWidth = 2,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n xLabel,\n yLabel,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Line chart'}>\n {({ width, height: innerHeight, margin }) => {\n void margin\n\n // Determine if x-axis data is numeric or categorical\n const xValues = data.map((d) => d[xKey])\n const isNumericX = xValues.every((v) => typeof v === 'number')\n\n // Build x scale and accessor\n let xAxisScale: ScaleLinear<number, number> | ScalePoint<string>\n let getX: (d: DataPoint) => number\n\n if (isNumericX) {\n const numericValues = xValues as number[]\n const xMin = Math.min(...numericValues)\n const xMax = Math.max(...numericValues)\n const linearX = scaleLinear<number, number>()\n .domain([xMin, xMax])\n .range([0, width])\n xAxisScale = linearX\n getX = (d: DataPoint) => linearX(Number(d[xKey]))\n } else {\n const categories = xValues.map(String)\n const pointX = scalePoint<string>()\n .domain(categories)\n .range([0, width])\n .padding(0.5)\n xAxisScale = pointX\n getX = (d: DataPoint) => pointX(String(d[xKey])) ?? 0\n }\n\n // Build y scale across all series\n const allValues = data.flatMap((d) =>\n series.map((s) => Number(d[s.key]) || 0),\n )\n const yMax = Math.max(...allValues)\n const yScale = scaleLinear<number, number>()\n .domain([0, yMax * 1.1])\n .range([innerHeight, 0])\n .nice()\n\n // Line generator\n const curveType = curved ? curveMonotoneX : curveLinear\n const lineGen = line<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n // Build data summary for screen readers\n const dataSummary = data.map((d) => {\n const xVal = String(d[xKey])\n const vals = series.map((s) =>\n `${s.label}: ${Number(d[s.key]).toLocaleString()}`\n ).join(', ')\n return `${xVal} — ${vals}`\n }).join('. ')\n\n return (\n <>\n {/* Screen-reader data summary */}\n <desc>{dataSummary}</desc>\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Lines */}\n {series.map((s, seriesIdx) => {\n const pathGen = lineGen\n .x((d) => getX(d))\n .y((d) => yScale(Number(d[s.key]) || 0))\n\n const pathD = pathGen(data) ?? ''\n\n return (\n <g key={s.key}>\n {/* Line path */}\n <path\n d={pathD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n\n {/* Data point dots */}\n {showDots &&\n data.map((d, i) => {\n const cx = getX(d)\n const cy = yScale(Number(d[s.key]) || 0)\n return (\n <circle\n key={`${s.key}-dot-${i}`}\n cx={cx}\n cy={cy}\n r={dotSize}\n fill={colors[seriesIdx]}\n className=\"transition-opacity hover:opacity-80\"\n />\n )\n })}\n </g>\n )\n })}\n\n {/* Invisible hover/focus rectangles for tooltip */}\n {showTooltip &&\n data.map((d, i) => {\n const cx = getX(d)\n const sliceWidth = width / Math.max(data.length - 1, 1)\n const xVal = String(d[xKey])\n const pointAriaLabel = `${xVal}: ${series.map((s) => `${s.label} ${Number(d[s.key]).toLocaleString()}`).join(', ')}`\n\n const tooltipContent = (\n <div>\n <div className=\"font-medium\">{xVal}</div>\n {series.map((s, sIdx) => (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {Number(d[s.key]).toLocaleString()}\n </div>\n ))}\n </div>\n )\n\n return (\n <rect\n key={`hover-${i}`}\n x={cx - sliceWidth / 2}\n y={0}\n width={sliceWidth}\n height={innerHeight}\n fill=\"transparent\"\n tabIndex={0}\n role=\"graphics-symbol\"\n aria-label={pointAriaLabel}\n className=\"focus-visible:outline-hidden\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n tooltipContent,\n )\n }}\n onMouseLeave={hide}\n onFocus={(e) => {\n const svgRect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const sliceRect = e.currentTarget.getBoundingClientRect()\n show(\n sliceRect.left + sliceRect.width / 2 - (svgRect?.left ?? 0),\n sliceRect.top + sliceRect.height / 2 - (svgRect?.top ?? 0),\n tooltipContent,\n )\n }}\n onBlur={hide}\n />\n )\n })}\n\n {/* Axes */}\n <Axis\n scale={xAxisScale as AnyScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={yScale} orientation=\"left\" label={yLabel} />\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && series.length > 1 && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nLineChart.displayName = 'LineChart'\n"],"mappings":"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"}
1
+ {"version":3,"file":"line-chart.js","names":[],"sources":["../../../src/ui/charts/line-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { ScaleLinear, ScalePoint } from 'd3-scale'\nimport { scaleLinear, scalePoint } from 'd3-scale'\nimport { curveLinear,curveMonotoneX, line } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { type AnyScale,Axis } from './_internal/axes'\nimport { resolveColor } from './_internal/colors'\nimport { GridLines } from './_internal/grid-lines'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\nimport type { DataPoint, Series } from './_internal/types'\nimport { ChartContainer } from './chart-container'\n\nexport interface LineChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array */\n data: DataPoint[]\n /** Key for x-axis */\n xKey: string\n /** Series definitions — each becomes a line */\n series: Series[]\n /** Use curved (monotone) interpolation */\n curved?: boolean\n /** Show dots at data points */\n showDots?: boolean\n /** Dot radius */\n dotSize?: number\n /** Line stroke width */\n strokeWidth?: number\n /** Chart height */\n height?: number\n /** Show grid lines */\n showGrid?: boolean\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** X-axis label */\n xLabel?: string\n /** Y-axis label */\n yLabel?: string\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(\n (\n {\n data,\n xKey,\n series,\n curved = false,\n showDots = false,\n dotSize = 4,\n strokeWidth = 2,\n height = 300,\n showGrid = true,\n showTooltip = true,\n showLegend = false,\n animate = true,\n xLabel,\n yLabel,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n return (\n <motion.div\n ref={ref}\n className={cn('relative', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n <ChartContainer height={height} ariaLabel={ariaLabel ?? 'Line chart'}>\n {({ width, height: innerHeight, margin }) => {\n void margin\n\n // Determine if x-axis data is numeric or categorical\n const xValues = data.map((d) => d[xKey])\n const isNumericX = xValues.every((v) => typeof v === 'number')\n\n // Build x scale and accessor\n let xAxisScale: ScaleLinear<number, number> | ScalePoint<string>\n let getX: (d: DataPoint) => number\n\n if (isNumericX) {\n const numericValues = xValues as number[]\n const xMin = Math.min(...numericValues)\n const xMax = Math.max(...numericValues)\n const linearX = scaleLinear<number, number>()\n .domain([xMin, xMax])\n .range([0, width])\n xAxisScale = linearX\n getX = (d: DataPoint) => linearX(Number(d[xKey]))\n } else {\n const categories = xValues.map(String)\n const pointX = scalePoint<string>()\n .domain(categories)\n .range([0, width])\n .padding(0.5)\n xAxisScale = pointX\n getX = (d: DataPoint) => pointX(String(d[xKey])) ?? 0\n }\n\n // Build y scale across all series\n const allValues = data.flatMap((d) =>\n series.map((s) => Number(d[s.key]) || 0),\n )\n const yMax = Math.max(...allValues)\n const yScale = scaleLinear<number, number>()\n .domain([0, yMax * 1.1])\n .range([innerHeight, 0])\n .nice()\n\n // Line generator\n const curveType = curved ? curveMonotoneX : curveLinear\n const lineGen = line<DataPoint>()\n .curve(curveType)\n .defined((d) => d !== undefined && d !== null)\n\n // Build data summary for screen readers\n const dataSummary = data.map((d) => {\n const xVal = String(d[xKey])\n const vals = series.map((s) =>\n `${s.label}: ${Number(d[s.key]).toLocaleString()}`\n ).join(', ')\n return `${xVal} — ${vals}`\n }).join('. ')\n\n return (\n <>\n {/* Screen-reader data summary */}\n <desc>{dataSummary}</desc>\n\n {/* Grid */}\n {showGrid && (\n <GridLines\n width={width}\n height={innerHeight}\n yScale={yScale}\n horizontal\n />\n )}\n\n {/* Lines */}\n {series.map((s, seriesIdx) => {\n const pathGen = lineGen\n .x((d) => getX(d))\n .y((d) => yScale(Number(d[s.key]) || 0))\n\n const pathD = pathGen(data) ?? ''\n\n return (\n <g key={s.key}>\n {/* Line path */}\n <path\n d={pathD}\n fill=\"none\"\n stroke={colors[seriesIdx]}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n\n {/* Data point dots */}\n {showDots &&\n data.map((d, i) => {\n const cx = getX(d)\n const cy = yScale(Number(d[s.key]) || 0)\n return (\n <circle\n key={`${s.key}-dot-${i}`}\n cx={cx}\n cy={cy}\n r={dotSize}\n fill={colors[seriesIdx]}\n className=\"transition-opacity hover:opacity-80\"\n />\n )\n })}\n </g>\n )\n })}\n\n {/* Invisible hover/focus rectangles for tooltip */}\n {showTooltip &&\n data.map((d, i) => {\n const cx = getX(d)\n const sliceWidth = width / Math.max(data.length - 1, 1)\n const xVal = String(d[xKey])\n const pointAriaLabel = `${xVal}: ${series.map((s) => `${s.label} ${Number(d[s.key]).toLocaleString()}`).join(', ')}`\n\n const tooltipContent = (\n <div>\n <div className=\"font-medium\">{xVal}</div>\n {series.map((s, sIdx) => (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {Number(d[s.key]).toLocaleString()}\n </div>\n ))}\n </div>\n )\n\n return (\n <rect\n key={`hover-${i}`}\n x={cx - sliceWidth / 2}\n y={0}\n width={sliceWidth}\n height={innerHeight}\n fill=\"transparent\"\n tabIndex={0}\n role=\"graphics-symbol\"\n aria-label={pointAriaLabel}\n className=\"focus-visible:outline-hidden\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n tooltipContent,\n )\n }}\n onMouseLeave={hide}\n onFocus={(e) => {\n const svgRect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const sliceRect = e.currentTarget.getBoundingClientRect()\n show(\n sliceRect.left + sliceRect.width / 2 - (svgRect?.left ?? 0),\n sliceRect.top + sliceRect.height / 2 - (svgRect?.top ?? 0),\n tooltipContent,\n )\n }}\n onBlur={hide}\n />\n )\n })}\n\n {/* Axes */}\n <Axis\n scale={xAxisScale as AnyScale}\n orientation=\"bottom\"\n transform={`translate(0,${innerHeight})`}\n label={xLabel}\n />\n <Axis scale={yScale} orientation=\"left\" label={yLabel} />\n </>\n )\n }}\n </ChartContainer>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n\n {/* Legend */}\n {showLegend && series.length > 1 && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nLineChart.displayName = 'LineChart'\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/ui/charts/pie-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { PieArcDatum } from 'd3-shape'\nimport { arc as d3Arc,pie as d3Pie } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\nimport { useEffect,useRef, useState } from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\n\ninterface PieSlice {\n label: string\n value: number\n color?: string\n}\n\nexport interface PieChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data with label and value */\n data: PieSlice[]\n /** Pie or donut variant */\n variant?: 'pie' | 'donut'\n /** Inner radius ratio for donut (0-1, default 0.6) */\n innerRadius?: number\n /** Gap angle between slices in radians */\n padAngle?: number\n /** Corner radius for slice edges */\n cornerRadius?: number\n /** Chart height (and width, since pie is square) */\n height?: number\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Show percentage labels on/near slices */\n showLabels?: boolean\n /** Animate slices */\n animate?: boolean\n className?: string\n /** Content to show in center of donut */\n centerLabel?: React.ReactNode\n /** Accessible label for the chart */\n ariaLabel?: string\n}\n\nexport const PieChart = React.forwardRef<HTMLDivElement, PieChartProps>(\n (\n {\n data,\n variant = 'pie',\n innerRadius: innerRadiusRatio = 0.6,\n padAngle = 0,\n cornerRadius = 0,\n height = 300,\n showTooltip = true,\n showLegend = false,\n showLabels = false,\n animate = true,\n className,\n centerLabel,\n ariaLabel,\n ...props\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [containerWidth, setContainerWidth] = useState(0)\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n useEffect(() => {\n if (!containerRef.current) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) setContainerWidth(entry.contentRect.width)\n })\n observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [])\n\n // Pie chart is square — use the smaller of width/height\n const size = containerWidth > 0 ? Math.min(containerWidth, height) : height\n const outerRadius = size / 2\n const innerR = variant === 'donut' ? outerRadius * innerRadiusRatio : 0\n\n // Resolve colors for each slice\n const colors = data.map((d, i) => resolveColor(d.color, i))\n\n // Compute total for percentages\n const total = data.reduce((sum, d) => sum + d.value, 0)\n\n // D3 pie layout\n const pieLayout = d3Pie<PieSlice>()\n .value((d) => d.value)\n .padAngle(padAngle)\n .sort(null)\n\n const arcs = pieLayout(data)\n\n // D3 arc generator\n const arcGenerator = d3Arc<PieArcDatum<PieSlice>>()\n .innerRadius(innerR)\n .outerRadius(outerRadius - 2) // slight inset so hover offset doesn't clip\n .cornerRadius(cornerRadius)\n\n // Label arc — position labels at 70% of the way from inner to outer radius\n const labelRadius = innerR + (outerRadius - 2 - innerR) * 0.7\n const labelArc = d3Arc<PieArcDatum<PieSlice>>()\n .innerRadius(labelRadius)\n .outerRadius(labelRadius)\n\n return (\n <motion.div\n ref={(node) => {\n (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n className={cn('relative w-full', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n {containerWidth > 0 && (\n <>\n <svg\n width={containerWidth}\n height={height}\n role=\"img\"\n aria-label={ariaLabel ?? 'Pie chart'}\n >\n <g transform={`translate(${containerWidth / 2},${height / 2})`}>\n {arcs.map((d, i) => {\n const path = arcGenerator(d)\n if (!path) return null\n\n // Hover offset: push slice outward along its centroid angle\n const [cx, cy] = arcGenerator.centroid(d)\n const angle = Math.atan2(cy, cx)\n const offsetX = Math.cos(angle) * 4\n const offsetY = Math.sin(angle) * 4\n const isHovered = hoveredIndex === i\n\n return (\n <path\n key={`slice-${d.data.label}-${i}`}\n d={path}\n fill={colors[i]}\n className=\"cursor-pointer transition-transform\"\n style={{\n transform: isHovered\n ? `translate(${offsetX}px, ${offsetY}px)`\n : undefined,\n }}\n onMouseEnter={() => setHoveredIndex(i)}\n onMouseMove={(e) => {\n if (showTooltip) {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const pct =\n total > 0\n ? ((d.data.value / total) * 100).toFixed(1)\n : '0'\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">{d.data.label}</div>\n <div>\n {d.data.value.toLocaleString()} ({pct}%)\n </div>\n </div>,\n )\n }\n }}\n onMouseLeave={() => {\n setHoveredIndex(null)\n hide()\n }}\n />\n )\n })}\n\n {/* Percentage labels */}\n {showLabels &&\n arcs.map((d, i) => {\n const [lx, ly] = labelArc.centroid(d)\n const pct =\n total > 0\n ? ((d.data.value / total) * 100).toFixed(0)\n : '0'\n\n // Skip tiny slices (< 3%) to avoid label overlap\n if (total > 0 && d.data.value / total < 0.03) return null\n\n return (\n <text\n key={`label-${d.data.label}-${i}`}\n x={lx}\n y={ly}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"pointer-events-none fill-accent-fg text-ds-xs font-medium\"\n >\n {pct}%\n </text>\n )\n })}\n\n {/* Center label for donut variant */}\n {variant === 'donut' && centerLabel && innerR > 0 && (\n <foreignObject\n x={-innerR * 0.7}\n y={-innerR * 0.7}\n width={innerR * 1.4}\n height={innerR * 1.4}\n >\n <div className=\"flex h-full w-full items-center justify-center text-center text-surface-fg\">\n {centerLabel}\n </div>\n </foreignObject>\n )}\n </g>\n </svg>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n </>\n )}\n\n {/* Legend */}\n {showLegend && (\n <Legend\n items={data.map((d, i) => ({\n label: d.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nPieChart.displayName = 'PieChart'\n"],"mappings":"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"}
1
+ {"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/ui/charts/pie-chart.tsx"],"sourcesContent":["'use client'\n\nimport type { PieArcDatum } from 'd3-shape'\nimport { arc as d3Arc,pie as d3Pie } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\nimport { useEffect,useRef, useState } from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\n\ninterface PieSlice {\n label: string\n value: number\n color?: string\n}\n\nexport interface PieChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data with label and value */\n data: PieSlice[]\n /** Pie or donut variant */\n variant?: 'pie' | 'donut'\n /** Inner radius ratio for donut (0-1, default 0.6) */\n innerRadius?: number\n /** Gap angle between slices in radians */\n padAngle?: number\n /** Corner radius for slice edges */\n cornerRadius?: number\n /** Chart height (and width, since pie is square) */\n height?: number\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Show percentage labels on/near slices */\n showLabels?: boolean\n /** Animate slices */\n animate?: boolean\n className?: string\n /** Content to show in center of donut */\n centerLabel?: React.ReactNode\n /** Accessible label for the chart */\n ariaLabel?: string\n}\n\nexport const PieChart = React.forwardRef<HTMLDivElement, PieChartProps>(\n (\n {\n data,\n variant = 'pie',\n innerRadius: innerRadiusRatio = 0.6,\n padAngle = 0,\n cornerRadius = 0,\n height = 300,\n showTooltip = true,\n showLegend = false,\n showLabels = false,\n animate = true,\n className,\n centerLabel,\n ariaLabel,\n ...props\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [containerWidth, setContainerWidth] = useState(0)\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n useEffect(() => {\n if (!containerRef.current) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) setContainerWidth(entry.contentRect.width)\n })\n observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [])\n\n // Pie chart is square — use the smaller of width/height\n const size = containerWidth > 0 ? Math.min(containerWidth, height) : height\n const outerRadius = size / 2\n const innerR = variant === 'donut' ? outerRadius * innerRadiusRatio : 0\n\n // Resolve colors for each slice\n const colors = data.map((d, i) => resolveColor(d.color, i))\n\n // Compute total for percentages\n const total = data.reduce((sum, d) => sum + d.value, 0)\n\n // D3 pie layout\n const pieLayout = d3Pie<PieSlice>()\n .value((d) => d.value)\n .padAngle(padAngle)\n .sort(null)\n\n const arcs = pieLayout(data)\n\n // D3 arc generator\n const arcGenerator = d3Arc<PieArcDatum<PieSlice>>()\n .innerRadius(innerR)\n .outerRadius(outerRadius - 2) // slight inset so hover offset doesn't clip\n .cornerRadius(cornerRadius)\n\n // Label arc — position labels at 70% of the way from inner to outer radius\n const labelRadius = innerR + (outerRadius - 2 - innerR) * 0.7\n const labelArc = d3Arc<PieArcDatum<PieSlice>>()\n .innerRadius(labelRadius)\n .outerRadius(labelRadius)\n\n return (\n <motion.div\n ref={(node) => {\n (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n className={cn('relative w-full', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n {containerWidth > 0 && (\n <>\n <svg\n width={containerWidth}\n height={height}\n role=\"img\"\n aria-label={ariaLabel ?? 'Pie chart'}\n >\n <g transform={`translate(${containerWidth / 2},${height / 2})`}>\n {arcs.map((d, i) => {\n const path = arcGenerator(d)\n if (!path) return null\n\n // Hover offset: push slice outward along its centroid angle\n const [cx, cy] = arcGenerator.centroid(d)\n const angle = Math.atan2(cy, cx)\n const offsetX = Math.cos(angle) * 4\n const offsetY = Math.sin(angle) * 4\n const isHovered = hoveredIndex === i\n\n return (\n <path\n key={`slice-${d.data.label}-${i}`}\n d={path}\n fill={colors[i]}\n className=\"cursor-pointer transition-transform\"\n style={{\n transform: isHovered\n ? `translate(${offsetX}px, ${offsetY}px)`\n : undefined,\n }}\n onMouseEnter={() => setHoveredIndex(i)}\n onMouseMove={(e) => {\n if (showTooltip) {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n const pct =\n total > 0\n ? ((d.data.value / total) * 100).toFixed(1)\n : '0'\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">{d.data.label}</div>\n <div>\n {d.data.value.toLocaleString()} ({pct}%)\n </div>\n </div>,\n )\n }\n }}\n onMouseLeave={() => {\n setHoveredIndex(null)\n hide()\n }}\n />\n )\n })}\n\n {/* Percentage labels */}\n {showLabels &&\n arcs.map((d, i) => {\n const [lx, ly] = labelArc.centroid(d)\n const pct =\n total > 0\n ? ((d.data.value / total) * 100).toFixed(0)\n : '0'\n\n // Skip tiny slices (< 3%) to avoid label overlap\n if (total > 0 && d.data.value / total < 0.03) return null\n\n return (\n <text\n key={`label-${d.data.label}-${i}`}\n x={lx}\n y={ly}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"pointer-events-none fill-accent-fg text-ds-xs font-medium\"\n >\n {pct}%\n </text>\n )\n })}\n\n {/* Center label for donut variant */}\n {variant === 'donut' && centerLabel && innerR > 0 && (\n <foreignObject\n x={-innerR * 0.7}\n y={-innerR * 0.7}\n width={innerR * 1.4}\n height={innerR * 1.4}\n >\n <div className=\"flex h-full w-full items-center justify-center text-center text-surface-fg\">\n {centerLabel}\n </div>\n </foreignObject>\n )}\n </g>\n </svg>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n </>\n )}\n\n {/* Legend */}\n {showLegend && (\n <Legend\n items={data.map((d, i) => ({\n label: d.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nPieChart.displayName = 'PieChart'\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"radar-chart.js","names":[],"sources":["../../../src/ui/charts/radar-chart.tsx"],"sourcesContent":["'use client'\n\nimport { curveLinearClosed,lineRadial } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\nimport { useEffect,useRef, useState } from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\n\nexport interface RadarChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array (one entry per data point / axis) */\n data: Record<string, string | number>[]\n /** Axis labels (3-8 axes) */\n axes: string[]\n /** Series to plot */\n series: { key: string; label: string; color?: string }[]\n /** Max value (auto-detect if not set) */\n maxValue?: number\n /** Number of concentric grid rings (default: 5) */\n levels?: number\n /** Fill opacity for the data polygon (default: 0.25) */\n fillOpacity?: number\n /** Show dots at vertices */\n showDots?: boolean\n /** Chart height (default: 300) */\n height?: number\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(\n (\n {\n data,\n axes,\n series,\n maxValue: maxValueProp,\n levels = 5,\n fillOpacity = 0.25,\n showDots = false,\n height = 300,\n showTooltip = true,\n showLegend = false,\n animate = true,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [containerWidth, setContainerWidth] = useState(0)\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n useEffect(() => {\n if (!containerRef.current) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) setContainerWidth(entry.contentRect.width)\n })\n observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [])\n\n // Radar chart is square — use the smaller of width/height\n const svgSize = containerWidth > 0 ? Math.min(containerWidth, height) : height\n const radius = svgSize / 2 - 40 // leave room for labels\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n // Auto-detect maxValue if not provided\n const maxValue =\n maxValueProp ??\n Math.max(\n ...data.flatMap((d) => series.map((s) => Number(d[s.key]) || 0)),\n 1,\n )\n\n // Angle per axis slice\n const angleSlice = (2 * Math.PI) / axes.length\n\n // D3 radial line generator for the data polygon\n const radarLine = lineRadial<number>()\n .radius((d) => (radius * d) / maxValue)\n .angle((_, i) => i * angleSlice)\n .curve(curveLinearClosed)\n\n // Convert a data row into an array of values aligned with axes\n const getSeriesValues = (seriesKey: string): number[] =>\n axes.map((_, i) => Number(data[i]?.[seriesKey]) || 0)\n\n // Convert polar to cartesian for a given axis index and value\n const polarToXY = (axisIndex: number, value: number) => {\n const angle = angleSlice * axisIndex - Math.PI / 2\n const r = (radius * value) / maxValue\n return {\n x: r * Math.cos(angle),\n y: r * Math.sin(angle),\n }\n }\n\n return (\n <motion.div\n ref={(node) => {\n (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n className={cn('relative w-full', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n {containerWidth > 0 && (\n <>\n <svg\n width={containerWidth}\n height={height}\n role=\"img\"\n aria-label={ariaLabel ?? 'Radar chart'}\n >\n <g transform={`translate(${containerWidth / 2},${height / 2})`}>\n {/* Concentric grid polygons */}\n {Array.from({ length: levels }, (_, i) => {\n const levelRadius = (radius / levels) * (i + 1)\n const points = axes\n .map((_, j) => {\n const angle = angleSlice * j - Math.PI / 2\n return `${levelRadius * Math.cos(angle)},${levelRadius * Math.sin(angle)}`\n })\n .join(' ')\n return (\n <polygon\n key={`grid-${i}`}\n points={points}\n fill=\"none\"\n stroke=\"var(--color-surface-border)\"\n strokeDasharray=\"3,3\"\n strokeWidth={1}\n />\n )\n })}\n\n {/* Axis lines from center to outer edge */}\n {axes.map((_, i) => {\n const angle = angleSlice * i - Math.PI / 2\n const x = radius * Math.cos(angle)\n const y = radius * Math.sin(angle)\n return (\n <line\n key={`axis-${i}`}\n x1={0}\n y1={0}\n x2={x}\n y2={y}\n stroke=\"var(--color-surface-border)\"\n strokeWidth={1}\n />\n )\n })}\n\n {/* Axis labels */}\n {axes.map((label, i) => {\n const angle = angleSlice * i - Math.PI / 2\n const labelRadius = radius + 18\n const x = labelRadius * Math.cos(angle)\n const y = labelRadius * Math.sin(angle)\n\n // Determine text-anchor based on position\n let textAnchor: 'start' | 'middle' | 'end' = 'middle'\n if (Math.abs(Math.cos(angle)) > 0.1) {\n textAnchor = Math.cos(angle) > 0 ? 'start' : 'end'\n }\n\n return (\n <text\n key={`label-${i}`}\n x={x}\n y={y}\n textAnchor={textAnchor}\n dominantBaseline=\"central\"\n className=\"fill-surface-fg-muted text-ds-xs\"\n >\n {label}\n </text>\n )\n })}\n\n {/* Level value labels on the first axis */}\n {Array.from({ length: levels }, (_, i) => {\n const levelValue = Math.round((maxValue / levels) * (i + 1))\n const levelRadius = (radius / levels) * (i + 1)\n const angle = -Math.PI / 2 // first axis is at top\n const x = levelRadius * Math.cos(angle) + 4\n const y = levelRadius * Math.sin(angle)\n return (\n <text\n key={`level-label-${i}`}\n x={x}\n y={y}\n textAnchor=\"start\"\n dominantBaseline=\"auto\"\n className=\"fill-surface-fg-subtle text-ds-xs\"\n >\n {levelValue}\n </text>\n )\n })}\n\n {/* Data polygons — one per series */}\n {series.map((s, seriesIdx) => {\n const values = getSeriesValues(s.key)\n const pathD = radarLine(values)\n if (!pathD) return null\n\n return (\n <g key={s.key}>\n <path\n d={pathD}\n fill={colors[seriesIdx]}\n fillOpacity={fillOpacity}\n stroke={colors[seriesIdx]}\n strokeWidth={2}\n strokeLinejoin=\"round\"\n />\n\n {/* Vertex dots */}\n {showDots &&\n values.map((v, i) => {\n const { x, y } = polarToXY(i, v)\n return (\n <circle\n key={`dot-${s.key}-${i}`}\n cx={x}\n cy={y}\n r={4}\n fill={colors[seriesIdx]}\n stroke=\"var(--color-surface-base)\"\n strokeWidth={2}\n className=\"transition-opacity\"\n />\n )\n })}\n </g>\n )\n })}\n\n {/* Invisible hover areas at each vertex for tooltips */}\n {showTooltip &&\n axes.map((axisLabel, i) => {\n // Place a transparent circle at the outermost series point\n // for hit detection. Use the max value point for the axis.\n const angle = angleSlice * i - Math.PI / 2\n const hitX = radius * Math.cos(angle)\n const hitY = radius * Math.sin(angle)\n\n return (\n <circle\n key={`hover-${i}`}\n cx={hitX}\n cy={hitY}\n r={16}\n fill=\"transparent\"\n className=\"cursor-pointer\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">{axisLabel}</div>\n {series.map((s, sIdx) => {\n const val = Number(data[i]?.[s.key]) || 0\n return (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {val.toLocaleString()}\n </div>\n )\n })}\n </div>,\n )\n }}\n onMouseLeave={hide}\n />\n )\n })}\n </g>\n </svg>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n </>\n )}\n\n {/* Legend */}\n {showLegend && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nRadarChart.displayName = 'RadarChart'\n"],"mappings":"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"}
1
+ {"version":3,"file":"radar-chart.js","names":[],"sources":["../../../src/ui/charts/radar-chart.tsx"],"sourcesContent":["'use client'\n\nimport { curveLinearClosed,lineRadial } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\nimport { useEffect,useRef, useState } from 'react'\n\nimport { motionProps,tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\nimport { Legend } from './_internal/legend'\nimport { ChartTooltip, useChartTooltip } from './_internal/tooltip'\n\nexport interface RadarChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Data array (one entry per data point / axis) */\n data: Record<string, string | number>[]\n /** Axis labels (3-8 axes) */\n axes: string[]\n /** Series to plot */\n series: { key: string; label: string; color?: string }[]\n /** Max value (auto-detect if not set) */\n maxValue?: number\n /** Number of concentric grid rings (default: 5) */\n levels?: number\n /** Fill opacity for the data polygon (default: 0.25) */\n fillOpacity?: number\n /** Show dots at vertices */\n showDots?: boolean\n /** Chart height (default: 300) */\n height?: number\n /** Show tooltip on hover */\n showTooltip?: boolean\n /** Show legend */\n showLegend?: boolean\n /** Animate on mount */\n animate?: boolean\n /** Accessible label for the chart */\n ariaLabel?: string\n className?: string\n}\n\nexport const RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(\n (\n {\n data,\n axes,\n series,\n maxValue: maxValueProp,\n levels = 5,\n fillOpacity = 0.25,\n showDots = false,\n height = 300,\n showTooltip = true,\n showLegend = false,\n animate = true,\n ariaLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [containerWidth, setContainerWidth] = useState(0)\n const { tooltip, show, hide } = useChartTooltip()\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n useEffect(() => {\n if (!containerRef.current) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) setContainerWidth(entry.contentRect.width)\n })\n observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [])\n\n // Radar chart is square — use the smaller of width/height\n const svgSize = containerWidth > 0 ? Math.min(containerWidth, height) : height\n const radius = svgSize / 2 - 40 // leave room for labels\n\n // Resolve colors for each series\n const colors = series.map((s, i) => resolveColor(s.color, i))\n\n // Auto-detect maxValue if not provided\n const maxValue =\n maxValueProp ??\n Math.max(\n ...data.flatMap((d) => series.map((s) => Number(d[s.key]) || 0)),\n 1,\n )\n\n // Angle per axis slice\n const angleSlice = (2 * Math.PI) / axes.length\n\n // D3 radial line generator for the data polygon\n const radarLine = lineRadial<number>()\n .radius((d) => (radius * d) / maxValue)\n .angle((_, i) => i * angleSlice)\n .curve(curveLinearClosed)\n\n // Convert a data row into an array of values aligned with axes\n const getSeriesValues = (seriesKey: string): number[] =>\n axes.map((_, i) => Number(data[i]?.[seriesKey]) || 0)\n\n // Convert polar to cartesian for a given axis index and value\n const polarToXY = (axisIndex: number, value: number) => {\n const angle = angleSlice * axisIndex - Math.PI / 2\n const r = (radius * value) / maxValue\n return {\n x: r * Math.cos(angle),\n y: r * Math.sin(angle),\n }\n }\n\n return (\n <motion.div\n ref={(node) => {\n (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n className={cn('relative w-full', className)}\n {...(shouldAnimate\n ? { initial: { opacity: 0, scale: 0.96 }, animate: { opacity: 1, scale: 1 }, transition: tweens.fade }\n : {})}\n {...motionProps(props)}\n >\n {containerWidth > 0 && (\n <>\n <svg\n width={containerWidth}\n height={height}\n role=\"img\"\n aria-label={ariaLabel ?? 'Radar chart'}\n >\n <g transform={`translate(${containerWidth / 2},${height / 2})`}>\n {/* Concentric grid polygons */}\n {Array.from({ length: levels }, (_, i) => {\n const levelRadius = (radius / levels) * (i + 1)\n const points = axes\n .map((_, j) => {\n const angle = angleSlice * j - Math.PI / 2\n return `${levelRadius * Math.cos(angle)},${levelRadius * Math.sin(angle)}`\n })\n .join(' ')\n return (\n <polygon\n key={`grid-${i}`}\n points={points}\n fill=\"none\"\n stroke=\"var(--color-surface-border)\"\n strokeDasharray=\"3,3\"\n strokeWidth={1}\n />\n )\n })}\n\n {/* Axis lines from center to outer edge */}\n {axes.map((_, i) => {\n const angle = angleSlice * i - Math.PI / 2\n const x = radius * Math.cos(angle)\n const y = radius * Math.sin(angle)\n return (\n <line\n key={`axis-${i}`}\n x1={0}\n y1={0}\n x2={x}\n y2={y}\n stroke=\"var(--color-surface-border)\"\n strokeWidth={1}\n />\n )\n })}\n\n {/* Axis labels */}\n {axes.map((label, i) => {\n const angle = angleSlice * i - Math.PI / 2\n const labelRadius = radius + 18\n const x = labelRadius * Math.cos(angle)\n const y = labelRadius * Math.sin(angle)\n\n // Determine text-anchor based on position\n let textAnchor: 'start' | 'middle' | 'end' = 'middle'\n if (Math.abs(Math.cos(angle)) > 0.1) {\n textAnchor = Math.cos(angle) > 0 ? 'start' : 'end'\n }\n\n return (\n <text\n key={`label-${i}`}\n x={x}\n y={y}\n textAnchor={textAnchor}\n dominantBaseline=\"central\"\n className=\"fill-surface-fg-muted text-ds-xs\"\n >\n {label}\n </text>\n )\n })}\n\n {/* Level value labels on the first axis */}\n {Array.from({ length: levels }, (_, i) => {\n const levelValue = Math.round((maxValue / levels) * (i + 1))\n const levelRadius = (radius / levels) * (i + 1)\n const angle = -Math.PI / 2 // first axis is at top\n const x = levelRadius * Math.cos(angle) + 4\n const y = levelRadius * Math.sin(angle)\n return (\n <text\n key={`level-label-${i}`}\n x={x}\n y={y}\n textAnchor=\"start\"\n dominantBaseline=\"auto\"\n className=\"fill-surface-fg-subtle text-ds-xs\"\n >\n {levelValue}\n </text>\n )\n })}\n\n {/* Data polygons — one per series */}\n {series.map((s, seriesIdx) => {\n const values = getSeriesValues(s.key)\n const pathD = radarLine(values)\n if (!pathD) return null\n\n return (\n <g key={s.key}>\n <path\n d={pathD}\n fill={colors[seriesIdx]}\n fillOpacity={fillOpacity}\n stroke={colors[seriesIdx]}\n strokeWidth={2}\n strokeLinejoin=\"round\"\n />\n\n {/* Vertex dots */}\n {showDots &&\n values.map((v, i) => {\n const { x, y } = polarToXY(i, v)\n return (\n <circle\n key={`dot-${s.key}-${i}`}\n cx={x}\n cy={y}\n r={4}\n fill={colors[seriesIdx]}\n stroke=\"var(--color-surface-base)\"\n strokeWidth={2}\n className=\"transition-opacity\"\n />\n )\n })}\n </g>\n )\n })}\n\n {/* Invisible hover areas at each vertex for tooltips */}\n {showTooltip &&\n axes.map((axisLabel, i) => {\n // Place a transparent circle at the outermost series point\n // for hit detection. Use the max value point for the axis.\n const angle = angleSlice * i - Math.PI / 2\n const hitX = radius * Math.cos(angle)\n const hitY = radius * Math.sin(angle)\n\n return (\n <circle\n key={`hover-${i}`}\n cx={hitX}\n cy={hitY}\n r={16}\n fill=\"transparent\"\n className=\"cursor-pointer\"\n onMouseMove={(e) => {\n const rect = e.currentTarget\n .closest('div')\n ?.getBoundingClientRect()\n show(\n e.clientX - (rect?.left ?? 0),\n e.clientY - (rect?.top ?? 0),\n <div>\n <div className=\"font-medium\">{axisLabel}</div>\n {series.map((s, sIdx) => {\n const val = Number(data[i]?.[s.key]) || 0\n return (\n <div\n key={s.key}\n className=\"flex items-center gap-ds-02\"\n >\n <span\n className=\"inline-block h-2 w-2 rounded-pill\"\n style={{ backgroundColor: colors[sIdx] }}\n />\n <span className=\"text-surface-fg-muted\">\n {s.label}:\n </span>{' '}\n {val.toLocaleString()}\n </div>\n )\n })}\n </div>,\n )\n }}\n onMouseLeave={hide}\n />\n )\n })}\n </g>\n </svg>\n\n {/* Tooltip overlay */}\n {showTooltip && <ChartTooltip state={tooltip} />}\n </>\n )}\n\n {/* Legend */}\n {showLegend && (\n <Legend\n items={series.map((s, i) => ({\n label: s.label,\n color: colors[i],\n }))}\n className=\"mt-ds-04\"\n />\n )}\n </motion.div>\n )\n },\n)\nRadarChart.displayName = 'RadarChart'\n"],"mappings":";;;;;;;;;;;AA0CA,IAAa,IAAa,EAAM,YAE5B,EACE,SACA,SACA,WACA,UAAU,GACV,YAAS,GACT,iBAAc,KACd,cAAW,IACX,YAAS,KACT,iBAAc,IACd,gBAAa,IACb,aAAU,IACV,cACA,cACA,GAAG,KAEL,MACG;CACL,IAAM,IAAe,EAAuB,IAAI,GAC1C,CAAC,GAAgB,KAAqB,EAAS,CAAC,GAChD,EAAE,YAAS,SAAM,YAAS,EAAgB,GAC1C,IAAgB,EAAiB,GACjC,IAAgB,KAAW,CAAC;CAElC,QAAgB;EACd,IAAI,CAAC,EAAa,SAAS;EAC3B,IAAM,IAAW,IAAI,gBAAgB,MAAY;GAC/C,IAAM,IAAQ,EAAQ;GACtB,AAAI,KAAO,EAAkB,EAAM,YAAY,KAAK;EACtD,CAAC;EAED,OADA,EAAS,QAAQ,EAAa,OAAO,SACxB,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC;CAIL,IAAM,KADU,IAAiB,IAAI,KAAK,IAAI,GAAgB,CAAM,IAAI,KAC/C,IAAI,IAGvB,IAAS,EAAO,KAAK,GAAG,MAAM,EAAa,EAAE,OAAO,CAAC,CAAC,GAGtD,IACJ,KACA,KAAK,IACH,GAAG,EAAK,SAAS,MAAM,EAAO,KAAK,MAAM,OAAO,EAAE,EAAE,IAAI,KAAK,CAAC,CAAC,GAC/D,CACF,GAGI,IAAc,IAAI,KAAK,KAAM,EAAK,QAGlC,IAAY,EAAmB,CAAC,CACnC,QAAQ,MAAO,IAAS,IAAK,CAAQ,CAAC,CACtC,OAAO,GAAG,MAAM,IAAI,CAAU,CAAC,CAC/B,MAAM,CAAiB,GAGpB,KAAmB,MACvB,EAAK,KAAK,GAAG,MAAM,OAAO,EAAK,EAAE,GAAG,EAAU,KAAK,CAAC,GAGhD,KAAa,GAAmB,MAAkB;EACtD,IAAM,IAAQ,IAAa,IAAY,KAAK,KAAK,GAC3C,IAAK,IAAS,IAAS;EAC7B,OAAO;GACL,GAAG,IAAI,KAAK,IAAI,CAAK;GACrB,GAAG,IAAI,KAAK,IAAI,CAAK;EACvB;CACF;CAEA,OACE,kBAAC,EAAO,KAAR;EACE,MAAM,MAAS;GAEb,AADA,EAAgE,UAAU,GACtE,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,MAAK,EAAuD,UAAU;EACjF;EACA,WAAW,EAAG,mBAAmB,CAAS;EAC1C,GAAK,IACD;GAAE,SAAS;IAAE,SAAS;IAAG,OAAO;GAAK;GAAG,SAAS;IAAE,SAAS;IAAG,OAAO;GAAE;GAAG,YAAY,EAAO;EAAK,IACnG,CAAC;EACL,GAAI,EAAY,CAAK;YAVvB,CAYG,IAAiB,KAChB,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD;GACE,OAAO;GACC;GACR,MAAK;GACL,cAAY,KAAa;aAEzB,kBAAC,KAAD;IAAG,WAAW,aAAa,IAAiB,EAAE,GAAG,IAAS,EAAE;cAA5D;KAEG,MAAM,KAAK,EAAE,QAAQ,EAAO,IAAI,GAAG,MAAM;MACxC,IAAM,IAAe,IAAS,KAAW,IAAI;MAO7C,OACE,kBAAC,WAAD;OAEU,QATG,EACZ,KAAK,GAAG,MAAM;QACb,IAAM,IAAQ,IAAa,IAAI,KAAK,KAAK;QACzC,OAAO,GAAG,IAAc,KAAK,IAAI,CAAK,EAAE,GAAG,IAAc,KAAK,IAAI,CAAK;OACzE,CAAC,CAAC,CACD,KAAK,GAII;OACR,MAAK;OACL,QAAO;OACP,iBAAgB;OAChB,aAAa;MACd,GANM,QAAQ,GAMd;KAEL,CAAC;KAGA,EAAK,KAAK,GAAG,MAAM;MAClB,IAAM,IAAQ,IAAa,IAAI,KAAK,KAAK;MAGzC,OACE,kBAAC,QAAD;OAEE,IAAI;OACJ,IAAI;OACJ,IAPM,IAAS,KAAK,IAAI,CAAK;OAQ7B,IAPM,IAAS,KAAK,IAAI,CAAK;OAQ7B,QAAO;OACP,aAAa;MACd,GAPM,QAAQ,GAOd;KAEL,CAAC;KAGA,EAAK,KAAK,GAAO,MAAM;MACtB,IAAM,IAAQ,IAAa,IAAI,KAAK,KAAK,GACnC,IAAc,IAAS,IACvB,IAAI,IAAc,KAAK,IAAI,CAAK,GAChC,IAAI,IAAc,KAAK,IAAI,CAAK,GAGlC,IAAyC;MAK7C,OAJI,KAAK,IAAI,KAAK,IAAI,CAAK,CAAC,IAAI,OAC9B,IAAa,KAAK,IAAI,CAAK,IAAI,IAAI,UAAU,QAI7C,kBAAC,QAAD;OAEK;OACA;OACS;OACZ,kBAAiB;OACjB,WAAU;iBAET;MACG,GARC,SAAS,GAQV;KAEV,CAAC;KAGA,MAAM,KAAK,EAAE,QAAQ,EAAO,IAAI,GAAG,MAAM;MACxC,IAAM,IAAa,KAAK,MAAO,IAAW,KAAW,IAAI,EAAE,GACrD,IAAe,IAAS,KAAW,IAAI,IACvC,IAAQ,CAAC,KAAK,KAAK;MAGzB,OACE,kBAAC,QAAD;OAEK,GALG,IAAc,KAAK,IAAI,CAAK,IAAI;OAMnC,GALG,IAAc,KAAK,IAAI,CAAK;OAMlC,YAAW;OACX,kBAAiB;OACjB,WAAU;iBAET;MACG,GARC,eAAe,GAQhB;KAEV,CAAC;KAGA,EAAO,KAAK,GAAG,MAAc;MAC5B,IAAM,IAAS,EAAgB,EAAE,GAAG,GAC9B,IAAQ,EAAU,CAAM;MAG9B,OAFK,IAGH,kBAAC,KAAD,EAAA,UAAA,CACE,kBAAC,QAAD;OACE,GAAG;OACH,MAAM,EAAO;OACA;OACb,QAAQ,EAAO;OACf,aAAa;OACb,gBAAe;MAChB,CAAA,GAGA,KACC,EAAO,KAAK,GAAG,MAAM;OACnB,IAAM,EAAE,MAAG,SAAM,EAAU,GAAG,CAAC;OAC/B,OACE,kBAAC,UAAD;QAEE,IAAI;QACJ,IAAI;QACJ,GAAG;QACH,MAAM,EAAO;QACb,QAAO;QACP,aAAa;QACb,WAAU;OACX,GARM,OAAO,EAAE,IAAI,GAAG,GAQtB;MAEL,CAAC,CACF,EAAA,GA3BK,EAAE,GA2BP,IA9Bc;KAgCrB,CAAC;KAGA,KACC,EAAK,KAAK,GAAW,MAAM;MAGzB,IAAM,IAAQ,IAAa,IAAI,KAAK,KAAK;MAIzC,OACE,kBAAC,UAAD;OAEE,IANS,IAAS,KAAK,IAAI,CAAK;OAOhC,IANS,IAAS,KAAK,IAAI,CAAK;OAOhC,GAAG;OACH,MAAK;OACL,WAAU;OACV,cAAc,MAAM;QAClB,IAAM,IAAO,EAAE,cACZ,QAAQ,KAAK,CAAC,EACb,sBAAsB;QAC1B,EACE,EAAE,WAAW,GAAM,QAAQ,IAC3B,EAAE,WAAW,GAAM,OAAO,IAC1B,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAe;QAAe,CAAA,GAC5C,EAAO,KAAK,GAAG,MAAS;SACvB,IAAM,IAAM,OAAO,EAAK,EAAE,GAAG,EAAE,IAAI,KAAK;SACxC,OACE,kBAAC,OAAD;UAEE,WAAU;oBAFZ;WAIE,kBAAC,QAAD;YACE,WAAU;YACV,OAAO,EAAE,iBAAiB,EAAO,GAAM;WACxC,CAAA;WACD,kBAAC,QAAD;YAAM,WAAU;sBAAhB,CACG,EAAE,OAAM,GACL;;WAAE;WACP,EAAI,eAAe;UACjB;YAXE,EAAE,GAWJ;QAET,CAAC,CACE,EAAA,CAAA,CACP;OACF;OACA,cAAc;MACf,GArCM,SAAS,GAqCf;KAEL,CAAC;IACF;;EACA,CAAA,GAGJ,KAAe,kBAAC,GAAD,EAAc,OAAO,EAAU,CAAA,CAC/C,EAAA,CAAA,GAIH,KACC,kBAAC,GAAD;GACE,OAAO,EAAO,KAAK,GAAG,OAAO;IAC3B,OAAO,EAAE;IACT,OAAO,EAAO;GAChB,EAAE;GACF,WAAU;EACX,CAAA,CAEO;;AAEd,CACF;AACA,EAAW,cAAc"}
@@ -25,12 +25,12 @@ var d = {
25
25
  className: e("inline-block align-middle", y),
26
26
  ...b,
27
27
  children: r.map((e, r) => {
28
- let a = T + r * (t + 1), o = M(e);
28
+ let a = T + r * (t + 1), o = M(e), s = Math.max(1, n - o);
29
29
  return /* @__PURE__ */ i("rect", {
30
30
  x: a,
31
31
  y: o,
32
32
  width: t,
33
- height: Math.max(1, n - o),
33
+ height: s,
34
34
  rx: Math.min(1, t / 2),
35
35
  fill: S
36
36
  }, r);
@@ -1 +1 @@
1
- {"version":3,"file":"sparkline.js","names":[],"sources":["../../../src/ui/charts/sparkline.tsx"],"sourcesContent":["'use client'\n\nimport { scaleLinear } from 'd3-scale'\nimport { area, curveMonotoneX,line } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\n\nexport interface SparklineProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'children'> {\n /** Numeric data points */\n data: number[]\n /** Visual variant */\n variant?: 'line' | 'bar' | 'area'\n /** Width (default: 120) */\n width?: number\n /** Height (default: 32) */\n height?: number\n /** Color token or CSS color */\n color?: string\n /** Show a dot on the last data point (line/area only) */\n showLastDot?: boolean\n /** Line stroke width (line/area only, default: 1.5) */\n strokeWidth?: number\n /** Animate on mount (default: true) */\n animate?: boolean\n className?: string\n}\n\nconst pathDrawTransition = { duration: 1, ease: 'easeOut' as const }\n\nexport const Sparkline = React.forwardRef<SVGSVGElement, SparklineProps>(\n (\n {\n data,\n variant = 'line',\n width = 120,\n height = 32,\n color,\n showLastDot = false,\n strokeWidth = 1.5,\n animate = true,\n className,\n ...props\n },\n ref,\n ) => {\n const resolvedColor = resolveColor(color, 0)\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n if (!data.length) return null\n\n const padding = variant === 'bar' ? 1 : strokeWidth\n const innerWidth = width - padding * 2\n const innerHeight = height - padding * 2\n\n const xScale = scaleLinear()\n .domain([0, Math.max(data.length - 1, 1)])\n .range([padding, padding + innerWidth])\n\n const yMin = Math.min(...data)\n const yMax = Math.max(...data)\n const yDomain = yMin === yMax ? [yMin - 1, yMax + 1] : [yMin, yMax]\n\n const yScale = scaleLinear()\n .domain(yDomain)\n .range([padding + innerHeight, padding])\n\n if (variant === 'bar') {\n const barGap = 1\n const barWidth = Math.max(\n 1,\n (innerWidth - barGap * (data.length - 1)) / data.length,\n )\n // For bars, baseline is the bottom of the chart\n const baselineY = padding + innerHeight\n\n return (\n <svg\n ref={ref}\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Sparkline bar chart\"\n className={cn('inline-block align-middle', className)}\n {...props}\n >\n {data.map((value, i) => {\n const x = padding + i * (barWidth + barGap)\n const y = yScale(value)\n const barHeight = Math.max(1, baselineY - y)\n return (\n <rect\n key={i}\n x={x}\n y={y}\n width={barWidth}\n height={barHeight}\n rx={Math.min(1, barWidth / 2)}\n fill={resolvedColor}\n />\n )\n })}\n </svg>\n )\n }\n\n if (variant === 'area') {\n const areaGen = area<number>()\n .curve(curveMonotoneX)\n .x((_, i) => xScale(i))\n .y0(padding + innerHeight)\n .y1((d) => yScale(d))\n\n const lineGen = line<number>()\n .curve(curveMonotoneX)\n .x((_, i) => xScale(i))\n .y((d) => yScale(d))\n\n const areaD = areaGen(data) ?? ''\n const lineD = lineGen(data) ?? ''\n\n const lastX = xScale(data.length - 1)\n const lastY = yScale(data[data.length - 1])\n\n return (\n <svg\n ref={ref}\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Sparkline area chart\"\n className={cn('inline-block align-middle', className)}\n {...props}\n >\n <path d={areaD} fill={resolvedColor} opacity={0.2} />\n {shouldAnimate ? (\n <motion.path\n d={lineD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={pathDrawTransition}\n />\n ) : (\n <path\n d={lineD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n )}\n {showLastDot && (\n <circle\n cx={lastX}\n cy={lastY}\n r={strokeWidth + 1}\n fill={resolvedColor}\n />\n )}\n </svg>\n )\n }\n\n // Default: line variant\n const lineGen = line<number>()\n .curve(curveMonotoneX)\n .x((_, i) => xScale(i))\n .y((d) => yScale(d))\n\n const pathD = lineGen(data) ?? ''\n\n const lastX = xScale(data.length - 1)\n const lastY = yScale(data[data.length - 1])\n\n return (\n <svg\n ref={ref}\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Sparkline chart\"\n className={cn('inline-block align-middle', className)}\n {...props}\n >\n {shouldAnimate ? (\n <motion.path\n d={pathD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={pathDrawTransition}\n />\n ) : (\n <path\n d={pathD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n )}\n {showLastDot && (\n <circle\n cx={lastX}\n cy={lastY}\n r={strokeWidth + 1}\n fill={resolvedColor}\n />\n )}\n </svg>\n )\n },\n)\nSparkline.displayName = 'Sparkline'\n"],"mappings":"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"}
1
+ {"version":3,"file":"sparkline.js","names":[],"sources":["../../../src/ui/charts/sparkline.tsx"],"sourcesContent":["'use client'\n\nimport { scaleLinear } from 'd3-scale'\nimport { area, curveMonotoneX,line } from 'd3-shape'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\nimport { useReducedMotion } from './_internal/animation'\nimport { resolveColor } from './_internal/colors'\n\nexport interface SparklineProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'children'> {\n /** Numeric data points */\n data: number[]\n /** Visual variant */\n variant?: 'line' | 'bar' | 'area'\n /** Width (default: 120) */\n width?: number\n /** Height (default: 32) */\n height?: number\n /** Color token or CSS color */\n color?: string\n /** Show a dot on the last data point (line/area only) */\n showLastDot?: boolean\n /** Line stroke width (line/area only, default: 1.5) */\n strokeWidth?: number\n /** Animate on mount (default: true) */\n animate?: boolean\n className?: string\n}\n\nconst pathDrawTransition = { duration: 1, ease: 'easeOut' as const }\n\nexport const Sparkline = React.forwardRef<SVGSVGElement, SparklineProps>(\n (\n {\n data,\n variant = 'line',\n width = 120,\n height = 32,\n color,\n showLastDot = false,\n strokeWidth = 1.5,\n animate = true,\n className,\n ...props\n },\n ref,\n ) => {\n const resolvedColor = resolveColor(color, 0)\n const reducedMotion = useReducedMotion()\n const shouldAnimate = animate && !reducedMotion\n\n if (!data.length) return null\n\n const padding = variant === 'bar' ? 1 : strokeWidth\n const innerWidth = width - padding * 2\n const innerHeight = height - padding * 2\n\n const xScale = scaleLinear()\n .domain([0, Math.max(data.length - 1, 1)])\n .range([padding, padding + innerWidth])\n\n const yMin = Math.min(...data)\n const yMax = Math.max(...data)\n const yDomain = yMin === yMax ? [yMin - 1, yMax + 1] : [yMin, yMax]\n\n const yScale = scaleLinear()\n .domain(yDomain)\n .range([padding + innerHeight, padding])\n\n if (variant === 'bar') {\n const barGap = 1\n const barWidth = Math.max(\n 1,\n (innerWidth - barGap * (data.length - 1)) / data.length,\n )\n // For bars, baseline is the bottom of the chart\n const baselineY = padding + innerHeight\n\n return (\n <svg\n ref={ref}\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Sparkline bar chart\"\n className={cn('inline-block align-middle', className)}\n {...props}\n >\n {data.map((value, i) => {\n const x = padding + i * (barWidth + barGap)\n const y = yScale(value)\n const barHeight = Math.max(1, baselineY - y)\n return (\n <rect\n key={i}\n x={x}\n y={y}\n width={barWidth}\n height={barHeight}\n rx={Math.min(1, barWidth / 2)}\n fill={resolvedColor}\n />\n )\n })}\n </svg>\n )\n }\n\n if (variant === 'area') {\n const areaGen = area<number>()\n .curve(curveMonotoneX)\n .x((_, i) => xScale(i))\n .y0(padding + innerHeight)\n .y1((d) => yScale(d))\n\n const lineGen = line<number>()\n .curve(curveMonotoneX)\n .x((_, i) => xScale(i))\n .y((d) => yScale(d))\n\n const areaD = areaGen(data) ?? ''\n const lineD = lineGen(data) ?? ''\n\n const lastX = xScale(data.length - 1)\n const lastY = yScale(data[data.length - 1])\n\n return (\n <svg\n ref={ref}\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Sparkline area chart\"\n className={cn('inline-block align-middle', className)}\n {...props}\n >\n <path d={areaD} fill={resolvedColor} opacity={0.2} />\n {shouldAnimate ? (\n <motion.path\n d={lineD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={pathDrawTransition}\n />\n ) : (\n <path\n d={lineD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n )}\n {showLastDot && (\n <circle\n cx={lastX}\n cy={lastY}\n r={strokeWidth + 1}\n fill={resolvedColor}\n />\n )}\n </svg>\n )\n }\n\n // Default: line variant\n const lineGen = line<number>()\n .curve(curveMonotoneX)\n .x((_, i) => xScale(i))\n .y((d) => yScale(d))\n\n const pathD = lineGen(data) ?? ''\n\n const lastX = xScale(data.length - 1)\n const lastY = yScale(data[data.length - 1])\n\n return (\n <svg\n ref={ref}\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Sparkline chart\"\n className={cn('inline-block align-middle', className)}\n {...props}\n >\n {shouldAnimate ? (\n <motion.path\n d={pathD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={pathDrawTransition}\n />\n ) : (\n <path\n d={pathD}\n fill=\"none\"\n stroke={resolvedColor}\n strokeWidth={strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n )}\n {showLastDot && (\n <circle\n cx={lastX}\n cy={lastY}\n r={strokeWidth + 1}\n fill={resolvedColor}\n />\n )}\n </svg>\n )\n },\n)\nSparkline.displayName = 'Sparkline'\n"],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  "use client";
2
+ import * as React from 'react';
2
3
  export interface DateSeparatorProps {
3
4
  date: Date | string;
4
5
  format?: (date: Date) => string;
5
6
  className?: string;
6
7
  }
7
- declare function DateSeparator({ date, format, className }: DateSeparatorProps): import("react/jsx-runtime").JSX.Element;
8
+ declare function DateSeparator({ date, format, className }: DateSeparatorProps): React.JSX.Element;
8
9
  declare namespace DateSeparator {
9
10
  var displayName: string;
10
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"date-separator.d.ts","sourceRoot":"","sources":["../../../src/ui/chat/date-separator.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAsBD,iBAAS,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,kBAAkB,2CAarE;kBAbQ,aAAa;;;AAgBtB,OAAO,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"date-separator.d.ts","sourceRoot":"","sources":["../../../src/ui/chat/date-separator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAsBD,iBAAS,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,kBAAkB,qBAarE;kBAbQ,aAAa;;;AAgBtB,OAAO,EAAE,aAAa,EAAE,CAAA"}
@@ -24,14 +24,14 @@ export interface MessageAvatarProps {
24
24
  size?: 'sm' | 'md';
25
25
  children?: React.ReactNode;
26
26
  }
27
- declare function MessageAvatar({ src, fallback, icon, size, children, }: MessageAvatarProps): import("react/jsx-runtime").JSX.Element;
27
+ declare function MessageAvatar({ src, fallback, icon, size, children, }: MessageAvatarProps): React.JSX.Element;
28
28
  declare namespace MessageAvatar {
29
29
  var displayName: string;
30
30
  }
31
31
  export interface MessageContentProps extends React.HTMLAttributes<HTMLDivElement> {
32
32
  children: React.ReactNode;
33
33
  }
34
- declare function MessageContent({ children, className, ...props }: MessageContentProps): import("react/jsx-runtime").JSX.Element;
34
+ declare function MessageContent({ children, className, ...props }: MessageContentProps): React.JSX.Element;
35
35
  declare namespace MessageContent {
36
36
  var displayName: string;
37
37
  }
@@ -42,14 +42,14 @@ export interface MessageAuthorProps {
42
42
  formattedTimestamp?: string;
43
43
  timestampFormat?: (date: Date) => string;
44
44
  }
45
- declare function MessageAuthor({ name, badge, timestamp, formattedTimestamp, timestampFormat, }: MessageAuthorProps): import("react/jsx-runtime").JSX.Element | null;
45
+ declare function MessageAuthor({ name, badge, timestamp, formattedTimestamp, timestampFormat, }: MessageAuthorProps): React.JSX.Element | null;
46
46
  declare namespace MessageAuthor {
47
47
  var displayName: string;
48
48
  }
49
49
  export interface MessageBodyProps extends React.HTMLAttributes<HTMLDivElement> {
50
50
  children: React.ReactNode;
51
51
  }
52
- declare function MessageBody({ children, className, ...props }: MessageBodyProps): import("react/jsx-runtime").JSX.Element;
52
+ declare function MessageBody({ children, className, ...props }: MessageBodyProps): React.JSX.Element;
53
53
  declare namespace MessageBody {
54
54
  var displayName: string;
55
55
  }
@@ -60,7 +60,7 @@ export interface MessageEditableBodyProps {
60
60
  canEdit?: boolean;
61
61
  renderContent?: (content: string) => React.ReactNode;
62
62
  }
63
- declare function MessageEditableBody({ content, onSave, onCancel, canEdit, renderContent, }: MessageEditableBodyProps): import("react/jsx-runtime").JSX.Element;
63
+ declare function MessageEditableBody({ content, onSave, onCancel, canEdit, renderContent, }: MessageEditableBodyProps): React.JSX.Element;
64
64
  declare namespace MessageEditableBody {
65
65
  var displayName: string;
66
66
  }
@@ -72,7 +72,7 @@ export interface MessageReactionsProps {
72
72
  }[];
73
73
  onReact: (emoji: string) => void;
74
74
  }
75
- declare function MessageReactions({ reactions, onReact }: MessageReactionsProps): import("react/jsx-runtime").JSX.Element | null;
75
+ declare function MessageReactions({ reactions, onReact }: MessageReactionsProps): React.JSX.Element | null;
76
76
  declare namespace MessageReactions {
77
77
  var displayName: string;
78
78
  }
@@ -80,7 +80,7 @@ export interface MessageActionsProps {
80
80
  children: React.ReactNode;
81
81
  delay?: number;
82
82
  }
83
- declare function MessageActions({ children, delay }: MessageActionsProps): import("react/jsx-runtime").JSX.Element;
83
+ declare function MessageActions({ children, delay }: MessageActionsProps): React.JSX.Element;
84
84
  declare namespace MessageActions {
85
85
  var displayName: string;
86
86
  }
@@ -90,7 +90,7 @@ export interface MessageActionProps {
90
90
  onClick: () => void;
91
91
  variant?: 'default' | 'danger';
92
92
  }
93
- declare function MessageAction({ icon, label, onClick, variant, }: MessageActionProps): import("react/jsx-runtime").JSX.Element;
93
+ declare function MessageAction({ icon, label, onClick, variant, }: MessageActionProps): React.JSX.Element;
94
94
  declare namespace MessageAction {
95
95
  var displayName: string;
96
96
  }