@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
@@ -0,0 +1,95 @@
1
+ /* eslint-disable import/no-cycle, sort-keys */
2
+ import type { Component } from 'solid-js';
3
+ import type { ActiveDotType, DotType } from "./types"
4
+
5
+ export const SCALE_TYPES = [
6
+ "auto",
7
+ "linear",
8
+ "pow",
9
+ "sqrt",
10
+ "log",
11
+ "identity",
12
+ "time",
13
+ "band",
14
+ "point",
15
+ "ordinal",
16
+ "quantile",
17
+ "quantize",
18
+ "utc",
19
+ "sequential",
20
+ "threshold",
21
+ ]
22
+
23
+ /**
24
+ * Get the display name of a component.
25
+ * In Solid, components don't have displayName, so we fall back to .name.
26
+ * @param {Object} Comp Specified Component
27
+ * @return {String} Display name of Component
28
+ */
29
+ export const getDisplayName = (Comp: Component | string) => {
30
+ if (typeof Comp === "string") {
31
+ return Comp
32
+ }
33
+ if (!Comp) {
34
+ return ""
35
+ }
36
+ return Comp.name || "Component"
37
+ }
38
+
39
+ export const isClipDot = (dot: ActiveDotType | DotType): boolean => {
40
+ if (dot && typeof dot === "object" && "clipDot" in dot) {
41
+ return Boolean(dot.clipDot)
42
+ }
43
+ return true
44
+ }
45
+
46
+ /* React `<Foo />` builds a vNode (lazy descriptor) that `cloneElement` can
47
+ * re-instantiate per iteration with merged props. Solid `<Foo />` evaluates
48
+ * eagerly to a live DOM Node — function reference + original props are gone.
49
+ * The closest emulation: detect a Node value and clone it, optionally applying
50
+ * iteration-specific attrs. Spies inside the original component fire ONCE at
51
+ * JSX evaluation; only the rendered DOM count and final attribute values are
52
+ * recoverable. Documented under Cluster C / GOTCHA-016. */
53
+ export function isJsxNode(value: unknown): value is Node {
54
+ return value != null && typeof value === "object" && "cloneNode" in value
55
+ }
56
+
57
+ const SVG_CAMEL_TO_KEBAB: Record<string, string> = {
58
+ tabindex: "tabindex",
59
+ readOnly: "readonly",
60
+ contentEditable: "contenteditable",
61
+ spellCheck: "spellcheck",
62
+ autoFocus: "autofocus",
63
+ clipPath: "clip-path",
64
+ clipRule: "clip-rule",
65
+ fillOpacity: "fill-opacity",
66
+ strokeWidth: "stroke-width",
67
+ strokeOpacity: "stroke-opacity",
68
+ strokeLinecap: "stroke-linecap",
69
+ strokeLinejoin: "stroke-linejoin",
70
+ strokeDasharray: "stroke-dasharray",
71
+ strokeDashoffset: "stroke-dashoffset",
72
+ textAnchor: "text-anchor",
73
+ }
74
+
75
+ function attrNameFor(key: string): string {
76
+ return SVG_CAMEL_TO_KEBAB[key] ?? key
77
+ }
78
+
79
+ /* Apply iteration props onto a fresh clone of a user-supplied JSX Node.
80
+ * Skips function values, undefined, `style`, and the "key"/"children"/"className"/"class"
81
+ * meta-props; other objects are stringified like React does. Booleans serialize as "true"/"false" to match recharts upstream
82
+ * `cloneElement` behaviour where downstream `getAttribute` reads the string. */
83
+ export function cloneJsxNodeWithProps(node: Node, props: Record<string, unknown>): Node {
84
+ const cloned = node.cloneNode(true)
85
+ if (!(cloned instanceof Element)) return cloned
86
+
87
+ for (const key in props) {
88
+ if (key === "key" || key === "children" || key === "className" || key === "class") continue
89
+ const value = props[key]
90
+ if (value == null || typeof value === "function" || key === "style") continue
91
+ /* React stringifies object values on DOM attributes (payload -> "[object Object]", arrays -> "0,300") */
92
+ cloned.setAttribute(attrNameFor(key), String(value))
93
+ }
94
+ return cloned
95
+ }
@@ -0,0 +1,187 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import { isNan } from "./DataUtils"
3
+
4
+ const MULTIPLY_OR_DIVIDE_REGEX = /(-?\d+(?:\.\d+)?[a-zA-Z%]*)([*/])(-?\d+(?:\.\d+)?[a-zA-Z%]*)/
5
+ const ADD_OR_SUBTRACT_REGEX = /(-?\d+(?:\.\d+)?[a-zA-Z%]*)([+-])(-?\d+(?:\.\d+)?[a-zA-Z%]*)/
6
+ const CSS_LENGTH_UNIT_REGEX = /^(px|cm|vh|vw|em|rem|%|mm|in|pt|pc|ex|ch|vmin|vmax|Q)$/
7
+ const NUM_SPLIT_REGEX = /(-?\d+(?:\.\d+)?)([a-zA-Z%]+)?/
8
+
9
+ type SupportedUnits = "cm" | "mm" | "pt" | "pc" | "in" | "Q" | "px"
10
+
11
+ const CONVERSION_RATES: Record<SupportedUnits, number> = {
12
+ Q: 96 / (2.54 * 40),
13
+ cm: 96 / 2.54,
14
+ in: 96,
15
+ mm: 96 / 25.4,
16
+ pc: 96 / 6,
17
+ pt: 96 / 72,
18
+ px: 1,
19
+ }
20
+
21
+ const FIXED_CSS_LENGTH_UNITS: ReadonlySet<SupportedUnits> = new Set([
22
+ "cm",
23
+ "mm",
24
+ "pt",
25
+ "pc",
26
+ "in",
27
+ "Q",
28
+ "px",
29
+ ])
30
+
31
+ function isSupportedUnit(unit: string): unit is SupportedUnits {
32
+ return FIXED_CSS_LENGTH_UNITS.has(unit as SupportedUnits)
33
+ }
34
+
35
+ const STR_NAN = "NaN"
36
+
37
+ function convertToPx(value: number, unit: SupportedUnits): number {
38
+ return value * CONVERSION_RATES[unit]
39
+ }
40
+
41
+ class DecimalCSS {
42
+ static parse(str: string) {
43
+ const [, numStr, unit] = NUM_SPLIT_REGEX.exec(str) ?? []
44
+
45
+ if (numStr == null) {
46
+ return DecimalCSS.NaN
47
+ }
48
+
49
+ return new DecimalCSS(parseFloat(numStr), unit ?? "")
50
+ }
51
+
52
+ static NaN = new DecimalCSS(NaN, "")
53
+
54
+ constructor(
55
+ public num: number,
56
+ public unit: string,
57
+ ) {
58
+ this.num = num
59
+ this.unit = unit
60
+
61
+ if (isNan(num)) {
62
+ this.unit = ""
63
+ }
64
+
65
+ if (unit !== "" && !CSS_LENGTH_UNIT_REGEX.test(unit)) {
66
+ this.num = NaN
67
+ this.unit = ""
68
+ }
69
+
70
+ if (isSupportedUnit(unit)) {
71
+ this.num = convertToPx(num, unit)
72
+ this.unit = "px"
73
+ }
74
+ }
75
+
76
+ add(other: DecimalCSS) {
77
+ if (this.unit !== other.unit) {
78
+ return new DecimalCSS(NaN, "")
79
+ }
80
+
81
+ return new DecimalCSS(this.num + other.num, this.unit)
82
+ }
83
+
84
+ subtract(other: DecimalCSS) {
85
+ if (this.unit !== other.unit) {
86
+ return new DecimalCSS(NaN, "")
87
+ }
88
+
89
+ return new DecimalCSS(this.num - other.num, this.unit)
90
+ }
91
+
92
+ multiply(other: DecimalCSS) {
93
+ if (this.unit !== "" && other.unit !== "" && this.unit !== other.unit) {
94
+ return new DecimalCSS(NaN, "")
95
+ }
96
+
97
+ return new DecimalCSS(this.num * other.num, this.unit || other.unit)
98
+ }
99
+
100
+ divide(other: DecimalCSS) {
101
+ if (this.unit !== "" && other.unit !== "" && this.unit !== other.unit) {
102
+ return new DecimalCSS(NaN, "")
103
+ }
104
+
105
+ return new DecimalCSS(this.num / other.num, this.unit || other.unit)
106
+ }
107
+
108
+ toString() {
109
+ return `${this.num}${this.unit}`
110
+ }
111
+
112
+ isNaN() {
113
+ return isNan(this.num)
114
+ }
115
+ }
116
+
117
+ function calculateArithmetic(expr: string | undefined): string {
118
+ if (expr == null || expr.includes(STR_NAN)) {
119
+ return STR_NAN
120
+ }
121
+
122
+ let newExpr = expr
123
+ while (newExpr.includes("*") || newExpr.includes("/")) {
124
+ const [, leftOperand, operator, rightOperand] = MULTIPLY_OR_DIVIDE_REGEX.exec(newExpr) ?? []
125
+ const lTs = DecimalCSS.parse(leftOperand ?? "")
126
+ const rTs = DecimalCSS.parse(rightOperand ?? "")
127
+ const result = operator === "*" ? lTs.multiply(rTs) : lTs.divide(rTs)
128
+ if (result.isNaN()) {
129
+ return STR_NAN
130
+ }
131
+ newExpr = newExpr.replace(MULTIPLY_OR_DIVIDE_REGEX, () => result.toString())
132
+ }
133
+
134
+ while (newExpr.includes("+") || /.-\d+(?:\.\d+)?/.test(newExpr)) {
135
+ const [, leftOperand, operator, rightOperand] = ADD_OR_SUBTRACT_REGEX.exec(newExpr) ?? []
136
+ const lTs = DecimalCSS.parse(leftOperand ?? "")
137
+ const rTs = DecimalCSS.parse(rightOperand ?? "")
138
+ const result = operator === "+" ? lTs.add(rTs) : lTs.subtract(rTs)
139
+ if (result.isNaN()) {
140
+ return STR_NAN
141
+ }
142
+ newExpr = newExpr.replace(ADD_OR_SUBTRACT_REGEX, () => result.toString())
143
+ }
144
+
145
+ return newExpr
146
+ }
147
+
148
+ const PARENTHESES_REGEX = /\(([^()]*)\)/
149
+
150
+ function calculateParentheses(expr: string): string {
151
+ let newExpr = expr
152
+ let match: ReturnType<typeof RegExp.prototype.exec> | null
153
+ while ((match = PARENTHESES_REGEX.exec(newExpr)) != null) {
154
+ const [, parentheticalExpression] = match
155
+ newExpr = newExpr.replace(PARENTHESES_REGEX, () =>
156
+ calculateArithmetic(parentheticalExpression),
157
+ )
158
+ }
159
+
160
+ return newExpr
161
+ }
162
+
163
+ function evaluateExpression(expression: string): string {
164
+ let newExpr = expression.replace(/\s+/g, "")
165
+ newExpr = calculateParentheses(newExpr)
166
+ newExpr = calculateArithmetic(newExpr)
167
+
168
+ return newExpr
169
+ }
170
+
171
+ export function safeEvaluateExpression(expression: string): string {
172
+ try {
173
+ return evaluateExpression(expression)
174
+ } catch {
175
+ return STR_NAN
176
+ }
177
+ }
178
+
179
+ export function reduceCSSCalc(expression: string): string {
180
+ const result = safeEvaluateExpression(expression.slice(5, -1))
181
+
182
+ if (result === STR_NAN) {
183
+ return ""
184
+ }
185
+
186
+ return result
187
+ }
@@ -0,0 +1,52 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import type { JSX } from '@solidjs/web';
3
+ import { SymbolType } from "./types"
4
+ import type { ShapeAnimationProps } from "./types"
5
+ import { ScatterPointItem, ScatterCustomizedShape } from "../cartesian/Scatter"
6
+ import { Symbols } from "../shape/Symbols"
7
+ import { Shape } from "./ActiveShapeUtils"
8
+ import { DATA_ITEM_GRAPHICAL_ITEM_ID_ATTRIBUTE_NAME } from "./Constants"
9
+ import { GraphicalItemId } from "../state/graphicalItemsSlice"
10
+
11
+ export type ScatterShapeProps = ScatterPointItem &
12
+ ShapeAnimationProps & {
13
+ isActive?: boolean
14
+ index: number
15
+ [DATA_ITEM_GRAPHICAL_ITEM_ID_ATTRIBUTE_NAME]: GraphicalItemId
16
+ }
17
+
18
+ export function ScatterSymbol(
19
+ props: {
20
+ option: ScatterCustomizedShape
21
+ isActive: boolean
22
+ } & ScatterShapeProps,
23
+ ): JSX.Element {
24
+ return <>{renderScatterSymbol(props)}</>
25
+ }
26
+
27
+ /* Runs inside ScatterSymbol's JSX expression so every reactive read is tracked. */
28
+ function renderScatterSymbol(
29
+ props: {
30
+ option: ScatterCustomizedShape
31
+ isActive: boolean
32
+ } & ScatterShapeProps,
33
+ ): JSX.Element {
34
+ /* eslint-disable solid/reactivity -- option type and shapeProps are stable at mount; component re-renders via Solid's fine-grained reactivity on JSX reads below */
35
+ const { option: _option, isActive: _isActive, ...shapeProps } = props
36
+ if (typeof props.option === "string") {
37
+ const symbolType = props.option as SymbolType
38
+ return (
39
+ <Shape
40
+ option={<Symbols type={symbolType} {...shapeProps} />}
41
+ isActive={props.isActive}
42
+ shapeType="symbols"
43
+ {...shapeProps}
44
+ />
45
+ )
46
+ }
47
+
48
+ return (
49
+ <Shape option={props.option} isActive={props.isActive} shapeType="symbols" {...shapeProps} />
50
+ )
51
+ /* eslint-enable solid/reactivity */
52
+ }
@@ -0,0 +1,87 @@
1
+ import { createContext, untrack, useContext } from "solid-js"
2
+ import type { JSX } from "@solidjs/web"
3
+ import { mergeProps } from "./solid-1-compat"
4
+ import { cloneJsxNodeWithProps, isJsxNode } from "./ReactUtils"
5
+ import { camelizeSvgPropsForHandler } from "./svgPropertiesNoEvents"
6
+
7
+ /**
8
+ * Upstream renders a shape passed as an element with
9
+ * `cloneElement(option, { ...props, ...option.props })`. Solid evaluates `<Sector fill="red" />`
10
+ * eagerly, so there is no unrendered element to clone. Instead the caller provides the props it
11
+ * would inject, then reads the option lazily inside the provider: the built-in shape evaluated
12
+ * there merges them under its own explicit props.
13
+ *
14
+ * Each evaluation arms a one-shot token: only the first shape evaluated after arming takes it,
15
+ * so shapes nested inside that shape (e.g. the curves of AreaRevealShape) are unaffected.
16
+ */
17
+ type ShapeElementPropsToken = { props: Record<string, unknown>; consumed: boolean }
18
+
19
+ export type ShapeElementPropsSlot = { token: ShapeElementPropsToken | null }
20
+
21
+ const ShapeElementPropsContext = createContext<ShapeElementPropsSlot | null>(null)
22
+
23
+ export function createShapeElementPropsSlot(): ShapeElementPropsSlot {
24
+ return { token: null }
25
+ }
26
+
27
+ /** Arm the slot with the props for the next shape evaluated inside the provider. */
28
+ export function armShapeElementProps(slot: ShapeElementPropsSlot, props: Record<string, unknown>): ShapeElementPropsToken {
29
+ const token = { consumed: false, props }
30
+ slot.token = token
31
+ return token
32
+ }
33
+
34
+ /** Stop offering the injected props to shapes evaluated from now on. */
35
+ export function disarmShapeElementProps(slot: ShapeElementPropsSlot): void {
36
+ slot.token = null
37
+ }
38
+
39
+ export function ShapeElementPropsProvider(props: { slot: ShapeElementPropsSlot; children: JSX.Element }) {
40
+ /* eslint-disable-next-line solid/reactivity -- the slot is a stable mutable container */
41
+ return <ShapeElementPropsContext value={props.slot}>{props.children}</ShapeElementPropsContext>
42
+ }
43
+
44
+ /**
45
+ * Merge props injected by an enclosing ShapeElementPropsProvider under the shape's own props.
46
+ * Own props win, like upstream's `{ ...props, ...option.props }`.
47
+ */
48
+ export function useShapeElementProps<P extends object>(own: P): P {
49
+ const slot = useContext(ShapeElementPropsContext)
50
+ const token = slot?.token
51
+ if (token == null || token.consumed) {
52
+ return own
53
+ }
54
+ token.consumed = true
55
+ return untrack(() => mergeProps(token.props, own)) as unknown as P
56
+ }
57
+
58
+ /**
59
+ * Renders a `shape`-style option the way upstream does for element / function / default:
60
+ * - an element: built-in shapes take `shapeProps` while evaluated; other elements are cloned
61
+ * with them applied (Solid cannot clone an unrendered element);
62
+ * - a function: called with the props in upstream's camelCase spelling;
63
+ * - anything else: `renderDefault(shapeProps)`.
64
+ */
65
+ export function ShapeOption(props: {
66
+ option: unknown
67
+ shapeProps: Record<string, unknown>
68
+ renderDefault: (shapeProps: Record<string, unknown>) => JSX.Element
69
+ }) {
70
+ const slot = createShapeElementPropsSlot()
71
+ const render = (): JSX.Element => {
72
+ const token = armShapeElementProps(slot, props.shapeProps)
73
+ /* read once: an element option mints a new node per read */
74
+ const option = props.option
75
+ disarmShapeElementProps(slot)
76
+ if (isJsxNode(option)) {
77
+ return token.consumed
78
+ ? (option as unknown as JSX.Element)
79
+ : (cloneJsxNodeWithProps(option, props.shapeProps) as unknown as JSX.Element)
80
+ }
81
+ if (typeof option === "function") {
82
+ return (option as (p: Record<string, unknown>) => JSX.Element)(camelizeSvgPropsForHandler(props.shapeProps))
83
+ }
84
+ return props.renderDefault(props.shapeProps)
85
+ }
86
+ return <ShapeElementPropsProvider slot={slot}>{render()}</ShapeElementPropsProvider>
87
+ }
@@ -0,0 +1,60 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import { getAngledRectangleWidth } from "./CartesianUtils"
3
+ import { getEveryNth } from "./getEveryNth"
4
+ import { Size, CartesianTickItem, CartesianViewBoxRequired } from "./types"
5
+
6
+ export function getAngledTickWidth(contentSize: Size, unitSize: Size, angle: number | undefined) {
7
+ const size = {
8
+ height: contentSize.height + unitSize.height,
9
+ width: contentSize.width + unitSize.width,
10
+ }
11
+
12
+ return getAngledRectangleWidth(size, angle)
13
+ }
14
+
15
+ export function getTickBoundaries(
16
+ viewBox: CartesianViewBoxRequired,
17
+ sign: number,
18
+ sizeKey: string,
19
+ ) {
20
+ const isWidth = sizeKey === "width"
21
+ const { x, y, width, height } = viewBox
22
+ if (sign === 1) {
23
+ return {
24
+ end: isWidth ? x + width : y + height,
25
+ start: isWidth ? x : y,
26
+ }
27
+ }
28
+ return {
29
+ end: isWidth ? x : y,
30
+ start: isWidth ? x + width : y + height,
31
+ }
32
+ }
33
+
34
+ export function isVisible(
35
+ sign: number,
36
+ tickPosition: number,
37
+ getSize: () => number,
38
+ start: number,
39
+ end: number,
40
+ ): boolean {
41
+ /* Since getSize() is expensive (it reads the ticks' size from the DOM), we do this check first to avoid calculating
42
+ * the tick's size. */
43
+ if (sign * tickPosition < sign * start || sign * tickPosition > sign * end) {
44
+ return false
45
+ }
46
+
47
+ const size = getSize()
48
+
49
+ return (
50
+ sign * (tickPosition - (sign * size) / 2 - start) >= 0 &&
51
+ sign * (tickPosition + (sign * size) / 2 - end) <= 0
52
+ )
53
+ }
54
+
55
+ export function getNumberIntervalTicks(
56
+ ticks: ReadonlyArray<CartesianTickItem>,
57
+ interval: number,
58
+ ): ReadonlyArray<CartesianTickItem> | undefined {
59
+ return getEveryNth(ticks, interval + 1)
60
+ }
@@ -0,0 +1,48 @@
1
+ type IGetBoundingClient = Pick<Element, "getBoundingClientRect">
2
+
3
+ /**
4
+ * Calculates the height of the X-axis based on the tick labels and the axis label.
5
+ * @param params - The parameters object.
6
+ * @param [params.ticks] - An array-like object of tick elements, each with a `getBoundingClientRect` method.
7
+ * @param [params.label] - The axis label element, with a `getBoundingClientRect` method.
8
+ * @param [params.labelGapWithTick=5] - The gap between the label and the tick.
9
+ * @param [params.tickSize=0] - The length of the tick line.
10
+ * @param [params.tickMargin=0] - The margin between the tick line and the tick text.
11
+ * @returns The calculated height of the X-axis.
12
+ */
13
+ export const getCalculatedXAxisHeight = ({
14
+ ticks,
15
+ label,
16
+ labelGapWithTick = 5,
17
+ tickSize = 0,
18
+ tickMargin = 0,
19
+ }: {
20
+ ticks: ArrayLike<IGetBoundingClient> | null
21
+ label: IGetBoundingClient | null | undefined
22
+ labelGapWithTick: number | undefined
23
+ tickSize: number | undefined
24
+ tickMargin: number | undefined
25
+ }): number => {
26
+ let maxTickHeight = 0
27
+ if (ticks) {
28
+ Array.from(ticks).forEach((tickNode: IGetBoundingClient) => {
29
+ if (tickNode) {
30
+ const bbox = tickNode.getBoundingClientRect()
31
+
32
+ if (bbox.height > maxTickHeight) {
33
+ maxTickHeight = bbox.height
34
+ }
35
+ }
36
+ })
37
+
38
+ const labelHeight = label ? label.getBoundingClientRect().height : 0
39
+
40
+ const tickHeight = tickSize + tickMargin
41
+
42
+ const updatedXAxisHeight = maxTickHeight + tickHeight + labelHeight + (label ? labelGapWithTick : 0)
43
+
44
+ return Math.round(updatedXAxisHeight)
45
+ }
46
+
47
+ return 0
48
+ }
@@ -0,0 +1,48 @@
1
+ type IGetBoundingClient = Pick<Element, "getBoundingClientRect">
2
+
3
+ /**
4
+ * Calculates the width of the Y-axis based on the tick labels and the axis label.
5
+ * @param params - The parameters object.
6
+ * @param [params.ticks] - An array-like object of tick elements, each with a `getBoundingClientRect` method.
7
+ * @param [params.label] - The axis label element, with a `getBoundingClientRect` method.
8
+ * @param [params.labelGapWithTick=5] - The gap between the label and the tick.
9
+ * @param [params.tickSize=0] - The length of the tick line.
10
+ * @param [params.tickMargin=0] - The margin between the tick line and the tick text.
11
+ * @returns The calculated width of the Y-axis.
12
+ */
13
+ export const getCalculatedYAxisWidth = ({
14
+ ticks,
15
+ label,
16
+ labelGapWithTick = 5,
17
+ tickSize = 0,
18
+ tickMargin = 0,
19
+ }: {
20
+ ticks: ArrayLike<IGetBoundingClient> | null
21
+ label: IGetBoundingClient | null | undefined
22
+ labelGapWithTick: number | undefined
23
+ tickSize: number | undefined
24
+ tickMargin: number | undefined
25
+ }): number => {
26
+ let maxTickWidth = 0
27
+ if (ticks) {
28
+ Array.from(ticks).forEach((tickNode: IGetBoundingClient) => {
29
+ if (tickNode) {
30
+ const bbox = tickNode.getBoundingClientRect()
31
+
32
+ if (bbox.width > maxTickWidth) {
33
+ maxTickWidth = bbox.width
34
+ }
35
+ }
36
+ })
37
+
38
+ const labelWidth = label ? label.getBoundingClientRect().width : 0
39
+
40
+ const tickWidth = tickSize + tickMargin
41
+
42
+ const updatedYAxisWidth = maxTickWidth + tickWidth + labelWidth + (label ? labelGapWithTick : 0)
43
+
44
+ return Math.round(updatedYAxisWidth)
45
+ }
46
+
47
+ return 0
48
+ }
@@ -0,0 +1,48 @@
1
+ import { XAxisProps, YAxisProps } from "../index"
2
+ import { AxisDomain } from "./types"
3
+ import { AxisRange } from "../state/selectors/axisSelectors"
4
+ import { propsAreEqual } from "./propsAreEqual"
5
+
6
+ function shortArraysAreEqual(
7
+ arr1: AxisDomain | AxisRange | undefined,
8
+ arr2: AxisDomain | AxisRange | undefined,
9
+ ): boolean {
10
+ if (arr1 === arr2) {
11
+ return true
12
+ }
13
+
14
+ if (Array.isArray(arr1) && arr1.length === 2 && Array.isArray(arr2) && arr2.length === 2) {
15
+ return arr1[0] === arr2[0] && arr1[1] === arr2[1]
16
+ }
17
+
18
+ return false
19
+ }
20
+
21
+ /**
22
+ * Usually we would not compare array props deeply for performance consideration.
23
+ * However, for axis props, domain is sometimes defined as a two-elements array, and range is always
24
+ * a two-elements array. So we can do a shallow comparison for the rest props and a shallow
25
+ * comparison for these two array props.
26
+ * @param prevProps
27
+ * @param nextProps
28
+ */
29
+ export function axisPropsAreEqual<T extends YAxisProps | XAxisProps>(
30
+ prevProps: T,
31
+ nextProps: T,
32
+ ): boolean {
33
+ if (prevProps === nextProps) {
34
+ return true
35
+ }
36
+ const { domain: prevDomain, range: prevRange, ...prevRest } = prevProps
37
+ const { domain: nextDomain, range: nextRange, ...nextRest } = nextProps
38
+
39
+ if (!shortArraysAreEqual(prevDomain, nextDomain)) {
40
+ return false
41
+ }
42
+
43
+ if (!shortArraysAreEqual(prevRange, nextRange)) {
44
+ return false
45
+ }
46
+
47
+ return propsAreEqual(prevRest, nextRest)
48
+ }