@flikk/ui 1.0.0-beta.27 → 1.0.0-beta.29

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 (319) hide show
  1. package/dist/bg/1.webp +0 -0
  2. package/dist/bg/10.webp +0 -0
  3. package/dist/bg/11.webp +0 -0
  4. package/dist/bg/12.webp +0 -0
  5. package/dist/bg/13.webp +0 -0
  6. package/dist/bg/14.webp +0 -0
  7. package/dist/bg/15.webp +0 -0
  8. package/dist/bg/16.webp +0 -0
  9. package/dist/bg/17.webp +0 -0
  10. package/dist/bg/18.webp +0 -0
  11. package/dist/bg/19.webp +0 -0
  12. package/dist/bg/2.webp +0 -0
  13. package/dist/bg/20.webp +0 -0
  14. package/dist/bg/21.webp +0 -0
  15. package/dist/bg/22.webp +0 -0
  16. package/dist/bg/3.webp +0 -0
  17. package/dist/bg/4.webp +0 -0
  18. package/dist/bg/5.webp +0 -0
  19. package/dist/bg/6.webp +0 -0
  20. package/dist/bg/7.webp +0 -0
  21. package/dist/bg/8.webp +0 -0
  22. package/dist/bg/9.webp +0 -0
  23. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
  24. package/dist/components/ai/PromptInput/PromptInput.js +7 -143
  25. package/dist/components/ai/PromptInput/VoiceRecorder.js +0 -88
  26. package/dist/components/ai/TokenCounter/TokenCounter.theme.js +1 -1
  27. package/dist/components/canvas/Background.d.ts +19 -0
  28. package/dist/components/canvas/Background.js +23 -0
  29. package/dist/components/canvas/BaseNode.d.ts +15 -0
  30. package/dist/components/canvas/BaseNode.js +20 -0
  31. package/dist/components/canvas/CanvasToolbar.d.ts +34 -0
  32. package/dist/components/canvas/CanvasToolbar.js +34 -0
  33. package/dist/components/canvas/Edge.d.ts +35 -0
  34. package/dist/components/canvas/Edge.js +97 -0
  35. package/dist/components/canvas/EdgeLayer.d.ts +18 -0
  36. package/dist/components/canvas/EdgeLayer.js +111 -0
  37. package/dist/components/canvas/Handle.d.ts +11 -0
  38. package/dist/components/canvas/Handle.js +63 -0
  39. package/dist/components/canvas/MiniMap.d.ts +22 -0
  40. package/dist/components/canvas/MiniMap.js +105 -0
  41. package/dist/components/canvas/NodeCanvas.d.ts +10 -0
  42. package/dist/components/canvas/NodeCanvas.js +477 -0
  43. package/dist/components/canvas/NodeCanvas.theme.d.ts +7 -0
  44. package/dist/components/canvas/NodeCanvas.theme.js +9 -0
  45. package/dist/components/canvas/NodeCanvas.types.d.ts +187 -0
  46. package/dist/components/canvas/NodeControls.d.ts +25 -0
  47. package/dist/components/canvas/NodeControls.js +40 -0
  48. package/dist/components/canvas/NodeRenderer.d.ts +19 -0
  49. package/dist/components/canvas/NodeRenderer.js +117 -0
  50. package/dist/components/canvas/changes.d.ts +11 -0
  51. package/dist/components/canvas/changes.js +76 -0
  52. package/dist/components/canvas/context/CanvasContext.d.ts +32 -0
  53. package/dist/components/canvas/context/CanvasContext.js +14 -0
  54. package/dist/components/canvas/context/ConnectionContext.d.ts +33 -0
  55. package/dist/components/canvas/context/ConnectionContext.js +13 -0
  56. package/dist/components/canvas/context/HandleRegistry.d.ts +24 -0
  57. package/dist/components/canvas/context/HandleRegistry.js +15 -0
  58. package/dist/components/canvas/context/InteractionContext.d.ts +18 -0
  59. package/dist/components/canvas/context/InteractionContext.js +14 -0
  60. package/dist/components/canvas/context/NodeIdContext.d.ts +3 -0
  61. package/dist/components/canvas/context/NodeIdContext.js +15 -0
  62. package/dist/components/canvas/hooks/useConnection.d.ts +17 -0
  63. package/dist/components/canvas/hooks/useConnection.js +29 -0
  64. package/dist/components/canvas/hooks/useMarquee.d.ts +25 -0
  65. package/dist/components/canvas/hooks/useMarquee.js +91 -0
  66. package/dist/components/canvas/hooks/useNodeDrag.d.ts +23 -0
  67. package/dist/components/canvas/hooks/useNodeDrag.js +110 -0
  68. package/dist/components/canvas/hooks/usePanZoom.d.ts +30 -0
  69. package/dist/components/canvas/hooks/usePanZoom.js +189 -0
  70. package/dist/components/canvas/hooks/useViewport.d.ts +21 -0
  71. package/dist/components/canvas/hooks/useViewport.js +35 -0
  72. package/dist/components/canvas/index.d.ts +14 -0
  73. package/dist/components/canvas/index.js +12 -0
  74. package/dist/components/canvas/layout.d.ts +22 -0
  75. package/dist/components/canvas/layout.js +67 -0
  76. package/dist/components/canvas/utils.d.ts +4 -0
  77. package/dist/components/canvas/utils.js +16 -0
  78. package/dist/components/charts/AreaChart/AreaChart.js +136 -101
  79. package/dist/components/charts/AreaChart/AreaChart.types.d.ts +5 -5
  80. package/dist/components/charts/AreaChart/AreaChart.types.js +1 -0
  81. package/dist/components/charts/BarChart/BarChart.js +207 -143
  82. package/dist/components/charts/BarChart/BarChart.types.d.ts +4 -4
  83. package/dist/components/charts/BarChart/BarChart.types.js +1 -0
  84. package/dist/components/charts/ComboChart/ComboChart.types.d.ts +2 -2
  85. package/dist/components/charts/LineChart/LineChart.js +88 -72
  86. package/dist/components/charts/LineChart/LineChart.types.d.ts +3 -3
  87. package/dist/components/charts/RadarChart/RadarChart.js +1 -1
  88. package/dist/components/charts/RadarChart/RadarChart.theme.js +5 -2
  89. package/dist/components/charts/ScatterPlot/ScatterPlot.js +62 -72
  90. package/dist/components/charts/ScatterPlot/ScatterPlot.theme.js +10 -1
  91. package/dist/components/charts/ScatterPlot/ScatterPlot.types.d.ts +3 -9
  92. package/dist/components/charts/StackedBarChart/StackedBarChart.js +33 -33
  93. package/dist/components/charts/StackedBarChart/StackedBarChart.types.d.ts +2 -2
  94. package/dist/components/charts/hooks/index.d.ts +2 -0
  95. package/dist/components/charts/hooks/useChartDimensions.d.ts +29 -0
  96. package/dist/components/charts/hooks/useChartDimensions.js +42 -0
  97. package/dist/components/charts/shared/ChartTooltip/ChartTooltip.theme.js +1 -1
  98. package/dist/components/charts/types/chart.types.d.ts +11 -2
  99. package/dist/components/charts/types/chart.types.js +10 -3
  100. package/dist/components/core/Avatar/Avatar.js +5 -1
  101. package/dist/components/core/AvatarGroup/AvatarGroup.js +5 -1
  102. package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +4 -2
  103. package/dist/components/core/Badge/Badge.js +1 -1
  104. package/dist/components/core/Badge/Badge.theme.js +16 -15
  105. package/dist/components/core/Button/Button.js +1 -1
  106. package/dist/components/core/Button/Button.theme.js +2 -2
  107. package/dist/components/core/Calendar/Calendar.theme.js +1 -1
  108. package/dist/components/core/Card/Card.js +7 -3
  109. package/dist/components/core/Card/Card.theme.js +3 -3
  110. package/dist/components/core/Card/Card.types.d.ts +27 -2
  111. package/dist/components/core/CommandPalette/CommandPalette.theme.js +2 -2
  112. package/dist/components/core/ContextMenu/ContextMenu.theme.js +2 -2
  113. package/dist/components/core/ContextMenu/ContextMenuItem.js +1 -1
  114. package/dist/components/core/ContextMenu/ContextMenuSubTrigger.js +1 -1
  115. package/dist/components/core/Dropdown/Dropdown.theme.js +3 -3
  116. package/dist/components/core/Dropdown/DropdownMenu.js +57 -29
  117. package/dist/components/core/HeroCard/HeroCard.d.ts +5 -0
  118. package/dist/components/core/HeroCard/HeroCard.js +99 -0
  119. package/dist/components/core/HeroCard/HeroCard.theme.d.ts +3 -0
  120. package/dist/components/core/HeroCard/HeroCard.theme.js +8 -0
  121. package/dist/components/core/HeroCard/HeroCard.types.d.ts +70 -0
  122. package/dist/components/core/HeroCard/index.d.ts +4 -0
  123. package/dist/components/core/Kbd/Kbd.theme.js +1 -1
  124. package/dist/components/core/Modal/Modal.d.ts +1 -1
  125. package/dist/components/core/Modal/Modal.js +2 -7
  126. package/dist/components/core/Modal/Modal.theme.js +4 -8
  127. package/dist/components/core/Modal/Modal.types.d.ts +0 -10
  128. package/dist/components/core/Modal/index.d.ts +1 -1
  129. package/dist/components/core/ModalStack/ModalStack.d.ts +1 -1
  130. package/dist/components/core/ModalStack/ModalStack.types.d.ts +1 -2
  131. package/dist/components/core/ModalStack/ModalStackModal.d.ts +1 -1
  132. package/dist/components/core/ModalStack/ModalStackModal.js +2 -7
  133. package/dist/components/core/PageHeading/PageHeading.theme.js +2 -2
  134. package/dist/components/core/Popover/Popover.theme.js +1 -1
  135. package/dist/components/core/ScrollArea/ScrollArea.js +242 -4
  136. package/dist/components/core/ScrollArea/ScrollArea.types.d.ts +12 -1
  137. package/dist/components/core/ScrollArea/smooth/SmoothScrollEngine.d.ts +4 -0
  138. package/dist/components/core/ScrollArea/smooth/SmoothScrollEngine.js +23 -0
  139. package/dist/components/core/ScrollArea/smooth/useSmoothScroll.js +4 -0
  140. package/dist/components/core/ScrollArea/smooth/useSmoothScroll.types.d.ts +5 -0
  141. package/dist/components/core/Segmented/Segmented.theme.js +2 -2
  142. package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
  143. package/dist/components/core/index.d.ts +1 -0
  144. package/dist/components/core/index.js +2 -0
  145. package/dist/components/data-display/DescriptionList/DescriptionList.js +23 -7
  146. package/dist/components/data-display/DescriptionList/DescriptionList.theme.js +10 -3
  147. package/dist/components/data-display/DescriptionList/DescriptionList.types.d.ts +49 -10
  148. package/dist/components/data-display/DescriptionList/index.d.ts +1 -1
  149. package/dist/components/data-display/Feed/Feed.js +28 -5
  150. package/dist/components/data-display/Feed/Feed.theme.js +1 -1
  151. package/dist/components/data-display/Feed/Feed.types.d.ts +32 -1
  152. package/dist/components/data-display/Feed/index.d.ts +1 -1
  153. package/dist/components/data-display/Metric/Metric.js +8 -8
  154. package/dist/components/data-display/Metric/Metric.theme.d.ts +3 -2
  155. package/dist/components/data-display/Metric/Metric.theme.js +50 -68
  156. package/dist/components/data-display/Metric/Metric.types.d.ts +19 -21
  157. package/dist/components/data-display/Table/Table.js +2 -2
  158. package/dist/components/data-display/Table/Table.theme.js +24 -4
  159. package/dist/components/data-display/Table/Table.types.d.ts +8 -0
  160. package/dist/components/data-display/Table/TableBody.js +2 -2
  161. package/dist/components/data-display/Table/TableCell.js +1 -1
  162. package/dist/components/data-display/Table/TableRow.d.ts +1 -1
  163. package/dist/components/data-display/Table/TableRow.js +9 -2
  164. package/dist/components/data-display/Timeline/Timeline.js +27 -5
  165. package/dist/components/data-display/Timeline/Timeline.theme.d.ts +10 -2
  166. package/dist/components/data-display/Timeline/Timeline.theme.js +14 -8
  167. package/dist/components/data-display/Timeline/Timeline.types.d.ts +48 -16
  168. package/dist/components/data-display/Timeline/Timeline.utils.d.ts +6 -0
  169. package/dist/components/data-display/Timeline/Timeline.utils.js +11 -0
  170. package/dist/components/data-display/Timeline/TimelineItem.js +13 -20
  171. package/dist/components/data-display/Timeline/TimelineMarker.js +10 -8
  172. package/dist/components/data-display/Timeline/index.d.ts +2 -2
  173. package/dist/components/effects/3d/index.d.ts +0 -2
  174. package/dist/components/effects/3d/index.js +0 -1
  175. package/dist/components/effects/DotPattern/DotPattern.js +1 -1
  176. package/dist/components/effects/Overlay/Overlay.theme.js +1 -2
  177. package/dist/components/effects/Preloader/Preloader.animations.d.ts +23 -0
  178. package/dist/components/effects/Preloader/Preloader.animations.js +150 -0
  179. package/dist/components/effects/Preloader/Preloader.d.ts +3 -0
  180. package/dist/components/effects/Preloader/Preloader.js +119 -0
  181. package/dist/components/effects/Preloader/Preloader.types.d.ts +63 -0
  182. package/dist/components/effects/Preloader/index.d.ts +2 -0
  183. package/dist/components/effects/ProgressiveBlur/ProgressiveBlur.js +25 -14
  184. package/dist/components/effects/ProgressiveBlur/ProgressiveBlur.types.d.ts +2 -0
  185. package/dist/components/effects/TiltCard/TiltCard.d.ts +12 -0
  186. package/dist/components/effects/TiltCard/TiltCard.glow.d.ts +28 -0
  187. package/dist/components/effects/TiltCard/TiltCard.glow.js +114 -0
  188. package/dist/components/effects/TiltCard/TiltCard.js +177 -0
  189. package/dist/components/effects/{SpotlightBorder/SpotlightBorder.shaders.d.ts → TiltCard/TiltCard.shaders.d.ts} +1 -1
  190. package/dist/components/effects/{SpotlightBorder/SpotlightBorder.shaders.js → TiltCard/TiltCard.shaders.js} +1 -1
  191. package/dist/components/effects/TiltCard/TiltCard.types.d.ts +88 -0
  192. package/dist/components/effects/TiltCard/index.d.ts +2 -0
  193. package/dist/components/effects/index.d.ts +4 -12
  194. package/dist/components/effects/index.js +2 -6
  195. package/dist/components/forms/Checkbox/Checkbox.js +7 -1
  196. package/dist/components/forms/DatePicker/DatePicker.theme.js +2 -2
  197. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +1 -1
  198. package/dist/components/forms/FileUpload/FileUpload.js +1 -89
  199. package/dist/components/forms/FormLabel/FormLabel.theme.js +1 -1
  200. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +2 -2
  201. package/dist/components/forms/Slider/Slider.theme.js +1 -1
  202. package/dist/components/forms/Switch/Switch.js +27 -15
  203. package/dist/components/forms/Switch/Switch.theme.d.ts +36 -6
  204. package/dist/components/forms/Switch/Switch.theme.js +33 -4
  205. package/dist/components/forms/Switch/Switch.types.d.ts +12 -2
  206. package/dist/components/forms/TimePicker/TimePicker.theme.js +1 -2
  207. package/dist/components/forms/TimePicker/TimePickerContent.js +1 -90
  208. package/dist/components/forms/forms.theme.js +1 -1
  209. package/dist/components/forms/index.d.ts +0 -4
  210. package/dist/components/forms/index.js +0 -92
  211. package/dist/components/generative/GenerativeView.d.ts +21 -0
  212. package/dist/components/generative/GenerativeView.js +116 -0
  213. package/dist/components/generative/actions.d.ts +26 -0
  214. package/dist/components/generative/actions.js +51 -0
  215. package/dist/components/generative/index.d.ts +11 -0
  216. package/dist/components/generative/index.js +9 -0
  217. package/dist/components/generative/registry.d.ts +43 -0
  218. package/dist/components/generative/registry.js +114 -0
  219. package/dist/components/generative/resolvers.d.ts +35 -0
  220. package/dist/components/generative/resolvers.js +93 -0
  221. package/dist/components/generative/schema.generated.d.ts +2 -0
  222. package/dist/components/generative/schema.generated.js +1639 -0
  223. package/dist/components/generative/schemaTypes.d.ts +30 -0
  224. package/dist/components/generative/streaming.d.ts +39 -0
  225. package/dist/components/generative/streaming.js +283 -0
  226. package/dist/components/generative/tools.d.ts +21 -0
  227. package/dist/components/generative/tools.js +54 -0
  228. package/dist/components/generative/types.d.ts +41 -0
  229. package/dist/components/generative/useGenerativeStream.d.ts +37 -0
  230. package/dist/components/generative/useGenerativeStream.js +36 -0
  231. package/dist/components/generative/validate.d.ts +24 -0
  232. package/dist/components/generative/validate.js +259 -0
  233. package/dist/components/layout/AppShell/AppShell.theme.js +2 -2
  234. package/dist/components/layout/FormLayout/FormLayout.js +1 -90
  235. package/dist/components/layout/Grid/Grid.d.ts +3 -0
  236. package/dist/components/layout/Grid/Grid.js +50 -0
  237. package/dist/components/layout/Grid/Grid.theme.d.ts +2 -0
  238. package/dist/components/layout/Grid/Grid.theme.js +35 -0
  239. package/dist/components/layout/Grid/Grid.types.d.ts +57 -0
  240. package/dist/components/layout/Grid/index.d.ts +3 -0
  241. package/dist/components/layout/Section/Section.d.ts +3 -0
  242. package/dist/components/layout/Section/Section.js +18 -0
  243. package/dist/components/layout/Section/Section.theme.d.ts +2 -0
  244. package/dist/components/layout/Section/Section.theme.js +10 -0
  245. package/dist/components/layout/Section/Section.types.d.ts +34 -0
  246. package/dist/components/layout/Section/index.d.ts +3 -0
  247. package/dist/components/layout/Stack/Stack.d.ts +3 -0
  248. package/dist/components/layout/Stack/Stack.js +19 -0
  249. package/dist/components/layout/Stack/Stack.theme.d.ts +2 -0
  250. package/dist/components/layout/Stack/Stack.theme.js +10 -0
  251. package/dist/components/layout/Stack/Stack.types.d.ts +39 -0
  252. package/dist/components/layout/Stack/index.d.ts +3 -0
  253. package/dist/components/layout/index.d.ts +3 -0
  254. package/dist/components/layout/index.js +6 -0
  255. package/dist/generative.schema.json +1637 -0
  256. package/dist/index.js +180 -180
  257. package/dist/registry.json +648 -464
  258. package/dist/styles.css +1 -1
  259. package/dist/tools.json +1731 -0
  260. package/package.json +17 -4
  261. package/src/global.scss +53 -101
  262. package/src/styles/theme.css +687 -493
  263. package/dist/bg/1.jpg +0 -0
  264. package/dist/bg/10.jpg +0 -0
  265. package/dist/bg/11.jpg +0 -0
  266. package/dist/bg/14.jpg +0 -0
  267. package/dist/bg/15.jpg +0 -0
  268. package/dist/bg/16.jpg +0 -0
  269. package/dist/bg/17.jpg +0 -0
  270. package/dist/bg/18.jpg +0 -0
  271. package/dist/bg/19.jpg +0 -0
  272. package/dist/bg/2.jpg +0 -0
  273. package/dist/bg/20.jpg +0 -0
  274. package/dist/bg/21.jpg +0 -0
  275. package/dist/bg/22.jpg +0 -0
  276. package/dist/bg/23.jpg +0 -0
  277. package/dist/bg/24.jpg +0 -0
  278. package/dist/bg/3.jpg +0 -0
  279. package/dist/bg/4.jpg +0 -0
  280. package/dist/bg/5.jpg +0 -0
  281. package/dist/bg/6.jpg +0 -0
  282. package/dist/bg/7.jpg +0 -0
  283. package/dist/bg/8.jpg +0 -0
  284. package/dist/bg/9.jpg +0 -0
  285. package/dist/components/effects/MorphingText/MorphingText.d.ts +0 -17
  286. package/dist/components/effects/MorphingText/MorphingText.js +0 -125
  287. package/dist/components/effects/MorphingText/MorphingText.types.d.ts +0 -18
  288. package/dist/components/effects/MorphingText/index.d.ts +0 -2
  289. package/dist/components/effects/PageTransition/PageTransition.animations.d.ts +0 -8
  290. package/dist/components/effects/PageTransition/PageTransition.animations.js +0 -53
  291. package/dist/components/effects/PageTransition/PageTransition.d.ts +0 -3
  292. package/dist/components/effects/PageTransition/PageTransition.js +0 -82
  293. package/dist/components/effects/PageTransition/PageTransition.types.d.ts +0 -15
  294. package/dist/components/effects/PageTransition/index.d.ts +0 -2
  295. package/dist/components/effects/ParallaxSection/ParallaxSection.d.ts +0 -26
  296. package/dist/components/effects/ParallaxSection/ParallaxSection.js +0 -71
  297. package/dist/components/effects/ParallaxSection/ParallaxSection.types.d.ts +0 -11
  298. package/dist/components/effects/ParallaxSection/index.d.ts +0 -2
  299. package/dist/components/effects/Spotlight/Spotlight.d.ts +0 -36
  300. package/dist/components/effects/Spotlight/Spotlight.js +0 -112
  301. package/dist/components/effects/Spotlight/Spotlight.types.d.ts +0 -29
  302. package/dist/components/effects/Spotlight/index.d.ts +0 -2
  303. package/dist/components/effects/SpotlightBorder/SpotlightBorder.d.ts +0 -18
  304. package/dist/components/effects/SpotlightBorder/SpotlightBorder.js +0 -213
  305. package/dist/components/effects/SpotlightBorder/SpotlightBorder.types.d.ts +0 -61
  306. package/dist/components/effects/SpotlightBorder/index.d.ts +0 -2
  307. package/dist/components/effects/StickyScroll/StickyScroll.d.ts +0 -30
  308. package/dist/components/effects/StickyScroll/StickyScroll.js +0 -128
  309. package/dist/components/effects/StickyScroll/StickyScroll.types.d.ts +0 -19
  310. package/dist/components/effects/StickyScroll/index.d.ts +0 -2
  311. package/dist/components/forms/CronInput/CronInput.d.ts +0 -3
  312. package/dist/components/forms/CronInput/CronInput.js +0 -113
  313. package/dist/components/forms/CronInput/CronInput.theme.d.ts +0 -6
  314. package/dist/components/forms/CronInput/CronInput.theme.js +0 -75
  315. package/dist/components/forms/CronInput/CronInput.types.d.ts +0 -109
  316. package/dist/components/forms/CronInput/CronInput.utils.d.ts +0 -67
  317. package/dist/components/forms/CronInput/CronInput.utils.js +0 -505
  318. package/dist/components/forms/CronInput/index.d.ts +0 -4
  319. /package/dist/components/effects/{SpotlightBorder/SpotlightBorder.types.js → TiltCard/TiltCard.types.js} +0 -0
@@ -1,9 +1,10 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { useRef, useState, useId, useEffect, useMemo, useCallback } from 'react';
3
- import { motion } from 'motion/react';
2
+ import { useRef, useId, useMemo, useState, useCallback, useEffect } from 'react';
3
+ import { useReducedMotion, motion } from 'motion/react';
4
4
  import { cn } from '../../../utils/cn.js';
5
5
  import { useTooltipPosition } from '../hooks/useTooltipPosition.js';
6
6
  import { useChartAccessibility } from '../hooks/useChartAccessibility.js';
7
+ import { useChartDimensions } from '../hooks/useChartDimensions.js';
7
8
  import { XAxis } from '../shared/ChartAxis/XAxis.js';
8
9
  import { YAxis } from '../shared/ChartAxis/YAxis.js';
9
10
  import { HorizontalGrid } from '../shared/ChartGrid/HorizontalGrid.js';
@@ -13,6 +14,7 @@ import { ChartCrosshair } from '../shared/ChartCrosshair/ChartCrosshair.js';
13
14
  import { generateNiceTicks } from '../utils/chart-validation.js';
14
15
  import { generateCurvePath } from '../utils/path-utils.js';
15
16
  import { LINE_CHART_DEFAULTS } from './LineChart.types.js';
17
+ import { X_AXIS_MARGIN } from '../types/chart.types.js';
16
18
 
17
19
  // Production-ready color system with CORRECT CSS variable syntax
18
20
  const getSeriesColorClass = (index) => {
@@ -25,7 +27,19 @@ const getSeriesColorClass = (index) => {
25
27
  return colors[index % colors.length];
26
28
  };
27
29
  // Get color value for SVG elements and tooltips
28
- const getSeriesFillColor = (index) => {
30
+ const getSeriesFillColor = (index, key, config) => {
31
+ var _a;
32
+ if (key && config && ((_a = config[key]) === null || _a === void 0 ? void 0 : _a.color)) {
33
+ const customColor = config[key].color;
34
+ if (!customColor.startsWith("var(") &&
35
+ !customColor.startsWith("#") &&
36
+ !customColor.startsWith("rgb") &&
37
+ !customColor.startsWith("hsl") &&
38
+ customColor.includes("-")) {
39
+ return `var(--color-${customColor})`;
40
+ }
41
+ return customColor;
42
+ }
29
43
  const colorVars = [
30
44
  "var(--color-primary)",
31
45
  "var(--color-warning)",
@@ -43,7 +57,7 @@ color = LINE_CHART_DEFAULTS.color,
43
57
  dotRadius, radius, // @deprecated Use dotRadius instead
44
58
  strokeWidth = LINE_CHART_DEFAULTS.strokeWidth, curved = LINE_CHART_DEFAULTS.curved, curveType = LINE_CHART_DEFAULTS.curveType, showDots = LINE_CHART_DEFAULTS.showDots,
45
59
  // Base props
46
- className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.enableKeyboardNavigation, children, ...props }) => {
60
+ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.enableKeyboardNavigation, width, height, children, ...props }) => {
47
61
  var _a;
48
62
  // Resolve dotRadius with backward compatibility
49
63
  const resolvedDotRadius = (_a = dotRadius !== null && dotRadius !== void 0 ? dotRadius : radius) !== null && _a !== void 0 ? _a : LINE_CHART_DEFAULTS.dotRadius;
@@ -54,12 +68,21 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
54
68
  }
55
69
  // Simplified color system - no complex theme hook needed
56
70
  const containerRef = useRef(null);
57
- const [dimensions, setDimensions] = useState({ width: 600, height: 400 });
58
- const revealClipId = useId();
71
+ // `measured` gates the rise + dots so motion captures the baseline scaleY
72
+ // origin and dot positions at the real size, not the 600×400 fallback.
73
+ const { dimensions, measured } = useChartDimensions(containerRef);
59
74
  const shadowFilterId = useId();
60
75
  const verticalFadeId = useId();
61
76
  const horizontalFadeId = useId();
62
77
  const ANIMATION_DURATION = 1.5;
78
+ // Entrance: the line RISES from the x-axis (scaleY 0→1 about the baseline),
79
+ // mirroring how BarChart's bars grow up from the zero line. A single
80
+ // continuous path can't morph between datasets of different point counts, so
81
+ // it rises rather than draws. Keying the line group on the data signature
82
+ // replays the rise on every range switch; reduced-motion users get a stable
83
+ // key + scaleY:1 (no animation).
84
+ const shouldReduceMotion = useReducedMotion();
85
+ const dataSignature = useMemo(() => JSON.stringify(data), [data]);
63
86
  const [hoveredPoint, setHoveredPoint] = useState(null);
64
87
  // Detect if device is mobile/touch
65
88
  const isMobile = typeof window !== "undefined" &&
@@ -78,26 +101,6 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
78
101
  description,
79
102
  enableKeyboardNavigation,
80
103
  });
81
- // Measure container dimensions
82
- useEffect(() => {
83
- const updateDimensions = () => {
84
- if (containerRef.current) {
85
- const { width, height } = containerRef.current.getBoundingClientRect();
86
- setDimensions({
87
- width: width || 600,
88
- height: height || 400,
89
- });
90
- }
91
- };
92
- updateDimensions();
93
- const resizeObserver = new ResizeObserver(updateDimensions);
94
- if (containerRef.current) {
95
- resizeObserver.observe(containerRef.current);
96
- }
97
- return () => {
98
- resizeObserver.disconnect();
99
- };
100
- }, []);
101
104
  // Early return if no data
102
105
  if (!data || data.length === 0) {
103
106
  return (jsx("div", { className: cn("chart-container flex items-center justify-center text-[var(--color-text-placeholder)]", className), role: "img", "aria-label": "Empty line chart", ...props, children: jsx("span", { children: "No data available" }) }));
@@ -106,7 +109,7 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
106
109
  const margin = useMemo(() => ({
107
110
  top: 0,
108
111
  right: 0,
109
- bottom: showXAxis ? 40 : 0, // Reduce bottom margin when X-axis is hidden
112
+ bottom: showXAxis ? X_AXIS_MARGIN : 0, // shared X-axis margin so baselines align across chart types
110
113
  left: showYAxis ? 60 : 0, // Reduce left margin when Y-axis is hidden
111
114
  }), [showXAxis, showYAxis]);
112
115
  const innerWidth = dimensions.width - margin.left - margin.right;
@@ -189,7 +192,7 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
189
192
  key: seriesKey,
190
193
  label: ((_a = config[seriesKey]) === null || _a === void 0 ? void 0 : _a.label) || seriesKey,
191
194
  value: numValue,
192
- color: ((_b = config[seriesKey]) === null || _b === void 0 ? void 0 : _b.color) || getSeriesFillColor(keyIndex),
195
+ color: ((_b = config[seriesKey]) === null || _b === void 0 ? void 0 : _b.color) || getSeriesFillColor(keyIndex, seriesKey, config),
193
196
  };
194
197
  });
195
198
  const content = {
@@ -231,14 +234,15 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
231
234
  handleMouseEnter,
232
235
  handleMouseLeave,
233
236
  ]);
234
- return (jsxs("div", { ref: containerRef, className: cn("chart-container w-full h-full", className), ...chartAccessibilityProps, onMouseEnter: handleMouseInteraction, onMouseMove: handleMouseInteraction, ...props, children: [descriptionProps && jsx("div", { ...descriptionProps }), jsxs("svg", { width: "100%", height: "100%", viewBox: `0 0 ${dimensions.width} ${dimensions.height}`, className: "overflow-visible", role: "presentation", children: [jsxs("defs", { children: [jsx("filter", { id: shadowFilterId, x: "-20%", y: "-20%", width: "140%", height: "140%", children: jsx("feDropShadow", { dx: "8", dy: "8", stdDeviation: "8", floodOpacity: "0.15", floodColor: "#000000" }) }), jsxs("linearGradient", { id: verticalFadeId, x1: "0%", y1: "0%", x2: "0%", y2: "100%", children: [jsx("stop", { offset: "0%", stopColor: "#6b7280", stopOpacity: "0" }), jsx("stop", { offset: "40%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "50%", stopColor: "#6b7280", stopOpacity: "0.5" }), jsx("stop", { offset: "60%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "100%", stopColor: "#6b7280", stopOpacity: "0" })] }), jsxs("linearGradient", { id: horizontalFadeId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [jsx("stop", { offset: "0%", stopColor: "#6b7280", stopOpacity: "0" }), jsx("stop", { offset: "40%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "50%", stopColor: "#6b7280", stopOpacity: "0.5" }), jsx("stop", { offset: "60%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "100%", stopColor: "#6b7280", stopOpacity: "0" })] }), jsx("clipPath", { id: revealClipId, children: jsx(motion.rect, { initial: { width: 0, x: margin.left, y: margin.top }, animate: {
235
- width: innerWidth + margin.right,
236
- x: margin.left,
237
- y: margin.top,
238
- }, height: innerHeight, transition: {
239
- duration: ANIMATION_DURATION,
240
- ease: "easeOut",
241
- } }) })] }), jsx(HorizontalGrid, { show: showGrid, x: margin.left, y: margin.top, width: innerWidth, height: innerHeight, lineCount: 5 }), jsx(ChartCrosshair, { show: hoveredPoint !== null, x: hoveredPoint !== null
237
+ return (jsxs("div", { ref: containerRef, className: cn("chart-container w-full h-full", className), style: {
238
+ width: width !== undefined ? (typeof width === "number" ? `${width}px` : width) : undefined,
239
+ height: height !== undefined ? (typeof height === "number" ? `${height}px` : height) : undefined,
240
+ }, ...chartAccessibilityProps, onMouseEnter: handleMouseInteraction, onMouseMove: handleMouseInteraction, onMouseLeave: () => {
241
+ // Clear the crosshair + glow marker when the pointer leaves the chart.
242
+ // The per-point rects only hide the tooltip; nothing else resets this.
243
+ setHoveredPoint(null);
244
+ handleMouseLeave();
245
+ }, ...props, children: [descriptionProps && jsx("div", { ...descriptionProps }), jsxs("svg", { width: "100%", height: "100%", viewBox: `0 0 ${dimensions.width} ${dimensions.height}`, className: "overflow-visible", role: "presentation", children: [jsxs("defs", { children: [jsx("filter", { id: shadowFilterId, x: "-20%", y: "-20%", width: "140%", height: "140%", children: jsx("feDropShadow", { dx: "8", dy: "8", stdDeviation: "8", floodOpacity: "0.15", floodColor: "#000000" }) }), jsxs("linearGradient", { id: verticalFadeId, x1: "0%", y1: "0%", x2: "0%", y2: "100%", children: [jsx("stop", { offset: "0%", stopColor: "#6b7280", stopOpacity: "0" }), jsx("stop", { offset: "40%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "50%", stopColor: "#6b7280", stopOpacity: "0.5" }), jsx("stop", { offset: "60%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "100%", stopColor: "#6b7280", stopOpacity: "0" })] }), jsxs("linearGradient", { id: horizontalFadeId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [jsx("stop", { offset: "0%", stopColor: "#6b7280", stopOpacity: "0" }), jsx("stop", { offset: "40%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "50%", stopColor: "#6b7280", stopOpacity: "0.5" }), jsx("stop", { offset: "60%", stopColor: "#6b7280", stopOpacity: "0.3" }), jsx("stop", { offset: "100%", stopColor: "#6b7280", stopOpacity: "0" })] })] }), jsx(HorizontalGrid, { show: showGrid, x: margin.left, y: margin.top, width: innerWidth, height: innerHeight, lineCount: 5 }), jsx(ChartCrosshair, { show: hoveredPoint !== null, x: hoveredPoint !== null
242
246
  ? data.length === 1
243
247
  ? margin.left + innerWidth / 2
244
248
  : margin.left +
@@ -258,40 +262,52 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
258
262
  if (Math.abs(value) >= 1000)
259
263
  return `${(value / 1000).toFixed(0)}k`;
260
264
  return value.toString();
261
- } }), minValue < 0 && maxValue > 0 && (jsx("line", { x1: margin.left, y1: margin.top + innerHeight - ((0 - minValue) / (maxValue - minValue)) * innerHeight, x2: margin.left + innerWidth, y2: margin.top + innerHeight - ((0 - minValue) / (maxValue - minValue)) * innerHeight, className: "stroke-[var(--color-text-secondary)]", strokeWidth: 1, opacity: 0.6 })), jsx("g", { className: "chart-lines", children: dataKeys.map((key, keyIndex) => {
262
- const targetPath = allPaths[key];
263
- const colorClass = getSeriesColorClass(keyIndex);
264
- return (jsxs("g", { clipPath: `url(#${revealClipId})`, children: [jsx("path", { d: targetPath, fill: "none", strokeWidth: strokeWidth, strokeLinecap: "round", className: cn("transition-all duration-200", colorClass), filter: `url(#${shadowFilterId})` }), showDots &&
265
- data.map((item, dataIndex) => {
266
- const rawValue = item[key];
267
- const isNull = rawValue === null || rawValue === undefined;
268
- const value = isNull
269
- ? 0
270
- : typeof rawValue === "number"
271
- ? rawValue
272
- : 0;
273
- // Don't render dots for null values
274
- if (isNull)
275
- return null;
276
- const { x, y } = getPointPosition(dataIndex, value);
277
- const isFocused = isKeyboardMode && focusedElementIndex === dataIndex;
278
- return (jsx(motion.g, { initial: { opacity: 0, scale: 0 }, animate: { opacity: 1, scale: 1 }, transition: {
279
- // Sync with the line reveal: calculate when the line reaches this point
280
- delay: (dataIndex / (data.length - 1)) *
281
- ANIMATION_DURATION,
282
- type: "spring",
283
- stiffness: 260,
284
- damping: 20,
285
- }, style: {
286
- originX: "50%",
287
- originY: "50%",
288
- transformBox: "fill-box",
289
- }, children: jsx(ChartMarker, { cx: x, cy: y, radius: isFocused
290
- ? resolvedDotRadius + 2
291
- : resolvedDotRadius, colorClass: cn(colorClass, isFocused &&
292
- "stroke-[var(--color-primary-600)] stroke-2") }) }, `${key}-${dataIndex}`));
293
- })] }, key));
294
- }) }), !showDots && hoveredPoint !== null && (jsx("g", { className: "chart-hover-markers", children: dataKeys.map((key, keyIndex) => {
265
+ } }), minValue < 0 && maxValue > 0 && (jsx("line", { x1: margin.left, y1: margin.top + innerHeight - ((0 - minValue) / (maxValue - minValue)) * innerHeight, x2: margin.left + innerWidth, y2: margin.top + innerHeight - ((0 - minValue) / (maxValue - minValue)) * innerHeight, className: "stroke-[var(--color-text-secondary)]", strokeWidth: 1, opacity: 0.6 })), jsx("g", { className: "chart-lines", children: measured &&
266
+ dataKeys.map((key, keyIndex) => {
267
+ var _a;
268
+ const targetPath = allPaths[key];
269
+ const colorClass = getSeriesColorClass(keyIndex);
270
+ return (jsxs("g", { children: [jsxs(motion.g, { initial: { scaleY: shouldReduceMotion ? 1 : 0 }, animate: { scaleY: 1 }, transition: { duration: ANIMATION_DURATION, ease: "easeOut" },
271
+ // Rise from the x-axis like the bars. Framer forces
272
+ // transform-box:fill-box for SVG, so `originY:1` anchors scaleY
273
+ // to the group's fill-box BOTTOM. The invisible rect pins that
274
+ // bottom to the plot baseline (a bare line's bbox stops at its
275
+ // lowest point), so the line grows UP from the x-axis.
276
+ style: { originY: 1, transformOrigin: "bottom" }, children: [jsx("rect", { x: margin.left, y: margin.top, width: innerWidth, height: innerHeight, fill: "none", stroke: "none", style: { pointerEvents: "none" } }), jsx("path", { d: targetPath, fill: "none", strokeWidth: strokeWidth, strokeLinecap: "round",
277
+ // Constant stroke width through the scaleY rise (no squash).
278
+ vectorEffect: "non-scaling-stroke", className: cn("transition-all duration-200", colorClass), style: { stroke: (_a = config[key]) === null || _a === void 0 ? void 0 : _a.color }, filter: `url(#${shadowFilterId})` })] }, shouldReduceMotion ? "line-static" : dataSignature), showDots &&
279
+ data.map((item, dataIndex) => {
280
+ var _a;
281
+ const rawValue = item[key];
282
+ const isNull = rawValue === null || rawValue === undefined;
283
+ const value = isNull
284
+ ? 0
285
+ : typeof rawValue === "number"
286
+ ? rawValue
287
+ : 0;
288
+ // Don't render dots for null values
289
+ if (isNull)
290
+ return null;
291
+ const { x, y } = getPointPosition(dataIndex, value);
292
+ const isFocused = isKeyboardMode && focusedElementIndex === dataIndex;
293
+ return (jsx(motion.g, { initial: { opacity: 0, scale: 0 }, animate: { opacity: 1, scale: 1 }, transition: {
294
+ // Markers pop in one-by-one (left-to-right) only AFTER the
295
+ // line has fully risen — start the stagger at the rise's end.
296
+ delay: shouldReduceMotion ? 0 : ANIMATION_DURATION + dataIndex * 0.06,
297
+ type: "spring",
298
+ stiffness: 260,
299
+ damping: 20,
300
+ }, style: {
301
+ originX: "50%",
302
+ originY: "50%",
303
+ transformBox: "fill-box",
304
+ }, children: jsx(ChartMarker, { cx: x, cy: y, radius: isFocused
305
+ ? resolvedDotRadius + 2
306
+ : resolvedDotRadius, colorClass: cn(colorClass, isFocused &&
307
+ "stroke-[var(--color-primary-600)] stroke-2"), strokeColor: (_a = config[key]) === null || _a === void 0 ? void 0 : _a.color }) }, `${key}-${dataIndex}${shouldReduceMotion ? "" : `-${dataSignature}`}`));
308
+ })] }, key));
309
+ }) }), !showDots && hoveredPoint !== null && (jsx("g", { className: "chart-hover-markers", children: dataKeys.map((key, keyIndex) => {
310
+ var _a;
295
311
  const item = data[hoveredPoint.index];
296
312
  const rawValue = item[key];
297
313
  const isNull = rawValue === null || rawValue === undefined;
@@ -305,7 +321,7 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
305
321
  return null;
306
322
  const { x, y } = getPointPosition(hoveredPoint.index, value);
307
323
  const colorClass = getSeriesColorClass(keyIndex);
308
- return (jsx(ChartMarker, { cx: x, cy: y, radius: resolvedDotRadius, colorClass: colorClass }, `hover-${key}-${hoveredPoint.index}`));
324
+ return (jsx(ChartMarker, { cx: x, cy: y, radius: resolvedDotRadius, colorClass: colorClass, strokeColor: (_a = config[key]) === null || _a === void 0 ? void 0 : _a.color }, `hover-${key}-${hoveredPoint.index}`));
309
325
  }) })), jsx("g", { className: "chart-hover-areas", children: data.map((item, dataIndex) => {
310
326
  // Calculate hover area based on new point positioning
311
327
  const pointX = data.length === 1
@@ -332,7 +348,7 @@ className, title, description, enableKeyboardNavigation = LINE_CHART_DEFAULTS.en
332
348
  label: ((_a = config[seriesKey]) === null || _a === void 0 ? void 0 : _a.label) || seriesKey,
333
349
  value: numValue,
334
350
  color: ((_b = config[seriesKey]) === null || _b === void 0 ? void 0 : _b.color) ||
335
- getSeriesFillColor(keyIndex),
351
+ getSeriesFillColor(keyIndex, seriesKey, config),
336
352
  };
337
353
  });
338
354
  const content = {
@@ -11,12 +11,12 @@ export interface LineChartProps extends BaseChartProps, Omit<StandardChartDispla
11
11
  }
12
12
  export declare const LINE_CHART_DEFAULTS: {
13
13
  readonly color: undefined;
14
- readonly dotRadius: 4;
15
- readonly radius: 4;
14
+ readonly dotRadius: 3;
15
+ readonly radius: 3;
16
16
  readonly strokeWidth: 2;
17
17
  readonly curved: true;
18
18
  readonly curveType: import("..").CurveType;
19
- readonly showDots: true;
19
+ readonly showDots: false;
20
20
  readonly showGrid: true;
21
21
  readonly showXAxis: true;
22
22
  readonly showYAxis: true;
@@ -134,7 +134,7 @@ const RadarChart = ({ axes, series, size = 400, gridLevels = 5, maxValue: maxVal
134
134
  }, [showTooltip, buildTooltipContent, handleMouseEnter]);
135
135
  /* ----------------------------- Animation ----------------------------- */
136
136
  const shouldAnimate = showAnimation && !shouldReduceMotion;
137
- return (jsxs("div", { ref: containerRef, className: cn(theme.baseStyle, className), role: "img", "aria-label": `Radar chart comparing ${series.map((s) => s.label).join(", ")} across ${axes.join(", ")}`, ...props, children: [jsxs("svg", { viewBox: `0 0 ${size} ${size}`, width: size, height: size, className: "overflow-visible", children: [gridRings.map((points, idx) => (jsx("polygon", { points: points, fill: "none", stroke: theme.gridColor, strokeWidth: 1 }, `grid-${idx}`))), spokes.map((spoke, idx) => (jsx("line", { x1: spoke.x1, y1: spoke.y1, x2: spoke.x2, y2: spoke.y2, stroke: theme.axisColor, strokeWidth: 1 }, `spoke-${idx}`))), polygons.map((poly, idx) => shouldAnimate ? (jsx(motion.polygon, { points: poly.points, fill: poly.color, fillOpacity: fillOpacity, stroke: poly.color, strokeWidth: strokeWidth, strokeLinejoin: "round", initial: { opacity: 0, scale: 0 }, animate: { opacity: 1, scale: 1 }, transition: getSpringAnimation(RADAR_CHART_ANIMATIONS.preset, shouldReduceMotion, RADAR_CHART_ANIMATIONS.initialDelay +
137
+ return (jsxs("div", { ref: containerRef, className: cn(theme.baseStyle, className), role: "img", "aria-label": `Radar chart comparing ${series.map((s) => s.label).join(", ")} across ${axes.join(", ")}`, ...props, children: [jsxs("svg", { viewBox: `0 0 ${size} ${size}`, width: size, height: size, className: "overflow-visible", children: [gridRings.map((points, idx) => (jsx("polygon", { points: points, fill: "none", stroke: themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.gridColor, className: cn(!(themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.gridColor) && "stroke-[var(--color-border)]"), strokeWidth: 1 }, `grid-${idx}`))), spokes.map((spoke, idx) => (jsx("line", { x1: spoke.x1, y1: spoke.y1, x2: spoke.x2, y2: spoke.y2, stroke: themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.axisColor, className: cn(!(themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.axisColor) && "stroke-[var(--color-border-secondary)]"), strokeWidth: 1 }, `spoke-${idx}`))), polygons.map((poly, idx) => shouldAnimate ? (jsx(motion.polygon, { points: poly.points, fill: poly.color, fillOpacity: fillOpacity, stroke: poly.color, strokeWidth: strokeWidth, strokeLinejoin: "round", initial: { opacity: 0, scale: 0 }, animate: { opacity: 1, scale: 1 }, transition: getSpringAnimation(RADAR_CHART_ANIMATIONS.preset, shouldReduceMotion, RADAR_CHART_ANIMATIONS.initialDelay +
138
138
  getStaggerDelay(idx, RADAR_CHART_ANIMATIONS.seriesStagger)), style: { transformOrigin: `${cx}px ${cy}px` } }, `series-${idx}`)) : (jsx("polygon", { points: poly.points, fill: poly.color, fillOpacity: fillOpacity, stroke: poly.color, strokeWidth: strokeWidth, strokeLinejoin: "round" }, `series-${idx}`))), series.map((s, sIdx) => s.data.map((v, dIdx) => {
139
139
  const ratio = maxValue > 0 ? Math.min(v, maxValue) / maxValue : 0;
140
140
  const r = ratio * chartRadius;
@@ -8,9 +8,12 @@
8
8
  const radarChartTheme = {
9
9
  // Outer wrapper
10
10
  baseStyle: "flex flex-col items-center gap-4",
11
- // Grid ring stroke color (gray-200 equivalent)
11
+ // Grid ring / axis spoke colors are drawn from the dark-mode-aware
12
+ // `--color-border` / `--color-border-secondary` tokens in the component
13
+ // (applied via className so the CSS variable resolves). These hex values are
14
+ // only the fallback used when a consumer overrides `theme.gridColor` /
15
+ // `theme.axisColor` — they are NOT the rendered default.
12
16
  gridColor: "#e5e7eb",
13
- // Axis spoke stroke color (gray-300 equivalent)
14
17
  axisColor: "#d1d5db",
15
18
  // Axis label classes (applied to <text> elements via className)
16
19
  labelStyle: "text-xs fill-[#6b7280] select-none",
@@ -1,9 +1,10 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { useRef, useState, useEffect, useMemo, useCallback } from 'react';
2
+ import { useRef, useMemo, useCallback } from 'react';
3
3
  import { motion } from 'motion/react';
4
4
  import { cn } from '../../../utils/cn.js';
5
5
  import { useTooltipPosition } from '../hooks/useTooltipPosition.js';
6
6
  import { useChartAccessibility } from '../hooks/useChartAccessibility.js';
7
+ import { useChartDimensions } from '../hooks/useChartDimensions.js';
7
8
  import { XAxis } from '../shared/ChartAxis/XAxis.js';
8
9
  import { YAxis } from '../shared/ChartAxis/YAxis.js';
9
10
  import { ChartTooltip } from '../shared/ChartTooltip/ChartTooltip.js';
@@ -17,37 +18,17 @@ import { getCategoryColor, scatterPlotTheme } from './ScatterPlot.theme.js';
17
18
  * Now uses shared axis components with tick marks and value labels like other charts.
18
19
  */
19
20
  const ScatterPlot = ({ data, xLabel, yLabel, dotRadius: propDotRadius, pointSize, // @deprecated
20
- showGrid = SCATTER_PLOT_DEFAULTS.showGrid, showXAxis = SCATTER_PLOT_DEFAULTS.showXAxis, showYAxis = SCATTER_PLOT_DEFAULTS.showYAxis, showTooltip = SCATTER_PLOT_DEFAULTS.showTooltip, colors, minValue: propMinValue, maxValue: propMaxValue, theme: themeOverrides, className, svgClassName, dotClassName, gridClassName, axisClassName, title, description, enableKeyboardNavigation = SCATTER_PLOT_DEFAULTS.enableKeyboardNavigation, ...props }) => {
21
+ showGrid = SCATTER_PLOT_DEFAULTS.showGrid, showXAxis = SCATTER_PLOT_DEFAULTS.showXAxis, showYAxis = SCATTER_PLOT_DEFAULTS.showYAxis, showTooltip = SCATTER_PLOT_DEFAULTS.showTooltip, colors, minValue: propMinValue, maxValue: propMaxValue, theme: themeOverrides, className, svgClassName, dotClassName, gridClassName, axisClassName, title, description, enableKeyboardNavigation = SCATTER_PLOT_DEFAULTS.enableKeyboardNavigation, width, height, ...props }) => {
21
22
  var _a;
22
23
  const theme = { ...scatterPlotTheme, ...(themeOverrides || {}) };
23
24
  const chartColors = colors || theme.colors || scatterPlotTheme.colors;
24
25
  // Use dotRadius, fallback to pointSize for backward compatibility
25
26
  const dotRadiusValue = (_a = propDotRadius !== null && propDotRadius !== void 0 ? propDotRadius : pointSize) !== null && _a !== void 0 ? _a : SCATTER_PLOT_DEFAULTS.dotRadius;
26
- // Responsive container dimensions
27
+ // Responsive container dimensions. `measured` gates dot mount so motion
28
+ // captures scale-in geometry at real cx/cy, not the 600×400 fallback (dots
29
+ // would otherwise fly in from the wrong positions on cold load).
27
30
  const containerRef = useRef(null);
28
- const [dimensions, setDimensions] = useState({ width: 600, height: 400 });
29
- // Update dimensions on mount and resize
30
- useEffect(() => {
31
- if (!containerRef.current)
32
- return;
33
- const updateDimensions = () => {
34
- if (containerRef.current) {
35
- const rect = containerRef.current.getBoundingClientRect();
36
- setDimensions({
37
- width: rect.width || 600,
38
- height: rect.height || 400,
39
- });
40
- }
41
- };
42
- // Initial measurement
43
- updateDimensions();
44
- // Setup ResizeObserver
45
- const resizeObserver = new ResizeObserver(updateDimensions);
46
- resizeObserver.observe(containerRef.current);
47
- return () => {
48
- resizeObserver.disconnect();
49
- };
50
- }, []);
31
+ const { dimensions, measured } = useChartDimensions(containerRef);
51
32
  // Calculate ranges and categories
52
33
  const { xMin, xMax, yMin, yMax, categories, validData } = useMemo(() => {
53
34
  // Filter out invalid data points
@@ -155,53 +136,62 @@ showGrid = SCATTER_PLOT_DEFAULTS.showGrid, showXAxis = SCATTER_PLOT_DEFAULTS.sho
155
136
  }, [xMin, xMax]);
156
137
  // Return empty state if no data
157
138
  if (validData.length === 0) {
158
- return (jsx("div", { ref: containerRef, className: cn(theme.containerStyle, className), style: { minHeight: '400px' }, ...props, children: jsx("div", { className: theme.emptyStateStyle, children: data.length === 0 ? 'No data available' : 'No valid data points' }) }));
139
+ return (jsx("div", { ref: containerRef, className: cn(theme.containerStyle, className), style: {
140
+ minHeight: height === undefined ? '400px' : undefined,
141
+ width: width !== undefined ? (typeof width === "number" ? `${width}px` : width) : undefined,
142
+ height: height !== undefined ? (typeof height === "number" ? `${height}px` : height) : undefined,
143
+ }, ...props, children: jsx("div", { className: theme.emptyStateStyle, children: data.length === 0 ? 'No data available' : 'No valid data points' }) }));
159
144
  }
160
- return (jsxs("div", { ref: containerRef, className: cn(theme.containerStyle, className), style: { minHeight: '400px' }, ...chartAccessibilityProps, ...props, children: [jsxs("svg", { width: dimensions.width, height: dimensions.height, className: cn(theme.svgStyle, svgClassName), ...descriptionProps, children: [jsx(YAxis, { show: showYAxis, min: yMin, max: yMax, x: margin.left, y: margin.top, height: innerHeight, showGrid: showGrid, gridWidth: innerWidth, tickCount: 5, className: cn(axisClassName) }), validData.map((point, index) => {
161
- const cx = scaleX(point.x);
162
- const cy = scaleY(point.y);
163
- const size = point.size ? Math.sqrt(point.size) / 2 : dotRadiusValue;
164
- const pointColor = getColor(point.category);
165
- return (jsx(motion.circle, { cx: cx, cy: cy, r: size, fill: pointColor, className: cn(theme.dotStyle, dotClassName), strokeWidth: "0.5", initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, transition: { delay: index * 0.01, duration: 0.3 }, whileHover: { scale: 1.5, opacity: 1 }, onMouseEnter: (e) => {
166
- if (showTooltip) {
167
- const content = {
168
- category: point.label || point.category || `Point ${index + 1}`,
169
- series: [
170
- {
171
- key: 'x',
172
- label: xLabel || 'X',
173
- value: point.x.toFixed(2),
174
- color: pointColor,
175
- },
176
- {
177
- key: 'y',
178
- label: yLabel || 'Y',
179
- value: point.y.toFixed(2),
180
- color: pointColor,
181
- },
182
- ...(point.size
183
- ? [
184
- {
185
- key: 'size',
186
- label: 'Size',
187
- value: point.size.toFixed(2),
188
- color: pointColor,
189
- },
190
- ]
191
- : []),
192
- ],
193
- };
194
- // Pass SVG coordinates for proper positioning (especially in mobile/constrained containers)
195
- const svgCoordinates = isMobile ? {
196
- x: cx,
197
- y: cy,
198
- dimensions
199
- } : undefined;
200
- handleMouseEnter(e, content, svgCoordinates);
201
- }
202
- handleMouseInteraction();
203
- }, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave }, index));
204
- }), jsx(XAxis, { show: showXAxis, data: xAxisData, x: margin.left, y: margin.top + innerHeight, width: innerWidth, categoryWidth: innerWidth / (xAxisData.length - 1), categoryGap: 0, alignWithEdge: true, className: cn(axisClassName) }), xLabel && showXAxis && (jsx("text", { x: margin.left + innerWidth / 2, y: dimensions.height - 5, textAnchor: "middle", className: "text-sm fill-[var(--color-text-secondary)]", children: xLabel })), yLabel && showYAxis && (jsx("text", { x: 15, y: margin.top + innerHeight / 2, textAnchor: "middle", className: "text-sm fill-[var(--color-text-secondary)]", transform: `rotate(-90 15 ${margin.top + innerHeight / 2})`, children: yLabel }))] }), categories.length > 0 && (jsx("div", { className: theme.legendContainerStyle, children: categories.map((cat, index) => (jsxs("div", { className: theme.legendItemStyle, children: [jsx("div", { className: theme.legendDotStyle, style: { backgroundColor: getCategoryColor(chartColors, index) } }), jsx("span", { className: theme.legendLabelStyle, children: cat })] }, cat))) })), showTooltip && (jsx(ChartTooltip, { active: !!tooltipData, position: tooltipData ? { x: tooltipData.x, y: tooltipData.y } : { x: 0, y: 0 }, tooltipRef: tooltipRef, content: tooltipData === null || tooltipData === void 0 ? void 0 : tooltipData.content, chartType: "scatter" }))] }));
145
+ return (jsxs("div", { ref: containerRef, className: cn(theme.containerStyle, className), style: {
146
+ minHeight: height === undefined ? '400px' : undefined,
147
+ width: width !== undefined ? (typeof width === "number" ? `${width}px` : width) : undefined,
148
+ height: height !== undefined ? (typeof height === "number" ? `${height}px` : height) : undefined,
149
+ }, ...chartAccessibilityProps, ...props, children: [jsxs("svg", { width: dimensions.width, height: dimensions.height, className: cn(theme.svgStyle, svgClassName), ...descriptionProps, children: [jsx(YAxis, { show: showYAxis, min: yMin, max: yMax, x: margin.left, y: margin.top, height: innerHeight, showGrid: showGrid, gridWidth: innerWidth, tickCount: 5, className: cn(axisClassName) }), measured &&
150
+ validData.map((point, index) => {
151
+ const cx = scaleX(point.x);
152
+ const cy = scaleY(point.y);
153
+ const size = point.size ? Math.sqrt(point.size) / 2 : dotRadiusValue;
154
+ const pointColor = getColor(point.category);
155
+ return (jsx(motion.circle, { cx: cx, cy: cy, r: size, fill: pointColor, className: cn(theme.dotStyle, dotClassName), strokeWidth: "0.5", initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, transition: { delay: index * 0.01, duration: 0.3 }, whileHover: { scale: 1.5, opacity: 1 }, onMouseEnter: (e) => {
156
+ if (showTooltip) {
157
+ const content = {
158
+ category: point.label || point.category || `Point ${index + 1}`,
159
+ series: [
160
+ {
161
+ key: 'x',
162
+ label: xLabel || 'X',
163
+ value: point.x.toFixed(2),
164
+ color: pointColor,
165
+ },
166
+ {
167
+ key: 'y',
168
+ label: yLabel || 'Y',
169
+ value: point.y.toFixed(2),
170
+ color: pointColor,
171
+ },
172
+ ...(point.size
173
+ ? [
174
+ {
175
+ key: 'size',
176
+ label: 'Size',
177
+ value: point.size.toFixed(2),
178
+ color: pointColor,
179
+ },
180
+ ]
181
+ : []),
182
+ ],
183
+ };
184
+ // Pass SVG coordinates for proper positioning (especially in mobile/constrained containers)
185
+ const svgCoordinates = isMobile ? {
186
+ x: cx,
187
+ y: cy,
188
+ dimensions
189
+ } : undefined;
190
+ handleMouseEnter(e, content, svgCoordinates);
191
+ }
192
+ handleMouseInteraction();
193
+ }, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave }, index));
194
+ }), jsx(XAxis, { show: showXAxis, data: xAxisData, x: margin.left, y: margin.top + innerHeight, width: innerWidth, categoryWidth: innerWidth / (xAxisData.length - 1), categoryGap: 0, alignWithEdge: true, className: cn(axisClassName) }), xLabel && showXAxis && (jsx("text", { x: margin.left + innerWidth / 2, y: dimensions.height - 5, textAnchor: "middle", className: "text-sm fill-[var(--color-text-secondary)]", children: xLabel })), yLabel && showYAxis && (jsx("text", { x: 15, y: margin.top + innerHeight / 2, textAnchor: "middle", className: "text-sm fill-[var(--color-text-secondary)]", transform: `rotate(-90 15 ${margin.top + innerHeight / 2})`, children: yLabel }))] }), categories.length > 0 && (jsx("div", { className: theme.legendContainerStyle, children: categories.map((cat, index) => (jsxs("div", { className: theme.legendItemStyle, children: [jsx("div", { className: theme.legendDotStyle, style: { backgroundColor: getCategoryColor(chartColors, index) } }), jsx("span", { className: theme.legendLabelStyle, children: cat })] }, cat))) })), showTooltip && (jsx(ChartTooltip, { active: !!tooltipData, position: tooltipData ? { x: tooltipData.x, y: tooltipData.y } : { x: 0, y: 0 }, tooltipRef: tooltipRef, content: tooltipData === null || tooltipData === void 0 ? void 0 : tooltipData.content, chartType: "scatter" }))] }));
205
195
  };
206
196
  ScatterPlot.displayName = 'ScatterPlot';
207
197
 
@@ -32,7 +32,16 @@ const scatterPlotTheme = {
32
32
  * Get fill color for category (supports both CSS variables and direct colors)
33
33
  */
34
34
  function getCategoryColor(colors, categoryIndex) {
35
- return colors[categoryIndex % colors.length];
35
+ const color = colors[categoryIndex % colors.length];
36
+ if (color &&
37
+ !color.startsWith("var(") &&
38
+ !color.startsWith("#") &&
39
+ !color.startsWith("rgb") &&
40
+ !color.startsWith("hsl") &&
41
+ color.includes("-")) {
42
+ return `var(--color-${color})`;
43
+ }
44
+ return color;
36
45
  }
37
46
 
38
47
  export { getCategoryColor, scatterPlotTheme };
@@ -1,4 +1,4 @@
1
- import { StandardChartDisplayProps } from '../types/chart.types';
1
+ import { StandardChartDisplayProps, BaseChartProps } from '../types/chart.types';
2
2
  /**
3
3
  * Data point for ScatterPlot
4
4
  */
@@ -17,7 +17,7 @@ export interface ScatterPlotDataPoint {
17
17
  /**
18
18
  * ScatterPlot props - extends standardized chart props
19
19
  */
20
- export interface ScatterPlotProps extends StandardChartDisplayProps {
20
+ export interface ScatterPlotProps extends StandardChartDisplayProps, Omit<BaseChartProps, 'data' | 'config'> {
21
21
  /** Data points */
22
22
  data: ScatterPlotDataPoint[];
23
23
  /** X-axis label */
@@ -31,12 +31,6 @@ export interface ScatterPlotProps extends StandardChartDisplayProps {
31
31
  colors?: string[];
32
32
  /** Enable tooltip on hover */
33
33
  showTooltip?: boolean;
34
- /** Accessibility props */
35
- title?: string;
36
- description?: string;
37
- enableKeyboardNavigation?: boolean;
38
- /** Additional className */
39
- className?: string;
40
34
  /** className overrides for chart elements (shadcn approach) */
41
35
  svgClassName?: string;
42
36
  dotClassName?: string;
@@ -63,7 +57,7 @@ export declare const SCATTER_PLOT_DEFAULTS: {
63
57
  readonly curveType: import("..").CurveType;
64
58
  readonly fillOpacity: 0.3;
65
59
  readonly showStroke: true;
66
- readonly showDots: true;
60
+ readonly showDots: false;
67
61
  readonly orientation: "vertical" | "horizontal";
68
62
  readonly stacked: false;
69
63
  readonly variant: import("..").ChartVariant;