@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,541 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import { createMemo, For, Show } from 'solid-js';
3
+ import { splitProps } from "../util/solid-1-compat"
4
+ import type { WithoutRemoveFalse } from "../util/types"
5
+ import type { CamelCaseSVGAttrs } from "../util/CamelCaseSVGAttrs"
6
+ import type { JSX } from '@solidjs/web';
7
+ import { clsx } from "clsx"
8
+ import { isNullish, isNumber, isNumOrStr } from "../util/DataUtils"
9
+ import { Global } from "../util/Global"
10
+ import { getStringSize } from "../util/DOMUtils"
11
+ import { reduceCSSCalc } from "../util/ReduceCSSCalc"
12
+ import { svgPropertiesAndEvents } from "../util/svgPropertiesAndEvents"
13
+ import { resolveDefaultProps } from "../util/resolveDefaultProps"
14
+ import { isWellBehavedNumber } from "../util/isWellBehavedNumber"
15
+
16
+ const BREAKING_SPACES = /[ \f\n\r\t\v\u2028\u2029]+/
17
+
18
+ interface Words {
19
+ words: Array<string>
20
+ width: number | undefined
21
+ }
22
+
23
+ interface WordsWithWidth {
24
+ words: Array<string>
25
+ width: number
26
+ }
27
+
28
+ interface WordWithComputedWidth {
29
+ word: string
30
+ width: number
31
+ }
32
+
33
+ interface CalculatedWordWidths {
34
+ wordsWithComputedWidth: Array<WordWithComputedWidth>
35
+ spaceWidth: number
36
+ }
37
+
38
+ type CalculateWordWidthsParam = Pick<Props, "children" | "breakAll" | "style">
39
+
40
+ const calculateWordWidths = (param: CalculateWordWidthsParam): CalculatedWordWidths | null => {
41
+ try {
42
+ let words: string[] = []
43
+ if (!isNullish(param.children)) {
44
+ if (param.breakAll) {
45
+ words = param.children.toString().split("")
46
+ } else {
47
+ words = param.children.toString().split(BREAKING_SPACES)
48
+ }
49
+ }
50
+
51
+ const wordsWithComputedWidth = words.map((word) => ({
52
+ width: getStringSize(word, param.style).width,
53
+ word,
54
+ }))
55
+
56
+ const spaceWidth = param.breakAll ? 0 : getStringSize("\u00A0", param.style).width
57
+
58
+ return { spaceWidth, wordsWithComputedWidth }
59
+ } catch {
60
+ return null
61
+ }
62
+ }
63
+
64
+ /**
65
+ * @inline
66
+ */
67
+ export type TextAnchor = "start" | "middle" | "end" | "inherit"
68
+
69
+ export function isValidTextAnchor(value: string | undefined): value is TextAnchor {
70
+ return value === "start" || value === "middle" || value === "end" || value === "inherit"
71
+ }
72
+
73
+ /**
74
+ * @inline
75
+ */
76
+ export type TextVerticalAnchor = "start" | "middle" | "end"
77
+
78
+ /**
79
+ * @inline
80
+ */
81
+ export type RenderableText = string | number | boolean | null | undefined
82
+
83
+ export function isRenderableText(val: unknown): val is RenderableText {
84
+ return (
85
+ isNullish(val) || typeof val === "string" || typeof val === "number" || typeof val === "boolean"
86
+ )
87
+ }
88
+
89
+ interface TextProps {
90
+ /**
91
+ * When true, scales the text to fit within the specified width.
92
+ * The text will be scaled down proportionally to fit the available space.
93
+ *
94
+ * **Important interactions:**
95
+ * - Requires `width` to be defined to have any effect. If width is undefined, scaleToFit does nothing.
96
+ * - When enabled, `maxLines` restrictions are bypassed and ellipsis truncation is disabled.
97
+ * - Uses the first line's width to calculate the scale factor.
98
+ * - The scaling transform is applied as `scale(width / lineWidth)`.
99
+ *
100
+ * @defaultValue false
101
+ */
102
+ scaleToFit?: boolean
103
+
104
+ /**
105
+ * Text rotation angle in degrees.
106
+ * Positive values rotate clockwise, negative values rotate counterclockwise.
107
+ *
108
+ * @defaultValue 0
109
+ */
110
+ angle?: number
111
+
112
+ /**
113
+ * Horizontal text alignment within the text element.
114
+ * - 'start': Text starts at the x coordinate (left-aligned for LTR text)
115
+ * - 'middle': Text is centered on the x coordinate
116
+ * - 'end': Text ends at the x coordinate (right-aligned for LTR text)
117
+ * - 'inherit': Inherits the text-anchor from parent element
118
+ *
119
+ * **Note:** This controls horizontal alignment only and does not affect RTL text behavior.
120
+ * @defaultValue 'start'
121
+ */
122
+ textAnchor?: TextAnchor
123
+
124
+ /**
125
+ * Vertical text alignment relative to the y coordinate.
126
+ * - 'start': Text baseline starts at y coordinate (text appears below the y position)
127
+ * - 'middle': Text is vertically centered on the y coordinate
128
+ * - 'end': Text baseline ends at y coordinate (text appears above the y position)
129
+ *
130
+ * **Note:** This controls vertical positioning only and does not affect RTL (right-to-left) text behavior.
131
+ * The alignment calculation uses capHeight and lineHeight to determine the starting dy offset.
132
+ *
133
+ * @defaultValue 'end'
134
+ */
135
+ verticalAnchor?: TextVerticalAnchor
136
+
137
+ /**
138
+ * CSS styles to apply to the text element.
139
+ * These styles are used for text measurement calculations when width constraints or scaleToFit are used.
140
+ * Font-related properties (fontSize, fontFamily, fontWeight, etc.) are particularly important for accurate measurements.
141
+ */
142
+ style?: JSX.CSSProperties
143
+
144
+ /**
145
+ * Line height for multi-line text.
146
+ * Can be a number (height in pixels) or a string with CSS units.
147
+ * Used to calculate spacing between lines when text wraps to multiple lines.
148
+ * Also used in verticalAnchor calculations for positioning the text block.
149
+ * @defaultValue '1em'
150
+ */
151
+ lineHeight?: number | string
152
+
153
+ /**
154
+ * When true, enables character-level breaking instead of word-level breaking.
155
+ * - false: Text breaks at word boundaries (spaces, tabs, etc.)
156
+ * - true: Text can break between any characters, useful for languages without spaces
157
+ *
158
+ * **Note:** Only effective when `width` is defined to enable line breaking.
159
+ * @defaultValue false
160
+ */
161
+ breakAll?: boolean
162
+
163
+ /**
164
+ * The text content to render.
165
+ * Can be a string or number. Numbers will be converted to strings.
166
+ * undefined or null values will result in no text being rendered.
167
+ */
168
+ children?: RenderableText
169
+
170
+ /**
171
+ * Maximum number of lines to display when text wrapping is enabled.
172
+ * When text exceeds this limit, it will be truncated with an ellipsis (...).
173
+ *
174
+ * **Important requirements for ellipsis truncation:**
175
+ * - `width` must be defined (no effect when width is undefined)
176
+ * - `scaleToFit` must be false (when scaleToFit is true, maxLines is bypassed)
177
+ * - Text must actually overflow the specified maxLines or width constraints
178
+ *
179
+ * **Truncation behavior:**
180
+ * - Uses binary search to find the optimal truncation point
181
+ * - Adds ellipsis (...) at the end of the truncated text
182
+ * - Ensures the truncated text + ellipsis fits within the constraints
183
+ *
184
+ * **Interaction with other props:**
185
+ * - When `scaleToFit` is true, this property is ignored
186
+ * - Requires `width` to be set for line breaking to occur
187
+ */
188
+ maxLines?: number
189
+ /**
190
+ * When width is specified, the text will automatically wrap by calculating the width of text.
191
+ */
192
+ width?: number | string
193
+ }
194
+
195
+ export type Props = WithoutRemoveFalse<
196
+ Omit<
197
+ JSX.TextSVGAttributes<SVGTextElement>,
198
+ "textAnchor" | "text-anchor" | "children" | "ref" | "style" | "x" | "y" | "dx" | "dy" | "width"
199
+ >
200
+ > &
201
+ CamelCaseSVGAttrs &
202
+ TextProps & {
203
+ x?: number | string
204
+ y?: number | string
205
+ dx?: number | string
206
+ dy?: number | string
207
+ className?: string
208
+ ref?: SVGTextElement | ((el: SVGTextElement) => void)
209
+ }
210
+
211
+ type CalculateWordsByLinesProps = Pick<Props, "maxLines" | "children" | "style" | "breakAll">
212
+
213
+ const calculate = (
214
+ words: ReadonlyArray<WordWithComputedWidth>,
215
+ lineWidth: number | string | undefined,
216
+ spaceWidth: number,
217
+ scaleToFit: boolean,
218
+ ): ReadonlyArray<WordsWithWidth> =>
219
+ words.reduce((result: Array<WordsWithWidth>, { word, width }) => {
220
+ const currentLine = result[result.length - 1]
221
+
222
+ if (
223
+ currentLine &&
224
+ width != null &&
225
+ (lineWidth == null ||
226
+ scaleToFit ||
227
+ currentLine.width + width + spaceWidth < Number(lineWidth))
228
+ ) {
229
+ /* Word can be added to an existing line */
230
+ currentLine.words.push(word)
231
+ currentLine.width += width + spaceWidth
232
+ } else {
233
+ /* Add first word to line or word is too long to scaleToFit on existing line */
234
+ const newLine: WordsWithWidth = { width, words: [word] }
235
+ result.push(newLine)
236
+ }
237
+
238
+ return result
239
+ }, [])
240
+
241
+ const findLongestLine = (words: ReadonlyArray<WordsWithWidth>): WordsWithWidth =>
242
+ words.reduce((a: WordsWithWidth, b: WordsWithWidth) => (a.width > b.width ? a : b))
243
+
244
+ const suffix = "\u2026"
245
+
246
+ const checkOverflow = (
247
+ text: string,
248
+ index: number,
249
+ breakAll: TextProps["breakAll"],
250
+ style: TextProps["style"],
251
+ maxLines: number,
252
+ lineWidth: number | string | undefined,
253
+ spaceWidth: number,
254
+ scaleToFit: boolean,
255
+ ): [boolean, ReadonlyArray<Words>] => {
256
+ const tempText = text.slice(0, index)
257
+
258
+ const words = calculateWordWidths({
259
+ breakAll,
260
+ children: tempText + suffix,
261
+ style,
262
+ })
263
+
264
+ if (!words) {
265
+ return [false, []]
266
+ }
267
+
268
+ const result: ReadonlyArray<WordsWithWidth> = calculate(
269
+ words.wordsWithComputedWidth,
270
+ lineWidth,
271
+ spaceWidth,
272
+ scaleToFit,
273
+ )
274
+
275
+ const doesOverflow = result.length > maxLines || findLongestLine(result).width > Number(lineWidth)
276
+
277
+ return [doesOverflow, result]
278
+ }
279
+
280
+ const calculateWordsByLines = (
281
+ lineProps: CalculateWordsByLinesProps,
282
+ initialWordsWithComputedWith: ReadonlyArray<WordWithComputedWidth>,
283
+ spaceWidth: number,
284
+ lineWidth: number | string | undefined,
285
+ scaleToFit: boolean,
286
+ ): ReadonlyArray<Words> => {
287
+ const shouldLimitLines = isNumber(lineProps.maxLines)
288
+ const text = String(lineProps.children)
289
+
290
+ const originalResult: ReadonlyArray<WordsWithWidth> = calculate(
291
+ initialWordsWithComputedWith,
292
+ lineWidth,
293
+ spaceWidth,
294
+ scaleToFit,
295
+ )
296
+
297
+ if (!shouldLimitLines || scaleToFit) {
298
+ return originalResult
299
+ }
300
+
301
+ const overflows =
302
+ originalResult.length > (lineProps.maxLines ?? 0) ||
303
+ findLongestLine(originalResult).width > Number(lineWidth)
304
+ if (!overflows) {
305
+ return originalResult
306
+ }
307
+
308
+ let start = 0
309
+ let end = text.length - 1
310
+
311
+ let iterations = 0
312
+ let trimmedResult
313
+
314
+ while (start <= end && iterations <= text.length - 1) {
315
+ const middle = Math.floor((start + end) / 2)
316
+ const prev = middle - 1
317
+
318
+ const [doesPrevOverflow, result] = checkOverflow(
319
+ text,
320
+ prev,
321
+ lineProps.breakAll,
322
+ lineProps.style,
323
+ lineProps.maxLines ?? 0,
324
+ lineWidth,
325
+ spaceWidth,
326
+ scaleToFit,
327
+ )
328
+ const [doesMiddleOverflow] = checkOverflow(
329
+ text,
330
+ middle,
331
+ lineProps.breakAll,
332
+ lineProps.style,
333
+ lineProps.maxLines ?? 0,
334
+ lineWidth,
335
+ spaceWidth,
336
+ scaleToFit,
337
+ )
338
+
339
+ if (!doesPrevOverflow && !doesMiddleOverflow) {
340
+ start = middle + 1
341
+ }
342
+
343
+ if (doesPrevOverflow && doesMiddleOverflow) {
344
+ end = middle - 1
345
+ }
346
+
347
+ if (!doesPrevOverflow && doesMiddleOverflow) {
348
+ trimmedResult = result
349
+ break
350
+ }
351
+
352
+ iterations++
353
+ }
354
+
355
+ /* Fallback to originalResult (result without trimming) if we cannot find the
356
+ * where to trim. This should not happen :tm: */
357
+ return trimmedResult || originalResult
358
+ }
359
+
360
+ const getWordsWithoutCalculate = (children: RenderableText): Array<Words> => {
361
+ const words = !isNullish(children) ? children.toString().split(BREAKING_SPACES) : []
362
+ return [{ width: undefined, words }]
363
+ }
364
+
365
+ type GetWordsByLinesProps = Pick<
366
+ Props,
367
+ "width" | "scaleToFit" | "children" | "style" | "breakAll" | "maxLines"
368
+ >
369
+
370
+ export const getWordsByLines = (p: GetWordsByLinesProps) => {
371
+ /* Only perform calculations if using features that require them (multiline, scaleToFit) */
372
+ if ((p.width || p.scaleToFit) && !Global.isSsr) {
373
+ let wordsWithComputedWidth: ReadonlyArray<WordWithComputedWidth>
374
+ let spaceWidth: number
375
+
376
+ const wordWidths = calculateWordWidths({
377
+ breakAll: p.breakAll,
378
+ children: p.children,
379
+ style: p.style,
380
+ })
381
+
382
+ if (wordWidths) {
383
+ const { wordsWithComputedWidth: wcw, spaceWidth: sw } = wordWidths
384
+
385
+ wordsWithComputedWidth = wcw
386
+ spaceWidth = sw
387
+ } else {
388
+ return getWordsWithoutCalculate(p.children)
389
+ }
390
+
391
+ return calculateWordsByLines(
392
+ { breakAll: p.breakAll, children: p.children, maxLines: p.maxLines, style: p.style },
393
+ wordsWithComputedWidth,
394
+ spaceWidth,
395
+ p.width,
396
+ Boolean(p.scaleToFit),
397
+ )
398
+ }
399
+ return getWordsWithoutCalculate(p.children)
400
+ }
401
+
402
+ const DEFAULT_FILL = "#808080"
403
+
404
+ export const textDefaultProps = {
405
+ angle: 0,
406
+ breakAll: false,
407
+ /* Magic number from d3 */
408
+ capHeight: "0.71em",
409
+ fill: DEFAULT_FILL,
410
+ lineHeight: "1em",
411
+ scaleToFit: false,
412
+ textAnchor: "start",
413
+ /* Maintain compat with existing charts / default SVG behavior */
414
+ verticalAnchor: "end",
415
+ x: 0,
416
+ y: 0,
417
+ } as const satisfies Partial<Props>
418
+
419
+ export function Text(outsideProps: Props) {
420
+ const resolved = resolveDefaultProps(outsideProps, textDefaultProps)
421
+
422
+ const wordsByLines = createMemo((): ReadonlyArray<Words> => {
423
+ return getWordsByLines({
424
+ breakAll: resolved.breakAll as boolean | undefined,
425
+ children: resolved.children as RenderableText,
426
+ maxLines: resolved.maxLines as number | undefined,
427
+ scaleToFit: resolved.scaleToFit as boolean | undefined,
428
+ style: resolved.style as JSX.CSSProperties | undefined,
429
+ width: resolved.width as number | string | undefined,
430
+ })
431
+ })
432
+
433
+ const propsX = () => resolved.x
434
+ const propsY = () => resolved.y
435
+ const lineHeight = () => resolved.lineHeight
436
+ const capHeight = () => resolved.capHeight
437
+ const fill = () => resolved.fill
438
+ const scaleToFit = () => resolved.scaleToFit
439
+ const textAnchor = () => resolved.textAnchor as string
440
+ const verticalAnchor = () => resolved.verticalAnchor
441
+
442
+ return (
443
+ <Show when={isNumOrStr(propsX()) && isNumOrStr(propsY()) && wordsByLines().length > 0}>
444
+ {(() => {
445
+ const x = () => Number(propsX()) + (isNumber(resolved.dx) ? resolved.dx : 0)
446
+ const y = () => Number(propsY()) + (isNumber(resolved.dy) ? resolved.dy : 0)
447
+
448
+ return (
449
+ <Show when={isWellBehavedNumber(x()) && isWellBehavedNumber(y())}>
450
+ {(() => {
451
+ const startDy = createMemo(() => {
452
+ const lines = wordsByLines()
453
+ switch (verticalAnchor()) {
454
+ case "start":
455
+ return reduceCSSCalc(`calc(${capHeight()})`)
456
+ case "middle":
457
+ return reduceCSSCalc(
458
+ `calc(${(lines.length - 1) / 2} * -${lineHeight()} + (${capHeight()} / 2))`,
459
+ )
460
+ default:
461
+ return reduceCSSCalc(`calc(${lines.length - 1} * -${lineHeight()})`)
462
+ }
463
+ })
464
+
465
+ const computedTransform = createMemo(() => {
466
+ const transforms: string[] = []
467
+ const lines = wordsByLines()
468
+ const firstLine = lines[0]
469
+ if (scaleToFit() && firstLine != null) {
470
+ const lineWidth = firstLine.width
471
+ const w = resolved.width
472
+ transforms.push(
473
+ `scale(${isNumber(w) && isNumber(lineWidth) ? Number(w) / lineWidth : 1})`,
474
+ )
475
+ }
476
+ if (resolved.angle) {
477
+ transforms.push(`rotate(${resolved.angle}, ${x()}, ${y()})`)
478
+ }
479
+ return transforms.length ? transforms.join(" ") : (resolved.transform as string | undefined)
480
+ })
481
+
482
+ /* `width` MUST stay on textProps — upstream forwards it as the SVG attr,
483
+ tests assert `toHaveAttribute("width", "78")`. The excluded keys are
484
+ handled separately; splitProps excludes them without reading them (a
485
+ rest-destructure would re-run the `children` getter). */
486
+ const [, rest] = splitProps(resolved as Record<string, unknown>, [
487
+ "dx",
488
+ "dy",
489
+ "angle",
490
+ "className",
491
+ "breakAll",
492
+ "maxLines",
493
+ "scaleToFit",
494
+ "children",
495
+ "style",
496
+ "x",
497
+ "y",
498
+ "lineHeight",
499
+ "verticalAnchor",
500
+ "textAnchor",
501
+ "capHeight",
502
+ "fill",
503
+ "ref",
504
+ ])
505
+ const filteredProps = () => svgPropertiesAndEvents(rest)
506
+
507
+ return (
508
+ <text
509
+ {...filteredProps()}
510
+ ref={resolved.ref as ((el: SVGTextElement) => void) | undefined}
511
+ x={x()}
512
+ y={y()}
513
+ class={clsx("recharts-text", resolved.className as string | undefined)}
514
+ text-anchor={textAnchor() as "start" | "middle" | "end" | "inherit"}
515
+ fill={(fill() as string).includes("url") ? DEFAULT_FILL : (fill() as string)}
516
+ transform={computedTransform()}
517
+ >
518
+ <For each={wordsByLines() as Words[]}>
519
+ {(line, index) => {
520
+ const words = () => line.words.join(resolved.breakAll ? "" : " ")
521
+ return (
522
+ <tspan
523
+ x={x()}
524
+ dy={index() === 0 ? startDy() : (lineHeight() as string | number)}
525
+ >
526
+ {words()}
527
+ </tspan>
528
+ )
529
+ }}
530
+ </For>
531
+ </text>
532
+ )
533
+ })()}
534
+ </Show>
535
+ )
536
+ })()}
537
+ </Show>
538
+ )
539
+ }
540
+
541
+ Text.displayName = "Text"