@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,134 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import type { JSX } from '@solidjs/web';
|
|
3
|
+
import { isPercent } from "../util/DataUtils"
|
|
4
|
+
|
|
5
|
+
import type { Percent } from "../util/types"
|
|
6
|
+
import type { Props } from "./ResponsiveContainer"
|
|
7
|
+
|
|
8
|
+
export const defaultResponsiveContainerProps = {
|
|
9
|
+
debounce: 0,
|
|
10
|
+
height: "100%",
|
|
11
|
+
initialDimension: {
|
|
12
|
+
height: -1,
|
|
13
|
+
width: -1,
|
|
14
|
+
},
|
|
15
|
+
minWidth: 0,
|
|
16
|
+
width: "100%",
|
|
17
|
+
} as const satisfies Partial<Props>
|
|
18
|
+
|
|
19
|
+
export const calculateChartDimensions = (
|
|
20
|
+
containerWidth: number | undefined,
|
|
21
|
+
containerHeight: number | undefined,
|
|
22
|
+
props: {
|
|
23
|
+
aspect: number | undefined
|
|
24
|
+
height: Percent | number | undefined
|
|
25
|
+
maxHeight: number | undefined
|
|
26
|
+
width: Percent | number | undefined
|
|
27
|
+
},
|
|
28
|
+
) => {
|
|
29
|
+
const {
|
|
30
|
+
width = defaultResponsiveContainerProps.width,
|
|
31
|
+
height = defaultResponsiveContainerProps.height,
|
|
32
|
+
aspect,
|
|
33
|
+
maxHeight,
|
|
34
|
+
} = props
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
* The containerWidth and containerHeight are already percentage based because it's set as that percentage in CSS.
|
|
38
|
+
* Means we don't have to calculate percentages here.
|
|
39
|
+
*/
|
|
40
|
+
let calculatedWidth: number | undefined = isPercent(width) ? containerWidth : Number(width)
|
|
41
|
+
let calculatedHeight: number | undefined = isPercent(height) ? containerHeight : Number(height)
|
|
42
|
+
|
|
43
|
+
if (aspect && aspect > 0) {
|
|
44
|
+
/* Preserve the desired aspect ratio */
|
|
45
|
+
if (calculatedWidth) {
|
|
46
|
+
/* Will default to using width for aspect ratio */
|
|
47
|
+
calculatedHeight = calculatedWidth / aspect
|
|
48
|
+
} else if (calculatedHeight) {
|
|
49
|
+
/* But we should also take height into consideration */
|
|
50
|
+
calculatedWidth = calculatedHeight * aspect
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* if maxHeight is set, overwrite if calculatedHeight is greater than maxHeight */
|
|
54
|
+
if (maxHeight && calculatedHeight != null && calculatedHeight > maxHeight) {
|
|
55
|
+
calculatedHeight = maxHeight
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { calculatedHeight, calculatedWidth }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const bothOverflow: JSX.CSSProperties = {
|
|
63
|
+
height: 0,
|
|
64
|
+
overflow: "visible",
|
|
65
|
+
width: 0,
|
|
66
|
+
}
|
|
67
|
+
const overflowX: JSX.CSSProperties = {
|
|
68
|
+
overflowX: "visible",
|
|
69
|
+
width: 0,
|
|
70
|
+
} as JSX.CSSProperties
|
|
71
|
+
const overflowY: JSX.CSSProperties = {
|
|
72
|
+
height: 0,
|
|
73
|
+
overflowY: "visible",
|
|
74
|
+
} as JSX.CSSProperties
|
|
75
|
+
const noStyle: JSX.CSSProperties = {}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* This zero-size, overflow-visible is required to allow the chart to shrink.
|
|
79
|
+
* Without it, the chart itself will fill the ResponsiveContainer, and while it allows the chart to grow,
|
|
80
|
+
* it would always keep the container at the size of the chart,
|
|
81
|
+
* and ResizeObserver would never fire.
|
|
82
|
+
* With this zero-size element, the chart itself never actually fills the container,
|
|
83
|
+
* it just so happens that it is visible because it overflows.
|
|
84
|
+
* I learned this trick from the `react-virtualized` library: https://github.com/bvaughn/react-virtualized-auto-sizer/blob/master/src/AutoSizer.ts
|
|
85
|
+
* See https://github.com/recharts/recharts/issues/172 and also https://github.com/bvaughn/react-virtualized/issues/68
|
|
86
|
+
*
|
|
87
|
+
* Also, we don't need to apply the zero-size style if the dimension is a fixed number (or undefined),
|
|
88
|
+
* because in that case the chart can't shrink in that dimension anyway.
|
|
89
|
+
* This fixes defining the dimensions using aspect ratio: https://github.com/recharts/recharts/issues/6245
|
|
90
|
+
*/
|
|
91
|
+
export const getInnerDivStyle = (props: {
|
|
92
|
+
height?: Percent | number
|
|
93
|
+
width?: Percent | number
|
|
94
|
+
}): JSX.CSSProperties => {
|
|
95
|
+
/* eslint-disable-next-line solid/reactivity -- plain object, not a Solid props proxy */
|
|
96
|
+
const { width, height } = props
|
|
97
|
+
const isWidthPercent = isPercent(width)
|
|
98
|
+
const isHeightPercent = isPercent(height)
|
|
99
|
+
|
|
100
|
+
if (isWidthPercent && isHeightPercent) {
|
|
101
|
+
return bothOverflow
|
|
102
|
+
}
|
|
103
|
+
if (isWidthPercent) {
|
|
104
|
+
return overflowX
|
|
105
|
+
}
|
|
106
|
+
if (isHeightPercent) {
|
|
107
|
+
return overflowY
|
|
108
|
+
}
|
|
109
|
+
return noStyle
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getDefaultWidthAndHeight({
|
|
113
|
+
width,
|
|
114
|
+
height,
|
|
115
|
+
aspect,
|
|
116
|
+
}: {
|
|
117
|
+
aspect: number | undefined
|
|
118
|
+
height: Percent | number | undefined
|
|
119
|
+
width: Percent | number | undefined
|
|
120
|
+
}): { height: Percent | number | undefined; width: Percent | number | undefined } {
|
|
121
|
+
let calculatedWidth = width
|
|
122
|
+
let calculatedHeight = height
|
|
123
|
+
|
|
124
|
+
if (calculatedWidth === undefined && calculatedHeight === undefined) {
|
|
125
|
+
calculatedWidth = defaultResponsiveContainerProps.width
|
|
126
|
+
calculatedHeight = defaultResponsiveContainerProps.height
|
|
127
|
+
} else if (calculatedWidth === undefined) {
|
|
128
|
+
calculatedWidth = aspect && aspect > 0 ? undefined : defaultResponsiveContainerProps.width
|
|
129
|
+
} else if (calculatedHeight === undefined) {
|
|
130
|
+
calculatedHeight = aspect && aspect > 0 ? undefined : defaultResponsiveContainerProps.height
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return { height: calculatedHeight, width: calculatedWidth }
|
|
134
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { createContext, Show, useContext } from 'solid-js';
|
|
3
|
+
import type { JSX } from '@solidjs/web';
|
|
4
|
+
import { uniqueId } from "../util/DataUtils"
|
|
5
|
+
import { useChartStore } from "../state/RechartsStoreContext"
|
|
6
|
+
import { selectPlotArea } from "../state/selectors/selectPlotArea"
|
|
7
|
+
|
|
8
|
+
const ClipPathIdContext = createContext<string | null>(null)
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generates a unique clip path ID for use in SVG elements,
|
|
12
|
+
* and puts it in a context provider.
|
|
13
|
+
*
|
|
14
|
+
* To read the clip path ID, use the `useClipPathId` hook,
|
|
15
|
+
* or render `<ClipPath>` component which will automatically use the ID from this context.
|
|
16
|
+
*
|
|
17
|
+
* @param props children - children to be wrapped by the provider
|
|
18
|
+
* @returns Context Provider
|
|
19
|
+
*/
|
|
20
|
+
export function ClipPathProvider(props: { children: JSX.Element }) {
|
|
21
|
+
const clipPathId = `${uniqueId("recharts")}-clip`
|
|
22
|
+
const ctx = useChartStore()
|
|
23
|
+
const plotArea = () => (ctx ? selectPlotArea(ctx.store) : undefined)
|
|
24
|
+
|
|
25
|
+
/* Show's render-fn child re-fires on every truthy `when` value change —
|
|
26
|
+
* meaning the entire body, including `{props.children}`, gets re-instantiated
|
|
27
|
+
* each time `plotArea()` returns a new reference. With the Solid props proxy
|
|
28
|
+
* for children, that re-instantiates user JSX (and every Bar/Funnel inside)
|
|
29
|
+
* on every chart-offset reactive cycle. The cleanup of those children fires
|
|
30
|
+
* `removeZIndexLayer` / `removeGraphicalItem` etc., which invalidates
|
|
31
|
+
* selectors that feed back into selectPlotArea — tight loop, OOM. Always
|
|
32
|
+
* render the Provider + children; gate only the inline <defs> on plotArea. */
|
|
33
|
+
return (
|
|
34
|
+
<ClipPathIdContext value={clipPathId}>
|
|
35
|
+
<Show when={plotArea()}>
|
|
36
|
+
{(area) => (
|
|
37
|
+
<defs>
|
|
38
|
+
<clipPath id={clipPathId}>
|
|
39
|
+
<rect x={area().x} y={area().y} height={area().height} width={area().width} />
|
|
40
|
+
</clipPath>
|
|
41
|
+
</defs>
|
|
42
|
+
)}
|
|
43
|
+
</Show>
|
|
44
|
+
{props.children}
|
|
45
|
+
</ClipPathIdContext>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const useClipPathId = (): string | null => {
|
|
50
|
+
return useContext(ClipPathIdContext)
|
|
51
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { JSX } from '@solidjs/web';
|
|
2
|
+
import type { WithoutRemoveFalse } from "../util/types"
|
|
3
|
+
import { untrack } from "solid-js"
|
|
4
|
+
import { clsx } from "clsx"
|
|
5
|
+
import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
|
|
6
|
+
|
|
7
|
+
import { bindRef, splitProps } from '../util/solid-1-compat';
|
|
8
|
+
interface LayerProps {
|
|
9
|
+
class?: string
|
|
10
|
+
children?: JSX.Element
|
|
11
|
+
ref?: SVGGElement | ((el: SVGGElement) => void)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type Props = WithoutRemoveFalse<JSX.SvgSVGAttributes<SVGGElement>> & LayerProps
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates an SVG group element to group other SVG elements.
|
|
18
|
+
*
|
|
19
|
+
* Useful if you want to apply transformations or styles to a set of elements
|
|
20
|
+
* without affecting other elements in the SVG.
|
|
21
|
+
*
|
|
22
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/g
|
|
23
|
+
*/
|
|
24
|
+
export function Layer(props: Props) {
|
|
25
|
+
const [local, others] = splitProps(props, ["children", "class", "ref"])
|
|
26
|
+
const layerClass = () => clsx("recharts-layer", local.class)
|
|
27
|
+
const svgRest = () => svgPropertiesAndEvents(others)
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<g
|
|
31
|
+
class={layerClass()}
|
|
32
|
+
{...svgRest()}
|
|
33
|
+
ref={(el) => untrack(() => bindRef(local.ref, el))}
|
|
34
|
+
>
|
|
35
|
+
{local.children}
|
|
36
|
+
</g>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import type { JSX } from '@solidjs/web';
|
|
3
|
+
import { createMemo, Show } from 'solid-js';
|
|
4
|
+
import { useChartHeight, useChartWidth } from "../context/chartLayoutContext"
|
|
5
|
+
import { useAccessibilityLayer } from "../context/accessibilityContext"
|
|
6
|
+
import { useIsPanorama } from "../context/PanoramaContext"
|
|
7
|
+
import { Surface } from "./Surface"
|
|
8
|
+
import { useChartStore } from "../state/RechartsStoreContext"
|
|
9
|
+
import { selectBrushDimensions } from "../state/selectors/brushSelectors"
|
|
10
|
+
import { isPositiveNumber } from "../util/isWellBehavedNumber"
|
|
11
|
+
import { AllZIndexPortals } from "../zIndex/ZIndexPortal"
|
|
12
|
+
import { bindRef } from "../util/solid-1-compat"
|
|
13
|
+
|
|
14
|
+
type RootSurfaceProps = {
|
|
15
|
+
children: JSX.Element
|
|
16
|
+
title: string | undefined
|
|
17
|
+
desc: string | undefined
|
|
18
|
+
otherAttributes: Record<string, unknown> | null
|
|
19
|
+
ref?: SVGSVGElement | ((el: SVGSVGElement) => void)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const FULL_WIDTH_AND_HEIGHT = {
|
|
23
|
+
display: "block",
|
|
24
|
+
height: "100%",
|
|
25
|
+
/*
|
|
26
|
+
* display: block is necessary here because the default for an SVG is display: inline,
|
|
27
|
+
* which in some browsers (Chrome) adds a little bit of extra space above and below the SVG
|
|
28
|
+
* to make space for the descender of letters like "g" and "y". This throws off the height calculation
|
|
29
|
+
* and causes the container to grow indefinitely on each render with responsive=true.
|
|
30
|
+
* Display: block removes that extra space.
|
|
31
|
+
*
|
|
32
|
+
* Interestingly, Firefox does not have this problem, but it doesn't hurt to add the style anyway.
|
|
33
|
+
*/
|
|
34
|
+
width: "100%",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function MainChartSurface(props: RootSurfaceProps) {
|
|
38
|
+
const width = createMemo(() => useChartWidth())
|
|
39
|
+
const height = createMemo(() => useChartHeight())
|
|
40
|
+
const hasAccessibilityLayer = createMemo(() => useAccessibilityLayer())
|
|
41
|
+
|
|
42
|
+
const tabIndex = (): number | undefined => {
|
|
43
|
+
if (props.otherAttributes != null) {
|
|
44
|
+
if (typeof props.otherAttributes.tabIndex === "number") {
|
|
45
|
+
return props.otherAttributes.tabIndex
|
|
46
|
+
}
|
|
47
|
+
return hasAccessibilityLayer() ? 0 : undefined
|
|
48
|
+
}
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const role = (): JSX.HTMLAttributes<HTMLElement>["role"] => {
|
|
53
|
+
if (props.otherAttributes != null) {
|
|
54
|
+
if (typeof props.otherAttributes.role === "string") {
|
|
55
|
+
return props.otherAttributes.role as JSX.HTMLAttributes<HTMLElement>["role"]
|
|
56
|
+
}
|
|
57
|
+
return hasAccessibilityLayer() ? "application" : undefined
|
|
58
|
+
}
|
|
59
|
+
return undefined
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const ready = createMemo(() => isPositiveNumber(width()) && isPositiveNumber(height()))
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Show when={ready()}>
|
|
66
|
+
<Surface
|
|
67
|
+
{...props.otherAttributes}
|
|
68
|
+
title={props.title}
|
|
69
|
+
desc={props.desc}
|
|
70
|
+
role={role()}
|
|
71
|
+
tabindex={tabIndex()}
|
|
72
|
+
width={width() ?? 0}
|
|
73
|
+
height={height() ?? 0}
|
|
74
|
+
style={FULL_WIDTH_AND_HEIGHT}
|
|
75
|
+
ref={(el) => bindRef(props.ref, el)}
|
|
76
|
+
>
|
|
77
|
+
{props.children}
|
|
78
|
+
</Surface>
|
|
79
|
+
</Show>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function BrushPanoramaSurface(props: { children: JSX.Element }) {
|
|
84
|
+
const ctx = useChartStore()
|
|
85
|
+
const brushDimensions = () => (ctx ? selectBrushDimensions(ctx.store) : undefined)
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<Show when={brushDimensions()}>
|
|
89
|
+
{(dims) => (
|
|
90
|
+
<Surface width={dims().width} height={dims().height} x={dims().x} y={dims().y}>
|
|
91
|
+
{props.children}
|
|
92
|
+
</Surface>
|
|
93
|
+
)}
|
|
94
|
+
</Show>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function RootSurface(props: RootSurfaceProps) {
|
|
99
|
+
const isPanorama = useIsPanorama()
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<Show
|
|
103
|
+
when={isPanorama === false}
|
|
104
|
+
fallback={
|
|
105
|
+
<BrushPanoramaSurface>
|
|
106
|
+
<AllZIndexPortals isPanorama>{props.children}</AllZIndexPortals>
|
|
107
|
+
</BrushPanoramaSurface>
|
|
108
|
+
}
|
|
109
|
+
>
|
|
110
|
+
<MainChartSurface
|
|
111
|
+
ref={(el) => bindRef(props.ref, el)}
|
|
112
|
+
title={props.title}
|
|
113
|
+
desc={props.desc}
|
|
114
|
+
otherAttributes={props.otherAttributes}
|
|
115
|
+
>
|
|
116
|
+
<AllZIndexPortals isPanorama={false}>{props.children}</AllZIndexPortals>
|
|
117
|
+
</MainChartSurface>
|
|
118
|
+
</Show>
|
|
119
|
+
)
|
|
120
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { JSX } from '@solidjs/web';
|
|
2
|
+
import { untrack } from "solid-js"
|
|
3
|
+
import { clsx } from "clsx"
|
|
4
|
+
import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
|
|
5
|
+
import type { CartesianViewBox } from "../util/types"
|
|
6
|
+
|
|
7
|
+
import { bindRef, splitProps } from '../util/solid-1-compat';
|
|
8
|
+
interface SurfaceProps {
|
|
9
|
+
width: number | string
|
|
10
|
+
height: number | string
|
|
11
|
+
viewBox?: CartesianViewBox
|
|
12
|
+
class?: string
|
|
13
|
+
style?: JSX.CSSProperties
|
|
14
|
+
children?: JSX.Element
|
|
15
|
+
title?: string
|
|
16
|
+
desc?: string
|
|
17
|
+
ref?: SVGSVGElement | ((el: SVGSVGElement) => void)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type Props = Omit<JSX.SvgSVGAttributes<SVGSVGElement>, "viewBox"> & SurfaceProps
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Renders an SVG element.
|
|
24
|
+
*
|
|
25
|
+
* All charts already include a Surface component, so you would not normally use this directly.
|
|
26
|
+
*
|
|
27
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg
|
|
28
|
+
*/
|
|
29
|
+
export function Surface(props: Props) {
|
|
30
|
+
const [local, others] = splitProps(props, [
|
|
31
|
+
"children",
|
|
32
|
+
"class",
|
|
33
|
+
"desc",
|
|
34
|
+
"height",
|
|
35
|
+
"ref",
|
|
36
|
+
"style",
|
|
37
|
+
"title",
|
|
38
|
+
"viewBox",
|
|
39
|
+
"width",
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
const svgView = () => local.viewBox || { height: local.height, width: local.width, x: 0, y: 0 }
|
|
43
|
+
const layerClass = () => clsx("recharts-surface", local.class)
|
|
44
|
+
const svgRest = () => svgPropertiesAndEvents(others)
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<svg
|
|
48
|
+
{...svgRest()}
|
|
49
|
+
class={layerClass()}
|
|
50
|
+
width={local.width}
|
|
51
|
+
height={local.height}
|
|
52
|
+
style={local.style}
|
|
53
|
+
viewBox={`${svgView().x} ${svgView().y} ${svgView().width} ${svgView().height}`}
|
|
54
|
+
ref={(el) => untrack(() => bindRef(props.ref, el))}
|
|
55
|
+
>
|
|
56
|
+
<title>{local.title}</title>
|
|
57
|
+
<desc>{local.desc}</desc>
|
|
58
|
+
{local.children}
|
|
59
|
+
</svg>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle, sort-keys */
|
|
2
|
+
import { createContext, createSignal, onCleanup, useContext } from 'solid-js';
|
|
3
|
+
/* React parity: upstream walks `props.children` via `findAllByType(Cell)` to
|
|
4
|
+
* discover per-data-point overrides (fill, stroke, ...). Solid JSX is opaque —
|
|
5
|
+
* descendants resolve to DOM nodes, not vnodes — so introspection is impossible.
|
|
6
|
+
* Instead, <Cell/> calls `register()` at setup time to hand its props up; the
|
|
7
|
+
* graphical-item parent (Bar/Pie/Scatter/...) reads `cells()` to get an
|
|
8
|
+
* insertion-ordered array shaped like upstream's findAllByType result. */
|
|
9
|
+
|
|
10
|
+
export type CellPropsRecord = Record<string, unknown>
|
|
11
|
+
|
|
12
|
+
/* Upstream code reads `cells[i].props` — keep that wrapper shape so existing
|
|
13
|
+
* computeBarRectangles / Pie / Scatter logic spreads `(cells[i] as { props }).props`
|
|
14
|
+
* unchanged. */
|
|
15
|
+
export type RegisteredCell = { props: CellPropsRecord }
|
|
16
|
+
|
|
17
|
+
export type CellsRegistry = {
|
|
18
|
+
register: (props: () => CellPropsRecord) => void
|
|
19
|
+
cells: () => ReadonlyArray<RegisteredCell>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const CellsContext = createContext<CellsRegistry | null>(null)
|
|
23
|
+
|
|
24
|
+
/* Each Cell entry stores the prop accessor — re-reading at consumer time keeps
|
|
25
|
+
* fill/stroke reactive to upstream signal changes (e.g. row.visitors > 0
|
|
26
|
+
* branch flipping in BarNegative). */
|
|
27
|
+
type Entry = { id: number; getProps: () => CellPropsRecord }
|
|
28
|
+
|
|
29
|
+
export function createCellsRegistry(): CellsRegistry & {
|
|
30
|
+
Provider: typeof CellsContext
|
|
31
|
+
} {
|
|
32
|
+
/* Cells register from their component body, so this registry opts into owned writes. */
|
|
33
|
+
const [entries, setEntries] = createSignal<ReadonlyArray<Entry>>([], { ownedWrite: true })
|
|
34
|
+
let nextId = 0
|
|
35
|
+
|
|
36
|
+
const register = (getProps: () => CellPropsRecord): void => {
|
|
37
|
+
const id = nextId++
|
|
38
|
+
setEntries((prev) => [...prev, { id, getProps }])
|
|
39
|
+
onCleanup(() => {
|
|
40
|
+
setEntries((prev) => prev.filter((e) => e.id !== id))
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const cells = (): ReadonlyArray<RegisteredCell> =>
|
|
45
|
+
entries().map((e) => ({ props: e.getProps() }))
|
|
46
|
+
|
|
47
|
+
return { register, cells, Provider: CellsContext }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function useCellsRegistry(): CellsRegistry | null {
|
|
51
|
+
return useContext(CellsContext)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const CellsContextProvider = CellsContext
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { createContext, createEffect, onCleanup, untrack, useContext } from 'solid-js';
|
|
2
|
+
import type { Accessor } from 'solid-js';
|
|
3
|
+
import type { JSX } from '@solidjs/web';
|
|
4
|
+
import type { ErrorBarsState } from "../state/errorBarSlice"
|
|
5
|
+
import type { AxisId } from "../state/cartesianAxisSlice"
|
|
6
|
+
import type {
|
|
7
|
+
ErrorBarDataItem,
|
|
8
|
+
ErrorBarDataPointFormatter,
|
|
9
|
+
ErrorBarDirection,
|
|
10
|
+
} from "../cartesian/ErrorBar"
|
|
11
|
+
import type { ErrorBarsSettings } from "../state/errorBarSlice"
|
|
12
|
+
import { useChartStore } from "../state/RechartsStoreContext"
|
|
13
|
+
import { useGraphicalItemId } from "./RegisterGraphicalItemId"
|
|
14
|
+
import type { BarRectangleItem } from "../cartesian/Bar"
|
|
15
|
+
import type { LinePointItem } from "../cartesian/Line"
|
|
16
|
+
import type { ScatterPointItem } from "../cartesian/Scatter"
|
|
17
|
+
import type { DataKey } from "../util/types"
|
|
18
|
+
import { isSameStoreEntry } from "../state/storeIdentity"
|
|
19
|
+
import { teardownWrite } from "../state/teardownWrite"
|
|
20
|
+
|
|
21
|
+
type ErrorBarItemType = BarRectangleItem | LinePointItem | ScatterPointItem
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A type-erased formatter that the context stores.
|
|
25
|
+
* The entry parameter uses the union so consumers can call it with any item type.
|
|
26
|
+
*/
|
|
27
|
+
type ErasedErrorBarFormatter = (
|
|
28
|
+
entry: ErrorBarItemType,
|
|
29
|
+
dataKey: DataKey<ErrorBarItemType, number[] | number>,
|
|
30
|
+
direction: ErrorBarDirection,
|
|
31
|
+
) => ErrorBarDataItem
|
|
32
|
+
|
|
33
|
+
type ErrorBarContextType = {
|
|
34
|
+
data: ReadonlyArray<unknown> | undefined
|
|
35
|
+
dataPointFormatter: ErasedErrorBarFormatter
|
|
36
|
+
errorBarOffset: number
|
|
37
|
+
xAxisId: AxisId
|
|
38
|
+
yAxisId: AxisId
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const initialContextState: ErrorBarContextType = {
|
|
42
|
+
data: [],
|
|
43
|
+
dataPointFormatter: () => ({ value: 0, x: 0, y: 0 }),
|
|
44
|
+
errorBarOffset: 0,
|
|
45
|
+
xAxisId: "xAxis-0",
|
|
46
|
+
yAxisId: "yAxis-0",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Provider value is an Accessor (GOTCHA-005-A) — Solid context returns a static
|
|
50
|
+
read at consume time, so wrapping the value in `() => ...` lets ErrorBarImpl
|
|
51
|
+
re-evaluate `ctx().data` reactively as `rects()` populates. */
|
|
52
|
+
const initialContextAccessor: Accessor<ErrorBarContextType> = () => initialContextState
|
|
53
|
+
|
|
54
|
+
const ErrorBarContext = createContext<Accessor<ErrorBarContextType>>(initialContextAccessor)
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Wraps a specifically-typed formatter into the erased context formatter type.
|
|
58
|
+
* This is safe because at runtime, each provider only passes entries
|
|
59
|
+
* of the correct type for its formatter.
|
|
60
|
+
*/
|
|
61
|
+
function eraseFormatter<T extends ErrorBarItemType>(
|
|
62
|
+
formatter: ErrorBarDataPointFormatter<T>,
|
|
63
|
+
): ErasedErrorBarFormatter {
|
|
64
|
+
return (entry, dataKey, direction) =>
|
|
65
|
+
formatter(entry as T, dataKey as DataKey<T, number[] | number>, direction)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type SetErrorBarContextProps<T extends ErrorBarItemType> = {
|
|
69
|
+
data: ReadonlyArray<unknown> | undefined
|
|
70
|
+
dataPointFormatter: ErrorBarDataPointFormatter<T>
|
|
71
|
+
errorBarOffset: number
|
|
72
|
+
xAxisId: AxisId
|
|
73
|
+
yAxisId: AxisId
|
|
74
|
+
children: JSX.Element
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function SetErrorBarContext<T extends ErrorBarItemType>(props: SetErrorBarContextProps<T>) {
|
|
78
|
+
/* Pass the Accessor itself (not its value) so consumers re-evaluate as
|
|
79
|
+
`props.data` populates downstream — Solid's createContext returns a single
|
|
80
|
+
read at useContext time, the Accessor wraps the live value. */
|
|
81
|
+
const value: Accessor<ErrorBarContextType> = () => ({
|
|
82
|
+
data: props.data,
|
|
83
|
+
dataPointFormatter: eraseFormatter(props.dataPointFormatter),
|
|
84
|
+
errorBarOffset: props.errorBarOffset,
|
|
85
|
+
xAxisId: props.xAxisId,
|
|
86
|
+
yAxisId: props.yAxisId,
|
|
87
|
+
})
|
|
88
|
+
return <ErrorBarContext value={value}>{props.children}</ErrorBarContext>
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const useErrorBarContext = (): Accessor<ErrorBarContextType> => useContext(ErrorBarContext)
|
|
92
|
+
|
|
93
|
+
export function ReportErrorBarSettings(props: ErrorBarsSettings): null {
|
|
94
|
+
const ctx = useChartStore()
|
|
95
|
+
const graphicalItemId = useGraphicalItemId()
|
|
96
|
+
let prevProps: ErrorBarsSettings | null = null
|
|
97
|
+
|
|
98
|
+
/* Track only dataKey/direction; setStore reads stay untracked so this
|
|
99
|
+
scope does not re-subscribe to state.errorBars[id] (would loop). */
|
|
100
|
+
createEffect(
|
|
101
|
+
() => ({ dataKey: props.dataKey, direction: props.direction }),
|
|
102
|
+
({ dataKey, direction }) => {
|
|
103
|
+
untrack(() => {
|
|
104
|
+
if (graphicalItemId == null) {
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
const next: ErrorBarsSettings = { dataKey, direction }
|
|
108
|
+
if (prevProps === null) {
|
|
109
|
+
ctx?.setStore("errorBars", (errorBars: ErrorBarsState) => {
|
|
110
|
+
const list = errorBars[graphicalItemId] ?? []
|
|
111
|
+
errorBars[graphicalItemId] = [...list, next]
|
|
112
|
+
})
|
|
113
|
+
} else {
|
|
114
|
+
const prev = prevProps
|
|
115
|
+
ctx?.setStore("errorBars", (errorBars: ErrorBarsState) => {
|
|
116
|
+
const list = errorBars[graphicalItemId]
|
|
117
|
+
if (list == null) return
|
|
118
|
+
errorBars[graphicalItemId] = list.map((e) => (isSameStoreEntry(e, prev) ? next : e))
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
prevProps = next
|
|
122
|
+
})
|
|
123
|
+
},
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
onCleanup(() => {
|
|
127
|
+
teardownWrite(() => {
|
|
128
|
+
if (prevProps != null && graphicalItemId != null) {
|
|
129
|
+
const toRemove = prevProps
|
|
130
|
+
ctx?.setStore(
|
|
131
|
+
"errorBars",
|
|
132
|
+
(errorBars: ErrorBarsState) => {
|
|
133
|
+
const list = errorBars[graphicalItemId]
|
|
134
|
+
if (list == null) return
|
|
135
|
+
errorBars[graphicalItemId] = list.filter(
|
|
136
|
+
(e: ErrorBarsSettings) => !isSameStoreEntry(e, toRemove),
|
|
137
|
+
)
|
|
138
|
+
},
|
|
139
|
+
)
|
|
140
|
+
prevProps = null
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
return null
|
|
146
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { children as resolveChildren } from 'solid-js';
|
|
2
|
+
import type { JSX } from '@solidjs/web';
|
|
3
|
+
/**
|
|
4
|
+
* Wraps user JSX (e.g. <ErrorBar/>) so that:
|
|
5
|
+
* - createComponent(ErrorBar, ...) fires exactly once,
|
|
6
|
+
* - that single invocation captures the current owner — which must include
|
|
7
|
+
* both RegisterGraphicalItemId.Provider AND SetErrorBarContext.Provider,
|
|
8
|
+
* - subsequent re-renders of the descendant tree read the memoized nodes
|
|
9
|
+
* instead of re-minting ErrorBar (which would loop the addErrorBar
|
|
10
|
+
* dispatch through the store-feedback cycle).
|
|
11
|
+
*
|
|
12
|
+
* MUST be rendered inside SetErrorBarContext.Provider and inside the
|
|
13
|
+
* RegisterGraphicalItemId children-fn scope. See GOTCHA-017.
|
|
14
|
+
*/
|
|
15
|
+
export function GraphicalItemChildrenScope(props: { children: JSX.Element }): JSX.Element {
|
|
16
|
+
const resolved = resolveChildren(() => props.children)
|
|
17
|
+
return <>{resolved()}</>
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext, useContext } from 'solid-js';
|
|
2
|
+
import type { JSX } from '@solidjs/web';
|
|
3
|
+
const PanoramaContext = createContext<boolean | null>(null)
|
|
4
|
+
|
|
5
|
+
export const useIsPanorama = (): boolean => useContext(PanoramaContext) != null
|
|
6
|
+
|
|
7
|
+
export const PanoramaContextProvider = (props: { children: JSX.Element }) => (
|
|
8
|
+
<PanoramaContext value>{props.children}</PanoramaContext>
|
|
9
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createContext, useContext } from 'solid-js';
|
|
2
|
+
import type { JSX } from '@solidjs/web';
|
|
3
|
+
import { useUniqueId } from "../util/useUniqueId"
|
|
4
|
+
import type { GraphicalItemId } from "../state/graphicalItemsSlice"
|
|
5
|
+
|
|
6
|
+
export type IdSetter = {
|
|
7
|
+
/**
|
|
8
|
+
* Children must be a function that receives the resolved ID of the graphical item.
|
|
9
|
+
* This ID will either be the one provided via props.id or generated automatically.
|
|
10
|
+
*/
|
|
11
|
+
children: (id: GraphicalItemId) => JSX.Element
|
|
12
|
+
id?: string
|
|
13
|
+
type: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const GraphicalItemIdContext = createContext<GraphicalItemId | null>(null)
|
|
17
|
+
|
|
18
|
+
export const RegisterGraphicalItemId = (props: IdSetter) => {
|
|
19
|
+
/* eslint-disable-next-line solid/reactivity -- IDs are stable; useUniqueId calls useId() which must run at setup, not in a memo */
|
|
20
|
+
const resolvedId = useUniqueId(`recharts-${props.type}`, props.id)
|
|
21
|
+
return (
|
|
22
|
+
<GraphicalItemIdContext value={resolvedId}>
|
|
23
|
+
{props.children(resolvedId)}
|
|
24
|
+
</GraphicalItemIdContext>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function useGraphicalItemId(): GraphicalItemId | null {
|
|
29
|
+
return useContext(GraphicalItemIdContext)
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext } from 'solid-js';
|
|
2
|
+
export type BrushStartEndIndex = {
|
|
3
|
+
endIndex: number
|
|
4
|
+
startIndex: number
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type OnBrushUpdate = (newState: BrushStartEndIndex) => void
|
|
8
|
+
|
|
9
|
+
export const BrushUpdateDispatchContext = createContext<OnBrushUpdate>(() => {})
|