@solidports/recharts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/LICENSE +22 -0
  2. package/NOTICE +19 -0
  3. package/README.md +102 -0
  4. package/dist/dev.js +28564 -0
  5. package/dist/index.d.ts +7859 -0
  6. package/dist/index.js +28546 -0
  7. package/package.json +98 -0
  8. package/src/animation/AnimatedItems.tsx +183 -0
  9. package/src/animation/AnimationController.ts +33 -0
  10. package/src/animation/AnimationControllerImpl.ts +36 -0
  11. package/src/animation/AnimationHandle.ts +307 -0
  12. package/src/animation/CSSTransitionAnimate.tsx +170 -0
  13. package/src/animation/JavascriptAnimate.tsx +119 -0
  14. package/src/animation/easing.ts +221 -0
  15. package/src/animation/matchBy.ts +164 -0
  16. package/src/animation/timeoutController.ts +70 -0
  17. package/src/animation/useAnimationController.tsx +34 -0
  18. package/src/animation/useAnimationStartSnapshot.ts +118 -0
  19. package/src/animation/util.ts +41 -0
  20. package/src/cartesian/Area.tsx +915 -0
  21. package/src/cartesian/AreaRevealShape.tsx +190 -0
  22. package/src/cartesian/Bar.tsx +1369 -0
  23. package/src/cartesian/BarStack.tsx +152 -0
  24. package/src/cartesian/Brush.tsx +951 -0
  25. package/src/cartesian/CartesianAxis.tsx +722 -0
  26. package/src/cartesian/CartesianGrid.tsx +711 -0
  27. package/src/cartesian/ErrorBar.tsx +361 -0
  28. package/src/cartesian/Funnel.tsx +803 -0
  29. package/src/cartesian/GraphicalItemClipPath.tsx +67 -0
  30. package/src/cartesian/Line.tsx +863 -0
  31. package/src/cartesian/LineDrawShape.tsx +89 -0
  32. package/src/cartesian/ReferenceArea.tsx +331 -0
  33. package/src/cartesian/ReferenceDot.tsx +304 -0
  34. package/src/cartesian/ReferenceLine.tsx +474 -0
  35. package/src/cartesian/Scatter.tsx +888 -0
  36. package/src/cartesian/XAxis.tsx +433 -0
  37. package/src/cartesian/YAxis.tsx +443 -0
  38. package/src/cartesian/ZAxis.tsx +155 -0
  39. package/src/cartesian/cartesianPositionToCSSTranslate.tsx +29 -0
  40. package/src/cartesian/cartesianViewBoxToTrapezoid.tsx +21 -0
  41. package/src/cartesian/getCartesianPosition.tsx +267 -0
  42. package/src/cartesian/getEquidistantTicks.ts +144 -0
  43. package/src/cartesian/getTicks.ts +225 -0
  44. package/src/cartesian/isOutsidePosition.ts +15 -0
  45. package/src/cartesian/useAnimatedLineLength.ts +54 -0
  46. package/src/chart/AreaChart.tsx +29 -0
  47. package/src/chart/BarChart.tsx +29 -0
  48. package/src/chart/CartesianChart.tsx +131 -0
  49. package/src/chart/CategoricalChart.tsx +94 -0
  50. package/src/chart/ComposedChart.tsx +29 -0
  51. package/src/chart/FunnelChart.tsx +29 -0
  52. package/src/chart/LineChart.tsx +29 -0
  53. package/src/chart/PieChart.tsx +50 -0
  54. package/src/chart/PolarChart.tsx +164 -0
  55. package/src/chart/RadarChart.tsx +70 -0
  56. package/src/chart/RadialBarChart.tsx +46 -0
  57. package/src/chart/RechartsWrapper.tsx +551 -0
  58. package/src/chart/Sankey.tsx +1534 -0
  59. package/src/chart/ScatterChart.tsx +29 -0
  60. package/src/chart/SunburstChart.tsx +504 -0
  61. package/src/chart/Treemap.tsx +1223 -0
  62. package/src/chart/createInitialRootProps.ts +24 -0
  63. package/src/chart/types.ts +53 -0
  64. package/src/component/ActivePoints.tsx +144 -0
  65. package/src/component/Cell.tsx +37 -0
  66. package/src/component/Cursor.tsx +185 -0
  67. package/src/component/Customized.tsx +50 -0
  68. package/src/component/DefaultLegendContent.tsx +348 -0
  69. package/src/component/DefaultTooltipContent.tsx +224 -0
  70. package/src/component/Dots.tsx +157 -0
  71. package/src/component/Label.tsx +636 -0
  72. package/src/component/LabelList.tsx +375 -0
  73. package/src/component/Legend.tsx +512 -0
  74. package/src/component/ResponsiveContainer.tsx +348 -0
  75. package/src/component/Text.tsx +541 -0
  76. package/src/component/Tooltip.tsx +470 -0
  77. package/src/component/TooltipBoundingBox.tsx +146 -0
  78. package/src/component/responsiveContainerUtils.ts +134 -0
  79. package/src/container/ClipPathProvider.tsx +51 -0
  80. package/src/container/Layer.tsx +38 -0
  81. package/src/container/RootSurface.tsx +120 -0
  82. package/src/container/Surface.tsx +61 -0
  83. package/src/context/CellsContext.tsx +54 -0
  84. package/src/context/ErrorBarContext.tsx +146 -0
  85. package/src/context/GraphicalItemChildrenScope.tsx +18 -0
  86. package/src/context/PanoramaContext.tsx +9 -0
  87. package/src/context/RegisterGraphicalItemId.tsx +30 -0
  88. package/src/context/accessibilityContext.tsx +6 -0
  89. package/src/context/brushUpdateContext.tsx +9 -0
  90. package/src/context/chartDataContext.tsx +97 -0
  91. package/src/context/chartLayoutContext.tsx +201 -0
  92. package/src/context/legendPayloadContext.tsx +20 -0
  93. package/src/context/legendPortalContext.tsx +12 -0
  94. package/src/context/tooltipContext.tsx +89 -0
  95. package/src/context/tooltipPortalContext.tsx +12 -0
  96. package/src/context/useTooltipAxis.ts +22 -0
  97. package/src/hooks.ts +476 -0
  98. package/src/index.ts +280 -0
  99. package/src/polar/Pie.tsx +1360 -0
  100. package/src/polar/PolarAngleAxis.tsx +616 -0
  101. package/src/polar/PolarGrid.tsx +312 -0
  102. package/src/polar/PolarRadiusAxis.tsx +547 -0
  103. package/src/polar/Radar.tsx +734 -0
  104. package/src/polar/RadialBar.tsx +917 -0
  105. package/src/polar/defaultPolarAngleAxisProps.tsx +27 -0
  106. package/src/polar/defaultPolarRadiusAxisProps.tsx +25 -0
  107. package/src/shape/Cross.tsx +89 -0
  108. package/src/shape/Curve.tsx +343 -0
  109. package/src/shape/Dot.tsx +70 -0
  110. package/src/shape/Polygon.tsx +195 -0
  111. package/src/shape/Rectangle.tsx +470 -0
  112. package/src/shape/Sector.tsx +347 -0
  113. package/src/shape/Symbols.tsx +139 -0
  114. package/src/shape/Trapezoid.tsx +280 -0
  115. package/src/state/RechartsStateContext.tsx +12 -0
  116. package/src/state/RechartsStateProvider.tsx +87 -0
  117. package/src/state/RechartsStoreContext.tsx +25 -0
  118. package/src/state/RechartsStoreProvider.tsx +35 -0
  119. package/src/state/ReportChartProps.tsx +40 -0
  120. package/src/state/ReportEventSettings.tsx +30 -0
  121. package/src/state/ReportMainChartProps.tsx +61 -0
  122. package/src/state/ReportPolarOptions.tsx +35 -0
  123. package/src/state/SetGraphicalItem.ts +79 -0
  124. package/src/state/SetLegendPayload.ts +134 -0
  125. package/src/state/SetTooltipEntrySettings.tsx +72 -0
  126. package/src/state/actions.ts +464 -0
  127. package/src/state/brushSlice.ts +13 -0
  128. package/src/state/cartesianAxisSlice.ts +141 -0
  129. package/src/state/chartDataSlice.ts +50 -0
  130. package/src/state/chartState.ts +297 -0
  131. package/src/state/errorBarSlice.ts +29 -0
  132. package/src/state/eventSettingsSlice.ts +8 -0
  133. package/src/state/events.ts +76 -0
  134. package/src/state/externalEventsMiddleware.ts +255 -0
  135. package/src/state/graphicalItemsSlice.ts +74 -0
  136. package/src/state/hooks/useChartSelectors.tsx +45 -0
  137. package/src/state/keyboardEventsMiddleware.ts +228 -0
  138. package/src/state/layoutSlice.ts +21 -0
  139. package/src/state/legendSlice.ts +57 -0
  140. package/src/state/mouseEventsMiddleware.ts +185 -0
  141. package/src/state/optionsSlice.ts +47 -0
  142. package/src/state/polarAxisSlice.ts +10 -0
  143. package/src/state/polarOptionsSlice.ts +12 -0
  144. package/src/state/rawData.ts +26 -0
  145. package/src/state/referenceElementsSlice.ts +40 -0
  146. package/src/state/renderedTicksSlice.ts +15 -0
  147. package/src/state/rootPropsSlice.ts +47 -0
  148. package/src/state/selectors/areaSelectors.ts +240 -0
  149. package/src/state/selectors/arrayEqualityCheck.ts +29 -0
  150. package/src/state/selectors/axisSelectors.ts +2157 -0
  151. package/src/state/selectors/barSelectors.ts +310 -0
  152. package/src/state/selectors/barStackSelectors.ts +77 -0
  153. package/src/state/selectors/brushSelectors.ts +33 -0
  154. package/src/state/selectors/chartSelector.ts +185 -0
  155. package/src/state/selectors/combiners/combineActiveLabel.ts +16 -0
  156. package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +95 -0
  157. package/src/state/selectors/combiners/combineAllBarPositions.ts +122 -0
  158. package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +16 -0
  159. package/src/state/selectors/combiners/combineBarPosition.ts +23 -0
  160. package/src/state/selectors/combiners/combineBarSizeList.ts +80 -0
  161. package/src/state/selectors/combiners/combineCheckedDomain.ts +48 -0
  162. package/src/state/selectors/combiners/combineConfiguredScale.ts +111 -0
  163. package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +45 -0
  164. package/src/state/selectors/combiners/combineDisplayedStackedData.ts +50 -0
  165. package/src/state/selectors/combiners/combineInverseScaleFunction.ts +16 -0
  166. package/src/state/selectors/combiners/combineRealScaleType.ts +44 -0
  167. package/src/state/selectors/combiners/combineStackedData.ts +27 -0
  168. package/src/state/selectors/combiners/combineTooltipInteractionState.ts +86 -0
  169. package/src/state/selectors/combiners/combineTooltipPayload.ts +205 -0
  170. package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +58 -0
  171. package/src/state/selectors/containerSelectors.ts +12 -0
  172. package/src/state/selectors/dataSelectors.ts +88 -0
  173. package/src/state/selectors/funnelSelectors.ts +75 -0
  174. package/src/state/selectors/graphicalItemSelectors.ts +30 -0
  175. package/src/state/selectors/legendSelectors.ts +29 -0
  176. package/src/state/selectors/lineSelectors.ts +134 -0
  177. package/src/state/selectors/numberDomainEqualityCheck.ts +14 -0
  178. package/src/state/selectors/pickAxisId.ts +5 -0
  179. package/src/state/selectors/pickAxisType.ts +3 -0
  180. package/src/state/selectors/pieSelectors.ts +97 -0
  181. package/src/state/selectors/polarAxisSelectors.ts +201 -0
  182. package/src/state/selectors/polarGridSelectors.ts +28 -0
  183. package/src/state/selectors/polarScaleSelectors.ts +133 -0
  184. package/src/state/selectors/polarSelectors.ts +219 -0
  185. package/src/state/selectors/radarSelectors.ts +191 -0
  186. package/src/state/selectors/radialBarSelectors.ts +435 -0
  187. package/src/state/selectors/rootPropsSelectors.ts +25 -0
  188. package/src/state/selectors/scatterSelectors.ts +96 -0
  189. package/src/state/selectors/selectActivePropsFromChartPointer.ts +26 -0
  190. package/src/state/selectors/selectAllAxes.ts +17 -0
  191. package/src/state/selectors/selectChartOffset.ts +16 -0
  192. package/src/state/selectors/selectChartOffsetInternal.ts +136 -0
  193. package/src/state/selectors/selectLegendArea.ts +20 -0
  194. package/src/state/selectors/selectPlotArea.ts +22 -0
  195. package/src/state/selectors/selectTooltipAxisId.ts +7 -0
  196. package/src/state/selectors/selectTooltipAxisType.ts +32 -0
  197. package/src/state/selectors/selectTooltipEventType.ts +48 -0
  198. package/src/state/selectors/selectTooltipPayloadSearcher.ts +6 -0
  199. package/src/state/selectors/selectTooltipSettings.ts +39 -0
  200. package/src/state/selectors/selectTooltipState.ts +8 -0
  201. package/src/state/selectors/selectors.ts +271 -0
  202. package/src/state/selectors/tooltipSelectors.ts +578 -0
  203. package/src/state/selectors/touchSelectors.ts +31 -0
  204. package/src/state/store.ts +29 -0
  205. package/src/state/storeIdentity.ts +9 -0
  206. package/src/state/teardownWrite.ts +10 -0
  207. package/src/state/tooltipInteraction.ts +23 -0
  208. package/src/state/tooltipSlice.ts +334 -0
  209. package/src/state/touchEventsMiddleware.ts +214 -0
  210. package/src/state/types/AnimationSettings.ts +20 -0
  211. package/src/state/types/AreaSettings.ts +14 -0
  212. package/src/state/types/BarSettings.ts +15 -0
  213. package/src/state/types/LineSettings.ts +9 -0
  214. package/src/state/types/PieSettings.ts +34 -0
  215. package/src/state/types/RadarSettings.ts +5 -0
  216. package/src/state/types/RadialBarSettings.ts +10 -0
  217. package/src/state/types/ScatterSettings.ts +12 -0
  218. package/src/state/types/StackedGraphicalItem.ts +34 -0
  219. package/src/state/useChartState.ts +17 -0
  220. package/src/state/zIndexSlice.ts +39 -0
  221. package/src/synchronisation/syncSelectors.ts +7 -0
  222. package/src/synchronisation/types.ts +44 -0
  223. package/src/synchronisation/useChartSynchronisation.tsx +404 -0
  224. package/src/theme/RechartsTheme.ts +16 -0
  225. package/src/theme/RechartsThemeContext.ts +19 -0
  226. package/src/theme/darkTheme.ts +13 -0
  227. package/src/theme/graphicalItemIdentity.ts +70 -0
  228. package/src/theme/legacyTheme.ts +17 -0
  229. package/src/theme/lightTheme.ts +13 -0
  230. package/src/types.ts +54 -0
  231. package/src/util/ActiveShapeUtils.tsx +162 -0
  232. package/src/util/BarUtils.tsx +62 -0
  233. package/src/util/BarePortal.tsx +50 -0
  234. package/src/util/CamelCaseSVGAttrs.ts +34 -0
  235. package/src/util/CartesianUtils.ts +48 -0
  236. package/src/util/ChartUtils.ts +802 -0
  237. package/src/util/Constants.ts +42 -0
  238. package/src/util/CssPrefixUtils.ts +20 -0
  239. package/src/util/DOMUtils.ts +129 -0
  240. package/src/util/DataUtils.ts +216 -0
  241. package/src/util/Events.ts +16 -0
  242. package/src/util/FunnelUtils.tsx +15 -0
  243. package/src/util/Global.ts +12 -0
  244. package/src/util/IfOverflow.ts +15 -0
  245. package/src/util/LRUCache.ts +41 -0
  246. package/src/util/LogUtils.ts +22 -0
  247. package/src/util/PolarUtils.ts +132 -0
  248. package/src/util/RadialBarUtils.tsx +24 -0
  249. package/src/util/ReactUtils.ts +95 -0
  250. package/src/util/ReduceCSSCalc.ts +187 -0
  251. package/src/util/ScatterUtils.tsx +52 -0
  252. package/src/util/ShapeElementProps.tsx +87 -0
  253. package/src/util/TickUtils.ts +60 -0
  254. package/src/util/XAxisUtils.ts +48 -0
  255. package/src/util/YAxisUtils.ts +48 -0
  256. package/src/util/axisPropsAreEqual.ts +48 -0
  257. package/src/util/createCartesianCharts.tsx +150 -0
  258. package/src/util/createEventProxy.ts +20 -0
  259. package/src/util/createPolarCharts.tsx +112 -0
  260. package/src/util/cursor/getCursorPoints.ts +46 -0
  261. package/src/util/cursor/getCursorRectangle.ts +28 -0
  262. package/src/util/cursor/getRadialCursorPoints.ts +32 -0
  263. package/src/util/excludeEventProps.ts +171 -0
  264. package/src/util/getActiveCoordinate.ts +213 -0
  265. package/src/util/getAxisTypeBasedOnLayout.ts +21 -0
  266. package/src/util/getClassNameFromUnknown.ts +6 -0
  267. package/src/util/getEveryNth.ts +27 -0
  268. package/src/util/getRadiusAndStrokeWidthFromDot.ts +35 -0
  269. package/src/util/getRelativeCoordinate.ts +80 -0
  270. package/src/util/getSliced.ts +13 -0
  271. package/src/util/hoverDedupe.ts +41 -0
  272. package/src/util/isDomainSpecifiedByUser.ts +219 -0
  273. package/src/util/isWellBehavedNumber.ts +7 -0
  274. package/src/util/pathTotalLength.ts +25 -0
  275. package/src/util/payload/getUniqPayload.ts +28 -0
  276. package/src/util/propsAreEqual.ts +121 -0
  277. package/src/util/resolveDefaultProps.ts +161 -0
  278. package/src/util/round.ts +32 -0
  279. package/src/util/scale/CartesianScaleHelper.ts +72 -0
  280. package/src/util/scale/CustomScaleDefinition.ts +81 -0
  281. package/src/util/scale/RechartsScale.ts +130 -0
  282. package/src/util/scale/createCategoricalInverse.ts +72 -0
  283. package/src/util/scale/getNiceTickValues.ts +311 -0
  284. package/src/util/scale/index.ts +2 -0
  285. package/src/util/scale/util/arithmetic.ts +54 -0
  286. package/src/util/solid-1-compat.ts +310 -0
  287. package/src/util/solidJsxCamelAugment.d.ts +84 -0
  288. package/src/util/stacks/getStackSeriesIdentifier.ts +21 -0
  289. package/src/util/stacks/stackTypes.ts +60 -0
  290. package/src/util/structurallyEqual.ts +31 -0
  291. package/src/util/svgPropertiesAndEvents.ts +53 -0
  292. package/src/util/svgPropertiesNoEvents.ts +571 -0
  293. package/src/util/tooltip/translate.ts +171 -0
  294. package/src/util/typedDataKey.ts +48 -0
  295. package/src/util/types.ts +1560 -0
  296. package/src/util/useAnimationId.ts +31 -0
  297. package/src/util/useElementOffset.ts +110 -0
  298. package/src/util/useId.ts +8 -0
  299. package/src/util/usePrefersReducedMotion.ts +48 -0
  300. package/src/util/useReportScale.ts +24 -0
  301. package/src/util/useUniqueId.ts +30 -0
  302. package/src/zIndex/DefaultZIndexes.ts +84 -0
  303. package/src/zIndex/ZIndexLayer.tsx +121 -0
  304. package/src/zIndex/ZIndexPortal.tsx +79 -0
  305. package/src/zIndex/getZIndexFromUnknown.ts +14 -0
  306. package/src/zIndex/zIndexSelectors.ts +48 -0
@@ -0,0 +1,863 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import type { Formatter } from "../component/DefaultTooltipContent"
3
+ import { createMemo, createSignal, Show } from 'solid-js';
4
+ import type { JSX } from '@solidjs/web';
5
+ import { clsx } from "clsx"
6
+ import type { CurveType, Props as CurveProps } from "../shape/Curve"
7
+ import { Layer } from "../container/Layer"
8
+ import {
9
+ LabelListContextBridge,
10
+ CartesianLabelListContextProvider,
11
+ type CartesianLabelListEntry,
12
+ type ImplicitLabelListType,
13
+ LabelListFromLabelProp,
14
+ } from "../component/LabelList"
15
+ import { Dots } from "../component/Dots"
16
+ import type { ErrorBarDataItem, ErrorBarDataPointFormatter } from "./ErrorBar"
17
+ import { interpolate, isNullish, noop } from "../util/DataUtils"
18
+ import { isClipDot } from "../util/ReactUtils"
19
+ import { getCateCoordinateOfLine, getTooltipNameProp, getValueByDataKey } from "../util/ChartUtils"
20
+ import type {
21
+ ActiveDotType,
22
+ ActiveShape,
23
+ AnimationDuration,
24
+ AnimationTiming,
25
+ CartesianLayout,
26
+ DataConsumer,
27
+ DataKey,
28
+ DataProvider,
29
+ DotType,
30
+ LegendType,
31
+ TickItem,
32
+ TooltipType,
33
+ TrapezoidViewBox,
34
+ } from "../util/types"
35
+ import type { LegendPayload } from "../component/DefaultLegendContent"
36
+ import { ActivePoints } from "../component/ActivePoints"
37
+ import type { TooltipPayloadConfiguration } from "../state/tooltipSlice"
38
+ import { SetTooltipEntrySettings } from "../state/SetTooltipEntrySettings"
39
+ import { SetErrorBarContext } from "../context/ErrorBarContext"
40
+ import { GraphicalItemChildrenScope } from "../context/GraphicalItemChildrenScope"
41
+ import { GraphicalItemClipPath, useNeedsClip } from "./GraphicalItemClipPath"
42
+ import { useChartLayout } from "../context/chartLayoutContext"
43
+ import type { BaseAxisWithScale } from "../state/selectors/axisSelectors"
44
+ import { useIsPanorama } from "../context/PanoramaContext"
45
+ import { selectLinePoints } from "../state/selectors/lineSelectors"
46
+ import { useChartStore } from "../state/RechartsStoreContext"
47
+ import type { AxisId } from "../state/cartesianAxisSlice"
48
+ import { SetLegendPayload } from "../state/SetLegendPayload"
49
+ import { useAnimationId } from "../util/useAnimationId"
50
+ import { useAnimatedLineLength } from "./useAnimatedLineLength"
51
+ import { LineDrawShape } from "./LineDrawShape"
52
+ import { pathTotalLength } from "../util/pathTotalLength"
53
+ import type { LineDrawShapeProps } from "./LineDrawShape"
54
+ import { resolveDefaultProps } from "../util/resolveDefaultProps"
55
+ import { usePlotArea } from "../hooks"
56
+ import type { WithIdRequired } from "../util/useUniqueId"
57
+ import { RegisterGraphicalItemId } from "../context/RegisterGraphicalItemId"
58
+ import { SetCartesianGraphicalItem } from "../state/SetGraphicalItem"
59
+ import { svgPropertiesNoEvents } from "../util/svgPropertiesNoEvents"
60
+ import { AnimatedItems, useAnimationCallbacks } from "../animation/AnimatedItems"
61
+ import type { AnimationInterpolateFn } from "../animation/AnimatedItems"
62
+ import { matchByIndex } from "../animation/matchBy"
63
+ import type { AnimationItem, AnimationMatchByProp } from "../animation/matchBy"
64
+ import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
65
+ import { getRadiusAndStrokeWidthFromDot } from "../util/getRadiusAndStrokeWidthFromDot"
66
+ import { Shape } from "../util/ActiveShapeUtils"
67
+ import type { ZIndexable } from "../zIndex/ZIndexLayer"
68
+ import { ZIndexLayer } from "../zIndex/ZIndexLayer"
69
+ import { DefaultZIndexes } from "../zIndex/DefaultZIndexes"
70
+ import type { GraphicalItemId } from "../state/graphicalItemsSlice"
71
+ import type { ChartData } from "../state/chartDataSlice"
72
+
73
+ import { mergeProps, splitProps } from '../util/solid-1-compat';
74
+ export interface LinePointItem {
75
+ readonly value: number
76
+ readonly payload?: unknown
77
+ /**
78
+ * Line coordinates can have gaps in them. We have `connectNulls` prop that allows to connect those gaps anyway.
79
+ * What it means is that some points can have `null` x or y coordinates.
80
+ */
81
+ x: number | null
82
+ y: number | null
83
+ }
84
+
85
+ /**
86
+ * Internal props, combination of external props + defaultProps + private Recharts state
87
+ */
88
+ interface InternalLineProps extends ZIndexable {
89
+ activeDot: ActiveDotType
90
+ animateNewValues: boolean
91
+ animationBegin: number
92
+ animationDuration: AnimationDuration
93
+ animationEasing: AnimationTiming
94
+ animationInterpolateFn: AnimationInterpolateFn<LinePointItem, CartesianLayout>
95
+ animationMatchBy: AnimationMatchByProp<LinePointItem>
96
+
97
+ className?: string
98
+ connectNulls: boolean
99
+ data?: unknown
100
+ dataKey?: DataKey<unknown>
101
+ dot: DotType
102
+ height: number
103
+ hide: boolean
104
+ id: GraphicalItemId
105
+ isAnimationActive: boolean | "auto"
106
+ label: ImplicitLabelListType
107
+ layout: "horizontal" | "vertical"
108
+ left: number
109
+ legendType: LegendType
110
+ shape: ActiveShape<LineDrawShapeProps, SVGPathElement>
111
+
112
+ name?: string | number
113
+ needClip?: boolean
114
+
115
+ onAnimationEnd?: () => void
116
+ onAnimationStart?: () => void
117
+
118
+ points: ReadonlyArray<LinePointItem>
119
+ tooltipType?: TooltipType
120
+ formatter?: Formatter
121
+ top: number
122
+ type?: CurveType
123
+ unit?: string | number | null
124
+ width: number
125
+ xAxisId: AxisId
126
+ yAxisId: AxisId
127
+ children?: JSX.Element
128
+ }
129
+
130
+ /**
131
+ * External props, intended for end users to fill in
132
+ */
133
+ interface LineProps<DataPointType = unknown, DataValueType = unknown>
134
+ extends DataProvider<DataPointType>, DataConsumer<DataPointType, DataValueType>, ZIndexable {
135
+ /**
136
+ * The active dot is rendered on the closest data point when user interacts with the chart.
137
+ * @defaultValue true
138
+ */
139
+ activeDot?: ActiveDotType
140
+ /** @defaultValue true */
141
+ animateNewValues?: boolean
142
+ /** @defaultValue 0 */
143
+ animationBegin?: number
144
+ /** @defaultValue 1500 */
145
+ animationDuration?: AnimationDuration
146
+ /** @defaultValue ease */
147
+ animationEasing?: AnimationTiming
148
+ /**
149
+ * Custom animation function for interpolating data items.
150
+ * When provided, this replaces the default animation interpolation.
151
+ *
152
+ * @since 3.9
153
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
154
+ */
155
+ animationInterpolateFn?: AnimationInterpolateFn<LinePointItem, CartesianLayout>
156
+ /**
157
+ * Strategy for matching previous items to next items during animation.
158
+ *
159
+ * - `matchByIndex` (default): match by array position with proportional stretching
160
+ * - `matchAppend`: match sequentially by index and treat newly appended items as new
161
+ * - `matchByDataKey('someKey')`: match by a data key from the payload
162
+ * - Custom function `(item, index) => key`: match by the returned key
163
+ *
164
+ * @defaultValue index
165
+ */
166
+ animationMatchBy?: AnimationMatchByProp<LinePointItem>
167
+ className?: string
168
+ /** @defaultValue false */
169
+ connectNulls?: boolean
170
+ /** @defaultValue true */
171
+ dot?: DotType
172
+ /** @defaultValue false */
173
+ hide?: boolean
174
+ id?: string
175
+ /** @defaultValue auto */
176
+ isAnimationActive?: boolean | "auto"
177
+ /** @defaultValue false */
178
+ label?: ImplicitLabelListType
179
+ /** @defaultValue line */
180
+ legendType?: LegendType
181
+ /**
182
+ * The shape of the line. Defaults to `LineDrawShape`, which reveals the path via
183
+ * stroke-dasharray during the entrance animation.
184
+ * During animations, a function shape also receives `animationElapsedTime`,
185
+ * `isAnimating`, `isEntrance`, and `visibleLength`.
186
+ */
187
+ shape?: ActiveShape<LineDrawShapeProps, SVGPathElement>
188
+ name?: string | number
189
+ onAnimationEnd?: () => void
190
+ onAnimationStart?: () => void
191
+ tooltipType?: TooltipType
192
+ /**
193
+ * Formats the value displayed in the tooltip for this Line.
194
+ * When set, takes precedence over the `formatter` prop on the Tooltip component.
195
+ */
196
+ formatter?: Formatter
197
+ /** @defaultValue linear */
198
+ type?: CurveType
199
+ unit?: string | number | null
200
+ /** @defaultValue 0 */
201
+ xAxisId?: AxisId
202
+ /** @defaultValue 0 */
203
+ yAxisId?: AxisId
204
+ /** @defaultValue 400 */
205
+ zIndex?: number
206
+ /** @defaultValue #3182bd */
207
+ stroke?: string
208
+ /** @defaultValue 1 */
209
+ strokeWidth?: string | number
210
+ strokeDasharray?: string | number
211
+ children?: JSX.Element
212
+ }
213
+
214
+ /**
215
+ * Because of naming conflict, we are forced to ignore certain (valid) SVG attributes.
216
+ */
217
+ type LineSvgProps = Omit<CurveProps, "points" | "pathRef" | "ref" | "layout" | "baseLine">
218
+
219
+ type InternalProps = LineSvgProps & InternalLineProps
220
+
221
+ /* eslint-disable-next-line typescript-eslint/no-explicit-any -- upstream contract: untyped items accept any data */
222
+ export type Props<DataPointType = any, DataValueType = any> = LineSvgProps & LineProps<DataPointType, DataValueType>
223
+
224
+ /* eslint-disable solid/reactivity -- plain utility fn; Props parameter is not a Solid reactive proxy at this call site */
225
+ const computeLegendPayloadFromAreaData = (props: Props): ReadonlyArray<LegendPayload> => {
226
+ return [
227
+ {
228
+ color: props.stroke,
229
+ dataKey: props.dataKey,
230
+ inactive: props.hide,
231
+ payload: props,
232
+ type: props.legendType,
233
+ value: getTooltipNameProp(props.name, props.dataKey),
234
+ },
235
+ ]
236
+ }
237
+ /* eslint-enable solid/reactivity */
238
+
239
+ function SetLineTooltipEntrySettings(
240
+ props: Pick<
241
+ InternalProps,
242
+ | "dataKey"
243
+ | "data"
244
+ | "stroke"
245
+ | "strokeWidth"
246
+ | "fill"
247
+ | "name"
248
+ | "hide"
249
+ | "unit"
250
+ | "tooltipType"
251
+ | "formatter"
252
+ | "id"
253
+ >,
254
+ ) {
255
+ /* GOTCHA-005 (session 38): wrap in createMemo so reactive props flow into the
256
+ settings object — setup-time literal would freeze defaults at first render. */
257
+ const tooltipEntrySettings = createMemo<TooltipPayloadConfiguration>(() => ({
258
+ dataDefinedOnItem: props.data,
259
+ getPosition: noop,
260
+ settings: {
261
+ color: props.stroke,
262
+ dataKey: props.dataKey,
263
+ fill: props.fill,
264
+ formatter: props.formatter,
265
+ graphicalItemId: props.id,
266
+ hide: props.hide,
267
+ name: getTooltipNameProp(props.name, props.dataKey),
268
+ nameKey: undefined,
269
+ stroke: props.stroke,
270
+ strokeWidth: props.strokeWidth,
271
+ type: props.tooltipType,
272
+ unit: props.unit,
273
+ },
274
+ }))
275
+ return <SetTooltipEntrySettings tooltipEntrySettings={tooltipEntrySettings()} />
276
+ }
277
+
278
+ function LineDotsWrapper(props: {
279
+ points: ReadonlyArray<LinePointItem>
280
+ clipPathId: string
281
+ allProps: InternalProps
282
+ }) {
283
+ const lineProps = createMemo(() => svgPropertiesNoEvents(props.allProps, "id"))
284
+
285
+ return (
286
+ <Dots
287
+ points={props.points}
288
+ dot={props.allProps.dot}
289
+ className="recharts-line-dots"
290
+ dotClassName="recharts-line-dot"
291
+ dataKey={props.allProps.dataKey}
292
+ baseProps={lineProps()}
293
+ needClip={props.allProps.needClip}
294
+ clipPathId={props.clipPathId}
295
+ />
296
+ )
297
+ }
298
+
299
+ function LineLabelListProvider(props: {
300
+ showLabels: boolean
301
+ children: JSX.Element
302
+ points: ReadonlyArray<LinePointItem>
303
+ }) {
304
+ const labelListEntries = createMemo((): ReadonlyArray<CartesianLabelListEntry> => {
305
+ return props.points?.map((point): CartesianLabelListEntry => {
306
+ const viewBox: TrapezoidViewBox = {
307
+ height: 0,
308
+ lowerWidth: 0,
309
+ upperWidth: 0,
310
+ width: 0,
311
+ x: point.x ?? 0,
312
+ y: point.y ?? 0,
313
+ }
314
+ return {
315
+ ...viewBox,
316
+ fill: undefined,
317
+ parentViewBox: undefined,
318
+ payload: point.payload,
319
+ value: point.value,
320
+ viewBox,
321
+ }
322
+ })
323
+ })
324
+ /* eslint-disable solid/reactivity -- showLabels and labelListEntries() are reactive inside JSX; linter can't trace through Context.Provider value prop */
325
+ return (
326
+ <CartesianLabelListContextProvider value={props.showLabels ? labelListEntries() : undefined}>
327
+ {props.children}
328
+ </CartesianLabelListContextProvider>
329
+ )
330
+ /* eslint-enable solid/reactivity */
331
+ }
332
+
333
+ function StaticCurve(props: {
334
+ clipPathId: string
335
+ pathRef: { current: SVGPathElement | null } | undefined
336
+ points: ReadonlyArray<LinePointItem>
337
+ allProps: InternalProps
338
+ animationElapsedTime?: number
339
+ isAnimating?: boolean
340
+ isEntrance?: boolean
341
+ visibleLength?: number | null
342
+ }) {
343
+ /* GOTCHA-014: spreads + reactive attrs go through mergeProps lazy memos. If the first
344
+ property read happens inside an event handler (no owner), Solid warns. Hoist
345
+ derived attrs into setup-scope createMemos so the memo's owner is the component. */
346
+ /* eslint-disable-next-line solid/reactivity -- splitProps keeps lazy getters; reads happen in the memo below */
347
+ const [, others] = splitProps(props.allProps, [
348
+ "type",
349
+ "layout",
350
+ "connectNulls",
351
+ "needClip",
352
+ "shape",
353
+ "strokeDasharray",
354
+ ])
355
+ const eventProps = createMemo(() => svgPropertiesAndEvents(others))
356
+ const clipPath = createMemo(() =>
357
+ props.allProps.needClip ? `url(#clipPath-${props.clipPathId})` : undefined,
358
+ )
359
+
360
+ return (
361
+ <>
362
+ <Show when={props.points?.length > 1}>
363
+ <Shape
364
+ {...eventProps()}
365
+ shapeType="curve"
366
+ option={props.allProps.shape}
367
+ DefaultShape={LineDrawShape}
368
+ class="recharts-line-curve"
369
+ clip-path={clipPath()}
370
+ connectNulls={props.allProps.connectNulls}
371
+ fill="none"
372
+ layout={props.allProps.layout}
373
+ points={props.points}
374
+ strokeDasharray={props.allProps.strokeDasharray}
375
+ type={props.allProps.type}
376
+ pathRef={props.pathRef}
377
+ animationElapsedTime={props.animationElapsedTime}
378
+ isAnimating={props.isAnimating}
379
+ isEntrance={props.allProps.animateNewValues ? props.isEntrance : false}
380
+ visibleLength={props.visibleLength}
381
+ />
382
+ </Show>
383
+ <LineDotsWrapper
384
+ points={props.points}
385
+ clipPathId={props.clipPathId}
386
+ allProps={props.allProps}
387
+ />
388
+ </>
389
+ )
390
+ }
391
+
392
+ function averageShift(items: ReadonlyArray<AnimationItem<LinePointItem>>): number {
393
+ let total = 0
394
+ let count = 0
395
+ for (const item of items) {
396
+ if (item.status === "matched" && item.prev.x != null && item.next.x != null) {
397
+ total += item.next.x - item.prev.x
398
+ count++
399
+ }
400
+ }
401
+ return count > 0 ? total / count : 0
402
+ }
403
+
404
+ const defaultLineAnimateItems: AnimationInterpolateFn<LinePointItem, CartesianLayout> = (
405
+ items,
406
+ animationElapsedTime,
407
+ ) => {
408
+ if (items == null) {
409
+ // First render: return empty, stroke-dasharray handles the reveal
410
+ return []
411
+ }
412
+ // At animationElapsedTime=1 return only the non-removed items
413
+ if (animationElapsedTime === 1) return items.flatMap((item) => (item.status === "removed" ? [] : [item.next]))
414
+
415
+ const shift = averageShift(items)
416
+
417
+ const result: LinePointItem[] = []
418
+
419
+ for (const item of items) {
420
+ if (item.status === "matched") {
421
+ result.push({
422
+ ...item.next,
423
+ x: interpolate(item.prev.x, item.next.x, animationElapsedTime),
424
+ y: interpolate(item.prev.y, item.next.y, animationElapsedTime),
425
+ })
426
+ } else if (item.status === "added") {
427
+ if (item.next.x != null) {
428
+ // Extrapolate entry position: the point starts where it "would have been"
429
+ const entryX = item.next.x - shift
430
+ result.push({
431
+ ...item.next,
432
+ x: interpolate(entryX, item.next.x, animationElapsedTime),
433
+ y: item.next.y,
434
+ })
435
+ } else {
436
+ result.push(item.next)
437
+ }
438
+ } else if (item.status === "removed") {
439
+ if (item.prev.x != null) {
440
+ const exitX = item.prev.x + shift
441
+ result.push({
442
+ ...item.prev,
443
+ x: interpolate(item.prev.x, exitX, animationElapsedTime),
444
+ y: item.prev.y,
445
+ })
446
+ }
447
+ // else: removed items are simply dropped
448
+ }
449
+ }
450
+
451
+ return result
452
+ }
453
+
454
+ function CurveWithAnimation(props: {
455
+ clipPathId: string
456
+ allProps: InternalProps
457
+ previousPointsRef: { current: ReadonlyArray<LinePointItem> | null }
458
+ }) {
459
+ /* GOTCHA-014-J: ref-object shape `{ current }` matches upstream React `useRef`.
460
+ Tests assert `pathRef: { current: <SVGPathElement> }` on the props payload
461
+ passed to user click/mouse handlers. Curve's `<path>` writes via callback
462
+ into `pathRef.current`. */
463
+ /* Signal-backed so the dasharray memos re-run once the <path> ref attaches; React
464
+ gets the same re-measure from the re-render after onAnimationStart. */
465
+ const [pathElement, setPathElement] = createSignal<SVGPathElement | null>(null, { ownedWrite: true })
466
+ const pathRef: { current: SVGPathElement | null } = {
467
+ get current() {
468
+ return pathElement()
469
+ },
470
+ set current(element: SVGPathElement | null) {
471
+ setPathElement(() => element)
472
+ },
473
+ }
474
+
475
+ const { isAnimating, handleAnimationStart, handleAnimationEnd } = useAnimationCallbacks(
476
+ () => props.allProps.onAnimationStart,
477
+ () => props.allProps.onAnimationEnd,
478
+ )
479
+ /* Same content-compared identity AnimatedItems uses for its animation id. */
480
+ const lengthAnimationId = useAnimationId(() => props.allProps.points, "recharts-line-length-")
481
+ const getVisibleLength = useAnimatedLineLength(lengthAnimationId)
482
+
483
+ /* Measured once per path `d` (see pathTotalLength), and only for animating lines. */
484
+ const totalLength = (): number => pathTotalLength(pathRef.current)
485
+
486
+ // Guard for totalLength: don't update previousPointsRef before SVG path is measured.
487
+ // A line that never animates has nothing to reveal, so a mounted path is enough.
488
+ const shouldUpdatePreviousRef = (animationElapsedTime: number) =>
489
+ animationElapsedTime > 0 &&
490
+ (props.allProps.isAnimationActive === false ? pathRef.current != null : totalLength() > 0)
491
+
492
+ return (
493
+ <LineLabelListProvider points={props.allProps.points} showLabels={!isAnimating()}>
494
+ {/* GOTCHA-017: user JSX (ErrorBar) memoized via children() helper inside
495
+ SetErrorBarContext.Provider scope so createComponent(ErrorBar) captures
496
+ live ctx Accessor, not initial-default. Single read site. */}
497
+ <GraphicalItemChildrenScope>{props.allProps.children}</GraphicalItemChildrenScope>
498
+ <AnimatedItems
499
+ animationInput={props.allProps.points}
500
+ animationIdPrefix="recharts-line-"
501
+ items={props.allProps.points}
502
+ previousItemsRef={props.previousPointsRef}
503
+ isAnimationActive={props.allProps.isAnimationActive}
504
+ animationBegin={props.allProps.animationBegin}
505
+ animationDuration={props.allProps.animationDuration}
506
+ animationEasing={props.allProps.animationEasing}
507
+ onAnimationStart={handleAnimationStart}
508
+ onAnimationEnd={handleAnimationEnd}
509
+ animationInterpolateFn={props.allProps.animationInterpolateFn}
510
+ animationMatchBy={props.allProps.animationMatchBy}
511
+ shouldUpdatePreviousRef={shouldUpdatePreviousRef}
512
+ layout={props.allProps.layout}
513
+ >
514
+ {(stepData, animationElapsedTime, isEntrance) => {
515
+ const animationActive = () => isAnimating() || animationElapsedTime() < 1
516
+ const visibleLength = createMemo(() =>
517
+ animationActive()
518
+ ? getVisibleLength(animationElapsedTime(), totalLength())
519
+ : null,
520
+ )
521
+ return (
522
+ <StaticCurve
523
+ allProps={props.allProps}
524
+ points={stepData()}
525
+ clipPathId={props.clipPathId}
526
+ pathRef={pathRef}
527
+ animationElapsedTime={animationElapsedTime()}
528
+ isAnimating={animationActive()}
529
+ isEntrance={isEntrance()}
530
+ visibleLength={visibleLength()}
531
+ />
532
+ )
533
+ }}
534
+ </AnimatedItems>
535
+ <LabelListFromLabelProp label={props.allProps.label} />
536
+ </LineLabelListProvider>
537
+ )
538
+ }
539
+
540
+ function RenderCurve(props: { clipPathId: string; allProps: InternalProps }) {
541
+ const previousPointsRef: { current: ReadonlyArray<LinePointItem> | null } = { current: null }
542
+ return (
543
+ <CurveWithAnimation
544
+ clipPathId={props.clipPathId}
545
+ allProps={props.allProps}
546
+ previousPointsRef={previousPointsRef}
547
+ />
548
+ )
549
+ }
550
+
551
+ const errorBarDataPointFormatter: ErrorBarDataPointFormatter<LinePointItem> = (
552
+ dataPoint: LinePointItem,
553
+ dataKey,
554
+ ): ErrorBarDataItem => {
555
+ return {
556
+ errorVal: getValueByDataKey(dataPoint.payload as LinePointItem, dataKey),
557
+ value: dataPoint.value,
558
+ x: dataPoint.x ?? undefined,
559
+ y: dataPoint.y ?? undefined,
560
+ }
561
+ }
562
+
563
+ function LineWithState(props: InternalProps) {
564
+ return (
565
+ <Show when={!props.hide}>
566
+ {(() => {
567
+ const layerClass = () => clsx("recharts-line", props.className)
568
+ const clipPathId = () => props.id
569
+ const dotMeta = () => getRadiusAndStrokeWidthFromDot(props.dot)
570
+ const clipDot = () => isClipDot(props.dot)
571
+ const dotSize = () => dotMeta().r * 2 + dotMeta().strokeWidth
572
+ const activePointsClipPath = () =>
573
+ props.needClip ? `url(#clipPath-${clipDot() ? "" : "dots-"}${clipPathId()})` : undefined
574
+
575
+ return (
576
+ <ZIndexLayer zIndex={props.zIndex}>
577
+ <Layer class={layerClass()}>
578
+ <Show when={props.needClip}>
579
+ <defs>
580
+ <GraphicalItemClipPath
581
+ clipPathId={clipPathId()}
582
+ xAxisId={props.xAxisId}
583
+ yAxisId={props.yAxisId}
584
+ />
585
+ <Show when={!clipDot()}>
586
+ <clipPath id={`clipPath-dots-${clipPathId()}`}>
587
+ <rect
588
+ x={props.left - dotSize() / 2}
589
+ y={props.top - dotSize() / 2}
590
+ width={props.width + dotSize()}
591
+ height={props.height + dotSize()}
592
+ />
593
+ </clipPath>
594
+ </Show>
595
+ </defs>
596
+ </Show>
597
+ {/* GOTCHA-017 (session 34): SetErrorBarContext hoisted to Line()
598
+ outer scope. RenderCurve is now inside the Provider scope via
599
+ the outer wrapper. */}
600
+ <RenderCurve allProps={props} clipPathId={clipPathId()} />
601
+ </Layer>
602
+ <ActivePoints
603
+ activeDot={props.activeDot}
604
+ points={props.points}
605
+ mainColor={props.stroke}
606
+ itemDataKey={props.dataKey}
607
+ clipPath={activePointsClipPath()}
608
+ />
609
+ </ZIndexLayer>
610
+ )
611
+ })()}
612
+ </Show>
613
+ )
614
+ }
615
+
616
+ export const defaultLineProps = {
617
+ activeDot: true,
618
+ animateNewValues: true,
619
+ animationBegin: 0,
620
+ animationDuration: 1500,
621
+ animationEasing: "ease",
622
+ animationInterpolateFn: defaultLineAnimateItems,
623
+ animationMatchBy: matchByIndex,
624
+ connectNulls: false,
625
+ dot: true,
626
+ fill: "#fff",
627
+ hide: false,
628
+ isAnimationActive: "auto",
629
+ label: false,
630
+ legendType: "line",
631
+ shape: LineDrawShape,
632
+ stroke: "#3182bd",
633
+ strokeWidth: 1,
634
+ type: "linear",
635
+ xAxisId: 0,
636
+ yAxisId: 0,
637
+ zIndex: DefaultZIndexes.line,
638
+ } as const satisfies Partial<Props>
639
+
640
+ function LineImpl(props: WithIdRequired<Props>) {
641
+ const resolved = resolveDefaultProps(props, defaultLineProps)
642
+
643
+ const needClipResult = createMemo(() => useNeedsClip(resolved.xAxisId, resolved.yAxisId))
644
+ /* arrow thunks: bare hooks, but callsites repeatedly read inside Show predicate
645
+ and render-fn — thunk preserves callsite shape and reactivity. See GOTCHA-011. */
646
+ const plotArea = createMemo(() => usePlotArea())
647
+ const layout = createMemo(() => useChartLayout())
648
+ const isPanorama = useIsPanorama()
649
+ const ctx = useChartStore()
650
+ /* selectLinePoints is a per-chart chartSelector memo keyed by these ids. It resolves the
651
+ item's settings from the store itself, so a dataKey or data change re-derives the points
652
+ once for every reader, and an all-primitive key never pins a replaced settings node. */
653
+ const points = createMemo(() =>
654
+ ctx
655
+ ? selectLinePoints(ctx.store, resolved.xAxisId, resolved.yAxisId, isPanorama, resolved.id)
656
+ : undefined,
657
+ )
658
+
659
+ return (
660
+ <Show
661
+ when={
662
+ (layout() === "horizontal" || layout() === "vertical") &&
663
+ points() != null &&
664
+ plotArea() != null
665
+ }
666
+ >
667
+ {(() => {
668
+ const viewBox = plotArea()
669
+ const {
670
+ height,
671
+ width,
672
+ x: left,
673
+ y: top,
674
+ } = viewBox as { height: number; width: number; x: number; y: number }
675
+
676
+ return (
677
+ <LineWithState
678
+ {...resolved}
679
+ id={resolved.id}
680
+ connectNulls={resolved.connectNulls}
681
+ dot={resolved.dot}
682
+ activeDot={resolved.activeDot}
683
+ animateNewValues={resolved.animateNewValues}
684
+ animationBegin={resolved.animationBegin}
685
+ animationDuration={resolved.animationDuration}
686
+ animationEasing={resolved.animationEasing}
687
+ isAnimationActive={resolved.isAnimationActive}
688
+ hide={resolved.hide}
689
+ label={resolved.label}
690
+ legendType={resolved.legendType}
691
+ xAxisId={resolved.xAxisId}
692
+ yAxisId={resolved.yAxisId}
693
+ points={points() as ReadonlyArray<LinePointItem>}
694
+ layout={layout() as "horizontal" | "vertical"}
695
+ height={height}
696
+ width={width}
697
+ left={left}
698
+ top={top}
699
+ needClip={needClipResult()?.needClip()}
700
+ />
701
+ )
702
+ })()}
703
+ </Show>
704
+ )
705
+ }
706
+
707
+ export function computeLinePoints({
708
+ layout,
709
+ xAxis,
710
+ yAxis,
711
+ xAxisTicks,
712
+ yAxisTicks,
713
+ dataKey,
714
+ bandSize,
715
+ displayedData,
716
+ }: {
717
+ layout: CartesianLayout
718
+ xAxis: BaseAxisWithScale
719
+ yAxis: BaseAxisWithScale
720
+ xAxisTicks: TickItem[]
721
+ yAxisTicks: TickItem[]
722
+ dataKey: Props["dataKey"]
723
+ bandSize: number
724
+ displayedData: ChartData
725
+ }): ReadonlyArray<LinePointItem> {
726
+ return displayedData
727
+ .map((entry, index): LinePointItem | null => {
728
+ const entryRecord =
729
+ entry != null && typeof entry === "object"
730
+ ? (entry as Record<string, unknown>)
731
+ : ({} as Record<string, unknown>)
732
+ const value = getValueByDataKey(entry, dataKey) as number
733
+
734
+ if (layout === "horizontal") {
735
+ const x = getCateCoordinateOfLine({
736
+ axis: xAxis,
737
+ bandSize,
738
+ entry: entryRecord,
739
+ index,
740
+ ticks: xAxisTicks,
741
+ })
742
+ const y = isNullish(value) ? null : yAxis.scale.map(value)
743
+ return {
744
+ payload: entry,
745
+ value,
746
+ x,
747
+ y: y ?? null,
748
+ }
749
+ }
750
+
751
+ const x = isNullish(value) ? null : xAxis.scale.map(value)
752
+ const y = getCateCoordinateOfLine({
753
+ axis: yAxis,
754
+ bandSize,
755
+ entry: entryRecord,
756
+ index,
757
+ ticks: yAxisTicks,
758
+ })
759
+ if (x == null || y == null) {
760
+ return null
761
+ }
762
+ return {
763
+ payload: entry,
764
+ value,
765
+ x,
766
+ y,
767
+ }
768
+ })
769
+ .filter(Boolean) as ReadonlyArray<LinePointItem>
770
+ }
771
+
772
+ /**
773
+ * @provides LabelListContext
774
+ * @provides ErrorBarContext
775
+ * @consumes CartesianChartContext
776
+ */
777
+ function LineFn(outsideProps: Props) {
778
+ /* GOTCHA-013 + GOTCHA-014: split children, then mergeProps for the defaults
779
+ layer. resolveDefaultProps `{...realProps}` snapshots the props proxy at
780
+ first render — animationEasing, isAnimationActive and every other prop
781
+ freeze. mergeProps preserves the lazy proxy so reactive parents (e.g.
782
+ tests changing dataKey at runtime) keep flowing values into LineImpl. */
783
+ const [childrenProps, restProps] = splitProps(outsideProps, ["children"])
784
+ const props = mergeProps(defaultLineProps, restProps) as ReturnType<
785
+ typeof resolveDefaultProps<typeof restProps, typeof defaultLineProps>
786
+ >
787
+ const isPanorama = useIsPanorama()
788
+ const ctx = useChartStore()
789
+ return (
790
+ <RegisterGraphicalItemId id={props.id} type="line">
791
+ {(id) => {
792
+ /* GOTCHA-017 (session 34): SetErrorBarContext hoisted from LineWithState
793
+ to here so user JSX <ErrorBar/> in props.children evaluates inside the
794
+ Provider owner. Points come from the same selector LineImpl uses. */
795
+ const linePoints = () =>
796
+ ctx
797
+ ? selectLinePoints(ctx.store, props.xAxisId, props.yAxisId, isPanorama, id)
798
+ : undefined
799
+ return (
800
+ <>
801
+ <SetLegendPayload legendPayload={computeLegendPayloadFromAreaData(props)} />
802
+ <SetLineTooltipEntrySettings
803
+ dataKey={props.dataKey}
804
+ data={props.data}
805
+ stroke={props.stroke}
806
+ strokeWidth={props.strokeWidth}
807
+ fill={props.fill}
808
+ name={props.name}
809
+ hide={props.hide}
810
+ unit={props.unit}
811
+ tooltipType={props.tooltipType}
812
+ formatter={props.formatter}
813
+ id={id}
814
+ />
815
+ <SetCartesianGraphicalItem
816
+ type="line"
817
+ id={id}
818
+ data={props.data}
819
+ xAxisId={props.xAxisId}
820
+ yAxisId={props.yAxisId}
821
+ zAxisId={0}
822
+ dataKey={props.dataKey}
823
+ hide={props.hide}
824
+ isPanorama={isPanorama}
825
+ />
826
+ <SetErrorBarContext
827
+ xAxisId={props.xAxisId}
828
+ yAxisId={props.yAxisId}
829
+ data={linePoints()}
830
+ dataPointFormatter={errorBarDataPointFormatter}
831
+ errorBarOffset={0}
832
+ >
833
+ <LabelListContextBridge>
834
+ {(() => {
835
+ /* GOTCHA-017 (session 34): memoize children INSIDE SetErrorBarContext
836
+ so ErrorBar JSX createComponent captures the live Provider. */
837
+ const memoizedChildren = createMemo(() => childrenProps.children)
838
+ return (
839
+ <LineImpl {...props} id={id}>
840
+ {memoizedChildren()}
841
+ </LineImpl>
842
+ )
843
+ })()}
844
+ </LabelListContextBridge>
845
+ </SetErrorBarContext>
846
+ </>
847
+ )
848
+ }}
849
+ </RegisterGraphicalItemId>
850
+ )
851
+ }
852
+
853
+ /**
854
+ * Typed entry point: the generics constrain `data`/`dataKey` at the call site, like upstream.
855
+ */
856
+ /* eslint-disable-next-line typescript-eslint/no-explicit-any -- upstream contract: untyped items accept any data */
857
+ export const Line = LineFn as {
858
+ <DataPointType = any, DataValueType = any>(props: Props<DataPointType, DataValueType>): JSX.Element
859
+ /* eslint-disable-next-line typescript-eslint/no-explicit-any -- upstream fallback overload for mismatched data/dataKey */
860
+ (props: Props<any, any>): JSX.Element
861
+ displayName?: string
862
+ }
863
+ Line.displayName = "Line"