@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.
Files changed (219) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +53 -0
  3. package/src/animation/AnimatedItems.tsrx +82 -0
  4. package/src/animation/AnimationControllerImpl.js +33 -0
  5. package/src/animation/AnimationHandle.js +291 -0
  6. package/src/animation/JavascriptAnimate.tsrx +81 -0
  7. package/src/animation/easing.js +193 -0
  8. package/src/animation/matchBy.js +279 -0
  9. package/src/animation/timeoutController.js +49 -0
  10. package/src/animation/useAnimationController.ts +22 -0
  11. package/src/animation/useAnimationStartSnapshot.ts +43 -0
  12. package/src/animation/util.js +11 -0
  13. package/src/cartesian/Bar.ts +4 -0
  14. package/src/cartesian/Bar.tsrx +716 -0
  15. package/src/cartesian/Bar.tsrx.d.ts +4 -0
  16. package/src/cartesian/BarStack.tsrx +97 -0
  17. package/src/cartesian/BarStack.tsrx.d.ts +6 -0
  18. package/src/cartesian/CartesianAxis.tsrx +413 -0
  19. package/src/cartesian/CartesianAxis.tsrx.d.ts +3 -0
  20. package/src/cartesian/GraphicalItemClipPath.tsrx +44 -0
  21. package/src/cartesian/Line.ts +4 -0
  22. package/src/cartesian/Line.tsrx +544 -0
  23. package/src/cartesian/Line.tsrx.d.ts +4 -0
  24. package/src/cartesian/LineDrawShape.tsrx +106 -0
  25. package/src/cartesian/LineDrawShape.tsrx.d.ts +2 -0
  26. package/src/cartesian/XAxis.tsrx +156 -0
  27. package/src/cartesian/XAxis.tsrx.d.ts +3 -0
  28. package/src/cartesian/YAxis.tsrx +183 -0
  29. package/src/cartesian/YAxis.tsrx.d.ts +3 -0
  30. package/src/cartesian/getCartesianPosition.js +277 -0
  31. package/src/cartesian/getEquidistantTicks.js +133 -0
  32. package/src/cartesian/getTicks.js +280 -0
  33. package/src/cartesian/useAnimatedLineLength.ts +33 -0
  34. package/src/chart/BarChart.tsrx +22 -0
  35. package/src/chart/BarChart.tsrx.d.ts +2 -0
  36. package/src/chart/CartesianChart.tsrx +76 -0
  37. package/src/chart/CartesianChart.tsrx.d.ts +10 -0
  38. package/src/chart/CategoricalChart.tsrx +54 -0
  39. package/src/chart/LineChart.tsrx +22 -0
  40. package/src/chart/LineChart.tsrx.d.ts +2 -0
  41. package/src/chart/RechartsWrapper.tsrx +294 -0
  42. package/src/component/ActivePoints.tsrx +76 -0
  43. package/src/component/Cell.ts +37 -0
  44. package/src/component/Dots.tsrx +74 -0
  45. package/src/component/Label.tsrx +309 -0
  46. package/src/component/Label.tsrx.d.ts +12 -0
  47. package/src/component/LabelList.tsrx +83 -0
  48. package/src/component/LabelList.tsrx.d.ts +8 -0
  49. package/src/component/ResponsiveContainer.ts +22 -0
  50. package/src/component/Text.tsrx +281 -0
  51. package/src/component/Text.tsrx.d.ts +9 -0
  52. package/src/component/responsiveContainerUtils.js +111 -0
  53. package/src/container/ClipPathProvider.tsrx +29 -0
  54. package/src/container/Layer.tsrx +9 -0
  55. package/src/container/Layer.tsrx.d.ts +6 -0
  56. package/src/container/RootSurface.tsrx +76 -0
  57. package/src/container/Surface.tsrx +23 -0
  58. package/src/container/Surface.tsrx.d.ts +12 -0
  59. package/src/context/CellsContext.ts +80 -0
  60. package/src/context/ErrorBarContext.tsrx +53 -0
  61. package/src/context/PanoramaContext.ts +10 -0
  62. package/src/context/RegisterGraphicalItemId.tsrx +19 -0
  63. package/src/context/accessibilityContext.js +10 -0
  64. package/src/context/chartDataContext.ts +57 -0
  65. package/src/context/chartLayoutContext.ts +171 -0
  66. package/src/context/legendPortalContext.ts +5 -0
  67. package/src/context/tooltipContext.js +55 -0
  68. package/src/context/tooltipPortalContext.ts +5 -0
  69. package/src/hooks.js +509 -0
  70. package/src/index.ts +64 -0
  71. package/src/internal.ts +37 -0
  72. package/src/polar/defaultPolarAngleAxisProps.js +27 -0
  73. package/src/polar/defaultPolarRadiusAxisProps.js +24 -0
  74. package/src/shape/Cross.tsrx +25 -0
  75. package/src/shape/Cross.tsrx.d.ts +12 -0
  76. package/src/shape/Curve.tsrx +132 -0
  77. package/src/shape/Curve.tsrx.d.ts +42 -0
  78. package/src/shape/Dot.tsrx +21 -0
  79. package/src/shape/Dot.tsrx.d.ts +9 -0
  80. package/src/shape/Polygon.tsrx +95 -0
  81. package/src/shape/Polygon.tsrx.d.ts +13 -0
  82. package/src/shape/Rectangle.tsrx +162 -0
  83. package/src/shape/Rectangle.tsrx.d.ts +31 -0
  84. package/src/shape/Sector.tsrx +219 -0
  85. package/src/shape/Sector.tsrx.d.ts +29 -0
  86. package/src/shape/Symbols.tsrx +95 -0
  87. package/src/shape/Symbols.tsrx.d.ts +15 -0
  88. package/src/shape/Trapezoid.tsrx +56 -0
  89. package/src/shape/Trapezoid.tsrx.d.ts +29 -0
  90. package/src/state/RechartsReduxContext.ts +7 -0
  91. package/src/state/RechartsStoreProvider.tsrx +24 -0
  92. package/src/state/ReportChartProps.ts +13 -0
  93. package/src/state/ReportEventSettings.ts +15 -0
  94. package/src/state/ReportMainChartProps.ts +22 -0
  95. package/src/state/SetGraphicalItem.ts +61 -0
  96. package/src/state/SetLegendPayload.ts +61 -0
  97. package/src/state/SetTooltipEntrySettings.ts +40 -0
  98. package/src/state/brushSlice.js +36 -0
  99. package/src/state/cartesianAxisSlice.js +256 -0
  100. package/src/state/chartDataSlice.js +67 -0
  101. package/src/state/errorBarSlice.js +53 -0
  102. package/src/state/eventSettingsSlice.js +25 -0
  103. package/src/state/externalEventsMiddleware.js +127 -0
  104. package/src/state/graphicalItemsSlice.js +91 -0
  105. package/src/state/hooks.ts +46 -0
  106. package/src/state/keyboardEventsMiddleware.js +226 -0
  107. package/src/state/layoutSlice.js +57 -0
  108. package/src/state/legendSlice.js +83 -0
  109. package/src/state/mouseEventsMiddleware.js +130 -0
  110. package/src/state/optionsSlice.js +45 -0
  111. package/src/state/polarAxisSlice.js +33 -0
  112. package/src/state/polarOptionsSlice.js +26 -0
  113. package/src/state/reduxDevtoolsJsonStringifyReplacer.js +14 -0
  114. package/src/state/referenceElementsSlice.js +51 -0
  115. package/src/state/renderedTicksSlice.js +41 -0
  116. package/src/state/rootPropsSlice.js +48 -0
  117. package/src/state/selectors/arrayEqualityCheck.js +32 -0
  118. package/src/state/selectors/axisSelectors.js +2113 -0
  119. package/src/state/selectors/barSelectors.js +263 -0
  120. package/src/state/selectors/barStackSelectors.js +65 -0
  121. package/src/state/selectors/brushSelectors.js +21 -0
  122. package/src/state/selectors/combiners/combineActiveLabel.js +18 -0
  123. package/src/state/selectors/combiners/combineActiveTooltipIndex.js +75 -0
  124. package/src/state/selectors/combiners/combineAllBarPositions.js +169 -0
  125. package/src/state/selectors/combiners/combineAxisRangeWithReverse.js +11 -0
  126. package/src/state/selectors/combiners/combineBarPosition.js +17 -0
  127. package/src/state/selectors/combiners/combineBarSizeList.js +115 -0
  128. package/src/state/selectors/combiners/combineCheckedDomain.js +44 -0
  129. package/src/state/selectors/combiners/combineConfiguredScale.js +46 -0
  130. package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.js +48 -0
  131. package/src/state/selectors/combiners/combineDisplayedStackedData.js +54 -0
  132. package/src/state/selectors/combiners/combineInverseScaleFunction.js +12 -0
  133. package/src/state/selectors/combiners/combineRealScaleType.js +36 -0
  134. package/src/state/selectors/combiners/combineStackedData.js +22 -0
  135. package/src/state/selectors/combiners/combineTooltipInteractionState.js +121 -0
  136. package/src/state/selectors/combiners/combineTooltipPayload.js +248 -0
  137. package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.js +59 -0
  138. package/src/state/selectors/containerSelectors.js +6 -0
  139. package/src/state/selectors/dataSelectors.js +97 -0
  140. package/src/state/selectors/graphicalItemSelectors.js +25 -0
  141. package/src/state/selectors/legendSelectors.js +18 -0
  142. package/src/state/selectors/lineSelectors.js +106 -0
  143. package/src/state/selectors/numberDomainEqualityCheck.js +11 -0
  144. package/src/state/selectors/pickAxisId.js +3 -0
  145. package/src/state/selectors/pickAxisType.js +3 -0
  146. package/src/state/selectors/polarAxisSelectors.js +237 -0
  147. package/src/state/selectors/rootPropsSelectors.js +13 -0
  148. package/src/state/selectors/selectActivePropsFromChartPointer.js +23 -0
  149. package/src/state/selectors/selectAllAxes.js +15 -0
  150. package/src/state/selectors/selectChartOffset.js +12 -0
  151. package/src/state/selectors/selectChartOffsetInternal.js +174 -0
  152. package/src/state/selectors/selectPlotArea.js +19 -0
  153. package/src/state/selectors/selectTooltipAxisId.js +3 -0
  154. package/src/state/selectors/selectTooltipAxisType.js +25 -0
  155. package/src/state/selectors/selectTooltipEventType.js +27 -0
  156. package/src/state/selectors/selectTooltipPayloadSearcher.js +3 -0
  157. package/src/state/selectors/selectTooltipSettings.js +3 -0
  158. package/src/state/selectors/selectTooltipState.js +3 -0
  159. package/src/state/selectors/selectors.js +222 -0
  160. package/src/state/selectors/tooltipSelectors.js +471 -0
  161. package/src/state/selectors/touchSelectors.js +31 -0
  162. package/src/state/store.js +101 -0
  163. package/src/state/tooltipSlice.js +237 -0
  164. package/src/state/touchEventsMiddleware.js +140 -0
  165. package/src/state/types/StackedGraphicalItem.js +18 -0
  166. package/src/state/zIndexSlice.js +167 -0
  167. package/src/synchronisation/syncSelectors.js +5 -0
  168. package/src/synchronisation/useChartSynchronisation.tsrx +285 -0
  169. package/src/util/ActiveShapeUtils.tsrx +62 -0
  170. package/src/util/BarUtils.tsrx +35 -0
  171. package/src/util/CartesianUtils.js +66 -0
  172. package/src/util/ChartUtils.js +630 -0
  173. package/src/util/Constants.js +42 -0
  174. package/src/util/DOMUtils.js +180 -0
  175. package/src/util/DataUtils.js +199 -0
  176. package/src/util/Events.js +7 -0
  177. package/src/util/Global.js +13 -0
  178. package/src/util/LRUCache.js +58 -0
  179. package/src/util/LogUtils.js +29 -0
  180. package/src/util/PolarUtils.js +190 -0
  181. package/src/util/ReactUtils.ts +94 -0
  182. package/src/util/ReduceCSSCalc.js +260 -0
  183. package/src/util/TickUtils.js +43 -0
  184. package/src/util/YAxisUtils.js +43 -0
  185. package/src/util/axisPropsAreEqual.js +63 -0
  186. package/src/util/createEventProxy.js +18 -0
  187. package/src/util/excludeEventProps.js +172 -0
  188. package/src/util/getActiveCoordinate.js +253 -0
  189. package/src/util/getAxisTypeBasedOnLayout.js +17 -0
  190. package/src/util/getClassNameFromUnknown.js +8 -0
  191. package/src/util/getEveryNth.js +29 -0
  192. package/src/util/getRadiusAndStrokeWidthFromDot.js +28 -0
  193. package/src/util/getRelativeCoordinate.js +96 -0
  194. package/src/util/getSliced.js +11 -0
  195. package/src/util/isDomainSpecifiedByUser.js +255 -0
  196. package/src/util/isWellBehavedNumber.js +8 -0
  197. package/src/util/propsAreEqual.js +96 -0
  198. package/src/util/resolveDefaultProps.js +131 -0
  199. package/src/util/round.js +39 -0
  200. package/src/util/scale/RechartsScale.js +68 -0
  201. package/src/util/scale/createCategoricalInverse.js +77 -0
  202. package/src/util/scale/getNiceTickValues.js +354 -0
  203. package/src/util/scale/index.js +3 -0
  204. package/src/util/scale/util/arithmetic.js +51 -0
  205. package/src/util/stacks/getStackSeriesIdentifier.js +10 -0
  206. package/src/util/svgPropertiesAndEvents.ts +29 -0
  207. package/src/util/svgPropertiesNoEvents.js +383 -0
  208. package/src/util/types.ts +59 -0
  209. package/src/util/useAnimationId.ts +14 -0
  210. package/src/util/useId.ts +13 -0
  211. package/src/util/usePrefersReducedMotion.ts +30 -0
  212. package/src/util/useReportScale.ts +26 -0
  213. package/src/util/useUniqueId.js +34 -0
  214. package/src/zIndex/DefaultZIndexes.js +75 -0
  215. package/src/zIndex/ZIndexLayer.tsrx +80 -0
  216. package/src/zIndex/ZIndexLayer.tsrx.d.ts +2 -0
  217. package/src/zIndex/ZIndexPortal.tsrx +43 -0
  218. package/src/zIndex/getZIndexFromUnknown.js +15 -0
  219. package/src/zIndex/zIndexSelectors.js +45 -0
@@ -0,0 +1,544 @@
1
+ // Port of cartesian/Line.tsx — the line graphical item: redux registration,
2
+ // store-computed points, the draw-in curve, dots, labels, active points.
3
+ // `computeLinePoints` stays here (vendored lineSelectors imports it through
4
+ // cartesian/Line.ts).
5
+ import { memo, useCallback, useMemo, useRef } from 'octane';
6
+ import { clsx } from 'clsx';
7
+ import { Layer } from '../container/Layer.tsrx';
8
+ import { LineDrawShape } from './LineDrawShape.tsrx';
9
+ import { useAnimatedLineLength } from './useAnimatedLineLength.ts';
10
+ import {
11
+ CartesianLabelListContextProvider,
12
+ LabelListFromLabelProp,
13
+ } from '../component/LabelList.tsrx';
14
+ import { interpolate, isNullish, noop } from '../util/DataUtils';
15
+ import { isClipDot } from '../util/ReactUtils.ts';
16
+ import { getCateCoordinateOfLine, getTooltipNameProp, getValueByDataKey } from '../util/ChartUtils';
17
+ import { ActivePoints } from '../component/ActivePoints.tsrx';
18
+ import { SetTooltipEntrySettings } from '../state/SetTooltipEntrySettings';
19
+ import { SetErrorBarContext } from '../context/ErrorBarContext.tsrx';
20
+ import { GraphicalItemClipPath, useNeedsClip } from './GraphicalItemClipPath.tsrx';
21
+ import { useChartLayout } from '../context/chartLayoutContext.ts';
22
+ import { useIsPanorama } from '../context/PanoramaContext.ts';
23
+ import { selectLinePoints } from '../state/selectors/lineSelectors';
24
+ import { useAppSelector } from '../state/hooks';
25
+ import { SetLegendPayload } from '../state/SetLegendPayload';
26
+ import { AnimatedItems, useAnimationCallbacks } from '../animation/AnimatedItems.tsrx';
27
+ import { matchByIndex } from '../animation/matchBy';
28
+ import { resolveDefaultProps } from '../util/resolveDefaultProps';
29
+ import { usePlotArea } from '../hooks';
30
+ import { RegisterGraphicalItemId } from '../context/RegisterGraphicalItemId.tsrx';
31
+ import { SetCartesianGraphicalItem } from '../state/SetGraphicalItem';
32
+ import { svgPropertiesNoEvents } from '../util/svgPropertiesNoEvents';
33
+ import { svgPropertiesAndEvents } from '../util/svgPropertiesAndEvents.ts';
34
+ import { getRadiusAndStrokeWidthFromDot } from '../util/getRadiusAndStrokeWidthFromDot';
35
+ import { Shape } from '../util/ActiveShapeUtils.tsrx';
36
+ import { ZIndexLayer } from '../zIndex/ZIndexLayer.tsrx';
37
+ import { DefaultZIndexes } from '../zIndex/DefaultZIndexes';
38
+ import { propsAreEqual } from '../util/propsAreEqual';
39
+ import { Dots } from '../component/Dots.tsrx';
40
+
41
+ function getTotalLength(mainCurve) {
42
+ try {
43
+ return mainCurve && mainCurve.getTotalLength && mainCurve.getTotalLength() || 0;
44
+ } catch {
45
+ return 0;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Average x-shift between matched pairs — the overall direction/magnitude of
51
+ * data movement, used to extrapolate enter/exit positions.
52
+ */
53
+ function averageShift(items) {
54
+ let total = 0;
55
+ let count = 0;
56
+ for (const item of items) {
57
+ if (item.status === 'matched' && item.prev.x != null && item.next.x != null) {
58
+ total += item.next.x - item.prev.x;
59
+ count++;
60
+ }
61
+ }
62
+ return count > 0 ? total / count : 0;
63
+ }
64
+
65
+ const defaultLineAnimateItems = (items, animationElapsedTime) => {
66
+ if (items == null) {
67
+ // First render: return empty, stroke-dasharray handles the reveal
68
+ return [];
69
+ }
70
+ // At animationElapsedTime=1 return only the non-removed items
71
+ if (animationElapsedTime === 1) {
72
+ return items.flatMap((item) => (item.status === 'removed' ? [] : [item.next]));
73
+ }
74
+ const shift = averageShift(items);
75
+ const result = [];
76
+ for (const item of items) {
77
+ if (item.status === 'matched') {
78
+ result.push({
79
+ ...item.next,
80
+ x: interpolate(item.prev.x, item.next.x, animationElapsedTime),
81
+ y: interpolate(item.prev.y, item.next.y, animationElapsedTime),
82
+ });
83
+ } else if (item.status === 'added') {
84
+ if (item.next.x != null) {
85
+ // Extrapolate entry position: the point starts where it "would have been"
86
+ const entryX = item.next.x - shift;
87
+ result.push({
88
+ ...item.next,
89
+ x: interpolate(entryX, item.next.x, animationElapsedTime),
90
+ y: item.next.y,
91
+ });
92
+ } else {
93
+ result.push(item.next);
94
+ }
95
+ } else if (item.status === 'removed') {
96
+ if (item.prev.x != null) {
97
+ const exitX = item.prev.x + shift;
98
+ result.push({
99
+ ...item.prev,
100
+ x: interpolate(item.prev.x, exitX, animationElapsedTime),
101
+ y: item.prev.y,
102
+ });
103
+ }
104
+ // else: removed items are simply dropped
105
+ }
106
+ }
107
+ return result;
108
+ };
109
+
110
+ export const defaultLineProps = {
111
+ activeDot: true,
112
+ animateNewValues: true,
113
+ animationBegin: 0,
114
+ animationDuration: 1500,
115
+ animationEasing: 'ease',
116
+ animationInterpolateFn: defaultLineAnimateItems,
117
+ animationMatchBy: matchByIndex,
118
+ connectNulls: false,
119
+ dot: true,
120
+ fill: '#fff',
121
+ hide: false,
122
+ isAnimationActive: 'auto',
123
+ label: false,
124
+ legendType: 'line',
125
+ shape: LineDrawShape,
126
+ stroke: '#3182bd',
127
+ strokeWidth: 1,
128
+ xAxisId: 0,
129
+ yAxisId: 0,
130
+ zIndex: DefaultZIndexes.line,
131
+ type: 'linear',
132
+ };
133
+
134
+ const computeLegendPayloadFromAreaData = (props) => {
135
+ const { dataKey, name, stroke, legendType, hide } = props;
136
+ return [
137
+ {
138
+ inactive: hide,
139
+ dataKey,
140
+ type: legendType,
141
+ color: stroke,
142
+ value: getTooltipNameProp(name, dataKey),
143
+ payload: props,
144
+ },
145
+ ];
146
+ };
147
+
148
+ const SetLineTooltipEntrySettings = memo((props) => {
149
+ const {
150
+ dataKey,
151
+ data,
152
+ stroke,
153
+ strokeWidth,
154
+ fill,
155
+ name,
156
+ hide,
157
+ unit,
158
+ formatter,
159
+ tooltipType,
160
+ id,
161
+ } = props;
162
+ const tooltipEntrySettings = {
163
+ dataDefinedOnItem: data,
164
+ getPosition: noop,
165
+ settings: {
166
+ stroke,
167
+ strokeWidth,
168
+ fill,
169
+ dataKey,
170
+ nameKey: undefined,
171
+ name: getTooltipNameProp(name, dataKey),
172
+ hide,
173
+ type: tooltipType,
174
+ color: stroke,
175
+ unit,
176
+ formatter,
177
+ graphicalItemId: id,
178
+ },
179
+ };
180
+ return <SetTooltipEntrySettings tooltipEntrySettings={tooltipEntrySettings} />;
181
+ });
182
+
183
+ function LineDotsWrapper(props) {
184
+ const { clipPathId, points } = props;
185
+ const { dot, dataKey, needClip } = props.props;
186
+ // Exclude ID so it isn't duplicated across every dot.
187
+ const { id, ...propsWithoutId } = props.props;
188
+ const lineProps = svgPropertiesNoEvents(propsWithoutId);
189
+ return <Dots
190
+ points={points}
191
+ dot={dot}
192
+ className="recharts-line-dots"
193
+ dotClassName="recharts-line-dot"
194
+ dataKey={dataKey}
195
+ baseProps={lineProps}
196
+ needClip={needClip}
197
+ clipPathId={clipPathId}
198
+ />;
199
+ }
200
+
201
+ function LineLabelListProvider(props) @{
202
+ const { showLabels, children, points } = props;
203
+ const labelListEntries = useMemo(() => {
204
+ return points?.map((point) => {
205
+ const viewBox = {
206
+ x: point.x ?? 0,
207
+ y: point.y ?? 0,
208
+ width: 0,
209
+ lowerWidth: 0,
210
+ upperWidth: 0,
211
+ height: 0,
212
+ };
213
+ return {
214
+ ...viewBox,
215
+ value: point.value,
216
+ payload: point.payload,
217
+ viewBox,
218
+ parentViewBox: undefined,
219
+ fill: undefined,
220
+ };
221
+ });
222
+ }, [points]);
223
+ <CartesianLabelListContextProvider
224
+ value={showLabels ? labelListEntries : undefined}
225
+ >{children}</CartesianLabelListContextProvider>
226
+ }
227
+
228
+ function StaticCurve(staticCurveProps) {
229
+ const {
230
+ clipPathId,
231
+ pathRef,
232
+ points,
233
+ props,
234
+ animationElapsedTime,
235
+ isAnimating,
236
+ isEntrance,
237
+ visibleLength,
238
+ } = staticCurveProps;
239
+ const { type, layout, connectNulls, needClip, shape, strokeDasharray, ...others } = props;
240
+ const curveProps = {
241
+ ...svgPropertiesAndEvents(others),
242
+ fill: 'none',
243
+ className: 'recharts-line-curve',
244
+ clipPath: needClip ? 'url(#clipPath-' + clipPathId + ')' : undefined,
245
+ points,
246
+ type,
247
+ layout,
248
+ connectNulls,
249
+ strokeDasharray: strokeDasharray ?? props.strokeDasharray,
250
+ pathRef,
251
+ animationElapsedTime,
252
+ isAnimating,
253
+ isEntrance: props.animateNewValues ? isEntrance : false,
254
+ visibleLength,
255
+ };
256
+ return <>
257
+ {points?.length > 1 &&
258
+ <Shape option={shape} DefaultShape={defaultLineProps.shape} shapeProps={curveProps} />}
259
+ <LineDotsWrapper points={points} clipPathId={clipPathId} props={props} />
260
+ </>;
261
+ }
262
+
263
+ function CurveWithAnimation(curveWithAnimationProps) {
264
+ const { clipPathId, props, pathRef, previousPointsRef } = curveWithAnimationProps;
265
+ const {
266
+ points,
267
+ isAnimationActive,
268
+ animationBegin,
269
+ animationDuration,
270
+ animationEasing,
271
+ animationMatchBy,
272
+ animationInterpolateFn,
273
+ layout,
274
+ } = props;
275
+ const totalLength = getTotalLength(pathRef.current);
276
+ const { isAnimating, handleAnimationStart, handleAnimationEnd } = useAnimationCallbacks(
277
+ props.onAnimationStart,
278
+ props.onAnimationEnd,
279
+ );
280
+ const showLabels = !isAnimating;
281
+ const getVisibleLength = useAnimatedLineLength(points);
282
+ // Don't update previousPointsRef before the SVG path is measured.
283
+ const shouldUpdatePreviousRef = useCallback(
284
+ (animationElapsedTime) => animationElapsedTime > 0 && totalLength > 0,
285
+ [totalLength],
286
+ );
287
+ return <LineLabelListProvider points={points} showLabels={showLabels}>
288
+ {props.children}
289
+ <AnimatedItems
290
+ animationInput={points}
291
+ animationIdPrefix="recharts-line-"
292
+ items={points}
293
+ previousItemsRef={previousPointsRef}
294
+ isAnimationActive={isAnimationActive}
295
+ animationBegin={animationBegin}
296
+ animationDuration={animationDuration}
297
+ animationEasing={animationEasing}
298
+ onAnimationStart={handleAnimationStart}
299
+ onAnimationEnd={handleAnimationEnd}
300
+ animationInterpolateFn={animationInterpolateFn}
301
+ animationMatchBy={animationMatchBy}
302
+ shouldUpdatePreviousRef={shouldUpdatePreviousRef}
303
+ layout={layout}
304
+ >
305
+ {(stepData, animationElapsedTime, isEntrance) => {
306
+ const animationActive = isAnimating || animationElapsedTime < 1;
307
+ const visibleLength =
308
+ animationActive ? getVisibleLength(animationElapsedTime, totalLength) : null;
309
+ return <StaticCurve
310
+ props={props}
311
+ points={stepData}
312
+ clipPathId={clipPathId}
313
+ pathRef={pathRef}
314
+ animationElapsedTime={animationElapsedTime}
315
+ isAnimating={animationActive}
316
+ isEntrance={isEntrance}
317
+ visibleLength={visibleLength}
318
+ />;
319
+ }}
320
+ </AnimatedItems>
321
+ <LabelListFromLabelProp label={props.label} />
322
+ </LineLabelListProvider>;
323
+ }
324
+
325
+ function RenderCurve(props) {
326
+ const { clipPathId } = props;
327
+ const previousPointsRef = useRef(null);
328
+ const pathRef = useRef(null);
329
+ return <CurveWithAnimation
330
+ props={props.props}
331
+ clipPathId={clipPathId}
332
+ previousPointsRef={previousPointsRef}
333
+ pathRef={pathRef}
334
+ />;
335
+ }
336
+
337
+ const errorBarDataPointFormatter = (dataPoint, dataKey) => {
338
+ return {
339
+ x: dataPoint.x ?? undefined,
340
+ y: dataPoint.y ?? undefined,
341
+ value: dataPoint.value,
342
+ // getValueByDataKey does not validate the output type
343
+ errorVal: getValueByDataKey(dataPoint.payload, dataKey),
344
+ };
345
+ };
346
+
347
+ function LineWithState(props) @{
348
+ const {
349
+ hide,
350
+ dot,
351
+ points,
352
+ className,
353
+ xAxisId,
354
+ yAxisId,
355
+ top,
356
+ left,
357
+ width,
358
+ height,
359
+ id,
360
+ needClip,
361
+ zIndex,
362
+ } = props;
363
+ if (hide) {
364
+ return null;
365
+ }
366
+ const layerClass = clsx('recharts-line', className);
367
+ const clipPathId = id;
368
+ const { r, strokeWidth } = getRadiusAndStrokeWidthFromDot(dot);
369
+ const clipDot = isClipDot(dot);
370
+ const dotSize = r * 2 + strokeWidth;
371
+ const activePointsClipPath = needClip
372
+ ? 'url(#clipPath-' + (clipDot ? '' : 'dots-') + clipPathId + ')'
373
+ : undefined;
374
+ <>
375
+ <ZIndexLayer zIndex={zIndex}>
376
+ <Layer className={layerClass}>
377
+ @if (needClip) {
378
+ <defs>
379
+ <GraphicalItemClipPath clipPathId={clipPathId} xAxisId={xAxisId} yAxisId={yAxisId} />
380
+ @if (!clipDot) {
381
+ <clipPath id={'clipPath-dots-' + clipPathId}>
382
+ <rect
383
+ x={left - dotSize / 2}
384
+ y={top - dotSize / 2}
385
+ width={width + dotSize}
386
+ height={height + dotSize}
387
+ />
388
+ </clipPath>
389
+ }
390
+ </defs>
391
+ }
392
+ <SetErrorBarContext
393
+ xAxisId={xAxisId}
394
+ yAxisId={yAxisId}
395
+ data={points}
396
+ dataPointFormatter={errorBarDataPointFormatter}
397
+ errorBarOffset={0}
398
+ >
399
+ <RenderCurve props={props} clipPathId={clipPathId} />
400
+ </SetErrorBarContext>
401
+ </Layer>
402
+ </ZIndexLayer>
403
+ <ActivePoints
404
+ activeDot={props.activeDot}
405
+ points={points}
406
+ mainColor={props.stroke}
407
+ itemDataKey={props.dataKey}
408
+ clipPath={activePointsClipPath}
409
+ />
410
+ </>
411
+ }
412
+
413
+ function LineImpl(props) {
414
+ const {
415
+ activeDot,
416
+ animateNewValues,
417
+ animationBegin,
418
+ animationDuration,
419
+ animationEasing,
420
+ connectNulls,
421
+ dot,
422
+ hide,
423
+ isAnimationActive,
424
+ label,
425
+ legendType,
426
+ xAxisId,
427
+ yAxisId,
428
+ id,
429
+ ...everythingElse
430
+ } = resolveDefaultProps(props, defaultLineProps);
431
+ const { needClip } = useNeedsClip(xAxisId, yAxisId);
432
+ const plotArea = usePlotArea();
433
+ const layout = useChartLayout();
434
+ const isPanorama = useIsPanorama();
435
+ const points = useAppSelector(
436
+ (state) => selectLinePoints(state, xAxisId, yAxisId, isPanorama, id),
437
+ );
438
+ if (layout !== 'horizontal' && layout !== 'vertical' || points == null || plotArea == null) {
439
+ // Cannot render Line in an unsupported layout
440
+ return null;
441
+ }
442
+ const { height, width, x: left, y: top } = plotArea;
443
+ return <LineWithState
444
+ {...everythingElse}
445
+ id={id}
446
+ connectNulls={connectNulls}
447
+ dot={dot}
448
+ activeDot={activeDot}
449
+ animateNewValues={animateNewValues}
450
+ animationBegin={animationBegin}
451
+ animationDuration={animationDuration}
452
+ animationEasing={animationEasing}
453
+ isAnimationActive={isAnimationActive}
454
+ hide={hide}
455
+ label={label}
456
+ legendType={legendType}
457
+ xAxisId={xAxisId}
458
+ yAxisId={yAxisId}
459
+ points={points}
460
+ layout={layout}
461
+ height={height}
462
+ width={width}
463
+ left={left}
464
+ top={top}
465
+ needClip={needClip}
466
+ />;
467
+ }
468
+
469
+ export function computeLinePoints({
470
+ layout,
471
+ xAxis,
472
+ yAxis,
473
+ xAxisTicks,
474
+ yAxisTicks,
475
+ dataKey,
476
+ bandSize,
477
+ displayedData,
478
+ }) {
479
+ return displayedData.map((entry, index) => {
480
+ // getValueByDataKey does not validate the output type
481
+ const value = getValueByDataKey(entry, dataKey);
482
+ if (layout === 'horizontal') {
483
+ const x = getCateCoordinateOfLine({ axis: xAxis, ticks: xAxisTicks, bandSize, entry, index });
484
+ const y =
485
+ isNullish(value) ? null : yAxis.scale.map(value);
486
+ return {
487
+ x,
488
+ y: y ?? null,
489
+ value,
490
+ payload: entry,
491
+ };
492
+ }
493
+ const x =
494
+ isNullish(value) ? null : xAxis.scale.map(value);
495
+ const y = getCateCoordinateOfLine({ axis: yAxis, ticks: yAxisTicks, bandSize, entry, index });
496
+ if (x == null || y == null) {
497
+ return null;
498
+ }
499
+ return { x, y, value, payload: entry };
500
+ }).filter(Boolean);
501
+ }
502
+
503
+ function LineFn(outsideProps) {
504
+ const props = resolveDefaultProps(outsideProps, defaultLineProps);
505
+ const isPanorama = useIsPanorama();
506
+ return <RegisterGraphicalItemId id={props.id} type="line">
507
+ {(id) => <>
508
+ <SetLegendPayload legendPayload={computeLegendPayloadFromAreaData(props)} />
509
+ <SetLineTooltipEntrySettings
510
+ dataKey={props.dataKey}
511
+ data={props.data}
512
+ stroke={props.stroke}
513
+ strokeWidth={props.strokeWidth}
514
+ fill={props.fill}
515
+ name={props.name}
516
+ hide={props.hide}
517
+ unit={props.unit}
518
+ formatter={props.formatter}
519
+ tooltipType={props.tooltipType}
520
+ id={id}
521
+ />
522
+ <SetCartesianGraphicalItem
523
+ type="line"
524
+ id={id}
525
+ data={props.data}
526
+ xAxisId={props.xAxisId}
527
+ yAxisId={props.yAxisId}
528
+ zAxisId={0}
529
+ dataKey={props.dataKey}
530
+ hide={props.hide}
531
+ isPanorama={isPanorama}
532
+ />
533
+ <LineImpl {...props} id={id} />
534
+ </>}
535
+ </RegisterGraphicalItemId>;
536
+ }
537
+
538
+ /**
539
+ * @provides LabelListContext
540
+ * @provides ErrorBarContext
541
+ * @consumes CartesianChartContext
542
+ */
543
+ export const Line = memo(LineFn, propsAreEqual);
544
+ Line.displayName = 'Line';
@@ -0,0 +1,4 @@
1
+ // Type declaration for the .tsrx component (resolved by relative path).
2
+ export declare const defaultLineProps: Record<string, unknown>;
3
+ export declare const Line: (props: Record<string, unknown>) => unknown;
4
+ export declare function computeLinePoints(input: Record<string, unknown>): unknown[];
@@ -0,0 +1,106 @@
1
+ // Port of cartesian/LineDrawShape.tsx — the default Line shape: the entrance
2
+ // animation progressively reveals the path via stroke-dasharray.
3
+ import { Curve } from '../shape/Curve.tsrx';
4
+
5
+ /**
6
+ * Reads the total length of an SVG path element, returning 0 if the element
7
+ * is null or the measurement fails (e.g. in JSDOM).
8
+ */
9
+ function getTotalLength(path) {
10
+ try {
11
+ return path && path.getTotalLength && path.getTotalLength() || 0;
12
+ } catch {
13
+ return 0;
14
+ }
15
+ }
16
+
17
+ // Uses `totalLength` as the gap (not totalLength - length) to dodge a
18
+ // float-serialization artifact that paints a phantom endpoint dot with
19
+ // round/square linecaps.
20
+ function generateSimpleStrokeDasharray(totalLength, length) {
21
+ return length + 'px ' + totalLength + 'px';
22
+ }
23
+
24
+ // Odd-length stroke-dasharray values repeat once ("5" behaves like "5 5").
25
+ function normalizeDashPattern(lines) {
26
+ return lines.length % 2 !== 0 ? [...lines, ...lines] : lines;
27
+ }
28
+
29
+ function repeat(lines, count) {
30
+ const result = [];
31
+ for (let i = 0; i < count; ++i) {
32
+ result.push(...lines);
33
+ }
34
+ return result;
35
+ }
36
+
37
+ /**
38
+ * Builds a dasharray that reveals exactly `length` pixels of the user's dash
39
+ * pattern, followed by a `totalLength` gap hiding the rest.
40
+ */
41
+ function getStrokeDasharray(length, totalLength, lines) {
42
+ const normalizedLines = normalizeDashPattern(lines);
43
+ const lineLength = normalizedLines.reduce((pre, next) => pre + next, 0);
44
+ // if lineLength is 0 return the default when no strokeDasharray is provided
45
+ if (!lineLength) {
46
+ return generateSimpleStrokeDasharray(totalLength, length);
47
+ }
48
+ const count = Math.floor(length / lineLength);
49
+ const remainLength = length % lineLength;
50
+ let remainLines = [];
51
+ for (let i = 0, sum = 0; i < normalizedLines.length; (sum += normalizedLines[i] ?? 0, ++i)) {
52
+ const lineValue = normalizedLines[i];
53
+ if (lineValue != null && sum + lineValue > remainLength) {
54
+ remainLines = [...normalizedLines.slice(0, i), remainLength - sum];
55
+ break;
56
+ }
57
+ }
58
+ const emptyLines =
59
+ remainLines.length % 2 === 0 ? [0, totalLength] : [totalLength];
60
+ return [...repeat(normalizedLines, count), ...remainLines, ...emptyLines].map(
61
+ (line) => line + 'px',
62
+ ).join(', ');
63
+ }
64
+
65
+ function computeAnimatedStrokeDasharray(userStrokeDasharray, totalLength, visibleLength) {
66
+ if (userStrokeDasharray) {
67
+ const lines = String(userStrokeDasharray).split(/[,\s]+/gim).map((num) => parseFloat(num));
68
+ return getStrokeDasharray(visibleLength, totalLength, lines);
69
+ }
70
+ return generateSimpleStrokeDasharray(totalLength, visibleLength);
71
+ }
72
+
73
+ /**
74
+ * The default shape for Line: the entrance animation reveals the path through
75
+ * `strokeDasharray` as animationElapsedTime goes 0 → 1.
76
+ * @since 3.9
77
+ */
78
+ export function LineDrawShape(props) {
79
+ const {
80
+ animationElapsedTime,
81
+ isAnimating,
82
+ isEntrance,
83
+ visibleLength,
84
+ strokeDasharray: userStrokeDasharray,
85
+ connectNulls,
86
+ ...curveProps
87
+ } = props;
88
+ const finalConnectNulls = connectNulls ?? false;
89
+ let strokeDasharray;
90
+ if (visibleLength != null) {
91
+ const { pathRef } = curveProps;
92
+ const totalLength = getTotalLength(pathRef?.current ?? null);
93
+ strokeDasharray = computeAnimatedStrokeDasharray(
94
+ userStrokeDasharray,
95
+ totalLength,
96
+ visibleLength,
97
+ );
98
+ } else if (userStrokeDasharray != null) {
99
+ strokeDasharray = String(userStrokeDasharray);
100
+ }
101
+ return <Curve
102
+ {...curveProps}
103
+ connectNulls={finalConnectNulls}
104
+ strokeDasharray={strokeDasharray}
105
+ />;
106
+ }
@@ -0,0 +1,2 @@
1
+ // Type declaration for the .tsrx component (resolved by relative path).
2
+ export declare const LineDrawShape: (props: Record<string, unknown>) => unknown;