solid-recharts 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/package.json +10 -7
- package/src/cartesian/Area.tsx +40 -55
- package/src/cartesian/Bar.tsx +66 -58
- package/src/cartesian/BarStack.tsx +5 -2
- package/src/cartesian/Brush.tsx +1 -1
- package/src/cartesian/Funnel.tsx +15 -19
- package/src/cartesian/Line.tsx +34 -51
- package/src/cartesian/LineDrawShape.tsx +8 -6
- package/src/cartesian/ReferenceArea.tsx +25 -35
- package/src/cartesian/ReferenceDot.tsx +24 -34
- package/src/cartesian/ReferenceLine.tsx +25 -34
- package/src/cartesian/Scatter.tsx +25 -37
- package/src/cartesian/XAxis.tsx +54 -67
- package/src/cartesian/YAxis.tsx +53 -66
- package/src/cartesian/ZAxis.tsx +27 -40
- package/src/chart/SunburstChart.tsx +1 -1
- package/src/component/ActivePoints.tsx +0 -9
- package/src/component/Customized.tsx +1 -1
- package/src/component/Dots.tsx +7 -3
- package/src/context/ErrorBarContext.tsx +15 -24
- package/src/polar/Pie.tsx +36 -48
- package/src/polar/PolarAngleAxis.tsx +41 -50
- package/src/polar/PolarRadiusAxis.tsx +40 -48
- package/src/polar/Radar.tsx +22 -34
- package/src/polar/RadialBar.tsx +21 -39
- package/src/shape/Curve.tsx +1 -1
- package/src/shape/Symbols.tsx +1 -1
- package/src/state/RechartsReduxContext.tsx +1 -1
- package/src/state/SetLegendPayload.ts +19 -27
- package/src/state/SetTooltipEntrySettings.tsx +9 -26
- package/src/state/cartesianAxisSlice.ts +40 -60
- package/src/state/createCollectionActions.ts +51 -0
- package/src/state/createSelector.ts +97 -0
- package/src/state/externalEventsMiddleware.ts +2 -11
- package/src/state/graphicalItemsSlice.ts +27 -40
- package/src/state/isEventThrottled.ts +12 -0
- package/src/state/keyboardEventsMiddleware.ts +2 -8
- package/src/state/layoutSlice.ts +8 -4
- package/src/state/legendSlice.ts +24 -26
- package/src/state/mouseEventsMiddleware.ts +2 -13
- package/src/state/patched.ts +19 -0
- package/src/state/referenceElementsSlice.ts +40 -31
- package/src/state/registerInStore.ts +68 -0
- package/src/state/selectors/areaSelectors.ts +13 -36
- package/src/state/selectors/arrayEqualityCheck.ts +32 -7
- package/src/state/selectors/axisSelectors.ts +215 -169
- package/src/state/selectors/barSelectors.ts +8 -36
- package/src/state/selectors/combiners/combineConfiguredScale.ts +1 -1
- package/src/state/selectors/combiners/combineRealScaleType.ts +1 -1
- package/src/state/selectors/dataSelectors.ts +35 -16
- package/src/state/selectors/numberDomainEqualityCheck.ts +16 -8
- package/src/state/selectors/selectAxisForGraphicalItem.ts +52 -0
- package/src/state/store.ts +0 -1
- package/src/state/tooltipSlice.ts +93 -64
- package/src/util/ActiveShapeUtils.tsx +0 -7
- package/src/util/BarUtils.tsx +27 -22
- package/src/util/ChartUtils.ts +69 -25
- package/src/util/propsAreEqual.ts +3 -33
- package/src/util/stacks/stackTypes.ts +1 -1
- package/src/util/types.ts +2 -2
- package/test/animation/CSSTransitionAnimate.timing.spec.tsx +1 -1
- package/test/animation/JavascriptAnimate.spec.tsx +1 -1
- package/test/animation/legacyAnimationLengthChange.spec.tsx +1 -1
- package/test/cartesian/Area.animation.spec.tsx +1 -1
- package/test/cartesian/Area.range.spec.tsx +1 -1
- package/test/cartesian/Area.spec.tsx +1 -1
- package/test/cartesian/Area.stacked.render.spec.tsx +1 -1
- package/test/cartesian/Area.typed.spec.tsx +1 -1
- package/test/cartesian/Axis.integration.spec.tsx +1 -1
- package/test/cartesian/Bar/Bar.csstransition.spec.tsx +1 -1
- package/test/cartesian/Bar/Bar.spec.tsx +1 -1
- package/test/cartesian/Bar/Bar.typed.spec.tsx +1 -1
- package/test/cartesian/Bar.animation.spec.tsx +1 -1
- package/test/cartesian/Bar.stackDomain.spec.tsx +1 -1
- package/test/cartesian/Bar.stacked.render.spec.tsx +1 -1
- package/test/cartesian/Bar.zeroDimensionFiltering.spec.tsx +1 -1
- package/test/cartesian/Brush.keyboard.spec.tsx +1 -1
- package/test/cartesian/Brush.panorama.spec.tsx +1 -1
- package/test/cartesian/Brush.props.spec.tsx +1 -1
- package/test/cartesian/Brush.render.spec.tsx +1 -1
- package/test/cartesian/Brush.spec.tsx +1 -1
- package/test/cartesian/Brush.stacked.spec.tsx +1 -1
- package/test/cartesian/CartesianAxis.render.spec.tsx +1 -1
- package/test/cartesian/CartesianAxis.spec.tsx +2 -2
- package/test/cartesian/CartesianGrid.render.spec.tsx +1 -1
- package/test/cartesian/CartesianGrid.spec.tsx +1 -1
- package/test/cartesian/ErrorBar.render.spec.tsx +1 -1
- package/test/cartesian/ErrorBar.spec.tsx +1 -1
- package/test/cartesian/Funnel.animation.spec.tsx +1 -1
- package/test/cartesian/Funnel.spec.tsx +1 -1
- package/test/cartesian/Funnel.typed.spec.tsx +1 -1
- package/test/cartesian/GraphicalItemClipPath.scale-behavior.spec.tsx +2 -2
- package/test/cartesian/Line.animation.spec.tsx +1 -1
- package/test/cartesian/Line.sparseAnimationPath.spec.tsx +1 -1
- package/test/cartesian/Line.spec.tsx +1 -1
- package/test/cartesian/Line.typed.spec.tsx +1 -1
- package/test/cartesian/ReferenceArea.render.spec.tsx +1 -1
- package/test/cartesian/ReferenceArea.spec.tsx +1 -1
- package/test/cartesian/ReferenceArea.typed.spec.tsx +1 -1
- package/test/cartesian/ReferenceDot.render.spec.tsx +1 -1
- package/test/cartesian/ReferenceDot.spec.tsx +1 -1
- package/test/cartesian/ReferenceDot.typed.spec.tsx +1 -1
- package/test/cartesian/ReferenceLine/ReferenceLine.panorama.spec.tsx +1 -1
- package/test/cartesian/ReferenceLine/ReferenceLine.spec.tsx +1 -1
- package/test/cartesian/ReferenceLine/ReferenceLine.typed.spec.tsx +1 -1
- package/test/cartesian/ReferenceLine/getEndPoints.spec.ts +1 -1
- package/test/cartesian/ReferenceLine.render.spec.tsx +1 -1
- package/test/cartesian/Scatter.animation.spec.tsx +1 -1
- package/test/cartesian/Scatter.render.spec.tsx +1 -1
- package/test/cartesian/Scatter.spec.tsx +1 -1
- package/test/cartesian/Scatter.typed.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.barSize.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.brush.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.categorydomain.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.datatypes.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.hide.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.multiaxis.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.numberdomain.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.padding.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.padding_clip.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.state.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.tick.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.timescale.spec.tsx +2 -2
- package/test/cartesian/XAxis/XAxis.typed.spec.tsx +1 -1
- package/test/cartesian/XAxis/XAxis.vertical.spec.tsx +1 -1
- package/test/cartesian/XAxis.tickFormatter.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.7362.derivedDomain.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.interval-zero.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.label.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.tick.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.tickFormatter.spec.tsx +1 -1
- package/test/cartesian/YAxis/YAxis.typed.spec.tsx +1 -1
- package/test/cartesian/ZAxis.spec.tsx +1 -1
- package/test/cartesian/ZAxis.typed.spec.tsx +1 -1
- package/test/cartesian/axisLineAndStroke.spec.tsx +1 -1
- package/test/cartesian/miscFeatureGaps.spec.tsx +1 -1
- package/test/chart/AccessibilityLayer.spec.tsx +1 -1
- package/test/chart/AccessibilityScans.spec.tsx +2 -2
- package/test/chart/AreaChart.spec.tsx +1 -1
- package/test/chart/AreaChart.typed.spec.tsx +1 -1
- package/test/chart/BarChart.spec.tsx +1 -1
- package/test/chart/BarChart.typed.spec.tsx +1 -1
- package/test/chart/CategoricalChart.spec.tsx +1 -1
- package/test/chart/ComposedChart.spec.tsx +1 -1
- package/test/chart/ComposedChart.typed.spec.tsx +1 -1
- package/test/chart/FunnelChart.spec.tsx +1 -1
- package/test/chart/FunnelChart.typed.spec.tsx +1 -1
- package/test/chart/LineChart.smoke.spec.tsx +1 -1
- package/test/chart/LineChart.spec.tsx +1 -1
- package/test/chart/LineChart.typed.spec.tsx +1 -1
- package/test/chart/NicheChartTooltip.spec.tsx +1 -1
- package/test/chart/PieChart.spec.tsx +1 -1
- package/test/chart/PieChart.typed.spec.tsx +1 -1
- package/test/chart/RadarChart.spec.tsx +1 -1
- package/test/chart/RadarChart.typed.spec.tsx +1 -1
- package/test/chart/RadialBarChart.spec.tsx +1 -1
- package/test/chart/RadialBarChart.typed.spec.tsx +1 -1
- package/test/chart/RechartsWrapper.spec.tsx +1 -1
- package/test/chart/Sankey.content.spec.tsx +1 -1
- package/test/chart/Sankey.spec.tsx +1 -1
- package/test/chart/ScatterChart.spec.tsx +1 -1
- package/test/chart/ScatterChart.typed.spec.tsx +1 -1
- package/test/chart/SunburstChart.spec.tsx +1 -1
- package/test/chart/Treemap.animation.spec.tsx +1 -1
- package/test/chart/Treemap.spec.tsx +1 -1
- package/test/chart/chartEvents.spec.tsx +1 -1
- package/test/chart/responsive.spec.tsx +1 -1
- package/test/component/Cell.render.spec.tsx +1 -1
- package/test/component/Cell.spec.tsx +1 -1
- package/test/component/Cursor.spec.tsx +1 -1
- package/test/component/DefaultTooltipContent.spec.tsx +1 -1
- package/test/component/Label.render.spec.tsx +1 -1
- package/test/component/Label.spec.tsx +1 -1
- package/test/component/LabelList.spec.tsx +1 -1
- package/test/component/Legend.itemSorter.spec.tsx +1 -1
- package/test/component/Legend.render.spec.tsx +1 -1
- package/test/component/Legend.spec.tsx +1 -1
- package/test/component/ResponsiveContainer.spec.tsx +1 -1
- package/test/component/ResponsiveContainerDataTest.spec.tsx +1 -1
- package/test/component/Text.spec.tsx +1 -1
- package/test/component/Tooltip/ActiveDot.spec.tsx +1 -1
- package/test/component/Tooltip/tooltipEventType.spec.tsx +1 -1
- package/test/component/Tooltip/tooltipTestHelpers.tsx +1 -1
- package/test/component/Tooltip.defaultIndex.spec.tsx +1 -1
- package/test/component/Tooltip.hover.spec.tsx +1 -1
- package/test/component/Tooltip.item.spec.tsx +1 -1
- package/test/component/Tooltip.keyboard.spec.tsx +1 -1
- package/test/component/Tooltip.payload.spec.tsx +1 -1
- package/test/component/Tooltip.touch.spec.tsx +1 -1
- package/test/component/Tooltip.visibility.spec.tsx +1 -1
- package/test/component/TooltipBoundingBox.spec.tsx +2 -2
- package/test/container/ClipPath.spec.tsx +1 -1
- package/test/context/chartLayoutContext.spec.tsx +1 -1
- package/test/helper/createSelectorTestCase.tsx +1 -1
- package/test/helper/mockAxes.ts +1 -1
- package/test/helper/selectorTestHelpers.tsx +1 -1
- package/test/hooks/useActiveTooltipDataPoints.spec.tsx +1 -1
- package/test/hooks/useOffset.spec.tsx +1 -1
- package/test/hooks/useTooltipStateHooks.spec.tsx +1 -1
- package/test/polar/Pie/Pie-TwoLevelPieChart.spec.tsx +1 -1
- package/test/polar/Pie/Pie.spec.tsx +1 -1
- package/test/polar/Pie/Pie.typed.spec.tsx +1 -1
- package/test/polar/Pie.animation.spec.tsx +1 -1
- package/test/polar/PieWithLegend.animation.spec.tsx +1 -1
- package/test/polar/PolarAngleAxis/PolarAngleAxis.events.spec.tsx +1 -1
- package/test/polar/PolarAngleAxis/PolarAngleAxis.spec.tsx +1 -1
- package/test/polar/PolarAngleAxis/PolarAngleAxis.typed.spec.tsx +1 -1
- package/test/polar/PolarAngleAxis.render.spec.tsx +1 -1
- package/test/polar/PolarGrid.render.spec.tsx +1 -1
- package/test/polar/PolarGrid.spec.tsx +1 -1
- package/test/polar/PolarLegendPerRow.render.spec.tsx +1 -1
- package/test/polar/PolarRadiusAxis.events.spec.tsx +1 -1
- package/test/polar/PolarRadiusAxis.render.spec.tsx +1 -1
- package/test/polar/PolarRadiusAxis.spec.tsx +1 -1
- package/test/polar/PolarRadiusAxis.typed.spec.tsx +1 -1
- package/test/polar/PolarTooltipLegend.render.spec.tsx +1 -1
- package/test/polar/Radar.animation.spec.tsx +1 -1
- package/test/polar/Radar.render.spec.tsx +1 -1
- package/test/polar/Radar.spec.tsx +1 -1
- package/test/polar/Radar.typed.spec.tsx +1 -1
- package/test/polar/RadialBar/RadialBar.spec.tsx +1 -1
- package/test/polar/RadialBar/RadialBar.typed.spec.tsx +1 -1
- package/test/polar/RadialBar.animation.spec.tsx +1 -1
- package/test/polar/RadialBar.render.spec.tsx +1 -1
- package/test/polar/RadialBar.stacked.spec.tsx +1 -1
- package/test/setup.ts +1 -1
- package/test/shape/ActiveShape.spec.tsx +1 -1
- package/test/shape/Cross.spec.tsx +1 -1
- package/test/shape/Curve.spec.tsx +2 -2
- package/test/shape/Curve.typed.spec.tsx +1 -1
- package/test/shape/Dot.spec.tsx +1 -1
- package/test/shape/Polygon.spec.tsx +1 -1
- package/test/shape/Rectangle.animation.spec.tsx +1 -1
- package/test/shape/Rectangle.spec.tsx +1 -1
- package/test/shape/Sector.spec.tsx +1 -1
- package/test/shape/Symbols.spec.tsx +1 -1
- package/test/shape/Trapezoid.spec.tsx +1 -1
- package/test/state/createCollectionActions.spec.ts +87 -0
- package/test/state/createSelector.spec.ts +158 -0
- package/test/state/hooks.spec.tsx +1 -1
- package/test/state/registerInStore.spec.tsx +101 -0
- package/test/state/selectors/axisSelectors.spec.tsx +1 -1
- package/test/state/selectors/combiners/combineConfiguredScale.spec.ts +1 -1
- package/test/state/selectors/combiners/combineRealScaleType.spec.ts +1 -1
- package/test/state/selectors/dataSelectors.spec.tsx +1 -1
- package/test/state/selectors/legendSelectors.spec.tsx +1 -1
- package/test/state/selectors/radarSelectors.spec.tsx +1 -1
- package/test/state/selectors/selectActiveTooltipIndex.spec.tsx +1 -1
- package/test/state/selectors/selectDisplayedData.spec.tsx +1 -1
- package/test/state/selectors/selectStackGroups.spec.tsx +1 -1
- package/test/state/selectors/selectorMemoization.spec.tsx +136 -0
- package/test/state/selectors/selectors.spec.tsx +1 -1
- package/test/util/CartesianUtils/CartesianUtils.spec.ts +1 -1
- package/test/util/ChartUtils/ChartUtils.spec.ts +1 -1
- package/test/util/ChartUtils/getCateCoordinateOfLine.spec.ts +14 -0
- package/test/util/ChartUtils/getStackedData.spec.ts +1 -1
- package/test/util/ChartUtils/truncateByDomain.spec.ts +1 -1
- package/test/util/DomUtils.spec.tsx +1 -1
- package/test/util/FunnelUtils.spec.tsx +1 -1
- package/test/util/scale/createCategoricalInverse.spec.ts +1 -1
- package/test/util/useElementOffset.spec.tsx +1 -1
- package/test/util/usePrefersReducedMotion.spec.ts +1 -1
- package/test/util/useUniqueId.spec.ts +1 -1
- package/test/zIndex/AllZIndexPortals.spec.tsx +1 -1
- package/test/zIndex/DynamicZIndex.spec.tsx +1 -1
- package/test/zIndex/ZIndexLayer.portalOwner.spec.tsx +1 -1
- package/test/zIndex/componentZIndex.spec.tsx +1 -1
- package/test/zIndex/multiChartZIndexIsolation.spec.tsx +1 -1
- package/test-results/.last-run.json +4 -0
- package/NEXT_SESSION_PROMPT.md +0 -114
- package/src/state/reduxDevtoolsJsonStringifyReplacer.ts +0 -15
- package/src/util/axisPropsAreEqual.ts +0 -42
- package/src/util/resolveDefaultProps.tsx +0 -8
- package/src/util/typedDataKey.ts +0 -8
- package/test/helper/render.ts +0 -7
- package/test/state/reduxDevtoolsJsonStringifyReplacer.spec.ts +0 -25
- package/test/util/axisPropsAreEqual.spec.ts +0 -93
|
@@ -37,6 +37,10 @@ import {
|
|
|
37
37
|
selectYAxisIdFromGraphicalItemId,
|
|
38
38
|
} from "./graphicalItemSelectors";
|
|
39
39
|
import { combineBarPosition } from "./combiners/combineBarPosition";
|
|
40
|
+
import {
|
|
41
|
+
selectAxisWithScaleForGraphicalItem,
|
|
42
|
+
selectTicksForGraphicalItem,
|
|
43
|
+
} from "./selectAxisForGraphicalItem";
|
|
40
44
|
|
|
41
45
|
const selectSynchronisedBarSettings = (
|
|
42
46
|
state: RechartsRootState,
|
|
@@ -187,38 +191,6 @@ export const selectBarPosition = (
|
|
|
187
191
|
selectSynchronisedBarSettings(state, id),
|
|
188
192
|
);
|
|
189
193
|
|
|
190
|
-
const selectXAxisWithScale = (
|
|
191
|
-
state: RechartsRootState,
|
|
192
|
-
id: GraphicalItemId,
|
|
193
|
-
isPanorama: boolean,
|
|
194
|
-
) => {
|
|
195
|
-
const xAxisId = selectXAxisIdFromGraphicalItemId(state, id);
|
|
196
|
-
return xAxisId == null ? undefined : selectAxisWithScale(state, "xAxis", xAxisId, isPanorama);
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
const selectYAxisWithScale = (
|
|
200
|
-
state: RechartsRootState,
|
|
201
|
-
id: GraphicalItemId,
|
|
202
|
-
isPanorama: boolean,
|
|
203
|
-
) => {
|
|
204
|
-
const yAxisId = selectYAxisIdFromGraphicalItemId(state, id);
|
|
205
|
-
return yAxisId == null ? undefined : selectAxisWithScale(state, "yAxis", yAxisId, isPanorama);
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const selectXAxisTicks = (state: RechartsRootState, id: GraphicalItemId, isPanorama: boolean) => {
|
|
209
|
-
const xAxisId = selectXAxisIdFromGraphicalItemId(state, id);
|
|
210
|
-
return xAxisId == null
|
|
211
|
-
? undefined
|
|
212
|
-
: selectTicksOfGraphicalItem(state, "xAxis", xAxisId, isPanorama);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const selectYAxisTicks = (state: RechartsRootState, id: GraphicalItemId, isPanorama: boolean) => {
|
|
216
|
-
const yAxisId = selectYAxisIdFromGraphicalItemId(state, id);
|
|
217
|
-
return yAxisId == null
|
|
218
|
-
? undefined
|
|
219
|
-
: selectTicksOfGraphicalItem(state, "yAxis", yAxisId, isPanorama);
|
|
220
|
-
};
|
|
221
|
-
|
|
222
194
|
const selectBarStackGroups = (
|
|
223
195
|
state: RechartsRootState,
|
|
224
196
|
id: GraphicalItemId,
|
|
@@ -253,10 +225,10 @@ export const selectBarRectangles = (
|
|
|
253
225
|
): ReadonlyArray<BarRectangleItem> | undefined => {
|
|
254
226
|
const axisViewBox = selectAxisViewBox(state);
|
|
255
227
|
const offset = selectChartOffsetInternal(state);
|
|
256
|
-
const xAxis =
|
|
257
|
-
const yAxis =
|
|
258
|
-
const xAxisTicks =
|
|
259
|
-
const yAxisTicks =
|
|
228
|
+
const xAxis = selectAxisWithScaleForGraphicalItem(state, "xAxis", id, isPanorama);
|
|
229
|
+
const yAxis = selectAxisWithScaleForGraphicalItem(state, "yAxis", id, isPanorama);
|
|
230
|
+
const xAxisTicks = selectTicksForGraphicalItem(state, "xAxis", id, isPanorama);
|
|
231
|
+
const yAxisTicks = selectTicksForGraphicalItem(state, "yAxis", id, isPanorama);
|
|
260
232
|
const pos = selectBarPosition(state, id, isPanorama);
|
|
261
233
|
const layout: LayoutType = selectChartLayout(state);
|
|
262
234
|
const { chartData, dataStartIndex, dataEndIndex } =
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// we spread the namespace into a plain record and narrow each candidate to a
|
|
8
8
|
// scale factory through a user-defined type guard before calling it. Behavior is
|
|
9
9
|
// identical (unknown names / non-function exports → `undefined`).
|
|
10
|
-
import * as d3Scales from "
|
|
10
|
+
import * as d3Scales from "d3-scale";
|
|
11
11
|
import {
|
|
12
12
|
CategoricalDomain,
|
|
13
13
|
CategoricalDomainItem,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Ported from recharts 3.8.1 src/state/selectors/combiners/combineRealScaleType.ts
|
|
2
2
|
// (commit 7a23854).
|
|
3
|
-
import * as d3Scales from "
|
|
3
|
+
import * as d3Scales from "d3-scale";
|
|
4
4
|
import { RechartsScaleType } from "../../../util/types";
|
|
5
5
|
import { BaseCartesianAxis } from "../../cartesianAxisSlice";
|
|
6
6
|
import { upperFirst } from "../../../util/DataUtils";
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
// Ported from recharts 3.8.1 src/state/selectors/dataSelectors.ts (commit 7a23854).
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// `
|
|
7
|
-
//
|
|
3
|
+
// The chartData-projecting selectors below are wrapped in the Solid-native
|
|
4
|
+
// `createSelector` (ADR-0002) so they present a stable reference when the data
|
|
5
|
+
// is unchanged — the leaf-input fix the memoized selector graph depends on. The
|
|
6
|
+
// remaining `slice`-returning helpers stay plain (they intentionally produce a
|
|
7
|
+
// fresh window each call and their wrapped consumers absorb the churn).
|
|
8
8
|
import { RechartsRootState } from "../store";
|
|
9
9
|
import { ChartData, ChartDataState } from "../chartDataSlice";
|
|
10
|
+
import { createSelector } from "../createSelector";
|
|
11
|
+
|
|
12
|
+
// LEAF-INPUT rule (ADR-0002 "Known constraint"): these read the individual
|
|
13
|
+
// leaves of the chartData slice — never the slice root `state.chartData`, whose
|
|
14
|
+
// proxy reference is permanently stable in Solid and so can never invalidate a
|
|
15
|
+
// reference-keyed cache. Reading the leaves (the `chartData` array is replaced
|
|
16
|
+
// wholesale by `setChartData`; the indexes are primitives) lets `createSelector`
|
|
17
|
+
// return a stable projected object when nothing changed and a fresh one when it
|
|
18
|
+
// did — the reselect semantics the downstream selector graph relies on.
|
|
19
|
+
const pickChartData = (state: RechartsRootState): ChartData | undefined =>
|
|
20
|
+
state.chartData.chartData;
|
|
21
|
+
const pickComputedData = (state: RechartsRootState): unknown => state.chartData.computedData;
|
|
22
|
+
const pickDataStartIndex = (state: RechartsRootState): number => state.chartData.dataStartIndex;
|
|
23
|
+
const pickDataEndIndex = (state: RechartsRootState): number => state.chartData.dataEndIndex;
|
|
10
24
|
|
|
11
25
|
/**
|
|
12
26
|
* Always returns the data with the indexes set by a Brush. That might or might
|
|
@@ -15,23 +29,28 @@ import { ChartData, ChartDataState } from "../chartDataSlice";
|
|
|
15
29
|
* {@link selectChartDataAndAlwaysIgnoreIndexes} or
|
|
16
30
|
* {@link selectChartDataWithIndexesIfNotInPanoramaPosition4} when that matters.
|
|
17
31
|
*/
|
|
18
|
-
export const selectChartDataWithIndexes
|
|
19
|
-
|
|
32
|
+
export const selectChartDataWithIndexes: (state: RechartsRootState) => ChartDataState =
|
|
33
|
+
createSelector(
|
|
34
|
+
[pickChartData, pickComputedData, pickDataStartIndex, pickDataEndIndex],
|
|
35
|
+
(chartData, computedData, dataStartIndex, dataEndIndex) => ({
|
|
36
|
+
chartData,
|
|
37
|
+
computedData,
|
|
38
|
+
dataStartIndex,
|
|
39
|
+
dataEndIndex,
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
20
42
|
|
|
21
43
|
/**
|
|
22
44
|
* Always returns the full range of data, ignoring Brush indexes. Useful for the
|
|
23
45
|
* Brush panorama, Legend, and Tooltip.
|
|
24
46
|
*/
|
|
25
|
-
export const selectChartDataAndAlwaysIgnoreIndexes
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
chartData:
|
|
30
|
-
computedData: dataState.computedData,
|
|
31
|
-
dataEndIndex,
|
|
47
|
+
export const selectChartDataAndAlwaysIgnoreIndexes: (state: RechartsRootState) => ChartDataState =
|
|
48
|
+
createSelector([pickChartData, pickComputedData], (chartData, computedData) => ({
|
|
49
|
+
chartData,
|
|
50
|
+
computedData,
|
|
51
|
+
dataEndIndex: chartData != null ? chartData.length - 1 : 0,
|
|
32
52
|
dataStartIndex: 0,
|
|
33
|
-
};
|
|
34
|
-
};
|
|
53
|
+
}));
|
|
35
54
|
|
|
36
55
|
export const selectChartDataWithIndexesIfNotInPanoramaPosition4 = (
|
|
37
56
|
state: RechartsRootState,
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
// Ported from recharts 3.9.2 src/state/selectors/numberDomainEqualityCheck.ts.
|
|
2
|
+
// See arrayEqualityCheck.ts for why this is now ported (ADR-0002).
|
|
3
|
+
import type { NumberDomain } from "../../util/types";
|
|
4
|
+
|
|
5
|
+
export const numberDomainEqualityCheck = (
|
|
6
|
+
a: NumberDomain | undefined,
|
|
7
|
+
b: NumberDomain | undefined,
|
|
8
|
+
): boolean => {
|
|
9
|
+
if (a === b) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
if (a == null || b == null) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return a[0] === b[0] && a[1] === b[1];
|
|
16
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Resolves the scaled axis / ticks a cartesian graphical item is bound to, from
|
|
2
|
+
// the item's id. Area and Bar each declared these four wrappers privately (and
|
|
3
|
+
// Bar carried a dead `axisId == null` guard — selectX/YAxisIdFromGraphicalItemId
|
|
4
|
+
// never returns null, it falls back to defaultAxisId). Concentrated here so the
|
|
5
|
+
// "which axis does this item read" resolution lives once.
|
|
6
|
+
//
|
|
7
|
+
// A leaf module (like areaSelectors/barSelectors): it imports from both
|
|
8
|
+
// axisSelectors and graphicalItemSelectors, so it introduces no import cycle.
|
|
9
|
+
import { RechartsRootState } from "../store";
|
|
10
|
+
import { GraphicalItemId } from "../graphicalItemsSlice";
|
|
11
|
+
import {
|
|
12
|
+
selectAxisWithScale,
|
|
13
|
+
selectTicksOfGraphicalItem,
|
|
14
|
+
type BaseAxisWithScale,
|
|
15
|
+
} from "./axisSelectors";
|
|
16
|
+
import {
|
|
17
|
+
selectXAxisIdFromGraphicalItemId,
|
|
18
|
+
selectYAxisIdFromGraphicalItemId,
|
|
19
|
+
} from "./graphicalItemSelectors";
|
|
20
|
+
import type { TickItem } from "../../util/types";
|
|
21
|
+
|
|
22
|
+
type CartesianAxisType = "xAxis" | "yAxis";
|
|
23
|
+
|
|
24
|
+
const axisIdForGraphicalItem = (
|
|
25
|
+
state: RechartsRootState,
|
|
26
|
+
axisType: CartesianAxisType,
|
|
27
|
+
id: GraphicalItemId,
|
|
28
|
+
) =>
|
|
29
|
+
axisType === "xAxis"
|
|
30
|
+
? selectXAxisIdFromGraphicalItemId(state, id)
|
|
31
|
+
: selectYAxisIdFromGraphicalItemId(state, id);
|
|
32
|
+
|
|
33
|
+
export const selectAxisWithScaleForGraphicalItem = (
|
|
34
|
+
state: RechartsRootState,
|
|
35
|
+
axisType: CartesianAxisType,
|
|
36
|
+
id: GraphicalItemId,
|
|
37
|
+
isPanorama: boolean,
|
|
38
|
+
): BaseAxisWithScale | undefined =>
|
|
39
|
+
selectAxisWithScale(state, axisType, axisIdForGraphicalItem(state, axisType, id), isPanorama);
|
|
40
|
+
|
|
41
|
+
export const selectTicksForGraphicalItem = (
|
|
42
|
+
state: RechartsRootState,
|
|
43
|
+
axisType: CartesianAxisType,
|
|
44
|
+
id: GraphicalItemId,
|
|
45
|
+
isPanorama: boolean,
|
|
46
|
+
): TickItem[] | undefined =>
|
|
47
|
+
selectTicksOfGraphicalItem(
|
|
48
|
+
state,
|
|
49
|
+
axisType,
|
|
50
|
+
axisIdForGraphicalItem(state, axisType, id),
|
|
51
|
+
isPanorama,
|
|
52
|
+
);
|
package/src/state/store.ts
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
// root store composes them — `state` mirrors the slice state proxies, `actions`
|
|
7
7
|
// namespaces the slice actions by slice name (symmetric with `state`).
|
|
8
8
|
//
|
|
9
|
-
// Grows as each slice lands (PORT_ORDER Tier 2 builds the core feature-vertically).
|
|
10
9
|
import { createChartDataSlice, type ChartDataActions, type ChartDataState } from "./chartDataSlice";
|
|
11
10
|
import {
|
|
12
11
|
createChartLayoutSlice,
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
// graphicalItemsSlice (SetTooltipEntrySettings is the sole caller and each
|
|
8
8
|
// graphical item registers exactly one entry, so the id is unique).
|
|
9
9
|
import { createStore } from "solid-js";
|
|
10
|
+
import { createCollectionActions } from "./createCollectionActions";
|
|
11
|
+
import { patched } from "./patched";
|
|
10
12
|
import { TooltipTrigger } from "../chart/types";
|
|
11
13
|
import type { NameType, Payload, ValueType } from "../component/DefaultTooltipContent";
|
|
12
14
|
import { CartesianViewBoxRequired, Coordinate, DataKey, PolarCoordinate } from "../util/types";
|
|
@@ -179,96 +181,121 @@ export function createTooltipSlice(initialState: TooltipState = initialTooltipSt
|
|
|
179
181
|
settings: { ...initialState.settings },
|
|
180
182
|
});
|
|
181
183
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
184
|
+
// Deviation: recharts matches `prev` by reference (`indexOf`), but a Solid store
|
|
185
|
+
// proxies stored objects so the raw `prev` never `===` the proxied element. The
|
|
186
|
+
// collection matches by `settings.graphicalItemId` instead — the same proxy-safe
|
|
187
|
+
// identity strategy as graphicalItemsSlice. Each graphical item registers exactly
|
|
188
|
+
// one entry, so the id is unique.
|
|
189
|
+
const entries = createCollectionActions<TooltipPayloadConfiguration>(
|
|
190
|
+
(updater) =>
|
|
189
191
|
setState((s) => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// same proxy-safe identity strategy as graphicalItemsSlice. Each
|
|
194
|
-
// graphical item registers exactly one entry, so the id is unique.
|
|
195
|
-
const index = s.tooltipItemPayloads.findIndex(
|
|
196
|
-
(p) => p.settings.graphicalItemId === prev.settings.graphicalItemId,
|
|
197
|
-
);
|
|
198
|
-
if (index > -1) {
|
|
199
|
-
const nextItems = s.tooltipItemPayloads.slice();
|
|
200
|
-
nextItems[index] = next;
|
|
201
|
-
s.tooltipItemPayloads = nextItems;
|
|
192
|
+
const next = updater(s.tooltipItemPayloads);
|
|
193
|
+
if (next !== s.tooltipItemPayloads) {
|
|
194
|
+
s.tooltipItemPayloads = next;
|
|
202
195
|
}
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
},
|
|
196
|
+
}),
|
|
197
|
+
(p) => p.settings.graphicalItemId,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const actions: TooltipActions = {
|
|
201
|
+
addTooltipEntrySettings: entries.add,
|
|
202
|
+
replaceTooltipEntrySettings: entries.replace,
|
|
203
|
+
removeTooltipEntrySettings: entries.remove,
|
|
212
204
|
setTooltipSettingsState(payload) {
|
|
213
205
|
setState((s) => {
|
|
214
206
|
s.settings = payload;
|
|
215
207
|
});
|
|
216
208
|
},
|
|
217
209
|
setActiveMouseOverItemIndex(payload) {
|
|
210
|
+
// Slice immutability contract (ADR-0002): replace each written interaction
|
|
211
|
+
// node so `state.tooltip.<node>` yields a new reference and the selector
|
|
212
|
+
// graph invalidates by input-reference comparison. In-place leaf writes
|
|
213
|
+
// keep the node reference stable, so reference-keyed selectors would never
|
|
214
|
+
// recompute — see the store-proxy-reference-identity memory.
|
|
218
215
|
setState((s) => {
|
|
219
|
-
s.syncInteraction
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
s.
|
|
224
|
-
s.itemInteraction
|
|
225
|
-
|
|
226
|
-
|
|
216
|
+
s.syncInteraction = patched(s.syncInteraction, {
|
|
217
|
+
active: false,
|
|
218
|
+
sourceViewBox: undefined,
|
|
219
|
+
});
|
|
220
|
+
s.keyboardInteraction = patched(s.keyboardInteraction, { active: false });
|
|
221
|
+
s.itemInteraction = patched(s.itemInteraction, {
|
|
222
|
+
hover: {
|
|
223
|
+
active: true,
|
|
224
|
+
index: payload.activeIndex,
|
|
225
|
+
dataKey: payload.activeDataKey,
|
|
226
|
+
graphicalItemId: payload.activeGraphicalItemId,
|
|
227
|
+
coordinate: payload.activeCoordinate,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
227
230
|
});
|
|
228
231
|
},
|
|
229
232
|
mouseLeaveChart() {
|
|
230
233
|
setState((s) => {
|
|
231
|
-
s.itemInteraction
|
|
232
|
-
|
|
234
|
+
s.itemInteraction = patched(s.itemInteraction, {
|
|
235
|
+
hover: patched(s.itemInteraction.hover, { active: false }),
|
|
236
|
+
});
|
|
237
|
+
s.axisInteraction = patched(s.axisInteraction, {
|
|
238
|
+
hover: patched(s.axisInteraction.hover, { active: false }),
|
|
239
|
+
});
|
|
233
240
|
});
|
|
234
241
|
},
|
|
235
242
|
mouseLeaveItem() {
|
|
236
243
|
setState((s) => {
|
|
237
|
-
s.itemInteraction
|
|
244
|
+
s.itemInteraction = patched(s.itemInteraction, {
|
|
245
|
+
hover: patched(s.itemInteraction.hover, { active: false }),
|
|
246
|
+
});
|
|
238
247
|
});
|
|
239
248
|
},
|
|
240
249
|
setActiveClickItemIndex(payload) {
|
|
241
250
|
setState((s) => {
|
|
242
|
-
s.syncInteraction
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
s.
|
|
247
|
-
s.itemInteraction
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
s.syncInteraction = patched(s.syncInteraction, {
|
|
252
|
+
active: false,
|
|
253
|
+
sourceViewBox: undefined,
|
|
254
|
+
});
|
|
255
|
+
s.keyboardInteraction = patched(s.keyboardInteraction, { active: false });
|
|
256
|
+
s.itemInteraction = patched(s.itemInteraction, {
|
|
257
|
+
click: {
|
|
258
|
+
active: true,
|
|
259
|
+
index: payload.activeIndex,
|
|
260
|
+
dataKey: payload.activeDataKey,
|
|
261
|
+
graphicalItemId: payload.activeGraphicalItemId,
|
|
262
|
+
coordinate: payload.activeCoordinate,
|
|
263
|
+
},
|
|
264
|
+
});
|
|
250
265
|
});
|
|
251
266
|
},
|
|
252
267
|
setMouseOverAxisIndex(payload) {
|
|
253
268
|
setState((s) => {
|
|
254
|
-
s.syncInteraction
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
s.
|
|
259
|
-
s.axisInteraction
|
|
260
|
-
|
|
269
|
+
s.syncInteraction = patched(s.syncInteraction, {
|
|
270
|
+
active: false,
|
|
271
|
+
sourceViewBox: undefined,
|
|
272
|
+
});
|
|
273
|
+
s.keyboardInteraction = patched(s.keyboardInteraction, { active: false });
|
|
274
|
+
s.axisInteraction = patched(s.axisInteraction, {
|
|
275
|
+
hover: patched(s.axisInteraction.hover, {
|
|
276
|
+
active: true,
|
|
277
|
+
index: payload.activeIndex,
|
|
278
|
+
dataKey: payload.activeDataKey,
|
|
279
|
+
coordinate: payload.activeCoordinate,
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
261
282
|
});
|
|
262
283
|
},
|
|
263
284
|
setMouseClickAxisIndex(payload) {
|
|
264
285
|
setState((s) => {
|
|
265
|
-
s.syncInteraction
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
s.
|
|
270
|
-
s.axisInteraction
|
|
271
|
-
|
|
286
|
+
s.syncInteraction = patched(s.syncInteraction, {
|
|
287
|
+
active: false,
|
|
288
|
+
sourceViewBox: undefined,
|
|
289
|
+
});
|
|
290
|
+
s.keyboardInteraction = patched(s.keyboardInteraction, { active: false });
|
|
291
|
+
s.axisInteraction = patched(s.axisInteraction, {
|
|
292
|
+
click: patched(s.axisInteraction.click, {
|
|
293
|
+
active: true,
|
|
294
|
+
index: payload.activeIndex,
|
|
295
|
+
dataKey: payload.activeDataKey,
|
|
296
|
+
coordinate: payload.activeCoordinate,
|
|
297
|
+
}),
|
|
298
|
+
});
|
|
272
299
|
});
|
|
273
300
|
},
|
|
274
301
|
setSyncInteraction(payload) {
|
|
@@ -278,9 +305,11 @@ export function createTooltipSlice(initialState: TooltipState = initialTooltipSt
|
|
|
278
305
|
},
|
|
279
306
|
setKeyboardInteraction(payload) {
|
|
280
307
|
setState((s) => {
|
|
281
|
-
s.keyboardInteraction
|
|
282
|
-
|
|
283
|
-
|
|
308
|
+
s.keyboardInteraction = patched(s.keyboardInteraction, {
|
|
309
|
+
active: payload.active,
|
|
310
|
+
index: payload.activeIndex,
|
|
311
|
+
coordinate: payload.activeCoordinate,
|
|
312
|
+
});
|
|
284
313
|
});
|
|
285
314
|
},
|
|
286
315
|
};
|
|
@@ -28,13 +28,6 @@ function mergeShapeProps<PropsType extends object>(
|
|
|
28
28
|
return { ...props, ...option };
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/** Extracts a shape option's props (object form); element form is N/A (no cloneElement). */
|
|
32
|
-
export function getPropsFromShapeOption<PropsType extends object>(
|
|
33
|
-
option: Partial<PropsType>,
|
|
34
|
-
): Partial<PropsType> {
|
|
35
|
-
return option;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
31
|
function getShapeIndex(shapeProps: object): string | number | undefined {
|
|
39
32
|
if (!("index" in shapeProps)) {
|
|
40
33
|
return undefined;
|
package/src/util/BarUtils.tsx
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Exports `BarRectangle`/`defaultBarShape` for background bars and custom shapes;
|
|
4
4
|
// `MinPointSize` + `minPointSizeCallback` for computeBarRectangles.
|
|
5
|
-
import
|
|
6
|
-
import { createMemo } from "solid-js";
|
|
5
|
+
import { createMemo, omit } from "solid-js";
|
|
7
6
|
import type { JSX } from "@solidjs/web";
|
|
8
7
|
import { Rectangle, type RectangleProps } from "../shape/Rectangle";
|
|
9
8
|
import type { BarShapeProps } from "../cartesian/Bar";
|
|
@@ -27,11 +26,13 @@ export type BarRectangleProps = Omit<BarShapeProps, "value" | "tooltipPosition"
|
|
|
27
26
|
type BarRectangleShapeProps = Omit<BarRectangleProps, "option">;
|
|
28
27
|
|
|
29
28
|
export function BarRectangle(props: BarRectangleProps): JSX.Element {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
// Snapshot of every prop except `option`. `omit` (not native
|
|
30
|
+
// `{ option, ...rest }`) is required because callers may pass a merged props
|
|
31
|
+
// proxy (e.g. `<BarRectangle {...rect} isActive={…} />`), whose rest-destructure
|
|
32
|
+
// fails to exclude `option` and leaks it to custom shape/background functions.
|
|
33
|
+
// Spreading into a plain object keeps the downstream <Shape> reads a static
|
|
34
|
+
// snapshot (no STRICT_READ), while the memo re-runs when any prop changes.
|
|
35
|
+
const shapeProps = createMemo((): BarRectangleShapeProps => ({ ...omit(props, "option") }));
|
|
35
36
|
return (
|
|
36
37
|
<Shape<BarRectangleShapeProps, SVGPathElement>
|
|
37
38
|
option={props.option}
|
|
@@ -56,19 +57,23 @@ export type MinPointSize = number | ((value: number | undefined | null, index: n
|
|
|
56
57
|
* @returns minPointSize
|
|
57
58
|
*/
|
|
58
59
|
export const minPointSizeCallback =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
// `_defaultValue` is part of the callback's signature but unreachable at runtime:
|
|
61
|
+
// the only branch that returned it now throws (see below), as upstream's
|
|
62
|
+
// tiny-invariant did. Kept positionally for API parity.
|
|
63
|
+
(minPointSize: MinPointSize, _defaultValue = 0) =>
|
|
64
|
+
(value: unknown, index: number): number => {
|
|
65
|
+
if (isNumber(minPointSize)) {
|
|
66
|
+
return minPointSize;
|
|
67
|
+
}
|
|
68
|
+
const isValueNumberOrNil = isNumber(value) || isNullish(value);
|
|
69
|
+
if (isValueNumberOrNil) {
|
|
70
|
+
return minPointSize(value, index);
|
|
71
|
+
}
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
// Reached only when the value is neither a number nor nil; upstream asserts
|
|
74
|
+
// this via tiny-invariant, which always throws here — a plain throw is
|
|
75
|
+
// behavior-equivalent and drops the dependency.
|
|
76
|
+
throw new Error(
|
|
77
|
+
`minPointSize callback function received a value with type of ${typeof value}. Currently only numbers or null/undefined are supported.`,
|
|
78
|
+
);
|
|
79
|
+
};
|