solid-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 (639) hide show
  1. package/NEXT_SESSION_PROMPT.md +114 -0
  2. package/package.json +28 -0
  3. package/src/animation/AnimatedItems.tsx +169 -0
  4. package/src/animation/AnimationController.ts +24 -0
  5. package/src/animation/AnimationControllerImpl.ts +37 -0
  6. package/src/animation/AnimationHandle.ts +273 -0
  7. package/src/animation/CSSTransitionAnimate.tsx +142 -0
  8. package/src/animation/JavascriptAnimate.tsx +107 -0
  9. package/src/animation/easing.ts +261 -0
  10. package/src/animation/matchBy.ts +211 -0
  11. package/src/animation/timeoutController.ts +51 -0
  12. package/src/animation/useAnimationController.tsx +31 -0
  13. package/src/animation/useAnimationStartSnapshot.ts +73 -0
  14. package/src/animation/util.ts +16 -0
  15. package/src/cartesian/Area.tsx +810 -0
  16. package/src/cartesian/AreaRevealShape.tsx +250 -0
  17. package/src/cartesian/Bar.tsx +1216 -0
  18. package/src/cartesian/BarStack.tsx +148 -0
  19. package/src/cartesian/Brush.tsx +653 -0
  20. package/src/cartesian/CartesianAxis.tsx +541 -0
  21. package/src/cartesian/CartesianGrid.tsx +605 -0
  22. package/src/cartesian/ErrorBar.tsx +319 -0
  23. package/src/cartesian/Funnel.tsx +594 -0
  24. package/src/cartesian/GraphicalItemClipPath.tsx +75 -0
  25. package/src/cartesian/Line.tsx +742 -0
  26. package/src/cartesian/LineDrawShape.tsx +190 -0
  27. package/src/cartesian/ReferenceArea.tsx +275 -0
  28. package/src/cartesian/ReferenceDot.tsx +286 -0
  29. package/src/cartesian/ReferenceLine.tsx +414 -0
  30. package/src/cartesian/RenderedTicksReporter.tsx +49 -0
  31. package/src/cartesian/Scatter.tsx +741 -0
  32. package/src/cartesian/XAxis.tsx +293 -0
  33. package/src/cartesian/YAxis.tsx +333 -0
  34. package/src/cartesian/ZAxis.tsx +80 -0
  35. package/src/cartesian/getCartesianPosition.ts +255 -0
  36. package/src/cartesian/getEquidistantTicks.ts +126 -0
  37. package/src/cartesian/getTicks.ts +225 -0
  38. package/src/cartesian/useAnimatedLineLength.ts +84 -0
  39. package/src/chart/AreaChart.tsx +30 -0
  40. package/src/chart/BarChart.tsx +27 -0
  41. package/src/chart/CartesianChart.tsx +91 -0
  42. package/src/chart/CategoricalChart.tsx +60 -0
  43. package/src/chart/ComposedChart.tsx +29 -0
  44. package/src/chart/FunnelChart.tsx +29 -0
  45. package/src/chart/LineChart.tsx +29 -0
  46. package/src/chart/PieChart.tsx +41 -0
  47. package/src/chart/PolarChart.tsx +97 -0
  48. package/src/chart/RadarChart.tsx +37 -0
  49. package/src/chart/RadialBarChart.tsx +39 -0
  50. package/src/chart/RechartsWrapper.tsx +486 -0
  51. package/src/chart/Sankey.tsx +992 -0
  52. package/src/chart/ScatterChart.tsx +29 -0
  53. package/src/chart/SunburstChart.tsx +394 -0
  54. package/src/chart/Treemap.tsx +874 -0
  55. package/src/chart/types.ts +37 -0
  56. package/src/component/ActivePoints.tsx +136 -0
  57. package/src/component/Cell.tsx +72 -0
  58. package/src/component/Cursor.tsx +249 -0
  59. package/src/component/Customized.tsx +8 -0
  60. package/src/component/DefaultLegendContent.tsx +205 -0
  61. package/src/component/DefaultTooltipContent.tsx +247 -0
  62. package/src/component/Dots.tsx +128 -0
  63. package/src/component/Label.tsx +507 -0
  64. package/src/component/LabelList.tsx +270 -0
  65. package/src/component/Legend.tsx +273 -0
  66. package/src/component/ResponsiveContainer.tsx +397 -0
  67. package/src/component/Text.tsx +436 -0
  68. package/src/component/Tooltip.tsx +309 -0
  69. package/src/component/TooltipBoundingBox.tsx +152 -0
  70. package/src/component/responsiveContainerUtils.ts +128 -0
  71. package/src/container/ClipPathProvider.tsx +40 -0
  72. package/src/container/Layer.tsx +38 -0
  73. package/src/container/RootSurface.tsx +124 -0
  74. package/src/container/Surface.tsx +70 -0
  75. package/src/context/ErrorBarContext.tsx +85 -0
  76. package/src/context/PanoramaContext.tsx +13 -0
  77. package/src/context/RegisterGraphicalItemId.tsx +41 -0
  78. package/src/context/accessibilityContext.tsx +10 -0
  79. package/src/context/brushUpdateContext.ts +14 -0
  80. package/src/context/chartDataContext.tsx +79 -0
  81. package/src/context/chartLayoutContext.tsx +158 -0
  82. package/src/context/legendPayloadContext.ts +11 -0
  83. package/src/context/legendPortalContext.ts +11 -0
  84. package/src/context/tooltipContext.ts +72 -0
  85. package/src/context/tooltipPortalContext.ts +14 -0
  86. package/src/context/useTooltipAxis.ts +24 -0
  87. package/src/hooks.ts +312 -0
  88. package/src/index.ts +288 -0
  89. package/src/polar/Pie.tsx +912 -0
  90. package/src/polar/PolarAngleAxis.tsx +494 -0
  91. package/src/polar/PolarGrid.tsx +269 -0
  92. package/src/polar/PolarRadiusAxis.tsx +422 -0
  93. package/src/polar/Radar.tsx +652 -0
  94. package/src/polar/RadialBar.tsx +767 -0
  95. package/src/polar/defaultPolarAngleAxisProps.tsx +33 -0
  96. package/src/polar/defaultPolarRadiusAxisProps.tsx +28 -0
  97. package/src/shape/Cross.tsx +83 -0
  98. package/src/shape/Curve.tsx +335 -0
  99. package/src/shape/Dot.tsx +49 -0
  100. package/src/shape/Polygon.tsx +168 -0
  101. package/src/shape/Rectangle.tsx +301 -0
  102. package/src/shape/Sector.tsx +304 -0
  103. package/src/shape/Symbols.tsx +144 -0
  104. package/src/shape/Trapezoid.tsx +228 -0
  105. package/src/state/RechartsReduxContext.tsx +8 -0
  106. package/src/state/RechartsStoreContext.ts +15 -0
  107. package/src/state/RechartsStoreProvider.tsx +27 -0
  108. package/src/state/ReportChartProps.tsx +19 -0
  109. package/src/state/ReportEventSettings.tsx +19 -0
  110. package/src/state/ReportMainChartProps.tsx +35 -0
  111. package/src/state/ReportPolarOptions.tsx +28 -0
  112. package/src/state/SetLegendPayload.ts +50 -0
  113. package/src/state/SetTooltipEntrySettings.tsx +46 -0
  114. package/src/state/brushSlice.ts +60 -0
  115. package/src/state/cartesianAxisSlice.ts +288 -0
  116. package/src/state/chartDataSlice.ts +115 -0
  117. package/src/state/errorBarSlice.ts +84 -0
  118. package/src/state/eventSettingsSlice.ts +41 -0
  119. package/src/state/externalEventsMiddleware.ts +136 -0
  120. package/src/state/graphicalItemsSlice.ts +162 -0
  121. package/src/state/hooks.ts +42 -0
  122. package/src/state/keyboardEventsMiddleware.ts +213 -0
  123. package/src/state/layoutSlice.ts +71 -0
  124. package/src/state/legendSlice.ts +107 -0
  125. package/src/state/mouseEventsMiddleware.ts +103 -0
  126. package/src/state/optionsSlice.ts +64 -0
  127. package/src/state/polarAxisSlice.ts +65 -0
  128. package/src/state/polarOptionsSlice.ts +54 -0
  129. package/src/state/reduxDevtoolsJsonStringifyReplacer.ts +15 -0
  130. package/src/state/referenceElementsSlice.ts +121 -0
  131. package/src/state/renderedTicksSlice.ts +61 -0
  132. package/src/state/rootPropsSlice.ts +70 -0
  133. package/src/state/selectors/areaSelectors.ts +169 -0
  134. package/src/state/selectors/arrayEqualityCheck.ts +8 -0
  135. package/src/state/selectors/axisSelectors.ts +2196 -0
  136. package/src/state/selectors/barSelectors.ts +319 -0
  137. package/src/state/selectors/barStackSelectors.ts +79 -0
  138. package/src/state/selectors/brushSelectors.ts +40 -0
  139. package/src/state/selectors/combiners/combineActiveLabel.ts +21 -0
  140. package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +93 -0
  141. package/src/state/selectors/combiners/combineAllBarPositions.ts +131 -0
  142. package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +17 -0
  143. package/src/state/selectors/combiners/combineBarPosition.ts +24 -0
  144. package/src/state/selectors/combiners/combineBarSizeList.ts +75 -0
  145. package/src/state/selectors/combiners/combineCheckedDomain.ts +49 -0
  146. package/src/state/selectors/combiners/combineConfiguredScale.ts +121 -0
  147. package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +43 -0
  148. package/src/state/selectors/combiners/combineDisplayedStackedData.ts +50 -0
  149. package/src/state/selectors/combiners/combineInverseScaleFunction.ts +17 -0
  150. package/src/state/selectors/combiners/combineRealScaleType.ts +48 -0
  151. package/src/state/selectors/combiners/combineStackedData.ts +28 -0
  152. package/src/state/selectors/combiners/combineTooltipInteractionState.ts +86 -0
  153. package/src/state/selectors/combiners/combineTooltipPayload.ts +203 -0
  154. package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +45 -0
  155. package/src/state/selectors/containerSelectors.ts +12 -0
  156. package/src/state/selectors/dataSelectors.ts +90 -0
  157. package/src/state/selectors/funnelSelectors.ts +83 -0
  158. package/src/state/selectors/graphicalItemSelectors.ts +23 -0
  159. package/src/state/selectors/legendSelectors.ts +29 -0
  160. package/src/state/selectors/lineSelectors.ts +111 -0
  161. package/src/state/selectors/numberDomainEqualityCheck.ts +8 -0
  162. package/src/state/selectors/pickAxisId.ts +6 -0
  163. package/src/state/selectors/pickAxisType.ts +4 -0
  164. package/src/state/selectors/pieSelectors.ts +103 -0
  165. package/src/state/selectors/polarAxisSelectors.ts +202 -0
  166. package/src/state/selectors/polarGridSelectors.ts +24 -0
  167. package/src/state/selectors/polarScaleSelectors.ts +149 -0
  168. package/src/state/selectors/polarSelectors.ts +211 -0
  169. package/src/state/selectors/radarSelectors.ts +152 -0
  170. package/src/state/selectors/radialBarSelectors.ts +328 -0
  171. package/src/state/selectors/rootPropsSelectors.ts +36 -0
  172. package/src/state/selectors/scatterSelectors.ts +77 -0
  173. package/src/state/selectors/selectAllAxes.ts +10 -0
  174. package/src/state/selectors/selectChartOffset.ts +15 -0
  175. package/src/state/selectors/selectChartOffsetInternal.ts +111 -0
  176. package/src/state/selectors/selectPlotArea.ts +27 -0
  177. package/src/state/selectors/selectTooltipAxisId.ts +6 -0
  178. package/src/state/selectors/selectTooltipAxisType.ts +33 -0
  179. package/src/state/selectors/selectTooltipEventType.ts +45 -0
  180. package/src/state/selectors/selectTooltipPayloadSearcher.ts +7 -0
  181. package/src/state/selectors/selectTooltipSettings.ts +6 -0
  182. package/src/state/selectors/selectTooltipState.ts +5 -0
  183. package/src/state/selectors/tooltipSelectors.ts +690 -0
  184. package/src/state/selectors/touchSelectors.ts +29 -0
  185. package/src/state/store.ts +167 -0
  186. package/src/state/tooltipSlice.ts +289 -0
  187. package/src/state/types/AreaSettings.ts +17 -0
  188. package/src/state/types/BarSettings.ts +16 -0
  189. package/src/state/types/LineSettings.ts +12 -0
  190. package/src/state/types/PieSettings.ts +32 -0
  191. package/src/state/types/RadarSettings.ts +6 -0
  192. package/src/state/types/RadialBarSettings.ts +10 -0
  193. package/src/state/types/ScatterSettings.ts +13 -0
  194. package/src/state/types/StackedGraphicalItem.ts +33 -0
  195. package/src/state/unregisterOnCleanup.ts +26 -0
  196. package/src/state/zIndexSlice.ts +128 -0
  197. package/src/synchronisation/syncRegistry.ts +131 -0
  198. package/src/synchronisation/syncSelectors.ts +7 -0
  199. package/src/synchronisation/types.ts +42 -0
  200. package/src/synchronisation/useChartSynchronisation.tsx +372 -0
  201. package/src/types.ts +39 -0
  202. package/src/util/ActiveShapeUtils.tsx +80 -0
  203. package/src/util/BarUtils.tsx +74 -0
  204. package/src/util/CartesianUtils.ts +53 -0
  205. package/src/util/ChartUtils.ts +696 -0
  206. package/src/util/Constants.ts +42 -0
  207. package/src/util/CssPrefixUtils.ts +24 -0
  208. package/src/util/DOMUtils.ts +141 -0
  209. package/src/util/DataUtils.ts +205 -0
  210. package/src/util/FunnelUtils.tsx +37 -0
  211. package/src/util/Global.ts +15 -0
  212. package/src/util/IfOverflow.ts +17 -0
  213. package/src/util/LRUCache.ts +46 -0
  214. package/src/util/LogUtils.ts +26 -0
  215. package/src/util/PolarUtils.ts +134 -0
  216. package/src/util/RadialBarUtils.tsx +35 -0
  217. package/src/util/ReduceCSSCalc.ts +186 -0
  218. package/src/util/ShallowEqual.ts +43 -0
  219. package/src/util/TickUtils.ts +61 -0
  220. package/src/util/YAxisUtils.ts +49 -0
  221. package/src/util/adaptEventHandlers.ts +69 -0
  222. package/src/util/axisPropsAreEqual.ts +42 -0
  223. package/src/util/collectionUtils.ts +83 -0
  224. package/src/util/createCartesianCharts.tsx +101 -0
  225. package/src/util/createEventProxy.ts +24 -0
  226. package/src/util/createPolarCharts.tsx +86 -0
  227. package/src/util/cursor/getCursorPoints.ts +48 -0
  228. package/src/util/cursor/getCursorRectangle.ts +31 -0
  229. package/src/util/cursor/getRadialCursorPoints.ts +34 -0
  230. package/src/util/excludeEventProps.ts +172 -0
  231. package/src/util/getActiveCoordinate.ts +205 -0
  232. package/src/util/getAxisTypeBasedOnLayout.ts +21 -0
  233. package/src/util/getEveryNth.ts +30 -0
  234. package/src/util/getRadiusAndStrokeWidthFromDot.ts +35 -0
  235. package/src/util/getRelativeCoordinate.ts +84 -0
  236. package/src/util/getSliced.ts +21 -0
  237. package/src/util/isDomainSpecifiedByUser.ts +217 -0
  238. package/src/util/isWellBehavedNumber.ts +10 -0
  239. package/src/util/objectPath.ts +129 -0
  240. package/src/util/payload/getUniqPayload.ts +31 -0
  241. package/src/util/propsAreEqual.ts +137 -0
  242. package/src/util/resolveDefaultProps.tsx +8 -0
  243. package/src/util/round.ts +35 -0
  244. package/src/util/scale/CartesianScaleHelper.ts +72 -0
  245. package/src/util/scale/CustomScaleDefinition.ts +82 -0
  246. package/src/util/scale/RechartsScale.ts +131 -0
  247. package/src/util/scale/createCategoricalInverse.ts +83 -0
  248. package/src/util/scale/getNiceTickValues.ts +334 -0
  249. package/src/util/scale/index.ts +3 -0
  250. package/src/util/scale/util/DecimalLite.ts +194 -0
  251. package/src/util/scale/util/arithmetic.ts +56 -0
  252. package/src/util/stacks/getStackSeriesIdentifier.ts +20 -0
  253. package/src/util/stacks/stackTypes.ts +53 -0
  254. package/src/util/svgPropertiesAndEvents.ts +84 -0
  255. package/src/util/svgPropertiesNoEvents.ts +520 -0
  256. package/src/util/tooltip/translate.ts +179 -0
  257. package/src/util/typedDataKey.ts +8 -0
  258. package/src/util/types.ts +724 -0
  259. package/src/util/useAnimationId.tsx +31 -0
  260. package/src/util/useElementOffset.ts +164 -0
  261. package/src/util/useId.ts +20 -0
  262. package/src/util/usePrefersReducedMotion.ts +44 -0
  263. package/src/util/useUniqueId.ts +34 -0
  264. package/src/zIndex/DefaultZIndexes.tsx +87 -0
  265. package/src/zIndex/ZIndexLayer.tsx +126 -0
  266. package/src/zIndex/ZIndexPortal.tsx +69 -0
  267. package/src/zIndex/getZIndexFromUnknown.tsx +17 -0
  268. package/src/zIndex/zIndexSelectors.ts +46 -0
  269. package/test/_data.ts +408 -0
  270. package/test/animation/AnimationController.typed.spec.ts +53 -0
  271. package/test/animation/AnimationControllerImpl.spec.ts +271 -0
  272. package/test/animation/CSSTransitionAnimate.timing.spec.tsx +473 -0
  273. package/test/animation/JavascriptAnimate.spec.tsx +62 -0
  274. package/test/animation/RechartsAnimation.spec.ts +636 -0
  275. package/test/animation/easing.spec.ts +218 -0
  276. package/test/animation/legacyAnimationLengthChange.spec.tsx +803 -0
  277. package/test/animation/matchBy.spec.ts +467 -0
  278. package/test/animation/mockAnimationController.ts +40 -0
  279. package/test/animation/mockControllerAnimationManager.ts +143 -0
  280. package/test/animation/mockTimeoutController.ts +114 -0
  281. package/test/animation/timeoutController.spec.ts +138 -0
  282. package/test/animation/useAnimationStartSnapshot.spec.ts +147 -0
  283. package/test/animation/util.spec.ts +28 -0
  284. package/test/cartesian/Area.animation.spec.tsx +363 -0
  285. package/test/cartesian/Area.range.spec.tsx +54 -0
  286. package/test/cartesian/Area.spec.tsx +1202 -0
  287. package/test/cartesian/Area.stacked.render.spec.tsx +69 -0
  288. package/test/cartesian/Area.typed.spec.tsx +209 -0
  289. package/test/cartesian/Axis.integration.spec.tsx +158 -0
  290. package/test/cartesian/Bar/Bar.csstransition.spec.tsx +299 -0
  291. package/test/cartesian/Bar/Bar.spec.tsx +2314 -0
  292. package/test/cartesian/Bar/Bar.typed.spec.tsx +192 -0
  293. package/test/cartesian/Bar.animation.spec.tsx +426 -0
  294. package/test/cartesian/Bar.stackDomain.spec.tsx +66 -0
  295. package/test/cartesian/Bar.stacked.render.spec.tsx +53 -0
  296. package/test/cartesian/Bar.truncateByDomain.spec.tsx +237 -0
  297. package/test/cartesian/Bar.zeroDimensionFiltering.spec.tsx +336 -0
  298. package/test/cartesian/BarStack.spec.tsx +91 -0
  299. package/test/cartesian/Brush.keyboard.spec.tsx +88 -0
  300. package/test/cartesian/Brush.panorama.spec.tsx +41 -0
  301. package/test/cartesian/Brush.props.spec.tsx +63 -0
  302. package/test/cartesian/Brush.render.spec.tsx +117 -0
  303. package/test/cartesian/Brush.spec.tsx +522 -0
  304. package/test/cartesian/Brush.stacked.spec.tsx +221 -0
  305. package/test/cartesian/CartesianAxis.render.spec.tsx +50 -0
  306. package/test/cartesian/CartesianAxis.spec.tsx +396 -0
  307. package/test/cartesian/CartesianGrid.render.spec.tsx +39 -0
  308. package/test/cartesian/CartesianGrid.spec.tsx +2103 -0
  309. package/test/cartesian/ErrorBar.render.spec.tsx +69 -0
  310. package/test/cartesian/ErrorBar.spec.tsx +2414 -0
  311. package/test/cartesian/Funnel.animation.spec.tsx +241 -0
  312. package/test/cartesian/Funnel.spec.tsx +226 -0
  313. package/test/cartesian/Funnel.typed.spec.tsx +221 -0
  314. package/test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx +627 -0
  315. package/test/cartesian/GraphicalItemClipPath.spec.tsx +427 -0
  316. package/test/cartesian/Line.animation.spec.tsx +643 -0
  317. package/test/cartesian/Line.sparseAnimationPath.spec.tsx +98 -0
  318. package/test/cartesian/Line.spec.tsx +471 -0
  319. package/test/cartesian/Line.typed.spec.tsx +152 -0
  320. package/test/cartesian/ReferenceArea.render.spec.tsx +63 -0
  321. package/test/cartesian/ReferenceArea.spec.tsx +663 -0
  322. package/test/cartesian/ReferenceArea.typed.spec.tsx +74 -0
  323. package/test/cartesian/ReferenceDot.render.spec.tsx +55 -0
  324. package/test/cartesian/ReferenceDot.spec.tsx +462 -0
  325. package/test/cartesian/ReferenceDot.typed.spec.tsx +76 -0
  326. package/test/cartesian/ReferenceLine/ReferenceLine.panorama.spec.tsx +184 -0
  327. package/test/cartesian/ReferenceLine/ReferenceLine.spec.tsx +744 -0
  328. package/test/cartesian/ReferenceLine/ReferenceLine.typed.spec.tsx +74 -0
  329. package/test/cartesian/ReferenceLine/getEndPoints.spec.ts +399 -0
  330. package/test/cartesian/ReferenceLine.render.spec.tsx +134 -0
  331. package/test/cartesian/Scatter.animation.spec.tsx +381 -0
  332. package/test/cartesian/Scatter.render.spec.tsx +61 -0
  333. package/test/cartesian/Scatter.spec.tsx +406 -0
  334. package/test/cartesian/Scatter.typed.spec.tsx +153 -0
  335. package/test/cartesian/XAxis/XAxis.barSize.spec.tsx +336 -0
  336. package/test/cartesian/XAxis/XAxis.brush.spec.tsx +266 -0
  337. package/test/cartesian/XAxis/XAxis.categorydomain.spec.tsx +872 -0
  338. package/test/cartesian/XAxis/XAxis.dataKey.spec.tsx +86 -0
  339. package/test/cartesian/XAxis/XAxis.datatypes.spec.tsx +127 -0
  340. package/test/cartesian/XAxis/XAxis.hide.spec.tsx +106 -0
  341. package/test/cartesian/XAxis/XAxis.multiaxis.spec.tsx +336 -0
  342. package/test/cartesian/XAxis/XAxis.numberdomain.spec.tsx +1466 -0
  343. package/test/cartesian/XAxis/XAxis.padding.spec.tsx +758 -0
  344. package/test/cartesian/XAxis/XAxis.padding_clip.spec.tsx +65 -0
  345. package/test/cartesian/XAxis/XAxis.state.spec.tsx +355 -0
  346. package/test/cartesian/XAxis/XAxis.tick.spec.tsx +493 -0
  347. package/test/cartesian/XAxis/XAxis.timescale.spec.tsx +233 -0
  348. package/test/cartesian/XAxis/XAxis.type.spec.tsx +107 -0
  349. package/test/cartesian/XAxis/XAxis.typed.spec.tsx +102 -0
  350. package/test/cartesian/XAxis/XAxis.vertical.spec.tsx +265 -0
  351. package/test/cartesian/XAxis.tickFormatter.spec.tsx +54 -0
  352. package/test/cartesian/YAxis/YAxis.7362.derivedDomain.spec.tsx +230 -0
  353. package/test/cartesian/YAxis/YAxis.7362.spec.tsx +104 -0
  354. package/test/cartesian/YAxis/YAxis.interval-zero.spec.tsx +88 -0
  355. package/test/cartesian/YAxis/YAxis.label.spec.tsx +219 -0
  356. package/test/cartesian/YAxis/YAxis.spec.tsx +1595 -0
  357. package/test/cartesian/YAxis/YAxis.tick.spec.tsx +428 -0
  358. package/test/cartesian/YAxis/YAxis.tickFormatter.spec.tsx +54 -0
  359. package/test/cartesian/YAxis/YAxis.ticks.spec.tsx +263 -0
  360. package/test/cartesian/YAxis/YAxis.type.spec.tsx +107 -0
  361. package/test/cartesian/YAxis/YAxis.typed.spec.tsx +102 -0
  362. package/test/cartesian/ZAxis.spec.tsx +300 -0
  363. package/test/cartesian/ZAxis.typed.spec.tsx +33 -0
  364. package/test/cartesian/__snapshots__/Brush.spec.tsx.snap +5 -0
  365. package/test/cartesian/axisLineAndStroke.spec.tsx +72 -0
  366. package/test/cartesian/getCartesianPosition.spec.ts +907 -0
  367. package/test/cartesian/getEquidistantTicks.spec.ts +88 -0
  368. package/test/cartesian/getTicks.spec.ts +378 -0
  369. package/test/cartesian/miscFeatureGaps.spec.tsx +89 -0
  370. package/test/cartesian/useAnimatedLineLength.spec.ts +168 -0
  371. package/test/chart/AccessibilityLayer.spec.tsx +569 -0
  372. package/test/chart/AccessibilityScans.spec.tsx +286 -0
  373. package/test/chart/AreaChart.spec.tsx +409 -0
  374. package/test/chart/AreaChart.stacked.spec.tsx +1407 -0
  375. package/test/chart/AreaChart.typed.spec.tsx +39 -0
  376. package/test/chart/BarChart.spec.tsx +3719 -0
  377. package/test/chart/BarChart.typed.spec.tsx +60 -0
  378. package/test/chart/CategoricalChart.spec.tsx +255 -0
  379. package/test/chart/ComposedChart.spec.tsx +199 -0
  380. package/test/chart/ComposedChart.typed.spec.tsx +39 -0
  381. package/test/chart/FunnelChart.spec.tsx +215 -0
  382. package/test/chart/FunnelChart.typed.spec.tsx +39 -0
  383. package/test/chart/LineChart.multiseries.spec.tsx +50 -0
  384. package/test/chart/LineChart.smoke.spec.tsx +50 -0
  385. package/test/chart/LineChart.spec.tsx +930 -0
  386. package/test/chart/LineChart.typed.spec.tsx +39 -0
  387. package/test/chart/NicheChartTooltip.spec.tsx +81 -0
  388. package/test/chart/PieChart.spec.tsx +793 -0
  389. package/test/chart/PieChart.typed.spec.tsx +39 -0
  390. package/test/chart/RadarChart.spec.tsx +530 -0
  391. package/test/chart/RadarChart.typed.spec.tsx +39 -0
  392. package/test/chart/RadialBarChart.5966.spec.tsx +48 -0
  393. package/test/chart/RadialBarChart.spec.tsx +679 -0
  394. package/test/chart/RadialBarChart.typed.spec.tsx +39 -0
  395. package/test/chart/RechartsWrapper.spec.tsx +83 -0
  396. package/test/chart/Sankey.content.spec.tsx +46 -0
  397. package/test/chart/Sankey.spec.tsx +952 -0
  398. package/test/chart/Sankey.typed.spec.tsx +29 -0
  399. package/test/chart/ScatterChart.spec.tsx +2613 -0
  400. package/test/chart/ScatterChart.typed.spec.tsx +39 -0
  401. package/test/chart/SunburstChart.spec.tsx +146 -0
  402. package/test/chart/Treemap.animation.spec.tsx +52 -0
  403. package/test/chart/Treemap.spec.tsx +1003 -0
  404. package/test/chart/Treemap.typed.spec.tsx +26 -0
  405. package/test/chart/chartEvents.spec.tsx +127 -0
  406. package/test/chart/responsive.spec.tsx +620 -0
  407. package/test/component/Cell.render.spec.tsx +155 -0
  408. package/test/component/Cell.spec.tsx +12 -0
  409. package/test/component/Cursor.spec.tsx +186 -0
  410. package/test/component/DefaultTooltipContent.spec.tsx +102 -0
  411. package/test/component/Label.render.spec.tsx +63 -0
  412. package/test/component/Label.spec.tsx +686 -0
  413. package/test/component/Label.typed.spec.tsx +46 -0
  414. package/test/component/LabelList.spec.tsx +188 -0
  415. package/test/component/Legend.itemSorter.spec.tsx +704 -0
  416. package/test/component/Legend.render.spec.tsx +92 -0
  417. package/test/component/Legend.spec.tsx +2213 -0
  418. package/test/component/Legend.typed.spec.tsx +22 -0
  419. package/test/component/ResponsiveContainer.spec.tsx +523 -0
  420. package/test/component/ResponsiveContainerDataTest.spec.tsx +51 -0
  421. package/test/component/Text.spec.tsx +415 -0
  422. package/test/component/Text.typed.spec.tsx +46 -0
  423. package/test/component/Tooltip/ActiveDot.spec.tsx +370 -0
  424. package/test/component/Tooltip/Tooltip.animation.spec.tsx +209 -0
  425. package/test/component/Tooltip/Tooltip.content.spec.tsx +128 -0
  426. package/test/component/Tooltip/Tooltip.formatter.spec.tsx +152 -0
  427. package/test/component/Tooltip/Tooltip.includeHidden.spec.tsx +79 -0
  428. package/test/component/Tooltip/Tooltip.multipleDataArrays.spec.tsx +165 -0
  429. package/test/component/Tooltip/Tooltip.offset.spec.tsx +113 -0
  430. package/test/component/Tooltip/Tooltip.state.spec.tsx +74 -0
  431. package/test/component/Tooltip/Tooltip.sync.spec.tsx +639 -0
  432. package/test/component/Tooltip/defaultIndex.spec.tsx +227 -0
  433. package/test/component/Tooltip/graphicalItem.formatter.spec.tsx +138 -0
  434. package/test/component/Tooltip/itemSorter.spec.tsx +2815 -0
  435. package/test/component/Tooltip/tooltipEventType.spec.tsx +344 -0
  436. package/test/component/Tooltip/tooltipMouseHoverSelectors.ts +41 -0
  437. package/test/component/Tooltip/tooltipTestHelpers.tsx +162 -0
  438. package/test/component/Tooltip.defaultIndex.spec.tsx +48 -0
  439. package/test/component/Tooltip.hover.spec.tsx +61 -0
  440. package/test/component/Tooltip.item.spec.tsx +54 -0
  441. package/test/component/Tooltip.keyboard.spec.tsx +51 -0
  442. package/test/component/Tooltip.payload.spec.tsx +1716 -0
  443. package/test/component/Tooltip.touch.spec.tsx +39 -0
  444. package/test/component/Tooltip.visibility.spec.tsx +1889 -0
  445. package/test/component/TooltipBoundingBox.spec.tsx +89 -0
  446. package/test/component/responsiveContainerUtils.spec.ts +205 -0
  447. package/test/container/ClipPath.spec.tsx +602 -0
  448. package/test/container/chartDimensions.spec.tsx +368 -0
  449. package/test/context/chartLayoutContext.spec.tsx +378 -0
  450. package/test/helper/ExpectAxisDomain.tsx +27 -0
  451. package/test/helper/assertNotNull.ts +6 -0
  452. package/test/helper/assertZIndexLayerOrder.ts +19 -0
  453. package/test/helper/createSelectorTestCase.tsx +176 -0
  454. package/test/helper/expectAnimatedPieAngles.ts +100 -0
  455. package/test/helper/expectAnimatedPiePaths.ts +78 -0
  456. package/test/helper/expectAreaCurve.ts +15 -0
  457. package/test/helper/expectAxisTicks.ts +48 -0
  458. package/test/helper/expectBars.ts +54 -0
  459. package/test/helper/expectFunctionReturning.ts +58 -0
  460. package/test/helper/expectLabel.ts +32 -0
  461. package/test/helper/expectLastCalledWith.ts +48 -0
  462. package/test/helper/expectLine.ts +20 -0
  463. package/test/helper/expectPieSectors.ts +80 -0
  464. package/test/helper/expectScale.ts +37 -0
  465. package/test/helper/expectScatterPoints.ts +52 -0
  466. package/test/helper/expectStackGroups.ts +144 -0
  467. package/test/helper/mockAxes.ts +22 -0
  468. package/test/helper/mockGetBoundingClientRect.ts +66 -0
  469. package/test/helper/mockHTMLElementProperty.ts +19 -0
  470. package/test/helper/mockTouchingElement.ts +27 -0
  471. package/test/helper/offsetHelpers.ts +19 -0
  472. package/test/helper/parameterizedTestCases.tsx +99 -0
  473. package/test/helper/produceState.ts +32 -0
  474. package/test/helper/render.ts +7 -0
  475. package/test/helper/selectorTestHelpers.tsx +63 -0
  476. package/test/helper/trim.spec.ts +35 -0
  477. package/test/helper/trim.ts +11 -0
  478. package/test/hooks/useActiveTooltipDataPoints.spec.tsx +358 -0
  479. package/test/hooks/useAxisDomain.spec.tsx +361 -0
  480. package/test/hooks/useAxisScale.spec.tsx +283 -0
  481. package/test/hooks/useAxisTicks.spec.tsx +130 -0
  482. package/test/hooks/useOffset.spec.tsx +248 -0
  483. package/test/hooks/useTooltipStateHooks.spec.tsx +109 -0
  484. package/test/polar/Pie/Pie-TwoLevelPieChart.spec.tsx +135 -0
  485. package/test/polar/Pie/Pie.spec.tsx +784 -0
  486. package/test/polar/Pie/Pie.typed.spec.tsx +78 -0
  487. package/test/polar/Pie.animation.spec.tsx +529 -0
  488. package/test/polar/PieWithLegend.animation.spec.tsx +142 -0
  489. package/test/polar/PolarAngleAxis/PolarAngleAxis.events.spec.tsx +76 -0
  490. package/test/polar/PolarAngleAxis/PolarAngleAxis.spec.tsx +2079 -0
  491. package/test/polar/PolarAngleAxis/PolarAngleAxis.typed.spec.tsx +102 -0
  492. package/test/polar/PolarAngleAxis.render.spec.tsx +79 -0
  493. package/test/polar/PolarGrid.render.spec.tsx +75 -0
  494. package/test/polar/PolarGrid.spec.tsx +918 -0
  495. package/test/polar/PolarLegendPerRow.render.spec.tsx +85 -0
  496. package/test/polar/PolarRadiusAxis.events.spec.tsx +65 -0
  497. package/test/polar/PolarRadiusAxis.render.spec.tsx +52 -0
  498. package/test/polar/PolarRadiusAxis.spec.tsx +991 -0
  499. package/test/polar/PolarRadiusAxis.typed.spec.tsx +84 -0
  500. package/test/polar/PolarTooltipLegend.render.spec.tsx +80 -0
  501. package/test/polar/Radar.animation.spec.tsx +570 -0
  502. package/test/polar/Radar.render.spec.tsx +71 -0
  503. package/test/polar/Radar.spec.tsx +265 -0
  504. package/test/polar/Radar.typed.spec.tsx +119 -0
  505. package/test/polar/RadialBar/RadialBar.spec.tsx +1521 -0
  506. package/test/polar/RadialBar/RadialBar.typed.spec.tsx +132 -0
  507. package/test/polar/RadialBar.animation.spec.tsx +375 -0
  508. package/test/polar/RadialBar.render.spec.tsx +66 -0
  509. package/test/polar/RadialBar.stacked.spec.tsx +57 -0
  510. package/test/setup.ts +84 -0
  511. package/test/shape/ActiveShape.spec.tsx +181 -0
  512. package/test/shape/Cross.spec.tsx +60 -0
  513. package/test/shape/Cross.typed.spec.tsx +26 -0
  514. package/test/shape/Curve.spec.tsx +368 -0
  515. package/test/shape/Curve.typed.spec.tsx +69 -0
  516. package/test/shape/Dot.spec.tsx +73 -0
  517. package/test/shape/Dot.typed.spec.tsx +30 -0
  518. package/test/shape/Polygon.spec.tsx +357 -0
  519. package/test/shape/Polygon.typed.spec.tsx +28 -0
  520. package/test/shape/Rectangle.animation.spec.tsx +451 -0
  521. package/test/shape/Rectangle.spec.tsx +68 -0
  522. package/test/shape/Rectangle.typed.spec.tsx +24 -0
  523. package/test/shape/Sector.spec.tsx +76 -0
  524. package/test/shape/Sector.typed.spec.tsx +24 -0
  525. package/test/shape/Symbols.spec.tsx +43 -0
  526. package/test/shape/Symbols.typed.spec.tsx +24 -0
  527. package/test/shape/Trapezoid.spec.tsx +50 -0
  528. package/test/shape/Trapezoid.typed.spec.tsx +24 -0
  529. package/test/shape/__snapshots__/Cross.spec.tsx.snap +62 -0
  530. package/test/shape/__snapshots__/Curve.spec.tsx.snap +460 -0
  531. package/test/shape/__snapshots__/Polygon.spec.tsx.snap +58 -0
  532. package/test/shape/__snapshots__/Rectangle.spec.tsx.snap +117 -0
  533. package/test/shape/__snapshots__/Sector.spec.tsx.snap +71 -0
  534. package/test/shape/__snapshots__/Trapezoid.spec.tsx.snap +64 -0
  535. package/test/state/chartDataSlice.spec.ts +53 -0
  536. package/test/state/externalEventsMiddleware.spec.ts +178 -0
  537. package/test/state/graphicalItemsSlice.spec.ts +92 -0
  538. package/test/state/hooks.spec.tsx +68 -0
  539. package/test/state/legendSlice.spec.ts +44 -0
  540. package/test/state/mouseEventsMiddleware.spec.ts +75 -0
  541. package/test/state/optionsSlice.spec.ts +19 -0
  542. package/test/state/reduxDevtoolsJsonStringifyReplacer.spec.ts +25 -0
  543. package/test/state/referenceElementsSlice.spec.ts +84 -0
  544. package/test/state/selectors/areaSelectors.spec.tsx +77 -0
  545. package/test/state/selectors/axisSelectors.spec.tsx +1418 -0
  546. package/test/state/selectors/barStackSelectors.spec.tsx +752 -0
  547. package/test/state/selectors/brushSelectors.spec.tsx +30 -0
  548. package/test/state/selectors/cartesianAxisSlice.spec.ts +96 -0
  549. package/test/state/selectors/combineNiceTicks.spec.ts +207 -0
  550. package/test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts +61 -0
  551. package/test/state/selectors/combiners/combineAllBarPositions.spec.ts +39 -0
  552. package/test/state/selectors/combiners/combineConfiguredScale.spec.ts +56 -0
  553. package/test/state/selectors/combiners/combineDisplayedStackedData.spec.ts +123 -0
  554. package/test/state/selectors/combiners/combineRealScaleType.spec.ts +80 -0
  555. package/test/state/selectors/containerSelectors.spec.tsx +168 -0
  556. package/test/state/selectors/dataSelectors.spec.tsx +136 -0
  557. package/test/state/selectors/legendSelectors.spec.tsx +113 -0
  558. package/test/state/selectors/lineSelectors.spec.tsx +60 -0
  559. package/test/state/selectors/pieSelectors.spec.tsx +72 -0
  560. package/test/state/selectors/radarSelectors.spec.tsx +496 -0
  561. package/test/state/selectors/rootPropsSelectors.spec.tsx +169 -0
  562. package/test/state/selectors/scatterSelectors.spec.tsx +47 -0
  563. package/test/state/selectors/selectActiveTooltipIndex.spec.tsx +234 -0
  564. package/test/state/selectors/selectAllAxes.spec.tsx +18 -0
  565. package/test/state/selectors/selectAxisDomain.spec.tsx +21 -0
  566. package/test/state/selectors/selectAxisDomainIncludingNiceTicks.spec.tsx +19 -0
  567. package/test/state/selectors/selectAxisRangeWithReverse.spec.tsx +22 -0
  568. package/test/state/selectors/selectAxisScale.spec.tsx +91 -0
  569. package/test/state/selectors/selectBarRectangles.stackOffset.spec.tsx +503 -0
  570. package/test/state/selectors/selectBaseAxis.spec.tsx +56 -0
  571. package/test/state/selectors/selectCartesianItemsSettings.spec.tsx +57 -0
  572. package/test/state/selectors/selectChartOffset.spec.tsx +26 -0
  573. package/test/state/selectors/selectDisplayedData.spec.tsx +282 -0
  574. package/test/state/selectors/selectIsTooltipActive.spec.tsx +231 -0
  575. package/test/state/selectors/selectNumericalDomain.spec.tsx +21 -0
  576. package/test/state/selectors/selectRealScaleType.spec.tsx +19 -0
  577. package/test/state/selectors/selectStackGroups.spec.tsx +322 -0
  578. package/test/state/selectors/selectXAxisPosition.spec.tsx +22 -0
  579. package/test/state/selectors/selectYAxisPosition.spec.tsx +22 -0
  580. package/test/state/selectors/selectors.spec.tsx +1613 -0
  581. package/test/state/throttling.spec.ts +200 -0
  582. package/test/state/zIndexSlice.spec.ts +85 -0
  583. package/test/synchronisation/useChartSynchronisation.spec.tsx +225 -0
  584. package/test/util/BarUtils.spec.ts +39 -0
  585. package/test/util/CartesianUtils/CartesianUtils.spec.ts +261 -0
  586. package/test/util/CartesianUtils/rectWithPoints.spec.ts +48 -0
  587. package/test/util/ChartUtils/ChartUtils.spec.ts +491 -0
  588. package/test/util/ChartUtils/appendOffsetOfLegend.spec.ts +136 -0
  589. package/test/util/ChartUtils/appendOffsetOfLegend.spec.tsx +133 -0
  590. package/test/util/ChartUtils/getCateCoordinateOfLine.spec.ts +83 -0
  591. package/test/util/ChartUtils/getStackedData.spec.ts +416 -0
  592. package/test/util/ChartUtils/truncateByDomain.spec.ts +70 -0
  593. package/test/util/DataUtils.spec.ts +385 -0
  594. package/test/util/DomUtils.spec.tsx +117 -0
  595. package/test/util/FunnelUtils.spec.tsx +70 -0
  596. package/test/util/Global.spec.ts +11 -0
  597. package/test/util/LRUCache.spec.ts +81 -0
  598. package/test/util/LogUtils.spec.ts +45 -0
  599. package/test/util/PolarUtils.spec.ts +66 -0
  600. package/test/util/ReduceCssCalcPrototype.spec.ts +141 -0
  601. package/test/util/ShallowEqual.spec.ts +102 -0
  602. package/test/util/TickUtils.spec.ts +29 -0
  603. package/test/util/axisPropsAreEqual.spec.ts +93 -0
  604. package/test/util/createChartHelpers.spec.tsx +210 -0
  605. package/test/util/cursor/getCursorPoints.spec.ts +136 -0
  606. package/test/util/cursor/getCursorRectangle.spec.ts +50 -0
  607. package/test/util/cursor/getRadialCursorPoints.spec.ts +36 -0
  608. package/test/util/errorValue.spec.ts +69 -0
  609. package/test/util/getEveryNth.spec.ts +39 -0
  610. package/test/util/getRadiusAndStrokeWidthFromDot.spec.ts +51 -0
  611. package/test/util/getRelativeCoordinate.spec.ts +250 -0
  612. package/test/util/getSliced.spec.ts +45 -0
  613. package/test/util/isDomainSpecifiedByUser.spec.ts +207 -0
  614. package/test/util/isWellBehavedNumber.spec.ts +54 -0
  615. package/test/util/payload/getUniqPayload.spec.ts +56 -0
  616. package/test/util/propsAreEqual.spec.ts +75 -0
  617. package/test/util/round.spec.ts +112 -0
  618. package/test/util/scale/arithmetic.spec.ts +61 -0
  619. package/test/util/scale/createCategoricalInverse.spec.ts +84 -0
  620. package/test/util/scale/getNiceTickValues.spec.ts +421 -0
  621. package/test/util/scale/getTickValuesFixedDomain.spec.ts +155 -0
  622. package/test/util/svgPropertiesAndEvents.spec.tsx +206 -0
  623. package/test/util/svgPropertiesNoEvents.spec.tsx +228 -0
  624. package/test/util/tooltip/translate.spec.ts +396 -0
  625. package/test/util/useAnimationId.spec.tsx +59 -0
  626. package/test/util/useElementOffset.spec.tsx +173 -0
  627. package/test/util/usePrefersReducedMotion.spec.ts +54 -0
  628. package/test/util/useUniqueId.spec.ts +99 -0
  629. package/test/utils/diagnostics-allowlist.ts +18 -0
  630. package/test/utils/diagnostics.ts +58 -0
  631. package/test/zIndex/AllZIndexPortals.spec.tsx +83 -0
  632. package/test/zIndex/DefaultZIndexes.spec.ts +80 -0
  633. package/test/zIndex/DynamicZIndex.spec.tsx +102 -0
  634. package/test/zIndex/ZIndexLayer.portalOwner.spec.tsx +125 -0
  635. package/test/zIndex/componentZIndex.spec.tsx +255 -0
  636. package/test/zIndex/getZIndexFromUnknown.spec.ts +51 -0
  637. package/test/zIndex/multiChartZIndexIsolation.spec.tsx +90 -0
  638. package/test/zIndex/zIndexSelectors.spec.ts +172 -0
  639. package/tsconfig.json +11 -0
@@ -0,0 +1,2196 @@
1
+ // Ported from recharts 3.8.1 src/state/selectors/axisSelectors.ts (commit 7a23854).
2
+ //
3
+ // This is the scale spine every cartesian graphical item depends on: it turns
4
+ // registered axis settings + data into a domain, a scale function, and ticks.
5
+ //
6
+ // SOLID-NATIVE: recharts composes these with reselect `createSelector`; here they
7
+ // are plain functions composing other plain functions — memoization comes from
8
+ // `useAppSelector`'s `createMemo` at the consumer. Behavior is identical.
9
+ //
10
+ // SCOPE: this port covers the path needed to draw a <Line> from a <LineChart data>
11
+ // (category/number cartesian axes, point/band/linear scales). Branches that need
12
+ // not-yet-ported slices are stubbed with a clear marker and a behavior note:
13
+ // - stacks (stackGroups) → selectDomainOfStackGroups returns undefined
14
+ // - error bars (errorBarSlice) → selectAllErrorBarSettings returns {}
15
+ // - Brush panorama range → selectX/YAxisRange returns undefined when isPanorama
16
+ // - polar axes (angle/radius) → selectBaseAxis throws for them
17
+ // Each stub is the correct value for a chart that doesn't use that feature, so the
18
+ // non-stacked, no-error-bar, no-Brush <Line> path is exact.
19
+ // PORTED: reference elements (selectReferenceElementsDomain + the dots/lines/areas
20
+ // ByAxis selectors + combine*Domain) extend the numerical domain for
21
+ // ifOverflow='extendDomain' elements (referenceElementsSlice is wired in).
22
+ import { range } from "../../util/collectionUtils";
23
+ import { selectChartLayout } from "../../context/chartLayoutContext";
24
+ import {
25
+ getDomainOfStackGroups,
26
+ getStackedData,
27
+ getValueByDataKey,
28
+ isCategoricalAxis,
29
+ type StackId,
30
+ } from "../../util/ChartUtils";
31
+ import { type DefinitelyStackedGraphicalItem, isStacked } from "../types/StackedGraphicalItem";
32
+ import type { ErrorBarsSettings, ErrorBarsState } from "../errorBarSlice";
33
+ import { type AllStackGroups, type StackGroup } from "../../util/stacks/stackTypes";
34
+ import { getStackSeriesIdentifier } from "../../util/stacks/getStackSeriesIdentifier";
35
+ import {
36
+ combineDisplayedStackedData,
37
+ type DisplayedStackedData,
38
+ } from "./combiners/combineDisplayedStackedData";
39
+ import {
40
+ AxisDomain,
41
+ AxisTick,
42
+ AxisType,
43
+ CartesianTickItem,
44
+ CategoricalDomain,
45
+ CategoricalDomainItem,
46
+ ChartOffsetInternal,
47
+ Coordinate,
48
+ LayoutType,
49
+ NumberDomain,
50
+ RechartsScaleType,
51
+ Size,
52
+ StackOffsetType,
53
+ TickItem,
54
+ } from "../../util/types";
55
+ import {
56
+ AxisId,
57
+ BaseCartesianAxis,
58
+ CartesianAxisSettings,
59
+ XAxisOrientation,
60
+ XAxisSettings,
61
+ YAxisOrientation,
62
+ YAxisSettings,
63
+ ZAxisSettings,
64
+ } from "../cartesianAxisSlice";
65
+ import { AngleAxisSettings, RadiusAxisSettings } from "../polarAxisSlice";
66
+ import { RechartsRootState } from "../store";
67
+ import { CartesianGraphicalItemSettings } from "../graphicalItemsSlice";
68
+ import type { GraphicalItemSettings } from "../graphicalItemsSlice";
69
+ import {
70
+ selectChartDataWithIndexes,
71
+ selectChartDataWithIndexesIfNotInPanoramaPosition4,
72
+ selectChartDataSliceIfNotInPanorama,
73
+ } from "./dataSelectors";
74
+ import {
75
+ isWellFormedNumberDomain,
76
+ numericalDomainSpecifiedWithoutRequiringData,
77
+ parseNumericalUserDomain,
78
+ } from "../../util/isDomainSpecifiedByUser";
79
+ import { AppliedChartData, ChartData, ChartDataState } from "../chartDataSlice";
80
+ import {
81
+ getPercentValue,
82
+ hasDuplicate,
83
+ isNan,
84
+ isNotNil,
85
+ isNumOrStr,
86
+ mathSign,
87
+ } from "../../util/DataUtils";
88
+ import { selectChartHeight, selectChartWidth } from "./containerSelectors";
89
+ import { selectAllXAxes, selectAllYAxes } from "./selectAllAxes";
90
+ import { pickAxisType } from "./pickAxisType";
91
+ import { isWellBehavedNumber } from "../../util/isWellBehavedNumber";
92
+ import { getNiceTickValues, getTickValuesFixedDomain } from "../../util/scale";
93
+ import { selectChartOffsetInternal } from "./selectChartOffsetInternal";
94
+ import { selectBrushDimensions } from "./brushSelectors";
95
+ import { combineAxisRangeWithReverse } from "./combiners/combineAxisRangeWithReverse";
96
+ import { DEFAULT_Y_AXIS_WIDTH } from "../../util/Constants";
97
+ import { RechartsScale, rechartsScaleFactory } from "../../util/scale/RechartsScale";
98
+ import { combineCheckedDomain } from "./combiners/combineCheckedDomain";
99
+ import { CustomScaleDefinition } from "../../util/scale/CustomScaleDefinition";
100
+ import { combineConfiguredScale } from "./combiners/combineConfiguredScale";
101
+ import { combineInverseScaleFunction } from "./combiners/combineInverseScaleFunction";
102
+ import type { InverseScaleFunction } from "../../hooks";
103
+ import { combineRealScaleType } from "./combiners/combineRealScaleType";
104
+ import { AllAxisTypes, RenderableAxisType, selectTooltipAxisType } from "./selectTooltipAxisType";
105
+ // Polar axis selectors — value-import cycle with this module (polarAxisSelectors
106
+ // imports AxisRange + combineAxisRangeWithReverse back), resolved lazily at call
107
+ // time, the same shape recharts uses.
108
+ import {
109
+ selectAngleAxis,
110
+ selectAngleAxisRange,
111
+ selectRadiusAxis,
112
+ selectRadiusAxisRange,
113
+ } from "./polarAxisSelectors";
114
+ import {
115
+ selectBarCategoryGap,
116
+ selectChartName,
117
+ selectReverseStackOrder,
118
+ selectStackOffsetType,
119
+ } from "./rootPropsSelectors";
120
+ import { selectTooltipAxisId } from "./selectTooltipAxisId";
121
+ import type {
122
+ ReferenceAreaSettings,
123
+ ReferenceDotSettings,
124
+ ReferenceElementSettings,
125
+ ReferenceLineSettings,
126
+ } from "../referenceElementsSlice";
127
+
128
+ /**
129
+ * A pixel range `[start, end]` an axis maps its domain onto. Lives here in
130
+ * recharts too; consumers (e.g. ZAxisSettings) import it from this module.
131
+ */
132
+ export type AxisRange = readonly [number, number];
133
+
134
+ /**
135
+ * A {@link BaseCartesianAxis} after its scale has been constructed: the external
136
+ * `scale` definition (string/custom) is replaced with a concrete
137
+ * {@link RechartsScale}. Consumers (ChartUtils band/coordinate helpers) import
138
+ * it from this module, matching the reference.
139
+ */
140
+ export type BaseAxisWithScale = Omit<BaseCartesianAxis, "scale"> & { scale: RechartsScale };
141
+
142
+ export const defaultNumericDomain: AxisDomain = [0, "auto"];
143
+
144
+ export type RenderableAxisSettings =
145
+ | XAxisSettings
146
+ | YAxisSettings
147
+ | AngleAxisSettings
148
+ | RadiusAxisSettings;
149
+ export type AllAxisSettings =
150
+ | XAxisSettings
151
+ | YAxisSettings
152
+ | ZAxisSettings
153
+ | AngleAxisSettings
154
+ | RadiusAxisSettings;
155
+
156
+ /**
157
+ * All registered cartesian graphical items, before any axis/hide filtering.
158
+ */
159
+ export const selectUnfilteredCartesianItems = (
160
+ state: RechartsRootState,
161
+ ): ReadonlyArray<CartesianGraphicalItemSettings> => state.graphicalItems.cartesianItems;
162
+
163
+ /**
164
+ * If an axis is not explicitly defined as an element, we still need something to
165
+ * hold the domain and default settings.
166
+ */
167
+ export const implicitXAxis: XAxisSettings = {
168
+ allowDataOverflow: false,
169
+ allowDecimals: true,
170
+ allowDuplicatedCategory: true,
171
+ angle: 0,
172
+ dataKey: undefined,
173
+ domain: undefined,
174
+ height: 30,
175
+ hide: true,
176
+ id: 0,
177
+ includeHidden: false,
178
+ interval: "preserveEnd",
179
+ minTickGap: 5,
180
+ mirror: false,
181
+ name: undefined,
182
+ orientation: "bottom",
183
+ padding: { left: 0, right: 0 },
184
+ reversed: false,
185
+ scale: "auto",
186
+ tick: true,
187
+ tickCount: 5,
188
+ tickFormatter: undefined,
189
+ ticks: undefined,
190
+ type: "category",
191
+ unit: undefined,
192
+ niceTicks: "auto",
193
+ };
194
+
195
+ export const selectXAxisSettingsNoDefaults = (
196
+ state: RechartsRootState,
197
+ axisId: AxisId,
198
+ ): XAxisSettings | undefined => state.cartesianAxis.xAxis[axisId];
199
+
200
+ export const selectXAxisSettings = (state: RechartsRootState, axisId: AxisId): XAxisSettings => {
201
+ const axis = selectXAxisSettingsNoDefaults(state, axisId);
202
+ if (axis == null) {
203
+ return implicitXAxis;
204
+ }
205
+ return axis;
206
+ };
207
+
208
+ export const implicitYAxis: YAxisSettings = {
209
+ allowDataOverflow: false,
210
+ allowDecimals: true,
211
+ allowDuplicatedCategory: true,
212
+ angle: 0,
213
+ dataKey: undefined,
214
+ domain: defaultNumericDomain,
215
+ hide: true,
216
+ id: 0,
217
+ includeHidden: false,
218
+ interval: "preserveEnd",
219
+ minTickGap: 5,
220
+ mirror: false,
221
+ name: undefined,
222
+ orientation: "left",
223
+ padding: { top: 0, bottom: 0 },
224
+ reversed: false,
225
+ scale: "auto",
226
+ tick: true,
227
+ tickCount: 5,
228
+ tickFormatter: undefined,
229
+ ticks: undefined,
230
+ type: "number",
231
+ unit: undefined,
232
+ niceTicks: "auto",
233
+ width: DEFAULT_Y_AXIS_WIDTH,
234
+ };
235
+
236
+ export const selectYAxisSettingsNoDefaults = (
237
+ state: RechartsRootState,
238
+ axisId: AxisId,
239
+ ): YAxisSettings | undefined => state.cartesianAxis.yAxis[axisId];
240
+
241
+ export const selectYAxisSettings = (state: RechartsRootState, axisId: AxisId): YAxisSettings => {
242
+ const axis = selectYAxisSettingsNoDefaults(state, axisId);
243
+ if (axis == null) {
244
+ return implicitYAxis;
245
+ }
246
+ return axis;
247
+ };
248
+
249
+ export const implicitZAxis: ZAxisSettings = {
250
+ domain: [0, "auto"],
251
+ includeHidden: false,
252
+ reversed: false,
253
+ allowDataOverflow: false,
254
+ allowDuplicatedCategory: false,
255
+ dataKey: undefined,
256
+ id: 0,
257
+ name: "",
258
+ range: [64, 64],
259
+ scale: "auto",
260
+ type: "number",
261
+ unit: "",
262
+ };
263
+
264
+ export const selectZAxisSettings = (state: RechartsRootState, axisId: AxisId): ZAxisSettings => {
265
+ const axis = state.cartesianAxis.zAxis[axisId];
266
+ if (axis == null) {
267
+ return implicitZAxis;
268
+ }
269
+ return axis;
270
+ };
271
+
272
+ export const selectBaseAxis = (
273
+ state: RechartsRootState,
274
+ axisType: AllAxisTypes,
275
+ axisId: AxisId,
276
+ ): AllAxisSettings => {
277
+ switch (axisType) {
278
+ case "xAxis":
279
+ return selectXAxisSettings(state, axisId);
280
+ case "yAxis":
281
+ return selectYAxisSettings(state, axisId);
282
+ case "zAxis":
283
+ return selectZAxisSettings(state, axisId);
284
+ case "angleAxis":
285
+ return selectAngleAxis(state, axisId);
286
+ case "radiusAxis":
287
+ return selectRadiusAxis(state, axisId);
288
+ default:
289
+ // Exhaustive: all axis types handled above, so `axisType` is `never` here.
290
+ throw new Error(`Unexpected axis type: ${String(axisType)}`);
291
+ }
292
+ };
293
+
294
+ /**
295
+ * Selects an X or Y axis (with implicit defaults). Z, angle and radius axes are
296
+ * handled by {@link selectBaseAxis} / the polar vertical.
297
+ */
298
+ export const selectRenderableAxisSettings = (
299
+ state: RechartsRootState,
300
+ axisType: RenderableAxisType,
301
+ axisId: AxisId,
302
+ ): RenderableAxisSettings => {
303
+ switch (axisType) {
304
+ case "xAxis":
305
+ return selectXAxisSettings(state, axisId);
306
+ case "yAxis":
307
+ return selectYAxisSettings(state, axisId);
308
+ case "angleAxis":
309
+ return selectAngleAxis(state, axisId);
310
+ case "radiusAxis":
311
+ return selectRadiusAxis(state, axisId);
312
+ default:
313
+ // Exhaustive: all axis types handled above, so `axisType` is `never` here.
314
+ throw new Error(`Unexpected axis type: ${String(axisType)}`);
315
+ }
316
+ };
317
+
318
+ export const selectTooltipAxis = (state: RechartsRootState): RenderableAxisSettings =>
319
+ selectRenderableAxisSettings(state, selectTooltipAxisType(state), selectTooltipAxisId(state));
320
+
321
+ /**
322
+ * @return true if there is at least one Bar or RadialBar.
323
+ *
324
+ */
325
+ export const selectHasBar = (state: RechartsRootState): boolean =>
326
+ state.graphicalItems.cartesianItems.some((item) => item.type === "bar") ||
327
+ state.graphicalItems.polarItems.some((item) => item.type === "radialBar");
328
+
329
+ export type AxisDirection = "left-to-right" | "right-to-left" | "top-to-bottom" | "bottom-to-top";
330
+
331
+ /**
332
+ * The reading direction the keyboard tooltip navigation follows. Deviation:
333
+ * recharts derives this from selectAllXAxes/selectAllYAxes; the port reads the
334
+ * registered axis records directly (the implicit axis has `reversed: false`, so
335
+ * an empty record yields the default direction).
336
+ */
337
+ export const selectChartDirection = (state: RechartsRootState): AxisDirection | undefined => {
338
+ const layout = selectChartLayout(state);
339
+ switch (layout) {
340
+ case "horizontal":
341
+ return Object.values(state.cartesianAxis.xAxis).some((axis) => axis.reversed)
342
+ ? "right-to-left"
343
+ : "left-to-right";
344
+ case "vertical":
345
+ return Object.values(state.cartesianAxis.yAxis).some((axis) => axis.reversed)
346
+ ? "bottom-to-top"
347
+ : "top-to-bottom";
348
+ case "centric":
349
+ case "radial":
350
+ return "left-to-right";
351
+ default:
352
+ return undefined;
353
+ }
354
+ };
355
+
356
+ /**
357
+ * @returns predicate that returns true for graphical items relevant to the axis.
358
+ */
359
+ // An item that may carry any of the cartesian or polar axis ids; the `in`
360
+ // guards narrow per axis type (cartesian items lack angle/radius ids and vice
361
+ // versa, so the wrong-family branch returns false harmlessly).
362
+ type AnyAxisGraphicalItem = GraphicalItemSettings &
363
+ Partial<{
364
+ xAxisId: AxisId;
365
+ yAxisId: AxisId;
366
+ zAxisId: AxisId;
367
+ angleAxisId: AxisId;
368
+ radiusAxisId: AxisId;
369
+ }>;
370
+
371
+ export function itemAxisPredicate(axisType: AllAxisTypes, axisId: AxisId) {
372
+ return (item: AnyAxisGraphicalItem): boolean => {
373
+ switch (axisType) {
374
+ case "xAxis":
375
+ return "xAxisId" in item && item.xAxisId === axisId;
376
+ case "yAxis":
377
+ return "yAxisId" in item && item.yAxisId === axisId;
378
+ case "zAxis":
379
+ return "zAxisId" in item && item.zAxisId === axisId;
380
+ case "angleAxis":
381
+ return "angleAxisId" in item && item.angleAxisId === axisId;
382
+ case "radiusAxis":
383
+ return "radiusAxisId" in item && item.radiusAxisId === axisId;
384
+ default:
385
+ return false;
386
+ }
387
+ };
388
+ }
389
+
390
+ const selectAxisPredicate = (
391
+ _state: RechartsRootState,
392
+ axisType: AllAxisTypes,
393
+ axisId: AxisId,
394
+ ): ((item: CartesianGraphicalItemSettings) => boolean) => itemAxisPredicate(axisType, axisId);
395
+
396
+ export const combineGraphicalItemsSettings = <T extends GraphicalItemSettings>(
397
+ graphicalItems: ReadonlyArray<T>,
398
+ axisSettings: BaseCartesianAxis,
399
+ axisPredicate: (item: T) => boolean,
400
+ ): ReadonlyArray<T> =>
401
+ graphicalItems.filter(axisPredicate).filter((item) => {
402
+ if (axisSettings?.includeHidden === true) {
403
+ return true;
404
+ }
405
+ return !item.hide;
406
+ });
407
+
408
+ export const selectCartesianItemsSettings = (
409
+ state: RechartsRootState,
410
+ axisType: AllAxisTypes,
411
+ axisId: AxisId,
412
+ ): ReadonlyArray<CartesianGraphicalItemSettings> =>
413
+ combineGraphicalItemsSettings(
414
+ selectUnfilteredCartesianItems(state),
415
+ selectBaseAxis(state, axisType, axisId),
416
+ selectAxisPredicate(state, axisType, axisId),
417
+ );
418
+
419
+ export const filterGraphicalNotStackedItems = (
420
+ cartesianItems: ReadonlyArray<GraphicalItemSettings>,
421
+ ): ReadonlyArray<GraphicalItemSettings> =>
422
+ cartesianItems.filter((item) => !("stackId" in item) || item.stackId === undefined);
423
+
424
+ const selectCartesianItemsSettingsExceptStacked = (
425
+ state: RechartsRootState,
426
+ axisType: AllAxisTypes,
427
+ axisId: AxisId,
428
+ ): ReadonlyArray<GraphicalItemSettings> =>
429
+ filterGraphicalNotStackedItems(selectCartesianItemsSettings(state, axisType, axisId));
430
+
431
+ export const combineGraphicalItemsData = (
432
+ cartesianItems: ReadonlyArray<GraphicalItemSettings>,
433
+ ): ChartData =>
434
+ cartesianItems
435
+ .map((item) => item.data)
436
+ .filter(isNotNil)
437
+ .flat(1);
438
+
439
+ /**
440
+ * True if at least one graphical item relies on the chart-level data (no own
441
+ * `data` prop).
442
+ */
443
+ export const selectAnyCartesianItemsUsesChartData = (
444
+ state: RechartsRootState,
445
+ axisType: AllAxisTypes,
446
+ axisId: AxisId,
447
+ ): boolean => selectCartesianItemsSettings(state, axisType, axisId).some((item) => !item.data);
448
+
449
+ /**
450
+ * Data defined on the chart graphical items (Line/Scatter/etc.), filtered by axis.
451
+ */
452
+ export const selectCartesianGraphicalItemsData = (
453
+ state: RechartsRootState,
454
+ axisType: AllAxisTypes,
455
+ axisId: AxisId,
456
+ ): ChartData => combineGraphicalItemsData(selectCartesianItemsSettings(state, axisType, axisId));
457
+
458
+ export const combineDisplayedData = (
459
+ graphicalItemsData: ChartData,
460
+ { chartData = [], dataStartIndex, dataEndIndex }: ChartDataState,
461
+ ): ChartData => {
462
+ if (graphicalItemsData.length > 0) {
463
+ return graphicalItemsData;
464
+ }
465
+ return chartData.slice(dataStartIndex, dataEndIndex + 1);
466
+ };
467
+
468
+ /**
469
+ * All data in the chart (graphical items + chart root), useful for figuring out
470
+ * an axis domain. Discards original indexes, so not useful for ordering.
471
+ */
472
+ export const selectDisplayedData = (
473
+ state: RechartsRootState,
474
+ axisType: AllAxisTypes,
475
+ axisId: AxisId,
476
+ isPanorama: boolean,
477
+ ): ChartData =>
478
+ combineDisplayedData(
479
+ selectCartesianGraphicalItemsData(state, axisType, axisId),
480
+ selectChartDataWithIndexesIfNotInPanoramaPosition4(state, axisType, axisId, isPanorama),
481
+ );
482
+
483
+ export const combineAppliedValues = (
484
+ data: ChartData,
485
+ axisSettings: BaseCartesianAxis,
486
+ items: ReadonlyArray<GraphicalItemSettings>,
487
+ ): AppliedChartData => {
488
+ if (axisSettings?.dataKey != null) {
489
+ return data.map((item) => ({ value: getValueByDataKey(item, axisSettings.dataKey) }));
490
+ }
491
+ if (items.length > 0) {
492
+ return items
493
+ .map((item) => item.dataKey)
494
+ .flatMap((dataKey) => data.map((entry) => ({ value: getValueByDataKey(entry, dataKey) })));
495
+ }
496
+ return data.map((entry) => ({ value: entry }));
497
+ };
498
+
499
+ export const combineAllAppliedValues = (
500
+ displayedData: ChartData,
501
+ axisSettings: BaseCartesianAxis,
502
+ items: ReadonlyArray<GraphicalItemSettings>,
503
+ { chartData = [], dataStartIndex, dataEndIndex }: ChartDataState,
504
+ anyItemUsesChartData: boolean,
505
+ graphicalItemsData: ChartData,
506
+ ): AppliedChartData => {
507
+ const appliedValues = combineAppliedValues(displayedData, axisSettings, items);
508
+ if (anyItemUsesChartData && axisSettings?.dataKey != null && graphicalItemsData.length > 0) {
509
+ const chartDataSlice = chartData.slice(dataStartIndex, dataEndIndex + 1);
510
+ const chartAppliedValues: AppliedChartData = chartDataSlice
511
+ .map((item) => ({ value: getValueByDataKey(item, axisSettings.dataKey) }))
512
+ .filter((av) => av.value != null);
513
+ return [...chartAppliedValues, ...appliedValues];
514
+ }
515
+ return appliedValues;
516
+ };
517
+
518
+ /**
519
+ * All values with the appropriate dataKey applied. Expensive — iterates all data.
520
+ */
521
+ export const selectAllAppliedValues = (
522
+ state: RechartsRootState,
523
+ axisType: AllAxisTypes,
524
+ axisId: AxisId,
525
+ isPanorama: boolean,
526
+ ): AppliedChartData =>
527
+ combineAllAppliedValues(
528
+ selectDisplayedData(state, axisType, axisId, isPanorama),
529
+ selectBaseAxis(state, axisType, axisId),
530
+ selectCartesianItemsSettings(state, axisType, axisId),
531
+ selectChartDataWithIndexesIfNotInPanoramaPosition4(state, axisType, axisId, isPanorama),
532
+ selectAnyCartesianItemsUsesChartData(state, axisType, axisId),
533
+ selectCartesianGraphicalItemsData(state, axisType, axisId),
534
+ );
535
+
536
+ function makeNumber(val: unknown): number | undefined {
537
+ if (isNumOrStr(val) || val instanceof Date) {
538
+ const n = Number(val);
539
+ if (isWellBehavedNumber(n)) {
540
+ return n;
541
+ }
542
+ }
543
+ return undefined;
544
+ }
545
+
546
+ function makeDomain(val: unknown): NumberDomain | undefined {
547
+ if (Array.isArray(val)) {
548
+ const arr: ReadonlyArray<unknown> = val;
549
+ const attempt = [makeNumber(arr[0]), makeNumber(arr[1])];
550
+ if (isWellFormedNumberDomain(attempt)) {
551
+ return attempt;
552
+ }
553
+ return undefined;
554
+ }
555
+ const n = makeNumber(val);
556
+ if (n == null) {
557
+ return undefined;
558
+ }
559
+ return [n, n];
560
+ }
561
+
562
+ function onlyAllowNumbers(data: ReadonlyArray<unknown>): ReadonlyArray<number> {
563
+ return data.map(makeNumber).filter(isNotNil);
564
+ }
565
+
566
+ // ----- Error bars ----------------------------------------------------------
567
+ // The ErrorBarsSettings/State types live in the errorBarSlice (re-homed). The
568
+ // domain math below extends the numerical domain by each ErrorBar's value.
569
+
570
+ export function isErrorBarRelevantForAxisType(
571
+ axisType: AllAxisTypes,
572
+ errorBar: ErrorBarsSettings,
573
+ ): boolean {
574
+ switch (axisType) {
575
+ case "xAxis":
576
+ return errorBar.direction === "x";
577
+ case "yAxis":
578
+ return errorBar.direction === "y";
579
+ default:
580
+ return false;
581
+ }
582
+ }
583
+
584
+ export function getErrorDomainByDataKey(
585
+ entry: unknown,
586
+ appliedValue: unknown,
587
+ relevantErrorBars: ReadonlyArray<ErrorBarsSettings> | undefined,
588
+ ): ReadonlyArray<number> {
589
+ if (!relevantErrorBars || !relevantErrorBars.length) {
590
+ return [];
591
+ }
592
+
593
+ let appliedNumericValue: number | undefined;
594
+ if (typeof appliedValue === "number" && !isNan(appliedValue)) {
595
+ appliedNumericValue = appliedValue;
596
+ } else if (Array.isArray(appliedValue)) {
597
+ const numericRangeValues = onlyAllowNumbers(appliedValue);
598
+ if (numericRangeValues.length > 0) {
599
+ appliedNumericValue = Math.max(...numericRangeValues);
600
+ }
601
+ }
602
+
603
+ if (appliedNumericValue == null) {
604
+ return [];
605
+ }
606
+ const baseValue = appliedNumericValue;
607
+
608
+ return onlyAllowNumbers(
609
+ relevantErrorBars.flatMap((eb) => {
610
+ const errorValue = getValueByDataKey(entry, eb.dataKey);
611
+ let lowBound: unknown;
612
+ let highBound: unknown;
613
+
614
+ if (Array.isArray(errorValue)) {
615
+ const arr: ReadonlyArray<unknown> = errorValue;
616
+ lowBound = arr[0];
617
+ highBound = arr[1];
618
+ } else {
619
+ lowBound = errorValue;
620
+ highBound = errorValue;
621
+ }
622
+ if (!isWellBehavedNumber(lowBound) || !isWellBehavedNumber(highBound)) {
623
+ return [undefined];
624
+ }
625
+ return [baseValue - lowBound, baseValue + highBound];
626
+ }),
627
+ );
628
+ }
629
+
630
+ export const selectAllErrorBarSettings = (state: RechartsRootState): ErrorBarsState =>
631
+ state.errorBars;
632
+
633
+ // Ported from recharts combineRelevantErrorBarSettings + selectErrorBarsSettings
634
+ // (axisSelectors.ts): the ErrorBars registered against the cartesian items on the
635
+ // given axis, filtered to those whose direction is relevant for that axis type.
636
+ // reselect createSelector → plain function (memoization from useAppSelector).
637
+ export const selectErrorBarsSettings = (
638
+ state: RechartsRootState,
639
+ axisType: AllAxisTypes,
640
+ axisId: AxisId,
641
+ ): ReadonlyArray<ErrorBarsSettings> => {
642
+ const cartesianItemsSettings = selectCartesianItemsSettings(state, axisType, axisId);
643
+ const allErrorBarSettings = selectAllErrorBarSettings(state);
644
+ return cartesianItemsSettings
645
+ .flatMap((item) => allErrorBarSettings[item.id])
646
+ .filter((e): e is ErrorBarsSettings => Boolean(e))
647
+ .filter((e) => isErrorBarRelevantForAxisType(axisType, e));
648
+ };
649
+
650
+ export const mergeDomains = (
651
+ ...domains: ReadonlyArray<ReadonlyArray<number> | undefined>
652
+ ): NumberDomain | undefined => {
653
+ const allDomains = domains.filter(isNotNil);
654
+ if (allDomains.length === 0) {
655
+ return undefined;
656
+ }
657
+ const allValues = allDomains.flat();
658
+ const min = Math.min(...allValues);
659
+ const max = Math.max(...allValues);
660
+ return [min, max];
661
+ };
662
+
663
+ export const combineDomainOfAllAppliedNumericalValuesIncludingErrorValues = (
664
+ displayedData: ChartData,
665
+ axisSettings: BaseCartesianAxis,
666
+ items: ReadonlyArray<GraphicalItemSettings>,
667
+ errorBars: ErrorBarsState,
668
+ axisType: AllAxisTypes,
669
+ chartDataSlice: ChartData = [],
670
+ ): NumberDomain | undefined => {
671
+ let lowerEnd: number | undefined;
672
+ let upperEnd: number | undefined;
673
+ if (items.length > 0) {
674
+ items.forEach((item) => {
675
+ const itemData: ChartData = item.data != null ? [...item.data] : chartDataSlice;
676
+ const relevantErrorBars = errorBars[item.id]?.filter((errorBar) =>
677
+ isErrorBarRelevantForAxisType(axisType, errorBar),
678
+ );
679
+ itemData.forEach((entry) => {
680
+ const valueByDataKey = getValueByDataKey(entry, axisSettings.dataKey ?? item.dataKey);
681
+ const errorDomain = getErrorDomainByDataKey(entry, valueByDataKey, relevantErrorBars);
682
+ if (errorDomain.length >= 2) {
683
+ const localLower = Math.min(...errorDomain);
684
+ const localUpper = Math.max(...errorDomain);
685
+ if (lowerEnd == null || localLower < lowerEnd) {
686
+ lowerEnd = localLower;
687
+ }
688
+ if (upperEnd == null || localUpper > upperEnd) {
689
+ upperEnd = localUpper;
690
+ }
691
+ }
692
+ const dataValueDomain = makeDomain(valueByDataKey);
693
+ if (dataValueDomain != null) {
694
+ lowerEnd = lowerEnd == null ? dataValueDomain[0] : Math.min(lowerEnd, dataValueDomain[0]);
695
+ upperEnd = upperEnd == null ? dataValueDomain[1] : Math.max(upperEnd, dataValueDomain[1]);
696
+ }
697
+ });
698
+ });
699
+ }
700
+ if (axisSettings?.dataKey != null && items.length === 0) {
701
+ displayedData.forEach((item) => {
702
+ const dataValueDomain = makeDomain(getValueByDataKey(item, axisSettings.dataKey));
703
+ if (dataValueDomain != null) {
704
+ lowerEnd = lowerEnd == null ? dataValueDomain[0] : Math.min(lowerEnd, dataValueDomain[0]);
705
+ upperEnd = upperEnd == null ? dataValueDomain[1] : Math.max(upperEnd, dataValueDomain[1]);
706
+ }
707
+ });
708
+ }
709
+
710
+ if (isWellBehavedNumber(lowerEnd) && isWellBehavedNumber(upperEnd)) {
711
+ return [lowerEnd, upperEnd];
712
+ }
713
+ return undefined;
714
+ };
715
+
716
+ export const selectDomainOfAllAppliedNumericalValuesIncludingErrorValues = (
717
+ state: RechartsRootState,
718
+ axisType: AllAxisTypes,
719
+ axisId: AxisId,
720
+ isPanorama: boolean,
721
+ ): NumberDomain | undefined =>
722
+ combineDomainOfAllAppliedNumericalValuesIncludingErrorValues(
723
+ selectDisplayedData(state, axisType, axisId, isPanorama),
724
+ selectBaseAxis(state, axisType, axisId),
725
+ selectCartesianItemsSettingsExceptStacked(state, axisType, axisId),
726
+ selectAllErrorBarSettings(state),
727
+ axisType,
728
+ selectChartDataSliceIfNotInPanorama(state, axisType, axisId, isPanorama),
729
+ );
730
+
731
+ function onlyAllowNumbersAndStringsAndDates(item: {
732
+ value: unknown;
733
+ }): string | number | Date | undefined {
734
+ const { value } = item;
735
+ if (isNumOrStr(value) || value instanceof Date) {
736
+ return value;
737
+ }
738
+ return undefined;
739
+ }
740
+
741
+ const computeDomainOfTypeCategory = (
742
+ allDataSquished: AppliedChartData,
743
+ axisSettings: BaseCartesianAxis,
744
+ isCategorical: boolean,
745
+ ): CategoricalDomain => {
746
+ const categoricalDomain = allDataSquished
747
+ .map(onlyAllowNumbersAndStringsAndDates)
748
+ .filter(isNotNil);
749
+ if (
750
+ isCategorical &&
751
+ (axisSettings.dataKey == null ||
752
+ (axisSettings.allowDuplicatedCategory && hasDuplicate(categoricalDomain)))
753
+ ) {
754
+ return range(0, allDataSquished.length);
755
+ }
756
+ if (axisSettings.allowDuplicatedCategory) {
757
+ return categoricalDomain;
758
+ }
759
+ return Array.from(new Set(categoricalDomain));
760
+ };
761
+
762
+ // Reference elements (dots/lines/areas) with ifOverflow='extendDomain' extend
763
+ // the numerical domain so the element fits inside the plot area. Ported from
764
+ // recharts' selectReferenceDots/Lines/Areas → ...ByAxis → ...Domain chain; the
765
+ // reselect `createSelector`s become plain functions (memoization comes from
766
+ // useAppSelector's createMemo).
767
+ export const selectReferenceDots = (
768
+ state: RechartsRootState,
769
+ ): ReadonlyArray<ReferenceDotSettings> => state.referenceElements.dots;
770
+
771
+ export const selectReferenceAreas = (
772
+ state: RechartsRootState,
773
+ ): ReadonlyArray<ReferenceAreaSettings> => state.referenceElements.areas;
774
+
775
+ export const selectReferenceLines = (
776
+ state: RechartsRootState,
777
+ ): ReadonlyArray<ReferenceLineSettings> => state.referenceElements.lines;
778
+
779
+ export const filterReferenceElements = <T extends ReferenceElementSettings>(
780
+ elements: ReadonlyArray<T>,
781
+ axisType: AllAxisTypes,
782
+ axisId: AxisId,
783
+ ): ReadonlyArray<T> =>
784
+ elements
785
+ .filter((el) => el.ifOverflow === "extendDomain")
786
+ .filter((el) => (axisType === "xAxis" ? el.xAxisId === axisId : el.yAxisId === axisId));
787
+
788
+ export const selectReferenceDotsByAxis = (
789
+ state: RechartsRootState,
790
+ axisType: AllAxisTypes,
791
+ axisId: AxisId,
792
+ ): ReadonlyArray<ReferenceDotSettings> =>
793
+ filterReferenceElements(selectReferenceDots(state), axisType, axisId);
794
+
795
+ export const selectReferenceAreasByAxis = (
796
+ state: RechartsRootState,
797
+ axisType: AllAxisTypes,
798
+ axisId: AxisId,
799
+ ): ReadonlyArray<ReferenceAreaSettings> =>
800
+ filterReferenceElements(selectReferenceAreas(state), axisType, axisId);
801
+
802
+ export const selectReferenceLinesByAxis = (
803
+ state: RechartsRootState,
804
+ axisType: AllAxisTypes,
805
+ axisId: AxisId,
806
+ ): ReadonlyArray<ReferenceLineSettings> =>
807
+ filterReferenceElements(selectReferenceLines(state), axisType, axisId);
808
+
809
+ export const combineDotsDomain = (
810
+ dots: ReadonlyArray<ReferenceDotSettings> | undefined,
811
+ axisType: AllAxisTypes,
812
+ ): NumberDomain | undefined => {
813
+ if (dots == null) {
814
+ return undefined;
815
+ }
816
+ const allCoords = onlyAllowNumbers(dots.map((dot) => (axisType === "xAxis" ? dot.x : dot.y)));
817
+ if (allCoords.length === 0) {
818
+ return undefined;
819
+ }
820
+ return [Math.min(...allCoords), Math.max(...allCoords)];
821
+ };
822
+
823
+ export const combineAreasDomain = (
824
+ areas: ReadonlyArray<ReferenceAreaSettings> | undefined,
825
+ axisType: AllAxisTypes,
826
+ ): NumberDomain | undefined => {
827
+ if (areas == null) {
828
+ return undefined;
829
+ }
830
+ const allCoords = onlyAllowNumbers(
831
+ areas.flatMap((area) => [
832
+ axisType === "xAxis" ? area.x1 : area.y1,
833
+ axisType === "xAxis" ? area.x2 : area.y2,
834
+ ]),
835
+ );
836
+ if (allCoords.length === 0) {
837
+ return undefined;
838
+ }
839
+ return [Math.min(...allCoords), Math.max(...allCoords)];
840
+ };
841
+
842
+ function extractXCoordinates(line: ReferenceLineSettings): ReadonlyArray<number> {
843
+ if (line.x != null) {
844
+ return onlyAllowNumbers([line.x]);
845
+ }
846
+ const segmentCoordinates = line.segment?.map((s) => s.x);
847
+ if (segmentCoordinates == null || segmentCoordinates.length === 0) {
848
+ return [];
849
+ }
850
+ return onlyAllowNumbers(segmentCoordinates);
851
+ }
852
+
853
+ function extractYCoordinates(line: ReferenceLineSettings): ReadonlyArray<number> {
854
+ if (line.y != null) {
855
+ return onlyAllowNumbers([line.y]);
856
+ }
857
+ const segmentCoordinates = line.segment?.map((s) => s.y);
858
+ if (segmentCoordinates == null || segmentCoordinates.length === 0) {
859
+ return [];
860
+ }
861
+ return onlyAllowNumbers(segmentCoordinates);
862
+ }
863
+
864
+ export const combineLinesDomain = (
865
+ lines: ReadonlyArray<ReferenceLineSettings> | undefined,
866
+ axisType: AllAxisTypes,
867
+ ): NumberDomain | undefined => {
868
+ if (lines == null) {
869
+ return undefined;
870
+ }
871
+ const allCoords: ReadonlyArray<number> = lines.flatMap((line) =>
872
+ axisType === "xAxis" ? extractXCoordinates(line) : extractYCoordinates(line),
873
+ );
874
+ if (allCoords.length === 0) {
875
+ return undefined;
876
+ }
877
+ return [Math.min(...allCoords), Math.max(...allCoords)];
878
+ };
879
+
880
+ const selectReferenceElementsDomain = (
881
+ state: RechartsRootState,
882
+ axisType: AllAxisTypes,
883
+ axisId: AxisId,
884
+ ): NumberDomain | undefined => {
885
+ const dotsDomain = combineDotsDomain(
886
+ selectReferenceDotsByAxis(state, axisType, axisId),
887
+ axisType,
888
+ );
889
+ const areasDomain = combineAreasDomain(
890
+ selectReferenceAreasByAxis(state, axisType, axisId),
891
+ axisType,
892
+ );
893
+ const linesDomain = combineLinesDomain(
894
+ selectReferenceLinesByAxis(state, axisType, axisId),
895
+ axisType,
896
+ );
897
+ return mergeDomains(dotsDomain, areasDomain, linesDomain);
898
+ };
899
+
900
+ export const getDomainDefinition = (axisSettings: AllAxisSettings): AxisDomain => {
901
+ if (axisSettings == null || !("domain" in axisSettings)) {
902
+ return defaultNumericDomain;
903
+ }
904
+
905
+ if (axisSettings.domain != null) {
906
+ return axisSettings.domain;
907
+ }
908
+ if ("ticks" in axisSettings && axisSettings.ticks != null) {
909
+ if (axisSettings.type === "number") {
910
+ const allValues = onlyAllowNumbers(axisSettings.ticks);
911
+ return [Math.min(...allValues), Math.max(...allValues)];
912
+ }
913
+ if (axisSettings.type === "category") {
914
+ return axisSettings.ticks.map(String);
915
+ }
916
+ }
917
+ return axisSettings?.domain ?? defaultNumericDomain;
918
+ };
919
+
920
+ export const selectDomainDefinition = (
921
+ state: RechartsRootState,
922
+ axisType: AllAxisTypes,
923
+ axisId: AxisId,
924
+ ): AxisDomain => getDomainDefinition(selectBaseAxis(state, axisType, axisId));
925
+
926
+ const selectAllowsDataOverflow = (
927
+ state: RechartsRootState,
928
+ axisType: AllAxisTypes,
929
+ axisId: AxisId,
930
+ ): boolean => selectBaseAxis(state, axisType, axisId).allowDataOverflow;
931
+
932
+ export const selectDomainFromUserPreference = (
933
+ state: RechartsRootState,
934
+ axisType: AllAxisTypes,
935
+ axisId: AxisId,
936
+ ): NumberDomain | undefined =>
937
+ numericalDomainSpecifiedWithoutRequiringData(
938
+ selectDomainDefinition(state, axisType, axisId),
939
+ selectAllowsDataOverflow(state, axisType, axisId),
940
+ );
941
+
942
+ // Stacks: graphical items sharing a `stackId` stack on each other, extending the
943
+ // numerical domain. Ported from recharts' selectStackedCartesianItemsSettings →
944
+ // selectDisplayedStackedData → selectStackGroups → selectDomainOfStackGroups chain
945
+ // (reselect createSelectors → plain functions; memoization from useAppSelector).
946
+
947
+ /** Cartesian items (Bar/Area) that are actually stacked (have stackId + dataKey). */
948
+ export const selectStackedCartesianItemsSettings = (
949
+ state: RechartsRootState,
950
+ axisType: AllAxisTypes,
951
+ axisId: AxisId,
952
+ ): ReadonlyArray<DefinitelyStackedGraphicalItem> =>
953
+ selectCartesianItemsSettings(state, axisType, axisId)
954
+ .filter((item) => item.type === "area" || item.type === "bar")
955
+ .filter(isStacked);
956
+
957
+ const selectTooltipAxisForStacks = (state: RechartsRootState): BaseCartesianAxis =>
958
+ selectRenderableAxisSettings(state, selectTooltipAxisType(state), selectTooltipAxisId(state));
959
+
960
+ export const selectDisplayedStackedData = (
961
+ state: RechartsRootState,
962
+ axisType: AllAxisTypes,
963
+ axisId: AxisId,
964
+ isPanorama: boolean,
965
+ ): DisplayedStackedData =>
966
+ combineDisplayedStackedData(
967
+ selectStackedCartesianItemsSettings(state, axisType, axisId),
968
+ selectChartDataWithIndexesIfNotInPanoramaPosition4(state, axisType, axisId, isPanorama),
969
+ selectTooltipAxisForStacks(state),
970
+ );
971
+
972
+ export const combineStackGroups = (
973
+ displayedData: DisplayedStackedData,
974
+ items: ReadonlyArray<DefinitelyStackedGraphicalItem>,
975
+ stackOffsetType: StackOffsetType,
976
+ reverseStackOrder: boolean,
977
+ ): AllStackGroups => {
978
+ const itemsGroup: Record<StackId, Array<DefinitelyStackedGraphicalItem>> = {};
979
+ items.forEach((item) => {
980
+ if (item.stackId == null) {
981
+ return;
982
+ }
983
+ const stack = itemsGroup[item.stackId] ?? [];
984
+ stack.push(item);
985
+ itemsGroup[item.stackId] = stack;
986
+ });
987
+
988
+ return Object.fromEntries(
989
+ Object.entries(itemsGroup).map(([stackId, graphicalItems]): [StackId, StackGroup] => {
990
+ const orderedGraphicalItems = reverseStackOrder
991
+ ? [...graphicalItems].reverse()
992
+ : graphicalItems;
993
+ const dataKeys = orderedGraphicalItems.map((item) => getStackSeriesIdentifier(item));
994
+ return [
995
+ stackId,
996
+ {
997
+ stackedData: getStackedData(displayedData, dataKeys, stackOffsetType),
998
+ graphicalItems: orderedGraphicalItems,
999
+ },
1000
+ ];
1001
+ }),
1002
+ );
1003
+ };
1004
+
1005
+ /**
1006
+ * Stack groups are groups of graphical items that stack on each other, keyed by
1007
+ * stack ID. Items without a stack ID do not appear.
1008
+ */
1009
+ export const selectStackGroups = (
1010
+ state: RechartsRootState,
1011
+ axisType: AllAxisTypes,
1012
+ axisId: AxisId,
1013
+ isPanorama: boolean,
1014
+ ): AllStackGroups =>
1015
+ combineStackGroups(
1016
+ selectDisplayedStackedData(state, axisType, axisId, isPanorama),
1017
+ selectStackedCartesianItemsSettings(state, axisType, axisId),
1018
+ selectStackOffsetType(state),
1019
+ selectReverseStackOrder(state),
1020
+ );
1021
+
1022
+ export const combineDomainOfStackGroups = (
1023
+ stackGroups: AllStackGroups | undefined,
1024
+ { dataStartIndex, dataEndIndex }: ChartDataState,
1025
+ axisType: AllAxisTypes,
1026
+ domainFromUserPreference: NumberDomain | undefined,
1027
+ ): NumberDomain | undefined => {
1028
+ if (domainFromUserPreference != null) {
1029
+ return undefined;
1030
+ }
1031
+ if (axisType === "zAxis") {
1032
+ return undefined;
1033
+ }
1034
+ return getDomainOfStackGroups(stackGroups, dataStartIndex, dataEndIndex);
1035
+ };
1036
+
1037
+ export const selectDomainOfStackGroups = (
1038
+ state: RechartsRootState,
1039
+ axisType: AllAxisTypes,
1040
+ axisId: AxisId,
1041
+ isPanorama: boolean,
1042
+ ): NumberDomain | undefined =>
1043
+ combineDomainOfStackGroups(
1044
+ selectStackGroups(state, axisType, axisId, isPanorama),
1045
+ selectChartDataWithIndexes(state),
1046
+ axisType,
1047
+ selectDomainFromUserPreference(state, axisType, axisId),
1048
+ );
1049
+
1050
+ export const combineNumericalDomain = (
1051
+ axisSettings: BaseCartesianAxis,
1052
+ domainDefinition: AxisDomain | undefined,
1053
+ domainFromUserPreference: NumberDomain | undefined,
1054
+ domainOfStackGroups: NumberDomain | undefined,
1055
+ dataAndErrorBarsDomain: NumberDomain | undefined,
1056
+ referenceElementsDomain: NumberDomain | undefined,
1057
+ layout: LayoutType,
1058
+ axisType: AllAxisTypes,
1059
+ numericTicksDomain?: NumberDomain,
1060
+ ): NumberDomain | undefined => {
1061
+ if (domainFromUserPreference != null) {
1062
+ return domainFromUserPreference;
1063
+ }
1064
+
1065
+ // Polar branches verified against released recharts: stacked RadialBars extend
1066
+ // the numeric axis (angle axis in radial layout, radius axis in centric layout)
1067
+ // to the stack total — e.g. shadcn's radial-stacked fills [0, total] exactly.
1068
+ const shouldIncludeDomainOfStackGroups =
1069
+ (layout === "vertical" && axisType === "xAxis") ||
1070
+ (layout === "horizontal" && axisType === "yAxis") ||
1071
+ (layout === "radial" && axisType === "angleAxis") ||
1072
+ (layout === "centric" && axisType === "radiusAxis");
1073
+
1074
+ const mergedDomains = shouldIncludeDomainOfStackGroups
1075
+ ? mergeDomains(domainOfStackGroups, referenceElementsDomain, dataAndErrorBarsDomain)
1076
+ : mergeDomains(referenceElementsDomain, dataAndErrorBarsDomain);
1077
+
1078
+ const parsedDomain = parseNumericalUserDomain(
1079
+ domainDefinition,
1080
+ mergedDomains,
1081
+ axisSettings.allowDataOverflow,
1082
+ );
1083
+ if (parsedDomain != null) {
1084
+ return parsedDomain;
1085
+ }
1086
+
1087
+ /*
1088
+ * https://github.com/recharts/recharts/issues/7362
1089
+ * The user-provided domain could not be resolved without data - it's a function
1090
+ * bound or one of 'auto'/'dataMin'/'dataMax' - and there is no data domain to
1091
+ * resolve it from: empty or all-null data, and no domain-extending reference
1092
+ * elements (only reference dots/lines/areas with ifOverflow="extendDomain"
1093
+ * contribute to mergedDomains). If the
1094
+ * axis opted into data overflow and supplied an explicit numeric `ticks` array,
1095
+ * fall back to the ticks' [min, max] extent so the explicit tick ladder still
1096
+ * renders, mirroring what a literal numeric domain already does.
1097
+ */
1098
+ if (axisSettings.allowDataOverflow && mergedDomains == null && numericTicksDomain != null) {
1099
+ return numericTicksDomain;
1100
+ }
1101
+
1102
+ return parsedDomain;
1103
+ };
1104
+
1105
+ /**
1106
+ * https://github.com/recharts/recharts/issues/7362
1107
+ * Derives the [min, max] extent of an axis's explicit numeric `ticks`. Used by
1108
+ * {@link combineNumericalDomain} as a last-resort domain when a non-literal domain
1109
+ * cannot be resolved without data. Returns undefined for non-number axes, or when
1110
+ * no numeric ticks were supplied.
1111
+ */
1112
+ export const combineNumericTicksDomain = (
1113
+ axisSettings: AllAxisSettings,
1114
+ ): NumberDomain | undefined => {
1115
+ if (
1116
+ axisSettings == null ||
1117
+ axisSettings.type !== "number" ||
1118
+ !("ticks" in axisSettings) ||
1119
+ axisSettings.ticks == null
1120
+ ) {
1121
+ return undefined;
1122
+ }
1123
+ const numericTicks = onlyAllowNumbers(axisSettings.ticks);
1124
+ if (numericTicks.length === 0) {
1125
+ return undefined;
1126
+ }
1127
+ return [Math.min(...numericTicks), Math.max(...numericTicks)];
1128
+ };
1129
+
1130
+ export const selectNumericTicksDomain = (
1131
+ state: RechartsRootState,
1132
+ axisType: AllAxisTypes,
1133
+ axisId: AxisId,
1134
+ ): NumberDomain | undefined => combineNumericTicksDomain(selectBaseAxis(state, axisType, axisId));
1135
+
1136
+ export const selectNumericalDomain = (
1137
+ state: RechartsRootState,
1138
+ axisType: AllAxisTypes,
1139
+ axisId: AxisId,
1140
+ isPanorama: boolean,
1141
+ ): NumberDomain | undefined =>
1142
+ combineNumericalDomain(
1143
+ selectBaseAxis(state, axisType, axisId),
1144
+ selectDomainDefinition(state, axisType, axisId),
1145
+ selectDomainFromUserPreference(state, axisType, axisId),
1146
+ selectDomainOfStackGroups(state, axisType, axisId, isPanorama),
1147
+ selectDomainOfAllAppliedNumericalValuesIncludingErrorValues(
1148
+ state,
1149
+ axisType,
1150
+ axisId,
1151
+ isPanorama,
1152
+ ),
1153
+ selectReferenceElementsDomain(state, axisType, axisId),
1154
+ selectChartLayout(state),
1155
+ axisType,
1156
+ selectNumericTicksDomain(state, axisType, axisId),
1157
+ );
1158
+
1159
+ /**
1160
+ * Expand maps everything between 0 and 1; nothing to compute.
1161
+ * @see https://d3js.org/d3-shape/stack#stack-offsets
1162
+ */
1163
+ const expandDomain: NumberDomain = [0, 1];
1164
+
1165
+ export const combineAxisDomain = (
1166
+ axisSettings: BaseCartesianAxis,
1167
+ layout: LayoutType,
1168
+ displayedData: ChartData | undefined,
1169
+ allAppliedValues: AppliedChartData,
1170
+ stackOffsetType: StackOffsetType,
1171
+ axisType: AllAxisTypes,
1172
+ numericalDomain: NumberDomain | undefined,
1173
+ ): NumberDomain | CategoricalDomain | undefined => {
1174
+ if (
1175
+ (axisSettings == null || displayedData == null || displayedData.length === 0) &&
1176
+ numericalDomain === undefined
1177
+ ) {
1178
+ return undefined;
1179
+ }
1180
+ const { dataKey, type } = axisSettings;
1181
+ const isCategorical = isCategoricalAxis(layout, axisType);
1182
+
1183
+ if (isCategorical && dataKey == null) {
1184
+ return range(0, displayedData?.length ?? 0);
1185
+ }
1186
+
1187
+ if (type === "category") {
1188
+ return computeDomainOfTypeCategory(allAppliedValues, axisSettings, isCategorical);
1189
+ }
1190
+
1191
+ if (stackOffsetType === "expand" && !isCategorical) {
1192
+ return expandDomain;
1193
+ }
1194
+ return numericalDomain;
1195
+ };
1196
+
1197
+ export const selectAxisDomain = (
1198
+ state: RechartsRootState,
1199
+ axisType: AllAxisTypes,
1200
+ axisId: AxisId,
1201
+ isPanorama: boolean,
1202
+ ): NumberDomain | CategoricalDomain | undefined =>
1203
+ combineAxisDomain(
1204
+ selectBaseAxis(state, axisType, axisId),
1205
+ selectChartLayout(state),
1206
+ selectDisplayedData(state, axisType, axisId, isPanorama),
1207
+ selectAllAppliedValues(state, axisType, axisId, isPanorama),
1208
+ selectStackOffsetType(state),
1209
+ axisType,
1210
+ selectNumericalDomain(state, axisType, axisId, isPanorama),
1211
+ );
1212
+
1213
+ export const selectRealScaleType = (
1214
+ state: RechartsRootState,
1215
+ axisType: AllAxisTypes,
1216
+ axisId: AxisId,
1217
+ ): RechartsScaleType | undefined =>
1218
+ combineRealScaleType(
1219
+ selectBaseAxis(state, axisType, axisId),
1220
+ selectHasBar(state),
1221
+ selectChartName(state),
1222
+ );
1223
+
1224
+ export const combineNiceTicks = (
1225
+ axisDomain: NumberDomain | CategoricalDomain | undefined,
1226
+ axisSettings: RenderableAxisSettings,
1227
+ realScaleType: string | undefined,
1228
+ ): ReadonlyArray<number> | undefined => {
1229
+ const { niceTicks } = axisSettings;
1230
+
1231
+ if (niceTicks === "none") {
1232
+ return undefined;
1233
+ }
1234
+
1235
+ const domainDefinition: AxisDomain = getDomainDefinition(axisSettings);
1236
+ const hasDomainAutoKeyword =
1237
+ Array.isArray(domainDefinition) &&
1238
+ (domainDefinition[0] === "auto" || domainDefinition[1] === "auto");
1239
+
1240
+ if (
1241
+ (niceTicks === "snap125" || niceTicks === "adaptive") &&
1242
+ axisSettings != null &&
1243
+ axisSettings.tickCount &&
1244
+ isWellFormedNumberDomain(axisDomain)
1245
+ ) {
1246
+ if (hasDomainAutoKeyword) {
1247
+ return getNiceTickValues(
1248
+ axisDomain,
1249
+ axisSettings.tickCount,
1250
+ axisSettings.allowDecimals,
1251
+ niceTicks,
1252
+ );
1253
+ }
1254
+ if (axisSettings.type === "number") {
1255
+ return getTickValuesFixedDomain(
1256
+ axisDomain,
1257
+ axisSettings.tickCount,
1258
+ axisSettings.allowDecimals,
1259
+ niceTicks,
1260
+ );
1261
+ }
1262
+ }
1263
+
1264
+ if (
1265
+ niceTicks === "auto" &&
1266
+ realScaleType === "linear" &&
1267
+ axisSettings != null &&
1268
+ axisSettings.tickCount
1269
+ ) {
1270
+ if (hasDomainAutoKeyword && isWellFormedNumberDomain(axisDomain)) {
1271
+ return getNiceTickValues(
1272
+ axisDomain,
1273
+ axisSettings.tickCount,
1274
+ axisSettings.allowDecimals,
1275
+ "adaptive",
1276
+ );
1277
+ }
1278
+
1279
+ if (axisSettings.type === "number" && isWellFormedNumberDomain(axisDomain)) {
1280
+ return getTickValuesFixedDomain(
1281
+ axisDomain,
1282
+ axisSettings.tickCount,
1283
+ axisSettings.allowDecimals,
1284
+ "adaptive",
1285
+ );
1286
+ }
1287
+ }
1288
+
1289
+ return undefined;
1290
+ };
1291
+
1292
+ export const selectNiceTicks = (
1293
+ state: RechartsRootState,
1294
+ axisType: RenderableAxisType,
1295
+ axisId: AxisId,
1296
+ isPanorama: boolean,
1297
+ ): ReadonlyArray<number> | undefined =>
1298
+ combineNiceTicks(
1299
+ selectAxisDomain(state, axisType, axisId, isPanorama),
1300
+ selectRenderableAxisSettings(state, axisType, axisId),
1301
+ selectRealScaleType(state, axisType, axisId),
1302
+ );
1303
+
1304
+ export const combineAxisDomainWithNiceTicks = (
1305
+ axisSettings: BaseCartesianAxis,
1306
+ domain: NumberDomain | CategoricalDomain | undefined,
1307
+ niceTicks: ReadonlyArray<number> | undefined,
1308
+ axisType: RenderableAxisType,
1309
+ ): NumberDomain | CategoricalDomain | undefined => {
1310
+ if (
1311
+ axisType !== "angleAxis" &&
1312
+ axisSettings?.type === "number" &&
1313
+ isWellFormedNumberDomain(domain) &&
1314
+ // `niceTicks != null` (not `Array.isArray`) keeps the `number` element type:
1315
+ // `Array.isArray` widens a readonly array union to `any[]` (TS limitation).
1316
+ niceTicks != null &&
1317
+ niceTicks.length > 0
1318
+ ) {
1319
+ const minFromDomain = domain[0];
1320
+ const minFromTicks = niceTicks[0] ?? 0;
1321
+ const maxFromDomain = domain[1];
1322
+ const maxFromTicks = niceTicks[niceTicks.length - 1] ?? 0;
1323
+ return [Math.min(minFromDomain, minFromTicks), Math.max(maxFromDomain, maxFromTicks)];
1324
+ }
1325
+ return domain;
1326
+ };
1327
+
1328
+ export const selectAxisDomainIncludingNiceTicks = (
1329
+ state: RechartsRootState,
1330
+ axisType: RenderableAxisType,
1331
+ axisId: AxisId,
1332
+ isPanorama: boolean,
1333
+ ): NumberDomain | CategoricalDomain | undefined =>
1334
+ combineAxisDomainWithNiceTicks(
1335
+ selectBaseAxis(state, axisType, axisId),
1336
+ selectAxisDomain(state, axisType, axisId, isPanorama),
1337
+ selectNiceTicks(state, axisType, axisId, isPanorama),
1338
+ axisType,
1339
+ );
1340
+
1341
+ /**
1342
+ * Smallest gap between two data numbers as a ratio of the whole range (0..1).
1343
+ * Ignores any user domain; only considers domain from data.
1344
+ */
1345
+ export const selectSmallestDistanceBetweenValues = (
1346
+ state: RechartsRootState,
1347
+ axisType: RenderableAxisType,
1348
+ axisId: AxisId,
1349
+ isPanorama: boolean,
1350
+ ): number | undefined => {
1351
+ const axisSettings = selectBaseAxis(state, axisType, axisId);
1352
+ if (!axisSettings || axisSettings.type !== "number") {
1353
+ return undefined;
1354
+ }
1355
+ const allDataSquished = selectAllAppliedValues(state, axisType, axisId, isPanorama);
1356
+ let smallestDistanceBetweenValues = Infinity;
1357
+ const sortedValues = Array.from(onlyAllowNumbers(allDataSquished.map((d) => d.value))).sort(
1358
+ (a, b) => a - b,
1359
+ );
1360
+ const first = sortedValues[0];
1361
+ const last = sortedValues[sortedValues.length - 1];
1362
+ if (first == null || last == null) {
1363
+ return Infinity;
1364
+ }
1365
+ const diff = last - first;
1366
+ if (diff === 0) {
1367
+ return Infinity;
1368
+ }
1369
+ for (let i = 0; i < sortedValues.length - 1; i++) {
1370
+ const curr = sortedValues[i];
1371
+ const next = sortedValues[i + 1];
1372
+ if (curr == null || next == null) {
1373
+ continue;
1374
+ }
1375
+ const distance = next - curr;
1376
+ smallestDistanceBetweenValues = Math.min(smallestDistanceBetweenValues, distance);
1377
+ }
1378
+ return smallestDistanceBetweenValues / diff;
1379
+ };
1380
+
1381
+ const selectCalculatedPadding = (
1382
+ state: RechartsRootState,
1383
+ axisType: RenderableAxisType,
1384
+ axisId: AxisId,
1385
+ isPanorama: boolean,
1386
+ padding: string,
1387
+ ): number => {
1388
+ const smallestDistanceInPercent = selectSmallestDistanceBetweenValues(
1389
+ state,
1390
+ axisType,
1391
+ axisId,
1392
+ isPanorama,
1393
+ );
1394
+ if (!isWellBehavedNumber(smallestDistanceInPercent)) {
1395
+ return 0;
1396
+ }
1397
+ const layout = selectChartLayout(state);
1398
+ const barCategoryGap = selectBarCategoryGap(state);
1399
+ const offset = selectChartOffsetInternal(state);
1400
+ const rangeWidth = layout === "vertical" ? offset.height : offset.width;
1401
+
1402
+ if (padding === "gap") {
1403
+ return (smallestDistanceInPercent * rangeWidth) / 2;
1404
+ }
1405
+
1406
+ if (padding === "no-gap") {
1407
+ const gap = getPercentValue(barCategoryGap, smallestDistanceInPercent * rangeWidth);
1408
+ const halfBand = (smallestDistanceInPercent * rangeWidth) / 2;
1409
+ return halfBand - gap - ((halfBand - gap) / rangeWidth) * gap;
1410
+ }
1411
+
1412
+ return 0;
1413
+ };
1414
+
1415
+ export const selectCalculatedXAxisPadding = (
1416
+ state: RechartsRootState,
1417
+ axisId: AxisId,
1418
+ isPanorama: boolean,
1419
+ ): number => {
1420
+ const xAxisSettings = selectXAxisSettings(state, axisId);
1421
+ if (xAxisSettings == null || typeof xAxisSettings.padding !== "string") {
1422
+ return 0;
1423
+ }
1424
+ return selectCalculatedPadding(state, "xAxis", axisId, isPanorama, xAxisSettings.padding);
1425
+ };
1426
+
1427
+ export const selectCalculatedYAxisPadding = (
1428
+ state: RechartsRootState,
1429
+ axisId: AxisId,
1430
+ isPanorama: boolean,
1431
+ ): number => {
1432
+ const yAxisSettings = selectYAxisSettings(state, axisId);
1433
+ if (yAxisSettings == null || typeof yAxisSettings.padding !== "string") {
1434
+ return 0;
1435
+ }
1436
+ return selectCalculatedPadding(state, "yAxis", axisId, isPanorama, yAxisSettings.padding);
1437
+ };
1438
+
1439
+ const selectXAxisPadding = (
1440
+ state: RechartsRootState,
1441
+ axisId: AxisId,
1442
+ isPanorama: boolean,
1443
+ ): { left: number; right: number } => {
1444
+ const xAxisSettings = selectXAxisSettings(state, axisId);
1445
+ const calculated = selectCalculatedXAxisPadding(state, axisId, isPanorama);
1446
+ if (xAxisSettings == null) {
1447
+ return { left: 0, right: 0 };
1448
+ }
1449
+ const { padding } = xAxisSettings;
1450
+ if (typeof padding === "string") {
1451
+ return { left: calculated, right: calculated };
1452
+ }
1453
+ return {
1454
+ left: (padding.left ?? 0) + calculated,
1455
+ right: (padding.right ?? 0) + calculated,
1456
+ };
1457
+ };
1458
+
1459
+ const selectYAxisPadding = (
1460
+ state: RechartsRootState,
1461
+ axisId: AxisId,
1462
+ isPanorama: boolean,
1463
+ ): { top: number; bottom: number } => {
1464
+ const yAxisSettings = selectYAxisSettings(state, axisId);
1465
+ const calculated = selectCalculatedYAxisPadding(state, axisId, isPanorama);
1466
+ if (yAxisSettings == null) {
1467
+ return { top: 0, bottom: 0 };
1468
+ }
1469
+ const { padding } = yAxisSettings;
1470
+ if (typeof padding === "string") {
1471
+ return { top: calculated, bottom: calculated };
1472
+ }
1473
+ return {
1474
+ top: (padding.top ?? 0) + calculated,
1475
+ bottom: (padding.bottom ?? 0) + calculated,
1476
+ };
1477
+ };
1478
+
1479
+ export const selectXAxisRange = (
1480
+ state: RechartsRootState,
1481
+ axisId: AxisId,
1482
+ isPanorama: boolean,
1483
+ ): AxisRange | undefined => {
1484
+ const padding = selectXAxisPadding(state, axisId, isPanorama);
1485
+ if (isPanorama) {
1486
+ // The Brush panorama renders in its own Surface (0-origin) sized to the brush
1487
+ // rect; the plot spans the brush width minus the brush padding (its margin).
1488
+ const dims = selectBrushDimensions(state);
1489
+ const brushPadding = state.brush.padding;
1490
+ return [brushPadding.left + padding.left, dims.width - brushPadding.right - padding.right];
1491
+ }
1492
+ const offset = selectChartOffsetInternal(state);
1493
+ return [offset.left + padding.left, offset.left + offset.width - padding.right];
1494
+ };
1495
+
1496
+ export const selectYAxisRange = (
1497
+ state: RechartsRootState,
1498
+ axisId: AxisId,
1499
+ isPanorama: boolean,
1500
+ ): AxisRange | undefined => {
1501
+ const layout = selectChartLayout(state);
1502
+ const padding = selectYAxisPadding(state, axisId, isPanorama);
1503
+ if (isPanorama) {
1504
+ const dims = selectBrushDimensions(state);
1505
+ const brushPadding = state.brush.padding;
1506
+ const top = brushPadding.top + padding.top;
1507
+ const bottom = dims.height - brushPadding.bottom - padding.bottom;
1508
+ // Value axis grows upward → range is [bottom, top]; the panorama is horizontal.
1509
+ return [bottom, top];
1510
+ }
1511
+ const offset = selectChartOffsetInternal(state);
1512
+ if (layout === "horizontal") {
1513
+ return [offset.top + offset.height - padding.bottom, offset.top + padding.top];
1514
+ }
1515
+ return [offset.top + padding.top, offset.top + offset.height - padding.bottom];
1516
+ };
1517
+
1518
+ export const selectAxisRange = (
1519
+ state: RechartsRootState,
1520
+ axisType: AllAxisTypes,
1521
+ axisId: AxisId,
1522
+ isPanorama: boolean,
1523
+ ): AxisRange | undefined => {
1524
+ switch (axisType) {
1525
+ case "xAxis":
1526
+ return selectXAxisRange(state, axisId, isPanorama);
1527
+ case "yAxis":
1528
+ return selectYAxisRange(state, axisId, isPanorama);
1529
+ case "zAxis":
1530
+ return selectZAxisSettings(state, axisId)?.range;
1531
+ case "angleAxis":
1532
+ return selectAngleAxisRange(state);
1533
+ case "radiusAxis":
1534
+ return selectRadiusAxisRange(state, axisId);
1535
+ default:
1536
+ return undefined;
1537
+ }
1538
+ };
1539
+
1540
+ export const selectAxisRangeWithReverse = (
1541
+ state: RechartsRootState,
1542
+ axisType: AllAxisTypes,
1543
+ axisId: AxisId,
1544
+ isPanorama: boolean,
1545
+ ): AxisRange | undefined =>
1546
+ combineAxisRangeWithReverse(
1547
+ selectBaseAxis(state, axisType, axisId),
1548
+ selectAxisRange(state, axisType, axisId, isPanorama),
1549
+ );
1550
+
1551
+ export const selectCheckedAxisDomain = (
1552
+ state: RechartsRootState,
1553
+ axisType: RenderableAxisType,
1554
+ axisId: AxisId,
1555
+ isPanorama: boolean,
1556
+ ): NumberDomain | CategoricalDomain | undefined =>
1557
+ combineCheckedDomain(
1558
+ selectRealScaleType(state, axisType, axisId),
1559
+ selectAxisDomainIncludingNiceTicks(state, axisType, axisId, isPanorama),
1560
+ );
1561
+
1562
+ const selectConfiguredScale = (
1563
+ state: RechartsRootState,
1564
+ axisType: RenderableAxisType,
1565
+ axisId: AxisId,
1566
+ isPanorama: boolean,
1567
+ ): CustomScaleDefinition | undefined =>
1568
+ combineConfiguredScale(
1569
+ selectBaseAxis(state, axisType, axisId),
1570
+ selectRealScaleType(state, axisType, axisId),
1571
+ selectCheckedAxisDomain(state, axisType, axisId, isPanorama),
1572
+ selectAxisRangeWithReverse(state, axisType, axisId, isPanorama),
1573
+ );
1574
+
1575
+ export const combineCategoricalDomain = (
1576
+ layout: LayoutType,
1577
+ appliedValues: AppliedChartData,
1578
+ axis: RenderableAxisSettings,
1579
+ axisType: RenderableAxisType,
1580
+ ): ReadonlyArray<unknown> | undefined => {
1581
+ if (axis == null || axis.dataKey == null) {
1582
+ return undefined;
1583
+ }
1584
+ const { type, scale } = axis;
1585
+ const isCategorical = isCategoricalAxis(layout, axisType);
1586
+ if (isCategorical && (type === "number" || scale !== "auto")) {
1587
+ return appliedValues.map((d) => d.value);
1588
+ }
1589
+ return undefined;
1590
+ };
1591
+
1592
+ export const selectCategoricalDomain = (
1593
+ state: RechartsRootState,
1594
+ axisType: RenderableAxisType,
1595
+ axisId: AxisId,
1596
+ isPanorama: boolean,
1597
+ ): ReadonlyArray<unknown> | undefined =>
1598
+ combineCategoricalDomain(
1599
+ selectChartLayout(state),
1600
+ selectAllAppliedValues(state, axisType, axisId, isPanorama),
1601
+ selectRenderableAxisSettings(state, axisType, axisId),
1602
+ axisType,
1603
+ );
1604
+
1605
+ export const selectAxisScale = (
1606
+ state: RechartsRootState,
1607
+ axisType: RenderableAxisType,
1608
+ axisId: AxisId,
1609
+ isPanorama: boolean,
1610
+ ): RechartsScale | undefined =>
1611
+ rechartsScaleFactory(selectConfiguredScale(state, axisType, axisId, isPanorama));
1612
+
1613
+ /** The ticks the axis component actually rendered (from the renderedTicks slice). */
1614
+ export const selectRenderedTicksOfAxis = (
1615
+ state: RechartsRootState,
1616
+ axisType: "xAxis" | "yAxis",
1617
+ axisId: AxisId,
1618
+ ): ReadonlyArray<TickItem> | undefined => state.renderedTicks[axisType]?.[axisId];
1619
+
1620
+ /**
1621
+ * Maps a pixel coordinate back to a data value (the inverse of the axis scale).
1622
+ * Continuous scales invert; categorical scales snap to the nearest category.
1623
+ */
1624
+ export const selectAxisInverseScale = (
1625
+ state: RechartsRootState,
1626
+ axisType: RenderableAxisType,
1627
+ axisId: AxisId,
1628
+ isPanorama: boolean,
1629
+ ): InverseScaleFunction | undefined =>
1630
+ combineInverseScaleFunction(selectConfiguredScale(state, axisType, axisId, isPanorama));
1631
+
1632
+ /** Inverse scale that snaps a pixel coordinate to the nearest rendered tick value. */
1633
+ export const selectAxisInverseTickSnapScale = (
1634
+ state: RechartsRootState,
1635
+ axisType: "xAxis" | "yAxis",
1636
+ axisId: AxisId,
1637
+ ): InverseScaleFunction | undefined => {
1638
+ const ticks = selectRenderedTicksOfAxis(state, axisType, axisId);
1639
+ if (!ticks || ticks.length === 0) {
1640
+ return undefined;
1641
+ }
1642
+ return (pixelValue: number): unknown => {
1643
+ let minDistance = Infinity;
1644
+ let closestTick: TickItem | undefined = ticks[0];
1645
+ for (const tick of ticks) {
1646
+ const distance = Math.abs(tick.coordinate - pixelValue);
1647
+ if (distance < minDistance) {
1648
+ minDistance = distance;
1649
+ closestTick = tick;
1650
+ }
1651
+ }
1652
+ return closestTick?.value;
1653
+ };
1654
+ };
1655
+
1656
+ export const combineDuplicateDomain = (
1657
+ chartLayout: LayoutType,
1658
+ appliedValues: AppliedChartData,
1659
+ axis: BaseCartesianAxis,
1660
+ axisType: AllAxisTypes,
1661
+ ): ReadonlyArray<unknown> | undefined => {
1662
+ if (axis == null) {
1663
+ return undefined;
1664
+ }
1665
+ const { allowDuplicatedCategory, type, dataKey } = axis;
1666
+ const isCategorical = isCategoricalAxis(chartLayout, axisType);
1667
+ const allData = appliedValues.map((av) => av.value);
1668
+ const validData = allData.filter((v) => v != null);
1669
+ if (
1670
+ dataKey &&
1671
+ isCategorical &&
1672
+ type === "category" &&
1673
+ allowDuplicatedCategory &&
1674
+ hasDuplicate(validData)
1675
+ ) {
1676
+ return allData;
1677
+ }
1678
+ return undefined;
1679
+ };
1680
+
1681
+ export const selectDuplicateDomain = (
1682
+ state: RechartsRootState,
1683
+ axisType: AllAxisTypes,
1684
+ axisId: AxisId,
1685
+ isPanorama: boolean,
1686
+ ): ReadonlyArray<unknown> | undefined =>
1687
+ combineDuplicateDomain(
1688
+ selectChartLayout(state),
1689
+ selectAllAppliedValues(state, axisType, axisId, isPanorama),
1690
+ selectBaseAxis(state, axisType, axisId),
1691
+ axisType,
1692
+ );
1693
+
1694
+ /**
1695
+ * One of four near-identical tick generators. This one feeds graphical items
1696
+ * (e.g. <Line>) rather than the rendered axis ticks.
1697
+ */
1698
+ export const combineGraphicalItemTicks = (
1699
+ layout: LayoutType,
1700
+ axis: RenderableAxisSettings,
1701
+ scale: RechartsScale | undefined,
1702
+ axisRange: AxisRange | undefined,
1703
+ duplicateDomain: ReadonlyArray<unknown> | undefined,
1704
+ categoricalDomain: ReadonlyArray<unknown> | undefined,
1705
+ axisType: RenderableAxisType,
1706
+ ): TickItem[] | undefined => {
1707
+ if (axis == null || scale == null || axisRange == null || axisRange[0] === axisRange[1]) {
1708
+ return undefined;
1709
+ }
1710
+ const isCategorical = isCategoricalAxis(layout, axisType);
1711
+
1712
+ const { tickCount } = axis;
1713
+
1714
+ const offset = 0;
1715
+ // angleAxis adjusts offset by range direction; deferred (polar).
1716
+
1717
+ if (isCategorical && categoricalDomain) {
1718
+ return categoricalDomain
1719
+ .map((entry: unknown, index: number): TickItem | null => {
1720
+ const scaled = scale.map(entry);
1721
+ if (!isWellBehavedNumber(scaled)) {
1722
+ return null;
1723
+ }
1724
+ return {
1725
+ coordinate: scaled + offset,
1726
+ value: entry,
1727
+ index,
1728
+ offset,
1729
+ };
1730
+ })
1731
+ .filter(isNotNil);
1732
+ }
1733
+
1734
+ if (scale.ticks) {
1735
+ return scale
1736
+ .ticks(tickCount)
1737
+ .map((entry: number, index: number): TickItem | null => {
1738
+ const scaled = scale.map(entry);
1739
+ if (!isWellBehavedNumber(scaled)) {
1740
+ return null;
1741
+ }
1742
+ return { coordinate: scaled + offset, value: entry, index, offset };
1743
+ })
1744
+ .filter(isNotNil);
1745
+ }
1746
+
1747
+ // When axis has duplicated text, serial numbers are used to generate scale.
1748
+ return scale
1749
+ .domain()
1750
+ .map((entry: CategoricalDomainItem, index: number): TickItem | null => {
1751
+ const scaled = scale.map(entry);
1752
+ if (!isWellBehavedNumber(scaled)) {
1753
+ return null;
1754
+ }
1755
+ // Deviation: reference indexes `duplicateDomain[entry]` with a
1756
+ // `@ts-expect-error`; the serial case only ever has a numeric `entry`, so
1757
+ // guard on that instead of asserting.
1758
+ const value =
1759
+ duplicateDomain != null && typeof entry === "number" ? duplicateDomain[entry] : entry;
1760
+ return {
1761
+ coordinate: scaled + offset,
1762
+ value,
1763
+ index,
1764
+ offset,
1765
+ };
1766
+ })
1767
+ .filter(isNotNil);
1768
+ };
1769
+
1770
+ export const selectTicksOfGraphicalItem = (
1771
+ state: RechartsRootState,
1772
+ axisType: RenderableAxisType,
1773
+ axisId: AxisId,
1774
+ isPanorama: boolean,
1775
+ ): TickItem[] | undefined =>
1776
+ combineGraphicalItemTicks(
1777
+ selectChartLayout(state),
1778
+ selectRenderableAxisSettings(state, axisType, axisId),
1779
+ selectAxisScale(state, axisType, axisId, isPanorama),
1780
+ selectAxisRange(state, axisType, axisId, isPanorama),
1781
+ selectDuplicateDomain(state, axisType, axisId, isPanorama),
1782
+ selectCategoricalDomain(state, axisType, axisId, isPanorama),
1783
+ axisType,
1784
+ );
1785
+
1786
+ export const selectAxisWithScale = (
1787
+ state: RechartsRootState,
1788
+ axisType: RenderableAxisType,
1789
+ axisId: AxisId,
1790
+ isPanorama: boolean,
1791
+ ): BaseAxisWithScale | undefined => {
1792
+ const axis = selectBaseAxis(state, axisType, axisId);
1793
+ const scale = selectAxisScale(state, axisType, axisId, isPanorama);
1794
+ if (axis == null || scale == null) {
1795
+ return undefined;
1796
+ }
1797
+ return {
1798
+ ...axis,
1799
+ scale,
1800
+ };
1801
+ };
1802
+
1803
+ /**
1804
+ * The size of an axis along its primary dimension (X axis → width, Y axis →
1805
+ * height). Deviation: recharts derives this from selectXAxisSize/selectYAxisSize
1806
+ * (which add tick/label measurement); until those land it's the plot-area span
1807
+ * from the (axis-aware) offset — correct for the bar-size percentage math.
1808
+ */
1809
+ export const selectCartesianAxisSize = (
1810
+ state: RechartsRootState,
1811
+ axisType: RenderableAxisType,
1812
+ _axisId: AxisId,
1813
+ ): number | undefined => {
1814
+ const offset = selectChartOffsetInternal(state);
1815
+ switch (axisType) {
1816
+ case "xAxis":
1817
+ return offset.width;
1818
+ case "yAxis":
1819
+ return offset.height;
1820
+ default:
1821
+ return undefined;
1822
+ }
1823
+ };
1824
+
1825
+ // Re-export tick-item alias used by some consumers.
1826
+ export type { CartesianTickItem, AxisTick };
1827
+
1828
+ // ---------------------------------------------------------------------------
1829
+ // Axis RENDER selectors: position, size, and the rendered ticks that CartesianAxis
1830
+ // (via XAxis/YAxis) draws. Ported from recharts; the multi-axis offset-steps
1831
+ // machinery stacks axes of the same orientation/mirror.
1832
+ // ---------------------------------------------------------------------------
1833
+
1834
+ function compareIds(a: CartesianAxisSettings, b: CartesianAxisSettings): number {
1835
+ if (a.id < b.id) {
1836
+ return -1;
1837
+ }
1838
+ if (a.id > b.id) {
1839
+ return 1;
1840
+ }
1841
+ return 0;
1842
+ }
1843
+
1844
+ const getXAxisSize = (offset: ChartOffsetInternal, axisSettings: XAxisSettings): Size => ({
1845
+ width: offset.width,
1846
+ height: axisSettings.height,
1847
+ });
1848
+
1849
+ const getYAxisSize = (offset: ChartOffsetInternal, axisSettings: YAxisSettings): Size => {
1850
+ const width = typeof axisSettings.width === "number" ? axisSettings.width : DEFAULT_Y_AXIS_WIDTH;
1851
+ return { width, height: offset.height };
1852
+ };
1853
+
1854
+ export const selectXAxisSize = (state: RechartsRootState, xAxisId: AxisId): Size =>
1855
+ getXAxisSize(selectChartOffsetInternal(state), selectXAxisSettings(state, xAxisId));
1856
+
1857
+ export const selectYAxisSize = (state: RechartsRootState, yAxisId: AxisId): Size =>
1858
+ getYAxisSize(selectChartOffsetInternal(state), selectYAxisSettings(state, yAxisId));
1859
+
1860
+ type AxisOffsetSteps = Record<AxisId, number>;
1861
+
1862
+ const selectAllXAxesWithOffsetType = (
1863
+ state: RechartsRootState,
1864
+ orientation: XAxisOrientation,
1865
+ mirror: boolean,
1866
+ ): ReadonlyArray<XAxisSettings> =>
1867
+ selectAllXAxes(state)
1868
+ .filter((axis) => axis.orientation === orientation)
1869
+ .filter((axis) => axis.mirror === mirror)
1870
+ .slice()
1871
+ .sort(compareIds);
1872
+
1873
+ const selectAllYAxesWithOffsetType = (
1874
+ state: RechartsRootState,
1875
+ orientation: YAxisOrientation,
1876
+ mirror: boolean,
1877
+ ): ReadonlyArray<YAxisSettings> =>
1878
+ selectAllYAxes(state)
1879
+ .filter((axis) => axis.orientation === orientation)
1880
+ .filter((axis) => axis.mirror === mirror)
1881
+ .slice()
1882
+ .sort(compareIds);
1883
+
1884
+ const combineXAxisPositionStartingPoint = (
1885
+ offset: ChartOffsetInternal,
1886
+ orientation: XAxisOrientation,
1887
+ chartHeight: number,
1888
+ ): number => {
1889
+ switch (orientation) {
1890
+ case "top":
1891
+ return offset.top;
1892
+ case "bottom":
1893
+ return chartHeight - offset.bottom;
1894
+ default:
1895
+ return 0;
1896
+ }
1897
+ };
1898
+
1899
+ const combineYAxisPositionStartingPoint = (
1900
+ offset: ChartOffsetInternal,
1901
+ orientation: YAxisOrientation,
1902
+ chartWidth: number,
1903
+ ): number => {
1904
+ switch (orientation) {
1905
+ case "left":
1906
+ return offset.left;
1907
+ case "right":
1908
+ return chartWidth - offset.right;
1909
+ default:
1910
+ return 0;
1911
+ }
1912
+ };
1913
+
1914
+ const selectAllXAxesOffsetSteps = (
1915
+ state: RechartsRootState,
1916
+ orientation: XAxisOrientation,
1917
+ mirror: boolean,
1918
+ ): AxisOffsetSteps => {
1919
+ const chartHeight = selectChartHeight(state);
1920
+ const offset = selectChartOffsetInternal(state);
1921
+ const allAxesWithSameOffsetType = selectAllXAxesWithOffsetType(state, orientation, mirror);
1922
+ const steps: AxisOffsetSteps = {};
1923
+ let position: number | undefined;
1924
+ allAxesWithSameOffsetType.forEach((axis) => {
1925
+ const axisSize = getXAxisSize(offset, axis);
1926
+ if (position == null) {
1927
+ position = combineXAxisPositionStartingPoint(offset, orientation, chartHeight);
1928
+ }
1929
+ const needSpace = (orientation === "top" && !mirror) || (orientation === "bottom" && mirror);
1930
+ steps[axis.id] = position - Number(needSpace) * axisSize.height;
1931
+ position += (needSpace ? -1 : 1) * axisSize.height;
1932
+ });
1933
+ return steps;
1934
+ };
1935
+
1936
+ const selectAllYAxesOffsetSteps = (
1937
+ state: RechartsRootState,
1938
+ orientation: YAxisOrientation,
1939
+ mirror: boolean,
1940
+ ): AxisOffsetSteps => {
1941
+ const chartWidth = selectChartWidth(state);
1942
+ const offset = selectChartOffsetInternal(state);
1943
+ const allAxesWithSameOffsetType = selectAllYAxesWithOffsetType(state, orientation, mirror);
1944
+ const steps: AxisOffsetSteps = {};
1945
+ let position: number | undefined;
1946
+ allAxesWithSameOffsetType.forEach((axis) => {
1947
+ const axisSize = getYAxisSize(offset, axis);
1948
+ if (position == null) {
1949
+ position = combineYAxisPositionStartingPoint(offset, orientation, chartWidth);
1950
+ }
1951
+ const needSpace = (orientation === "left" && !mirror) || (orientation === "right" && mirror);
1952
+ steps[axis.id] = position - Number(needSpace) * axisSize.width;
1953
+ position += (needSpace ? -1 : 1) * axisSize.width;
1954
+ });
1955
+ return steps;
1956
+ };
1957
+
1958
+ export const selectXAxisPosition = (
1959
+ state: RechartsRootState,
1960
+ axisId: AxisId,
1961
+ ): Coordinate | undefined => {
1962
+ const offset = selectChartOffsetInternal(state);
1963
+ const axisSettings = selectXAxisSettings(state, axisId);
1964
+ if (axisSettings == null) {
1965
+ return undefined;
1966
+ }
1967
+ const allSteps = selectAllXAxesOffsetSteps(state, axisSettings.orientation, axisSettings.mirror);
1968
+ const stepOfThisAxis = allSteps[axisId];
1969
+ if (stepOfThisAxis == null) {
1970
+ return { x: offset.left, y: 0 };
1971
+ }
1972
+ return { x: offset.left, y: stepOfThisAxis };
1973
+ };
1974
+
1975
+ export const selectYAxisPosition = (
1976
+ state: RechartsRootState,
1977
+ axisId: AxisId,
1978
+ ): Coordinate | undefined => {
1979
+ const offset = selectChartOffsetInternal(state);
1980
+ const axisSettings = selectYAxisSettings(state, axisId);
1981
+ if (axisSettings == null) {
1982
+ return undefined;
1983
+ }
1984
+ const allSteps = selectAllYAxesOffsetSteps(state, axisSettings.orientation, axisSettings.mirror);
1985
+ const stepOfThisAxis = allSteps[axisId];
1986
+ if (stepOfThisAxis == null) {
1987
+ return { x: 0, y: offset.top };
1988
+ }
1989
+ return { x: stepOfThisAxis, y: offset.top };
1990
+ };
1991
+
1992
+ /**
1993
+ * The rendered ticks of an axis (one of recharts' four near-identical tick
1994
+ * generators — this is the CartesianAxis one). Ported verbatim.
1995
+ */
1996
+ export const combineAxisTicks = (
1997
+ layout: LayoutType,
1998
+ axis: RenderableAxisSettings,
1999
+ realScaleType: RechartsScaleType | undefined,
2000
+ scale: RechartsScale | undefined,
2001
+ niceTicks: ReadonlyArray<number> | undefined,
2002
+ axisRange: AxisRange | undefined,
2003
+ duplicateDomain: ReadonlyArray<unknown> | undefined,
2004
+ categoricalDomain: ReadonlyArray<unknown> | undefined,
2005
+ axisType: RenderableAxisType,
2006
+ ): ReadonlyArray<TickItem> | undefined => {
2007
+ if (axis == null || scale == null) {
2008
+ return undefined;
2009
+ }
2010
+
2011
+ const isCategorical = isCategoricalAxis(layout, axisType);
2012
+ const { type, ticks, tickCount } = axis;
2013
+
2014
+ // Deviation: reference compares `realScaleType === "scaleBand"` behind a
2015
+ // `@ts-expect-error` (RechartsScaleType has no such literal — recharts notes it
2016
+ // as a quirk/dead path). `String(...)` keeps the runtime check type-safely.
2017
+ const offsetForBand =
2018
+ String(realScaleType) === "scaleBand" && typeof scale.bandwidth === "function"
2019
+ ? scale.bandwidth() / 2
2020
+ : 2;
2021
+ let offset = type === "category" && scale.bandwidth ? scale.bandwidth() / offsetForBand : 0;
2022
+ offset =
2023
+ axisType === "angleAxis" && axisRange != null && axisRange.length >= 2
2024
+ ? mathSign(axisRange[0] - axisRange[1]) * 2 * offset
2025
+ : offset;
2026
+
2027
+ // User-provided ticks (or niceTicks) take precedence.
2028
+ const ticksOrNiceTicks = ticks || niceTicks;
2029
+ if (ticksOrNiceTicks) {
2030
+ return ticksOrNiceTicks
2031
+ .map((entry: AxisTick, index: number): TickItem | null => {
2032
+ const scaleContent = duplicateDomain ? duplicateDomain.indexOf(entry) : entry;
2033
+ const scaled = scale.map(scaleContent);
2034
+ if (!isWellBehavedNumber(scaled)) {
2035
+ return null;
2036
+ }
2037
+ return { index, coordinate: scaled + offset, value: entry, offset };
2038
+ })
2039
+ .filter(isNotNil);
2040
+ }
2041
+
2042
+ if (isCategorical && categoricalDomain) {
2043
+ return categoricalDomain
2044
+ .map((entry: unknown, index: number): TickItem | null => {
2045
+ const scaled = scale.map(entry);
2046
+ if (!isWellBehavedNumber(scaled)) {
2047
+ return null;
2048
+ }
2049
+ return { coordinate: scaled + offset, value: entry, index, offset };
2050
+ })
2051
+ .filter(isNotNil);
2052
+ }
2053
+
2054
+ if (scale.ticks) {
2055
+ return scale
2056
+ .ticks(tickCount)
2057
+ .map((entry: number, index: number): TickItem | null => {
2058
+ const scaled = scale.map(entry);
2059
+ if (!isWellBehavedNumber(scaled)) {
2060
+ return null;
2061
+ }
2062
+ return { coordinate: scaled + offset, value: entry, index, offset };
2063
+ })
2064
+ .filter(isNotNil);
2065
+ }
2066
+
2067
+ return scale
2068
+ .domain()
2069
+ .map((entry: CategoricalDomainItem, index: number): TickItem | null => {
2070
+ const scaled = scale.map(entry);
2071
+ if (!isWellBehavedNumber(scaled)) {
2072
+ return null;
2073
+ }
2074
+ // Deviation: reference indexes `duplicateDomain[entry]` with `@ts-expect-error`;
2075
+ // the serial case only has numeric entries, so guard on that.
2076
+ const value =
2077
+ duplicateDomain != null && typeof entry === "number" ? duplicateDomain[entry] : entry;
2078
+ return { coordinate: scaled + offset, value, index, offset };
2079
+ })
2080
+ .filter(isNotNil);
2081
+ };
2082
+
2083
+ export const selectTicksOfAxis = (
2084
+ state: RechartsRootState,
2085
+ axisType: RenderableAxisType,
2086
+ axisId: AxisId,
2087
+ isPanorama: boolean,
2088
+ ): ReadonlyArray<TickItem> | undefined =>
2089
+ combineAxisTicks(
2090
+ selectChartLayout(state),
2091
+ selectRenderableAxisSettings(state, axisType, axisId),
2092
+ selectRealScaleType(state, axisType, axisId),
2093
+ selectAxisScale(state, axisType, axisId, isPanorama),
2094
+ selectNiceTicks(state, axisType, axisId, isPanorama),
2095
+ selectAxisRange(state, axisType, axisId, isPanorama),
2096
+ selectDuplicateDomain(state, axisType, axisId, isPanorama),
2097
+ selectCategoricalDomain(state, axisType, axisId, isPanorama),
2098
+ pickAxisType(state, axisType),
2099
+ );
2100
+
2101
+ /**
2102
+ * The bundle of axis props that CartesianGrid passes to its coordinate
2103
+ * generators (and to the custom horizontal/vertical render-prop functions).
2104
+ * Ported from recharts' AxisPropsForCartesianGridTicksGeneration.
2105
+ */
2106
+ export type AxisPropsForCartesianGridTicksGeneration = {
2107
+ angle: number;
2108
+ interval: CartesianAxisSettings["interval"];
2109
+ minTickGap: number;
2110
+ orientation: XAxisOrientation | YAxisOrientation;
2111
+ tick: CartesianAxisSettings["tick"];
2112
+ tickCount: number | undefined;
2113
+ tickFormatter: CartesianAxisSettings["tickFormatter"];
2114
+ ticks: ReadonlyArray<AxisTick> | undefined;
2115
+ type: "number" | "category";
2116
+ unit: string | undefined;
2117
+ axisType: AxisType;
2118
+ categoricalDomain: ReadonlyArray<unknown> | undefined;
2119
+ duplicateDomain: ReadonlyArray<unknown> | undefined;
2120
+ isCategorical: boolean;
2121
+ niceTicks: ReadonlyArray<number> | undefined;
2122
+ range: AxisRange | undefined;
2123
+ realScaleType: string | undefined;
2124
+ scale: RechartsScale | undefined;
2125
+ };
2126
+
2127
+ /**
2128
+ * Builds the AxisPropsForCartesianGridTicksGeneration payload from the store —
2129
+ * the data CartesianGrid feeds to its default (and custom) coordinate
2130
+ * generators. Ported from recharts selectAxisPropsNeededForCartesianGridTicksGenerator.
2131
+ */
2132
+ export const selectAxisPropsNeededForCartesianGridTicksGenerator = (
2133
+ state: RechartsRootState,
2134
+ axisType: "xAxis" | "yAxis",
2135
+ axisId: AxisId,
2136
+ isPanorama: boolean,
2137
+ ): AxisPropsForCartesianGridTicksGeneration | undefined => {
2138
+ const cartesianAxis: XAxisSettings | YAxisSettings =
2139
+ axisType === "xAxis" ? selectXAxisSettings(state, axisId) : selectYAxisSettings(state, axisId);
2140
+ if (cartesianAxis == null) {
2141
+ return undefined;
2142
+ }
2143
+ const layout = selectChartLayout(state);
2144
+ const isCategorical = isCategoricalAxis(layout, axisType);
2145
+ return {
2146
+ angle: cartesianAxis.angle,
2147
+ interval: cartesianAxis.interval,
2148
+ minTickGap: cartesianAxis.minTickGap,
2149
+ orientation: cartesianAxis.orientation,
2150
+ tick: cartesianAxis.tick,
2151
+ tickCount: cartesianAxis.tickCount,
2152
+ tickFormatter: cartesianAxis.tickFormatter,
2153
+ ticks: cartesianAxis.ticks,
2154
+ type: cartesianAxis.type,
2155
+ unit: cartesianAxis.unit,
2156
+ axisType,
2157
+ categoricalDomain: selectCategoricalDomain(state, axisType, axisId, isPanorama),
2158
+ duplicateDomain: selectDuplicateDomain(state, axisType, axisId, isPanorama),
2159
+ isCategorical,
2160
+ niceTicks: selectNiceTicks(state, axisType, axisId, isPanorama),
2161
+ range: selectAxisRange(state, axisType, axisId, isPanorama),
2162
+ realScaleType: selectRealScaleType(state, axisType, axisId),
2163
+ scale: selectAxisScale(state, axisType, axisId, isPanorama),
2164
+ };
2165
+ };
2166
+
2167
+ // ---------------------------------------------------------------------------
2168
+ // Z axis scale (Scatter point size). The z scale maps the z data value to a
2169
+ // "size" (area); Scatter turns that into a radius. Ported from recharts.
2170
+ // ---------------------------------------------------------------------------
2171
+
2172
+ export type ZAxisWithScale = Omit<ZAxisSettings, "scale"> & { scale: RechartsScale };
2173
+
2174
+ const selectZAxisScale = (state: RechartsRootState, axisId: AxisId): RechartsScale | undefined =>
2175
+ rechartsScaleFactory(
2176
+ combineConfiguredScale(
2177
+ selectBaseAxis(state, "zAxis", axisId),
2178
+ selectRealScaleType(state, "zAxis", axisId),
2179
+ selectAxisDomain(state, "zAxis", axisId, false),
2180
+ selectAxisRangeWithReverse(state, "zAxis", axisId, false),
2181
+ ),
2182
+ );
2183
+
2184
+ export const selectZAxisWithScale = (
2185
+ state: RechartsRootState,
2186
+ _axisType: "zAxis",
2187
+ axisId: AxisId,
2188
+ _isPanorama: boolean,
2189
+ ): ZAxisWithScale | undefined => {
2190
+ const axis = selectZAxisSettings(state, axisId);
2191
+ const scale = selectZAxisScale(state, axisId);
2192
+ if (axis == null || scale == null) {
2193
+ return undefined;
2194
+ }
2195
+ return { ...axis, scale };
2196
+ };