@solidports/recharts 0.1.0 → 0.1.1

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 (304) hide show
  1. package/dist/index.d.ts +40 -2
  2. package/dist/index.js +14238 -7174
  3. package/dist/{dev.js → index.jsx} +18367 -15900
  4. package/dist/server.js +48178 -0
  5. package/package.json +36 -19
  6. package/src/animation/AnimatedItems.tsx +0 -183
  7. package/src/animation/AnimationController.ts +0 -33
  8. package/src/animation/AnimationControllerImpl.ts +0 -36
  9. package/src/animation/AnimationHandle.ts +0 -307
  10. package/src/animation/CSSTransitionAnimate.tsx +0 -170
  11. package/src/animation/JavascriptAnimate.tsx +0 -119
  12. package/src/animation/easing.ts +0 -221
  13. package/src/animation/matchBy.ts +0 -164
  14. package/src/animation/timeoutController.ts +0 -70
  15. package/src/animation/useAnimationController.tsx +0 -34
  16. package/src/animation/useAnimationStartSnapshot.ts +0 -118
  17. package/src/animation/util.ts +0 -41
  18. package/src/cartesian/Area.tsx +0 -915
  19. package/src/cartesian/AreaRevealShape.tsx +0 -190
  20. package/src/cartesian/Bar.tsx +0 -1369
  21. package/src/cartesian/BarStack.tsx +0 -152
  22. package/src/cartesian/Brush.tsx +0 -951
  23. package/src/cartesian/CartesianAxis.tsx +0 -722
  24. package/src/cartesian/CartesianGrid.tsx +0 -711
  25. package/src/cartesian/ErrorBar.tsx +0 -361
  26. package/src/cartesian/Funnel.tsx +0 -803
  27. package/src/cartesian/GraphicalItemClipPath.tsx +0 -67
  28. package/src/cartesian/Line.tsx +0 -863
  29. package/src/cartesian/LineDrawShape.tsx +0 -89
  30. package/src/cartesian/ReferenceArea.tsx +0 -331
  31. package/src/cartesian/ReferenceDot.tsx +0 -304
  32. package/src/cartesian/ReferenceLine.tsx +0 -474
  33. package/src/cartesian/Scatter.tsx +0 -888
  34. package/src/cartesian/XAxis.tsx +0 -433
  35. package/src/cartesian/YAxis.tsx +0 -443
  36. package/src/cartesian/ZAxis.tsx +0 -155
  37. package/src/cartesian/cartesianPositionToCSSTranslate.tsx +0 -29
  38. package/src/cartesian/cartesianViewBoxToTrapezoid.tsx +0 -21
  39. package/src/cartesian/getCartesianPosition.tsx +0 -267
  40. package/src/cartesian/getEquidistantTicks.ts +0 -144
  41. package/src/cartesian/getTicks.ts +0 -225
  42. package/src/cartesian/isOutsidePosition.ts +0 -15
  43. package/src/cartesian/useAnimatedLineLength.ts +0 -54
  44. package/src/chart/AreaChart.tsx +0 -29
  45. package/src/chart/BarChart.tsx +0 -29
  46. package/src/chart/CartesianChart.tsx +0 -131
  47. package/src/chart/CategoricalChart.tsx +0 -94
  48. package/src/chart/ComposedChart.tsx +0 -29
  49. package/src/chart/FunnelChart.tsx +0 -29
  50. package/src/chart/LineChart.tsx +0 -29
  51. package/src/chart/PieChart.tsx +0 -50
  52. package/src/chart/PolarChart.tsx +0 -164
  53. package/src/chart/RadarChart.tsx +0 -70
  54. package/src/chart/RadialBarChart.tsx +0 -46
  55. package/src/chart/RechartsWrapper.tsx +0 -551
  56. package/src/chart/Sankey.tsx +0 -1534
  57. package/src/chart/ScatterChart.tsx +0 -29
  58. package/src/chart/SunburstChart.tsx +0 -504
  59. package/src/chart/Treemap.tsx +0 -1223
  60. package/src/chart/createInitialRootProps.ts +0 -24
  61. package/src/chart/types.ts +0 -53
  62. package/src/component/ActivePoints.tsx +0 -144
  63. package/src/component/Cell.tsx +0 -37
  64. package/src/component/Cursor.tsx +0 -185
  65. package/src/component/Customized.tsx +0 -50
  66. package/src/component/DefaultLegendContent.tsx +0 -348
  67. package/src/component/DefaultTooltipContent.tsx +0 -224
  68. package/src/component/Dots.tsx +0 -157
  69. package/src/component/Label.tsx +0 -636
  70. package/src/component/LabelList.tsx +0 -375
  71. package/src/component/Legend.tsx +0 -512
  72. package/src/component/ResponsiveContainer.tsx +0 -348
  73. package/src/component/Text.tsx +0 -541
  74. package/src/component/Tooltip.tsx +0 -470
  75. package/src/component/TooltipBoundingBox.tsx +0 -146
  76. package/src/component/responsiveContainerUtils.ts +0 -134
  77. package/src/container/ClipPathProvider.tsx +0 -51
  78. package/src/container/Layer.tsx +0 -38
  79. package/src/container/RootSurface.tsx +0 -120
  80. package/src/container/Surface.tsx +0 -61
  81. package/src/context/CellsContext.tsx +0 -54
  82. package/src/context/ErrorBarContext.tsx +0 -146
  83. package/src/context/GraphicalItemChildrenScope.tsx +0 -18
  84. package/src/context/PanoramaContext.tsx +0 -9
  85. package/src/context/RegisterGraphicalItemId.tsx +0 -30
  86. package/src/context/accessibilityContext.tsx +0 -6
  87. package/src/context/brushUpdateContext.tsx +0 -9
  88. package/src/context/chartDataContext.tsx +0 -97
  89. package/src/context/chartLayoutContext.tsx +0 -201
  90. package/src/context/legendPayloadContext.tsx +0 -20
  91. package/src/context/legendPortalContext.tsx +0 -12
  92. package/src/context/tooltipContext.tsx +0 -89
  93. package/src/context/tooltipPortalContext.tsx +0 -12
  94. package/src/context/useTooltipAxis.ts +0 -22
  95. package/src/hooks.ts +0 -476
  96. package/src/index.ts +0 -280
  97. package/src/polar/Pie.tsx +0 -1360
  98. package/src/polar/PolarAngleAxis.tsx +0 -616
  99. package/src/polar/PolarGrid.tsx +0 -312
  100. package/src/polar/PolarRadiusAxis.tsx +0 -547
  101. package/src/polar/Radar.tsx +0 -734
  102. package/src/polar/RadialBar.tsx +0 -917
  103. package/src/polar/defaultPolarAngleAxisProps.tsx +0 -27
  104. package/src/polar/defaultPolarRadiusAxisProps.tsx +0 -25
  105. package/src/shape/Cross.tsx +0 -89
  106. package/src/shape/Curve.tsx +0 -343
  107. package/src/shape/Dot.tsx +0 -70
  108. package/src/shape/Polygon.tsx +0 -195
  109. package/src/shape/Rectangle.tsx +0 -470
  110. package/src/shape/Sector.tsx +0 -347
  111. package/src/shape/Symbols.tsx +0 -139
  112. package/src/shape/Trapezoid.tsx +0 -280
  113. package/src/state/RechartsStateContext.tsx +0 -12
  114. package/src/state/RechartsStateProvider.tsx +0 -87
  115. package/src/state/RechartsStoreContext.tsx +0 -25
  116. package/src/state/RechartsStoreProvider.tsx +0 -35
  117. package/src/state/ReportChartProps.tsx +0 -40
  118. package/src/state/ReportEventSettings.tsx +0 -30
  119. package/src/state/ReportMainChartProps.tsx +0 -61
  120. package/src/state/ReportPolarOptions.tsx +0 -35
  121. package/src/state/SetGraphicalItem.ts +0 -79
  122. package/src/state/SetLegendPayload.ts +0 -134
  123. package/src/state/SetTooltipEntrySettings.tsx +0 -72
  124. package/src/state/actions.ts +0 -464
  125. package/src/state/brushSlice.ts +0 -13
  126. package/src/state/cartesianAxisSlice.ts +0 -141
  127. package/src/state/chartDataSlice.ts +0 -50
  128. package/src/state/chartState.ts +0 -297
  129. package/src/state/errorBarSlice.ts +0 -29
  130. package/src/state/eventSettingsSlice.ts +0 -8
  131. package/src/state/events.ts +0 -76
  132. package/src/state/externalEventsMiddleware.ts +0 -255
  133. package/src/state/graphicalItemsSlice.ts +0 -74
  134. package/src/state/hooks/useChartSelectors.tsx +0 -45
  135. package/src/state/keyboardEventsMiddleware.ts +0 -228
  136. package/src/state/layoutSlice.ts +0 -21
  137. package/src/state/legendSlice.ts +0 -57
  138. package/src/state/mouseEventsMiddleware.ts +0 -185
  139. package/src/state/optionsSlice.ts +0 -47
  140. package/src/state/polarAxisSlice.ts +0 -10
  141. package/src/state/polarOptionsSlice.ts +0 -12
  142. package/src/state/rawData.ts +0 -26
  143. package/src/state/referenceElementsSlice.ts +0 -40
  144. package/src/state/renderedTicksSlice.ts +0 -15
  145. package/src/state/rootPropsSlice.ts +0 -47
  146. package/src/state/selectors/areaSelectors.ts +0 -240
  147. package/src/state/selectors/arrayEqualityCheck.ts +0 -29
  148. package/src/state/selectors/axisSelectors.ts +0 -2157
  149. package/src/state/selectors/barSelectors.ts +0 -310
  150. package/src/state/selectors/barStackSelectors.ts +0 -77
  151. package/src/state/selectors/brushSelectors.ts +0 -33
  152. package/src/state/selectors/chartSelector.ts +0 -185
  153. package/src/state/selectors/combiners/combineActiveLabel.ts +0 -16
  154. package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +0 -95
  155. package/src/state/selectors/combiners/combineAllBarPositions.ts +0 -122
  156. package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +0 -16
  157. package/src/state/selectors/combiners/combineBarPosition.ts +0 -23
  158. package/src/state/selectors/combiners/combineBarSizeList.ts +0 -80
  159. package/src/state/selectors/combiners/combineCheckedDomain.ts +0 -48
  160. package/src/state/selectors/combiners/combineConfiguredScale.ts +0 -111
  161. package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +0 -45
  162. package/src/state/selectors/combiners/combineDisplayedStackedData.ts +0 -50
  163. package/src/state/selectors/combiners/combineInverseScaleFunction.ts +0 -16
  164. package/src/state/selectors/combiners/combineRealScaleType.ts +0 -44
  165. package/src/state/selectors/combiners/combineStackedData.ts +0 -27
  166. package/src/state/selectors/combiners/combineTooltipInteractionState.ts +0 -86
  167. package/src/state/selectors/combiners/combineTooltipPayload.ts +0 -205
  168. package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +0 -58
  169. package/src/state/selectors/containerSelectors.ts +0 -12
  170. package/src/state/selectors/dataSelectors.ts +0 -88
  171. package/src/state/selectors/funnelSelectors.ts +0 -75
  172. package/src/state/selectors/graphicalItemSelectors.ts +0 -30
  173. package/src/state/selectors/legendSelectors.ts +0 -29
  174. package/src/state/selectors/lineSelectors.ts +0 -134
  175. package/src/state/selectors/numberDomainEqualityCheck.ts +0 -14
  176. package/src/state/selectors/pickAxisId.ts +0 -5
  177. package/src/state/selectors/pickAxisType.ts +0 -3
  178. package/src/state/selectors/pieSelectors.ts +0 -97
  179. package/src/state/selectors/polarAxisSelectors.ts +0 -201
  180. package/src/state/selectors/polarGridSelectors.ts +0 -28
  181. package/src/state/selectors/polarScaleSelectors.ts +0 -133
  182. package/src/state/selectors/polarSelectors.ts +0 -219
  183. package/src/state/selectors/radarSelectors.ts +0 -191
  184. package/src/state/selectors/radialBarSelectors.ts +0 -435
  185. package/src/state/selectors/rootPropsSelectors.ts +0 -25
  186. package/src/state/selectors/scatterSelectors.ts +0 -96
  187. package/src/state/selectors/selectActivePropsFromChartPointer.ts +0 -26
  188. package/src/state/selectors/selectAllAxes.ts +0 -17
  189. package/src/state/selectors/selectChartOffset.ts +0 -16
  190. package/src/state/selectors/selectChartOffsetInternal.ts +0 -136
  191. package/src/state/selectors/selectLegendArea.ts +0 -20
  192. package/src/state/selectors/selectPlotArea.ts +0 -22
  193. package/src/state/selectors/selectTooltipAxisId.ts +0 -7
  194. package/src/state/selectors/selectTooltipAxisType.ts +0 -32
  195. package/src/state/selectors/selectTooltipEventType.ts +0 -48
  196. package/src/state/selectors/selectTooltipPayloadSearcher.ts +0 -6
  197. package/src/state/selectors/selectTooltipSettings.ts +0 -39
  198. package/src/state/selectors/selectTooltipState.ts +0 -8
  199. package/src/state/selectors/selectors.ts +0 -271
  200. package/src/state/selectors/tooltipSelectors.ts +0 -578
  201. package/src/state/selectors/touchSelectors.ts +0 -31
  202. package/src/state/store.ts +0 -29
  203. package/src/state/storeIdentity.ts +0 -9
  204. package/src/state/teardownWrite.ts +0 -10
  205. package/src/state/tooltipInteraction.ts +0 -23
  206. package/src/state/tooltipSlice.ts +0 -334
  207. package/src/state/touchEventsMiddleware.ts +0 -214
  208. package/src/state/types/AnimationSettings.ts +0 -20
  209. package/src/state/types/AreaSettings.ts +0 -14
  210. package/src/state/types/BarSettings.ts +0 -15
  211. package/src/state/types/LineSettings.ts +0 -9
  212. package/src/state/types/PieSettings.ts +0 -34
  213. package/src/state/types/RadarSettings.ts +0 -5
  214. package/src/state/types/RadialBarSettings.ts +0 -10
  215. package/src/state/types/ScatterSettings.ts +0 -12
  216. package/src/state/types/StackedGraphicalItem.ts +0 -34
  217. package/src/state/useChartState.ts +0 -17
  218. package/src/state/zIndexSlice.ts +0 -39
  219. package/src/synchronisation/syncSelectors.ts +0 -7
  220. package/src/synchronisation/types.ts +0 -44
  221. package/src/synchronisation/useChartSynchronisation.tsx +0 -404
  222. package/src/theme/RechartsTheme.ts +0 -16
  223. package/src/theme/RechartsThemeContext.ts +0 -19
  224. package/src/theme/darkTheme.ts +0 -13
  225. package/src/theme/graphicalItemIdentity.ts +0 -70
  226. package/src/theme/legacyTheme.ts +0 -17
  227. package/src/theme/lightTheme.ts +0 -13
  228. package/src/types.ts +0 -54
  229. package/src/util/ActiveShapeUtils.tsx +0 -162
  230. package/src/util/BarUtils.tsx +0 -62
  231. package/src/util/BarePortal.tsx +0 -50
  232. package/src/util/CamelCaseSVGAttrs.ts +0 -34
  233. package/src/util/CartesianUtils.ts +0 -48
  234. package/src/util/ChartUtils.ts +0 -802
  235. package/src/util/Constants.ts +0 -42
  236. package/src/util/CssPrefixUtils.ts +0 -20
  237. package/src/util/DOMUtils.ts +0 -129
  238. package/src/util/DataUtils.ts +0 -216
  239. package/src/util/Events.ts +0 -16
  240. package/src/util/FunnelUtils.tsx +0 -15
  241. package/src/util/Global.ts +0 -12
  242. package/src/util/IfOverflow.ts +0 -15
  243. package/src/util/LRUCache.ts +0 -41
  244. package/src/util/LogUtils.ts +0 -22
  245. package/src/util/PolarUtils.ts +0 -132
  246. package/src/util/RadialBarUtils.tsx +0 -24
  247. package/src/util/ReactUtils.ts +0 -95
  248. package/src/util/ReduceCSSCalc.ts +0 -187
  249. package/src/util/ScatterUtils.tsx +0 -52
  250. package/src/util/ShapeElementProps.tsx +0 -87
  251. package/src/util/TickUtils.ts +0 -60
  252. package/src/util/XAxisUtils.ts +0 -48
  253. package/src/util/YAxisUtils.ts +0 -48
  254. package/src/util/axisPropsAreEqual.ts +0 -48
  255. package/src/util/createCartesianCharts.tsx +0 -150
  256. package/src/util/createEventProxy.ts +0 -20
  257. package/src/util/createPolarCharts.tsx +0 -112
  258. package/src/util/cursor/getCursorPoints.ts +0 -46
  259. package/src/util/cursor/getCursorRectangle.ts +0 -28
  260. package/src/util/cursor/getRadialCursorPoints.ts +0 -32
  261. package/src/util/excludeEventProps.ts +0 -171
  262. package/src/util/getActiveCoordinate.ts +0 -213
  263. package/src/util/getAxisTypeBasedOnLayout.ts +0 -21
  264. package/src/util/getClassNameFromUnknown.ts +0 -6
  265. package/src/util/getEveryNth.ts +0 -27
  266. package/src/util/getRadiusAndStrokeWidthFromDot.ts +0 -35
  267. package/src/util/getRelativeCoordinate.ts +0 -80
  268. package/src/util/getSliced.ts +0 -13
  269. package/src/util/hoverDedupe.ts +0 -41
  270. package/src/util/isDomainSpecifiedByUser.ts +0 -219
  271. package/src/util/isWellBehavedNumber.ts +0 -7
  272. package/src/util/pathTotalLength.ts +0 -25
  273. package/src/util/payload/getUniqPayload.ts +0 -28
  274. package/src/util/propsAreEqual.ts +0 -121
  275. package/src/util/resolveDefaultProps.ts +0 -161
  276. package/src/util/round.ts +0 -32
  277. package/src/util/scale/CartesianScaleHelper.ts +0 -72
  278. package/src/util/scale/CustomScaleDefinition.ts +0 -81
  279. package/src/util/scale/RechartsScale.ts +0 -130
  280. package/src/util/scale/createCategoricalInverse.ts +0 -72
  281. package/src/util/scale/getNiceTickValues.ts +0 -311
  282. package/src/util/scale/index.ts +0 -2
  283. package/src/util/scale/util/arithmetic.ts +0 -54
  284. package/src/util/solid-1-compat.ts +0 -310
  285. package/src/util/solidJsxCamelAugment.d.ts +0 -84
  286. package/src/util/stacks/getStackSeriesIdentifier.ts +0 -21
  287. package/src/util/stacks/stackTypes.ts +0 -60
  288. package/src/util/structurallyEqual.ts +0 -31
  289. package/src/util/svgPropertiesAndEvents.ts +0 -53
  290. package/src/util/svgPropertiesNoEvents.ts +0 -571
  291. package/src/util/tooltip/translate.ts +0 -171
  292. package/src/util/typedDataKey.ts +0 -48
  293. package/src/util/types.ts +0 -1560
  294. package/src/util/useAnimationId.ts +0 -31
  295. package/src/util/useElementOffset.ts +0 -110
  296. package/src/util/useId.ts +0 -8
  297. package/src/util/usePrefersReducedMotion.ts +0 -48
  298. package/src/util/useReportScale.ts +0 -24
  299. package/src/util/useUniqueId.ts +0 -30
  300. package/src/zIndex/DefaultZIndexes.ts +0 -84
  301. package/src/zIndex/ZIndexLayer.tsx +0 -121
  302. package/src/zIndex/ZIndexPortal.tsx +0 -79
  303. package/src/zIndex/getZIndexFromUnknown.ts +0 -14
  304. package/src/zIndex/zIndexSelectors.ts +0 -48
@@ -1,1369 +0,0 @@
1
- /* eslint-disable import/no-cycle, sort-keys */
2
- import type { Formatter } from "../component/DefaultTooltipContent"
3
- import { createEffect, createMemo, createSignal, For, Show, untrack, createRenderEffect } from 'solid-js';
4
- import { createHoverDedupe } from "../util/hoverDedupe"
5
- import type { JSX } from '@solidjs/web';
6
- import { clsx } from "clsx"
7
- import type { StackSeries } from "../util/stacks/stackTypes"
8
- import type { Props as RectangleProps, RectRadius } from "../shape/Rectangle"
9
- import { Layer } from "../container/Layer"
10
- import type { ErrorBarDataItem, ErrorBarDataPointFormatter } from "./ErrorBar"
11
- import {
12
- LabelListContextBridge,
13
- CartesianLabelListContextProvider,
14
- type CartesianLabelListEntry,
15
- type ImplicitLabelListType,
16
- LabelListFromLabelProp,
17
- } from "../component/LabelList"
18
- import { interpolate, isNan, mathSign, noop } from "../util/DataUtils"
19
- import {
20
- type BarPositionPosition,
21
- getBaseValueOfBar,
22
- getCateCoordinateOfBar,
23
- getTooltipNameProp,
24
- getValueByDataKey,
25
- type StackId,
26
- truncateByDomain,
27
- } from "../util/ChartUtils"
28
- import { adaptEventsOfChild } from "../util/types"
29
- import type {
30
- ActiveShape,
31
- AnimationDuration,
32
- CartesianViewBoxRequired,
33
- ChartOffsetInternal,
34
- Coordinate,
35
- DataConsumer,
36
- DataKey,
37
- LegendType,
38
- PresentationAttributesAdaptChildEvent,
39
- ShapeAnimationProps,
40
- TickItem,
41
- TooltipType,
42
- TrapezoidViewBox,
43
- } from "../util/types"
44
- import {
45
- BarRectangle,
46
- type BarRectangleProps,
47
- defaultBarShape,
48
- type MinPointSize,
49
- minPointSizeCallback,
50
- } from "../util/BarUtils"
51
- import { getRectanglePath } from "../shape/Rectangle"
52
- import { round } from "../util/round"
53
- import type { LegendPayload } from "../component/DefaultLegendContent"
54
- import {
55
- useMouseClickItemDispatch,
56
- useMouseEnterItemDispatch,
57
- useMouseLeaveItemDispatch,
58
- } from "../context/tooltipContext"
59
- import type { TooltipPayloadConfiguration } from "../state/tooltipSlice"
60
- import { SetTooltipEntrySettings } from "../state/SetTooltipEntrySettings"
61
- import { SetErrorBarContext } from "../context/ErrorBarContext"
62
- import { GraphicalItemClipPath, useNeedsClip } from "./GraphicalItemClipPath"
63
- import { useChartLayout } from "../context/chartLayoutContext"
64
- import { selectBarRectangles } from "../state/selectors/barSelectors"
65
- import type { BaseAxisWithScale } from "../state/selectors/axisSelectors"
66
- import { useChartStore } from "../state/RechartsStoreContext"
67
- import { useIsPanorama } from "../context/PanoramaContext"
68
- import { selectActiveTooltipDataKey, selectActiveTooltipIndex } from "../state/selectors/tooltipSelectors"
69
- import { SetLegendPayload } from "../state/SetLegendPayload"
70
- import { resolveDefaultProps } from "../util/resolveDefaultProps"
71
- import { RegisterGraphicalItemId } from "../context/RegisterGraphicalItemId"
72
- import type { BarSettings } from "../state/types/BarSettings"
73
- import { SetCartesianGraphicalItem } from "../state/SetGraphicalItem"
74
- import { svgPropertiesNoEvents, svgPropertiesNoEventsFromUnknown } from "../util/svgPropertiesNoEvents"
75
- import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
76
- import { isEventKey } from "../util/excludeEventProps"
77
- import { createCellsRegistry, useCellsRegistry } from "../context/CellsContext"
78
- import { AnimatedItems, useAnimationCallbacks } from "../animation/AnimatedItems"
79
- import type { AnimationInterpolateFn } from "../animation/AnimatedItems"
80
- import { matchAppend } from "../animation/matchBy"
81
- import type { AnimationMatchByProp } from "../animation/matchBy"
82
- import type { CartesianLayout } from "../util/types"
83
- import type { EasingInput } from "../animation/easing"
84
- import type { ZIndexable } from "../zIndex/ZIndexLayer"
85
- import { ZIndexLayer } from "../zIndex/ZIndexLayer"
86
- import { DefaultZIndexes } from "../zIndex/DefaultZIndexes"
87
- import { getZIndexFromUnknown } from "../zIndex/getZIndexFromUnknown"
88
- import type { AxisId } from "../state/cartesianAxisSlice"
89
- import { BarStackClipLayer, useBarStackClipPathUrl, useStackId } from "./BarStack"
90
- import type { GraphicalItemId } from "../state/graphicalItemsSlice"
91
- import type { ChartData } from "../state/chartDataSlice"
92
-
93
- import { mergeProps, splitProps } from '../util/solid-1-compat';
94
- type BarRectangleType = {
95
- x: number | null
96
- y: number | null
97
- width: number
98
- height: number
99
- }
100
-
101
- export interface BarRectangleItem extends RectangleProps {
102
- value: number | [number, number]
103
- /** the coordinate of background rectangle */
104
- background?: BarRectangleType
105
- tooltipPosition: Coordinate
106
- readonly payload?: unknown
107
- parentViewBox: CartesianViewBoxRequired
108
- x: number
109
- y: number
110
- width: number
111
- height: number
112
- /**
113
- * Chart range coordinate of the baseValue of the first bar in a stack.
114
- */
115
- stackedBarStart: number
116
- originalDataIndex: number
117
- }
118
-
119
- export type BarShapeProps = BarRectangleItem &
120
- ShapeAnimationProps & {
121
- isActive: boolean
122
- index: number
123
- option?: ActiveShape<BarShapeProps, SVGPathElement> | undefined
124
- }
125
-
126
- export interface BarProps<DataPointType = unknown, DataValueType = unknown>
127
- extends DataConsumer<DataPointType, DataValueType>, ZIndexable {
128
- className?: string
129
- index?: string | number
130
- xAxisId?: AxisId
131
- yAxisId?: AxisId
132
- stackId?: StackId
133
- barSize?: string | number
134
- unit?: string | number
135
- name?: string | number
136
- tooltipType?: TooltipType
137
- /**
138
- * Formats the value displayed in the tooltip for this Bar.
139
- * When set, takes precedence over the `formatter` prop on the Tooltip component.
140
- */
141
- formatter?: Formatter
142
- legendType?: LegendType
143
- minPointSize?: MinPointSize
144
- maxBarSize?: number
145
- hide?: boolean
146
- shape?: ActiveShape<BarShapeProps, SVGPathElement>
147
- activeBar?: ActiveShape<BarShapeProps, SVGPathElement>
148
- background?: ActiveShape<BarShapeProps, SVGPathElement> & ZIndexable
149
- radius?: RectRadius
150
- onAnimationStart?: () => void
151
- onAnimationEnd?: () => void
152
- isAnimationActive?: boolean | "auto"
153
- animationBegin?: number
154
- animationDuration?: AnimationDuration
155
- animationEasing?: EasingInput
156
- /**
157
- * Custom animation function for interpolating data items.
158
- * When provided, this replaces the default animation interpolation.
159
- *
160
- * @since 3.9
161
- * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
162
- */
163
- animationInterpolateFn?: AnimationInterpolateFn<BarRectangleItem, CartesianLayout>
164
- /**
165
- * Strategy for matching previous items to next items during animation.
166
- * Determines how Recharts pairs old data points with new data points
167
- * to create smooth transitions.
168
- *
169
- * - `matchAppend` (default): match sequentially by index and treat newly appended items as new
170
- * - `matchByIndex`: match by array position with proportional stretching
171
- * - `matchByDataKey('someKey')`: match by a data key from the payload
172
- * - Custom function `(item, index) => key`: match by the returned key
173
- *
174
- * @defaultValue append
175
- */
176
- animationMatchBy?: AnimationMatchByProp<BarRectangleItem>
177
- id?: string
178
- label?: ImplicitLabelListType
179
- zIndex?: number
180
- children?: JSX.Element
181
- }
182
-
183
- type InternalBarProps = {
184
- layout: "horizontal" | "vertical"
185
- data: ReadonlyArray<BarRectangleItem> | undefined
186
- xAxisId: string | number
187
- yAxisId: string | number
188
- hide: boolean
189
- legendType: LegendType
190
- minPointSize: MinPointSize
191
- activeBar: ActiveShape<BarShapeProps, SVGPathElement>
192
- isAnimationActive: boolean | "auto"
193
- animationBegin: number
194
- animationDuration: AnimationDuration
195
- animationEasing: EasingInput
196
- animationInterpolateFn: AnimationInterpolateFn<BarRectangleItem, CartesianLayout>
197
- animationMatchBy: AnimationMatchByProp<BarRectangleItem>
198
- needClip?: boolean
199
- className?: string
200
- index?: string | number
201
- stackId?: string | number
202
- barSize?: string | number
203
- unit?: string | number
204
- name?: string | number
205
- dataKey?: DataKey<unknown>
206
- tooltipType?: TooltipType
207
- formatter?: Formatter
208
- maxBarSize?: number
209
- shape?: ActiveShape<BarShapeProps, SVGPathElement>
210
- background?: ActiveShape<BarShapeProps, SVGPathElement>
211
- radius?: number | [number, number, number, number]
212
- onAnimationStart?: () => void
213
- onAnimationEnd?: () => void
214
- id: GraphicalItemId
215
- label?: ImplicitLabelListType
216
- children?: JSX.Element
217
- }
218
-
219
- type BarSvgProps = Omit<
220
- PresentationAttributesAdaptChildEvent<BarRectangleItem, SVGPathElement>,
221
- "radius" | "name" | "ref"
222
- >
223
-
224
- /* eslint-disable-next-line typescript-eslint/no-explicit-any -- upstream contract: untyped items accept any data */
225
- export type Props<DataPointType = any, DataValueType = any> = BarSvgProps & BarProps<DataPointType, DataValueType>
226
-
227
- type InternalProps = BarSvgProps & InternalBarProps
228
-
229
- /* eslint-disable solid/reactivity -- plain utility fn; Props parameter is not a Solid reactive proxy at this call site */
230
- const computeLegendPayloadFromBarData = (barProps: Props): ReadonlyArray<LegendPayload> => {
231
- return [
232
- {
233
- color: typeof barProps.fill === "string" ? barProps.fill : undefined,
234
- dataKey: barProps.dataKey,
235
- inactive: barProps.hide,
236
- payload: barProps,
237
- type: barProps.legendType,
238
- value: getTooltipNameProp(barProps.name, barProps.dataKey),
239
- },
240
- ]
241
- }
242
- /* eslint-enable solid/reactivity */
243
-
244
- function SetBarTooltipEntrySettings(
245
- props: Pick<
246
- InternalProps,
247
- "dataKey" | "stroke" | "strokeWidth" | "fill" | "name" | "hide" | "unit" | "tooltipType" | "formatter" | "id"
248
- >,
249
- ) {
250
- /* GOTCHA-005: createMemo so reactive props flow into the settings object. */
251
- const tooltipEntrySettings = createMemo<TooltipPayloadConfiguration>(() => ({
252
- dataDefinedOnItem: undefined,
253
- getPosition: noop,
254
- settings: {
255
- color: props.fill,
256
- dataKey: props.dataKey,
257
- fill: props.fill,
258
- formatter: props.formatter,
259
- graphicalItemId: props.id,
260
- hide: props.hide,
261
- name: getTooltipNameProp(props.name, props.dataKey),
262
- nameKey: undefined,
263
- stroke: props.stroke,
264
- strokeWidth: props.strokeWidth,
265
- type: props.tooltipType,
266
- unit: props.unit,
267
- },
268
- }))
269
- return <SetTooltipEntrySettings tooltipEntrySettings={tooltipEntrySettings()} />
270
- }
271
-
272
- function BarBackground(props: {
273
- background?: ActiveShape<BarShapeProps, SVGPathElement>
274
- data: ReadonlyArray<BarRectangleItem> | undefined
275
- dataKey: DataKey<unknown> | undefined
276
- allOtherBarProps: InternalProps
277
- }) {
278
- /* GOTCHA-016-C: one entry per pointer move across both event pairs, shared by all bars. */
279
- const hover = createHoverDedupe()
280
- const ctx = useChartStore()
281
- /* perf: cache selector result; without memo every consumer read triggers full chain. */
282
- const activeIndex = createMemo(() => (ctx ? selectActiveTooltipIndex(ctx.store) : undefined))
283
- /* eslint-disable solid/reactivity -- id is a stable identifier; handler and dataKey sources are accessors read at event time */
284
- const onMouseEnterFromContext = useMouseEnterItemDispatch(
285
- () =>
286
- props.allOtherBarProps.onMouseEnter as
287
- | ((d: BarRectangleItem, i: number, e: MouseEvent) => void)
288
- | undefined,
289
- () => props.dataKey,
290
- props.allOtherBarProps.id,
291
- )
292
- const onMouseLeaveFromContext = useMouseLeaveItemDispatch(
293
- () =>
294
- props.allOtherBarProps.onMouseLeave as
295
- | ((d: BarRectangleItem, i: number, e: MouseEvent) => void)
296
- | undefined,
297
- )
298
- const onClickFromContext = useMouseClickItemDispatch(
299
- () =>
300
- props.allOtherBarProps.onClick as
301
- | ((d: BarRectangleItem, i: number, e: MouseEvent) => void)
302
- | undefined,
303
- () => props.dataKey,
304
- props.allOtherBarProps.id,
305
- )
306
- /* eslint-enable solid/reactivity */
307
-
308
- return (
309
- <Show when={props.background && props.data != null}>
310
- <ZIndexLayer zIndex={getZIndexFromUnknown(props.background, DefaultZIndexes.barBackground)}>
311
- <For each={props.data}>
312
- {(entry: BarRectangleItem, i) => {
313
- return (
314
- <Show when={entry.background}>
315
- {(() => {
316
- /* match upstream: keep parentViewBox/payload/stackedBarStart on rest;
317
- strip only value/background/tooltipPosition. */
318
- const bgSvgProps = svgPropertiesNoEventsFromUnknown(props.background)
319
- const bgFill = typeof bgSvgProps?.fill === "string" ? bgSvgProps.fill : "#eee"
320
- const {
321
- value: _v,
322
- background: _bg,
323
- tooltipPosition: _tp,
324
- ...rectProps
325
- } = entry
326
- const bg = entry.background
327
- const adapted = (adaptEventsOfChild(
328
- props.allOtherBarProps as unknown as Record<string, unknown>,
329
- entry,
330
- i(),
331
- ) ?? {}) as Record<string, ((e: Event) => void) | undefined>
332
- /* GOTCHA-016-C: bind both pairs, dedupe per-instance. Compose adapted user handlers ahead of context dispatch. */
333
- const enter = onMouseEnterFromContext(entry, i()) as unknown as (
334
- e: MouseEvent,
335
- ) => void
336
- const leave = onMouseLeaveFromContext(entry, i()) as unknown as (
337
- e: MouseEvent,
338
- ) => void
339
- const click = onClickFromContext(entry, i()) as unknown as (e: MouseEvent) => void
340
- const userOver = adapted.onMouseOver
341
- const userOut = adapted.onMouseOut
342
- const fireEnter = (e: MouseEvent) => {
343
- if (!hover.enter(e)) return
344
- userOver?.(e)
345
- enter(e)
346
- }
347
- const fireLeave = (e: MouseEvent) => {
348
- if (!hover.leave(e)) return
349
- userOut?.(e)
350
- leave(e)
351
- }
352
- return (
353
- <BarRectangle
354
- option={props.background}
355
- isActive={String(entry.originalDataIndex ?? i()) === activeIndex()}
356
- {...rectProps}
357
- fill={bgFill}
358
- x={bg?.x ?? rectProps.x}
359
- y={bg?.y ?? rectProps.y}
360
- width={bg?.width ?? rectProps.width}
361
- height={bg?.height ?? rectProps.height}
362
- dataKey={props.dataKey}
363
- index={i()}
364
- className="recharts-bar-background-rectangle"
365
- {...adapted}
366
- onMouseEnter={fireEnter}
367
- onMouseOver={fireEnter}
368
- onMouseLeave={fireLeave}
369
- onMouseOut={fireLeave}
370
- onClick={click}
371
- />
372
- )
373
- })()}
374
- </Show>
375
- )
376
- }}
377
- </For>
378
- </ZIndexLayer>
379
- </Show>
380
- )
381
- }
382
-
383
- function BarLabelListProvider(props: {
384
- showLabels: boolean
385
- children: JSX.Element
386
- rects: ReadonlyArray<BarRectangleItem> | undefined
387
- }) {
388
- const labelListEntries = () =>
389
- props.rects?.map((entry: BarRectangleItem): CartesianLabelListEntry => {
390
- const viewBox: TrapezoidViewBox = {
391
- height: entry.height,
392
- lowerWidth: entry.width,
393
- upperWidth: entry.width,
394
- width: entry.width,
395
- x: entry.x,
396
- y: entry.y,
397
- }
398
- return {
399
- ...viewBox,
400
- fill: entry.fill,
401
- parentViewBox: entry.parentViewBox,
402
- payload: entry.payload,
403
- value: entry.value,
404
- viewBox,
405
- }
406
- })
407
-
408
- /* eslint-disable solid/reactivity -- Provider value reads labelListEntries() and props.showLabels inside JSX attribute; both are reactive */
409
- return (
410
- <CartesianLabelListContextProvider value={props.showLabels ? labelListEntries() : undefined}>
411
- {props.children}
412
- </CartesianLabelListContextProvider>
413
- )
414
- /* eslint-enable solid/reactivity */
415
- }
416
-
417
- /* perf: fast-path renderer for the common case (no custom shape, plain
418
- Rectangle, no per-bar update animation). Bypasses the
419
- BarStackClipLayer -> BarRectangle -> Shape -> ShapeSelector -> Dynamic ->
420
- Rectangle -> RectanglePath chain — 7 components per bar -> 0. Renders the
421
- exact 2-`<g>` + 1-`<path>` DOM structure required by Bar tests
422
- (recharts-bar-rectangle / recharts-inactive-bar / recharts-rectangle).
423
-
424
- 28 bars: 196 createComponent calls + 196 owner-tree nodes + ~5 reactive
425
- effects per bar saved. Reactive geometry (x/y/width/height/d) bound
426
- directly via JSX so Solid's compiler emits setAttribute ops with one
427
- render-effect per attribute slot (no scheduler dispatch through
428
- intermediate component scopes). */
429
- function FastBarPath(props: {
430
- entry: () => BarRectangleItem
431
- index: number
432
- staticAttrs: Record<string, unknown>
433
- entryStaticAttrs: Record<string, unknown>
434
- stackEvents: Record<string, (e: Event) => void>
435
- pathClass: () => string
436
- radius: RectRadius | undefined
437
- }) {
438
- const clipPathUrl = createMemo(() => useBarStackClipPathUrl(props.index))
439
- /* eslint-disable-next-line solid/reactivity -- radius is a stable numeric prop captured once at setup */
440
- const radius = props.radius ?? 0
441
- const isValid = () => {
442
- const e = props.entry()
443
- return (
444
- e.x === +e.x &&
445
- e.y === +e.y &&
446
- e.width === +e.width &&
447
- e.height === +e.height &&
448
- e.width !== 0 &&
449
- e.height !== 0
450
- )
451
- }
452
- const [pathEl, setPathEl] = createSignal<SVGPathElement | null>(null)
453
- /* perf: imperative per-frame setAttribute via ref. Prev-value cache skips
454
- redundant DOM writes — Solid effects re-run on any dep change, but most
455
- per-frame ticks only change one or two attrs, not all of them. */
456
- let prevX = NaN, prevY = NaN, prevW = NaN, prevH = NaN, prevD = "", prevFill = ""
457
- createRenderEffect(
458
- () => {
459
- const el = pathEl()
460
- if (!el) return null
461
- const e = props.entry()
462
- return { el, fill: e.fill, height: e.height, width: e.width, x: e.x, y: e.y }
463
- },
464
- (e) => {
465
- if (e == null) return
466
- const el = e.el
467
- const x = round(e.x)
468
- const y = round(e.y)
469
- const w = round(e.width)
470
- const h = round(e.height)
471
- if (x !== prevX) { el.setAttribute("x", String(x)); prevX = x }
472
- if (y !== prevY) { el.setAttribute("y", String(y)); prevY = y }
473
- if (w !== prevW) { el.setAttribute("width", String(w)); prevW = w }
474
- if (h !== prevH) { el.setAttribute("height", String(h)); prevH = h }
475
- const d = getRectanglePath(e.x, e.y, e.width, e.height, radius)
476
- if (d !== prevD) { el.setAttribute("d", d); prevD = d }
477
- const f = e.fill
478
- if (f != null && f !== prevFill) { el.setAttribute("fill", f); prevFill = f }
479
- },
480
- )
481
- const setPathRef = (el: SVGPathElement) => {
482
- el.setAttribute("radius", String(radius))
483
- setPathEl(el)
484
- }
485
- return (
486
- <g
487
- class="recharts-layer recharts-bar-stack-layer recharts-bar-rectangle"
488
- clip-path={clipPathUrl()}
489
- {...props.stackEvents}
490
- >
491
- <g class="recharts-layer recharts-inactive-bar">
492
- <Show when={isValid()}>
493
- <path
494
- ref={setPathRef}
495
- {...props.staticAttrs}
496
- {...props.entryStaticAttrs}
497
- class={props.pathClass()}
498
- />
499
- </Show>
500
- </g>
501
- </g>
502
- )
503
- }
504
-
505
- function BarRectangleWithActiveState(props: {
506
- rectProps: BarRectangleProps
507
- shape: ActiveShape<BarShapeProps, SVGPathElement> | undefined
508
- activeBar: ActiveShape<BarShapeProps, SVGPathElement>
509
- originalDataIndex: number
510
- dataKey: DataKey<unknown> | undefined
511
- }) {
512
- const ctx = useChartStore()
513
- const activeIndex = createMemo(() => (ctx ? selectActiveTooltipIndex(ctx.store) : undefined))
514
- const activeDataKey = createMemo(() => (ctx ? selectActiveTooltipDataKey(ctx.store) : undefined))
515
- /*
516
- * Bars support stacking, so there can be multiple bars at the same x value.
517
- * With Tooltip shared=false only the hovered Bar is active; with a shared Tooltip
518
- * (activeDataKey undefined) every bar at the active index is.
519
- * originalDataIndex is compared because the rendered array is filtered (null and
520
- * zero-dimension bars), while activeIndex indexes the displayed data slice.
521
- */
522
- const isActive = createMemo(
523
- () =>
524
- Boolean(props.activeBar) &&
525
- String(props.originalDataIndex) === activeIndex() &&
526
- (activeDataKey() == null || props.dataKey === activeDataKey()),
527
- )
528
- const isAnotherBarActive = createMemo(
529
- () =>
530
- activeIndex() != null &&
531
- (String(props.originalDataIndex) !== activeIndex() ||
532
- (activeDataKey() != null && props.dataKey !== activeDataKey())),
533
- )
534
-
535
- const [stayInLayer, setStayInLayer] = createSignal(false)
536
- const [hasMountedActive, setHasMountedActive] = createSignal(false)
537
-
538
- createEffect(
539
- () => ({ active: isActive(), anotherActive: isAnotherBarActive() }),
540
- ({ active, anotherActive }) => {
541
- let rafId: number | undefined
542
- if (active) {
543
- // 1. Enter the layer immediately
544
- setStayInLayer(true)
545
- // 2. Wait for the inactive state to paint in the new layer, then switch to active
546
- // so the CSS transition runs.
547
- rafId = requestAnimationFrame(() => {
548
- setHasMountedActive(true)
549
- })
550
- } else {
551
- setHasMountedActive(false)
552
- if (anotherActive) {
553
- setStayInLayer(false)
554
- }
555
- }
556
- return () => {
557
- if (rafId != null) {
558
- cancelAnimationFrame(rafId)
559
- }
560
- }
561
- },
562
- )
563
-
564
- // 4. Leave the layer only when the exit transition finishes
565
- const handleTransitionEnd = () => {
566
- if (!untrack(isActive)) {
567
- setStayInLayer(false)
568
- }
569
- }
570
-
571
- const option = (): ActiveShape<BarShapeProps, SVGPathElement> | undefined => {
572
- if (!isActive()) {
573
- return props.shape
574
- }
575
- return props.activeBar === true ? props.shape : props.activeBar
576
- }
577
-
578
- const content = () => (
579
- <BarRectangle
580
- {...props.rectProps}
581
- isActive={isActive() && hasMountedActive()}
582
- option={option()}
583
- onTransitionEnd={handleTransitionEnd}
584
- />
585
- )
586
-
587
- // Render in the active layer while active, or while the exit transition runs
588
- return (
589
- <Show when={isActive() || stayInLayer()} fallback={content()}>
590
- <ZIndexLayer zIndex={DefaultZIndexes.activeBar}>
591
- <BarStackClipLayer index={props.originalDataIndex}>{content()}</BarStackClipLayer>
592
- </ZIndexLayer>
593
- </Show>
594
- )
595
- }
596
-
597
- function BarRectangles(props: {
598
- data: ReadonlyArray<BarRectangleItem> | undefined
599
- allProps: InternalProps
600
- animationElapsedTime?: number
601
- isAnimating?: boolean
602
- isEntrance?: boolean
603
- }) {
604
- /* GOTCHA-016-C: one entry per pointer move across both event pairs, shared by all bars. */
605
- const hover = createHoverDedupe()
606
- /* eslint-disable solid/reactivity -- dataKey/id destructure and dispatch hook reads are stable identifiers captured once at setup */
607
- const { id: _id, name: _name, ...baseProps } = svgPropertiesNoEvents(props.allProps) ?? {}
608
- /* mirror upstream `<BarStackClipLayer ... onMouseEnter onMouseLeave onClick>`:
609
- wire context dispatchers + per-entry adaptEventsOfChild forwards */
610
- const onMouseEnterFromContext = useMouseEnterItemDispatch(
611
- () =>
612
- props.allProps.onMouseEnter as
613
- | ((d: BarRectangleItem, i: number, e: MouseEvent) => void)
614
- | undefined,
615
- () => props.allProps.dataKey,
616
- props.allProps.id,
617
- )
618
- const onMouseLeaveFromContext = useMouseLeaveItemDispatch(
619
- () =>
620
- props.allProps.onMouseLeave as
621
- | ((d: BarRectangleItem, i: number, e: MouseEvent) => void)
622
- | undefined,
623
- )
624
- const onClickFromContext = useMouseClickItemDispatch(
625
- () =>
626
- props.allProps.onClick as
627
- | ((d: BarRectangleItem, i: number, e: MouseEvent) => void)
628
- | undefined,
629
- () => props.allProps.dataKey,
630
- props.allProps.id,
631
- )
632
- /* eslint-enable solid/reactivity */
633
-
634
- /* perf: pre-extract event handlers once. `adaptEventsOfChild(props.allProps, …)`
635
- does `Object.keys` + `proxy[key]` per entry — that read iterates the BarImpl
636
- mergeProps proxy and triggers the `data` getter which calls
637
- `selectBarRectangles`. Inside the per-entry `adapted` createMemo this turns
638
- into a per-frame selector chain (343ms total in the profile). Snapshotting
639
- to a plain object decouples the per-entry binding from the proxy. */
640
- type ChildHandler = (data: BarRectangleItem, index: number, e: Event) => void
641
- const eventHandlers: Record<string, ChildHandler> = {}
642
- {
643
- /* eslint-disable-next-line solid/reactivity -- props.allProps proxy snapshot at setup; event handlers don't change after mount */
644
- const proxy = props.allProps as unknown as Record<string, unknown>
645
- for (const key of Object.keys(proxy)) {
646
- if (isEventKey(key)) {
647
- const v = proxy[key]
648
- if (typeof v === "function") {
649
- eventHandlers[key] = v as ChildHandler
650
- }
651
- }
652
- }
653
- }
654
-
655
- /* eslint-disable solid/reactivity -- shape/radius/className reads are intentional one-time setup captures; fast-path eligibility is determined once at mount */
656
- /* perf: detect fast-path eligibility ONCE at setup. Default Bar (no custom
657
- shape) hits FastBarPath which renders <g><g><path/></g></g> directly with
658
- reactive d-binding — bypasses 7-component-deep chain. Custom shape /
659
- activeBar / function-option falls through to BarStackClipLayer + Shape
660
- chain for parity with React's clone-and-extend semantics. */
661
- const useFastPath = props.allProps.shape == null && !props.allProps.activeBar
662
- const radius = props.allProps.radius
663
- /* split static path attrs once: spread on every <path/> covers fill/stroke/
664
- strokeWidth/className/data-* etc. without re-walking the proxy per bar. */
665
- const staticPathAttrs = (() => {
666
- if (!useFastPath) return {} as Record<string, unknown>
667
- const out: Record<string, unknown> = { ...(baseProps as Record<string, unknown>) }
668
- /* geometry handled by reactive d-binding; drop to avoid Solid emitting
669
- x/y/width/height attrs on the path element (path doesn't support them).
670
- keep fill — Bar's `fill="#8884d8"` prop is the default; entry.fill (Cell
671
- override) wins via reactive setAttribute in FastBarPath createEffect. */
672
- delete out.x
673
- delete out.y
674
- delete out.width
675
- delete out.height
676
- delete out.radius
677
- delete out.class
678
- delete out.className
679
- return out
680
- })()
681
- const baseClassName = (props.allProps as { className?: string }).className
682
- const pathClass = () => clsx("recharts-rectangle", baseClassName)
683
- /* eslint-enable solid/reactivity */
684
-
685
- /* perf: <For keyed={false}> over <For> — entries are NEW objects every animation frame
686
- (stepData spreads `{...entry, height: …}`) so referential `<For>` would
687
- tear down + remount the entire BarStackClipLayer/BarRectangle subtree per
688
- tick. <For keyed={false}> keeps slots stable and lets attribute bindings update in
689
- place; ~10x cheaper per frame on 50-bar charts.
690
-
691
- perf: don't spread the whole entry — only x/y/width/height/fill change
692
- per frame. Spreading the full object retriggers Solid's `assign` for
693
- every attribute (~30 svg keys each) every tick. Pass field-level
694
- accessors via mergeProps so the component sees individual reactive
695
- getters and only the live attrs touch the DOM. */
696
- /* eslint-disable solid/reactivity -- index is a plain number from <For keyed={false}> (not a signal accessor); reads inside the Index callback ARE tracked */
697
- return (
698
- <Show when={props.data}>
699
- <For keyed={false} each={props.data}>
700
- {(entry, index) => {
701
- const originalIndex = untrack(() => entry().originalDataIndex ?? index)
702
- const userOver = eventHandlers.onMouseOver
703
- const userOut = eventHandlers.onMouseOut
704
- const adapted: Record<string, (e: Event) => void> = {}
705
- for (const key in eventHandlers) {
706
- const handler = eventHandlers[key]
707
- if (handler) adapted[key] = (e: Event) => handler(entry(), originalIndex, e)
708
- }
709
- /* GOTCHA-016-C: dedupe user.hover paths so MouseEnter+MouseOver fires once. */
710
- const fireEnter = (e: MouseEvent & { currentTarget: SVGElement }) => {
711
- if (!hover.enter(e)) return
712
- userOver?.(entry(), originalIndex, e)
713
- onMouseEnterFromContext(entry(), originalIndex)(e)
714
- }
715
- const fireLeave = (e: MouseEvent & { currentTarget: SVGElement }) => {
716
- if (!hover.leave(e)) return
717
- userOut?.(entry(), originalIndex, e)
718
- onMouseLeaveFromContext(entry(), originalIndex)(e)
719
- }
720
- const handleClick = (e: MouseEvent & { currentTarget: SVGElement }) => {
721
- onClickFromContext(entry(), originalIndex)(e)
722
- }
723
- const stackEvents: Record<string, (e: Event) => void> = {
724
- ...adapted,
725
- onMouseEnter: fireEnter as unknown as (e: Event) => void,
726
- onMouseOver: fireEnter as unknown as (e: Event) => void,
727
- onMouseLeave: fireLeave as unknown as (e: Event) => void,
728
- onMouseOut: fireLeave as unknown as (e: Event) => void,
729
- onClick: handleClick as unknown as (e: Event) => void,
730
- }
731
- if (useFastPath) {
732
- /* perf: snapshot entry-derived static svg attrs ONCE at mount.
733
- `<path>` should carry `name`, `payload`, etc. from data row for
734
- parity with React's spread of {...entry} to Rectangle. Geometry
735
- attrs (x/y/width/height) overridden by reactive geomAttrs(). */
736
- const initialEntry = untrack(() => entry())
737
- /* Upstream Rectangle forwards only SVG attributes from the data row. */
738
- const entryStatic: Record<string, unknown> = untrack(() =>
739
- svgPropertiesAndEvents(initialEntry as unknown as Record<PropertyKey, unknown>),
740
- )
741
- delete entryStatic.x
742
- delete entryStatic.y
743
- delete entryStatic.width
744
- delete entryStatic.height
745
- delete entryStatic.fill
746
- delete entryStatic.radius
747
- delete entryStatic.value
748
- delete entryStatic.background
749
- delete entryStatic.tooltipPosition
750
- delete entryStatic.parentViewBox
751
- delete entryStatic.payload
752
- delete entryStatic.stackedBarStart
753
- return (
754
- <FastBarPath
755
- entry={entry}
756
- index={originalIndex}
757
- staticAttrs={staticPathAttrs}
758
- entryStaticAttrs={entryStatic}
759
- stackEvents={stackEvents}
760
- pathClass={pathClass}
761
- radius={radius as RectRadius | undefined}
762
- />
763
- )
764
- }
765
- /* perf: snapshot static fields once. fill/stroke etc. don't change
766
- per animation frame, so reading them via reactive getters made the
767
- downstream spread render effect re-tick uselessly. Only x/y/width/
768
- height stay reactive via override getters. */
769
- const initialEntry = untrack(() => entry())
770
- const rectProps = mergeProps(baseProps, initialEntry, {
771
- get x() {
772
- return entry().x
773
- },
774
- get y() {
775
- return entry().y
776
- },
777
- get width() {
778
- return entry().width
779
- },
780
- get height() {
781
- return entry().height
782
- },
783
- isActive: false,
784
- option: props.allProps.shape,
785
- index: originalIndex,
786
- dataKey: props.allProps.dataKey,
787
- get animationElapsedTime() {
788
- return props.animationElapsedTime
789
- },
790
- get isAnimating() {
791
- return props.isAnimating
792
- },
793
- get isEntrance() {
794
- return props.isEntrance
795
- },
796
- })
797
- return (
798
- <BarStackClipLayer
799
- index={originalIndex}
800
- class="recharts-bar-rectangle"
801
- {...adapted}
802
- onMouseEnter={fireEnter}
803
- onMouseOver={fireEnter}
804
- onMouseLeave={fireLeave}
805
- onMouseOut={fireLeave}
806
- onClick={handleClick}
807
- >
808
- <Show when={props.allProps.activeBar} fallback={<BarRectangle {...rectProps} />}>
809
- <BarRectangleWithActiveState
810
- rectProps={rectProps}
811
- shape={props.allProps.shape}
812
- activeBar={props.allProps.activeBar}
813
- originalDataIndex={originalIndex}
814
- dataKey={props.allProps.dataKey}
815
- />
816
- </Show>
817
- </BarStackClipLayer>
818
- )
819
- }}
820
- </For>
821
- </Show>
822
- )
823
- /* eslint-enable solid/reactivity */
824
- }
825
-
826
- function RectanglesWithAnimation(props: {
827
- allProps: InternalProps
828
- previousRectanglesRef: { current: ReadonlyArray<BarRectangleItem> | null }
829
- }) {
830
- const { isAnimating, handleAnimationStart, handleAnimationEnd } = useAnimationCallbacks(
831
- () => props.allProps.onAnimationStart,
832
- () => props.allProps.onAnimationEnd,
833
- )
834
-
835
- return (
836
- <BarLabelListProvider showLabels={!isAnimating()} rects={props.allProps.data}>
837
- <AnimatedItems
838
- animationInput={props.allProps.data}
839
- animationIdPrefix="recharts-bar-"
840
- items={props.allProps.data}
841
- previousItemsRef={props.previousRectanglesRef}
842
- isAnimationActive={props.allProps.isAnimationActive}
843
- animationBegin={props.allProps.animationBegin}
844
- animationDuration={props.allProps.animationDuration}
845
- animationEasing={props.allProps.animationEasing}
846
- onAnimationStart={handleAnimationStart}
847
- onAnimationEnd={handleAnimationEnd}
848
- animationInterpolateFn={props.allProps.animationInterpolateFn}
849
- animationMatchBy={props.allProps.animationMatchBy}
850
- layout={props.allProps.layout}
851
- >
852
- {(stepData, animationElapsedTime, isEntrance) => (
853
- <Layer>
854
- <BarRectangles
855
- allProps={props.allProps}
856
- data={stepData()}
857
- animationElapsedTime={animationElapsedTime()}
858
- isAnimating={isAnimating() || animationElapsedTime() < 1}
859
- isEntrance={isEntrance()}
860
- />
861
- </Layer>
862
- )}
863
- </AnimatedItems>
864
- <LabelListFromLabelProp label={props.allProps.label} />
865
- {props.allProps.children}
866
- </BarLabelListProvider>
867
- )
868
- }
869
-
870
- function RenderRectangles(props: { allProps: InternalProps }) {
871
- const previousRectanglesRef: { current: ReadonlyArray<BarRectangleItem> | null } = {
872
- current: null,
873
- }
874
- return (
875
- <RectanglesWithAnimation
876
- allProps={props.allProps}
877
- previousRectanglesRef={previousRectanglesRef}
878
- />
879
- )
880
- }
881
-
882
- const defaultBarAnimateItems: AnimationInterpolateFn<BarRectangleItem, CartesianLayout> = (
883
- items,
884
- animationElapsedTime,
885
- layout,
886
- ) => {
887
- if (items == null) return []
888
- if (animationElapsedTime === 1) {
889
- return items.flatMap((item) => (item.status === "removed" ? [] : [item.next]))
890
- }
891
- return items.flatMap((item) => {
892
- if (item.status === "removed") {
893
- // animate removed items to 0 height/width respective of layout
894
- if (layout === "horizontal") {
895
- return [
896
- {
897
- ...item.prev,
898
- height: interpolate(item.prev.height, 0, animationElapsedTime),
899
- y: interpolate(item.prev.y, item.prev.y + item.prev.height, animationElapsedTime),
900
- },
901
- ]
902
- }
903
- return [{ ...item.prev, width: interpolate(item.prev.width, 0, animationElapsedTime) }]
904
- }
905
- if (item.status === "matched") {
906
- return [
907
- {
908
- ...item.next,
909
- height: interpolate(item.prev.height, item.next.height, animationElapsedTime),
910
- width: interpolate(item.prev.width, item.next.width, animationElapsedTime),
911
- x: interpolate(item.prev.x, item.next.x, animationElapsedTime),
912
- y: interpolate(item.prev.y, item.next.y, animationElapsedTime),
913
- },
914
- ]
915
- }
916
- // added
917
- const { next } = item
918
- if (layout === "horizontal") {
919
- return [
920
- {
921
- ...next,
922
- height: interpolate(0, next.height, animationElapsedTime),
923
- y: interpolate(next.stackedBarStart, next.y, animationElapsedTime),
924
- },
925
- ]
926
- }
927
- return [
928
- {
929
- ...next,
930
- width: interpolate(0, next.width, animationElapsedTime),
931
- x: interpolate(next.stackedBarStart, next.x, animationElapsedTime),
932
- },
933
- ]
934
- })
935
- }
936
-
937
- const defaultMinPointSize: number = 0
938
-
939
- const errorBarDataPointFormatter: ErrorBarDataPointFormatter<BarRectangleItem> = (
940
- dataPoint: BarRectangleItem,
941
- dataKey,
942
- ): ErrorBarDataItem => {
943
- const value = Array.isArray(dataPoint.value) ? dataPoint.value[1] : dataPoint.value
944
- return {
945
- errorVal: getValueByDataKey(dataPoint, dataKey),
946
- value,
947
- x: dataPoint.x,
948
- y: dataPoint.y,
949
- }
950
- }
951
-
952
- function BarWithState(props: InternalProps) {
953
- return (
954
- <Show when={!props.hide && props.data != null}>
955
- {(() => {
956
- const layerClass = () => clsx("recharts-bar", props.className)
957
- const clipPathId = () => props.id
958
-
959
- return (
960
- <Layer class={layerClass()} id={props.id}>
961
- <Show when={props.needClip}>
962
- <defs>
963
- <GraphicalItemClipPath
964
- clipPathId={clipPathId()}
965
- xAxisId={props.xAxisId}
966
- yAxisId={props.yAxisId}
967
- />
968
- </defs>
969
- </Show>
970
- <Layer
971
- class="recharts-bar-rectangles"
972
- clip-path={props.needClip ? `url(#clipPath-${clipPathId()})` : undefined}
973
- >
974
- <BarBackground
975
- data={props.data}
976
- dataKey={props.dataKey}
977
- background={props.background}
978
- allOtherBarProps={props}
979
- />
980
- <RenderRectangles allProps={props} />
981
- </Layer>
982
- </Layer>
983
- )
984
- })()}
985
- </Show>
986
- )
987
- }
988
-
989
- export const defaultBarProps = {
990
- activeBar: false,
991
- animationBegin: 0,
992
- animationDuration: 400,
993
- animationEasing: "ease",
994
- animationInterpolateFn: defaultBarAnimateItems,
995
- animationMatchBy: matchAppend,
996
- background: false,
997
- hide: false,
998
- isAnimationActive: "auto",
999
- label: false,
1000
- legendType: "rect",
1001
- minPointSize: defaultMinPointSize,
1002
- xAxisId: 0,
1003
- yAxisId: 0,
1004
- zIndex: DefaultZIndexes.bar,
1005
- } as const satisfies Partial<Props>
1006
-
1007
- function BarImpl(props: InternalBarProps & { children?: JSX.Element }) {
1008
- const needClipResult = createMemo(() => useNeedsClip(props.xAxisId, props.yAxisId))
1009
- const layout = createMemo(() => useChartLayout())
1010
-
1011
- const isPanorama = useIsPanorama()
1012
- const ctx = useChartStore()
1013
- /* React parity for `<Cell/>` overrides: upstream walks props.children with
1014
- findAllByType(Cell) — impossible on Solid (opaque JSX). The registry is
1015
- provided ABOVE this scope (in Bar() before memoizedChildren) so the
1016
- memo's createComponent calls capture an owner that sees the Provider.
1017
- Reading `useCellsRegistry()` here returns that same registry. */
1018
- const registry = useCellsRegistry()
1019
- const cells = (): ReadonlyArray<JSX.Element> | undefined => {
1020
- if (registry == null) return undefined
1021
- const list = registry.cells()
1022
- return list.length === 0 ? undefined : (list as unknown as ReadonlyArray<JSX.Element>)
1023
- }
1024
-
1025
- /* selectBarRectangles is a per-chart chartSelector memo keyed by (id, isPanorama, cells). It
1026
- resolves the bar's settings and axes from the store, tracking each field it reads. */
1027
- const rects = createMemo(() =>
1028
- ctx ? selectBarRectangles(ctx.store, props.id, isPanorama, cells()) : undefined,
1029
- )
1030
-
1031
- return (
1032
- <Show when={layout() === "vertical" || layout() === "horizontal"}>
1033
- {(() => {
1034
- const withState = mergeProps(props, {
1035
- get layout() {
1036
- return layout() as "horizontal" | "vertical"
1037
- },
1038
- get needClip() {
1039
- return needClipResult()?.needClip()
1040
- },
1041
- get data() {
1042
- return rects()
1043
- },
1044
- })
1045
- /* GOTCHA-017 (session 34): SetErrorBarContext hoisted out of BarImpl
1046
- to Bar() outer scope (RegisterGraphicalItemId children-fn). Reason:
1047
- user JSX <ErrorBar/> evaluates eagerly when `children` getter is read
1048
- inside Bar's mergeProps literal — that scope is OUTSIDE BarImpl, so
1049
- ErrorBarImpl's useErrorBarContext returned the initial-default. With
1050
- the Provider hoisted, the children getter reads inside the Provider
1051
- owner. BarImpl now only computes/forwards rects; offset is computed
1052
- at the outer scope via the same store selector. */
1053
- return <BarWithState {...(withState as unknown as InternalProps)} />
1054
- })()}
1055
- </Show>
1056
- )
1057
- }
1058
-
1059
- /* React parity for `<Cell/>` overrides: provide a CellsRegistry so that user
1060
- `<For>{(row) => <Cell .../>}</For>` JSX evaluating inside `memoizedChildren`
1061
- sees the Provider in its owner chain. The Provider wraps the inner JSX so
1062
- the memoizedChildren memo created here has Provider as its enclosing owner,
1063
- which means the For + Cell createComponent calls fire under the Provider. */
1064
- function BarChildrenScope(props: {
1065
- childrenProps: { children?: JSX.Element }
1066
- id: GraphicalItemId
1067
- mergedBarProps: BarPropsWithDefaults
1068
- }) {
1069
- const cellsRegistry = createCellsRegistry()
1070
- return (
1071
- <cellsRegistry.Provider value={cellsRegistry}>
1072
- <LabelListContextBridge>
1073
- {(() => {
1074
- /* GOTCHA-017: memoize children INSIDE Provider so that the For/Cell
1075
- createComponent calls fired by `childrenProps.children` access run
1076
- with Provider as a parent owner. Memo capture happens at memo-create
1077
- time — moving creation here is what makes context lookup find the
1078
- registry. Repeated reads return the same Node (no re-mint loop). */
1079
- /* eslint-disable-next-line solid/reactivity -- props.childrenProps.children is read inside createMemo; this IS a tracked scope */
1080
- const memoizedChildren = createMemo(() => props.childrenProps.children)
1081
- /* eslint-disable-next-line solid/reactivity -- mergeProps result captured in variable per linter requirement; props.mergedBarProps is already a reactive proxy */
1082
- const barImplProps = mergeProps(props.mergedBarProps, {
1083
- id: props.id,
1084
- get children() {
1085
- return memoizedChildren()
1086
- },
1087
- }) as unknown as InternalBarProps
1088
- return (
1089
- <ZIndexLayer zIndex={props.mergedBarProps.zIndex}>
1090
- <BarImpl {...barImplProps} />
1091
- </ZIndexLayer>
1092
- )
1093
- })()}
1094
- </LabelListContextBridge>
1095
- </cellsRegistry.Provider>
1096
- )
1097
- }
1098
-
1099
- export function computeBarRectangles({
1100
- layout,
1101
- barSettings: { dataKey, minPointSize: minPointSizeProp, hasCustomShape = false },
1102
- pos,
1103
- bandSize,
1104
- xAxis,
1105
- yAxis,
1106
- xAxisTicks,
1107
- yAxisTicks,
1108
- stackedData,
1109
- displayedData,
1110
- offset,
1111
- cells,
1112
- parentViewBox,
1113
- dataStartIndex,
1114
- }: {
1115
- layout: "horizontal" | "vertical"
1116
- barSettings: BarSettings
1117
- pos: BarPositionPosition
1118
- bandSize: number
1119
- xAxis: BaseAxisWithScale
1120
- yAxis: BaseAxisWithScale
1121
- xAxisTicks: TickItem[]
1122
- yAxisTicks: TickItem[]
1123
- stackedData: StackSeries | undefined
1124
- offset: ChartOffsetInternal
1125
- displayedData: ChartData
1126
- cells: ReadonlyArray<JSX.Element> | undefined
1127
- parentViewBox: CartesianViewBoxRequired
1128
- dataStartIndex: number
1129
- }): ReadonlyArray<BarRectangleItem> | undefined {
1130
- const numericAxis = layout === "horizontal" ? yAxis : xAxis
1131
- const rawDomain = stackedData ? numericAxis.scale.domain() : null
1132
- const stackedDomain: ReadonlyArray<number> = rawDomain
1133
- ? rawDomain.map((d) => (typeof d === "number" ? d : Number(d)))
1134
- : (null as unknown as ReadonlyArray<number>)
1135
- const baseValue = getBaseValueOfBar({ numericAxis })
1136
- const stackedBarStart: number | undefined = numericAxis.scale.map(baseValue)
1137
-
1138
- return displayedData
1139
- .map((entry: unknown, index): BarRectangleItem | null => {
1140
- let value: unknown
1141
- let x: number | null
1142
- let y: unknown
1143
- let width: unknown
1144
- let height: unknown
1145
- let background: BarRectangleType
1146
-
1147
- if (stackedData) {
1148
- const untruncatedValue = stackedData[index + dataStartIndex]
1149
- if (untruncatedValue == null) {
1150
- return null
1151
- }
1152
- value = truncateByDomain(untruncatedValue, stackedDomain)
1153
- } else {
1154
- value = getValueByDataKey(entry, dataKey)
1155
- if (!Array.isArray(value)) {
1156
- value = [baseValue, value]
1157
- }
1158
- }
1159
-
1160
- const minPointSize = minPointSizeCallback(minPointSizeProp, defaultMinPointSize)(
1161
- (value as number[])[1],
1162
- index,
1163
- )
1164
-
1165
- if (layout === "horizontal") {
1166
- const baseValueScale = yAxis.scale.map((value as number[])[0])
1167
- const currentValueScale = yAxis.scale.map((value as number[])[1])
1168
- if (baseValueScale == null || currentValueScale == null) {
1169
- return null
1170
- }
1171
- x = getCateCoordinateOfBar({
1172
- axis: xAxis,
1173
- bandSize,
1174
- entry,
1175
- index,
1176
- offset: pos.offset,
1177
- ticks: xAxisTicks,
1178
- })
1179
- y = currentValueScale ?? baseValueScale ?? undefined
1180
- width = pos.size
1181
- const computedHeight = baseValueScale - currentValueScale
1182
- height = isNan(computedHeight) ? 0 : computedHeight
1183
- background = { height: offset.height, width: width as number, x, y: offset.top }
1184
-
1185
- if (Math.abs(minPointSize) > 0 && Math.abs(height as number) < Math.abs(minPointSize)) {
1186
- const delta =
1187
- mathSign((height as number) || minPointSize) *
1188
- (Math.abs(minPointSize) - Math.abs(height as number))
1189
- y = (y as number) - delta
1190
- height = (height as number) + delta
1191
- }
1192
- } else {
1193
- const baseValueScale = xAxis.scale.map((value as number[])[0])
1194
- const currentValueScale = xAxis.scale.map((value as number[])[1])
1195
- if (baseValueScale == null || currentValueScale == null) {
1196
- return null
1197
- }
1198
- x = baseValueScale
1199
- y = getCateCoordinateOfBar({
1200
- axis: yAxis,
1201
- bandSize,
1202
- entry,
1203
- index,
1204
- offset: pos.offset,
1205
- ticks: yAxisTicks,
1206
- })
1207
- width = currentValueScale - baseValueScale
1208
- height = pos.size
1209
- background = {
1210
- height: height as number,
1211
- width: offset.width,
1212
- x: offset.left,
1213
- y: y as number,
1214
- }
1215
-
1216
- if (Math.abs(minPointSize) > 0 && Math.abs(width as number) < Math.abs(minPointSize)) {
1217
- const delta =
1218
- mathSign((width as number) || minPointSize) *
1219
- (Math.abs(minPointSize) - Math.abs(width as number))
1220
- width = (width as number) + delta
1221
- }
1222
- }
1223
-
1224
- if (
1225
- x == null ||
1226
- y == null ||
1227
- width == null ||
1228
- height == null ||
1229
- (!hasCustomShape && (width === 0 || height === 0))
1230
- ) {
1231
- return null
1232
- }
1233
-
1234
- const barRectangleItem: BarRectangleItem = {
1235
- ...(entry as Record<string, unknown>),
1236
- background,
1237
- height: height as number,
1238
- originalDataIndex: index,
1239
- parentViewBox,
1240
- payload: entry,
1241
- stackedBarStart: stackedBarStart as number,
1242
- tooltipPosition: {
1243
- x: (x as number) + (width as number) / 2,
1244
- y: (y as number) + (height as number) / 2,
1245
- },
1246
- value: stackedData ? value : (value as number[])[1],
1247
- width: width as number,
1248
- x: x as number,
1249
- y: y as number,
1250
- ...(cells && cells[index] && (cells[index] as { props?: Record<string, unknown> }).props),
1251
- } as BarRectangleItem
1252
-
1253
- return barRectangleItem
1254
- })
1255
- .filter(Boolean) as ReadonlyArray<BarRectangleItem>
1256
- }
1257
-
1258
- /**
1259
- * @provides ErrorBarContext
1260
- * @provides LabelListContext
1261
- * @provides CellReader
1262
- * @consumes CartesianChartContext
1263
- * @consumes BarStackContext
1264
- */
1265
- type BarPropsWithDefaults = Props & Required<Pick<BarProps, keyof typeof defaultBarProps>>
1266
-
1267
- function BarFn(outsideProps: Props) {
1268
- /* GOTCHA-013: split children BEFORE resolveDefaultProps. resolveDefaultProps does
1269
- `{...realProps}` which enumerates own keys of the Solid props proxy — reading the
1270
- `children` getter eagerly invokes createComponent on user JSX (ErrorBar, etc.) at
1271
- Bar's setup time, BEFORE RegisterGraphicalItemId installs its Provider. ErrorBar's
1272
- `useGraphicalItemId()` then resolves to undefined and `ReportErrorBarSettings`
1273
- bails out early — `errorBars` slice stays empty forever. */
1274
- const [childrenProps, restProps] = splitProps(outsideProps, ["children"])
1275
- const rawProps = resolveDefaultProps(restProps, defaultBarProps)
1276
- const props = rawProps as BarPropsWithDefaults
1277
- const stackId = createMemo(() => useStackId(props.stackId))
1278
- const isPanorama = useIsPanorama()
1279
- const ctx = useChartStore()
1280
- /* A memo keeps the shape check out of SetCartesianGraphicalItem's props spread. */
1281
- const hasCustomShape = createMemo(
1282
- () => props.shape != null && props.shape !== defaultBarShape,
1283
- )
1284
- return (
1285
- <RegisterGraphicalItemId id={props.id} type="bar">
1286
- {(id) => {
1287
- /* GOTCHA-017 (session 34): hoist SetErrorBarContext from BarImpl to here.
1288
- Reason: user JSX <ErrorBar/> in props.children evaluates eagerly when the
1289
- children getter is read by BarImpl's children flow — that read happens
1290
- at the closest Provider scope above the read site. By installing
1291
- SetErrorBarContext at the same level as RegisterGraphicalItemId children-fn
1292
- (i.e. directly above where `childrenProps.children` is consumed by JSX),
1293
- ErrorBar's useErrorBarContext resolves to the live Provider, not the
1294
- initial-default. rects/offset are computed via the same selector BarImpl
1295
- uses; redundant compute is fine because Solid memoizes selector results. */
1296
- const rects = () =>
1297
- ctx ? selectBarRectangles(ctx.store, id, isPanorama, undefined) : undefined
1298
- const layoutForOffset = () => useChartLayout()
1299
- const errorBarOffset = () => {
1300
- const firstDataPoint = rects()?.[0]
1301
- if (
1302
- firstDataPoint == null ||
1303
- firstDataPoint.height == null ||
1304
- firstDataPoint.width == null
1305
- ) {
1306
- return 0
1307
- }
1308
- return layoutForOffset() === "vertical"
1309
- ? firstDataPoint.height / 2
1310
- : firstDataPoint.width / 2
1311
- }
1312
- return (
1313
- <>
1314
- <SetLegendPayload legendPayload={computeLegendPayloadFromBarData(props)} />
1315
- <SetBarTooltipEntrySettings
1316
- dataKey={props.dataKey}
1317
- stroke={props.stroke}
1318
- strokeWidth={props.strokeWidth}
1319
- fill={props.fill}
1320
- name={props.name}
1321
- hide={props.hide}
1322
- unit={props.unit}
1323
- tooltipType={props.tooltipType}
1324
- formatter={props.formatter}
1325
- id={id}
1326
- />
1327
- <SetCartesianGraphicalItem
1328
- type="bar"
1329
- id={id}
1330
- data={undefined}
1331
- xAxisId={props.xAxisId}
1332
- yAxisId={props.yAxisId}
1333
- zAxisId={0}
1334
- dataKey={props.dataKey}
1335
- stackId={stackId()}
1336
- hide={props.hide}
1337
- barSize={props.barSize}
1338
- minPointSize={props.minPointSize}
1339
- maxBarSize={props.maxBarSize}
1340
- isPanorama={isPanorama}
1341
- hasCustomShape={hasCustomShape()}
1342
- />
1343
- <SetErrorBarContext
1344
- xAxisId={props.xAxisId}
1345
- yAxisId={props.yAxisId}
1346
- data={rects()}
1347
- dataPointFormatter={errorBarDataPointFormatter}
1348
- errorBarOffset={errorBarOffset()}
1349
- >
1350
- <BarChildrenScope
1351
- childrenProps={childrenProps}
1352
- id={id}
1353
- mergedBarProps={props}
1354
- />
1355
- </SetErrorBarContext>
1356
- </>
1357
- )
1358
- }}
1359
- </RegisterGraphicalItemId>
1360
- )
1361
- }
1362
-
1363
- export const Bar = BarFn as {
1364
- <DataPointType = any, DataValueType = any>(props: Props<DataPointType, DataValueType>): JSX.Element
1365
- /* eslint-disable-next-line typescript-eslint/no-explicit-any -- upstream fallback overload for mismatched data/dataKey */
1366
- (props: Props<any, any>): JSX.Element
1367
- displayName?: string
1368
- }
1369
- Bar.displayName = "Bar"