@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,72 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { InverseScaleFunction } from "../../hooks"
|
|
3
|
+
import { CustomScaleDefinition } from "./CustomScaleDefinition"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Binary search to find the index where x would fit in array a.
|
|
7
|
+
* Works for arrays that are sorted both ascending and descending.
|
|
8
|
+
*
|
|
9
|
+
* Unlike d3.bisect, this implementation handles both ascending and descending arrays.
|
|
10
|
+
*
|
|
11
|
+
* @param haystack Sorted array of numbers
|
|
12
|
+
* @param needle Number to find the insertion index for
|
|
13
|
+
* @returns Index where x would fit in array a
|
|
14
|
+
*/
|
|
15
|
+
export function bisect(haystack: ReadonlyArray<number>, needle: number): number {
|
|
16
|
+
let lo = 0
|
|
17
|
+
let hi = haystack.length
|
|
18
|
+
const first = haystack[0] ?? 0
|
|
19
|
+
const last = haystack[haystack.length - 1] ?? 0
|
|
20
|
+
const ascending = first < last
|
|
21
|
+
|
|
22
|
+
while (lo < hi) {
|
|
23
|
+
const mid = Math.floor((lo + hi) / 2)
|
|
24
|
+
const midVal = haystack[mid] ?? 0
|
|
25
|
+
if (ascending ? midVal < needle : midVal > needle) {
|
|
26
|
+
lo = mid + 1
|
|
27
|
+
} else {
|
|
28
|
+
hi = mid
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return lo
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Computes an inverse scale function for categorical/ordinal scales.
|
|
36
|
+
* Uses bisect to find the closest domain value for a given pixel coordinate.
|
|
37
|
+
*/
|
|
38
|
+
export function createCategoricalInverse(
|
|
39
|
+
scale: CustomScaleDefinition | undefined,
|
|
40
|
+
allDataPointsOnAxis?: ReadonlyArray<unknown>,
|
|
41
|
+
): InverseScaleFunction | undefined {
|
|
42
|
+
if (!scale) {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
const domain = allDataPointsOnAxis ?? scale.domain()
|
|
46
|
+
const pixelPositions: number[] = domain.map(
|
|
47
|
+
(d) => (scale as (input: unknown) => number | undefined)(d) ?? 0,
|
|
48
|
+
)
|
|
49
|
+
const range = scale.range()
|
|
50
|
+
|
|
51
|
+
if (domain.length === 0 || range.length < 2) {
|
|
52
|
+
return undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (pixelValue: number): unknown => {
|
|
56
|
+
const index = bisect(pixelPositions, pixelValue)
|
|
57
|
+
|
|
58
|
+
if (index <= 0) {
|
|
59
|
+
return domain[0]
|
|
60
|
+
}
|
|
61
|
+
if (index >= domain.length) {
|
|
62
|
+
return domain[domain.length - 1]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const leftPixel = pixelPositions[index - 1] ?? 0
|
|
66
|
+
const rightPixel = pixelPositions[index] ?? 0
|
|
67
|
+
if (Math.abs(pixelValue - leftPixel) <= Math.abs(pixelValue - rightPixel)) {
|
|
68
|
+
return domain[index - 1]
|
|
69
|
+
}
|
|
70
|
+
return domain[index]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
/**
|
|
3
|
+
* @fileOverview calculate tick values of scale
|
|
4
|
+
* @author xile611, arcthur
|
|
5
|
+
* @date 2015-09-17
|
|
6
|
+
*/
|
|
7
|
+
import Decimal from "decimal.js-light"
|
|
8
|
+
import { getDigitCount, rangeStep } from "./util/arithmetic"
|
|
9
|
+
import type { NumberDomain } from "../types"
|
|
10
|
+
import type { NiceTicksAlgorithm } from "../../state/cartesianAxisSlice"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Calculate a interval of a minimum value and a maximum value
|
|
14
|
+
*
|
|
15
|
+
* @param {Number} min The minimum value
|
|
16
|
+
* @param {Number} max The maximum value
|
|
17
|
+
* @return {Array} An interval
|
|
18
|
+
*/
|
|
19
|
+
export const getValidInterval = ([min, max]: [number, number]): [number, number] => {
|
|
20
|
+
let [validMin, validMax] = [min, max]
|
|
21
|
+
|
|
22
|
+
// exchange
|
|
23
|
+
if (min > max) {
|
|
24
|
+
[validMin, validMax] = [max, min]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return [validMin, validMax]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Calculate the step which is easy to understand between ticks, like 10, 20, 25
|
|
32
|
+
*
|
|
33
|
+
* @param roughStep The rough step calculated by dividing the difference by the tickCount
|
|
34
|
+
* @param allowDecimals Allow the ticks to be decimals or not
|
|
35
|
+
* @param correctionFactor A correction factor
|
|
36
|
+
* @return The step which is easy to understand between two ticks
|
|
37
|
+
*/
|
|
38
|
+
export const getAdaptiveStep = (roughStep: Decimal, allowDecimals: boolean, correctionFactor: number) => {
|
|
39
|
+
if (roughStep.lte(0)) {
|
|
40
|
+
return new Decimal(0)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const digitCount = getDigitCount(roughStep.toNumber())
|
|
44
|
+
// The ratio between the rough step and the smallest number which has a bigger
|
|
45
|
+
// order of magnitudes than the rough step
|
|
46
|
+
const digitCountValue = new Decimal(10).pow(digitCount)
|
|
47
|
+
const stepRatio = roughStep.div(digitCountValue)
|
|
48
|
+
// When an integer and a float multiplied, the accuracy of result may be wrong
|
|
49
|
+
const stepRatioScale = digitCount !== 1 ? 0.05 : 0.1
|
|
50
|
+
const amendStepRatio = new Decimal(Math.ceil(stepRatio.div(stepRatioScale).toNumber()))
|
|
51
|
+
.add(correctionFactor)
|
|
52
|
+
.mul(stepRatioScale)
|
|
53
|
+
|
|
54
|
+
const formatStep = amendStepRatio.mul(digitCountValue)
|
|
55
|
+
|
|
56
|
+
return allowDecimals ? new Decimal(formatStep.toNumber()) : new Decimal(Math.ceil(formatStep.toNumber()))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type StepFunction = (roughStep: Decimal, allowDecimals: boolean, correctionFactor: number) => Decimal
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The snap125 step algorithm snaps to nice numbers (1, 2, 2.5, 5) at each
|
|
63
|
+
* order of magnitude, producing human-friendly tick intervals like
|
|
64
|
+
* 0, 5, 10, 15, 20 instead of 0, 4, 8, 12, 16.
|
|
65
|
+
*
|
|
66
|
+
* This is opt-in and can be enabled via the `niceTicks` prop on axis components.
|
|
67
|
+
*
|
|
68
|
+
* @param roughStep The rough step calculated by dividing the difference by the tickCount
|
|
69
|
+
* @param allowDecimals Allow the ticks to be decimals or not
|
|
70
|
+
* @param correctionFactor A correction factor
|
|
71
|
+
* @return The step which is easy to understand between two ticks
|
|
72
|
+
*/
|
|
73
|
+
export const getSnap125Step: StepFunction = (roughStep: Decimal, allowDecimals: boolean, correctionFactor: number) => {
|
|
74
|
+
if (roughStep.lte(0)) {
|
|
75
|
+
return new Decimal(0)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const NICE_STEPS = [1, 2, 2.5, 5]
|
|
79
|
+
|
|
80
|
+
const roughNum = roughStep.toNumber()
|
|
81
|
+
const exponent = Math.floor(new Decimal(roughNum).abs().log(10).toNumber())
|
|
82
|
+
let magnitude = new Decimal(10).pow(exponent)
|
|
83
|
+
|
|
84
|
+
// normalized is in the range [1, 10)
|
|
85
|
+
const normalized = roughStep.div(magnitude).toNumber()
|
|
86
|
+
|
|
87
|
+
// Find the smallest nice step >= normalized (ceiling)
|
|
88
|
+
let niceIdx = NICE_STEPS.findIndex(s => s >= normalized - 1e-10)
|
|
89
|
+
if (niceIdx === -1) {
|
|
90
|
+
// normalized > 5 (e.g. 7.3), move to next order of magnitude
|
|
91
|
+
magnitude = magnitude.mul(10)
|
|
92
|
+
niceIdx = 0
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Apply correction factor by stepping through the nice number sequence
|
|
96
|
+
niceIdx += correctionFactor
|
|
97
|
+
if (niceIdx >= NICE_STEPS.length) {
|
|
98
|
+
const extraMag = Math.floor(niceIdx / NICE_STEPS.length)
|
|
99
|
+
niceIdx %= NICE_STEPS.length
|
|
100
|
+
magnitude = magnitude.mul(new Decimal(10).pow(extraMag))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const niceStep = NICE_STEPS[niceIdx] ?? 1
|
|
104
|
+
const formatStep = new Decimal(niceStep).mul(magnitude)
|
|
105
|
+
|
|
106
|
+
return allowDecimals ? formatStep : new Decimal(Math.ceil(formatStep.toNumber()))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* calculate the ticks when the minimum value equals to the maximum value
|
|
111
|
+
*
|
|
112
|
+
* @param value The minimum value which is also the maximum value
|
|
113
|
+
* @param tickCount The count of ticks
|
|
114
|
+
* @param allowDecimals Allow the ticks to be decimals or not
|
|
115
|
+
* @return array of ticks
|
|
116
|
+
*/
|
|
117
|
+
export const getTickOfSingleValue = (value: number, tickCount: number, allowDecimals: boolean): Array<number> => {
|
|
118
|
+
let step: Decimal = new Decimal(1)
|
|
119
|
+
// calculate the middle value of ticks
|
|
120
|
+
let middle = new Decimal(value)
|
|
121
|
+
|
|
122
|
+
if (!middle.isint() && allowDecimals) {
|
|
123
|
+
const absVal = Math.abs(value)
|
|
124
|
+
|
|
125
|
+
if (absVal < 1) {
|
|
126
|
+
// The step should be a float number when the difference is smaller than 1
|
|
127
|
+
step = new Decimal(10).pow(getDigitCount(value) - 1)
|
|
128
|
+
|
|
129
|
+
middle = new Decimal(Math.floor(middle.div(step).toNumber())).mul(step)
|
|
130
|
+
} else if (absVal > 1) {
|
|
131
|
+
// Return the maximum integer which is smaller than 'value' when 'value' is greater than 1
|
|
132
|
+
middle = new Decimal(Math.floor(value))
|
|
133
|
+
}
|
|
134
|
+
} else if (value === 0) {
|
|
135
|
+
middle = new Decimal(Math.floor((tickCount - 1) / 2))
|
|
136
|
+
} else if (!allowDecimals) {
|
|
137
|
+
middle = new Decimal(Math.floor(value))
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const middleIndex = Math.floor((tickCount - 1) / 2)
|
|
141
|
+
const ticks: Array<number> = []
|
|
142
|
+
|
|
143
|
+
for (let i = 0; i < tickCount; i++) {
|
|
144
|
+
ticks.push(middle.add(new Decimal(i - middleIndex).mul(step)).toNumber())
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return ticks
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Calculate the step
|
|
152
|
+
*
|
|
153
|
+
* @param min The minimum value of an interval
|
|
154
|
+
* @param max The maximum value of an interval
|
|
155
|
+
* @param tickCount The count of ticks
|
|
156
|
+
* @param allowDecimals Allow the ticks to be decimals or not
|
|
157
|
+
* @param correctionFactor A correction factor
|
|
158
|
+
* @return The step, minimum value of ticks, maximum value of ticks
|
|
159
|
+
*/
|
|
160
|
+
export const calculateStep = (
|
|
161
|
+
min: number,
|
|
162
|
+
max: number,
|
|
163
|
+
tickCount: number,
|
|
164
|
+
allowDecimals: boolean,
|
|
165
|
+
correctionFactor: number = 0,
|
|
166
|
+
stepFn: StepFunction = getAdaptiveStep,
|
|
167
|
+
): {
|
|
168
|
+
step: Decimal
|
|
169
|
+
tickMin: Decimal
|
|
170
|
+
tickMax: Decimal
|
|
171
|
+
} => {
|
|
172
|
+
// dirty hack (for recharts' test)
|
|
173
|
+
if (!Number.isFinite((max - min) / (tickCount - 1))) {
|
|
174
|
+
return {
|
|
175
|
+
step: new Decimal(0),
|
|
176
|
+
tickMin: new Decimal(0),
|
|
177
|
+
tickMax: new Decimal(0),
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// The step which is easy to understand between two ticks
|
|
182
|
+
const step = stepFn(new Decimal(max).sub(min).div(tickCount - 1), allowDecimals, correctionFactor)
|
|
183
|
+
|
|
184
|
+
// A medial value of ticks
|
|
185
|
+
let middle
|
|
186
|
+
|
|
187
|
+
// When 0 is inside the interval, 0 should be a tick
|
|
188
|
+
if (min <= 0 && max >= 0) {
|
|
189
|
+
middle = new Decimal(0)
|
|
190
|
+
} else {
|
|
191
|
+
// calculate the middle value
|
|
192
|
+
middle = new Decimal(min).add(max).div(2)
|
|
193
|
+
// minus modulo value
|
|
194
|
+
middle = middle.sub(new Decimal(middle).mod(step))
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let belowCount = Math.ceil(middle.sub(min).div(step).toNumber())
|
|
198
|
+
let upCount = Math.ceil(new Decimal(max).sub(middle).div(step).toNumber())
|
|
199
|
+
const scaleCount = belowCount + upCount + 1
|
|
200
|
+
|
|
201
|
+
if (scaleCount > tickCount) {
|
|
202
|
+
// When more ticks need to cover the interval, step should be bigger.
|
|
203
|
+
return calculateStep(min, max, tickCount, allowDecimals, correctionFactor + 1, stepFn)
|
|
204
|
+
}
|
|
205
|
+
if (scaleCount < tickCount) {
|
|
206
|
+
// When less ticks can cover the interval, we should add some additional ticks
|
|
207
|
+
upCount = max > 0 ? upCount + (tickCount - scaleCount) : upCount
|
|
208
|
+
belowCount = max > 0 ? belowCount : belowCount + (tickCount - scaleCount)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
step,
|
|
213
|
+
tickMin: middle.sub(new Decimal(belowCount).mul(step)),
|
|
214
|
+
tickMax: middle.add(new Decimal(upCount).mul(step)),
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Calculate the ticks of an interval. Ticks can appear outside the interval
|
|
220
|
+
* if it makes them more rounded and nice.
|
|
221
|
+
*
|
|
222
|
+
* @param tuple of [min,max] min: The minimum value, max: The maximum value
|
|
223
|
+
* @param tickCount The count of ticks
|
|
224
|
+
* @param allowDecimals Allow the ticks to be decimals or not
|
|
225
|
+
* @param niceTicksMode The algorithm to use for calculating nice ticks.
|
|
226
|
+
* @return array of ticks
|
|
227
|
+
*/
|
|
228
|
+
export const getNiceTickValues = (
|
|
229
|
+
[min, max]: NumberDomain,
|
|
230
|
+
tickCount = 6,
|
|
231
|
+
allowDecimals = true,
|
|
232
|
+
niceTicksMode: NiceTicksAlgorithm = "auto",
|
|
233
|
+
): number[] => {
|
|
234
|
+
// More than two ticks should be return
|
|
235
|
+
const count = Math.max(tickCount, 2)
|
|
236
|
+
const [cormin, cormax] = getValidInterval([min, max])
|
|
237
|
+
|
|
238
|
+
if (cormin === -Infinity || cormax === Infinity) {
|
|
239
|
+
const values: Array<number> =
|
|
240
|
+
cormax === Infinity
|
|
241
|
+
? [cormin, ...Array(tickCount - 1).fill(Infinity)]
|
|
242
|
+
: [...Array(tickCount - 1).fill(-Infinity), cormax]
|
|
243
|
+
|
|
244
|
+
return min > max ? values.reverse() : values
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (cormin === cormax) {
|
|
248
|
+
return getTickOfSingleValue(cormin, tickCount, allowDecimals)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const stepFn = niceTicksMode === "snap125" ? getSnap125Step : getAdaptiveStep
|
|
252
|
+
|
|
253
|
+
// Get the step between two ticks
|
|
254
|
+
const { step, tickMin, tickMax } = calculateStep(cormin, cormax, count, allowDecimals, 0, stepFn)
|
|
255
|
+
|
|
256
|
+
const values = rangeStep(tickMin, tickMax.add(new Decimal(0.1).mul(step)), step)
|
|
257
|
+
|
|
258
|
+
return min > max ? values.reverse() : values
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Calculate the ticks of an interval.
|
|
263
|
+
* Ticks will be constrained to the interval [min, max] even if it makes them less rounded and nice.
|
|
264
|
+
*
|
|
265
|
+
* @param tuple of [min,max] min: The minimum value, max: The maximum value
|
|
266
|
+
* @param tickCount The count of ticks. This function may return less than tickCount ticks if the interval is too small.
|
|
267
|
+
* @param allowDecimals Allow the ticks to be decimals or not
|
|
268
|
+
* @param niceTicksMode The algorithm to use for calculating nice ticks. See {@link NiceTicksAlgorithm}.
|
|
269
|
+
* @return array of ticks
|
|
270
|
+
*/
|
|
271
|
+
export const getTickValuesFixedDomain = (
|
|
272
|
+
[min, max]: NumberDomain,
|
|
273
|
+
tickCount: number,
|
|
274
|
+
allowDecimals = true,
|
|
275
|
+
niceTicksMode: NiceTicksAlgorithm = "auto",
|
|
276
|
+
) => {
|
|
277
|
+
// More than two ticks should be return
|
|
278
|
+
const [cormin, cormax] = getValidInterval([min, max])
|
|
279
|
+
|
|
280
|
+
if (cormin === -Infinity || cormax === Infinity) {
|
|
281
|
+
return [min, max]
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (cormin === cormax) {
|
|
285
|
+
return [cormin]
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const stepFn = niceTicksMode === "snap125" ? getSnap125Step : getAdaptiveStep
|
|
289
|
+
const count = Math.max(tickCount, 2)
|
|
290
|
+
const step = stepFn(new Decimal(cormax).sub(cormin).div(count - 1), allowDecimals, 0)
|
|
291
|
+
let values = [...rangeStep(new Decimal(cormin), new Decimal(cormax), step), cormax]
|
|
292
|
+
|
|
293
|
+
if (allowDecimals === false) {
|
|
294
|
+
/*
|
|
295
|
+
* allowDecimals is false means that we want to have integer ticks.
|
|
296
|
+
* The step is guaranteed to be an integer in the code above which is great start
|
|
297
|
+
* but when the first step is not an integer, it will start stepping from a decimal value anyway.
|
|
298
|
+
* So we need to round all the values to integers after the fact.
|
|
299
|
+
* The domain boundary (cormax) is appended after the rangeStep values. When
|
|
300
|
+
* cormax rounds down to the same integer as the last rangeStep value, we end up
|
|
301
|
+
* with a duplicate trailing tick. Remove it.
|
|
302
|
+
*/
|
|
303
|
+
values = values.map(value => Math.round(value))
|
|
304
|
+
const last = values.length - 1
|
|
305
|
+
if (last > 0 && values[last] === values[last - 1]) {
|
|
306
|
+
values = values.slice(0, last)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return min > max ? values.reverse() : values
|
|
311
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileOverview Some common arithmetic methods
|
|
3
|
+
* @author xile611
|
|
4
|
+
* @date 2015-09-17
|
|
5
|
+
*/
|
|
6
|
+
import Decimal from "decimal.js-light"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get the digit count of a number.
|
|
10
|
+
* If the absolute value is in the interval [0.1, 1), the result is 0.
|
|
11
|
+
* If the absolute value is in the interval [0.01, 0.1), the digit count is -1.
|
|
12
|
+
* If the absolute value is in the interval [0.001, 0.01), the digit count is -2.
|
|
13
|
+
*
|
|
14
|
+
* @param {Number} value The number
|
|
15
|
+
* @return {Integer} Digit count
|
|
16
|
+
*/
|
|
17
|
+
function getDigitCount(value: number) {
|
|
18
|
+
let result
|
|
19
|
+
|
|
20
|
+
if (value === 0) {
|
|
21
|
+
result = 1
|
|
22
|
+
} else {
|
|
23
|
+
result = Math.floor(new Decimal(value).abs().log(10).toNumber()) + 1
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return result
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the data in the interval [start, end) with a fixed step.
|
|
31
|
+
* Also handles JS calculation precision issues.
|
|
32
|
+
*
|
|
33
|
+
* @param {Decimal} start Start point
|
|
34
|
+
* @param {Decimal} end End point, not included
|
|
35
|
+
* @param {Decimal} step Step size
|
|
36
|
+
* @return {Array} Array of numbers
|
|
37
|
+
*/
|
|
38
|
+
function rangeStep(start: Decimal, end: Decimal, step: Decimal): Array<number> {
|
|
39
|
+
let num = new Decimal(start)
|
|
40
|
+
let i = 0
|
|
41
|
+
const result: Array<number> = []
|
|
42
|
+
|
|
43
|
+
/* magic number to prevent infinite loop */
|
|
44
|
+
while (num.lt(end) && i < 100000) {
|
|
45
|
+
result.push(num.toNumber())
|
|
46
|
+
|
|
47
|
+
num = num.add(step)
|
|
48
|
+
i++
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { rangeStep, getDigitCount }
|