@octanejs/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 +21 -0
- package/package.json +53 -0
- package/src/animation/AnimatedItems.tsrx +82 -0
- package/src/animation/AnimationControllerImpl.js +33 -0
- package/src/animation/AnimationHandle.js +291 -0
- package/src/animation/JavascriptAnimate.tsrx +81 -0
- package/src/animation/easing.js +193 -0
- package/src/animation/matchBy.js +279 -0
- package/src/animation/timeoutController.js +49 -0
- package/src/animation/useAnimationController.ts +22 -0
- package/src/animation/useAnimationStartSnapshot.ts +43 -0
- package/src/animation/util.js +11 -0
- package/src/cartesian/Bar.ts +4 -0
- package/src/cartesian/Bar.tsrx +716 -0
- package/src/cartesian/Bar.tsrx.d.ts +4 -0
- package/src/cartesian/BarStack.tsrx +97 -0
- package/src/cartesian/BarStack.tsrx.d.ts +6 -0
- package/src/cartesian/CartesianAxis.tsrx +413 -0
- package/src/cartesian/CartesianAxis.tsrx.d.ts +3 -0
- package/src/cartesian/GraphicalItemClipPath.tsrx +44 -0
- package/src/cartesian/Line.ts +4 -0
- package/src/cartesian/Line.tsrx +544 -0
- package/src/cartesian/Line.tsrx.d.ts +4 -0
- package/src/cartesian/LineDrawShape.tsrx +106 -0
- package/src/cartesian/LineDrawShape.tsrx.d.ts +2 -0
- package/src/cartesian/XAxis.tsrx +156 -0
- package/src/cartesian/XAxis.tsrx.d.ts +3 -0
- package/src/cartesian/YAxis.tsrx +183 -0
- package/src/cartesian/YAxis.tsrx.d.ts +3 -0
- package/src/cartesian/getCartesianPosition.js +277 -0
- package/src/cartesian/getEquidistantTicks.js +133 -0
- package/src/cartesian/getTicks.js +280 -0
- package/src/cartesian/useAnimatedLineLength.ts +33 -0
- package/src/chart/BarChart.tsrx +22 -0
- package/src/chart/BarChart.tsrx.d.ts +2 -0
- package/src/chart/CartesianChart.tsrx +76 -0
- package/src/chart/CartesianChart.tsrx.d.ts +10 -0
- package/src/chart/CategoricalChart.tsrx +54 -0
- package/src/chart/LineChart.tsrx +22 -0
- package/src/chart/LineChart.tsrx.d.ts +2 -0
- package/src/chart/RechartsWrapper.tsrx +294 -0
- package/src/component/ActivePoints.tsrx +76 -0
- package/src/component/Cell.ts +37 -0
- package/src/component/Dots.tsrx +74 -0
- package/src/component/Label.tsrx +309 -0
- package/src/component/Label.tsrx.d.ts +12 -0
- package/src/component/LabelList.tsrx +83 -0
- package/src/component/LabelList.tsrx.d.ts +8 -0
- package/src/component/ResponsiveContainer.ts +22 -0
- package/src/component/Text.tsrx +281 -0
- package/src/component/Text.tsrx.d.ts +9 -0
- package/src/component/responsiveContainerUtils.js +111 -0
- package/src/container/ClipPathProvider.tsrx +29 -0
- package/src/container/Layer.tsrx +9 -0
- package/src/container/Layer.tsrx.d.ts +6 -0
- package/src/container/RootSurface.tsrx +76 -0
- package/src/container/Surface.tsrx +23 -0
- package/src/container/Surface.tsrx.d.ts +12 -0
- package/src/context/CellsContext.ts +80 -0
- package/src/context/ErrorBarContext.tsrx +53 -0
- package/src/context/PanoramaContext.ts +10 -0
- package/src/context/RegisterGraphicalItemId.tsrx +19 -0
- package/src/context/accessibilityContext.js +10 -0
- package/src/context/chartDataContext.ts +57 -0
- package/src/context/chartLayoutContext.ts +171 -0
- package/src/context/legendPortalContext.ts +5 -0
- package/src/context/tooltipContext.js +55 -0
- package/src/context/tooltipPortalContext.ts +5 -0
- package/src/hooks.js +509 -0
- package/src/index.ts +64 -0
- package/src/internal.ts +37 -0
- package/src/polar/defaultPolarAngleAxisProps.js +27 -0
- package/src/polar/defaultPolarRadiusAxisProps.js +24 -0
- package/src/shape/Cross.tsrx +25 -0
- package/src/shape/Cross.tsrx.d.ts +12 -0
- package/src/shape/Curve.tsrx +132 -0
- package/src/shape/Curve.tsrx.d.ts +42 -0
- package/src/shape/Dot.tsrx +21 -0
- package/src/shape/Dot.tsrx.d.ts +9 -0
- package/src/shape/Polygon.tsrx +95 -0
- package/src/shape/Polygon.tsrx.d.ts +13 -0
- package/src/shape/Rectangle.tsrx +162 -0
- package/src/shape/Rectangle.tsrx.d.ts +31 -0
- package/src/shape/Sector.tsrx +219 -0
- package/src/shape/Sector.tsrx.d.ts +29 -0
- package/src/shape/Symbols.tsrx +95 -0
- package/src/shape/Symbols.tsrx.d.ts +15 -0
- package/src/shape/Trapezoid.tsrx +56 -0
- package/src/shape/Trapezoid.tsrx.d.ts +29 -0
- package/src/state/RechartsReduxContext.ts +7 -0
- package/src/state/RechartsStoreProvider.tsrx +24 -0
- package/src/state/ReportChartProps.ts +13 -0
- package/src/state/ReportEventSettings.ts +15 -0
- package/src/state/ReportMainChartProps.ts +22 -0
- package/src/state/SetGraphicalItem.ts +61 -0
- package/src/state/SetLegendPayload.ts +61 -0
- package/src/state/SetTooltipEntrySettings.ts +40 -0
- package/src/state/brushSlice.js +36 -0
- package/src/state/cartesianAxisSlice.js +256 -0
- package/src/state/chartDataSlice.js +67 -0
- package/src/state/errorBarSlice.js +53 -0
- package/src/state/eventSettingsSlice.js +25 -0
- package/src/state/externalEventsMiddleware.js +127 -0
- package/src/state/graphicalItemsSlice.js +91 -0
- package/src/state/hooks.ts +46 -0
- package/src/state/keyboardEventsMiddleware.js +226 -0
- package/src/state/layoutSlice.js +57 -0
- package/src/state/legendSlice.js +83 -0
- package/src/state/mouseEventsMiddleware.js +130 -0
- package/src/state/optionsSlice.js +45 -0
- package/src/state/polarAxisSlice.js +33 -0
- package/src/state/polarOptionsSlice.js +26 -0
- package/src/state/reduxDevtoolsJsonStringifyReplacer.js +14 -0
- package/src/state/referenceElementsSlice.js +51 -0
- package/src/state/renderedTicksSlice.js +41 -0
- package/src/state/rootPropsSlice.js +48 -0
- package/src/state/selectors/arrayEqualityCheck.js +32 -0
- package/src/state/selectors/axisSelectors.js +2113 -0
- package/src/state/selectors/barSelectors.js +263 -0
- package/src/state/selectors/barStackSelectors.js +65 -0
- package/src/state/selectors/brushSelectors.js +21 -0
- package/src/state/selectors/combiners/combineActiveLabel.js +18 -0
- package/src/state/selectors/combiners/combineActiveTooltipIndex.js +75 -0
- package/src/state/selectors/combiners/combineAllBarPositions.js +169 -0
- package/src/state/selectors/combiners/combineAxisRangeWithReverse.js +11 -0
- package/src/state/selectors/combiners/combineBarPosition.js +17 -0
- package/src/state/selectors/combiners/combineBarSizeList.js +115 -0
- package/src/state/selectors/combiners/combineCheckedDomain.js +44 -0
- package/src/state/selectors/combiners/combineConfiguredScale.js +46 -0
- package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.js +48 -0
- package/src/state/selectors/combiners/combineDisplayedStackedData.js +54 -0
- package/src/state/selectors/combiners/combineInverseScaleFunction.js +12 -0
- package/src/state/selectors/combiners/combineRealScaleType.js +36 -0
- package/src/state/selectors/combiners/combineStackedData.js +22 -0
- package/src/state/selectors/combiners/combineTooltipInteractionState.js +121 -0
- package/src/state/selectors/combiners/combineTooltipPayload.js +248 -0
- package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.js +59 -0
- package/src/state/selectors/containerSelectors.js +6 -0
- package/src/state/selectors/dataSelectors.js +97 -0
- package/src/state/selectors/graphicalItemSelectors.js +25 -0
- package/src/state/selectors/legendSelectors.js +18 -0
- package/src/state/selectors/lineSelectors.js +106 -0
- package/src/state/selectors/numberDomainEqualityCheck.js +11 -0
- package/src/state/selectors/pickAxisId.js +3 -0
- package/src/state/selectors/pickAxisType.js +3 -0
- package/src/state/selectors/polarAxisSelectors.js +237 -0
- package/src/state/selectors/rootPropsSelectors.js +13 -0
- package/src/state/selectors/selectActivePropsFromChartPointer.js +23 -0
- package/src/state/selectors/selectAllAxes.js +15 -0
- package/src/state/selectors/selectChartOffset.js +12 -0
- package/src/state/selectors/selectChartOffsetInternal.js +174 -0
- package/src/state/selectors/selectPlotArea.js +19 -0
- package/src/state/selectors/selectTooltipAxisId.js +3 -0
- package/src/state/selectors/selectTooltipAxisType.js +25 -0
- package/src/state/selectors/selectTooltipEventType.js +27 -0
- package/src/state/selectors/selectTooltipPayloadSearcher.js +3 -0
- package/src/state/selectors/selectTooltipSettings.js +3 -0
- package/src/state/selectors/selectTooltipState.js +3 -0
- package/src/state/selectors/selectors.js +222 -0
- package/src/state/selectors/tooltipSelectors.js +471 -0
- package/src/state/selectors/touchSelectors.js +31 -0
- package/src/state/store.js +101 -0
- package/src/state/tooltipSlice.js +237 -0
- package/src/state/touchEventsMiddleware.js +140 -0
- package/src/state/types/StackedGraphicalItem.js +18 -0
- package/src/state/zIndexSlice.js +167 -0
- package/src/synchronisation/syncSelectors.js +5 -0
- package/src/synchronisation/useChartSynchronisation.tsrx +285 -0
- package/src/util/ActiveShapeUtils.tsrx +62 -0
- package/src/util/BarUtils.tsrx +35 -0
- package/src/util/CartesianUtils.js +66 -0
- package/src/util/ChartUtils.js +630 -0
- package/src/util/Constants.js +42 -0
- package/src/util/DOMUtils.js +180 -0
- package/src/util/DataUtils.js +199 -0
- package/src/util/Events.js +7 -0
- package/src/util/Global.js +13 -0
- package/src/util/LRUCache.js +58 -0
- package/src/util/LogUtils.js +29 -0
- package/src/util/PolarUtils.js +190 -0
- package/src/util/ReactUtils.ts +94 -0
- package/src/util/ReduceCSSCalc.js +260 -0
- package/src/util/TickUtils.js +43 -0
- package/src/util/YAxisUtils.js +43 -0
- package/src/util/axisPropsAreEqual.js +63 -0
- package/src/util/createEventProxy.js +18 -0
- package/src/util/excludeEventProps.js +172 -0
- package/src/util/getActiveCoordinate.js +253 -0
- package/src/util/getAxisTypeBasedOnLayout.js +17 -0
- package/src/util/getClassNameFromUnknown.js +8 -0
- package/src/util/getEveryNth.js +29 -0
- package/src/util/getRadiusAndStrokeWidthFromDot.js +28 -0
- package/src/util/getRelativeCoordinate.js +96 -0
- package/src/util/getSliced.js +11 -0
- package/src/util/isDomainSpecifiedByUser.js +255 -0
- package/src/util/isWellBehavedNumber.js +8 -0
- package/src/util/propsAreEqual.js +96 -0
- package/src/util/resolveDefaultProps.js +131 -0
- package/src/util/round.js +39 -0
- package/src/util/scale/RechartsScale.js +68 -0
- package/src/util/scale/createCategoricalInverse.js +77 -0
- package/src/util/scale/getNiceTickValues.js +354 -0
- package/src/util/scale/index.js +3 -0
- package/src/util/scale/util/arithmetic.js +51 -0
- package/src/util/stacks/getStackSeriesIdentifier.js +10 -0
- package/src/util/svgPropertiesAndEvents.ts +29 -0
- package/src/util/svgPropertiesNoEvents.js +383 -0
- package/src/util/types.ts +59 -0
- package/src/util/useAnimationId.ts +14 -0
- package/src/util/useId.ts +13 -0
- package/src/util/usePrefersReducedMotion.ts +30 -0
- package/src/util/useReportScale.ts +26 -0
- package/src/util/useUniqueId.js +34 -0
- package/src/zIndex/DefaultZIndexes.js +75 -0
- package/src/zIndex/ZIndexLayer.tsrx +80 -0
- package/src/zIndex/ZIndexLayer.tsrx.d.ts +2 -0
- package/src/zIndex/ZIndexPortal.tsrx +43 -0
- package/src/zIndex/getZIndexFromUnknown.js +15 -0
- package/src/zIndex/zIndexSelectors.js +45 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Vendored verbatim from recharts@3.9.2 es6/synchronisation/syncSelectors.js (framework-agnostic).
|
|
2
|
+
// Do not edit — update by re-vendoring when the recharts devDependency moves.
|
|
3
|
+
export function selectSynchronisedTooltipState(state) {
|
|
4
|
+
return state.tooltip.syncInteraction;
|
|
5
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// Port of synchronisation/useChartSynchronisation.ts — cross-chart tooltip and
|
|
2
|
+
// brush synchronisation over the shared eventemitter3 event center. A `.tsrx`
|
|
3
|
+
// module so the compiler slots every store read (these hooks read many
|
|
4
|
+
// selectors each).
|
|
5
|
+
import { useEffect } from 'octane';
|
|
6
|
+
import { useAppDispatch, useAppSelector } from '../state/hooks';
|
|
7
|
+
import {
|
|
8
|
+
selectEventEmitter,
|
|
9
|
+
selectSyncId,
|
|
10
|
+
selectSyncMethod,
|
|
11
|
+
} from '../state/selectors/rootPropsSelectors';
|
|
12
|
+
import { BRUSH_SYNC_EVENT, eventCenter, TOOLTIP_SYNC_EVENT } from '../util/Events';
|
|
13
|
+
import { createEventEmitter } from '../state/optionsSlice';
|
|
14
|
+
import { setSyncInteraction } from '../state/tooltipSlice';
|
|
15
|
+
import { selectTooltipDataKey } from '../state/selectors/selectors';
|
|
16
|
+
import {
|
|
17
|
+
selectActiveTooltipGraphicalItemId,
|
|
18
|
+
selectTooltipAxisTicks,
|
|
19
|
+
} from '../state/selectors/tooltipSelectors';
|
|
20
|
+
import { selectSynchronisedTooltipState } from './syncSelectors';
|
|
21
|
+
import { useChartLayout, useViewBox } from '../context/chartLayoutContext.ts';
|
|
22
|
+
import { setDataStartEndIndexes } from '../state/chartDataSlice';
|
|
23
|
+
import { noop } from '../util/DataUtils';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Listens for tooltip sync events from other charts and dispatches the
|
|
27
|
+
* appropriate sync interaction based on this chart's syncMethod
|
|
28
|
+
* ('index' scales coordinates between viewBoxes, 'value' matches labels
|
|
29
|
+
* against ticks, a function delegates tick resolution to the user).
|
|
30
|
+
*/
|
|
31
|
+
function useTooltipSyncEventsListener() {
|
|
32
|
+
const mySyncId = useAppSelector(selectSyncId);
|
|
33
|
+
const myEventEmitter = useAppSelector(selectEventEmitter);
|
|
34
|
+
const dispatch = useAppDispatch();
|
|
35
|
+
const syncMethod = useAppSelector(selectSyncMethod);
|
|
36
|
+
const tooltipTicks = useAppSelector(selectTooltipAxisTicks);
|
|
37
|
+
const layout = useChartLayout();
|
|
38
|
+
const viewBox = useViewBox();
|
|
39
|
+
const className = useAppSelector((state) => state.rootProps.className);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (mySyncId == null) {
|
|
42
|
+
// This chart is not synchronised with any other chart.
|
|
43
|
+
return noop;
|
|
44
|
+
}
|
|
45
|
+
const listener = (incomingSyncId, action, emitter) => {
|
|
46
|
+
if (myEventEmitter === emitter) {
|
|
47
|
+
// We don't want to dispatch actions that we sent ourselves.
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (mySyncId !== incomingSyncId) {
|
|
51
|
+
// This event is not for this chart
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Source chart deactivation (mouseLeave) clears sourceViewBox for ALL
|
|
55
|
+
// sync methods, letting normal emission resume.
|
|
56
|
+
if (action.payload.active === false) {
|
|
57
|
+
dispatch(
|
|
58
|
+
setSyncInteraction({
|
|
59
|
+
active: false,
|
|
60
|
+
coordinate: undefined,
|
|
61
|
+
dataKey: undefined,
|
|
62
|
+
index: null,
|
|
63
|
+
label: undefined,
|
|
64
|
+
sourceViewBox: undefined,
|
|
65
|
+
graphicalItemId: undefined,
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (syncMethod === 'index') {
|
|
71
|
+
if (viewBox && action?.payload?.coordinate && action.payload.sourceViewBox) {
|
|
72
|
+
const { x, y, ...otherCoordinateProps } = action.payload.coordinate;
|
|
73
|
+
const {
|
|
74
|
+
x: sourceX,
|
|
75
|
+
y: sourceY,
|
|
76
|
+
width: sourceWidth,
|
|
77
|
+
height: sourceHeight,
|
|
78
|
+
} = action.payload.sourceViewBox;
|
|
79
|
+
const scaledCoordinate = {
|
|
80
|
+
...otherCoordinateProps,
|
|
81
|
+
x: viewBox.x + (sourceWidth ? (x - sourceX) / sourceWidth : 0) * viewBox.width,
|
|
82
|
+
y: viewBox.y + (sourceHeight ? (y - sourceY) / sourceHeight : 0) * viewBox.height,
|
|
83
|
+
};
|
|
84
|
+
dispatch({
|
|
85
|
+
...action,
|
|
86
|
+
payload: { ...action.payload, coordinate: scaledCoordinate },
|
|
87
|
+
});
|
|
88
|
+
} else {
|
|
89
|
+
dispatch(action);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (tooltipTicks == null) {
|
|
94
|
+
// for the other two sync methods, we need the ticks to be available
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
let activeTick;
|
|
98
|
+
if (typeof syncMethod === 'function') {
|
|
99
|
+
// The 2.x CategoricalChartState data shape, kept for compatibility.
|
|
100
|
+
const syncMethodParam = {
|
|
101
|
+
activeTooltipIndex: action.payload.index == null
|
|
102
|
+
? undefined
|
|
103
|
+
: Number(action.payload.index),
|
|
104
|
+
isTooltipActive: action.payload.active,
|
|
105
|
+
activeIndex: action.payload.index == null ? undefined : Number(action.payload.index),
|
|
106
|
+
activeLabel: action.payload.label,
|
|
107
|
+
activeDataKey: action.payload.dataKey,
|
|
108
|
+
activeCoordinate: action.payload.coordinate,
|
|
109
|
+
};
|
|
110
|
+
const activeTooltipIndex = syncMethod(tooltipTicks, syncMethodParam);
|
|
111
|
+
activeTick = tooltipTicks[activeTooltipIndex];
|
|
112
|
+
} else if (syncMethod === 'value') {
|
|
113
|
+
// labels are always strings; tick.value might be string or number
|
|
114
|
+
activeTick = tooltipTicks.find((tick) => String(tick.value) === action.payload.label);
|
|
115
|
+
}
|
|
116
|
+
const { coordinate } = action.payload;
|
|
117
|
+
if (coordinate == null || viewBox == null) {
|
|
118
|
+
dispatch(
|
|
119
|
+
setSyncInteraction({
|
|
120
|
+
active: false,
|
|
121
|
+
coordinate: undefined,
|
|
122
|
+
dataKey: undefined,
|
|
123
|
+
index: null,
|
|
124
|
+
label: undefined,
|
|
125
|
+
sourceViewBox: undefined,
|
|
126
|
+
graphicalItemId: undefined,
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (activeTick == null) {
|
|
132
|
+
// No matching tick (sparse data): hide the tooltip but KEEP
|
|
133
|
+
// sourceViewBox so this chart stays in "receiving" mode and does not
|
|
134
|
+
// emit a counter-sync that would cascade-clear other charts.
|
|
135
|
+
dispatch(
|
|
136
|
+
setSyncInteraction({
|
|
137
|
+
active: false,
|
|
138
|
+
coordinate: undefined,
|
|
139
|
+
dataKey: undefined,
|
|
140
|
+
index: null,
|
|
141
|
+
label: undefined,
|
|
142
|
+
sourceViewBox: action.payload.sourceViewBox,
|
|
143
|
+
graphicalItemId: undefined,
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const { x, y } = coordinate;
|
|
149
|
+
const validateChartX = Math.min(x, viewBox.x + viewBox.width);
|
|
150
|
+
const validateChartY = Math.min(y, viewBox.y + viewBox.height);
|
|
151
|
+
const activeCoordinate = {
|
|
152
|
+
x: layout === 'horizontal' ? activeTick.coordinate : validateChartX,
|
|
153
|
+
y: layout === 'horizontal' ? validateChartY : activeTick.coordinate,
|
|
154
|
+
};
|
|
155
|
+
const syncAction = setSyncInteraction({
|
|
156
|
+
active: action.payload.active,
|
|
157
|
+
coordinate: activeCoordinate,
|
|
158
|
+
dataKey: action.payload.dataKey,
|
|
159
|
+
index: String(activeTick.index),
|
|
160
|
+
label: action.payload.label,
|
|
161
|
+
sourceViewBox: action.payload.sourceViewBox,
|
|
162
|
+
graphicalItemId: action.payload.graphicalItemId,
|
|
163
|
+
});
|
|
164
|
+
dispatch(syncAction);
|
|
165
|
+
};
|
|
166
|
+
eventCenter.on(TOOLTIP_SYNC_EVENT, listener);
|
|
167
|
+
return () => {
|
|
168
|
+
eventCenter.off(TOOLTIP_SYNC_EVENT, listener);
|
|
169
|
+
};
|
|
170
|
+
}, [className, dispatch, myEventEmitter, mySyncId, syncMethod, tooltipTicks, layout, viewBox]);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Listens for brush sync events from other charts and mirrors their data
|
|
175
|
+
* start/end indexes.
|
|
176
|
+
*/
|
|
177
|
+
function useBrushSyncEventsListener() {
|
|
178
|
+
const mySyncId = useAppSelector(selectSyncId);
|
|
179
|
+
const myEventEmitter = useAppSelector(selectEventEmitter);
|
|
180
|
+
const dispatch = useAppDispatch();
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (mySyncId == null) {
|
|
183
|
+
return noop;
|
|
184
|
+
}
|
|
185
|
+
const listener = (incomingSyncId, action, emitter) => {
|
|
186
|
+
if (myEventEmitter === emitter) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (mySyncId === incomingSyncId) {
|
|
190
|
+
dispatch(setDataStartEndIndexes(action));
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
eventCenter.on(BRUSH_SYNC_EVENT, listener);
|
|
194
|
+
return () => {
|
|
195
|
+
eventCenter.off(BRUSH_SYNC_EVENT, listener);
|
|
196
|
+
};
|
|
197
|
+
}, [dispatch, myEventEmitter, mySyncId]);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Receives synchronisation events from other charts. */
|
|
201
|
+
export function useSynchronisedEventsFromOtherCharts() {
|
|
202
|
+
const dispatch = useAppDispatch();
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
dispatch(createEventEmitter());
|
|
205
|
+
}, [dispatch]);
|
|
206
|
+
useTooltipSyncEventsListener();
|
|
207
|
+
useBrushSyncEventsListener();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Sends tooltip sync events to other charts. Emission is suppressed while
|
|
212
|
+
* `sourceViewBox` is present in the sync state (this chart is receiving),
|
|
213
|
+
* which prevents sparse-data charts from cascade-clearing other tooltips.
|
|
214
|
+
*/
|
|
215
|
+
export function useTooltipChartSynchronisation(
|
|
216
|
+
tooltipEventType,
|
|
217
|
+
trigger,
|
|
218
|
+
activeCoordinate,
|
|
219
|
+
activeLabel,
|
|
220
|
+
activeIndex,
|
|
221
|
+
isTooltipActive,
|
|
222
|
+
) {
|
|
223
|
+
const activeDataKey = useAppSelector(
|
|
224
|
+
(state) => selectTooltipDataKey(state, tooltipEventType, trigger),
|
|
225
|
+
);
|
|
226
|
+
const activeGraphicalItemId = useAppSelector(selectActiveTooltipGraphicalItemId);
|
|
227
|
+
const eventEmitterSymbol = useAppSelector(selectEventEmitter);
|
|
228
|
+
const syncId = useAppSelector(selectSyncId);
|
|
229
|
+
const syncMethod = useAppSelector(selectSyncMethod);
|
|
230
|
+
const tooltipState = useAppSelector(selectSynchronisedTooltipState);
|
|
231
|
+
const isReceivingSynchronisation = tooltipState?.sourceViewBox != null;
|
|
232
|
+
const viewBox = useViewBox();
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
if (isReceivingSynchronisation) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (syncId == null) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (eventEmitterSymbol == null) {
|
|
241
|
+
// Hooks used outside a chart context — return silently.
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const syncAction = setSyncInteraction({
|
|
245
|
+
active: isTooltipActive,
|
|
246
|
+
coordinate: activeCoordinate,
|
|
247
|
+
dataKey: activeDataKey,
|
|
248
|
+
index: activeIndex,
|
|
249
|
+
label: typeof activeLabel === 'number' ? String(activeLabel) : activeLabel,
|
|
250
|
+
sourceViewBox: viewBox,
|
|
251
|
+
graphicalItemId: activeGraphicalItemId,
|
|
252
|
+
});
|
|
253
|
+
eventCenter.emit(TOOLTIP_SYNC_EVENT, syncId, syncAction, eventEmitterSymbol);
|
|
254
|
+
}, [
|
|
255
|
+
isReceivingSynchronisation,
|
|
256
|
+
activeCoordinate,
|
|
257
|
+
activeDataKey,
|
|
258
|
+
activeGraphicalItemId,
|
|
259
|
+
activeIndex,
|
|
260
|
+
activeLabel,
|
|
261
|
+
eventEmitterSymbol,
|
|
262
|
+
syncId,
|
|
263
|
+
syncMethod,
|
|
264
|
+
isTooltipActive,
|
|
265
|
+
viewBox,
|
|
266
|
+
]);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Emits brush sync events when the brush start/end indexes change. */
|
|
270
|
+
export function useBrushChartSynchronisation() {
|
|
271
|
+
const syncId = useAppSelector(selectSyncId);
|
|
272
|
+
const eventEmitterSymbol = useAppSelector(selectEventEmitter);
|
|
273
|
+
const brushStartIndex = useAppSelector((state) => state.chartData.dataStartIndex);
|
|
274
|
+
const brushEndIndex = useAppSelector((state) => state.chartData.dataEndIndex);
|
|
275
|
+
useEffect(() => {
|
|
276
|
+
if (
|
|
277
|
+
syncId == null || brushStartIndex == null || brushEndIndex == null ||
|
|
278
|
+
eventEmitterSymbol == null
|
|
279
|
+
) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const syncAction = { startIndex: brushStartIndex, endIndex: brushEndIndex };
|
|
283
|
+
eventCenter.emit(BRUSH_SYNC_EVENT, syncId, syncAction, eventEmitterSymbol);
|
|
284
|
+
}, [brushEndIndex, brushStartIndex, eventEmitterSymbol, syncId]);
|
|
285
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Port of util/ActiveShapeUtils.tsx — renders a user-defined `shape`/
|
|
2
|
+
// `activeShape` option in all four accepted forms: an element (cloned with the
|
|
3
|
+
// computed props as defaults), a render function, a props object (merged), or
|
|
4
|
+
// boolean/undefined (default shape). octane cloneElement/isValidElement work
|
|
5
|
+
// on element descriptors — value-position elements, which is exactly how these
|
|
6
|
+
// options arrive (`shape={<Rectangle .../>}` compiles to a descriptor).
|
|
7
|
+
import { cloneElement, isValidElement } from 'octane';
|
|
8
|
+
import { Layer } from '../container/Layer.tsrx';
|
|
9
|
+
|
|
10
|
+
function mergeShapeProps(option, props) {
|
|
11
|
+
return { ...props, ...option };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getPropsFromShapeOption(option) {
|
|
15
|
+
if (isValidElement(option)) {
|
|
16
|
+
return option.props;
|
|
17
|
+
}
|
|
18
|
+
return option;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function renderWithShapeElement(option, props) {
|
|
22
|
+
return cloneElement(option, mergeShapeProps(getPropsFromShapeOption(option), props));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getShapeIndex(shapeProps) {
|
|
26
|
+
if (!('index' in shapeProps)) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const { index } = shapeProps;
|
|
30
|
+
return typeof index === 'number' || typeof index === 'string' ? index : undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isActiveShape(shapeProps) {
|
|
34
|
+
return 'isActive' in shapeProps && shapeProps.isActive === true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function Shape(shapeOuterProps) {
|
|
38
|
+
const {
|
|
39
|
+
option,
|
|
40
|
+
DefaultShape,
|
|
41
|
+
shapeProps,
|
|
42
|
+
activeClassName = 'recharts-active-shape',
|
|
43
|
+
inActiveClassName = 'recharts-shape',
|
|
44
|
+
} = shapeOuterProps;
|
|
45
|
+
const index = getShapeIndex(shapeProps);
|
|
46
|
+
let shape;
|
|
47
|
+
if (isValidElement(option)) {
|
|
48
|
+
shape = renderWithShapeElement(option, shapeProps);
|
|
49
|
+
} else if (option === DefaultShape) {
|
|
50
|
+
shape = <DefaultShape {...shapeProps} />;
|
|
51
|
+
} else if (typeof option === 'function') {
|
|
52
|
+
shape = option(shapeProps, index);
|
|
53
|
+
} else if (typeof option === 'object') {
|
|
54
|
+
shape = <DefaultShape {...mergeShapeProps(option, shapeProps)} />;
|
|
55
|
+
} else {
|
|
56
|
+
shape = <DefaultShape {...shapeProps} />;
|
|
57
|
+
}
|
|
58
|
+
if (isActiveShape(shapeProps)) {
|
|
59
|
+
return <Layer className={activeClassName}>{shape}</Layer>;
|
|
60
|
+
}
|
|
61
|
+
return <Layer className={inActiveClassName}>{shape}</Layer>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Port of util/BarUtils.tsx — the bar shape wrapper (Rectangle by default,
|
|
2
|
+
// user overridable through the Shape helper) + the minPointSize resolver.
|
|
3
|
+
import invariant from 'tiny-invariant';
|
|
4
|
+
import { Rectangle } from '../shape/Rectangle.tsrx';
|
|
5
|
+
import { Shape } from './ActiveShapeUtils.tsrx';
|
|
6
|
+
import { isNullish, isNumber } from './DataUtils';
|
|
7
|
+
|
|
8
|
+
export const defaultBarShape = Rectangle;
|
|
9
|
+
|
|
10
|
+
export function BarRectangle(barRectangleProps) {
|
|
11
|
+
const { option, ...shapeProps } = barRectangleProps;
|
|
12
|
+
return <Shape
|
|
13
|
+
option={option}
|
|
14
|
+
DefaultShape={defaultBarShape}
|
|
15
|
+
shapeProps={shapeProps}
|
|
16
|
+
activeClassName="recharts-active-bar"
|
|
17
|
+
inActiveClassName="recharts-inactive-bar"
|
|
18
|
+
/>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Safely gets minPointSize from the minPointSize prop if it is a function
|
|
23
|
+
*/
|
|
24
|
+
export const minPointSizeCallback = (minPointSize, defaultValue = 0) => (value, index) => {
|
|
25
|
+
if (isNumber(minPointSize)) return minPointSize;
|
|
26
|
+
const isValueNumberOrNil = isNumber(value) || isNullish(value);
|
|
27
|
+
if (isValueNumberOrNil) {
|
|
28
|
+
return minPointSize(value, index);
|
|
29
|
+
}
|
|
30
|
+
invariant(
|
|
31
|
+
isValueNumberOrNil,
|
|
32
|
+
`minPointSize callback function received a value with type of ${typeof value}. Currently only numbers or null/undefined are supported.`,
|
|
33
|
+
);
|
|
34
|
+
return defaultValue;
|
|
35
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Vendored verbatim from recharts@3.9.2 es6/util/CartesianUtils.js (framework-agnostic).
|
|
2
|
+
// Do not edit — update by re-vendoring when the recharts devDependency moves.
|
|
3
|
+
export var rectWithPoints = (_ref, _ref2) => {
|
|
4
|
+
var x1 = _ref.x,
|
|
5
|
+
y1 = _ref.y;
|
|
6
|
+
var x2 = _ref2.x,
|
|
7
|
+
y2 = _ref2.y;
|
|
8
|
+
return {
|
|
9
|
+
x: Math.min(x1, x2),
|
|
10
|
+
y: Math.min(y1, y2),
|
|
11
|
+
width: Math.abs(x2 - x1),
|
|
12
|
+
height: Math.abs(y2 - y1),
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Compute the x, y, width, and height of a box from two reference points.
|
|
18
|
+
* @param {Object} coords x1, x2, y1, and y2
|
|
19
|
+
* @return {Object} object
|
|
20
|
+
*/
|
|
21
|
+
export var rectWithCoords = (_ref3) => {
|
|
22
|
+
var x1 = _ref3.x1,
|
|
23
|
+
y1 = _ref3.y1,
|
|
24
|
+
x2 = _ref3.x2,
|
|
25
|
+
y2 = _ref3.y2;
|
|
26
|
+
return rectWithPoints(
|
|
27
|
+
{
|
|
28
|
+
x: x1,
|
|
29
|
+
y: y1,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
x: x2,
|
|
33
|
+
y: y2,
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Normalizes the angle so that 0 <= angle < 180.
|
|
39
|
+
* @param {number} angle Angle in degrees.
|
|
40
|
+
* @return {number} the normalized angle with a value of at least 0 and never greater or equal to 180. */
|
|
41
|
+
export function normalizeAngle(angle) {
|
|
42
|
+
return ((angle % 180) + 180) % 180;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Calculates the width of the largest horizontal line that fits inside a rectangle that is displayed at an angle.
|
|
46
|
+
* @param {Object} size Width and height of the text in a horizontal position.
|
|
47
|
+
* @param {number} angle Angle in degrees in which the text is displayed.
|
|
48
|
+
* @return {number} The width of the largest horizontal line that fits inside a rectangle that is displayed at an angle.
|
|
49
|
+
*/
|
|
50
|
+
export var getAngledRectangleWidth = function getAngledRectangleWidth(_ref4) {
|
|
51
|
+
var width = _ref4.width,
|
|
52
|
+
height = _ref4.height;
|
|
53
|
+
var angle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
54
|
+
// Ensure angle is >= 0 && < 180
|
|
55
|
+
var normalizedAngle = normalizeAngle(angle);
|
|
56
|
+
var angleRadians = (normalizedAngle * Math.PI) / 180;
|
|
57
|
+
|
|
58
|
+
/* Depending on the height and width of the rectangle, we may need to use different formulas to calculate the angled
|
|
59
|
+
* width. This threshold defines when each formula should kick in. */
|
|
60
|
+
var angleThreshold = Math.atan(height / width);
|
|
61
|
+
var angledWidth =
|
|
62
|
+
angleRadians > angleThreshold && angleRadians < Math.PI - angleThreshold
|
|
63
|
+
? height / Math.sin(angleRadians)
|
|
64
|
+
: width / Math.cos(angleRadians);
|
|
65
|
+
return Math.abs(angledWidth);
|
|
66
|
+
};
|