@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,95 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { TooltipIndex, TooltipInteractionState } from "../../tooltipSlice"
|
|
3
|
+
import { ChartData } from "../../chartDataSlice"
|
|
4
|
+
import { isWellBehavedNumber } from "../../../util/isWellBehavedNumber"
|
|
5
|
+
import { DataKey, CategoricalDomain, NumberDomain } from "../../../util/types"
|
|
6
|
+
import { getValueByDataKey } from "../../../util/ChartUtils"
|
|
7
|
+
import { isWellFormedNumberDomain } from "../../../util/isDomainSpecifiedByUser"
|
|
8
|
+
|
|
9
|
+
function toFiniteNumber(value: unknown): number | undefined {
|
|
10
|
+
if (typeof value === "number") {
|
|
11
|
+
return Number.isFinite(value) ? value : undefined
|
|
12
|
+
}
|
|
13
|
+
if (value instanceof Date) {
|
|
14
|
+
const numericValue = value.valueOf()
|
|
15
|
+
return Number.isFinite(numericValue) ? numericValue : undefined
|
|
16
|
+
}
|
|
17
|
+
const parsed = Number(value)
|
|
18
|
+
return Number.isFinite(parsed) ? parsed : undefined
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isValueWithinNumberDomain(value: unknown, domain: NumberDomain): boolean {
|
|
22
|
+
const numericValue = toFiniteNumber(value)
|
|
23
|
+
const lowerBound = domain[0]
|
|
24
|
+
const upperBound = domain[1]
|
|
25
|
+
|
|
26
|
+
if (numericValue === undefined) {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const min = Math.min(lowerBound, upperBound)
|
|
31
|
+
const max = Math.max(lowerBound, upperBound)
|
|
32
|
+
return numericValue >= min && numericValue <= max
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isValueWithinDomain(
|
|
36
|
+
entry: unknown,
|
|
37
|
+
axisDataKey: DataKey<unknown> | undefined,
|
|
38
|
+
domain: NumberDomain | CategoricalDomain | undefined,
|
|
39
|
+
): boolean {
|
|
40
|
+
if (domain == null || axisDataKey == null) {
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const value = getValueByDataKey(entry, axisDataKey)
|
|
45
|
+
if (value == null) {
|
|
46
|
+
return true
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!isWellFormedNumberDomain(domain)) {
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return isValueWithinNumberDomain(value, domain)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const combineActiveTooltipIndex = (
|
|
57
|
+
tooltipInteraction: TooltipInteractionState | undefined,
|
|
58
|
+
chartData: ChartData,
|
|
59
|
+
axisDataKey?: DataKey<unknown>,
|
|
60
|
+
domain?: NumberDomain | CategoricalDomain,
|
|
61
|
+
): TooltipIndex | null => {
|
|
62
|
+
const desiredIndex: TooltipIndex | undefined = tooltipInteraction?.index
|
|
63
|
+
if (desiredIndex == null) {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const indexAsNumber = Number(desiredIndex)
|
|
68
|
+
if (!isWellBehavedNumber(indexAsNumber)) {
|
|
69
|
+
return desiredIndex
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* Zero is a trivial limit for single-dimensional charts like Line and Area,
|
|
74
|
+
* but this also needs a support for multidimensional charts like Sankey and Treemap! TODO
|
|
75
|
+
*/
|
|
76
|
+
const lowerLimit = 0
|
|
77
|
+
let upperLimit: number = +Infinity
|
|
78
|
+
|
|
79
|
+
if (chartData.length > 0) {
|
|
80
|
+
upperLimit = chartData.length - 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const clampedIndex = Math.max(lowerLimit, Math.min(indexAsNumber, upperLimit))
|
|
84
|
+
const entry = chartData[clampedIndex]
|
|
85
|
+
|
|
86
|
+
if (entry == null) {
|
|
87
|
+
return String(clampedIndex)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!isValueWithinDomain(entry, axisDataKey, domain)) {
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return String(clampedIndex)
|
|
95
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { getPercentValue, isNullish } from "../../../util/DataUtils"
|
|
3
|
+
import { BarWithPosition, SizeList } from "../barSelectors"
|
|
4
|
+
import { isWellBehavedNumber } from "../../../util/isWellBehavedNumber"
|
|
5
|
+
import { BarPositionPosition } from "../../../util/ChartUtils"
|
|
6
|
+
import { BarCategory } from "./combineBarSizeList"
|
|
7
|
+
|
|
8
|
+
function getBarPositions(
|
|
9
|
+
barGap: string | number,
|
|
10
|
+
barCategoryGap: string | number,
|
|
11
|
+
bandSize: number,
|
|
12
|
+
sizeList: SizeList,
|
|
13
|
+
maxBarSize: number | undefined,
|
|
14
|
+
): ReadonlyArray<BarWithPosition> | undefined {
|
|
15
|
+
const len = sizeList.length
|
|
16
|
+
if (len < 1) {
|
|
17
|
+
return undefined
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let realBarGap = getPercentValue(barGap, bandSize, 0, true)
|
|
21
|
+
|
|
22
|
+
let result: ReadonlyArray<BarWithPosition>
|
|
23
|
+
const initialValue: ReadonlyArray<BarWithPosition> = []
|
|
24
|
+
|
|
25
|
+
// whether is barSize set by user
|
|
26
|
+
// Okay but why does it check only for the first element? What if the first element is set but others are not?
|
|
27
|
+
if (isWellBehavedNumber(sizeList[0]?.barSize)) {
|
|
28
|
+
let useFull = false
|
|
29
|
+
let fullBarSize: number = bandSize / len
|
|
30
|
+
let sum = sizeList.reduce((res, entry) => res + (entry.barSize || 0), 0)
|
|
31
|
+
sum += (len - 1) * realBarGap
|
|
32
|
+
|
|
33
|
+
if (sum >= bandSize) {
|
|
34
|
+
sum -= (len - 1) * realBarGap
|
|
35
|
+
realBarGap = 0
|
|
36
|
+
}
|
|
37
|
+
if (sum >= bandSize && fullBarSize > 0) {
|
|
38
|
+
useFull = true
|
|
39
|
+
fullBarSize *= 0.9
|
|
40
|
+
sum = len * fullBarSize
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const offset = Math.round((bandSize - sum) / 2)
|
|
44
|
+
let prev: BarPositionPosition = { offset: offset - realBarGap, size: 0 }
|
|
45
|
+
|
|
46
|
+
result = sizeList.reduce(
|
|
47
|
+
(res: ReadonlyArray<BarWithPosition>, entry: BarCategory): ReadonlyArray<BarWithPosition> => {
|
|
48
|
+
const newPosition: BarWithPosition = {
|
|
49
|
+
stackId: entry.stackId,
|
|
50
|
+
dataKeys: entry.dataKeys,
|
|
51
|
+
position: {
|
|
52
|
+
offset: prev.offset + prev.size + realBarGap,
|
|
53
|
+
size: useFull ? fullBarSize : (entry.barSize ?? 0),
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
const newRes: Array<BarWithPosition> = [...res, newPosition]
|
|
57
|
+
|
|
58
|
+
prev = newPosition.position
|
|
59
|
+
|
|
60
|
+
return newRes
|
|
61
|
+
},
|
|
62
|
+
initialValue,
|
|
63
|
+
)
|
|
64
|
+
} else {
|
|
65
|
+
const offset = getPercentValue(barCategoryGap, bandSize, 0, true)
|
|
66
|
+
|
|
67
|
+
if (bandSize - 2 * offset - (len - 1) * realBarGap <= 0) {
|
|
68
|
+
realBarGap = 0
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let originalSize = (bandSize - 2 * offset - (len - 1) * realBarGap) / len
|
|
72
|
+
if (originalSize > 1) {
|
|
73
|
+
originalSize = Math.round(originalSize)
|
|
74
|
+
}
|
|
75
|
+
const size = isWellBehavedNumber(maxBarSize) ? Math.min(originalSize, maxBarSize) : originalSize
|
|
76
|
+
result = sizeList.reduce(
|
|
77
|
+
(res: ReadonlyArray<BarWithPosition>, entry: BarCategory, i): ReadonlyArray<BarWithPosition> => [
|
|
78
|
+
...res,
|
|
79
|
+
{
|
|
80
|
+
stackId: entry.stackId,
|
|
81
|
+
dataKeys: entry.dataKeys,
|
|
82
|
+
position: {
|
|
83
|
+
offset: offset + (len * (originalSize - size)) / 2 + (size + realBarGap) * i,
|
|
84
|
+
size,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
initialValue,
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return result
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const combineAllBarPositions = (
|
|
96
|
+
sizeList: SizeList,
|
|
97
|
+
globalMaxBarSize: number | undefined,
|
|
98
|
+
barGap: string | number,
|
|
99
|
+
barCategoryGap: string | number,
|
|
100
|
+
barBandSize: number,
|
|
101
|
+
bandSize: number | undefined,
|
|
102
|
+
childMaxBarSize: number | undefined,
|
|
103
|
+
): ReadonlyArray<BarWithPosition> | undefined => {
|
|
104
|
+
const maxBarSize: number | undefined = isNullish(childMaxBarSize) ? globalMaxBarSize : childMaxBarSize
|
|
105
|
+
|
|
106
|
+
let allBarPositions: ReadonlyArray<BarWithPosition> | undefined = getBarPositions(
|
|
107
|
+
barGap,
|
|
108
|
+
barCategoryGap,
|
|
109
|
+
barBandSize !== bandSize ? barBandSize : bandSize,
|
|
110
|
+
sizeList,
|
|
111
|
+
maxBarSize,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if (barBandSize !== bandSize && allBarPositions != null) {
|
|
115
|
+
allBarPositions = allBarPositions.map(pos => ({
|
|
116
|
+
...pos,
|
|
117
|
+
position: { ...pos.position, offset: pos.position.offset - barBandSize / 2 },
|
|
118
|
+
}))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return allBarPositions
|
|
122
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { BaseCartesianAxis } from "../../cartesianAxisSlice"
|
|
3
|
+
import { AxisRange } from "../axisSelectors"
|
|
4
|
+
|
|
5
|
+
export const combineAxisRangeWithReverse = (
|
|
6
|
+
axisSettings: BaseCartesianAxis | undefined,
|
|
7
|
+
axisRange: AxisRange | undefined,
|
|
8
|
+
): AxisRange | undefined => {
|
|
9
|
+
if (!axisSettings || !axisRange) {
|
|
10
|
+
return undefined
|
|
11
|
+
}
|
|
12
|
+
if (axisSettings?.reversed) {
|
|
13
|
+
return [axisRange[1], axisRange[0]]
|
|
14
|
+
}
|
|
15
|
+
return axisRange
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { MaybeStackedGraphicalItem } from "../../types/StackedGraphicalItem"
|
|
3
|
+
import { BarPositionPosition } from "../../../util/ChartUtils"
|
|
4
|
+
import { BarWithPosition } from "../barSelectors"
|
|
5
|
+
|
|
6
|
+
export const combineBarPosition = (
|
|
7
|
+
allBarPositions: ReadonlyArray<BarWithPosition> | undefined,
|
|
8
|
+
barSettings: MaybeStackedGraphicalItem | undefined,
|
|
9
|
+
): BarPositionPosition | undefined => {
|
|
10
|
+
if (allBarPositions == null || barSettings == null) {
|
|
11
|
+
return undefined
|
|
12
|
+
}
|
|
13
|
+
const position = allBarPositions.find(
|
|
14
|
+
(p: BarWithPosition) =>
|
|
15
|
+
p.stackId === barSettings.stackId &&
|
|
16
|
+
barSettings.dataKey != null &&
|
|
17
|
+
p.dataKeys.includes(barSettings.dataKey),
|
|
18
|
+
)
|
|
19
|
+
if (position == null) {
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
return position.position
|
|
23
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import {
|
|
3
|
+
DefinitelyStackedGraphicalItem,
|
|
4
|
+
isStacked,
|
|
5
|
+
MaybeStackedGraphicalItem,
|
|
6
|
+
} from "../../types/StackedGraphicalItem"
|
|
7
|
+
import { StackId } from "../../../util/ChartUtils"
|
|
8
|
+
import { SizeList } from "../barSelectors"
|
|
9
|
+
import { getPercentValue, isNullish } from "../../../util/DataUtils"
|
|
10
|
+
import { DataKey } from "../../../util/types"
|
|
11
|
+
|
|
12
|
+
const getBarSize = (
|
|
13
|
+
globalSize: string | number | undefined,
|
|
14
|
+
totalSize: number | undefined,
|
|
15
|
+
selfSize: number | string | undefined,
|
|
16
|
+
): number | undefined => {
|
|
17
|
+
const barSize: string | number | undefined = selfSize ?? globalSize
|
|
18
|
+
|
|
19
|
+
if (isNullish(barSize)) {
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
return getPercentValue(barSize, totalSize, 0)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const combineBarSizeList = (
|
|
26
|
+
allBars: ReadonlyArray<MaybeStackedGraphicalItem>,
|
|
27
|
+
globalSize: string | number | undefined,
|
|
28
|
+
totalSize: number | undefined,
|
|
29
|
+
): SizeList => {
|
|
30
|
+
const initialValue: Record<StackId, Array<DefinitelyStackedGraphicalItem>> = {}
|
|
31
|
+
|
|
32
|
+
const stackedBars: ReadonlyArray<DefinitelyStackedGraphicalItem> = allBars.filter(isStacked)
|
|
33
|
+
const unstackedBars = allBars.filter((b) => b.stackId == null)
|
|
34
|
+
|
|
35
|
+
const groupByStack: Record<StackId, Array<DefinitelyStackedGraphicalItem>> = stackedBars.reduce(
|
|
36
|
+
(acc, bar) => {
|
|
37
|
+
let s = acc[bar.stackId]
|
|
38
|
+
if (s == null) {
|
|
39
|
+
s = []
|
|
40
|
+
}
|
|
41
|
+
s.push(bar)
|
|
42
|
+
acc[bar.stackId] = s
|
|
43
|
+
return acc
|
|
44
|
+
},
|
|
45
|
+
initialValue,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
const stackedSizeList: SizeList = Object.entries(groupByStack).map(
|
|
49
|
+
([stackId, bars]): BarCategory => {
|
|
50
|
+
const dataKeys = bars.map((b) => b.dataKey)
|
|
51
|
+
const barSize: number | undefined = getBarSize(globalSize, totalSize, bars[0]?.barSize)
|
|
52
|
+
return { barSize, dataKeys, stackId }
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
const unstackedSizeList: SizeList = unstackedBars.map((b): BarCategory => {
|
|
57
|
+
const dataKeys = [b.dataKey].filter((dk) => dk != null)
|
|
58
|
+
const barSize: number | undefined = getBarSize(globalSize, totalSize, b.barSize)
|
|
59
|
+
return { barSize, dataKeys, stackId: undefined }
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return [...stackedSizeList, ...unstackedSizeList]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type BarCategory = {
|
|
66
|
+
stackId: StackId | undefined
|
|
67
|
+
/**
|
|
68
|
+
* List of dataKeys of items stacked at this position.
|
|
69
|
+
* All of these Bars are either sharing the same stackId,
|
|
70
|
+
* or this is an array with one Bar because it has no stackId defined.
|
|
71
|
+
*
|
|
72
|
+
* This structure limits us to having one dataKey only once per stack which I think is reasonable.
|
|
73
|
+
* People who want to have the same data twice can duplicate their data to have two distinct dataKeys.
|
|
74
|
+
*/
|
|
75
|
+
dataKeys: ReadonlyArray<DataKey<unknown>>
|
|
76
|
+
/**
|
|
77
|
+
* Width (in horizontal chart) or height (in vertical chart) of this stack of items
|
|
78
|
+
*/
|
|
79
|
+
barSize: number | undefined
|
|
80
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { CategoricalDomain, NumberDomain } from "../../../util/types"
|
|
3
|
+
import { isWellFormedNumberDomain } from "../../../util/isDomainSpecifiedByUser"
|
|
4
|
+
import { isWellBehavedNumber } from "../../../util/isWellBehavedNumber"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This function validates and transforms the axis domain so that it is safe to use in the provided scale.
|
|
8
|
+
*/
|
|
9
|
+
export const combineCheckedDomain = (
|
|
10
|
+
realScaleType: string | undefined,
|
|
11
|
+
axisDomain: NumberDomain | CategoricalDomain | undefined,
|
|
12
|
+
): NumberDomain | CategoricalDomain | undefined => {
|
|
13
|
+
if (axisDomain == null) {
|
|
14
|
+
return undefined
|
|
15
|
+
}
|
|
16
|
+
switch (realScaleType) {
|
|
17
|
+
case "linear": {
|
|
18
|
+
/*
|
|
19
|
+
* linear scale only reads the first two numbers in the domain, and ignores everything else.
|
|
20
|
+
* So if it happens that someone somehow gave us a bigger domain,
|
|
21
|
+
* let's pick the min and max from it.
|
|
22
|
+
*/
|
|
23
|
+
if (!isWellFormedNumberDomain(axisDomain)) {
|
|
24
|
+
let min: number | undefined
|
|
25
|
+
let max: number | undefined
|
|
26
|
+
for (let i = 0; i < axisDomain.length; i++) {
|
|
27
|
+
const value = axisDomain[i]
|
|
28
|
+
if (!isWellBehavedNumber(value)) {
|
|
29
|
+
continue
|
|
30
|
+
}
|
|
31
|
+
if (min === undefined || value < min) {
|
|
32
|
+
min = value
|
|
33
|
+
}
|
|
34
|
+
if (max === undefined || value > max) {
|
|
35
|
+
max = value
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (min !== undefined && max !== undefined) {
|
|
39
|
+
return [min, max]
|
|
40
|
+
}
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
43
|
+
return axisDomain
|
|
44
|
+
}
|
|
45
|
+
default:
|
|
46
|
+
return axisDomain
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import * as d3Scales from "victory-vendor/d3-scale"
|
|
3
|
+
import { BaseCartesianAxis } from "../../cartesianAxisSlice"
|
|
4
|
+
import {
|
|
5
|
+
CategoricalDomain,
|
|
6
|
+
CategoricalDomainItem,
|
|
7
|
+
D3ScaleType,
|
|
8
|
+
NumberDomain,
|
|
9
|
+
} from "../../../util/types"
|
|
10
|
+
import { CustomScaleDefinition } from "../../../util/scale/CustomScaleDefinition"
|
|
11
|
+
import { AxisRange } from "../axisSelectors"
|
|
12
|
+
import { upperFirst } from "../../../util/DataUtils"
|
|
13
|
+
|
|
14
|
+
function lookupScale<Domain extends CategoricalDomainItem>(
|
|
15
|
+
key: string,
|
|
16
|
+
): (() => CustomScaleDefinition<Domain>) | undefined {
|
|
17
|
+
if (key in d3Scales) {
|
|
18
|
+
const val: unknown = (d3Scales as Record<string, unknown>)[key]
|
|
19
|
+
if (typeof val === "function") {
|
|
20
|
+
return val as () => CustomScaleDefinition<Domain>
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getD3ScaleFromType<Domain extends CategoricalDomainItem = CategoricalDomainItem>(
|
|
27
|
+
realScaleType: D3ScaleType,
|
|
28
|
+
): CustomScaleDefinition<Domain> | undefined {
|
|
29
|
+
const direct = lookupScale<Domain>(realScaleType)
|
|
30
|
+
if (direct != null) {
|
|
31
|
+
return direct()
|
|
32
|
+
}
|
|
33
|
+
const prefixed = lookupScale<Domain>(`scale${upperFirst(realScaleType)}`)
|
|
34
|
+
if (prefixed != null) {
|
|
35
|
+
return prefixed()
|
|
36
|
+
}
|
|
37
|
+
return undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Converts external scale definition into internal RechartsScale definition.
|
|
42
|
+
* @param scale custom function scale - if you have the `string` from outside, use `combineRealScaleType` first which will validate it and return D3ScaleType or undefined
|
|
43
|
+
* @param axisDomain
|
|
44
|
+
* @param axisRange
|
|
45
|
+
*/
|
|
46
|
+
export function combineConfiguredScaleInternal(
|
|
47
|
+
scale:
|
|
48
|
+
| CustomScaleDefinition
|
|
49
|
+
| CustomScaleDefinition<string>
|
|
50
|
+
| CustomScaleDefinition<number>
|
|
51
|
+
| CustomScaleDefinition<Date>,
|
|
52
|
+
axisDomain: ReadonlyArray<CategoricalDomainItem>,
|
|
53
|
+
axisRange: AxisRange,
|
|
54
|
+
): CustomScaleDefinition
|
|
55
|
+
export function combineConfiguredScaleInternal(
|
|
56
|
+
scale: D3ScaleType,
|
|
57
|
+
axisDomain: ReadonlyArray<CategoricalDomainItem>,
|
|
58
|
+
axisRange: AxisRange,
|
|
59
|
+
): CustomScaleDefinition
|
|
60
|
+
export function combineConfiguredScaleInternal(
|
|
61
|
+
scale: D3ScaleType | undefined,
|
|
62
|
+
axisDomain: ReadonlyArray<CategoricalDomainItem>,
|
|
63
|
+
axisRange: AxisRange,
|
|
64
|
+
): CustomScaleDefinition | undefined
|
|
65
|
+
export function combineConfiguredScaleInternal(
|
|
66
|
+
scale: undefined,
|
|
67
|
+
axisDomain: ReadonlyArray<CategoricalDomainItem>,
|
|
68
|
+
axisRange: AxisRange,
|
|
69
|
+
): undefined
|
|
70
|
+
export function combineConfiguredScaleInternal<
|
|
71
|
+
Domain extends CategoricalDomainItem = CategoricalDomainItem,
|
|
72
|
+
>(
|
|
73
|
+
scale: D3ScaleType | CustomScaleDefinition<Domain> | undefined,
|
|
74
|
+
axisDomain: ReadonlyArray<Domain>,
|
|
75
|
+
axisRange: AxisRange,
|
|
76
|
+
): CustomScaleDefinition<Domain> | undefined
|
|
77
|
+
export function combineConfiguredScaleInternal<
|
|
78
|
+
Domain extends CategoricalDomainItem = CategoricalDomainItem,
|
|
79
|
+
>(
|
|
80
|
+
scale: D3ScaleType | CustomScaleDefinition<Domain> | undefined,
|
|
81
|
+
axisDomain: ReadonlyArray<Domain>,
|
|
82
|
+
axisRange: AxisRange,
|
|
83
|
+
): CustomScaleDefinition<Domain> | undefined {
|
|
84
|
+
if (typeof scale === "function") {
|
|
85
|
+
return scale.copy().domain(axisDomain).range(axisRange)
|
|
86
|
+
}
|
|
87
|
+
if (scale == null) {
|
|
88
|
+
return undefined
|
|
89
|
+
}
|
|
90
|
+
const d3ScaleFunction: CustomScaleDefinition<Domain> | undefined = getD3ScaleFromType(scale)
|
|
91
|
+
if (d3ScaleFunction == null) {
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
d3ScaleFunction.domain(axisDomain).range(axisRange)
|
|
95
|
+
return d3ScaleFunction
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function combineConfiguredScale(
|
|
99
|
+
axis: BaseCartesianAxis,
|
|
100
|
+
realScaleType: D3ScaleType | undefined,
|
|
101
|
+
axisDomain: NumberDomain | CategoricalDomain | undefined,
|
|
102
|
+
axisRange: AxisRange | undefined,
|
|
103
|
+
): CustomScaleDefinition | undefined {
|
|
104
|
+
if (axisDomain == null || axisRange == null) {
|
|
105
|
+
return undefined
|
|
106
|
+
}
|
|
107
|
+
if (typeof axis.scale === "function") {
|
|
108
|
+
return combineConfiguredScaleInternal(axis.scale, axisDomain, axisRange)
|
|
109
|
+
}
|
|
110
|
+
return combineConfiguredScaleInternal(realScaleType, axisDomain, axisRange)
|
|
111
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { ChartOffsetInternal, Coordinate, LayoutType, TickItem } from "../../../util/types"
|
|
3
|
+
import { TooltipIndex, TooltipPayloadConfiguration } from "../../tooltipSlice"
|
|
4
|
+
|
|
5
|
+
export const combineCoordinateForDefaultIndex = (
|
|
6
|
+
width: number,
|
|
7
|
+
height: number,
|
|
8
|
+
layout: LayoutType,
|
|
9
|
+
offset: ChartOffsetInternal,
|
|
10
|
+
tooltipTicks: ReadonlyArray<TickItem> | undefined,
|
|
11
|
+
defaultIndex: TooltipIndex | undefined,
|
|
12
|
+
tooltipConfigurations: ReadonlyArray<TooltipPayloadConfiguration>,
|
|
13
|
+
): Coordinate | undefined => {
|
|
14
|
+
if (defaultIndex == null) {
|
|
15
|
+
return undefined
|
|
16
|
+
}
|
|
17
|
+
/*
|
|
18
|
+
* With defaultIndex alone, we don't have enough information to decide _which_ of the multiple tooltips to display.
|
|
19
|
+
* Maybe one day we could add new prop `activeGraphicalItemId` to the chart to help with that.
|
|
20
|
+
* Until then, we choose the first one.
|
|
21
|
+
*/
|
|
22
|
+
const firstConfiguration = tooltipConfigurations[0]
|
|
23
|
+
const maybePosition: Coordinate | undefined = firstConfiguration?.getPosition(defaultIndex)
|
|
24
|
+
if (maybePosition != null) {
|
|
25
|
+
return maybePosition
|
|
26
|
+
}
|
|
27
|
+
const tick = tooltipTicks?.[Number(defaultIndex)]
|
|
28
|
+
if (!tick) {
|
|
29
|
+
return undefined
|
|
30
|
+
}
|
|
31
|
+
switch (layout) {
|
|
32
|
+
case "horizontal": {
|
|
33
|
+
return {
|
|
34
|
+
x: tick.coordinate,
|
|
35
|
+
y: (offset.top + height) / 2,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
default: {
|
|
39
|
+
return {
|
|
40
|
+
x: (offset.left + width) / 2,
|
|
41
|
+
y: tick.coordinate,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { ChartDataState } from "../../chartDataSlice"
|
|
3
|
+
import { BaseCartesianAxis } from "../../cartesianAxisSlice"
|
|
4
|
+
import { getStackSeriesIdentifier } from "../../../util/stacks/getStackSeriesIdentifier"
|
|
5
|
+
import { getValueByDataKey } from "../../../util/ChartUtils"
|
|
6
|
+
import { StackSeriesIdentifier } from "../../../util/stacks/stackTypes"
|
|
7
|
+
import { DefinitelyStackedGraphicalItem } from "../../types/StackedGraphicalItem"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* In a stacked chart, each graphical item has its own data. That data could be either:
|
|
11
|
+
* - defined on the chart root, in which case the item gets a unique dataKey
|
|
12
|
+
* - or defined on the item itself, in which case multiple items can share the same dataKey
|
|
13
|
+
*
|
|
14
|
+
* That means we cannot use the dataKey as a unique identifier for the item.
|
|
15
|
+
*
|
|
16
|
+
* This type represents a single data point in a stacked chart, where each key is a series identifier
|
|
17
|
+
* and the value is the numeric value for that series using the numerical axis dataKey.
|
|
18
|
+
*/
|
|
19
|
+
export type DisplayedStackedDataPoint = Record<StackSeriesIdentifier, number>
|
|
20
|
+
|
|
21
|
+
export type DisplayedStackedData = ReadonlyArray<DisplayedStackedDataPoint>
|
|
22
|
+
|
|
23
|
+
export function combineDisplayedStackedData(
|
|
24
|
+
stackedGraphicalItems: ReadonlyArray<DefinitelyStackedGraphicalItem>,
|
|
25
|
+
{ chartData = [] }: ChartDataState,
|
|
26
|
+
tooltipAxisSettings: BaseCartesianAxis,
|
|
27
|
+
): DisplayedStackedData {
|
|
28
|
+
const { allowDuplicatedCategory, dataKey: tooltipDataKey } = tooltipAxisSettings
|
|
29
|
+
|
|
30
|
+
const knownItemsByDataKey = new Map<string | number, DisplayedStackedDataPoint>()
|
|
31
|
+
|
|
32
|
+
stackedGraphicalItems.forEach((item) => {
|
|
33
|
+
const resolvedData = item.data ?? chartData
|
|
34
|
+
if (resolvedData == null || resolvedData.length === 0) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
const stackIdentifier = getStackSeriesIdentifier(item)
|
|
38
|
+
resolvedData.forEach((entry, index) => {
|
|
39
|
+
const tooltipValue =
|
|
40
|
+
tooltipDataKey == null || allowDuplicatedCategory
|
|
41
|
+
? index
|
|
42
|
+
: String(getValueByDataKey(entry, tooltipDataKey, null))
|
|
43
|
+
const numericValue = getValueByDataKey(entry, item.dataKey, 0)
|
|
44
|
+
const curr = knownItemsByDataKey.get(tooltipValue) ?? {}
|
|
45
|
+
Object.assign(curr, { [stackIdentifier]: numericValue })
|
|
46
|
+
knownItemsByDataKey.set(tooltipValue, curr as DisplayedStackedDataPoint)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
return Array.from(knownItemsByDataKey.values())
|
|
50
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { InverseScaleFunction } from "../../../hooks"
|
|
3
|
+
import { createCategoricalInverse } from "../../../util/scale/createCategoricalInverse"
|
|
4
|
+
import { CustomScaleDefinition } from "../../../util/scale/CustomScaleDefinition"
|
|
5
|
+
|
|
6
|
+
export function combineInverseScaleFunction(
|
|
7
|
+
configuredScale: CustomScaleDefinition | undefined,
|
|
8
|
+
): InverseScaleFunction | undefined {
|
|
9
|
+
if (configuredScale == null) {
|
|
10
|
+
return undefined
|
|
11
|
+
}
|
|
12
|
+
if ("invert" in configuredScale && typeof configuredScale.invert === "function") {
|
|
13
|
+
return configuredScale.invert.bind(configuredScale)
|
|
14
|
+
}
|
|
15
|
+
return createCategoricalInverse(configuredScale, undefined)
|
|
16
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import * as d3Scales from "victory-vendor/d3-scale"
|
|
3
|
+
import type { RechartsScaleType } from "../../../util/types"
|
|
4
|
+
import { BaseCartesianAxis } from "../../cartesianAxisSlice"
|
|
5
|
+
import { upperFirst } from "../../../util/DataUtils"
|
|
6
|
+
|
|
7
|
+
function getD3ScaleName(name: string): string {
|
|
8
|
+
return `scale${upperFirst(name)}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function isSupportedScaleName(name: string): name is RechartsScaleType {
|
|
12
|
+
return getD3ScaleName(name) in d3Scales
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const combineRealScaleType = (
|
|
16
|
+
axisConfig: BaseCartesianAxis | undefined,
|
|
17
|
+
hasBar: boolean,
|
|
18
|
+
chartType: string,
|
|
19
|
+
): RechartsScaleType | undefined => {
|
|
20
|
+
if (axisConfig == null) {
|
|
21
|
+
return undefined
|
|
22
|
+
}
|
|
23
|
+
const { scale, type } = axisConfig
|
|
24
|
+
if (scale === "auto") {
|
|
25
|
+
if (
|
|
26
|
+
type === "category" &&
|
|
27
|
+
chartType &&
|
|
28
|
+
(chartType.indexOf("LineChart") >= 0 ||
|
|
29
|
+
chartType.indexOf("AreaChart") >= 0 ||
|
|
30
|
+
(chartType.indexOf("ComposedChart") >= 0 && !hasBar))
|
|
31
|
+
) {
|
|
32
|
+
return "point"
|
|
33
|
+
}
|
|
34
|
+
if (type === "category") {
|
|
35
|
+
return "band"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return "linear"
|
|
39
|
+
}
|
|
40
|
+
if (typeof scale === "string") {
|
|
41
|
+
return isSupportedScaleName(scale) ? scale : "point"
|
|
42
|
+
}
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { AllStackGroups, StackGroup, StackSeries } from "../../../util/stacks/stackTypes"
|
|
3
|
+
import { MaybeStackedGraphicalItem } from "../../types/StackedGraphicalItem"
|
|
4
|
+
import { getStackSeriesIdentifier } from "../../../util/stacks/getStackSeriesIdentifier"
|
|
5
|
+
|
|
6
|
+
export const combineStackedData = (
|
|
7
|
+
stackGroups: AllStackGroups | undefined,
|
|
8
|
+
barSettings: MaybeStackedGraphicalItem | undefined,
|
|
9
|
+
): StackSeries | undefined => {
|
|
10
|
+
const stackSeriesIdentifier = getStackSeriesIdentifier(barSettings)
|
|
11
|
+
if (!stackGroups || stackSeriesIdentifier == null || barSettings == null) {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
const { stackId } = barSettings
|
|
15
|
+
if (stackId == null) {
|
|
16
|
+
return undefined
|
|
17
|
+
}
|
|
18
|
+
const stackGroup: StackGroup | undefined = stackGroups[stackId]
|
|
19
|
+
if (!stackGroup) {
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
const { stackedData }: StackGroup = stackGroup
|
|
23
|
+
if (!stackedData) {
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
return stackedData.find((sd) => sd.key === stackSeriesIdentifier)
|
|
27
|
+
}
|