@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.
Files changed (306) hide show
  1. package/LICENSE +22 -0
  2. package/NOTICE +19 -0
  3. package/README.md +102 -0
  4. package/dist/dev.js +28564 -0
  5. package/dist/index.d.ts +7859 -0
  6. package/dist/index.js +28546 -0
  7. package/package.json +98 -0
  8. package/src/animation/AnimatedItems.tsx +183 -0
  9. package/src/animation/AnimationController.ts +33 -0
  10. package/src/animation/AnimationControllerImpl.ts +36 -0
  11. package/src/animation/AnimationHandle.ts +307 -0
  12. package/src/animation/CSSTransitionAnimate.tsx +170 -0
  13. package/src/animation/JavascriptAnimate.tsx +119 -0
  14. package/src/animation/easing.ts +221 -0
  15. package/src/animation/matchBy.ts +164 -0
  16. package/src/animation/timeoutController.ts +70 -0
  17. package/src/animation/useAnimationController.tsx +34 -0
  18. package/src/animation/useAnimationStartSnapshot.ts +118 -0
  19. package/src/animation/util.ts +41 -0
  20. package/src/cartesian/Area.tsx +915 -0
  21. package/src/cartesian/AreaRevealShape.tsx +190 -0
  22. package/src/cartesian/Bar.tsx +1369 -0
  23. package/src/cartesian/BarStack.tsx +152 -0
  24. package/src/cartesian/Brush.tsx +951 -0
  25. package/src/cartesian/CartesianAxis.tsx +722 -0
  26. package/src/cartesian/CartesianGrid.tsx +711 -0
  27. package/src/cartesian/ErrorBar.tsx +361 -0
  28. package/src/cartesian/Funnel.tsx +803 -0
  29. package/src/cartesian/GraphicalItemClipPath.tsx +67 -0
  30. package/src/cartesian/Line.tsx +863 -0
  31. package/src/cartesian/LineDrawShape.tsx +89 -0
  32. package/src/cartesian/ReferenceArea.tsx +331 -0
  33. package/src/cartesian/ReferenceDot.tsx +304 -0
  34. package/src/cartesian/ReferenceLine.tsx +474 -0
  35. package/src/cartesian/Scatter.tsx +888 -0
  36. package/src/cartesian/XAxis.tsx +433 -0
  37. package/src/cartesian/YAxis.tsx +443 -0
  38. package/src/cartesian/ZAxis.tsx +155 -0
  39. package/src/cartesian/cartesianPositionToCSSTranslate.tsx +29 -0
  40. package/src/cartesian/cartesianViewBoxToTrapezoid.tsx +21 -0
  41. package/src/cartesian/getCartesianPosition.tsx +267 -0
  42. package/src/cartesian/getEquidistantTicks.ts +144 -0
  43. package/src/cartesian/getTicks.ts +225 -0
  44. package/src/cartesian/isOutsidePosition.ts +15 -0
  45. package/src/cartesian/useAnimatedLineLength.ts +54 -0
  46. package/src/chart/AreaChart.tsx +29 -0
  47. package/src/chart/BarChart.tsx +29 -0
  48. package/src/chart/CartesianChart.tsx +131 -0
  49. package/src/chart/CategoricalChart.tsx +94 -0
  50. package/src/chart/ComposedChart.tsx +29 -0
  51. package/src/chart/FunnelChart.tsx +29 -0
  52. package/src/chart/LineChart.tsx +29 -0
  53. package/src/chart/PieChart.tsx +50 -0
  54. package/src/chart/PolarChart.tsx +164 -0
  55. package/src/chart/RadarChart.tsx +70 -0
  56. package/src/chart/RadialBarChart.tsx +46 -0
  57. package/src/chart/RechartsWrapper.tsx +551 -0
  58. package/src/chart/Sankey.tsx +1534 -0
  59. package/src/chart/ScatterChart.tsx +29 -0
  60. package/src/chart/SunburstChart.tsx +504 -0
  61. package/src/chart/Treemap.tsx +1223 -0
  62. package/src/chart/createInitialRootProps.ts +24 -0
  63. package/src/chart/types.ts +53 -0
  64. package/src/component/ActivePoints.tsx +144 -0
  65. package/src/component/Cell.tsx +37 -0
  66. package/src/component/Cursor.tsx +185 -0
  67. package/src/component/Customized.tsx +50 -0
  68. package/src/component/DefaultLegendContent.tsx +348 -0
  69. package/src/component/DefaultTooltipContent.tsx +224 -0
  70. package/src/component/Dots.tsx +157 -0
  71. package/src/component/Label.tsx +636 -0
  72. package/src/component/LabelList.tsx +375 -0
  73. package/src/component/Legend.tsx +512 -0
  74. package/src/component/ResponsiveContainer.tsx +348 -0
  75. package/src/component/Text.tsx +541 -0
  76. package/src/component/Tooltip.tsx +470 -0
  77. package/src/component/TooltipBoundingBox.tsx +146 -0
  78. package/src/component/responsiveContainerUtils.ts +134 -0
  79. package/src/container/ClipPathProvider.tsx +51 -0
  80. package/src/container/Layer.tsx +38 -0
  81. package/src/container/RootSurface.tsx +120 -0
  82. package/src/container/Surface.tsx +61 -0
  83. package/src/context/CellsContext.tsx +54 -0
  84. package/src/context/ErrorBarContext.tsx +146 -0
  85. package/src/context/GraphicalItemChildrenScope.tsx +18 -0
  86. package/src/context/PanoramaContext.tsx +9 -0
  87. package/src/context/RegisterGraphicalItemId.tsx +30 -0
  88. package/src/context/accessibilityContext.tsx +6 -0
  89. package/src/context/brushUpdateContext.tsx +9 -0
  90. package/src/context/chartDataContext.tsx +97 -0
  91. package/src/context/chartLayoutContext.tsx +201 -0
  92. package/src/context/legendPayloadContext.tsx +20 -0
  93. package/src/context/legendPortalContext.tsx +12 -0
  94. package/src/context/tooltipContext.tsx +89 -0
  95. package/src/context/tooltipPortalContext.tsx +12 -0
  96. package/src/context/useTooltipAxis.ts +22 -0
  97. package/src/hooks.ts +476 -0
  98. package/src/index.ts +280 -0
  99. package/src/polar/Pie.tsx +1360 -0
  100. package/src/polar/PolarAngleAxis.tsx +616 -0
  101. package/src/polar/PolarGrid.tsx +312 -0
  102. package/src/polar/PolarRadiusAxis.tsx +547 -0
  103. package/src/polar/Radar.tsx +734 -0
  104. package/src/polar/RadialBar.tsx +917 -0
  105. package/src/polar/defaultPolarAngleAxisProps.tsx +27 -0
  106. package/src/polar/defaultPolarRadiusAxisProps.tsx +25 -0
  107. package/src/shape/Cross.tsx +89 -0
  108. package/src/shape/Curve.tsx +343 -0
  109. package/src/shape/Dot.tsx +70 -0
  110. package/src/shape/Polygon.tsx +195 -0
  111. package/src/shape/Rectangle.tsx +470 -0
  112. package/src/shape/Sector.tsx +347 -0
  113. package/src/shape/Symbols.tsx +139 -0
  114. package/src/shape/Trapezoid.tsx +280 -0
  115. package/src/state/RechartsStateContext.tsx +12 -0
  116. package/src/state/RechartsStateProvider.tsx +87 -0
  117. package/src/state/RechartsStoreContext.tsx +25 -0
  118. package/src/state/RechartsStoreProvider.tsx +35 -0
  119. package/src/state/ReportChartProps.tsx +40 -0
  120. package/src/state/ReportEventSettings.tsx +30 -0
  121. package/src/state/ReportMainChartProps.tsx +61 -0
  122. package/src/state/ReportPolarOptions.tsx +35 -0
  123. package/src/state/SetGraphicalItem.ts +79 -0
  124. package/src/state/SetLegendPayload.ts +134 -0
  125. package/src/state/SetTooltipEntrySettings.tsx +72 -0
  126. package/src/state/actions.ts +464 -0
  127. package/src/state/brushSlice.ts +13 -0
  128. package/src/state/cartesianAxisSlice.ts +141 -0
  129. package/src/state/chartDataSlice.ts +50 -0
  130. package/src/state/chartState.ts +297 -0
  131. package/src/state/errorBarSlice.ts +29 -0
  132. package/src/state/eventSettingsSlice.ts +8 -0
  133. package/src/state/events.ts +76 -0
  134. package/src/state/externalEventsMiddleware.ts +255 -0
  135. package/src/state/graphicalItemsSlice.ts +74 -0
  136. package/src/state/hooks/useChartSelectors.tsx +45 -0
  137. package/src/state/keyboardEventsMiddleware.ts +228 -0
  138. package/src/state/layoutSlice.ts +21 -0
  139. package/src/state/legendSlice.ts +57 -0
  140. package/src/state/mouseEventsMiddleware.ts +185 -0
  141. package/src/state/optionsSlice.ts +47 -0
  142. package/src/state/polarAxisSlice.ts +10 -0
  143. package/src/state/polarOptionsSlice.ts +12 -0
  144. package/src/state/rawData.ts +26 -0
  145. package/src/state/referenceElementsSlice.ts +40 -0
  146. package/src/state/renderedTicksSlice.ts +15 -0
  147. package/src/state/rootPropsSlice.ts +47 -0
  148. package/src/state/selectors/areaSelectors.ts +240 -0
  149. package/src/state/selectors/arrayEqualityCheck.ts +29 -0
  150. package/src/state/selectors/axisSelectors.ts +2157 -0
  151. package/src/state/selectors/barSelectors.ts +310 -0
  152. package/src/state/selectors/barStackSelectors.ts +77 -0
  153. package/src/state/selectors/brushSelectors.ts +33 -0
  154. package/src/state/selectors/chartSelector.ts +185 -0
  155. package/src/state/selectors/combiners/combineActiveLabel.ts +16 -0
  156. package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +95 -0
  157. package/src/state/selectors/combiners/combineAllBarPositions.ts +122 -0
  158. package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +16 -0
  159. package/src/state/selectors/combiners/combineBarPosition.ts +23 -0
  160. package/src/state/selectors/combiners/combineBarSizeList.ts +80 -0
  161. package/src/state/selectors/combiners/combineCheckedDomain.ts +48 -0
  162. package/src/state/selectors/combiners/combineConfiguredScale.ts +111 -0
  163. package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +45 -0
  164. package/src/state/selectors/combiners/combineDisplayedStackedData.ts +50 -0
  165. package/src/state/selectors/combiners/combineInverseScaleFunction.ts +16 -0
  166. package/src/state/selectors/combiners/combineRealScaleType.ts +44 -0
  167. package/src/state/selectors/combiners/combineStackedData.ts +27 -0
  168. package/src/state/selectors/combiners/combineTooltipInteractionState.ts +86 -0
  169. package/src/state/selectors/combiners/combineTooltipPayload.ts +205 -0
  170. package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +58 -0
  171. package/src/state/selectors/containerSelectors.ts +12 -0
  172. package/src/state/selectors/dataSelectors.ts +88 -0
  173. package/src/state/selectors/funnelSelectors.ts +75 -0
  174. package/src/state/selectors/graphicalItemSelectors.ts +30 -0
  175. package/src/state/selectors/legendSelectors.ts +29 -0
  176. package/src/state/selectors/lineSelectors.ts +134 -0
  177. package/src/state/selectors/numberDomainEqualityCheck.ts +14 -0
  178. package/src/state/selectors/pickAxisId.ts +5 -0
  179. package/src/state/selectors/pickAxisType.ts +3 -0
  180. package/src/state/selectors/pieSelectors.ts +97 -0
  181. package/src/state/selectors/polarAxisSelectors.ts +201 -0
  182. package/src/state/selectors/polarGridSelectors.ts +28 -0
  183. package/src/state/selectors/polarScaleSelectors.ts +133 -0
  184. package/src/state/selectors/polarSelectors.ts +219 -0
  185. package/src/state/selectors/radarSelectors.ts +191 -0
  186. package/src/state/selectors/radialBarSelectors.ts +435 -0
  187. package/src/state/selectors/rootPropsSelectors.ts +25 -0
  188. package/src/state/selectors/scatterSelectors.ts +96 -0
  189. package/src/state/selectors/selectActivePropsFromChartPointer.ts +26 -0
  190. package/src/state/selectors/selectAllAxes.ts +17 -0
  191. package/src/state/selectors/selectChartOffset.ts +16 -0
  192. package/src/state/selectors/selectChartOffsetInternal.ts +136 -0
  193. package/src/state/selectors/selectLegendArea.ts +20 -0
  194. package/src/state/selectors/selectPlotArea.ts +22 -0
  195. package/src/state/selectors/selectTooltipAxisId.ts +7 -0
  196. package/src/state/selectors/selectTooltipAxisType.ts +32 -0
  197. package/src/state/selectors/selectTooltipEventType.ts +48 -0
  198. package/src/state/selectors/selectTooltipPayloadSearcher.ts +6 -0
  199. package/src/state/selectors/selectTooltipSettings.ts +39 -0
  200. package/src/state/selectors/selectTooltipState.ts +8 -0
  201. package/src/state/selectors/selectors.ts +271 -0
  202. package/src/state/selectors/tooltipSelectors.ts +578 -0
  203. package/src/state/selectors/touchSelectors.ts +31 -0
  204. package/src/state/store.ts +29 -0
  205. package/src/state/storeIdentity.ts +9 -0
  206. package/src/state/teardownWrite.ts +10 -0
  207. package/src/state/tooltipInteraction.ts +23 -0
  208. package/src/state/tooltipSlice.ts +334 -0
  209. package/src/state/touchEventsMiddleware.ts +214 -0
  210. package/src/state/types/AnimationSettings.ts +20 -0
  211. package/src/state/types/AreaSettings.ts +14 -0
  212. package/src/state/types/BarSettings.ts +15 -0
  213. package/src/state/types/LineSettings.ts +9 -0
  214. package/src/state/types/PieSettings.ts +34 -0
  215. package/src/state/types/RadarSettings.ts +5 -0
  216. package/src/state/types/RadialBarSettings.ts +10 -0
  217. package/src/state/types/ScatterSettings.ts +12 -0
  218. package/src/state/types/StackedGraphicalItem.ts +34 -0
  219. package/src/state/useChartState.ts +17 -0
  220. package/src/state/zIndexSlice.ts +39 -0
  221. package/src/synchronisation/syncSelectors.ts +7 -0
  222. package/src/synchronisation/types.ts +44 -0
  223. package/src/synchronisation/useChartSynchronisation.tsx +404 -0
  224. package/src/theme/RechartsTheme.ts +16 -0
  225. package/src/theme/RechartsThemeContext.ts +19 -0
  226. package/src/theme/darkTheme.ts +13 -0
  227. package/src/theme/graphicalItemIdentity.ts +70 -0
  228. package/src/theme/legacyTheme.ts +17 -0
  229. package/src/theme/lightTheme.ts +13 -0
  230. package/src/types.ts +54 -0
  231. package/src/util/ActiveShapeUtils.tsx +162 -0
  232. package/src/util/BarUtils.tsx +62 -0
  233. package/src/util/BarePortal.tsx +50 -0
  234. package/src/util/CamelCaseSVGAttrs.ts +34 -0
  235. package/src/util/CartesianUtils.ts +48 -0
  236. package/src/util/ChartUtils.ts +802 -0
  237. package/src/util/Constants.ts +42 -0
  238. package/src/util/CssPrefixUtils.ts +20 -0
  239. package/src/util/DOMUtils.ts +129 -0
  240. package/src/util/DataUtils.ts +216 -0
  241. package/src/util/Events.ts +16 -0
  242. package/src/util/FunnelUtils.tsx +15 -0
  243. package/src/util/Global.ts +12 -0
  244. package/src/util/IfOverflow.ts +15 -0
  245. package/src/util/LRUCache.ts +41 -0
  246. package/src/util/LogUtils.ts +22 -0
  247. package/src/util/PolarUtils.ts +132 -0
  248. package/src/util/RadialBarUtils.tsx +24 -0
  249. package/src/util/ReactUtils.ts +95 -0
  250. package/src/util/ReduceCSSCalc.ts +187 -0
  251. package/src/util/ScatterUtils.tsx +52 -0
  252. package/src/util/ShapeElementProps.tsx +87 -0
  253. package/src/util/TickUtils.ts +60 -0
  254. package/src/util/XAxisUtils.ts +48 -0
  255. package/src/util/YAxisUtils.ts +48 -0
  256. package/src/util/axisPropsAreEqual.ts +48 -0
  257. package/src/util/createCartesianCharts.tsx +150 -0
  258. package/src/util/createEventProxy.ts +20 -0
  259. package/src/util/createPolarCharts.tsx +112 -0
  260. package/src/util/cursor/getCursorPoints.ts +46 -0
  261. package/src/util/cursor/getCursorRectangle.ts +28 -0
  262. package/src/util/cursor/getRadialCursorPoints.ts +32 -0
  263. package/src/util/excludeEventProps.ts +171 -0
  264. package/src/util/getActiveCoordinate.ts +213 -0
  265. package/src/util/getAxisTypeBasedOnLayout.ts +21 -0
  266. package/src/util/getClassNameFromUnknown.ts +6 -0
  267. package/src/util/getEveryNth.ts +27 -0
  268. package/src/util/getRadiusAndStrokeWidthFromDot.ts +35 -0
  269. package/src/util/getRelativeCoordinate.ts +80 -0
  270. package/src/util/getSliced.ts +13 -0
  271. package/src/util/hoverDedupe.ts +41 -0
  272. package/src/util/isDomainSpecifiedByUser.ts +219 -0
  273. package/src/util/isWellBehavedNumber.ts +7 -0
  274. package/src/util/pathTotalLength.ts +25 -0
  275. package/src/util/payload/getUniqPayload.ts +28 -0
  276. package/src/util/propsAreEqual.ts +121 -0
  277. package/src/util/resolveDefaultProps.ts +161 -0
  278. package/src/util/round.ts +32 -0
  279. package/src/util/scale/CartesianScaleHelper.ts +72 -0
  280. package/src/util/scale/CustomScaleDefinition.ts +81 -0
  281. package/src/util/scale/RechartsScale.ts +130 -0
  282. package/src/util/scale/createCategoricalInverse.ts +72 -0
  283. package/src/util/scale/getNiceTickValues.ts +311 -0
  284. package/src/util/scale/index.ts +2 -0
  285. package/src/util/scale/util/arithmetic.ts +54 -0
  286. package/src/util/solid-1-compat.ts +310 -0
  287. package/src/util/solidJsxCamelAugment.d.ts +84 -0
  288. package/src/util/stacks/getStackSeriesIdentifier.ts +21 -0
  289. package/src/util/stacks/stackTypes.ts +60 -0
  290. package/src/util/structurallyEqual.ts +31 -0
  291. package/src/util/svgPropertiesAndEvents.ts +53 -0
  292. package/src/util/svgPropertiesNoEvents.ts +571 -0
  293. package/src/util/tooltip/translate.ts +171 -0
  294. package/src/util/typedDataKey.ts +48 -0
  295. package/src/util/types.ts +1560 -0
  296. package/src/util/useAnimationId.ts +31 -0
  297. package/src/util/useElementOffset.ts +110 -0
  298. package/src/util/useId.ts +8 -0
  299. package/src/util/usePrefersReducedMotion.ts +48 -0
  300. package/src/util/useReportScale.ts +24 -0
  301. package/src/util/useUniqueId.ts +30 -0
  302. package/src/zIndex/DefaultZIndexes.ts +84 -0
  303. package/src/zIndex/ZIndexLayer.tsx +121 -0
  304. package/src/zIndex/ZIndexPortal.tsx +79 -0
  305. package/src/zIndex/getZIndexFromUnknown.ts +14 -0
  306. package/src/zIndex/zIndexSelectors.ts +48 -0
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "author": "Lovro Žagar",
3
+ "bugs": "https://github.com/lovrozagar/solidports/issues",
4
+ "dependencies": {
5
+ "clsx": "2.1.1",
6
+ "decimal.js-light": "2.5.1",
7
+ "es-toolkit": "1.49.0",
8
+ "eventemitter3": "5.0.4",
9
+ "tiny-invariant": "1.3.3",
10
+ "victory-vendor": "37.3.6"
11
+ },
12
+ "description": "SolidJS 1:1 port of Recharts charting library",
13
+ "devDependencies": {
14
+ "@solidjs/signals": "2.0.0-rc.13",
15
+ "@solidjs/testing-library": "1.0.0-beta.3",
16
+ "@solidjs/vite-plugin": "3.0.0-next.47",
17
+ "@solidjs/web": "2.0.0-rc.13",
18
+ "@testing-library/dom": "10.4.1",
19
+ "@testing-library/jest-dom": "6.9.1",
20
+ "@types/bun": "latest",
21
+ "@types/node": "26.1.1",
22
+ "jsdom": "29.1.1",
23
+ "solid-js": "2.0.0-rc.13",
24
+ "ts-morph": "28.0.0",
25
+ "tsup": "8.5.1",
26
+ "tsup-preset-solid": "2.2.0",
27
+ "typescript": "7.0.2",
28
+ "vitest": "4.1.10",
29
+ "vitest-axe": "0.1.0"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "solid": "./src/index.ts",
38
+ "import": "./dist/index.js"
39
+ }
40
+ },
41
+ "files": [
42
+ "dist",
43
+ "src",
44
+ "README.md",
45
+ "LICENSE",
46
+ "NOTICE"
47
+ ],
48
+ "homepage": "https://github.com/lovrozagar/solidports/tree/main/packages/recharts#readme",
49
+ "keywords": [
50
+ "solid",
51
+ "solidjs",
52
+ "chart",
53
+ "charts",
54
+ "charting",
55
+ "recharts",
56
+ "data-visualization"
57
+ ],
58
+ "license": "MIT",
59
+ "main": "./dist/index.js",
60
+ "module": "./dist/index.js",
61
+ "name": "@solidports/recharts",
62
+ "peerDependencies": {
63
+ "@solidjs/web": ">=2.0.0-rc.13",
64
+ "solid-js": ">=2.0.0-rc.13"
65
+ },
66
+ "publishConfig": {
67
+ "access": "public"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "https://github.com/lovrozagar/solidports.git",
72
+ "directory": "packages/recharts"
73
+ },
74
+ "scripts": {
75
+ "build": "tsup",
76
+ "check": "bun run typecheck && bun run lint && bun run test",
77
+ "dev": "tsup --watch",
78
+ "lint": "oxlint src test",
79
+ "lint:fix": "oxlint --fix src test",
80
+ "parity": "bun scripts/parity-audit.ts",
81
+ "release": "bun run build && changeset publish",
82
+ "test": "vitest run",
83
+ "test:perf": "RECHARTS_PERF=1 vitest run test/perf",
84
+ "test:watch": "vitest",
85
+ "triage": "bun scripts/triage-tests.ts",
86
+ "type:check": "tsc --noEmit",
87
+ "typecheck": "tsc --noEmit",
88
+ "upstream:apply": "bun scripts/sync-upstream.ts apply",
89
+ "upstream:diff": "bun scripts/sync-upstream.ts diff",
90
+ "upstream:fetch": "bun scripts/sync-upstream.ts fetch",
91
+ "upstream:pin": "bun scripts/sync-upstream.ts pin",
92
+ "upstream:status": "bun scripts/sync-upstream.ts status"
93
+ },
94
+ "sideEffects": false,
95
+ "type": "module",
96
+ "types": "./dist/index.d.ts",
97
+ "version": "0.1.0"
98
+ }
@@ -0,0 +1,183 @@
1
+ import { createEffect, createMemo, createSignal, Show, untrack } from "solid-js"
2
+ import type { Accessor } from "solid-js"
3
+ import type { JSX } from "@solidjs/web"
4
+ import { JavascriptAnimate } from "./JavascriptAnimate"
5
+ import type { EasingInput } from "./easing"
6
+ import { useAnimationId } from "../util/useAnimationId"
7
+ import { matchAnimationItems, matchByIndex } from "./matchBy"
8
+ import type { AnimationItem, AnimationMatchByProp } from "./matchBy"
9
+ import { useAnimationStartSnapshot } from "./useAnimationStartSnapshot"
10
+ import type { CartesianLayout, PolarLayout } from "../util/types"
11
+ import type { AnimationInterpolateFn } from "../state/types/AnimationSettings"
12
+
13
+ export type { AnimationInterpolateFn }
14
+
15
+ /**
16
+ * Tracks animation state and provides callbacks for animation start/end.
17
+ *
18
+ * @param onAnimationStart optional callback to call when animation starts
19
+ * @param onAnimationEnd optional callback to call when animation ends
20
+ */
21
+ export function useAnimationCallbacks(
22
+ onAnimationStart: Accessor<(() => void) | undefined> = () => undefined,
23
+ onAnimationEnd: Accessor<(() => void) | undefined> = () => undefined,
24
+ ): {
25
+ isAnimating: Accessor<boolean>
26
+ handleAnimationStart: () => void
27
+ handleAnimationEnd: () => void
28
+ } {
29
+ const [isAnimating, setIsAnimating] = createSignal(false)
30
+
31
+ const handleAnimationStart = () => {
32
+ const callback = untrack(onAnimationStart)
33
+ if (typeof callback === "function") {
34
+ callback()
35
+ }
36
+ setIsAnimating(true)
37
+ }
38
+
39
+ const handleAnimationEnd = () => {
40
+ const callback = untrack(onAnimationEnd)
41
+ if (typeof callback === "function") {
42
+ callback()
43
+ }
44
+ setIsAnimating(false)
45
+ }
46
+
47
+ return { handleAnimationEnd, handleAnimationStart, isAnimating }
48
+ }
49
+
50
+ export type AnimatedItemsProps<ItemType, LayoutType extends CartesianLayout | PolarLayout> = {
51
+ /**
52
+ * Opaque input to detect when a new animation should start.
53
+ * When this value changes, a new animation begins.
54
+ */
55
+ animationInput: unknown
56
+ /** Prefix for the generated animation ID */
57
+ animationIdPrefix: string
58
+ /** The target items to animate towards */
59
+ items: ReadonlyArray<ItemType> | undefined
60
+ /** Ref holding previous items — used to detect first render vs data update */
61
+ previousItemsRef: { current: ReadonlyArray<ItemType> | null | undefined }
62
+ /** Whether animation is active */
63
+ isAnimationActive: boolean | "auto"
64
+ /** Delay in ms before animation begins */
65
+ animationBegin: number
66
+ /** Duration of animation in ms */
67
+ animationDuration: number
68
+ /** Easing function or named easing */
69
+ animationEasing: EasingInput
70
+ /** Called when the animation begins */
71
+ onAnimationStart?: () => void
72
+ /** Called when the animation completes */
73
+ onAnimationEnd?: () => void
74
+ /** The interpolation function — either the default or user-provided */
75
+ animationInterpolateFn: AnimationInterpolateFn<ItemType, LayoutType>
76
+ /**
77
+ * Strategy for matching previous items to next items during animation.
78
+ *
79
+ * - `matchByIndex` (default): match by array index with proportional stretching
80
+ * - `matchAppend`: match 1:1 by index, extras animate in as new
81
+ * - A function `(item, index) => key`: match by the returned key value
82
+ */
83
+ animationMatchBy?: AnimationMatchByProp<ItemType>
84
+ /**
85
+ * Optional guard for updating previousItemsRef. Default: `(animationElapsedTime) => animationElapsedTime > 0`.
86
+ * Line uses `(animationElapsedTime) => animationElapsedTime > 0 && totalLength > 0` to avoid updating before SVG path is measured.
87
+ */
88
+ shouldUpdatePreviousRef?: (animationElapsedTime: number) => boolean
89
+ /**
90
+ * Render with interpolated items and animation state. Invoked once; the
91
+ * accessors update in place on every animation frame.
92
+ *
93
+ * @param items The interpolated items at the current animation frame
94
+ * @param animationElapsedTime The normalized time (0-1), useful for additional animation effects
95
+ * @param isEntrance Whether this is the first render (entrance animation) or a data update animation.
96
+ */
97
+ children: (
98
+ items: Accessor<ReadonlyArray<ItemType>>,
99
+ animationElapsedTime: Accessor<number>,
100
+ isEntrance: Accessor<boolean>,
101
+ ) => JSX.Element
102
+ layout: LayoutType
103
+ }
104
+
105
+ /**
106
+ * A reusable animation wrapper for array-based chart data.
107
+ *
108
+ * Encapsulates the common animation pattern shared by Bar, Scatter, Funnel, Pie,
109
+ * Radar, RadialBar, Area, and Line:
110
+ * 1. Track previous items in a ref
111
+ * 2. Wrap in JavascriptAnimate
112
+ * 3. Update ref when animationElapsedTime > 0
113
+ *
114
+ * @since 3.9
115
+ */
116
+ export function AnimatedItems<ItemType, LayoutType extends CartesianLayout | PolarLayout>(
117
+ props: AnimatedItemsProps<ItemType, LayoutType>,
118
+ ) {
119
+ const animationId = useAnimationId(
120
+ () => props.animationInput,
121
+ untrack(() => props.animationIdPrefix),
122
+ )
123
+ const animationStartItems = useAnimationStartSnapshot(
124
+ animationId,
125
+ /* eslint-disable-next-line solid/reactivity -- the ref box is a stable mutable container owned by the caller */
126
+ props.previousItemsRef,
127
+ )
128
+ /* Memoized so per-frame reads do not re-run the caller's selector chain. */
129
+ const items = createMemo(() => props.items)
130
+ const animationItems = createMemo<ReadonlyArray<AnimationItem<ItemType>> | null>(() =>
131
+ matchAnimationItems(
132
+ animationStartItems.frozenStartValue() ?? null,
133
+ items(),
134
+ props.animationMatchBy ?? matchByIndex,
135
+ ),
136
+ )
137
+
138
+ return (
139
+ <JavascriptAnimate
140
+ animationId={animationId()}
141
+ begin={props.animationBegin}
142
+ duration={props.animationDuration}
143
+ isActive={props.isAnimationActive}
144
+ easing={props.animationEasing}
145
+ onAnimationEnd={props.onAnimationEnd}
146
+ onAnimationStart={props.onAnimationStart}
147
+ >
148
+ {(animationElapsedTime: Accessor<number>) => {
149
+ /* Fixed per render like upstream: a lazy read (e.g. on hover) would see the
150
+ unpublished t=1 refresh. */
151
+ const isEntrance = createMemo(() => animationStartItems.startValue() == null)
152
+ const stepData = createMemo(() => {
153
+ const current = items()
154
+ if (current == null) {
155
+ return current
156
+ }
157
+ return props.animationInterpolateFn(animationItems(), animationElapsedTime(), props.layout)
158
+ })
159
+ createEffect(
160
+ () => {
161
+ const t = animationElapsedTime()
162
+ const step = stepData()
163
+ const canUpdate =
164
+ props.shouldUpdatePreviousRef != null ? props.shouldUpdatePreviousRef(t) : t > 0
165
+ return { canUpdate, step, t }
166
+ },
167
+ ({ canUpdate, step, t }) => {
168
+ animationStartItems.syncStepValue(step ?? null, t, canUpdate)
169
+ },
170
+ )
171
+ return (
172
+ <Show when={stepData() != null}>
173
+ {props.children(
174
+ () => stepData() as ReadonlyArray<ItemType>,
175
+ animationElapsedTime,
176
+ isEntrance,
177
+ )}
178
+ </Show>
179
+ )
180
+ }}
181
+ </JavascriptAnimate>
182
+ )
183
+ }
@@ -0,0 +1,33 @@
1
+ import type { CancelableTimeout, TimeoutController } from "./timeoutController"
2
+ import type { AnimationHandle } from "./AnimationHandle"
3
+
4
+ /**
5
+ * It's actually always the case that JavaScript-based animations produce numbers,
6
+ * and CSS transition-based animations always produce strings,
7
+ * but it's so much easier to just have them together than to deal with all the generics.
8
+ *
9
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animation guide}
10
+ *
11
+ * @since 3.9
12
+ */
13
+ export type OnAnimationStateUpdate = (newState: number | string) => void
14
+
15
+ /**
16
+ * AnimationController accepts the animation state machine (= RechartsAnimation) plus a timeout controller,
17
+ * and manages the animation by calling the tick method of the animation state machine at the right time.
18
+ *
19
+ * One controller is only responsible for one animation. Every new animation will create a new controller.
20
+ *
21
+ * The animation state machine is responsible for calculating the animation progress
22
+ * and calling the onAnimationStart and onAnimationEnd callbacks at the right time,
23
+ * while the AnimationController is responsible for calling the tick method of the animation state machine.
24
+ *
25
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animation guide}
26
+ *
27
+ * @since 3.9
28
+ */
29
+ export type AnimationController = (
30
+ timeoutController: TimeoutController,
31
+ animationHandle: AnimationHandle,
32
+ listener: OnAnimationStateUpdate,
33
+ ) => CancelableTimeout
@@ -0,0 +1,36 @@
1
+ import type { AnimationController, OnAnimationStateUpdate } from "./AnimationController"
2
+ import type { AnimationHandle } from "./AnimationHandle"
3
+ import type { CancelableTimeout, TimeoutController } from "./timeoutController"
4
+
5
+ /**
6
+ * JavaScript animations require trigger and repaint as soon as possible,
7
+ * so this class uses the timeoutController to trigger updates as quickly as the controller allows.
8
+ *
9
+ * JavaScript animation progress is represented as a stream of values. The exact type depends on the animationHandle type.
10
+ * Each individual consumer is then responsible for mapping those values onto a React component.
11
+ */
12
+ export const animationControllerImpl: AnimationController = (
13
+ timeoutController: TimeoutController,
14
+ animationHandle: AnimationHandle,
15
+ listener: OnAnimationStateUpdate,
16
+ ): CancelableTimeout => {
17
+ let cancellable: CancelableTimeout | undefined
18
+ const nextUpdate = (now: number) => {
19
+ const timeRemaining = animationHandle.tick(now)
20
+ if (animationHandle.getState() === "active") {
21
+ listener(animationHandle.getInterpolated())
22
+ if (animationHandle.getProgress() === 1) {
23
+ animationHandle.complete()
24
+ cancellable = undefined
25
+ return
26
+ }
27
+ cancellable = timeoutController.setTimeout(nextUpdate, timeRemaining)
28
+ return
29
+ }
30
+ cancellable = timeoutController.setTimeout(nextUpdate, timeRemaining)
31
+ }
32
+
33
+ cancellable = timeoutController.setTimeout(nextUpdate, 0)
34
+
35
+ return () => cancellable?.()
36
+ }
@@ -0,0 +1,307 @@
1
+ // eslint-disable-next-line max-classes-per-file
2
+ import { interpolate } from "../util/DataUtils"
3
+ import type { EasingFunction, NamedBezier } from "./easing"
4
+
5
+ const INIT = "init" as const
6
+ const PENDING = "pending" as const
7
+ const ACTIVE = "active" as const
8
+ const COMPLETED = "completed" as const
9
+
10
+ export type AnimationState = typeof INIT | typeof PENDING | typeof ACTIVE | typeof COMPLETED
11
+
12
+ type AnimationStateCallback = () => void
13
+
14
+ function duration(time: number): number {
15
+ return Math.max(0, time)
16
+ }
17
+
18
+ abstract class RechartsAnimation<T, E> {
19
+ /**
20
+ * Returns the absolute time after the animationBegin delay has been completed,
21
+ * and when the animationDuration started ticking.
22
+ */
23
+ public getAnimationStartedTime(): number | undefined {
24
+ return this.animationStartedTime
25
+ }
26
+
27
+ /**
28
+ * Returns the absolute time of when the animation began - now it will wait for {animationBegin} ms before the transition starts
29
+ */
30
+ public getBeginStartedTime(): number | undefined {
31
+ return this.beginStartedTime
32
+ }
33
+
34
+ private readonly onAnimationEnd: undefined | AnimationStateCallback
35
+
36
+ private progress: number
37
+
38
+ private animationStartedTime: number | undefined
39
+
40
+ private beginStartedTime: number | undefined
41
+
42
+ protected readonly animationDuration: number
43
+
44
+ private readonly animationBegin: number
45
+
46
+ private readonly from: T
47
+
48
+ private readonly to: T
49
+
50
+ protected readonly easing: E
51
+
52
+ private readonly animationId: string
53
+
54
+ constructor(param: {
55
+ animationId: string
56
+ onAnimationStart: undefined | AnimationStateCallback
57
+ onAnimationEnd: undefined | AnimationStateCallback
58
+ animationDuration: number
59
+ animationBegin: number
60
+ from: T
61
+ to: T
62
+ easing: E
63
+ }) {
64
+ this.animationId = param.animationId
65
+ this.onAnimationEnd = param.onAnimationEnd
66
+ this.animationDuration = duration(param.animationDuration)
67
+ this.animationBegin = duration(param.animationBegin)
68
+ this.progress = 0
69
+ this.from = param.from
70
+ this.to = param.to
71
+ this.easing = param.easing
72
+ // Mimic what the previous animationManager was doing - call onAnimationStart immediately and synchronously
73
+ param.onAnimationStart?.()
74
+ }
75
+
76
+ private state: AnimationState = INIT
77
+
78
+ /**
79
+ * Returns the state machine current state
80
+ * - `init`: animation had just been created. It immediately calls `onAnimationStart`
81
+ * - `pending`: animation is now paused for `animationBegin` milliseconds until the transition begins
82
+ * - `active`: animation is transitioning items on screen
83
+ * - `completed`: animation has completed its transition and executed `onAnimationEnd`.
84
+ * This state is final and the animation is no longer allowed to transition to other states.
85
+ */
86
+ public getState() {
87
+ return this.state
88
+ }
89
+
90
+ /**
91
+ * Returns the easing input or function
92
+ */
93
+ public getEasing(): E {
94
+ return this.easing
95
+ }
96
+
97
+ /**
98
+ * Returns the configuration - the duration of the transition.
99
+ * Does not change in time, does not change when state changes, this is a static value.
100
+ */
101
+ public getAnimationDuration(): number {
102
+ return this.animationDuration
103
+ }
104
+
105
+ /**
106
+ * Sets the current time of the animation. The animation sets its internal state and progress accordingly.
107
+ * This is current, absolute time; not additive!
108
+ * This allows you to essentially "travel back in time" based on the value you pass in here.
109
+ *
110
+ * Returns the (relative) time remaining until the current activity is over.
111
+ * Meaning: if the state is in a middle of a delay, returns the time left until the delay is finished.
112
+ * If the state is in the middle of a transition, returns time left until that transition is complete.
113
+ * This is useful because it's the same number you can take and put into setTimeout(fn, X)
114
+ * as that's how much time we need to wait until the next state transition happens.
115
+ */
116
+ public tick(now: number): number {
117
+ if (this.getState() === INIT) {
118
+ this.state = PENDING
119
+ this.beginStartedTime = now
120
+ return this.animationBegin
121
+ }
122
+
123
+ if (this.getState() === PENDING) {
124
+ if (this.beginStartedTime == null) {
125
+ throw new Error("@solidports/recharts: pending animation has no begin time")
126
+ }
127
+ const timeElapsed = now - this.beginStartedTime
128
+ if (timeElapsed >= this.animationBegin) {
129
+ this.state = ACTIVE
130
+ this.animationStartedTime = now
131
+ // The state flipped just now so the elapsed time is zero
132
+ return this.nextAnimationUpdate(0)
133
+ }
134
+ return duration(this.animationBegin - timeElapsed)
135
+ }
136
+
137
+ if (this.getState() === ACTIVE) {
138
+ if (this.animationStartedTime == null) {
139
+ throw new Error("@solidports/recharts: active animation has no start time")
140
+ }
141
+ const timeElapsed = now - this.animationStartedTime
142
+ this.setProgress(timeElapsed / this.animationDuration)
143
+ return this.nextAnimationUpdate(timeElapsed)
144
+ }
145
+
146
+ // state === COMPLETED, nothing interesting is going to happen
147
+ return 0
148
+ }
149
+
150
+ private setProgress(newProgress: number) {
151
+ this.progress = Math.min(1, Math.max(0, newProgress))
152
+ }
153
+
154
+ /**
155
+ * Returns an abstract "progress" which is number between 0 and 1 which shows the distance of transition.
156
+ * This progress depends on the animation state:
157
+ * - `init`: 0
158
+ * - `pending`: 0
159
+ * - `active`: transitioning between [0, 1] based on the time elapsed
160
+ * - `completed`: 1
161
+ *
162
+ * The progress is hard-capped to be between 0 and 1 (inclusive) to avoid overshooting caused by coarse timers.
163
+ * For this reason, the easing function must be applied _after_ this animation state,
164
+ * so that one has a chance to construct dynamic "overshoot" animations.
165
+ *
166
+ * The progress is linear with time.
167
+ * If you wish for easing, use `getInterpolated()` instead.
168
+ */
169
+ public getProgress(): number {
170
+ return this.progress
171
+ }
172
+
173
+ /**
174
+ * Completes the animation. Completed animation:
175
+ * - cannot be manipulated anymore
176
+ * - its progress is set to 1
177
+ * - tick function doesn't do anything
178
+ * - getState() always returns 'completed'
179
+ */
180
+ public complete() {
181
+ this.progress = 1
182
+ if (this.state === "active") {
183
+ // Do not call callbacks if the animation was interrupted before it even started!
184
+ this.onAnimationEnd?.()
185
+ }
186
+ this.state = COMPLETED
187
+ }
188
+
189
+ /**
190
+ * Returns the starting value of the animation.
191
+ * Does not include progress, easing, interpolation, none of that - just the static starting value
192
+ */
193
+ public getFrom() {
194
+ return this.from
195
+ }
196
+
197
+ /**
198
+ * Returns the end value of the animation.
199
+ * Does not include progress, easing, interpolation, none of that - just the static end value
200
+ */
201
+ public getTo() {
202
+ return this.to
203
+ }
204
+
205
+ /**
206
+ * Unique identifier of an animation
207
+ */
208
+ public getAnimationId(): string {
209
+ return this.animationId
210
+ }
211
+
212
+ /**
213
+ * Returns the configuration - the duration of delay in between animation initialization, and transition.
214
+ * Does not change in time, does not change when state changes, this is a static value.
215
+ */
216
+ getAnimationBegin(): number {
217
+ return this.animationBegin
218
+ }
219
+
220
+ /**
221
+ * Returns value of the transition at the current time.
222
+ * The exact details differ based on the animation type
223
+ */
224
+ public abstract getInterpolated(): T
225
+
226
+ /**
227
+ * Returns the duration of time of when the controller should ask for the next update
228
+ */
229
+ protected abstract nextAnimationUpdate(timeElapsed: number): number
230
+ }
231
+
232
+ /**
233
+ * Animation handle representing a Javascript-based animation.
234
+ * This animation requires one render cycle for each frame, and it calls setTimeout as quickly as possible
235
+ *
236
+ * @since 3.9
237
+ */
238
+ export class JavascriptAnimation extends RechartsAnimation<number, EasingFunction> {
239
+ // eslint-disable-next-line class-methods-use-this
240
+ protected nextAnimationUpdate(): number {
241
+ /*
242
+ * JavaScript-based animations have to update as soon as possible,
243
+ * so we return 0 here to indicate that the next update should be scheduled immediately
244
+ * and it should trigger render on every occasion.
245
+ */
246
+ return 0
247
+ }
248
+
249
+ /**
250
+ * Returns value of the animation after its easing function had been applied.
251
+ * This value, unlike getProgress(), can escape the [0..1] range
252
+ * because this is entirely within the easing function control. Spring typically does this.
253
+ */
254
+ public getInterpolated(): number {
255
+ return this.easing(interpolate(this.getFrom(), this.getTo(), this.getProgress()))
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Animation handle representing a CSS transition.
261
+ * This animation requires only one render, and the actual transition is then handled by the browser.
262
+ *
263
+ * @since 3.9
264
+ */
265
+ export class CSSTransitionAnimation extends RechartsAnimation<string, NamedBezier> {
266
+ protected nextAnimationUpdate(timeElapsed: number): number {
267
+ /**
268
+ * CSS transitions do not need DOM updates past the initial render
269
+ * so here we just instruct the controller to wait until the animation duration is over.
270
+ */
271
+ return duration(this.animationDuration - timeElapsed)
272
+ }
273
+
274
+ /**
275
+ * Returns the final value of the animation (the `to`).
276
+ *
277
+ * CSS transitions leave both interpolation and easing to the browser,
278
+ * so all we need to do here is return the final state
279
+ * and let browser handle the rest.
280
+ */
281
+ public getInterpolated(): string {
282
+ return this.getTo()
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Recharts animation state machine.
288
+ *
289
+ * Possible transitions are:
290
+ * - `init`: starting state - `onAnimationStart` executes
291
+ * - `init` to `pending` - `animationBegin` duration begins
292
+ * - `pending` to `active` - `animationDuration` duration begins, timer ticks decide the progress
293
+ * - `active` to `completed` - `onAnimationEnd` executes
294
+ *
295
+ * The state always moves in this direction, cannot move backwards.
296
+ *
297
+ * The animation queue is static and consists of four elements:
298
+ * - `onAnimationStart`: function that is called when the animation is created
299
+ * - `animationBegin`: delay between `onAnimationStart` and the transition
300
+ * - the transition itself, takes `animationDuration` ms to finish
301
+ * - `onAnimationEnd`: function that is called when the animation is moving from `active` to `completed`
302
+ *
303
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animation guide}
304
+ *
305
+ * @since 3.9
306
+ */
307
+ export type AnimationHandle = JavascriptAnimation | CSSTransitionAnimation