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.
- package/NEXT_SESSION_PROMPT.md +114 -0
- package/package.json +28 -0
- package/src/animation/AnimatedItems.tsx +169 -0
- package/src/animation/AnimationController.ts +24 -0
- package/src/animation/AnimationControllerImpl.ts +37 -0
- package/src/animation/AnimationHandle.ts +273 -0
- package/src/animation/CSSTransitionAnimate.tsx +142 -0
- package/src/animation/JavascriptAnimate.tsx +107 -0
- package/src/animation/easing.ts +261 -0
- package/src/animation/matchBy.ts +211 -0
- package/src/animation/timeoutController.ts +51 -0
- package/src/animation/useAnimationController.tsx +31 -0
- package/src/animation/useAnimationStartSnapshot.ts +73 -0
- package/src/animation/util.ts +16 -0
- package/src/cartesian/Area.tsx +810 -0
- package/src/cartesian/AreaRevealShape.tsx +250 -0
- package/src/cartesian/Bar.tsx +1216 -0
- package/src/cartesian/BarStack.tsx +148 -0
- package/src/cartesian/Brush.tsx +653 -0
- package/src/cartesian/CartesianAxis.tsx +541 -0
- package/src/cartesian/CartesianGrid.tsx +605 -0
- package/src/cartesian/ErrorBar.tsx +319 -0
- package/src/cartesian/Funnel.tsx +594 -0
- package/src/cartesian/GraphicalItemClipPath.tsx +75 -0
- package/src/cartesian/Line.tsx +742 -0
- package/src/cartesian/LineDrawShape.tsx +190 -0
- package/src/cartesian/ReferenceArea.tsx +275 -0
- package/src/cartesian/ReferenceDot.tsx +286 -0
- package/src/cartesian/ReferenceLine.tsx +414 -0
- package/src/cartesian/RenderedTicksReporter.tsx +49 -0
- package/src/cartesian/Scatter.tsx +741 -0
- package/src/cartesian/XAxis.tsx +293 -0
- package/src/cartesian/YAxis.tsx +333 -0
- package/src/cartesian/ZAxis.tsx +80 -0
- package/src/cartesian/getCartesianPosition.ts +255 -0
- package/src/cartesian/getEquidistantTicks.ts +126 -0
- package/src/cartesian/getTicks.ts +225 -0
- package/src/cartesian/useAnimatedLineLength.ts +84 -0
- package/src/chart/AreaChart.tsx +30 -0
- package/src/chart/BarChart.tsx +27 -0
- package/src/chart/CartesianChart.tsx +91 -0
- package/src/chart/CategoricalChart.tsx +60 -0
- package/src/chart/ComposedChart.tsx +29 -0
- package/src/chart/FunnelChart.tsx +29 -0
- package/src/chart/LineChart.tsx +29 -0
- package/src/chart/PieChart.tsx +41 -0
- package/src/chart/PolarChart.tsx +97 -0
- package/src/chart/RadarChart.tsx +37 -0
- package/src/chart/RadialBarChart.tsx +39 -0
- package/src/chart/RechartsWrapper.tsx +486 -0
- package/src/chart/Sankey.tsx +992 -0
- package/src/chart/ScatterChart.tsx +29 -0
- package/src/chart/SunburstChart.tsx +394 -0
- package/src/chart/Treemap.tsx +874 -0
- package/src/chart/types.ts +37 -0
- package/src/component/ActivePoints.tsx +136 -0
- package/src/component/Cell.tsx +72 -0
- package/src/component/Cursor.tsx +249 -0
- package/src/component/Customized.tsx +8 -0
- package/src/component/DefaultLegendContent.tsx +205 -0
- package/src/component/DefaultTooltipContent.tsx +247 -0
- package/src/component/Dots.tsx +128 -0
- package/src/component/Label.tsx +507 -0
- package/src/component/LabelList.tsx +270 -0
- package/src/component/Legend.tsx +273 -0
- package/src/component/ResponsiveContainer.tsx +397 -0
- package/src/component/Text.tsx +436 -0
- package/src/component/Tooltip.tsx +309 -0
- package/src/component/TooltipBoundingBox.tsx +152 -0
- package/src/component/responsiveContainerUtils.ts +128 -0
- package/src/container/ClipPathProvider.tsx +40 -0
- package/src/container/Layer.tsx +38 -0
- package/src/container/RootSurface.tsx +124 -0
- package/src/container/Surface.tsx +70 -0
- package/src/context/ErrorBarContext.tsx +85 -0
- package/src/context/PanoramaContext.tsx +13 -0
- package/src/context/RegisterGraphicalItemId.tsx +41 -0
- package/src/context/accessibilityContext.tsx +10 -0
- package/src/context/brushUpdateContext.ts +14 -0
- package/src/context/chartDataContext.tsx +79 -0
- package/src/context/chartLayoutContext.tsx +158 -0
- package/src/context/legendPayloadContext.ts +11 -0
- package/src/context/legendPortalContext.ts +11 -0
- package/src/context/tooltipContext.ts +72 -0
- package/src/context/tooltipPortalContext.ts +14 -0
- package/src/context/useTooltipAxis.ts +24 -0
- package/src/hooks.ts +312 -0
- package/src/index.ts +288 -0
- package/src/polar/Pie.tsx +912 -0
- package/src/polar/PolarAngleAxis.tsx +494 -0
- package/src/polar/PolarGrid.tsx +269 -0
- package/src/polar/PolarRadiusAxis.tsx +422 -0
- package/src/polar/Radar.tsx +652 -0
- package/src/polar/RadialBar.tsx +767 -0
- package/src/polar/defaultPolarAngleAxisProps.tsx +33 -0
- package/src/polar/defaultPolarRadiusAxisProps.tsx +28 -0
- package/src/shape/Cross.tsx +83 -0
- package/src/shape/Curve.tsx +335 -0
- package/src/shape/Dot.tsx +49 -0
- package/src/shape/Polygon.tsx +168 -0
- package/src/shape/Rectangle.tsx +301 -0
- package/src/shape/Sector.tsx +304 -0
- package/src/shape/Symbols.tsx +144 -0
- package/src/shape/Trapezoid.tsx +228 -0
- package/src/state/RechartsReduxContext.tsx +8 -0
- package/src/state/RechartsStoreContext.ts +15 -0
- package/src/state/RechartsStoreProvider.tsx +27 -0
- package/src/state/ReportChartProps.tsx +19 -0
- package/src/state/ReportEventSettings.tsx +19 -0
- package/src/state/ReportMainChartProps.tsx +35 -0
- package/src/state/ReportPolarOptions.tsx +28 -0
- package/src/state/SetLegendPayload.ts +50 -0
- package/src/state/SetTooltipEntrySettings.tsx +46 -0
- package/src/state/brushSlice.ts +60 -0
- package/src/state/cartesianAxisSlice.ts +288 -0
- package/src/state/chartDataSlice.ts +115 -0
- package/src/state/errorBarSlice.ts +84 -0
- package/src/state/eventSettingsSlice.ts +41 -0
- package/src/state/externalEventsMiddleware.ts +136 -0
- package/src/state/graphicalItemsSlice.ts +162 -0
- package/src/state/hooks.ts +42 -0
- package/src/state/keyboardEventsMiddleware.ts +213 -0
- package/src/state/layoutSlice.ts +71 -0
- package/src/state/legendSlice.ts +107 -0
- package/src/state/mouseEventsMiddleware.ts +103 -0
- package/src/state/optionsSlice.ts +64 -0
- package/src/state/polarAxisSlice.ts +65 -0
- package/src/state/polarOptionsSlice.ts +54 -0
- package/src/state/reduxDevtoolsJsonStringifyReplacer.ts +15 -0
- package/src/state/referenceElementsSlice.ts +121 -0
- package/src/state/renderedTicksSlice.ts +61 -0
- package/src/state/rootPropsSlice.ts +70 -0
- package/src/state/selectors/areaSelectors.ts +169 -0
- package/src/state/selectors/arrayEqualityCheck.ts +8 -0
- package/src/state/selectors/axisSelectors.ts +2196 -0
- package/src/state/selectors/barSelectors.ts +319 -0
- package/src/state/selectors/barStackSelectors.ts +79 -0
- package/src/state/selectors/brushSelectors.ts +40 -0
- package/src/state/selectors/combiners/combineActiveLabel.ts +21 -0
- package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +93 -0
- package/src/state/selectors/combiners/combineAllBarPositions.ts +131 -0
- package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +17 -0
- package/src/state/selectors/combiners/combineBarPosition.ts +24 -0
- package/src/state/selectors/combiners/combineBarSizeList.ts +75 -0
- package/src/state/selectors/combiners/combineCheckedDomain.ts +49 -0
- package/src/state/selectors/combiners/combineConfiguredScale.ts +121 -0
- package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +43 -0
- package/src/state/selectors/combiners/combineDisplayedStackedData.ts +50 -0
- package/src/state/selectors/combiners/combineInverseScaleFunction.ts +17 -0
- package/src/state/selectors/combiners/combineRealScaleType.ts +48 -0
- package/src/state/selectors/combiners/combineStackedData.ts +28 -0
- package/src/state/selectors/combiners/combineTooltipInteractionState.ts +86 -0
- package/src/state/selectors/combiners/combineTooltipPayload.ts +203 -0
- package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +45 -0
- package/src/state/selectors/containerSelectors.ts +12 -0
- package/src/state/selectors/dataSelectors.ts +90 -0
- package/src/state/selectors/funnelSelectors.ts +83 -0
- package/src/state/selectors/graphicalItemSelectors.ts +23 -0
- package/src/state/selectors/legendSelectors.ts +29 -0
- package/src/state/selectors/lineSelectors.ts +111 -0
- package/src/state/selectors/numberDomainEqualityCheck.ts +8 -0
- package/src/state/selectors/pickAxisId.ts +6 -0
- package/src/state/selectors/pickAxisType.ts +4 -0
- package/src/state/selectors/pieSelectors.ts +103 -0
- package/src/state/selectors/polarAxisSelectors.ts +202 -0
- package/src/state/selectors/polarGridSelectors.ts +24 -0
- package/src/state/selectors/polarScaleSelectors.ts +149 -0
- package/src/state/selectors/polarSelectors.ts +211 -0
- package/src/state/selectors/radarSelectors.ts +152 -0
- package/src/state/selectors/radialBarSelectors.ts +328 -0
- package/src/state/selectors/rootPropsSelectors.ts +36 -0
- package/src/state/selectors/scatterSelectors.ts +77 -0
- package/src/state/selectors/selectAllAxes.ts +10 -0
- package/src/state/selectors/selectChartOffset.ts +15 -0
- package/src/state/selectors/selectChartOffsetInternal.ts +111 -0
- package/src/state/selectors/selectPlotArea.ts +27 -0
- package/src/state/selectors/selectTooltipAxisId.ts +6 -0
- package/src/state/selectors/selectTooltipAxisType.ts +33 -0
- package/src/state/selectors/selectTooltipEventType.ts +45 -0
- package/src/state/selectors/selectTooltipPayloadSearcher.ts +7 -0
- package/src/state/selectors/selectTooltipSettings.ts +6 -0
- package/src/state/selectors/selectTooltipState.ts +5 -0
- package/src/state/selectors/tooltipSelectors.ts +690 -0
- package/src/state/selectors/touchSelectors.ts +29 -0
- package/src/state/store.ts +167 -0
- package/src/state/tooltipSlice.ts +289 -0
- package/src/state/types/AreaSettings.ts +17 -0
- package/src/state/types/BarSettings.ts +16 -0
- package/src/state/types/LineSettings.ts +12 -0
- package/src/state/types/PieSettings.ts +32 -0
- package/src/state/types/RadarSettings.ts +6 -0
- package/src/state/types/RadialBarSettings.ts +10 -0
- package/src/state/types/ScatterSettings.ts +13 -0
- package/src/state/types/StackedGraphicalItem.ts +33 -0
- package/src/state/unregisterOnCleanup.ts +26 -0
- package/src/state/zIndexSlice.ts +128 -0
- package/src/synchronisation/syncRegistry.ts +131 -0
- package/src/synchronisation/syncSelectors.ts +7 -0
- package/src/synchronisation/types.ts +42 -0
- package/src/synchronisation/useChartSynchronisation.tsx +372 -0
- package/src/types.ts +39 -0
- package/src/util/ActiveShapeUtils.tsx +80 -0
- package/src/util/BarUtils.tsx +74 -0
- package/src/util/CartesianUtils.ts +53 -0
- package/src/util/ChartUtils.ts +696 -0
- package/src/util/Constants.ts +42 -0
- package/src/util/CssPrefixUtils.ts +24 -0
- package/src/util/DOMUtils.ts +141 -0
- package/src/util/DataUtils.ts +205 -0
- package/src/util/FunnelUtils.tsx +37 -0
- package/src/util/Global.ts +15 -0
- package/src/util/IfOverflow.ts +17 -0
- package/src/util/LRUCache.ts +46 -0
- package/src/util/LogUtils.ts +26 -0
- package/src/util/PolarUtils.ts +134 -0
- package/src/util/RadialBarUtils.tsx +35 -0
- package/src/util/ReduceCSSCalc.ts +186 -0
- package/src/util/ShallowEqual.ts +43 -0
- package/src/util/TickUtils.ts +61 -0
- package/src/util/YAxisUtils.ts +49 -0
- package/src/util/adaptEventHandlers.ts +69 -0
- package/src/util/axisPropsAreEqual.ts +42 -0
- package/src/util/collectionUtils.ts +83 -0
- package/src/util/createCartesianCharts.tsx +101 -0
- package/src/util/createEventProxy.ts +24 -0
- package/src/util/createPolarCharts.tsx +86 -0
- package/src/util/cursor/getCursorPoints.ts +48 -0
- package/src/util/cursor/getCursorRectangle.ts +31 -0
- package/src/util/cursor/getRadialCursorPoints.ts +34 -0
- package/src/util/excludeEventProps.ts +172 -0
- package/src/util/getActiveCoordinate.ts +205 -0
- package/src/util/getAxisTypeBasedOnLayout.ts +21 -0
- package/src/util/getEveryNth.ts +30 -0
- package/src/util/getRadiusAndStrokeWidthFromDot.ts +35 -0
- package/src/util/getRelativeCoordinate.ts +84 -0
- package/src/util/getSliced.ts +21 -0
- package/src/util/isDomainSpecifiedByUser.ts +217 -0
- package/src/util/isWellBehavedNumber.ts +10 -0
- package/src/util/objectPath.ts +129 -0
- package/src/util/payload/getUniqPayload.ts +31 -0
- package/src/util/propsAreEqual.ts +137 -0
- package/src/util/resolveDefaultProps.tsx +8 -0
- package/src/util/round.ts +35 -0
- package/src/util/scale/CartesianScaleHelper.ts +72 -0
- package/src/util/scale/CustomScaleDefinition.ts +82 -0
- package/src/util/scale/RechartsScale.ts +131 -0
- package/src/util/scale/createCategoricalInverse.ts +83 -0
- package/src/util/scale/getNiceTickValues.ts +334 -0
- package/src/util/scale/index.ts +3 -0
- package/src/util/scale/util/DecimalLite.ts +194 -0
- package/src/util/scale/util/arithmetic.ts +56 -0
- package/src/util/stacks/getStackSeriesIdentifier.ts +20 -0
- package/src/util/stacks/stackTypes.ts +53 -0
- package/src/util/svgPropertiesAndEvents.ts +84 -0
- package/src/util/svgPropertiesNoEvents.ts +520 -0
- package/src/util/tooltip/translate.ts +179 -0
- package/src/util/typedDataKey.ts +8 -0
- package/src/util/types.ts +724 -0
- package/src/util/useAnimationId.tsx +31 -0
- package/src/util/useElementOffset.ts +164 -0
- package/src/util/useId.ts +20 -0
- package/src/util/usePrefersReducedMotion.ts +44 -0
- package/src/util/useUniqueId.ts +34 -0
- package/src/zIndex/DefaultZIndexes.tsx +87 -0
- package/src/zIndex/ZIndexLayer.tsx +126 -0
- package/src/zIndex/ZIndexPortal.tsx +69 -0
- package/src/zIndex/getZIndexFromUnknown.tsx +17 -0
- package/src/zIndex/zIndexSelectors.ts +46 -0
- package/test/_data.ts +408 -0
- package/test/animation/AnimationController.typed.spec.ts +53 -0
- package/test/animation/AnimationControllerImpl.spec.ts +271 -0
- package/test/animation/CSSTransitionAnimate.timing.spec.tsx +473 -0
- package/test/animation/JavascriptAnimate.spec.tsx +62 -0
- package/test/animation/RechartsAnimation.spec.ts +636 -0
- package/test/animation/easing.spec.ts +218 -0
- package/test/animation/legacyAnimationLengthChange.spec.tsx +803 -0
- package/test/animation/matchBy.spec.ts +467 -0
- package/test/animation/mockAnimationController.ts +40 -0
- package/test/animation/mockControllerAnimationManager.ts +143 -0
- package/test/animation/mockTimeoutController.ts +114 -0
- package/test/animation/timeoutController.spec.ts +138 -0
- package/test/animation/useAnimationStartSnapshot.spec.ts +147 -0
- package/test/animation/util.spec.ts +28 -0
- package/test/cartesian/Area.animation.spec.tsx +363 -0
- package/test/cartesian/Area.range.spec.tsx +54 -0
- package/test/cartesian/Area.spec.tsx +1202 -0
- package/test/cartesian/Area.stacked.render.spec.tsx +69 -0
- package/test/cartesian/Area.typed.spec.tsx +209 -0
- package/test/cartesian/Axis.integration.spec.tsx +158 -0
- package/test/cartesian/Bar/Bar.csstransition.spec.tsx +299 -0
- package/test/cartesian/Bar/Bar.spec.tsx +2314 -0
- package/test/cartesian/Bar/Bar.typed.spec.tsx +192 -0
- package/test/cartesian/Bar.animation.spec.tsx +426 -0
- package/test/cartesian/Bar.stackDomain.spec.tsx +66 -0
- package/test/cartesian/Bar.stacked.render.spec.tsx +53 -0
- package/test/cartesian/Bar.truncateByDomain.spec.tsx +237 -0
- package/test/cartesian/Bar.zeroDimensionFiltering.spec.tsx +336 -0
- package/test/cartesian/BarStack.spec.tsx +91 -0
- package/test/cartesian/Brush.keyboard.spec.tsx +88 -0
- package/test/cartesian/Brush.panorama.spec.tsx +41 -0
- package/test/cartesian/Brush.props.spec.tsx +63 -0
- package/test/cartesian/Brush.render.spec.tsx +117 -0
- package/test/cartesian/Brush.spec.tsx +522 -0
- package/test/cartesian/Brush.stacked.spec.tsx +221 -0
- package/test/cartesian/CartesianAxis.render.spec.tsx +50 -0
- package/test/cartesian/CartesianAxis.spec.tsx +396 -0
- package/test/cartesian/CartesianGrid.render.spec.tsx +39 -0
- package/test/cartesian/CartesianGrid.spec.tsx +2103 -0
- package/test/cartesian/ErrorBar.render.spec.tsx +69 -0
- package/test/cartesian/ErrorBar.spec.tsx +2414 -0
- package/test/cartesian/Funnel.animation.spec.tsx +241 -0
- package/test/cartesian/Funnel.spec.tsx +226 -0
- package/test/cartesian/Funnel.typed.spec.tsx +221 -0
- package/test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx +627 -0
- package/test/cartesian/GraphicalItemClipPath.spec.tsx +427 -0
- package/test/cartesian/Line.animation.spec.tsx +643 -0
- package/test/cartesian/Line.sparseAnimationPath.spec.tsx +98 -0
- package/test/cartesian/Line.spec.tsx +471 -0
- package/test/cartesian/Line.typed.spec.tsx +152 -0
- package/test/cartesian/ReferenceArea.render.spec.tsx +63 -0
- package/test/cartesian/ReferenceArea.spec.tsx +663 -0
- package/test/cartesian/ReferenceArea.typed.spec.tsx +74 -0
- package/test/cartesian/ReferenceDot.render.spec.tsx +55 -0
- package/test/cartesian/ReferenceDot.spec.tsx +462 -0
- package/test/cartesian/ReferenceDot.typed.spec.tsx +76 -0
- package/test/cartesian/ReferenceLine/ReferenceLine.panorama.spec.tsx +184 -0
- package/test/cartesian/ReferenceLine/ReferenceLine.spec.tsx +744 -0
- package/test/cartesian/ReferenceLine/ReferenceLine.typed.spec.tsx +74 -0
- package/test/cartesian/ReferenceLine/getEndPoints.spec.ts +399 -0
- package/test/cartesian/ReferenceLine.render.spec.tsx +134 -0
- package/test/cartesian/Scatter.animation.spec.tsx +381 -0
- package/test/cartesian/Scatter.render.spec.tsx +61 -0
- package/test/cartesian/Scatter.spec.tsx +406 -0
- package/test/cartesian/Scatter.typed.spec.tsx +153 -0
- package/test/cartesian/XAxis/XAxis.barSize.spec.tsx +336 -0
- package/test/cartesian/XAxis/XAxis.brush.spec.tsx +266 -0
- package/test/cartesian/XAxis/XAxis.categorydomain.spec.tsx +872 -0
- package/test/cartesian/XAxis/XAxis.dataKey.spec.tsx +86 -0
- package/test/cartesian/XAxis/XAxis.datatypes.spec.tsx +127 -0
- package/test/cartesian/XAxis/XAxis.hide.spec.tsx +106 -0
- package/test/cartesian/XAxis/XAxis.multiaxis.spec.tsx +336 -0
- package/test/cartesian/XAxis/XAxis.numberdomain.spec.tsx +1466 -0
- package/test/cartesian/XAxis/XAxis.padding.spec.tsx +758 -0
- package/test/cartesian/XAxis/XAxis.padding_clip.spec.tsx +65 -0
- package/test/cartesian/XAxis/XAxis.state.spec.tsx +355 -0
- package/test/cartesian/XAxis/XAxis.tick.spec.tsx +493 -0
- package/test/cartesian/XAxis/XAxis.timescale.spec.tsx +233 -0
- package/test/cartesian/XAxis/XAxis.type.spec.tsx +107 -0
- package/test/cartesian/XAxis/XAxis.typed.spec.tsx +102 -0
- package/test/cartesian/XAxis/XAxis.vertical.spec.tsx +265 -0
- package/test/cartesian/XAxis.tickFormatter.spec.tsx +54 -0
- package/test/cartesian/YAxis/YAxis.7362.derivedDomain.spec.tsx +230 -0
- package/test/cartesian/YAxis/YAxis.7362.spec.tsx +104 -0
- package/test/cartesian/YAxis/YAxis.interval-zero.spec.tsx +88 -0
- package/test/cartesian/YAxis/YAxis.label.spec.tsx +219 -0
- package/test/cartesian/YAxis/YAxis.spec.tsx +1595 -0
- package/test/cartesian/YAxis/YAxis.tick.spec.tsx +428 -0
- package/test/cartesian/YAxis/YAxis.tickFormatter.spec.tsx +54 -0
- package/test/cartesian/YAxis/YAxis.ticks.spec.tsx +263 -0
- package/test/cartesian/YAxis/YAxis.type.spec.tsx +107 -0
- package/test/cartesian/YAxis/YAxis.typed.spec.tsx +102 -0
- package/test/cartesian/ZAxis.spec.tsx +300 -0
- package/test/cartesian/ZAxis.typed.spec.tsx +33 -0
- package/test/cartesian/__snapshots__/Brush.spec.tsx.snap +5 -0
- package/test/cartesian/axisLineAndStroke.spec.tsx +72 -0
- package/test/cartesian/getCartesianPosition.spec.ts +907 -0
- package/test/cartesian/getEquidistantTicks.spec.ts +88 -0
- package/test/cartesian/getTicks.spec.ts +378 -0
- package/test/cartesian/miscFeatureGaps.spec.tsx +89 -0
- package/test/cartesian/useAnimatedLineLength.spec.ts +168 -0
- package/test/chart/AccessibilityLayer.spec.tsx +569 -0
- package/test/chart/AccessibilityScans.spec.tsx +286 -0
- package/test/chart/AreaChart.spec.tsx +409 -0
- package/test/chart/AreaChart.stacked.spec.tsx +1407 -0
- package/test/chart/AreaChart.typed.spec.tsx +39 -0
- package/test/chart/BarChart.spec.tsx +3719 -0
- package/test/chart/BarChart.typed.spec.tsx +60 -0
- package/test/chart/CategoricalChart.spec.tsx +255 -0
- package/test/chart/ComposedChart.spec.tsx +199 -0
- package/test/chart/ComposedChart.typed.spec.tsx +39 -0
- package/test/chart/FunnelChart.spec.tsx +215 -0
- package/test/chart/FunnelChart.typed.spec.tsx +39 -0
- package/test/chart/LineChart.multiseries.spec.tsx +50 -0
- package/test/chart/LineChart.smoke.spec.tsx +50 -0
- package/test/chart/LineChart.spec.tsx +930 -0
- package/test/chart/LineChart.typed.spec.tsx +39 -0
- package/test/chart/NicheChartTooltip.spec.tsx +81 -0
- package/test/chart/PieChart.spec.tsx +793 -0
- package/test/chart/PieChart.typed.spec.tsx +39 -0
- package/test/chart/RadarChart.spec.tsx +530 -0
- package/test/chart/RadarChart.typed.spec.tsx +39 -0
- package/test/chart/RadialBarChart.5966.spec.tsx +48 -0
- package/test/chart/RadialBarChart.spec.tsx +679 -0
- package/test/chart/RadialBarChart.typed.spec.tsx +39 -0
- package/test/chart/RechartsWrapper.spec.tsx +83 -0
- package/test/chart/Sankey.content.spec.tsx +46 -0
- package/test/chart/Sankey.spec.tsx +952 -0
- package/test/chart/Sankey.typed.spec.tsx +29 -0
- package/test/chart/ScatterChart.spec.tsx +2613 -0
- package/test/chart/ScatterChart.typed.spec.tsx +39 -0
- package/test/chart/SunburstChart.spec.tsx +146 -0
- package/test/chart/Treemap.animation.spec.tsx +52 -0
- package/test/chart/Treemap.spec.tsx +1003 -0
- package/test/chart/Treemap.typed.spec.tsx +26 -0
- package/test/chart/chartEvents.spec.tsx +127 -0
- package/test/chart/responsive.spec.tsx +620 -0
- package/test/component/Cell.render.spec.tsx +155 -0
- package/test/component/Cell.spec.tsx +12 -0
- package/test/component/Cursor.spec.tsx +186 -0
- package/test/component/DefaultTooltipContent.spec.tsx +102 -0
- package/test/component/Label.render.spec.tsx +63 -0
- package/test/component/Label.spec.tsx +686 -0
- package/test/component/Label.typed.spec.tsx +46 -0
- package/test/component/LabelList.spec.tsx +188 -0
- package/test/component/Legend.itemSorter.spec.tsx +704 -0
- package/test/component/Legend.render.spec.tsx +92 -0
- package/test/component/Legend.spec.tsx +2213 -0
- package/test/component/Legend.typed.spec.tsx +22 -0
- package/test/component/ResponsiveContainer.spec.tsx +523 -0
- package/test/component/ResponsiveContainerDataTest.spec.tsx +51 -0
- package/test/component/Text.spec.tsx +415 -0
- package/test/component/Text.typed.spec.tsx +46 -0
- package/test/component/Tooltip/ActiveDot.spec.tsx +370 -0
- package/test/component/Tooltip/Tooltip.animation.spec.tsx +209 -0
- package/test/component/Tooltip/Tooltip.content.spec.tsx +128 -0
- package/test/component/Tooltip/Tooltip.formatter.spec.tsx +152 -0
- package/test/component/Tooltip/Tooltip.includeHidden.spec.tsx +79 -0
- package/test/component/Tooltip/Tooltip.multipleDataArrays.spec.tsx +165 -0
- package/test/component/Tooltip/Tooltip.offset.spec.tsx +113 -0
- package/test/component/Tooltip/Tooltip.state.spec.tsx +74 -0
- package/test/component/Tooltip/Tooltip.sync.spec.tsx +639 -0
- package/test/component/Tooltip/defaultIndex.spec.tsx +227 -0
- package/test/component/Tooltip/graphicalItem.formatter.spec.tsx +138 -0
- package/test/component/Tooltip/itemSorter.spec.tsx +2815 -0
- package/test/component/Tooltip/tooltipEventType.spec.tsx +344 -0
- package/test/component/Tooltip/tooltipMouseHoverSelectors.ts +41 -0
- package/test/component/Tooltip/tooltipTestHelpers.tsx +162 -0
- package/test/component/Tooltip.defaultIndex.spec.tsx +48 -0
- package/test/component/Tooltip.hover.spec.tsx +61 -0
- package/test/component/Tooltip.item.spec.tsx +54 -0
- package/test/component/Tooltip.keyboard.spec.tsx +51 -0
- package/test/component/Tooltip.payload.spec.tsx +1716 -0
- package/test/component/Tooltip.touch.spec.tsx +39 -0
- package/test/component/Tooltip.visibility.spec.tsx +1889 -0
- package/test/component/TooltipBoundingBox.spec.tsx +89 -0
- package/test/component/responsiveContainerUtils.spec.ts +205 -0
- package/test/container/ClipPath.spec.tsx +602 -0
- package/test/container/chartDimensions.spec.tsx +368 -0
- package/test/context/chartLayoutContext.spec.tsx +378 -0
- package/test/helper/ExpectAxisDomain.tsx +27 -0
- package/test/helper/assertNotNull.ts +6 -0
- package/test/helper/assertZIndexLayerOrder.ts +19 -0
- package/test/helper/createSelectorTestCase.tsx +176 -0
- package/test/helper/expectAnimatedPieAngles.ts +100 -0
- package/test/helper/expectAnimatedPiePaths.ts +78 -0
- package/test/helper/expectAreaCurve.ts +15 -0
- package/test/helper/expectAxisTicks.ts +48 -0
- package/test/helper/expectBars.ts +54 -0
- package/test/helper/expectFunctionReturning.ts +58 -0
- package/test/helper/expectLabel.ts +32 -0
- package/test/helper/expectLastCalledWith.ts +48 -0
- package/test/helper/expectLine.ts +20 -0
- package/test/helper/expectPieSectors.ts +80 -0
- package/test/helper/expectScale.ts +37 -0
- package/test/helper/expectScatterPoints.ts +52 -0
- package/test/helper/expectStackGroups.ts +144 -0
- package/test/helper/mockAxes.ts +22 -0
- package/test/helper/mockGetBoundingClientRect.ts +66 -0
- package/test/helper/mockHTMLElementProperty.ts +19 -0
- package/test/helper/mockTouchingElement.ts +27 -0
- package/test/helper/offsetHelpers.ts +19 -0
- package/test/helper/parameterizedTestCases.tsx +99 -0
- package/test/helper/produceState.ts +32 -0
- package/test/helper/render.ts +7 -0
- package/test/helper/selectorTestHelpers.tsx +63 -0
- package/test/helper/trim.spec.ts +35 -0
- package/test/helper/trim.ts +11 -0
- package/test/hooks/useActiveTooltipDataPoints.spec.tsx +358 -0
- package/test/hooks/useAxisDomain.spec.tsx +361 -0
- package/test/hooks/useAxisScale.spec.tsx +283 -0
- package/test/hooks/useAxisTicks.spec.tsx +130 -0
- package/test/hooks/useOffset.spec.tsx +248 -0
- package/test/hooks/useTooltipStateHooks.spec.tsx +109 -0
- package/test/polar/Pie/Pie-TwoLevelPieChart.spec.tsx +135 -0
- package/test/polar/Pie/Pie.spec.tsx +784 -0
- package/test/polar/Pie/Pie.typed.spec.tsx +78 -0
- package/test/polar/Pie.animation.spec.tsx +529 -0
- package/test/polar/PieWithLegend.animation.spec.tsx +142 -0
- package/test/polar/PolarAngleAxis/PolarAngleAxis.events.spec.tsx +76 -0
- package/test/polar/PolarAngleAxis/PolarAngleAxis.spec.tsx +2079 -0
- package/test/polar/PolarAngleAxis/PolarAngleAxis.typed.spec.tsx +102 -0
- package/test/polar/PolarAngleAxis.render.spec.tsx +79 -0
- package/test/polar/PolarGrid.render.spec.tsx +75 -0
- package/test/polar/PolarGrid.spec.tsx +918 -0
- package/test/polar/PolarLegendPerRow.render.spec.tsx +85 -0
- package/test/polar/PolarRadiusAxis.events.spec.tsx +65 -0
- package/test/polar/PolarRadiusAxis.render.spec.tsx +52 -0
- package/test/polar/PolarRadiusAxis.spec.tsx +991 -0
- package/test/polar/PolarRadiusAxis.typed.spec.tsx +84 -0
- package/test/polar/PolarTooltipLegend.render.spec.tsx +80 -0
- package/test/polar/Radar.animation.spec.tsx +570 -0
- package/test/polar/Radar.render.spec.tsx +71 -0
- package/test/polar/Radar.spec.tsx +265 -0
- package/test/polar/Radar.typed.spec.tsx +119 -0
- package/test/polar/RadialBar/RadialBar.spec.tsx +1521 -0
- package/test/polar/RadialBar/RadialBar.typed.spec.tsx +132 -0
- package/test/polar/RadialBar.animation.spec.tsx +375 -0
- package/test/polar/RadialBar.render.spec.tsx +66 -0
- package/test/polar/RadialBar.stacked.spec.tsx +57 -0
- package/test/setup.ts +84 -0
- package/test/shape/ActiveShape.spec.tsx +181 -0
- package/test/shape/Cross.spec.tsx +60 -0
- package/test/shape/Cross.typed.spec.tsx +26 -0
- package/test/shape/Curve.spec.tsx +368 -0
- package/test/shape/Curve.typed.spec.tsx +69 -0
- package/test/shape/Dot.spec.tsx +73 -0
- package/test/shape/Dot.typed.spec.tsx +30 -0
- package/test/shape/Polygon.spec.tsx +357 -0
- package/test/shape/Polygon.typed.spec.tsx +28 -0
- package/test/shape/Rectangle.animation.spec.tsx +451 -0
- package/test/shape/Rectangle.spec.tsx +68 -0
- package/test/shape/Rectangle.typed.spec.tsx +24 -0
- package/test/shape/Sector.spec.tsx +76 -0
- package/test/shape/Sector.typed.spec.tsx +24 -0
- package/test/shape/Symbols.spec.tsx +43 -0
- package/test/shape/Symbols.typed.spec.tsx +24 -0
- package/test/shape/Trapezoid.spec.tsx +50 -0
- package/test/shape/Trapezoid.typed.spec.tsx +24 -0
- package/test/shape/__snapshots__/Cross.spec.tsx.snap +62 -0
- package/test/shape/__snapshots__/Curve.spec.tsx.snap +460 -0
- package/test/shape/__snapshots__/Polygon.spec.tsx.snap +58 -0
- package/test/shape/__snapshots__/Rectangle.spec.tsx.snap +117 -0
- package/test/shape/__snapshots__/Sector.spec.tsx.snap +71 -0
- package/test/shape/__snapshots__/Trapezoid.spec.tsx.snap +64 -0
- package/test/state/chartDataSlice.spec.ts +53 -0
- package/test/state/externalEventsMiddleware.spec.ts +178 -0
- package/test/state/graphicalItemsSlice.spec.ts +92 -0
- package/test/state/hooks.spec.tsx +68 -0
- package/test/state/legendSlice.spec.ts +44 -0
- package/test/state/mouseEventsMiddleware.spec.ts +75 -0
- package/test/state/optionsSlice.spec.ts +19 -0
- package/test/state/reduxDevtoolsJsonStringifyReplacer.spec.ts +25 -0
- package/test/state/referenceElementsSlice.spec.ts +84 -0
- package/test/state/selectors/areaSelectors.spec.tsx +77 -0
- package/test/state/selectors/axisSelectors.spec.tsx +1418 -0
- package/test/state/selectors/barStackSelectors.spec.tsx +752 -0
- package/test/state/selectors/brushSelectors.spec.tsx +30 -0
- package/test/state/selectors/cartesianAxisSlice.spec.ts +96 -0
- package/test/state/selectors/combineNiceTicks.spec.ts +207 -0
- package/test/state/selectors/combiners/combineActiveTooltipIndex.spec.ts +61 -0
- package/test/state/selectors/combiners/combineAllBarPositions.spec.ts +39 -0
- package/test/state/selectors/combiners/combineConfiguredScale.spec.ts +56 -0
- package/test/state/selectors/combiners/combineDisplayedStackedData.spec.ts +123 -0
- package/test/state/selectors/combiners/combineRealScaleType.spec.ts +80 -0
- package/test/state/selectors/containerSelectors.spec.tsx +168 -0
- package/test/state/selectors/dataSelectors.spec.tsx +136 -0
- package/test/state/selectors/legendSelectors.spec.tsx +113 -0
- package/test/state/selectors/lineSelectors.spec.tsx +60 -0
- package/test/state/selectors/pieSelectors.spec.tsx +72 -0
- package/test/state/selectors/radarSelectors.spec.tsx +496 -0
- package/test/state/selectors/rootPropsSelectors.spec.tsx +169 -0
- package/test/state/selectors/scatterSelectors.spec.tsx +47 -0
- package/test/state/selectors/selectActiveTooltipIndex.spec.tsx +234 -0
- package/test/state/selectors/selectAllAxes.spec.tsx +18 -0
- package/test/state/selectors/selectAxisDomain.spec.tsx +21 -0
- package/test/state/selectors/selectAxisDomainIncludingNiceTicks.spec.tsx +19 -0
- package/test/state/selectors/selectAxisRangeWithReverse.spec.tsx +22 -0
- package/test/state/selectors/selectAxisScale.spec.tsx +91 -0
- package/test/state/selectors/selectBarRectangles.stackOffset.spec.tsx +503 -0
- package/test/state/selectors/selectBaseAxis.spec.tsx +56 -0
- package/test/state/selectors/selectCartesianItemsSettings.spec.tsx +57 -0
- package/test/state/selectors/selectChartOffset.spec.tsx +26 -0
- package/test/state/selectors/selectDisplayedData.spec.tsx +282 -0
- package/test/state/selectors/selectIsTooltipActive.spec.tsx +231 -0
- package/test/state/selectors/selectNumericalDomain.spec.tsx +21 -0
- package/test/state/selectors/selectRealScaleType.spec.tsx +19 -0
- package/test/state/selectors/selectStackGroups.spec.tsx +322 -0
- package/test/state/selectors/selectXAxisPosition.spec.tsx +22 -0
- package/test/state/selectors/selectYAxisPosition.spec.tsx +22 -0
- package/test/state/selectors/selectors.spec.tsx +1613 -0
- package/test/state/throttling.spec.ts +200 -0
- package/test/state/zIndexSlice.spec.ts +85 -0
- package/test/synchronisation/useChartSynchronisation.spec.tsx +225 -0
- package/test/util/BarUtils.spec.ts +39 -0
- package/test/util/CartesianUtils/CartesianUtils.spec.ts +261 -0
- package/test/util/CartesianUtils/rectWithPoints.spec.ts +48 -0
- package/test/util/ChartUtils/ChartUtils.spec.ts +491 -0
- package/test/util/ChartUtils/appendOffsetOfLegend.spec.ts +136 -0
- package/test/util/ChartUtils/appendOffsetOfLegend.spec.tsx +133 -0
- package/test/util/ChartUtils/getCateCoordinateOfLine.spec.ts +83 -0
- package/test/util/ChartUtils/getStackedData.spec.ts +416 -0
- package/test/util/ChartUtils/truncateByDomain.spec.ts +70 -0
- package/test/util/DataUtils.spec.ts +385 -0
- package/test/util/DomUtils.spec.tsx +117 -0
- package/test/util/FunnelUtils.spec.tsx +70 -0
- package/test/util/Global.spec.ts +11 -0
- package/test/util/LRUCache.spec.ts +81 -0
- package/test/util/LogUtils.spec.ts +45 -0
- package/test/util/PolarUtils.spec.ts +66 -0
- package/test/util/ReduceCssCalcPrototype.spec.ts +141 -0
- package/test/util/ShallowEqual.spec.ts +102 -0
- package/test/util/TickUtils.spec.ts +29 -0
- package/test/util/axisPropsAreEqual.spec.ts +93 -0
- package/test/util/createChartHelpers.spec.tsx +210 -0
- package/test/util/cursor/getCursorPoints.spec.ts +136 -0
- package/test/util/cursor/getCursorRectangle.spec.ts +50 -0
- package/test/util/cursor/getRadialCursorPoints.spec.ts +36 -0
- package/test/util/errorValue.spec.ts +69 -0
- package/test/util/getEveryNth.spec.ts +39 -0
- package/test/util/getRadiusAndStrokeWidthFromDot.spec.ts +51 -0
- package/test/util/getRelativeCoordinate.spec.ts +250 -0
- package/test/util/getSliced.spec.ts +45 -0
- package/test/util/isDomainSpecifiedByUser.spec.ts +207 -0
- package/test/util/isWellBehavedNumber.spec.ts +54 -0
- package/test/util/payload/getUniqPayload.spec.ts +56 -0
- package/test/util/propsAreEqual.spec.ts +75 -0
- package/test/util/round.spec.ts +112 -0
- package/test/util/scale/arithmetic.spec.ts +61 -0
- package/test/util/scale/createCategoricalInverse.spec.ts +84 -0
- package/test/util/scale/getNiceTickValues.spec.ts +421 -0
- package/test/util/scale/getTickValuesFixedDomain.spec.ts +155 -0
- package/test/util/svgPropertiesAndEvents.spec.tsx +206 -0
- package/test/util/svgPropertiesNoEvents.spec.tsx +228 -0
- package/test/util/tooltip/translate.spec.ts +396 -0
- package/test/util/useAnimationId.spec.tsx +59 -0
- package/test/util/useElementOffset.spec.tsx +173 -0
- package/test/util/usePrefersReducedMotion.spec.ts +54 -0
- package/test/util/useUniqueId.spec.ts +99 -0
- package/test/utils/diagnostics-allowlist.ts +18 -0
- package/test/utils/diagnostics.ts +58 -0
- package/test/zIndex/AllZIndexPortals.spec.tsx +83 -0
- package/test/zIndex/DefaultZIndexes.spec.ts +80 -0
- package/test/zIndex/DynamicZIndex.spec.tsx +102 -0
- package/test/zIndex/ZIndexLayer.portalOwner.spec.tsx +125 -0
- package/test/zIndex/componentZIndex.spec.tsx +255 -0
- package/test/zIndex/getZIndexFromUnknown.spec.ts +51 -0
- package/test/zIndex/multiChartZIndexIsolation.spec.tsx +90 -0
- package/test/zIndex/zIndexSelectors.spec.ts +172 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,1216 @@
|
|
|
1
|
+
// Ported from recharts 3.8.1 src/cartesian/Bar.tsx (commit 7a23854).
|
|
2
|
+
//
|
|
3
|
+
// MINIMAL PORT — a second graphical item, reusing the axis spine + the band scale.
|
|
4
|
+
// Deferred (documented): range bars (scalar values only), element-form shape,
|
|
5
|
+
// ErrorBar.
|
|
6
|
+
// activeBar CSS transition + ZIndexLayer: vendor/recharts-reference/src/cartesian/Bar.tsx L573–671.
|
|
7
|
+
// (Stacks, animation, labels,
|
|
8
|
+
// tooltip/legend, Cells — per-bar fill/stroke/class via <Cell> children — and the
|
|
9
|
+
// function-form custom `shape` render prop are wired.)
|
|
10
|
+
// Solid deviations: `resolveDefaultProps`→`merge`; RegisterGraphicalItemId +
|
|
11
|
+
// Set* effect-dispatch components → a `createEffect` add/replace + `onCleanup`
|
|
12
|
+
// remove (the same idiom as <Line>).
|
|
13
|
+
import { createEffect, createMemo, createSignal, For, merge, Show } from "solid-js";
|
|
14
|
+
import type { JSX } from "@solidjs/web";
|
|
15
|
+
import { noop } from "../util/DataUtils";
|
|
16
|
+
import { useAppSelector, useAppStore } from "../state/hooks";
|
|
17
|
+
import {
|
|
18
|
+
AnimatedItems,
|
|
19
|
+
type AnimationInterpolateFn,
|
|
20
|
+
useAnimationCallbacks,
|
|
21
|
+
} from "../animation/AnimatedItems";
|
|
22
|
+
import { matchAppend, type AnimationMatchByProp } from "../animation/matchBy";
|
|
23
|
+
import type { MutableRef } from "../animation/useAnimationStartSnapshot";
|
|
24
|
+
import type { EasingInput } from "../animation/easing";
|
|
25
|
+
import { useCartesianChartLayout } from "../context/chartLayoutContext";
|
|
26
|
+
import { RegisterGraphicalItemId } from "../context/RegisterGraphicalItemId";
|
|
27
|
+
import { SetErrorBarContext } from "../context/ErrorBarContext";
|
|
28
|
+
import type { ErrorBarDataItem, ErrorBarDataPointFormatter } from "./ErrorBar";
|
|
29
|
+
import { SetTooltipEntrySettings } from "../state/SetTooltipEntrySettings";
|
|
30
|
+
import { TooltipPayloadConfiguration } from "../state/tooltipSlice";
|
|
31
|
+
import { SetLegendPayload } from "../state/SetLegendPayload";
|
|
32
|
+
import { LegendPayload } from "../component/DefaultLegendContent";
|
|
33
|
+
import type { Formatter } from "../component/DefaultTooltipContent";
|
|
34
|
+
import {
|
|
35
|
+
useMouseClickItemDispatch,
|
|
36
|
+
useMouseEnterItemDispatch,
|
|
37
|
+
useMouseLeaveItemDispatch,
|
|
38
|
+
} from "../context/tooltipContext";
|
|
39
|
+
import { useIsPanorama } from "../context/PanoramaContext";
|
|
40
|
+
import { useUniqueId } from "../util/useUniqueId";
|
|
41
|
+
import { Layer } from "../container/Layer";
|
|
42
|
+
import { GraphicalItemClipPath, useNeedsClip } from "./GraphicalItemClipPath";
|
|
43
|
+
import { type CellProps, collectCells } from "../component/Cell";
|
|
44
|
+
import {
|
|
45
|
+
type CartesianLabelListEntry,
|
|
46
|
+
CartesianLabelListContextProvider,
|
|
47
|
+
type ImplicitLabelListType,
|
|
48
|
+
LabelListFromLabelProp,
|
|
49
|
+
} from "../component/LabelList";
|
|
50
|
+
import { selectBarRectangles } from "../state/selectors/barSelectors";
|
|
51
|
+
import { BarSettings } from "../state/types/BarSettings";
|
|
52
|
+
import { AxisId } from "../state/cartesianAxisSlice";
|
|
53
|
+
import { ChartData } from "../state/chartDataSlice";
|
|
54
|
+
import {
|
|
55
|
+
AnimationDuration,
|
|
56
|
+
CartesianLayout,
|
|
57
|
+
CartesianViewBoxRequired,
|
|
58
|
+
Coordinate,
|
|
59
|
+
DataKey,
|
|
60
|
+
LegendType,
|
|
61
|
+
ShapeAnimationProps,
|
|
62
|
+
TickItem,
|
|
63
|
+
TooltipType,
|
|
64
|
+
TrapezoidViewBox,
|
|
65
|
+
} from "../util/types";
|
|
66
|
+
import {
|
|
67
|
+
getBaseValueOfBar,
|
|
68
|
+
getCateCoordinateOfBar,
|
|
69
|
+
getTooltipNameProp,
|
|
70
|
+
getValueByDataKey,
|
|
71
|
+
truncateByDomain,
|
|
72
|
+
} from "../util/ChartUtils";
|
|
73
|
+
import type { StackSeries } from "../util/stacks/stackTypes";
|
|
74
|
+
import { interpolate, isNan, isNotNil, mathSign } from "../util/DataUtils";
|
|
75
|
+
import {
|
|
76
|
+
BarRectangle,
|
|
77
|
+
defaultBarShape,
|
|
78
|
+
MinPointSize,
|
|
79
|
+
minPointSizeCallback,
|
|
80
|
+
type BarRectangleProps,
|
|
81
|
+
} from "../util/BarUtils";
|
|
82
|
+
import { ActiveShape, ChartOffsetInternal } from "../util/types";
|
|
83
|
+
import type { RectRadius } from "../shape/Rectangle";
|
|
84
|
+
import { DefaultZIndexes } from "../zIndex/DefaultZIndexes";
|
|
85
|
+
import { getZIndexFromUnknown } from "../zIndex/getZIndexFromUnknown";
|
|
86
|
+
import { ZIndexLayer, type ZIndexable } from "../zIndex/ZIndexLayer";
|
|
87
|
+
import { svgPropertiesAndEventsFromUnknown } from "../util/svgPropertiesAndEvents";
|
|
88
|
+
import { svgPropertiesNoEventsFromUnknown } from "../util/svgPropertiesNoEvents";
|
|
89
|
+
import {
|
|
90
|
+
selectActiveTooltipDataKey,
|
|
91
|
+
selectActiveTooltipIndex,
|
|
92
|
+
} from "../state/selectors/tooltipSelectors";
|
|
93
|
+
import { BaseAxisWithScale } from "../state/selectors/axisSelectors";
|
|
94
|
+
import { StackId } from "../util/ChartUtils";
|
|
95
|
+
import { BarStackClipLayer, useStackId } from "./BarStack";
|
|
96
|
+
import { unregisterOnCleanup } from "../state/unregisterOnCleanup";
|
|
97
|
+
|
|
98
|
+
const defaultMinPointSize = 0;
|
|
99
|
+
|
|
100
|
+
type BarRectangleType = {
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
width: number;
|
|
104
|
+
height: number;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
function spreadableDataEntry(entry: unknown): Record<string, unknown> {
|
|
108
|
+
if (entry != null && typeof entry === "object" && !Array.isArray(entry)) {
|
|
109
|
+
return { ...entry };
|
|
110
|
+
}
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface BarRectangleItem {
|
|
115
|
+
x: number;
|
|
116
|
+
y: number;
|
|
117
|
+
width: number;
|
|
118
|
+
height: number;
|
|
119
|
+
/** Full-span background rectangle geometry (plot area along the value axis). */
|
|
120
|
+
background?: BarRectangleType;
|
|
121
|
+
/** The bar's value (data-derived; recharts types it `number | [number, number]`). */
|
|
122
|
+
value: unknown;
|
|
123
|
+
payload?: unknown;
|
|
124
|
+
tooltipPosition: Coordinate;
|
|
125
|
+
parentViewBox: CartesianViewBoxRequired;
|
|
126
|
+
stackedBarStart: number | undefined;
|
|
127
|
+
/** Stable pre-filter index within the displayed data slice. */
|
|
128
|
+
originalDataIndex: number;
|
|
129
|
+
/** Per-bar presentation overrides from a matching <Cell> child (if any). */
|
|
130
|
+
cell?: CellProps | undefined;
|
|
131
|
+
/** From <Cell> children or data row spread (recharts merges cell.props onto the item). */
|
|
132
|
+
fill?: string;
|
|
133
|
+
stroke?: string;
|
|
134
|
+
class?: string;
|
|
135
|
+
/** Extra fields from the data row (`...entry` spread in recharts). */
|
|
136
|
+
label?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type BarShapeProps = Omit<BarRectangleItem, "value" | "tooltipPosition"> &
|
|
140
|
+
// v3.9: a function-form custom shape also receives animationElapsedTime / isAnimating /
|
|
141
|
+
// isEntrance while the bar animates (recharts BarShapeProps = BarRectangleItem & ShapeAnimationProps & …).
|
|
142
|
+
ShapeAnimationProps & {
|
|
143
|
+
// value/tooltipPosition are optional here: a bar shape receives them, but the same
|
|
144
|
+
// shape option also renders backgrounds (which omit them — see BarRectangleProps).
|
|
145
|
+
value?: BarRectangleItem["value"];
|
|
146
|
+
tooltipPosition?: BarRectangleItem["tooltipPosition"];
|
|
147
|
+
isActive: boolean;
|
|
148
|
+
index: number;
|
|
149
|
+
/** Fired when the bar's CSS enter/exit transition ends (set during animation). */
|
|
150
|
+
onTransitionEnd?: () => void;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
type BarPointerEvent = MouseEvent | TouchEvent;
|
|
154
|
+
|
|
155
|
+
export type BarMouseEvent = (data: BarRectangleItem, index: number, event: BarPointerEvent) => void;
|
|
156
|
+
|
|
157
|
+
export function computeBarRectangles({
|
|
158
|
+
layout,
|
|
159
|
+
barSettings,
|
|
160
|
+
pos,
|
|
161
|
+
offset,
|
|
162
|
+
bandSize,
|
|
163
|
+
xAxis,
|
|
164
|
+
yAxis,
|
|
165
|
+
xAxisTicks,
|
|
166
|
+
yAxisTicks,
|
|
167
|
+
displayedData,
|
|
168
|
+
parentViewBox,
|
|
169
|
+
stackedData,
|
|
170
|
+
stackedDomain,
|
|
171
|
+
cells,
|
|
172
|
+
dataStartIndex = 0,
|
|
173
|
+
}: {
|
|
174
|
+
layout: CartesianLayout;
|
|
175
|
+
barSettings: BarSettings;
|
|
176
|
+
pos: { offset: number; size: number };
|
|
177
|
+
offset: ChartOffsetInternal;
|
|
178
|
+
bandSize: number;
|
|
179
|
+
xAxis: BaseAxisWithScale;
|
|
180
|
+
yAxis: BaseAxisWithScale;
|
|
181
|
+
xAxisTicks: TickItem[];
|
|
182
|
+
yAxisTicks: TickItem[];
|
|
183
|
+
displayedData: ChartData;
|
|
184
|
+
parentViewBox: CartesianViewBoxRequired;
|
|
185
|
+
/** Stacked series for this bar (undefined → unstacked [base, value]). */
|
|
186
|
+
stackedData?: StackSeries | undefined;
|
|
187
|
+
stackedDomain?: ReadonlyArray<number> | null;
|
|
188
|
+
/** Per-bar <Cell> presentation props, indexed by displayed-data position. */
|
|
189
|
+
cells?: ReadonlyArray<CellProps> | undefined;
|
|
190
|
+
dataStartIndex?: number;
|
|
191
|
+
}): ReadonlyArray<BarRectangleItem> | undefined {
|
|
192
|
+
const { dataKey, minPointSize: minPointSizeProp, hasCustomShape } = barSettings;
|
|
193
|
+
const numericAxis = layout === "horizontal" ? yAxis : xAxis;
|
|
194
|
+
const baseValue = getBaseValueOfBar({ numericAxis });
|
|
195
|
+
const stackedBarStart = numericAxis.scale.map(baseValue);
|
|
196
|
+
const getMinPointSize = minPointSizeCallback(minPointSizeProp, defaultMinPointSize);
|
|
197
|
+
|
|
198
|
+
return displayedData
|
|
199
|
+
.map((entry, index): BarRectangleItem | null => {
|
|
200
|
+
// Stacked → [start, end] from the stacked data; unstacked → [base, value].
|
|
201
|
+
let value: [unknown, unknown];
|
|
202
|
+
if (stackedData) {
|
|
203
|
+
const untruncated = stackedData[index + dataStartIndex];
|
|
204
|
+
const truncated =
|
|
205
|
+
untruncated != null && stackedDomain != null
|
|
206
|
+
? truncateByDomain(untruncated, stackedDomain)
|
|
207
|
+
: untruncated;
|
|
208
|
+
value = Array.isArray(truncated) ? [truncated[0], truncated[1]] : [baseValue, undefined];
|
|
209
|
+
} else {
|
|
210
|
+
const resolvedValue = getValueByDataKey(entry, dataKey);
|
|
211
|
+
if (Array.isArray(resolvedValue)) {
|
|
212
|
+
value = [resolvedValue[0], resolvedValue[1]];
|
|
213
|
+
} else {
|
|
214
|
+
value = [baseValue, resolvedValue];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const minPointSize = getMinPointSize(value[1], index);
|
|
218
|
+
|
|
219
|
+
let x: number | null;
|
|
220
|
+
let y: number | null | undefined;
|
|
221
|
+
let width: number;
|
|
222
|
+
let height: number;
|
|
223
|
+
let background: BarRectangleType;
|
|
224
|
+
|
|
225
|
+
if (layout === "horizontal") {
|
|
226
|
+
const baseValueScale = yAxis.scale.map(value[0]);
|
|
227
|
+
const currentValueScale = yAxis.scale.map(value[1]);
|
|
228
|
+
if (baseValueScale == null || currentValueScale == null) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
x = getCateCoordinateOfBar({
|
|
232
|
+
axis: xAxis,
|
|
233
|
+
ticks: xAxisTicks,
|
|
234
|
+
bandSize,
|
|
235
|
+
offset: pos.offset,
|
|
236
|
+
entry,
|
|
237
|
+
index,
|
|
238
|
+
});
|
|
239
|
+
y = currentValueScale ?? baseValueScale ?? undefined;
|
|
240
|
+
width = pos.size;
|
|
241
|
+
const computedHeight = baseValueScale - currentValueScale;
|
|
242
|
+
height = isNan(computedHeight) ? 0 : computedHeight;
|
|
243
|
+
|
|
244
|
+
if (Math.abs(minPointSize) > 0 && Math.abs(height) < Math.abs(minPointSize)) {
|
|
245
|
+
const delta =
|
|
246
|
+
mathSign(height || minPointSize) * (Math.abs(minPointSize) - Math.abs(height));
|
|
247
|
+
y -= delta;
|
|
248
|
+
height += delta;
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
const baseValueScale = xAxis.scale.map(value[0]);
|
|
252
|
+
const currentValueScale = xAxis.scale.map(value[1]);
|
|
253
|
+
if (baseValueScale == null || currentValueScale == null) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
x = baseValueScale;
|
|
257
|
+
const yCoord = getCateCoordinateOfBar({
|
|
258
|
+
axis: yAxis,
|
|
259
|
+
ticks: yAxisTicks,
|
|
260
|
+
bandSize,
|
|
261
|
+
offset: pos.offset,
|
|
262
|
+
entry,
|
|
263
|
+
index,
|
|
264
|
+
});
|
|
265
|
+
if (yCoord == null) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
y = yCoord;
|
|
269
|
+
width = currentValueScale - baseValueScale;
|
|
270
|
+
height = pos.size;
|
|
271
|
+
|
|
272
|
+
if (Math.abs(minPointSize) > 0 && Math.abs(width) < Math.abs(minPointSize)) {
|
|
273
|
+
const delta =
|
|
274
|
+
mathSign(width || minPointSize) * (Math.abs(minPointSize) - Math.abs(width));
|
|
275
|
+
width += delta;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (
|
|
280
|
+
x == null ||
|
|
281
|
+
y == null ||
|
|
282
|
+
width == null ||
|
|
283
|
+
height == null ||
|
|
284
|
+
(!hasCustomShape && (width === 0 || height === 0))
|
|
285
|
+
) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (layout === "horizontal") {
|
|
290
|
+
background = { x, y: offset.top, width, height: offset.height };
|
|
291
|
+
} else {
|
|
292
|
+
background = { x: offset.left, y, width: offset.width, height };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const labelValue = getValueByDataKey(entry, "label");
|
|
296
|
+
const label = typeof labelValue === "string" ? labelValue : undefined;
|
|
297
|
+
const cell = cells?.[index];
|
|
298
|
+
const cellClass = typeof cell?.class === "string" ? cell.class : undefined;
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
...spreadableDataEntry(entry),
|
|
302
|
+
x,
|
|
303
|
+
y,
|
|
304
|
+
width,
|
|
305
|
+
height,
|
|
306
|
+
value: stackedData ? value : value[1],
|
|
307
|
+
payload: entry,
|
|
308
|
+
...(label != null ? { label } : {}),
|
|
309
|
+
...(cell?.fill != null ? { fill: cell.fill } : {}),
|
|
310
|
+
...(cell?.stroke != null ? { stroke: cell.stroke } : {}),
|
|
311
|
+
...(cellClass != null ? { class: cellClass } : {}),
|
|
312
|
+
background,
|
|
313
|
+
tooltipPosition: { x: x + width / 2, y: y + height / 2 },
|
|
314
|
+
parentViewBox,
|
|
315
|
+
stackedBarStart: stackedBarStart ?? undefined,
|
|
316
|
+
originalDataIndex: index,
|
|
317
|
+
...(cell != null ? { cell } : {}),
|
|
318
|
+
};
|
|
319
|
+
})
|
|
320
|
+
.filter(isNotNil);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Per-frame bar growth from the baseline (horizontal → height; vertical → width); t=1 → final. */
|
|
324
|
+
// Default per-frame interpolation for Bar rectangles (the `animationInterpolateFn`
|
|
325
|
+
// the new AnimatedItems engine drives). Mirrors recharts 3.9 `defaultBarAnimateItems`:
|
|
326
|
+
// matched rects tween between prev/next; added rects grow from `stackedBarStart`;
|
|
327
|
+
// removed rects shrink back to the baseline before disappearing at t=1.
|
|
328
|
+
const defaultBarAnimateItems: AnimationInterpolateFn<BarRectangleItem, CartesianLayout> = (
|
|
329
|
+
items,
|
|
330
|
+
t,
|
|
331
|
+
layout,
|
|
332
|
+
) => {
|
|
333
|
+
if (items == null) return [];
|
|
334
|
+
if (t === 1) {
|
|
335
|
+
return items.flatMap((item) => (item.status === "removed" ? [] : [item.next]));
|
|
336
|
+
}
|
|
337
|
+
return items.flatMap((item): BarRectangleItem[] => {
|
|
338
|
+
if (item.status === "removed") {
|
|
339
|
+
if (layout === "horizontal") {
|
|
340
|
+
return [
|
|
341
|
+
{
|
|
342
|
+
...item.prev,
|
|
343
|
+
height: interpolate(item.prev.height, 0, t),
|
|
344
|
+
y: interpolate(item.prev.y, item.prev.y + item.prev.height, t),
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
return [{ ...item.prev, width: interpolate(item.prev.width, 0, t) }];
|
|
349
|
+
}
|
|
350
|
+
if (item.status === "matched") {
|
|
351
|
+
return [
|
|
352
|
+
{
|
|
353
|
+
...item.next,
|
|
354
|
+
x: interpolate(item.prev.x, item.next.x, t),
|
|
355
|
+
y: interpolate(item.prev.y, item.next.y, t),
|
|
356
|
+
width: interpolate(item.prev.width, item.next.width, t),
|
|
357
|
+
height: interpolate(item.prev.height, item.next.height, t),
|
|
358
|
+
},
|
|
359
|
+
];
|
|
360
|
+
}
|
|
361
|
+
// added
|
|
362
|
+
const { next } = item;
|
|
363
|
+
if (layout === "horizontal") {
|
|
364
|
+
return [
|
|
365
|
+
{
|
|
366
|
+
...next,
|
|
367
|
+
height: interpolate(0, next.height, t),
|
|
368
|
+
y: interpolate(next.stackedBarStart, next.y, t),
|
|
369
|
+
},
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
return [
|
|
373
|
+
{
|
|
374
|
+
...next,
|
|
375
|
+
width: interpolate(0, next.width, t),
|
|
376
|
+
x: interpolate(next.stackedBarStart, next.x, t),
|
|
377
|
+
},
|
|
378
|
+
];
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
function BarBackground(props: {
|
|
383
|
+
background?: ActiveShape<BarShapeProps, SVGPathElement> | undefined;
|
|
384
|
+
data: ReadonlyArray<BarRectangleItem>;
|
|
385
|
+
dataKey: DataKey<unknown> | undefined;
|
|
386
|
+
graphicalItemId: string;
|
|
387
|
+
onClick?: BarMouseEvent;
|
|
388
|
+
onMouseEnter?: BarMouseEvent;
|
|
389
|
+
onMouseLeave?: BarMouseEvent;
|
|
390
|
+
onMouseMove?: BarMouseEvent;
|
|
391
|
+
onMouseDown?: BarMouseEvent;
|
|
392
|
+
onMouseUp?: BarMouseEvent;
|
|
393
|
+
onMouseOver?: BarMouseEvent;
|
|
394
|
+
onMouseOut?: BarMouseEvent;
|
|
395
|
+
onTouchMove?: BarMouseEvent;
|
|
396
|
+
onTouchEnd?: BarMouseEvent;
|
|
397
|
+
}): JSX.Element {
|
|
398
|
+
const activeIndex = useAppSelector(selectActiveTooltipIndex);
|
|
399
|
+
// Getter args: the hooks read handler/dataKey at event time (fresh, never stale).
|
|
400
|
+
const onMouseEnter = useMouseEnterItemDispatch(
|
|
401
|
+
() => props.onMouseEnter,
|
|
402
|
+
() => props.dataKey,
|
|
403
|
+
props.graphicalItemId,
|
|
404
|
+
);
|
|
405
|
+
const onMouseLeave = useMouseLeaveItemDispatch(() => props.onMouseLeave);
|
|
406
|
+
const onClick = useMouseClickItemDispatch(
|
|
407
|
+
() => props.onClick,
|
|
408
|
+
() => props.dataKey,
|
|
409
|
+
props.graphicalItemId,
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
// Per-background-rectangle BarRectangle props (DATA, not JSX). Recomputes on data /
|
|
413
|
+
// active-index change; the `<Show>`/`<For>` below render it. Returning JSX from a
|
|
414
|
+
// memo and feeding it into <ZIndexLayer> (a Portal) leaked ownerless effects on
|
|
415
|
+
// recompute — see the Bar main-layer note. The <Show> wraps <ZIndexLayer> so the
|
|
416
|
+
// Portal subtree stays stable and only the <For> rows update.
|
|
417
|
+
const backgroundRects = createMemo<ReadonlyArray<BarRectangleProps> | undefined>(() => {
|
|
418
|
+
const backgroundFromProps = props.background;
|
|
419
|
+
if (!backgroundFromProps) {
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
const active = activeIndex();
|
|
423
|
+
const dataKey = props.dataKey;
|
|
424
|
+
const backgroundProps = svgPropertiesNoEventsFromUnknown(backgroundFromProps);
|
|
425
|
+
const backgroundEventProps = svgPropertiesAndEventsFromUnknown({
|
|
426
|
+
onMouseOver: props.onMouseOver,
|
|
427
|
+
onMouseOut: props.onMouseOut,
|
|
428
|
+
onMouseMove: props.onMouseMove,
|
|
429
|
+
onMouseDown: props.onMouseDown,
|
|
430
|
+
onMouseUp: props.onMouseUp,
|
|
431
|
+
onTouchMove: props.onTouchMove,
|
|
432
|
+
onTouchEnd: props.onTouchEnd,
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
const rects = props.data.flatMap((entry, i): BarRectangleProps[] => {
|
|
436
|
+
const bg = entry.background;
|
|
437
|
+
if (bg == null) {
|
|
438
|
+
return [];
|
|
439
|
+
}
|
|
440
|
+
const { value: _value, background: _bg, tooltipPosition: _tp, ...rest } = entry;
|
|
441
|
+
return [
|
|
442
|
+
{
|
|
443
|
+
option: backgroundFromProps,
|
|
444
|
+
isActive: String(entry.originalDataIndex) === active,
|
|
445
|
+
...rest,
|
|
446
|
+
fill: "#eee",
|
|
447
|
+
...bg,
|
|
448
|
+
...(backgroundProps ?? {}),
|
|
449
|
+
...(backgroundEventProps ?? {}),
|
|
450
|
+
onMouseEnter: onMouseEnter(entry, entry.originalDataIndex),
|
|
451
|
+
onMouseLeave: onMouseLeave(entry, entry.originalDataIndex),
|
|
452
|
+
onClick: onClick(entry, entry.originalDataIndex),
|
|
453
|
+
dataKey,
|
|
454
|
+
index: i,
|
|
455
|
+
class: "recharts-bar-background-rectangle",
|
|
456
|
+
},
|
|
457
|
+
];
|
|
458
|
+
});
|
|
459
|
+
return rects.length > 0 ? rects : undefined;
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
return (
|
|
463
|
+
<Show when={backgroundRects()}>
|
|
464
|
+
{(rects) => (
|
|
465
|
+
<ZIndexLayer zIndex={getZIndexFromUnknown(props.background, DefaultZIndexes.barBackground)}>
|
|
466
|
+
<Layer>
|
|
467
|
+
<For each={rects()}>
|
|
468
|
+
{(barRectangleProps) => <BarRectangle {...barRectangleProps} />}
|
|
469
|
+
</For>
|
|
470
|
+
</Layer>
|
|
471
|
+
</ZIndexLayer>
|
|
472
|
+
)}
|
|
473
|
+
</Show>
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function barEntryShapeProps(
|
|
478
|
+
entry: BarRectangleItem,
|
|
479
|
+
displayIndex: number,
|
|
480
|
+
dataKey: DataKey<unknown> | undefined,
|
|
481
|
+
fill: string,
|
|
482
|
+
stroke: string | undefined,
|
|
483
|
+
cellClass: string | undefined,
|
|
484
|
+
radius: RectRadius | undefined,
|
|
485
|
+
// v3.9: forwarded so a function-form custom shape can react to the animation state.
|
|
486
|
+
animationState: ShapeAnimationProps,
|
|
487
|
+
): Omit<BarRectangleProps, "option" | "isActive"> {
|
|
488
|
+
const { background: _bg, value: _v, tooltipPosition: _tp, ...rest } = entry;
|
|
489
|
+
return {
|
|
490
|
+
...rest,
|
|
491
|
+
fill,
|
|
492
|
+
stroke,
|
|
493
|
+
radius,
|
|
494
|
+
dataKey,
|
|
495
|
+
index: displayIndex,
|
|
496
|
+
class: cellClass,
|
|
497
|
+
animationElapsedTime: animationState.animationElapsedTime,
|
|
498
|
+
isAnimating: animationState.isAnimating,
|
|
499
|
+
isEntrance: animationState.isEntrance,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function BarRectangleNeverActive(props: {
|
|
504
|
+
shape: ActiveShape<BarShapeProps, SVGPathElement>;
|
|
505
|
+
entry: BarRectangleItem;
|
|
506
|
+
displayIndex: number;
|
|
507
|
+
dataKey: DataKey<unknown> | undefined;
|
|
508
|
+
fill: string;
|
|
509
|
+
stroke?: string;
|
|
510
|
+
cellClass?: string;
|
|
511
|
+
radius?: RectRadius;
|
|
512
|
+
animationElapsedTime?: number;
|
|
513
|
+
isAnimating?: boolean;
|
|
514
|
+
isEntrance?: boolean;
|
|
515
|
+
onMouseMove?: (event: MouseEvent) => void;
|
|
516
|
+
onMouseDown?: (event: MouseEvent) => void;
|
|
517
|
+
onMouseUp?: (event: MouseEvent) => void;
|
|
518
|
+
}): JSX.Element {
|
|
519
|
+
return (
|
|
520
|
+
<BarRectangle
|
|
521
|
+
{...barEntryShapeProps(
|
|
522
|
+
props.entry,
|
|
523
|
+
props.displayIndex,
|
|
524
|
+
props.dataKey,
|
|
525
|
+
props.fill,
|
|
526
|
+
props.stroke,
|
|
527
|
+
props.cellClass,
|
|
528
|
+
props.radius,
|
|
529
|
+
{
|
|
530
|
+
animationElapsedTime: props.animationElapsedTime,
|
|
531
|
+
isAnimating: props.isAnimating,
|
|
532
|
+
isEntrance: props.isEntrance,
|
|
533
|
+
},
|
|
534
|
+
)}
|
|
535
|
+
option={props.shape}
|
|
536
|
+
isActive={false}
|
|
537
|
+
onMouseMove={props.onMouseMove}
|
|
538
|
+
onMouseDown={props.onMouseDown}
|
|
539
|
+
onMouseUp={props.onMouseUp}
|
|
540
|
+
/>
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function BarRectangleWithActiveState(props: {
|
|
545
|
+
shape: ActiveShape<BarShapeProps, SVGPathElement>;
|
|
546
|
+
activeBar: Exclude<BarProps["activeBar"], false | undefined>;
|
|
547
|
+
entry: BarRectangleItem;
|
|
548
|
+
displayIndex: number;
|
|
549
|
+
dataKey: DataKey<unknown> | undefined;
|
|
550
|
+
fill: string;
|
|
551
|
+
stroke?: string;
|
|
552
|
+
cellClass?: string;
|
|
553
|
+
radius?: RectRadius;
|
|
554
|
+
animationElapsedTime?: number;
|
|
555
|
+
isAnimating?: boolean;
|
|
556
|
+
isEntrance?: boolean;
|
|
557
|
+
isEntryActive: (entry: BarRectangleItem, dataKey: DataKey<unknown> | undefined) => boolean;
|
|
558
|
+
onMouseMove?: (event: MouseEvent) => void;
|
|
559
|
+
onMouseDown?: (event: MouseEvent) => void;
|
|
560
|
+
onMouseUp?: (event: MouseEvent) => void;
|
|
561
|
+
}): JSX.Element {
|
|
562
|
+
const isActive = (): boolean => props.isEntryActive(props.entry, props.dataKey);
|
|
563
|
+
|
|
564
|
+
const [stayInLayer, setStayInLayer] = createSignal(false);
|
|
565
|
+
const [hasMountedActive, setHasMountedActive] = createSignal(false);
|
|
566
|
+
|
|
567
|
+
createEffect(
|
|
568
|
+
() => isActive(),
|
|
569
|
+
(active) => {
|
|
570
|
+
let rafId: number | undefined;
|
|
571
|
+
if (active) {
|
|
572
|
+
setStayInLayer(true);
|
|
573
|
+
rafId = requestAnimationFrame(() => {
|
|
574
|
+
setHasMountedActive(true);
|
|
575
|
+
});
|
|
576
|
+
} else {
|
|
577
|
+
setHasMountedActive(false);
|
|
578
|
+
}
|
|
579
|
+
return () => {
|
|
580
|
+
if (rafId != null) {
|
|
581
|
+
cancelAnimationFrame(rafId);
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
},
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
const isVisuallyActive = (): boolean => isActive() && hasMountedActive();
|
|
588
|
+
const shouldRenderInLayer = (): boolean => isActive() || stayInLayer();
|
|
589
|
+
|
|
590
|
+
const handleTransitionEnd = (): void => {
|
|
591
|
+
if (!isActive()) {
|
|
592
|
+
setStayInLayer(false);
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const renderRectangle = (): JSX.Element => {
|
|
597
|
+
const active = isActive();
|
|
598
|
+
let option: ActiveShape<BarShapeProps, SVGPathElement>;
|
|
599
|
+
if (active) {
|
|
600
|
+
option = props.activeBar === true ? props.shape : props.activeBar;
|
|
601
|
+
} else {
|
|
602
|
+
option = props.shape;
|
|
603
|
+
}
|
|
604
|
+
return (
|
|
605
|
+
<BarRectangle
|
|
606
|
+
{...barEntryShapeProps(
|
|
607
|
+
props.entry,
|
|
608
|
+
props.displayIndex,
|
|
609
|
+
props.dataKey,
|
|
610
|
+
props.fill,
|
|
611
|
+
props.stroke,
|
|
612
|
+
props.cellClass,
|
|
613
|
+
props.radius,
|
|
614
|
+
{
|
|
615
|
+
animationElapsedTime: props.animationElapsedTime,
|
|
616
|
+
isAnimating: props.isAnimating,
|
|
617
|
+
isEntrance: props.isEntrance,
|
|
618
|
+
},
|
|
619
|
+
)}
|
|
620
|
+
option={option}
|
|
621
|
+
isActive={isVisuallyActive()}
|
|
622
|
+
onTransitionEnd={handleTransitionEnd}
|
|
623
|
+
onMouseMove={props.onMouseMove}
|
|
624
|
+
onMouseDown={props.onMouseDown}
|
|
625
|
+
onMouseUp={props.onMouseUp}
|
|
626
|
+
/>
|
|
627
|
+
);
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
return (
|
|
631
|
+
<>
|
|
632
|
+
<Show when={shouldRenderInLayer()}>
|
|
633
|
+
<ZIndexLayer zIndex={DefaultZIndexes.activeBar}>
|
|
634
|
+
<BarStackClipLayer index={props.entry.originalDataIndex}>
|
|
635
|
+
{renderRectangle()}
|
|
636
|
+
</BarStackClipLayer>
|
|
637
|
+
</ZIndexLayer>
|
|
638
|
+
</Show>
|
|
639
|
+
<Show when={!shouldRenderInLayer()}>{renderRectangle()}</Show>
|
|
640
|
+
</>
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function BarRectangleLayer(props: {
|
|
645
|
+
entry: BarRectangleItem;
|
|
646
|
+
displayIndex: number;
|
|
647
|
+
dataKey: DataKey<unknown> | undefined;
|
|
648
|
+
shape: ActiveShape<BarShapeProps, SVGPathElement>;
|
|
649
|
+
activeBar: BarProps["activeBar"];
|
|
650
|
+
fill: string;
|
|
651
|
+
stroke?: string;
|
|
652
|
+
cellClass?: string;
|
|
653
|
+
radius?: RectRadius;
|
|
654
|
+
animationElapsedTime?: number;
|
|
655
|
+
isAnimating?: boolean;
|
|
656
|
+
isEntrance?: boolean;
|
|
657
|
+
isEntryActive: (entry: BarRectangleItem, dataKey: DataKey<unknown> | undefined) => boolean;
|
|
658
|
+
onMouseEnter: (event: MouseEvent) => void;
|
|
659
|
+
onMouseLeave: (event: MouseEvent) => void;
|
|
660
|
+
onClick: (event: MouseEvent) => void;
|
|
661
|
+
onMouseMove?: (event: MouseEvent) => void;
|
|
662
|
+
onMouseDown?: (event: MouseEvent) => void;
|
|
663
|
+
onMouseUp?: (event: MouseEvent) => void;
|
|
664
|
+
onMouseOver?: (event: MouseEvent) => void;
|
|
665
|
+
onMouseOut?: (event: MouseEvent) => void;
|
|
666
|
+
onTouchMove?: (event: TouchEvent) => void;
|
|
667
|
+
onTouchEnd?: (event: TouchEvent) => void;
|
|
668
|
+
}): JSX.Element {
|
|
669
|
+
return (
|
|
670
|
+
<BarStackClipLayer
|
|
671
|
+
index={props.entry.originalDataIndex}
|
|
672
|
+
class="recharts-bar-rectangle"
|
|
673
|
+
onMouseEnter={props.onMouseEnter}
|
|
674
|
+
onMouseLeave={props.onMouseLeave}
|
|
675
|
+
onClick={props.onClick}
|
|
676
|
+
onMouseOver={props.onMouseOver}
|
|
677
|
+
onMouseOut={props.onMouseOut}
|
|
678
|
+
onTouchMove={props.onTouchMove}
|
|
679
|
+
onTouchEnd={props.onTouchEnd}
|
|
680
|
+
>
|
|
681
|
+
{/* move/down/up ride the rectangle path itself (reference puts them on the
|
|
682
|
+
wrapping g via adaptEventsOfChild; the path is the g's only child, and
|
|
683
|
+
these events bubble, so this is behavior-equivalent). */}
|
|
684
|
+
{props.activeBar ? (
|
|
685
|
+
<BarRectangleWithActiveState
|
|
686
|
+
shape={props.shape}
|
|
687
|
+
activeBar={props.activeBar}
|
|
688
|
+
entry={props.entry}
|
|
689
|
+
displayIndex={props.displayIndex}
|
|
690
|
+
dataKey={props.dataKey}
|
|
691
|
+
fill={props.fill}
|
|
692
|
+
stroke={props.stroke}
|
|
693
|
+
cellClass={props.cellClass}
|
|
694
|
+
radius={props.radius}
|
|
695
|
+
animationElapsedTime={props.animationElapsedTime}
|
|
696
|
+
isAnimating={props.isAnimating}
|
|
697
|
+
isEntrance={props.isEntrance}
|
|
698
|
+
isEntryActive={props.isEntryActive}
|
|
699
|
+
onMouseMove={props.onMouseMove}
|
|
700
|
+
onMouseDown={props.onMouseDown}
|
|
701
|
+
onMouseUp={props.onMouseUp}
|
|
702
|
+
/>
|
|
703
|
+
) : (
|
|
704
|
+
<BarRectangleNeverActive
|
|
705
|
+
shape={props.shape}
|
|
706
|
+
entry={props.entry}
|
|
707
|
+
displayIndex={props.displayIndex}
|
|
708
|
+
dataKey={props.dataKey}
|
|
709
|
+
fill={props.fill}
|
|
710
|
+
stroke={props.stroke}
|
|
711
|
+
cellClass={props.cellClass}
|
|
712
|
+
radius={props.radius}
|
|
713
|
+
animationElapsedTime={props.animationElapsedTime}
|
|
714
|
+
isAnimating={props.isAnimating}
|
|
715
|
+
isEntrance={props.isEntrance}
|
|
716
|
+
onMouseMove={props.onMouseMove}
|
|
717
|
+
onMouseDown={props.onMouseDown}
|
|
718
|
+
onMouseUp={props.onMouseUp}
|
|
719
|
+
/>
|
|
720
|
+
)}
|
|
721
|
+
</BarStackClipLayer>
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
export interface BarProps extends ZIndexable {
|
|
726
|
+
xAxisId?: AxisId;
|
|
727
|
+
yAxisId?: AxisId;
|
|
728
|
+
dataKey?: DataKey<unknown>;
|
|
729
|
+
data?: ChartData;
|
|
730
|
+
/** Series name shown in tooltip/legend; falls back to a string dataKey. */
|
|
731
|
+
name?: string | number;
|
|
732
|
+
/** Unit appended to the value in the tooltip. */
|
|
733
|
+
unit?: string | number;
|
|
734
|
+
/** Tooltip entry type (recharts only supports `'none'`). */
|
|
735
|
+
tooltipType?: TooltipType;
|
|
736
|
+
/** Formats this Bar's tooltip value; takes precedence over the Tooltip-level `formatter`. */
|
|
737
|
+
formatter?: Formatter;
|
|
738
|
+
fill?: string;
|
|
739
|
+
fillOpacity?: number | string;
|
|
740
|
+
opacity?: number | string;
|
|
741
|
+
cursor?: string;
|
|
742
|
+
stroke?: string;
|
|
743
|
+
strokeWidth?: number;
|
|
744
|
+
hide?: boolean;
|
|
745
|
+
stackId?: StackId;
|
|
746
|
+
barSize?: number;
|
|
747
|
+
maxBarSize?: number;
|
|
748
|
+
minPointSize?: MinPointSize;
|
|
749
|
+
/** Corner radius of each bar (single number or [tl, tr, br, bl]). @defaultValue 0 */
|
|
750
|
+
radius?: RectRadius;
|
|
751
|
+
/** Per-bar labels (via LabelList). @defaultValue false */
|
|
752
|
+
label?: ImplicitLabelListType;
|
|
753
|
+
/**
|
|
754
|
+
* Renders a full-span background per bar (`true`, props object, or render function).
|
|
755
|
+
* @defaultValue false
|
|
756
|
+
*/
|
|
757
|
+
background?: ActiveShape<BarShapeProps, SVGPathElement> & { zIndex?: number };
|
|
758
|
+
/** Custom bar shape. @defaultValue Rectangle */
|
|
759
|
+
shape?: ActiveShape<BarShapeProps, SVGPathElement>;
|
|
760
|
+
/** Highlight the active bar (boolean uses default shape). @defaultValue false */
|
|
761
|
+
// `ActiveShape` already includes `boolean`, so no explicit `| boolean` needed.
|
|
762
|
+
activeBar?: ActiveShape<BarShapeProps, SVGPathElement>;
|
|
763
|
+
onAnimationStart?: () => void;
|
|
764
|
+
onAnimationEnd?: () => void;
|
|
765
|
+
isAnimationActive?: boolean | "auto";
|
|
766
|
+
animationBegin?: number;
|
|
767
|
+
animationDuration?: AnimationDuration;
|
|
768
|
+
animationEasing?: EasingInput;
|
|
769
|
+
/** Custom per-frame interpolation for the bar rectangles (v3.9). */
|
|
770
|
+
animationInterpolateFn?: AnimationInterpolateFn<BarRectangleItem, CartesianLayout>;
|
|
771
|
+
/** How prev/next rectangles are matched across data updates (v3.9). @defaultValue matchAppend */
|
|
772
|
+
animationMatchBy?: AnimationMatchByProp<BarRectangleItem>;
|
|
773
|
+
id?: string;
|
|
774
|
+
class?: string;
|
|
775
|
+
/** Legend icon type. @defaultValue 'rect' */
|
|
776
|
+
legendType?: LegendType;
|
|
777
|
+
onClick?: BarMouseEvent;
|
|
778
|
+
onMouseEnter?: BarMouseEvent;
|
|
779
|
+
onMouseLeave?: BarMouseEvent;
|
|
780
|
+
onMouseMove?: BarMouseEvent;
|
|
781
|
+
onMouseDown?: BarMouseEvent;
|
|
782
|
+
onMouseUp?: BarMouseEvent;
|
|
783
|
+
onMouseOver?: BarMouseEvent;
|
|
784
|
+
onMouseOut?: BarMouseEvent;
|
|
785
|
+
onTouchMove?: BarMouseEvent;
|
|
786
|
+
onTouchEnd?: BarMouseEvent;
|
|
787
|
+
/** <Cell> children supplying per-bar fill/stroke/class overrides. */
|
|
788
|
+
children?: JSX.Element;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
export const barDefaultProps = {
|
|
792
|
+
fill: "#3182bd",
|
|
793
|
+
shape: defaultBarShape,
|
|
794
|
+
background: false,
|
|
795
|
+
hide: false,
|
|
796
|
+
isAnimationActive: "auto",
|
|
797
|
+
animationBegin: 0,
|
|
798
|
+
animationDuration: 400,
|
|
799
|
+
animationEasing: "ease",
|
|
800
|
+
animationInterpolateFn: defaultBarAnimateItems,
|
|
801
|
+
animationMatchBy: matchAppend,
|
|
802
|
+
minPointSize: defaultMinPointSize,
|
|
803
|
+
legendType: "rect",
|
|
804
|
+
activeBar: false,
|
|
805
|
+
zIndex: DefaultZIndexes.bar,
|
|
806
|
+
xAxisId: 0,
|
|
807
|
+
yAxisId: 0,
|
|
808
|
+
} as const;
|
|
809
|
+
|
|
810
|
+
// Coerces an error value (read via dataKey) to the number / [low, high] shape an
|
|
811
|
+
// ErrorBar needs; anything else yields undefined (no whisker). Mirrors Line.
|
|
812
|
+
const coerceErrorVal = (value: unknown): number[] | number | undefined => {
|
|
813
|
+
if (typeof value === "number") {
|
|
814
|
+
return value;
|
|
815
|
+
}
|
|
816
|
+
if (value != null && Array.isArray(value)) {
|
|
817
|
+
const nums = value.filter((v): v is number => typeof v === "number");
|
|
818
|
+
return nums.length === value.length ? nums : undefined;
|
|
819
|
+
}
|
|
820
|
+
return undefined;
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
// Maps a BarRectangleItem (erased to `unknown` through the ErrorBar context) to the
|
|
824
|
+
// {x, y, value, errorVal} an ErrorBar draws from. Stacked bars carry a [start, end]
|
|
825
|
+
// value array → use the end value (recharts' errorBarDataPointFormatter).
|
|
826
|
+
const barErrorBarFormatter: ErrorBarDataPointFormatter = (entry, dataKey): ErrorBarDataItem => {
|
|
827
|
+
const x = getValueByDataKey(entry, "x");
|
|
828
|
+
const y = getValueByDataKey(entry, "y");
|
|
829
|
+
const rawValue = getValueByDataKey(entry, "value");
|
|
830
|
+
// Array.isArray narrows `unknown` to `any[]`; keep the element `unknown` (the
|
|
831
|
+
// `any → unknown` assignment is safe) so the typeof guard below stays sound.
|
|
832
|
+
const value: unknown = Array.isArray(rawValue) ? rawValue[rawValue.length - 1] : rawValue;
|
|
833
|
+
const payload = getValueByDataKey(entry, "payload");
|
|
834
|
+
return {
|
|
835
|
+
x: typeof x === "number" ? x : undefined,
|
|
836
|
+
y: typeof y === "number" ? y : undefined,
|
|
837
|
+
value: typeof value === "number" ? value : 0,
|
|
838
|
+
errorVal: coerceErrorVal(getValueByDataKey(payload, dataKey)),
|
|
839
|
+
};
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
export const Bar = (props: BarProps): JSX.Element => {
|
|
843
|
+
const store = useAppStore();
|
|
844
|
+
const merged = merge(barDefaultProps, props);
|
|
845
|
+
const isPanorama = useIsPanorama();
|
|
846
|
+
const id = useUniqueId("recharts-bar", props.id);
|
|
847
|
+
const stackId = useStackId(props.stackId);
|
|
848
|
+
// Custom shape render prop (function form), captured once.
|
|
849
|
+
const shape = merged.shape ?? defaultBarShape;
|
|
850
|
+
const activeBar = merged.activeBar;
|
|
851
|
+
const hasCustomShape = shape !== defaultBarShape;
|
|
852
|
+
|
|
853
|
+
let prev: BarSettings | null = null;
|
|
854
|
+
|
|
855
|
+
createEffect(
|
|
856
|
+
(): BarSettings => ({
|
|
857
|
+
id,
|
|
858
|
+
type: "bar",
|
|
859
|
+
isPanorama,
|
|
860
|
+
data: merged.data,
|
|
861
|
+
dataKey: merged.dataKey,
|
|
862
|
+
xAxisId: merged.xAxisId,
|
|
863
|
+
yAxisId: merged.yAxisId,
|
|
864
|
+
zAxisId: 0,
|
|
865
|
+
hide: merged.hide,
|
|
866
|
+
stackId,
|
|
867
|
+
barSize: merged.barSize,
|
|
868
|
+
maxBarSize: merged.maxBarSize,
|
|
869
|
+
minPointSize: merged.minPointSize,
|
|
870
|
+
hasCustomShape,
|
|
871
|
+
}),
|
|
872
|
+
(settings) => {
|
|
873
|
+
if (store == null) {
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
if (prev === null) {
|
|
877
|
+
store.actions.graphicalItems.addCartesianGraphicalItem(settings);
|
|
878
|
+
} else if (prev !== settings) {
|
|
879
|
+
store.actions.graphicalItems.replaceCartesianGraphicalItem({ prev, next: settings });
|
|
880
|
+
}
|
|
881
|
+
prev = settings;
|
|
882
|
+
},
|
|
883
|
+
);
|
|
884
|
+
|
|
885
|
+
unregisterOnCleanup(() => {
|
|
886
|
+
if (prev && store != null) {
|
|
887
|
+
store.actions.graphicalItems.removeCartesianGraphicalItem(prev);
|
|
888
|
+
prev = null;
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
// Per-bar <Cell> overrides (collected from children, in data order).
|
|
893
|
+
const cells = collectCells(() => props.children);
|
|
894
|
+
const rectangles = useAppSelector((state) => selectBarRectangles(state, id, isPanorama, cells()));
|
|
895
|
+
|
|
896
|
+
// Registers this bar's tooltip payload entry (an explicit `name` prop wins,
|
|
897
|
+
// else it falls back to a string dataKey).
|
|
898
|
+
const tooltipConfig = createMemo<TooltipPayloadConfiguration>(() => ({
|
|
899
|
+
dataDefinedOnItem: merged.data,
|
|
900
|
+
getPosition: noop,
|
|
901
|
+
settings: {
|
|
902
|
+
stroke: merged.stroke,
|
|
903
|
+
strokeWidth: merged.strokeWidth,
|
|
904
|
+
// recharts' defaultBarProps has NO `fill` — the #3182bd default is applied
|
|
905
|
+
// only at render time, so the tooltip entry carries the RAW prop fill
|
|
906
|
+
// (undefined when unset). Use props.fill, not merged.fill, for parity.
|
|
907
|
+
fill: props.fill,
|
|
908
|
+
dataKey: merged.dataKey,
|
|
909
|
+
nameKey: undefined,
|
|
910
|
+
name: getTooltipNameProp(merged.name, merged.dataKey),
|
|
911
|
+
hide: merged.hide,
|
|
912
|
+
type: merged.tooltipType,
|
|
913
|
+
color: props.fill,
|
|
914
|
+
unit: merged.unit,
|
|
915
|
+
formatter: merged.formatter,
|
|
916
|
+
graphicalItemId: id,
|
|
917
|
+
},
|
|
918
|
+
}));
|
|
919
|
+
|
|
920
|
+
// Item-type tooltip dispatch: hovering/clicking a single rectangle activates the
|
|
921
|
+
// tooltip for this bar (the `item` eventType path — `<Tooltip shared={false}>`).
|
|
922
|
+
// Getter args: the hooks read handler/dataKey at event time (fresh, never stale).
|
|
923
|
+
const onItemEnter = useMouseEnterItemDispatch(
|
|
924
|
+
() => props.onMouseEnter,
|
|
925
|
+
() => merged.dataKey,
|
|
926
|
+
id,
|
|
927
|
+
);
|
|
928
|
+
const onItemLeave = useMouseLeaveItemDispatch(() => props.onMouseLeave);
|
|
929
|
+
const onItemClick = useMouseClickItemDispatch(
|
|
930
|
+
() => props.onClick,
|
|
931
|
+
() => merged.dataKey,
|
|
932
|
+
id,
|
|
933
|
+
);
|
|
934
|
+
// Capture optional handlers once (not `props.*` reads inside <For>/<Layer>).
|
|
935
|
+
const onMouseOverHandler = props.onMouseOver;
|
|
936
|
+
const onMouseOutHandler = props.onMouseOut;
|
|
937
|
+
const onMouseMoveHandler = props.onMouseMove;
|
|
938
|
+
const onMouseDownHandler = props.onMouseDown;
|
|
939
|
+
const onMouseUpHandler = props.onMouseUp;
|
|
940
|
+
const onTouchMoveHandler = props.onTouchMove;
|
|
941
|
+
const onTouchEndHandler = props.onTouchEnd;
|
|
942
|
+
|
|
943
|
+
// Legend payload entry for this bar.
|
|
944
|
+
const legendPayload = createMemo<ReadonlyArray<LegendPayload>>(() => [
|
|
945
|
+
{
|
|
946
|
+
inactive: merged.hide,
|
|
947
|
+
dataKey: merged.dataKey,
|
|
948
|
+
type: merged.legendType,
|
|
949
|
+
// recharts' defaultBarProps has NO `fill` — the #3182bd default is applied
|
|
950
|
+
// only at render time, so the legend color is the RAW prop fill (undefined
|
|
951
|
+
// when unset → Bar legend has no default color).
|
|
952
|
+
color: props.fill,
|
|
953
|
+
value: getTooltipNameProp(merged.name, merged.dataKey),
|
|
954
|
+
payload: props,
|
|
955
|
+
},
|
|
956
|
+
]);
|
|
957
|
+
|
|
958
|
+
const activeTooltipIndex = useAppSelector(selectActiveTooltipIndex);
|
|
959
|
+
const activeTooltipDataKey = useAppSelector(selectActiveTooltipDataKey);
|
|
960
|
+
const isEntryActive = (
|
|
961
|
+
entry: BarRectangleItem,
|
|
962
|
+
dataKey: DataKey<unknown> | undefined,
|
|
963
|
+
): boolean => {
|
|
964
|
+
const idx = activeTooltipIndex();
|
|
965
|
+
if (idx == null) {
|
|
966
|
+
return false;
|
|
967
|
+
}
|
|
968
|
+
const dk = activeTooltipDataKey();
|
|
969
|
+
return String(entry.originalDataIndex) === idx && (dk == null || dataKey === dk);
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
// One LabelList entry per rectangle (its trapezoid viewBox + value/payload),
|
|
973
|
+
// provided to LabelList via context.
|
|
974
|
+
const shouldRenderBars = createMemo(() => !merged.hide && rectangles());
|
|
975
|
+
const labelListEntries = createMemo<ReadonlyArray<CartesianLabelListEntry>>(() => {
|
|
976
|
+
const rects = rectangles();
|
|
977
|
+
if (!rects) {
|
|
978
|
+
return [];
|
|
979
|
+
}
|
|
980
|
+
return rects.map((r) => {
|
|
981
|
+
const viewBox: TrapezoidViewBox = {
|
|
982
|
+
x: r.x,
|
|
983
|
+
y: r.y,
|
|
984
|
+
upperWidth: r.width,
|
|
985
|
+
lowerWidth: r.width,
|
|
986
|
+
width: r.width,
|
|
987
|
+
height: r.height,
|
|
988
|
+
};
|
|
989
|
+
return {
|
|
990
|
+
...viewBox,
|
|
991
|
+
viewBox,
|
|
992
|
+
parentViewBox: r.parentViewBox,
|
|
993
|
+
value: r.value,
|
|
994
|
+
payload: r.payload,
|
|
995
|
+
fill: r.fill,
|
|
996
|
+
};
|
|
997
|
+
});
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
const layout = useCartesianChartLayout();
|
|
1001
|
+
// ErrorBar whiskers are centered on each bar: offset by half the bar's cross size
|
|
1002
|
+
// (recharts: vertical → height/2, else width/2). 0 when there are no rectangles.
|
|
1003
|
+
const errorBarOffset = (): number => {
|
|
1004
|
+
const r0 = rectangles()?.[0];
|
|
1005
|
+
if (r0 == null) {
|
|
1006
|
+
return 0;
|
|
1007
|
+
}
|
|
1008
|
+
return layout() === "vertical" ? r0.height / 2 : r0.width / 2;
|
|
1009
|
+
};
|
|
1010
|
+
const { needClip } = useNeedsClip(merged.xAxisId, merged.yAxisId);
|
|
1011
|
+
const barClipPath = createMemo(() => (needClip() ? `url(#clipPath-${id})` : undefined));
|
|
1012
|
+
// Holds the latest visible rectangles frame so a re-animation (data change)
|
|
1013
|
+
// tweens from where the bars currently are. Managed by AnimatedItems via
|
|
1014
|
+
// useAnimationStartSnapshot.
|
|
1015
|
+
const previousRectanglesRef: MutableRef<ReadonlyArray<BarRectangleItem> | null | undefined> = {
|
|
1016
|
+
current: null,
|
|
1017
|
+
};
|
|
1018
|
+
// Cartesian layout for the interpolation fn (Bar is only horizontal | vertical).
|
|
1019
|
+
const cartesianLayout = (): CartesianLayout =>
|
|
1020
|
+
layout() === "vertical" ? "vertical" : "horizontal";
|
|
1021
|
+
// Animation state, sourced the same way upstream does (useAnimationCallbacks):
|
|
1022
|
+
// `isAnimating` flips true on start / false on end (and forwards the user
|
|
1023
|
+
// onAnimationStart/onAnimationEnd callbacks). Labels are hidden while animating
|
|
1024
|
+
// (recharts: BarLabelListProvider showLabels={!isAnimating}); custom shapes also
|
|
1025
|
+
// receive `isAnimating` (combined with `animationElapsedTime < 1` below, matching
|
|
1026
|
+
// upstream's `isAnimating || animationElapsedTime < 1`).
|
|
1027
|
+
const { isAnimating, handleAnimationStart, handleAnimationEnd } = useAnimationCallbacks(
|
|
1028
|
+
() => props.onAnimationStart?.(),
|
|
1029
|
+
() => props.onAnimationEnd?.(),
|
|
1030
|
+
);
|
|
1031
|
+
const labelContextEntries = createMemo(() => (isAnimating() ? undefined : labelListEntries()));
|
|
1032
|
+
|
|
1033
|
+
// Gate: render only in a cartesian layout AND when there are rectangles to draw.
|
|
1034
|
+
// Mirrors <Line>/<Area>'s inline `<Show when={!hide && points()}>` template: the
|
|
1035
|
+
// animated subtree is created ONCE under this Show and its inner reactive reads
|
|
1036
|
+
// update in place.
|
|
1037
|
+
//
|
|
1038
|
+
// Two NO_OWNER_EFFECT leaks shaped this structure (the `<Show>` wraps `<ZIndexLayer>`,
|
|
1039
|
+
// NOT the other way around):
|
|
1040
|
+
// 1. The previous `barLayer = createMemo(() => <JSX>)` returned a JSX subtree from
|
|
1041
|
+
// a memo; on a data change the memo recomputed and the `{barLayer()}` insert
|
|
1042
|
+
// re-created the whole subtree during the flush queue, leaking ownerless
|
|
1043
|
+
// render-effects. A non-keyed `<Show>` keeps the subtree stable across data
|
|
1044
|
+
// changes (only inner reads update), so that leak is gone.
|
|
1045
|
+
// 2. Unlike <Line>/<Area>, Bar wraps its content in <ZIndexLayer>, which renders
|
|
1046
|
+
// its children through a <Portal> (bar zIndex is non-zero). A <Portal> whose
|
|
1047
|
+
// children are a reactive `<Show>` makes the Portal's internal `insert`
|
|
1048
|
+
// re-create an ownerless render-effect when the portal target settles (e.g. a
|
|
1049
|
+
// no-data chart with a sibling chart mounting). Keeping <ZIndexLayer> OUTSIDE
|
|
1050
|
+
// the Show would put a live `<Show>` into the Portal even with no rects; nesting
|
|
1051
|
+
// it INSIDE the Show means an empty Bar mounts no Portal at all (nothing to
|
|
1052
|
+
// leak), and a populated Bar mounts a stable subtree into the Portal.
|
|
1053
|
+
// (`[]` is truthy, matching the old memo which rendered an empty `<For>` for an
|
|
1054
|
+
// empty rects array.)
|
|
1055
|
+
const renderableRects = createMemo<ReadonlyArray<BarRectangleItem> | undefined>(() => {
|
|
1056
|
+
const chartLayout = layout();
|
|
1057
|
+
if (chartLayout !== "horizontal" && chartLayout !== "vertical") {
|
|
1058
|
+
return undefined;
|
|
1059
|
+
}
|
|
1060
|
+
return shouldRenderBars() || undefined;
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
return (
|
|
1064
|
+
<>
|
|
1065
|
+
<SetTooltipEntrySettings tooltipEntrySettings={tooltipConfig()} />
|
|
1066
|
+
<SetLegendPayload id={id} legendPayload={legendPayload()} />
|
|
1067
|
+
<Show when={renderableRects()}>
|
|
1068
|
+
{(rects) => (
|
|
1069
|
+
<ZIndexLayer zIndex={merged.zIndex}>
|
|
1070
|
+
<Layer id={id} class={merged.class ? `recharts-bar ${merged.class}` : "recharts-bar"}>
|
|
1071
|
+
<Show when={needClip()}>
|
|
1072
|
+
<defs>
|
|
1073
|
+
<GraphicalItemClipPath
|
|
1074
|
+
clipPathId={id}
|
|
1075
|
+
xAxisId={merged.xAxisId}
|
|
1076
|
+
yAxisId={merged.yAxisId}
|
|
1077
|
+
/>
|
|
1078
|
+
</defs>
|
|
1079
|
+
</Show>
|
|
1080
|
+
<Layer class="recharts-bar-rectangles" clipPath={barClipPath()}>
|
|
1081
|
+
<BarBackground
|
|
1082
|
+
background={merged.background}
|
|
1083
|
+
data={rects()}
|
|
1084
|
+
dataKey={merged.dataKey}
|
|
1085
|
+
graphicalItemId={id}
|
|
1086
|
+
onClick={props.onClick}
|
|
1087
|
+
onMouseEnter={props.onMouseEnter}
|
|
1088
|
+
onMouseLeave={props.onMouseLeave}
|
|
1089
|
+
onMouseMove={props.onMouseMove}
|
|
1090
|
+
onMouseDown={props.onMouseDown}
|
|
1091
|
+
onMouseUp={props.onMouseUp}
|
|
1092
|
+
onMouseOver={props.onMouseOver}
|
|
1093
|
+
onMouseOut={props.onMouseOut}
|
|
1094
|
+
onTouchMove={props.onTouchMove}
|
|
1095
|
+
onTouchEnd={props.onTouchEnd}
|
|
1096
|
+
/>
|
|
1097
|
+
<CartesianLabelListContextProvider value={labelContextEntries}>
|
|
1098
|
+
<AnimatedItems
|
|
1099
|
+
animationInput={rects()}
|
|
1100
|
+
animationIdPrefix="recharts-bar-"
|
|
1101
|
+
items={rects()}
|
|
1102
|
+
previousItemsRef={previousRectanglesRef}
|
|
1103
|
+
isAnimationActive={merged.isAnimationActive}
|
|
1104
|
+
animationBegin={merged.animationBegin}
|
|
1105
|
+
animationDuration={merged.animationDuration}
|
|
1106
|
+
animationEasing={merged.animationEasing}
|
|
1107
|
+
onAnimationStart={handleAnimationStart}
|
|
1108
|
+
onAnimationEnd={handleAnimationEnd}
|
|
1109
|
+
animationInterpolateFn={merged.animationInterpolateFn}
|
|
1110
|
+
animationMatchBy={merged.animationMatchBy}
|
|
1111
|
+
layout={cartesianLayout()}
|
|
1112
|
+
>
|
|
1113
|
+
{(frame, animationElapsedTime, isEntrance) => (
|
|
1114
|
+
<Layer>
|
|
1115
|
+
<For each={frame}>
|
|
1116
|
+
{(r, i) => (
|
|
1117
|
+
// Render every selector-output rectangle, matching recharts
|
|
1118
|
+
// (zero-dimension genuinely-empty bars are already dropped at
|
|
1119
|
+
// the selector level — selectBarRectangles). We must NOT also
|
|
1120
|
+
// filter on width/height here: mid-animation a growing bar is
|
|
1121
|
+
// momentarily collapsed (t≈0 → height/width 0) and recharts
|
|
1122
|
+
// keeps that element in the DOM, so the rectangles render while
|
|
1123
|
+
// the chart animates (e.g. a Brush window narrowing). Filtering
|
|
1124
|
+
// here suppressed all animated bars until the animation was
|
|
1125
|
+
// driven to a non-zero frame.
|
|
1126
|
+
<BarRectangleLayer
|
|
1127
|
+
entry={r}
|
|
1128
|
+
displayIndex={i()}
|
|
1129
|
+
dataKey={merged.dataKey}
|
|
1130
|
+
activeBar={activeBar}
|
|
1131
|
+
fill={r.fill ?? r.cell?.fill ?? merged.fill}
|
|
1132
|
+
stroke={r.stroke ?? r.cell?.stroke ?? merged.stroke}
|
|
1133
|
+
radius={merged.radius}
|
|
1134
|
+
shape={shape}
|
|
1135
|
+
animationElapsedTime={animationElapsedTime}
|
|
1136
|
+
// Mirror upstream's `isAnimating || animationElapsedTime < 1`.
|
|
1137
|
+
isAnimating={isAnimating() || animationElapsedTime < 1}
|
|
1138
|
+
isEntrance={isEntrance}
|
|
1139
|
+
isEntryActive={isEntryActive}
|
|
1140
|
+
cellClass={typeof r.class === "string" ? r.class : undefined}
|
|
1141
|
+
onMouseEnter={onItemEnter(r, r.originalDataIndex)}
|
|
1142
|
+
onMouseLeave={onItemLeave(r, r.originalDataIndex)}
|
|
1143
|
+
onClick={onItemClick(r, r.originalDataIndex)}
|
|
1144
|
+
onMouseOver={
|
|
1145
|
+
onMouseOverHandler != null
|
|
1146
|
+
? (event) => onMouseOverHandler(r, r.originalDataIndex, event)
|
|
1147
|
+
: undefined
|
|
1148
|
+
}
|
|
1149
|
+
onMouseOut={
|
|
1150
|
+
onMouseOutHandler != null
|
|
1151
|
+
? (event) => onMouseOutHandler(r, r.originalDataIndex, event)
|
|
1152
|
+
: undefined
|
|
1153
|
+
}
|
|
1154
|
+
onMouseMove={
|
|
1155
|
+
onMouseMoveHandler != null
|
|
1156
|
+
? (event) => onMouseMoveHandler(r, r.originalDataIndex, event)
|
|
1157
|
+
: undefined
|
|
1158
|
+
}
|
|
1159
|
+
onMouseDown={
|
|
1160
|
+
onMouseDownHandler != null
|
|
1161
|
+
? (event) => onMouseDownHandler(r, r.originalDataIndex, event)
|
|
1162
|
+
: undefined
|
|
1163
|
+
}
|
|
1164
|
+
onMouseUp={
|
|
1165
|
+
onMouseUpHandler != null
|
|
1166
|
+
? (event) => onMouseUpHandler(r, r.originalDataIndex, event)
|
|
1167
|
+
: undefined
|
|
1168
|
+
}
|
|
1169
|
+
onTouchMove={
|
|
1170
|
+
onTouchMoveHandler != null
|
|
1171
|
+
? (event) => onTouchMoveHandler(r, i(), event)
|
|
1172
|
+
: undefined
|
|
1173
|
+
}
|
|
1174
|
+
onTouchEnd={
|
|
1175
|
+
onTouchEndHandler != null
|
|
1176
|
+
? (event) => onTouchEndHandler(r, i(), event)
|
|
1177
|
+
: undefined
|
|
1178
|
+
}
|
|
1179
|
+
/>
|
|
1180
|
+
)}
|
|
1181
|
+
</For>
|
|
1182
|
+
</Layer>
|
|
1183
|
+
)}
|
|
1184
|
+
</AnimatedItems>
|
|
1185
|
+
<LabelListFromLabelProp label={merged.label} />
|
|
1186
|
+
</CartesianLabelListContextProvider>
|
|
1187
|
+
</Layer>
|
|
1188
|
+
</Layer>
|
|
1189
|
+
</ZIndexLayer>
|
|
1190
|
+
)}
|
|
1191
|
+
</Show>
|
|
1192
|
+
{/* Children (e.g. <ErrorBar>, <LabelList>) mount ONCE here at the stable
|
|
1193
|
+
top-level return — NOT inside the rectangles-dependent `barLayer` memo,
|
|
1194
|
+
which would re-mount them on every rect recompute (ErrorBar would then
|
|
1195
|
+
churn add/removeErrorBar → re-extend the domain → recompute → loop).
|
|
1196
|
+
recharts wraps the bar body in RegisterGraphicalItemId + SetErrorBarContext;
|
|
1197
|
+
we provide them (plus the label-list context) here so children register and
|
|
1198
|
+
draw against the live rectangles while staying mounted. */}
|
|
1199
|
+
<RegisterGraphicalItemId type="bar" id={id}>
|
|
1200
|
+
{() => (
|
|
1201
|
+
<SetErrorBarContext
|
|
1202
|
+
xAxisId={merged.xAxisId}
|
|
1203
|
+
yAxisId={merged.yAxisId}
|
|
1204
|
+
data={rectangles() ?? []}
|
|
1205
|
+
dataPointFormatter={barErrorBarFormatter}
|
|
1206
|
+
errorBarOffset={errorBarOffset()}
|
|
1207
|
+
>
|
|
1208
|
+
<CartesianLabelListContextProvider value={labelContextEntries}>
|
|
1209
|
+
{props.children}
|
|
1210
|
+
</CartesianLabelListContextProvider>
|
|
1211
|
+
</SetErrorBarContext>
|
|
1212
|
+
)}
|
|
1213
|
+
</RegisterGraphicalItemId>
|
|
1214
|
+
</>
|
|
1215
|
+
);
|
|
1216
|
+
};
|