@solidports/recharts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/NOTICE +19 -0
- package/README.md +102 -0
- package/dist/dev.js +28564 -0
- package/dist/index.d.ts +7859 -0
- package/dist/index.js +28546 -0
- package/package.json +98 -0
- package/src/animation/AnimatedItems.tsx +183 -0
- package/src/animation/AnimationController.ts +33 -0
- package/src/animation/AnimationControllerImpl.ts +36 -0
- package/src/animation/AnimationHandle.ts +307 -0
- package/src/animation/CSSTransitionAnimate.tsx +170 -0
- package/src/animation/JavascriptAnimate.tsx +119 -0
- package/src/animation/easing.ts +221 -0
- package/src/animation/matchBy.ts +164 -0
- package/src/animation/timeoutController.ts +70 -0
- package/src/animation/useAnimationController.tsx +34 -0
- package/src/animation/useAnimationStartSnapshot.ts +118 -0
- package/src/animation/util.ts +41 -0
- package/src/cartesian/Area.tsx +915 -0
- package/src/cartesian/AreaRevealShape.tsx +190 -0
- package/src/cartesian/Bar.tsx +1369 -0
- package/src/cartesian/BarStack.tsx +152 -0
- package/src/cartesian/Brush.tsx +951 -0
- package/src/cartesian/CartesianAxis.tsx +722 -0
- package/src/cartesian/CartesianGrid.tsx +711 -0
- package/src/cartesian/ErrorBar.tsx +361 -0
- package/src/cartesian/Funnel.tsx +803 -0
- package/src/cartesian/GraphicalItemClipPath.tsx +67 -0
- package/src/cartesian/Line.tsx +863 -0
- package/src/cartesian/LineDrawShape.tsx +89 -0
- package/src/cartesian/ReferenceArea.tsx +331 -0
- package/src/cartesian/ReferenceDot.tsx +304 -0
- package/src/cartesian/ReferenceLine.tsx +474 -0
- package/src/cartesian/Scatter.tsx +888 -0
- package/src/cartesian/XAxis.tsx +433 -0
- package/src/cartesian/YAxis.tsx +443 -0
- package/src/cartesian/ZAxis.tsx +155 -0
- package/src/cartesian/cartesianPositionToCSSTranslate.tsx +29 -0
- package/src/cartesian/cartesianViewBoxToTrapezoid.tsx +21 -0
- package/src/cartesian/getCartesianPosition.tsx +267 -0
- package/src/cartesian/getEquidistantTicks.ts +144 -0
- package/src/cartesian/getTicks.ts +225 -0
- package/src/cartesian/isOutsidePosition.ts +15 -0
- package/src/cartesian/useAnimatedLineLength.ts +54 -0
- package/src/chart/AreaChart.tsx +29 -0
- package/src/chart/BarChart.tsx +29 -0
- package/src/chart/CartesianChart.tsx +131 -0
- package/src/chart/CategoricalChart.tsx +94 -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 +50 -0
- package/src/chart/PolarChart.tsx +164 -0
- package/src/chart/RadarChart.tsx +70 -0
- package/src/chart/RadialBarChart.tsx +46 -0
- package/src/chart/RechartsWrapper.tsx +551 -0
- package/src/chart/Sankey.tsx +1534 -0
- package/src/chart/ScatterChart.tsx +29 -0
- package/src/chart/SunburstChart.tsx +504 -0
- package/src/chart/Treemap.tsx +1223 -0
- package/src/chart/createInitialRootProps.ts +24 -0
- package/src/chart/types.ts +53 -0
- package/src/component/ActivePoints.tsx +144 -0
- package/src/component/Cell.tsx +37 -0
- package/src/component/Cursor.tsx +185 -0
- package/src/component/Customized.tsx +50 -0
- package/src/component/DefaultLegendContent.tsx +348 -0
- package/src/component/DefaultTooltipContent.tsx +224 -0
- package/src/component/Dots.tsx +157 -0
- package/src/component/Label.tsx +636 -0
- package/src/component/LabelList.tsx +375 -0
- package/src/component/Legend.tsx +512 -0
- package/src/component/ResponsiveContainer.tsx +348 -0
- package/src/component/Text.tsx +541 -0
- package/src/component/Tooltip.tsx +470 -0
- package/src/component/TooltipBoundingBox.tsx +146 -0
- package/src/component/responsiveContainerUtils.ts +134 -0
- package/src/container/ClipPathProvider.tsx +51 -0
- package/src/container/Layer.tsx +38 -0
- package/src/container/RootSurface.tsx +120 -0
- package/src/container/Surface.tsx +61 -0
- package/src/context/CellsContext.tsx +54 -0
- package/src/context/ErrorBarContext.tsx +146 -0
- package/src/context/GraphicalItemChildrenScope.tsx +18 -0
- package/src/context/PanoramaContext.tsx +9 -0
- package/src/context/RegisterGraphicalItemId.tsx +30 -0
- package/src/context/accessibilityContext.tsx +6 -0
- package/src/context/brushUpdateContext.tsx +9 -0
- package/src/context/chartDataContext.tsx +97 -0
- package/src/context/chartLayoutContext.tsx +201 -0
- package/src/context/legendPayloadContext.tsx +20 -0
- package/src/context/legendPortalContext.tsx +12 -0
- package/src/context/tooltipContext.tsx +89 -0
- package/src/context/tooltipPortalContext.tsx +12 -0
- package/src/context/useTooltipAxis.ts +22 -0
- package/src/hooks.ts +476 -0
- package/src/index.ts +280 -0
- package/src/polar/Pie.tsx +1360 -0
- package/src/polar/PolarAngleAxis.tsx +616 -0
- package/src/polar/PolarGrid.tsx +312 -0
- package/src/polar/PolarRadiusAxis.tsx +547 -0
- package/src/polar/Radar.tsx +734 -0
- package/src/polar/RadialBar.tsx +917 -0
- package/src/polar/defaultPolarAngleAxisProps.tsx +27 -0
- package/src/polar/defaultPolarRadiusAxisProps.tsx +25 -0
- package/src/shape/Cross.tsx +89 -0
- package/src/shape/Curve.tsx +343 -0
- package/src/shape/Dot.tsx +70 -0
- package/src/shape/Polygon.tsx +195 -0
- package/src/shape/Rectangle.tsx +470 -0
- package/src/shape/Sector.tsx +347 -0
- package/src/shape/Symbols.tsx +139 -0
- package/src/shape/Trapezoid.tsx +280 -0
- package/src/state/RechartsStateContext.tsx +12 -0
- package/src/state/RechartsStateProvider.tsx +87 -0
- package/src/state/RechartsStoreContext.tsx +25 -0
- package/src/state/RechartsStoreProvider.tsx +35 -0
- package/src/state/ReportChartProps.tsx +40 -0
- package/src/state/ReportEventSettings.tsx +30 -0
- package/src/state/ReportMainChartProps.tsx +61 -0
- package/src/state/ReportPolarOptions.tsx +35 -0
- package/src/state/SetGraphicalItem.ts +79 -0
- package/src/state/SetLegendPayload.ts +134 -0
- package/src/state/SetTooltipEntrySettings.tsx +72 -0
- package/src/state/actions.ts +464 -0
- package/src/state/brushSlice.ts +13 -0
- package/src/state/cartesianAxisSlice.ts +141 -0
- package/src/state/chartDataSlice.ts +50 -0
- package/src/state/chartState.ts +297 -0
- package/src/state/errorBarSlice.ts +29 -0
- package/src/state/eventSettingsSlice.ts +8 -0
- package/src/state/events.ts +76 -0
- package/src/state/externalEventsMiddleware.ts +255 -0
- package/src/state/graphicalItemsSlice.ts +74 -0
- package/src/state/hooks/useChartSelectors.tsx +45 -0
- package/src/state/keyboardEventsMiddleware.ts +228 -0
- package/src/state/layoutSlice.ts +21 -0
- package/src/state/legendSlice.ts +57 -0
- package/src/state/mouseEventsMiddleware.ts +185 -0
- package/src/state/optionsSlice.ts +47 -0
- package/src/state/polarAxisSlice.ts +10 -0
- package/src/state/polarOptionsSlice.ts +12 -0
- package/src/state/rawData.ts +26 -0
- package/src/state/referenceElementsSlice.ts +40 -0
- package/src/state/renderedTicksSlice.ts +15 -0
- package/src/state/rootPropsSlice.ts +47 -0
- package/src/state/selectors/areaSelectors.ts +240 -0
- package/src/state/selectors/arrayEqualityCheck.ts +29 -0
- package/src/state/selectors/axisSelectors.ts +2157 -0
- package/src/state/selectors/barSelectors.ts +310 -0
- package/src/state/selectors/barStackSelectors.ts +77 -0
- package/src/state/selectors/brushSelectors.ts +33 -0
- package/src/state/selectors/chartSelector.ts +185 -0
- package/src/state/selectors/combiners/combineActiveLabel.ts +16 -0
- package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +95 -0
- package/src/state/selectors/combiners/combineAllBarPositions.ts +122 -0
- package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +16 -0
- package/src/state/selectors/combiners/combineBarPosition.ts +23 -0
- package/src/state/selectors/combiners/combineBarSizeList.ts +80 -0
- package/src/state/selectors/combiners/combineCheckedDomain.ts +48 -0
- package/src/state/selectors/combiners/combineConfiguredScale.ts +111 -0
- package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +45 -0
- package/src/state/selectors/combiners/combineDisplayedStackedData.ts +50 -0
- package/src/state/selectors/combiners/combineInverseScaleFunction.ts +16 -0
- package/src/state/selectors/combiners/combineRealScaleType.ts +44 -0
- package/src/state/selectors/combiners/combineStackedData.ts +27 -0
- package/src/state/selectors/combiners/combineTooltipInteractionState.ts +86 -0
- package/src/state/selectors/combiners/combineTooltipPayload.ts +205 -0
- package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +58 -0
- package/src/state/selectors/containerSelectors.ts +12 -0
- package/src/state/selectors/dataSelectors.ts +88 -0
- package/src/state/selectors/funnelSelectors.ts +75 -0
- package/src/state/selectors/graphicalItemSelectors.ts +30 -0
- package/src/state/selectors/legendSelectors.ts +29 -0
- package/src/state/selectors/lineSelectors.ts +134 -0
- package/src/state/selectors/numberDomainEqualityCheck.ts +14 -0
- package/src/state/selectors/pickAxisId.ts +5 -0
- package/src/state/selectors/pickAxisType.ts +3 -0
- package/src/state/selectors/pieSelectors.ts +97 -0
- package/src/state/selectors/polarAxisSelectors.ts +201 -0
- package/src/state/selectors/polarGridSelectors.ts +28 -0
- package/src/state/selectors/polarScaleSelectors.ts +133 -0
- package/src/state/selectors/polarSelectors.ts +219 -0
- package/src/state/selectors/radarSelectors.ts +191 -0
- package/src/state/selectors/radialBarSelectors.ts +435 -0
- package/src/state/selectors/rootPropsSelectors.ts +25 -0
- package/src/state/selectors/scatterSelectors.ts +96 -0
- package/src/state/selectors/selectActivePropsFromChartPointer.ts +26 -0
- package/src/state/selectors/selectAllAxes.ts +17 -0
- package/src/state/selectors/selectChartOffset.ts +16 -0
- package/src/state/selectors/selectChartOffsetInternal.ts +136 -0
- package/src/state/selectors/selectLegendArea.ts +20 -0
- package/src/state/selectors/selectPlotArea.ts +22 -0
- package/src/state/selectors/selectTooltipAxisId.ts +7 -0
- package/src/state/selectors/selectTooltipAxisType.ts +32 -0
- package/src/state/selectors/selectTooltipEventType.ts +48 -0
- package/src/state/selectors/selectTooltipPayloadSearcher.ts +6 -0
- package/src/state/selectors/selectTooltipSettings.ts +39 -0
- package/src/state/selectors/selectTooltipState.ts +8 -0
- package/src/state/selectors/selectors.ts +271 -0
- package/src/state/selectors/tooltipSelectors.ts +578 -0
- package/src/state/selectors/touchSelectors.ts +31 -0
- package/src/state/store.ts +29 -0
- package/src/state/storeIdentity.ts +9 -0
- package/src/state/teardownWrite.ts +10 -0
- package/src/state/tooltipInteraction.ts +23 -0
- package/src/state/tooltipSlice.ts +334 -0
- package/src/state/touchEventsMiddleware.ts +214 -0
- package/src/state/types/AnimationSettings.ts +20 -0
- package/src/state/types/AreaSettings.ts +14 -0
- package/src/state/types/BarSettings.ts +15 -0
- package/src/state/types/LineSettings.ts +9 -0
- package/src/state/types/PieSettings.ts +34 -0
- package/src/state/types/RadarSettings.ts +5 -0
- package/src/state/types/RadialBarSettings.ts +10 -0
- package/src/state/types/ScatterSettings.ts +12 -0
- package/src/state/types/StackedGraphicalItem.ts +34 -0
- package/src/state/useChartState.ts +17 -0
- package/src/state/zIndexSlice.ts +39 -0
- package/src/synchronisation/syncSelectors.ts +7 -0
- package/src/synchronisation/types.ts +44 -0
- package/src/synchronisation/useChartSynchronisation.tsx +404 -0
- package/src/theme/RechartsTheme.ts +16 -0
- package/src/theme/RechartsThemeContext.ts +19 -0
- package/src/theme/darkTheme.ts +13 -0
- package/src/theme/graphicalItemIdentity.ts +70 -0
- package/src/theme/legacyTheme.ts +17 -0
- package/src/theme/lightTheme.ts +13 -0
- package/src/types.ts +54 -0
- package/src/util/ActiveShapeUtils.tsx +162 -0
- package/src/util/BarUtils.tsx +62 -0
- package/src/util/BarePortal.tsx +50 -0
- package/src/util/CamelCaseSVGAttrs.ts +34 -0
- package/src/util/CartesianUtils.ts +48 -0
- package/src/util/ChartUtils.ts +802 -0
- package/src/util/Constants.ts +42 -0
- package/src/util/CssPrefixUtils.ts +20 -0
- package/src/util/DOMUtils.ts +129 -0
- package/src/util/DataUtils.ts +216 -0
- package/src/util/Events.ts +16 -0
- package/src/util/FunnelUtils.tsx +15 -0
- package/src/util/Global.ts +12 -0
- package/src/util/IfOverflow.ts +15 -0
- package/src/util/LRUCache.ts +41 -0
- package/src/util/LogUtils.ts +22 -0
- package/src/util/PolarUtils.ts +132 -0
- package/src/util/RadialBarUtils.tsx +24 -0
- package/src/util/ReactUtils.ts +95 -0
- package/src/util/ReduceCSSCalc.ts +187 -0
- package/src/util/ScatterUtils.tsx +52 -0
- package/src/util/ShapeElementProps.tsx +87 -0
- package/src/util/TickUtils.ts +60 -0
- package/src/util/XAxisUtils.ts +48 -0
- package/src/util/YAxisUtils.ts +48 -0
- package/src/util/axisPropsAreEqual.ts +48 -0
- package/src/util/createCartesianCharts.tsx +150 -0
- package/src/util/createEventProxy.ts +20 -0
- package/src/util/createPolarCharts.tsx +112 -0
- package/src/util/cursor/getCursorPoints.ts +46 -0
- package/src/util/cursor/getCursorRectangle.ts +28 -0
- package/src/util/cursor/getRadialCursorPoints.ts +32 -0
- package/src/util/excludeEventProps.ts +171 -0
- package/src/util/getActiveCoordinate.ts +213 -0
- package/src/util/getAxisTypeBasedOnLayout.ts +21 -0
- package/src/util/getClassNameFromUnknown.ts +6 -0
- package/src/util/getEveryNth.ts +27 -0
- package/src/util/getRadiusAndStrokeWidthFromDot.ts +35 -0
- package/src/util/getRelativeCoordinate.ts +80 -0
- package/src/util/getSliced.ts +13 -0
- package/src/util/hoverDedupe.ts +41 -0
- package/src/util/isDomainSpecifiedByUser.ts +219 -0
- package/src/util/isWellBehavedNumber.ts +7 -0
- package/src/util/pathTotalLength.ts +25 -0
- package/src/util/payload/getUniqPayload.ts +28 -0
- package/src/util/propsAreEqual.ts +121 -0
- package/src/util/resolveDefaultProps.ts +161 -0
- package/src/util/round.ts +32 -0
- package/src/util/scale/CartesianScaleHelper.ts +72 -0
- package/src/util/scale/CustomScaleDefinition.ts +81 -0
- package/src/util/scale/RechartsScale.ts +130 -0
- package/src/util/scale/createCategoricalInverse.ts +72 -0
- package/src/util/scale/getNiceTickValues.ts +311 -0
- package/src/util/scale/index.ts +2 -0
- package/src/util/scale/util/arithmetic.ts +54 -0
- package/src/util/solid-1-compat.ts +310 -0
- package/src/util/solidJsxCamelAugment.d.ts +84 -0
- package/src/util/stacks/getStackSeriesIdentifier.ts +21 -0
- package/src/util/stacks/stackTypes.ts +60 -0
- package/src/util/structurallyEqual.ts +31 -0
- package/src/util/svgPropertiesAndEvents.ts +53 -0
- package/src/util/svgPropertiesNoEvents.ts +571 -0
- package/src/util/tooltip/translate.ts +171 -0
- package/src/util/typedDataKey.ts +48 -0
- package/src/util/types.ts +1560 -0
- package/src/util/useAnimationId.ts +31 -0
- package/src/util/useElementOffset.ts +110 -0
- package/src/util/useId.ts +8 -0
- package/src/util/usePrefersReducedMotion.ts +48 -0
- package/src/util/useReportScale.ts +24 -0
- package/src/util/useUniqueId.ts +30 -0
- package/src/zIndex/DefaultZIndexes.ts +84 -0
- package/src/zIndex/ZIndexLayer.tsx +121 -0
- package/src/zIndex/ZIndexPortal.tsx +79 -0
- package/src/zIndex/getZIndexFromUnknown.ts +14 -0
- package/src/zIndex/zIndexSelectors.ts +48 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileOverview Polygon
|
|
3
|
+
*/
|
|
4
|
+
import type { JSX } from '@solidjs/web';
|
|
5
|
+
import { useShapeElementProps } from "../util/ShapeElementProps"
|
|
6
|
+
import type { WithoutRemoveFalse } from "../util/types"
|
|
7
|
+
import { Show } from 'solid-js';
|
|
8
|
+
import { clsx } from "clsx"
|
|
9
|
+
import type { Coordinate } from "../util/types"
|
|
10
|
+
import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
|
|
11
|
+
import { roundTemplateLiteral } from "../util/round"
|
|
12
|
+
|
|
13
|
+
const isValidatePoint = (point: Coordinate | undefined): point is Coordinate => {
|
|
14
|
+
return point != null && point.x === +point.x && point.y === +point.y
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const getParsedPoints = (points: ReadonlyArray<Coordinate> = []) => {
|
|
18
|
+
let segmentPoints: Coordinate[][] = [[]]
|
|
19
|
+
|
|
20
|
+
points.forEach((entry) => {
|
|
21
|
+
const lastLink = segmentPoints[segmentPoints.length - 1]
|
|
22
|
+
if (isValidatePoint(entry)) {
|
|
23
|
+
if (lastLink) {
|
|
24
|
+
lastLink.push(entry)
|
|
25
|
+
}
|
|
26
|
+
} else if (lastLink && lastLink.length > 0) {
|
|
27
|
+
segmentPoints.push([])
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const firstPoint = points[0]
|
|
32
|
+
const lastLink = segmentPoints[segmentPoints.length - 1]
|
|
33
|
+
if (isValidatePoint(firstPoint) && lastLink) {
|
|
34
|
+
lastLink.push(firstPoint)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const finalLink = segmentPoints[segmentPoints.length - 1]
|
|
38
|
+
if (finalLink && finalLink.length <= 0) {
|
|
39
|
+
segmentPoints = segmentPoints.slice(0, -1)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return segmentPoints
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const getSinglePolygonPath = (points: ReadonlyArray<Coordinate>, connectNulls?: boolean) => {
|
|
46
|
+
let segmentPoints = getParsedPoints(points)
|
|
47
|
+
|
|
48
|
+
if (connectNulls) {
|
|
49
|
+
segmentPoints = [
|
|
50
|
+
segmentPoints.reduce((res: Coordinate[], segPoints: Coordinate[]) => {
|
|
51
|
+
res.push(...segPoints)
|
|
52
|
+
return res
|
|
53
|
+
}, []),
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const polygonPath = segmentPoints
|
|
58
|
+
.map((segPoints) => {
|
|
59
|
+
return segPoints.reduce((path: string, point: Coordinate, index: number) => {
|
|
60
|
+
return roundTemplateLiteral`${path}${index === 0 ? "M" : "L"}${point.x},${point.y}`
|
|
61
|
+
}, "")
|
|
62
|
+
})
|
|
63
|
+
.join("")
|
|
64
|
+
|
|
65
|
+
return segmentPoints.length === 1 ? `${polygonPath}Z` : polygonPath
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const getRanglePath = (
|
|
69
|
+
points: ReadonlyArray<Coordinate>,
|
|
70
|
+
baseLinePoints: ReadonlyArray<Coordinate>,
|
|
71
|
+
connectNulls?: boolean,
|
|
72
|
+
) => {
|
|
73
|
+
const outerPath = getSinglePolygonPath(points, connectNulls)
|
|
74
|
+
|
|
75
|
+
return `${outerPath.slice(-1) === "Z" ? outerPath.slice(0, -1) : outerPath}L${getSinglePolygonPath(
|
|
76
|
+
Array.from(baseLinePoints).reverse(),
|
|
77
|
+
connectNulls,
|
|
78
|
+
).slice(1)}`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface PolygonProps {
|
|
82
|
+
class?: string
|
|
83
|
+
/**
|
|
84
|
+
* The coordinates of all the vertexes of the polygon, like an array of objects with x and y coordinates.
|
|
85
|
+
*/
|
|
86
|
+
points?: ReadonlyArray<Coordinate>
|
|
87
|
+
baseLinePoints?: ReadonlyArray<Coordinate>
|
|
88
|
+
connectNulls?: boolean
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The customized event handler of click on the polygon
|
|
92
|
+
*/
|
|
93
|
+
onClick?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
94
|
+
/**
|
|
95
|
+
* The customized event handler of mousedown on the polygon
|
|
96
|
+
*/
|
|
97
|
+
onMouseDown?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
98
|
+
/**
|
|
99
|
+
* The customized event handler of mouseup on the polygon
|
|
100
|
+
*/
|
|
101
|
+
onMouseUp?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
102
|
+
/**
|
|
103
|
+
* The customized event handler of mousemove on the polygon
|
|
104
|
+
*/
|
|
105
|
+
onMouseMove?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
106
|
+
/**
|
|
107
|
+
* The customized event handler of mouseover on the polygon
|
|
108
|
+
*/
|
|
109
|
+
onMouseOver?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
110
|
+
/**
|
|
111
|
+
* The customized event handler of mouseout on the polygon
|
|
112
|
+
*/
|
|
113
|
+
onMouseOut?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
114
|
+
/**
|
|
115
|
+
* The customized event handler of mouseenter on the polygon
|
|
116
|
+
*/
|
|
117
|
+
onMouseEnter?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
118
|
+
/**
|
|
119
|
+
* The customized event handler of mouseleave on the polygon
|
|
120
|
+
*/
|
|
121
|
+
onMouseLeave?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type Props = WithoutRemoveFalse<Omit<JSX.PathSVGAttributes<SVGPathElement>, "points" | keyof PolygonProps>> & PolygonProps
|
|
125
|
+
|
|
126
|
+
export function Polygon(ownProps: Props) {
|
|
127
|
+
/* Props injected for a shape passed as an element (see ShapeElementProps). */
|
|
128
|
+
const props = useShapeElementProps(ownProps)
|
|
129
|
+
const hasPoints = () => props.points && props.points.length > 0
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<Show when={hasPoints()}>
|
|
133
|
+
<Show
|
|
134
|
+
when={props.baseLinePoints && props.baseLinePoints.length > 0}
|
|
135
|
+
fallback={
|
|
136
|
+
<SinglePolygonPath
|
|
137
|
+
points={props.points}
|
|
138
|
+
connectNulls={props.connectNulls}
|
|
139
|
+
class={props.class}
|
|
140
|
+
{...svgPropertiesAndEvents(props)}
|
|
141
|
+
/>
|
|
142
|
+
}
|
|
143
|
+
>
|
|
144
|
+
<RangePolygon
|
|
145
|
+
points={props.points}
|
|
146
|
+
baseLinePoints={props.baseLinePoints}
|
|
147
|
+
connectNulls={props.connectNulls}
|
|
148
|
+
class={props.class}
|
|
149
|
+
{...svgPropertiesAndEvents(props)}
|
|
150
|
+
/>
|
|
151
|
+
</Show>
|
|
152
|
+
</Show>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function SinglePolygonPath(props: Props) {
|
|
157
|
+
const layerClass = () => clsx("recharts-polygon", props.class)
|
|
158
|
+
const singlePath = () => getSinglePolygonPath(props.points ?? [], props.connectNulls)
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<path
|
|
162
|
+
{...svgPropertiesAndEvents(props)}
|
|
163
|
+
fill={singlePath().slice(-1) === "Z" ? props.fill : "none"}
|
|
164
|
+
class={layerClass()}
|
|
165
|
+
d={singlePath()}
|
|
166
|
+
/>
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function RangePolygon(props: Props) {
|
|
171
|
+
const layerClass = () => clsx("recharts-polygon", props.class)
|
|
172
|
+
const hasStroke = () => props.stroke && props.stroke !== "none"
|
|
173
|
+
const rangePath = () =>
|
|
174
|
+
getRanglePath(props.points ?? [], props.baseLinePoints ?? [], props.connectNulls)
|
|
175
|
+
const singlePath = () => getSinglePolygonPath(props.points ?? [], props.connectNulls)
|
|
176
|
+
const baseLinePath = () => getSinglePolygonPath(props.baseLinePoints ?? [], props.connectNulls)
|
|
177
|
+
const filteredProps = () => svgPropertiesAndEvents(props)
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<g class={layerClass()}>
|
|
181
|
+
<path
|
|
182
|
+
{...filteredProps()}
|
|
183
|
+
fill={rangePath().slice(-1) === "Z" ? props.fill : "none"}
|
|
184
|
+
stroke="none"
|
|
185
|
+
d={rangePath()}
|
|
186
|
+
/>
|
|
187
|
+
<Show when={hasStroke()}>
|
|
188
|
+
<path {...filteredProps()} fill="none" d={singlePath()} />
|
|
189
|
+
</Show>
|
|
190
|
+
<Show when={hasStroke()}>
|
|
191
|
+
<path {...filteredProps()} fill="none" d={baseLinePath()} />
|
|
192
|
+
</Show>
|
|
193
|
+
</g>
|
|
194
|
+
)
|
|
195
|
+
}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
/**
|
|
3
|
+
* @fileOverview Rectangle
|
|
4
|
+
*/
|
|
5
|
+
import type { JSX } from '@solidjs/web';
|
|
6
|
+
import { useShapeElementProps } from "../util/ShapeElementProps"
|
|
7
|
+
import type { WithoutRemoveFalse } from "../util/types"
|
|
8
|
+
import { createMemo, createSignal, Show, untrack, createEffect } from 'solid-js';
|
|
9
|
+
import { clsx } from "clsx"
|
|
10
|
+
import type { AnimationDuration } from "../util/types"
|
|
11
|
+
import { JavascriptAnimate } from "../animation/JavascriptAnimate"
|
|
12
|
+
import type { EasingInput } from "../animation/easing"
|
|
13
|
+
import { interpolate } from "../util/DataUtils"
|
|
14
|
+
import { useAnimationId } from "../util/useAnimationId"
|
|
15
|
+
import { getTransitionVal } from "../animation/util"
|
|
16
|
+
import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
|
|
17
|
+
import { round, roundTemplateLiteral } from "../util/round"
|
|
18
|
+
|
|
19
|
+
import { mergeProps } from '../util/solid-1-compat';
|
|
20
|
+
/**
|
|
21
|
+
* @inline
|
|
22
|
+
*/
|
|
23
|
+
export type RectRadius = number | [number, number, number, number]
|
|
24
|
+
|
|
25
|
+
export const getRectanglePath = (
|
|
26
|
+
x: number,
|
|
27
|
+
y: number,
|
|
28
|
+
width: number,
|
|
29
|
+
height: number,
|
|
30
|
+
radius: RectRadius,
|
|
31
|
+
): string => {
|
|
32
|
+
const roundedWidth = round(width)
|
|
33
|
+
const roundedHeight = round(height)
|
|
34
|
+
const maxRadius = Math.min(Math.abs(roundedWidth) / 2, Math.abs(roundedHeight) / 2)
|
|
35
|
+
const ySign = roundedHeight >= 0 ? 1 : -1
|
|
36
|
+
const xSign = roundedWidth >= 0 ? 1 : -1
|
|
37
|
+
const clockWise =
|
|
38
|
+
(roundedHeight >= 0 && roundedWidth >= 0) || (roundedHeight < 0 && roundedWidth < 0) ? 1 : 0
|
|
39
|
+
let path
|
|
40
|
+
|
|
41
|
+
if (maxRadius > 0 && Array.isArray(radius)) {
|
|
42
|
+
const newRadius: RectRadius = [0, 0, 0, 0]
|
|
43
|
+
for (let i = 0, len = 4; i < len; i++) {
|
|
44
|
+
const r: number = radius[i] ?? 0
|
|
45
|
+
newRadius[i] = r > maxRadius ? maxRadius : r
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
path = roundTemplateLiteral`M${x},${y + ySign * newRadius[0]}`
|
|
49
|
+
|
|
50
|
+
if (newRadius[0] > 0) {
|
|
51
|
+
path += roundTemplateLiteral`A ${newRadius[0]},${newRadius[0]},0,0,${clockWise},${x + xSign * newRadius[0]},${y}`
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
path += roundTemplateLiteral`L ${x + width - xSign * newRadius[1]},${y}`
|
|
55
|
+
|
|
56
|
+
if (newRadius[1] > 0) {
|
|
57
|
+
path += roundTemplateLiteral`A ${newRadius[1]},${newRadius[1]},0,0,${clockWise},
|
|
58
|
+
${x + width},${y + ySign * newRadius[1]}`
|
|
59
|
+
}
|
|
60
|
+
path += roundTemplateLiteral`L ${x + width},${y + height - ySign * newRadius[2]}`
|
|
61
|
+
|
|
62
|
+
if (newRadius[2] > 0) {
|
|
63
|
+
path += roundTemplateLiteral`A ${newRadius[2]},${newRadius[2]},0,0,${clockWise},
|
|
64
|
+
${x + width - xSign * newRadius[2]},${y + height}`
|
|
65
|
+
}
|
|
66
|
+
path += roundTemplateLiteral`L ${x + xSign * newRadius[3]},${y + height}`
|
|
67
|
+
|
|
68
|
+
if (newRadius[3] > 0) {
|
|
69
|
+
path += roundTemplateLiteral`A ${newRadius[3]},${newRadius[3]},0,0,${clockWise},
|
|
70
|
+
${x},${y + height - ySign * newRadius[3]}`
|
|
71
|
+
}
|
|
72
|
+
path += "Z"
|
|
73
|
+
} else if (maxRadius > 0 && radius === +radius && radius > 0) {
|
|
74
|
+
const newRadius = Math.min(maxRadius, radius)
|
|
75
|
+
|
|
76
|
+
path = roundTemplateLiteral`M ${x},${y + ySign * newRadius}
|
|
77
|
+
A ${newRadius},${newRadius},0,0,${clockWise},${x + xSign * newRadius},${y}
|
|
78
|
+
L ${x + width - xSign * newRadius},${y}
|
|
79
|
+
A ${newRadius},${newRadius},0,0,${clockWise},${x + width},${y + ySign * newRadius}
|
|
80
|
+
L ${x + width},${y + height - ySign * newRadius}
|
|
81
|
+
A ${newRadius},${newRadius},0,0,${clockWise},${x + width - xSign * newRadius},${y + height}
|
|
82
|
+
L ${x + xSign * newRadius},${y + height}
|
|
83
|
+
A ${newRadius},${newRadius},0,0,${clockWise},${x},${y + height - ySign * newRadius} Z`
|
|
84
|
+
} else {
|
|
85
|
+
path = roundTemplateLiteral`M ${x},${y} h ${width} v ${height} h ${-width} Z`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return path
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface RectangleProps {
|
|
92
|
+
class?: string
|
|
93
|
+
/**
|
|
94
|
+
* The x-coordinate of top left point of the rectangle.
|
|
95
|
+
* @defaultValue 0
|
|
96
|
+
*/
|
|
97
|
+
x?: number
|
|
98
|
+
/**
|
|
99
|
+
* The y-coordinate of top left point of the rectangle.
|
|
100
|
+
* @defaultValue 0
|
|
101
|
+
*/
|
|
102
|
+
y?: number
|
|
103
|
+
/**
|
|
104
|
+
* Width of the rectangle in pixels.
|
|
105
|
+
* @defaultValue 0
|
|
106
|
+
*/
|
|
107
|
+
width?: number
|
|
108
|
+
/**
|
|
109
|
+
* Height of the rectangle in pixels.
|
|
110
|
+
* @defaultValue 0
|
|
111
|
+
*/
|
|
112
|
+
height?: number
|
|
113
|
+
/**
|
|
114
|
+
* The radius of corners.
|
|
115
|
+
*
|
|
116
|
+
* If you provide a single number, it applies to all four corners.
|
|
117
|
+
* If you provide an array of four numbers, they apply to top-left, top-right, bottom-right, bottom-left corners respectively.
|
|
118
|
+
*
|
|
119
|
+
* @see {@link https://recharts.github.io/en-US/guide/roundedBars/ Guide: Rounded bar corners}
|
|
120
|
+
*
|
|
121
|
+
* @defaultValue 0
|
|
122
|
+
*/
|
|
123
|
+
radius?: RectRadius
|
|
124
|
+
/**
|
|
125
|
+
* If set "auto", animation is disabled during SSR and when the user prefers reduced motion.
|
|
126
|
+
* @defaultValue false
|
|
127
|
+
*/
|
|
128
|
+
isAnimationActive?: boolean | "auto"
|
|
129
|
+
/**
|
|
130
|
+
* If set "auto", animation is disabled during SSR and when the user prefers reduced motion.
|
|
131
|
+
* @defaultValue false
|
|
132
|
+
*/
|
|
133
|
+
isUpdateAnimationActive?: boolean | "auto"
|
|
134
|
+
/**
|
|
135
|
+
* @defaultValue 0
|
|
136
|
+
*/
|
|
137
|
+
animationBegin?: number
|
|
138
|
+
/**
|
|
139
|
+
* @defaultValue 1500
|
|
140
|
+
*/
|
|
141
|
+
animationDuration?: AnimationDuration
|
|
142
|
+
/**
|
|
143
|
+
* @defaultValue ease
|
|
144
|
+
*/
|
|
145
|
+
animationEasing?: EasingInput
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The customized event handler of click on the rectangle
|
|
149
|
+
*/
|
|
150
|
+
onClick?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
151
|
+
/**
|
|
152
|
+
* The customized event handler of mousedown on the rectangle
|
|
153
|
+
*/
|
|
154
|
+
onMouseDown?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
155
|
+
/**
|
|
156
|
+
* The customized event handler of mouseup on the rectangle
|
|
157
|
+
*/
|
|
158
|
+
onMouseUp?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
159
|
+
/**
|
|
160
|
+
* The customized event handler of mousemove on the rectangle
|
|
161
|
+
*/
|
|
162
|
+
onMouseMove?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
163
|
+
/**
|
|
164
|
+
* The customized event handler of mouseover on the rectangle
|
|
165
|
+
*/
|
|
166
|
+
onMouseOver?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
167
|
+
/**
|
|
168
|
+
* The customized event handler of mouseout on the rectangle
|
|
169
|
+
*/
|
|
170
|
+
onMouseOut?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
171
|
+
/**
|
|
172
|
+
* The customized event handler of mouseenter on the rectangle
|
|
173
|
+
*/
|
|
174
|
+
onMouseEnter?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
175
|
+
/**
|
|
176
|
+
* The customized event handler of mouseleave on the rectangle
|
|
177
|
+
*/
|
|
178
|
+
onMouseLeave?: (e: MouseEvent & { currentTarget: SVGPathElement }) => void
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export type Props = WithoutRemoveFalse<Omit<JSX.PathSVGAttributes<SVGPathElement>, "radius" | keyof RectangleProps>> & RectangleProps
|
|
182
|
+
|
|
183
|
+
export const defaultRectangleProps = {
|
|
184
|
+
animationBegin: 0,
|
|
185
|
+
animationDuration: 1500,
|
|
186
|
+
animationEasing: "ease",
|
|
187
|
+
height: 0,
|
|
188
|
+
isAnimationActive: false,
|
|
189
|
+
isUpdateAnimationActive: false,
|
|
190
|
+
radius: 0,
|
|
191
|
+
width: 0,
|
|
192
|
+
x: 0,
|
|
193
|
+
y: 0,
|
|
194
|
+
} as const satisfies Partial<Props>
|
|
195
|
+
|
|
196
|
+
type ResolvedRectangleProps = Props & {
|
|
197
|
+
x: number
|
|
198
|
+
y: number
|
|
199
|
+
width: number
|
|
200
|
+
height: number
|
|
201
|
+
radius: NonNullable<Props["radius"]>
|
|
202
|
+
animationBegin: number
|
|
203
|
+
animationDuration: number
|
|
204
|
+
animationEasing: NonNullable<Props["animationEasing"]>
|
|
205
|
+
isAnimationActive: boolean | "auto"
|
|
206
|
+
isUpdateAnimationActive: boolean | "auto"
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Static-path branch (when isUpdateAnimationActive=false). Rendered as its own
|
|
210
|
+
* Solid component so each prop binding (x/y/width/height/d) is a separate
|
|
211
|
+
* accessor that re-runs on prop changes — replacing the IIFE that snapshotted
|
|
212
|
+
* everything on first mount. */
|
|
213
|
+
const RECT_GEOMETRY_KEYS: ReadonlySet<string> = new Set(["x", "y", "width", "height", "radius"])
|
|
214
|
+
|
|
215
|
+
function RectanglePath(rpProps: { props: ResolvedRectangleProps; layerClass: () => string }) {
|
|
216
|
+
/* perf: snapshot non-geometry props ONCE at mount via untrack. Bar entry
|
|
217
|
+
animation re-allocates `entry()` per frame; the upstream mergeProps
|
|
218
|
+
getters for fill/stroke/etc. are wired to read `entry().<key>` reactively,
|
|
219
|
+
so any reactive read inside this function subscribes the consumer scope
|
|
220
|
+
to the per-frame signal. Putting svgPropertiesAndEvents inside createMemo
|
|
221
|
+
re-ran the full `for...in` proxy walk every animation tick (~700 calls /
|
|
222
|
+
500ms on 28 bars; ~6.2ms self in profile).
|
|
223
|
+
x/y/width/height/d/radius are bound individually below so they stay
|
|
224
|
+
reactive — the path's geometry still updates per frame. */
|
|
225
|
+
const otherPathProps = untrack(() => {
|
|
226
|
+
/* One filter pass over the props view; a splitProps view first would add a getter
|
|
227
|
+
layer per key that the filter then walks again. */
|
|
228
|
+
const all = svgPropertiesAndEvents(rpProps.props) as Record<string, unknown>
|
|
229
|
+
const rest: Record<string, unknown> = {}
|
|
230
|
+
for (const key in all) {
|
|
231
|
+
if (!RECT_GEOMETRY_KEYS.has(key)) {
|
|
232
|
+
rest[key] = all[key]
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return rest
|
|
236
|
+
})
|
|
237
|
+
/* perf: collapse all geometry attribute writes into ONE createEffect using
|
|
238
|
+
a captured node ref. Per-frame work goes from 6 reactive render effects
|
|
239
|
+
(d, x, y, width, height, radius) × 28 bars × 12 frames ≈ 2K node updates
|
|
240
|
+
to 1 effect × 28 × 12 ≈ 336 updates. Each effect skipped saves a
|
|
241
|
+
cleanNode/runTop scheduler round-trip (the dominant ~25ms cost in the
|
|
242
|
+
profile). Reads are batched: one entry() snapshot drives all 5 setAttr
|
|
243
|
+
calls under one reactive owner. */
|
|
244
|
+
let pathNode: SVGPathElement | undefined
|
|
245
|
+
let prevD = ""
|
|
246
|
+
let prevX = NaN
|
|
247
|
+
let prevY = NaN
|
|
248
|
+
let prevW = NaN
|
|
249
|
+
let prevH = NaN
|
|
250
|
+
let prevR: number | undefined = undefined
|
|
251
|
+
createEffect(
|
|
252
|
+
() => ({
|
|
253
|
+
height: rpProps.props.height,
|
|
254
|
+
radius: rpProps.props.radius,
|
|
255
|
+
width: rpProps.props.width,
|
|
256
|
+
x: rpProps.props.x,
|
|
257
|
+
y: rpProps.props.y,
|
|
258
|
+
}),
|
|
259
|
+
(geometry) => {
|
|
260
|
+
if (pathNode == null) return
|
|
261
|
+
const x = round(geometry.x)
|
|
262
|
+
const y = round(geometry.y)
|
|
263
|
+
const w = round(geometry.width)
|
|
264
|
+
const h = round(geometry.height)
|
|
265
|
+
const r = geometry.radius
|
|
266
|
+
const d = getRectanglePath(geometry.x, geometry.y, geometry.width, geometry.height, r)
|
|
267
|
+
if (d !== prevD) {
|
|
268
|
+
pathNode.setAttribute("d", d)
|
|
269
|
+
prevD = d
|
|
270
|
+
}
|
|
271
|
+
if (x !== prevX) {
|
|
272
|
+
pathNode.setAttribute("x", String(x))
|
|
273
|
+
prevX = x
|
|
274
|
+
}
|
|
275
|
+
if (y !== prevY) {
|
|
276
|
+
pathNode.setAttribute("y", String(y))
|
|
277
|
+
prevY = y
|
|
278
|
+
}
|
|
279
|
+
if (w !== prevW) {
|
|
280
|
+
pathNode.setAttribute("width", String(w))
|
|
281
|
+
prevW = w
|
|
282
|
+
}
|
|
283
|
+
if (h !== prevH) {
|
|
284
|
+
pathNode.setAttribute("height", String(h))
|
|
285
|
+
prevH = h
|
|
286
|
+
}
|
|
287
|
+
if (typeof r === "number" && r !== prevR) {
|
|
288
|
+
pathNode.setAttribute("radius", String(r))
|
|
289
|
+
prevR = r
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
)
|
|
293
|
+
return (
|
|
294
|
+
<path
|
|
295
|
+
{...otherPathProps}
|
|
296
|
+
class={rpProps.layerClass()}
|
|
297
|
+
ref={(el) => {
|
|
298
|
+
pathNode = el
|
|
299
|
+
}}
|
|
300
|
+
/>
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Renders a rectangle element. Unlike the {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/rect rect SVG element}, this component supports rounded corners
|
|
306
|
+
* and animation.
|
|
307
|
+
*
|
|
308
|
+
* This component accepts X and Y coordinates in pixels.
|
|
309
|
+
* If you need to position the rectangle based on your chart's data,
|
|
310
|
+
* consider using the {@link ReferenceArea} component instead.
|
|
311
|
+
*/
|
|
312
|
+
export function Rectangle(ownProps: Props) {
|
|
313
|
+
/* Props injected for a shape passed as an element (see ShapeElementProps). */
|
|
314
|
+
const rectangleProps = useShapeElementProps(ownProps)
|
|
315
|
+
/* mergeProps preserves the props proxy so x/y/width/height stay reactive.
|
|
316
|
+
* resolveDefaultProps spreads at setup time and freezes them — see
|
|
317
|
+
* GOTCHA-005-C. The cast restores the resolved-prop guarantees that
|
|
318
|
+
* downstream code (RectanglePath, animation closures) relies on. */
|
|
319
|
+
const props = mergeProps(defaultRectangleProps, rectangleProps) as ResolvedRectangleProps
|
|
320
|
+
/* React's useRef stores the path node; Solid needs an explicit setter
|
|
321
|
+
* callback because `ref={letBoundVar}` is a no-op (Solid only writes
|
|
322
|
+
* through function refs / signal setters). */
|
|
323
|
+
let pathRef: SVGPathElement | undefined
|
|
324
|
+
const capturePathRef = (el: SVGPathElement) => {
|
|
325
|
+
pathRef = el
|
|
326
|
+
if (el.getTotalLength) {
|
|
327
|
+
try {
|
|
328
|
+
const pathTotalLength = el.getTotalLength()
|
|
329
|
+
if (pathTotalLength) {
|
|
330
|
+
setTotalLength(pathTotalLength)
|
|
331
|
+
}
|
|
332
|
+
} catch {
|
|
333
|
+
/* calculate total length error */
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const [totalLength, setTotalLength] = createSignal(-1)
|
|
338
|
+
|
|
339
|
+
const animationIdInput = createMemo(() => ({
|
|
340
|
+
height: props.height,
|
|
341
|
+
radius: props.radius,
|
|
342
|
+
width: props.width,
|
|
343
|
+
x: props.x,
|
|
344
|
+
y: props.y,
|
|
345
|
+
}))
|
|
346
|
+
/* eslint-disable-next-line solid/reactivity -- animationIdInput is a createMemo accessor passed by reference; useAnimationId tracks it internally */
|
|
347
|
+
const animationId = useAnimationId(animationIdInput, "rectangle-")
|
|
348
|
+
|
|
349
|
+
const isValid = () =>
|
|
350
|
+
props.x === +props.x &&
|
|
351
|
+
props.y === +props.y &&
|
|
352
|
+
props.width === +props.width &&
|
|
353
|
+
props.height === +props.height &&
|
|
354
|
+
props.width !== 0 &&
|
|
355
|
+
props.height !== 0
|
|
356
|
+
|
|
357
|
+
/* eslint-disable solid/reactivity -- prev* are intentional initial snapshots for animation; they track previous frame values, not reactive state */
|
|
358
|
+
let prevWidth = untrack(() => props.width)
|
|
359
|
+
let prevHeight = untrack(() => props.height)
|
|
360
|
+
let prevX = untrack(() => props.x)
|
|
361
|
+
let prevY = untrack(() => props.y)
|
|
362
|
+
/* eslint-enable solid/reactivity */
|
|
363
|
+
|
|
364
|
+
const layerClass = () =>
|
|
365
|
+
clsx("recharts-rectangle", props.class, (props as { className?: string }).className)
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<Show when={isValid()}>
|
|
369
|
+
<Show
|
|
370
|
+
when={props.isUpdateAnimationActive}
|
|
371
|
+
fallback={
|
|
372
|
+
<RectanglePath
|
|
373
|
+
props={props as ResolvedRectangleProps}
|
|
374
|
+
layerClass={layerClass}
|
|
375
|
+
/>
|
|
376
|
+
}
|
|
377
|
+
>
|
|
378
|
+
{(() => {
|
|
379
|
+
const from = () => `0px ${totalLength() === -1 ? 1 : totalLength()}px`
|
|
380
|
+
const to = () => `${totalLength()}px 0px`
|
|
381
|
+
const transition = () =>
|
|
382
|
+
getTransitionVal(
|
|
383
|
+
["strokeDasharray"],
|
|
384
|
+
props.animationDuration,
|
|
385
|
+
typeof props.animationEasing === "string"
|
|
386
|
+
? props.animationEasing
|
|
387
|
+
: defaultRectangleProps.animationEasing,
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
return (
|
|
391
|
+
<JavascriptAnimate
|
|
392
|
+
animationId={animationId()}
|
|
393
|
+
canBegin={totalLength() > 0}
|
|
394
|
+
duration={props.animationDuration}
|
|
395
|
+
easing={props.animationEasing}
|
|
396
|
+
isActive={props.isUpdateAnimationActive}
|
|
397
|
+
begin={props.animationBegin}
|
|
398
|
+
>
|
|
399
|
+
{(t: () => number) => {
|
|
400
|
+
/* GOTCHA-014: thunk children — invoked once, attribute-only updates per tick.
|
|
401
|
+
Snapshot prev* once per memo eval but write back only via effect to avoid
|
|
402
|
+
stale-eval drift. */
|
|
403
|
+
/* Upstream reads prev* refs once per Rectangle render, so the start point
|
|
404
|
+
is frozen until geometry props change; per-frame ref writes only seed
|
|
405
|
+
the next animation. */
|
|
406
|
+
const start = createMemo(() => {
|
|
407
|
+
void props.width
|
|
408
|
+
void props.height
|
|
409
|
+
void props.x
|
|
410
|
+
void props.y
|
|
411
|
+
return untrack(() => ({ height: prevHeight, width: prevWidth, x: prevX, y: prevY }))
|
|
412
|
+
})
|
|
413
|
+
const currWidth = createMemo(() => interpolate(start().width, props.width, t()))
|
|
414
|
+
const currHeight = createMemo(() => interpolate(start().height, props.height, t()))
|
|
415
|
+
const currX = createMemo(() => interpolate(start().x, props.x, t()))
|
|
416
|
+
const currY = createMemo(() => interpolate(start().y, props.y, t()))
|
|
417
|
+
createEffect(
|
|
418
|
+
() => (t() > 0 ? { prevHeight: currHeight(), prevWidth: currWidth(), prevX: currX(), prevY: currY() } : null),
|
|
419
|
+
(step) => {
|
|
420
|
+
if (step != null && pathRef) {
|
|
421
|
+
prevWidth = step.prevWidth
|
|
422
|
+
prevHeight = step.prevHeight
|
|
423
|
+
prevX = step.prevX
|
|
424
|
+
prevY = step.prevY
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
)
|
|
428
|
+
const animationStyle = createMemo(() => {
|
|
429
|
+
if (props.isAnimationActive === false) {
|
|
430
|
+
return { "stroke-dasharray": to() }
|
|
431
|
+
}
|
|
432
|
+
if (t() > 0) {
|
|
433
|
+
return { "stroke-dasharray": to(), transition: transition() }
|
|
434
|
+
}
|
|
435
|
+
return { "stroke-dasharray": from() }
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
const otherPathProps = createMemo(() => {
|
|
439
|
+
const {
|
|
440
|
+
radius: _,
|
|
441
|
+
x: _x,
|
|
442
|
+
y: _y,
|
|
443
|
+
width: _w,
|
|
444
|
+
height: _h,
|
|
445
|
+
style: _s,
|
|
446
|
+
...rest
|
|
447
|
+
} = svgPropertiesAndEvents(props)
|
|
448
|
+
return rest
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
<path
|
|
453
|
+
{...otherPathProps()}
|
|
454
|
+
class={layerClass()}
|
|
455
|
+
d={getRectanglePath(currX(), currY(), currWidth(), currHeight(), props.radius)}
|
|
456
|
+
ref={capturePathRef}
|
|
457
|
+
style={{
|
|
458
|
+
...animationStyle(),
|
|
459
|
+
...(typeof props.style === "object" ? props.style : {}),
|
|
460
|
+
}}
|
|
461
|
+
/>
|
|
462
|
+
)
|
|
463
|
+
}}
|
|
464
|
+
</JavascriptAnimate>
|
|
465
|
+
)
|
|
466
|
+
})()}
|
|
467
|
+
</Show>
|
|
468
|
+
</Show>
|
|
469
|
+
)
|
|
470
|
+
}
|