@eifi1/ui-kit 0.54.0 → 0.56.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 (847) hide show
  1. package/README.md +90 -76
  2. package/dist/admin/plan-change.js +2 -2
  3. package/dist/admin/plan-change.js.map +1 -1
  4. package/dist/admin/user-roster.d.ts +6 -0
  5. package/dist/admin/user-roster.js +4 -0
  6. package/dist/admin/user-roster.js.map +1 -1
  7. package/dist/billing/billing-labels.d.ts +26 -0
  8. package/dist/billing/billing-labels.js +9 -0
  9. package/dist/billing/billing-labels.js.map +1 -1
  10. package/dist/billing/subscription-standing.d.ts +61 -0
  11. package/dist/billing/subscription-standing.js +51 -0
  12. package/dist/billing/subscription-standing.js.map +1 -0
  13. package/dist/billing/usage-meter.d.ts +52 -0
  14. package/dist/billing/usage-meter.js +52 -0
  15. package/dist/billing/usage-meter.js.map +1 -0
  16. package/dist/chart.d.ts +1 -0
  17. package/dist/chart.js +4 -0
  18. package/dist/chart.js.map +1 -1
  19. package/dist/components/alert-banner.js +2 -3
  20. package/dist/components/alert-banner.js.map +1 -1
  21. package/dist/components/amount-input.js +3 -15
  22. package/dist/components/amount-input.js.map +1 -1
  23. package/dist/components/autocomplete.js +2 -2
  24. package/dist/components/autocomplete.js.map +1 -1
  25. package/dist/components/bulk-action-bar.js +2 -1
  26. package/dist/components/bulk-action-bar.js.map +1 -1
  27. package/dist/components/button.d.ts +35 -1
  28. package/dist/components/button.js +6 -9
  29. package/dist/components/button.js.map +1 -1
  30. package/dist/components/calendar-heatmap.js +2 -2
  31. package/dist/components/calendar-heatmap.js.map +1 -1
  32. package/dist/components/camera-button.d.ts +89 -0
  33. package/dist/components/camera-button.js +122 -0
  34. package/dist/components/camera-button.js.map +1 -0
  35. package/dist/components/camera-capture.d.ts +66 -0
  36. package/dist/components/camera-capture.js +190 -0
  37. package/dist/components/camera-capture.js.map +1 -0
  38. package/dist/components/camera-labels.d.ts +20 -0
  39. package/dist/components/camera-labels.js +15 -0
  40. package/dist/components/camera-labels.js.map +1 -0
  41. package/dist/components/chart-edge.d.ts +9 -0
  42. package/dist/components/chart-edge.js +14 -3
  43. package/dist/components/chart-edge.js.map +1 -1
  44. package/dist/components/chart-zoom-core.js +34 -29
  45. package/dist/components/chart-zoom-core.js.map +1 -1
  46. package/dist/components/checkbox-group.js +1 -1
  47. package/dist/components/checkbox-group.js.map +1 -1
  48. package/dist/components/combobox-core.js +3 -2
  49. package/dist/components/combobox-core.js.map +1 -1
  50. package/dist/components/combobox.js +2 -2
  51. package/dist/components/combobox.js.map +1 -1
  52. package/dist/components/consent-again-notice-labels.d.ts +25 -0
  53. package/dist/components/consent-again-notice-labels.js +15 -0
  54. package/dist/components/consent-again-notice-labels.js.map +1 -0
  55. package/dist/components/consent-again-notice.d.ts +85 -0
  56. package/dist/components/consent-again-notice.js +94 -0
  57. package/dist/components/consent-again-notice.js.map +1 -0
  58. package/dist/components/country-select.js +2 -7
  59. package/dist/components/country-select.js.map +1 -1
  60. package/dist/components/currency-select.js +2 -2
  61. package/dist/components/currency-select.js.map +1 -1
  62. package/dist/components/danger-confirm.js +2 -2
  63. package/dist/components/danger-confirm.js.map +1 -1
  64. package/dist/components/data-table-column-settings.js +2 -2
  65. package/dist/components/data-table-column-settings.js.map +1 -1
  66. package/dist/components/data-table-fit.js.map +1 -1
  67. package/dist/components/data-table-virtual.js +13 -3
  68. package/dist/components/data-table-virtual.js.map +1 -1
  69. package/dist/components/date-field.js +2 -2
  70. package/dist/components/date-field.js.map +1 -1
  71. package/dist/components/date-picker.js +2 -2
  72. package/dist/components/date-picker.js.map +1 -1
  73. package/dist/components/date-range-picker.js +2 -6
  74. package/dist/components/date-range-picker.js.map +1 -1
  75. package/dist/components/dialog-frame.d.ts +3 -1
  76. package/dist/components/dialog-frame.js.map +1 -1
  77. package/dist/components/dropdown.js +7 -3
  78. package/dist/components/dropdown.js.map +1 -1
  79. package/dist/components/entity-combobox.js +2 -2
  80. package/dist/components/entity-combobox.js.map +1 -1
  81. package/dist/components/field-parts.d.ts +108 -6
  82. package/dist/components/field-parts.js +59 -6
  83. package/dist/components/field-parts.js.map +1 -1
  84. package/dist/components/field-suggestion-labels.d.ts +2 -0
  85. package/dist/components/field-suggestion-labels.js +10 -0
  86. package/dist/components/field-suggestion-labels.js.map +1 -0
  87. package/dist/components/field.js +1 -1
  88. package/dist/components/field.js.map +1 -1
  89. package/dist/components/file-button.d.ts +1 -1
  90. package/dist/components/file-button.js.map +1 -1
  91. package/dist/components/floating-panel.d.ts +7 -6
  92. package/dist/components/floating-panel.js +3 -17
  93. package/dist/components/floating-panel.js.map +1 -1
  94. package/dist/components/form-actions.d.ts +3 -2
  95. package/dist/components/form-actions.js.map +1 -1
  96. package/dist/components/hover-menu.js +3 -2
  97. package/dist/components/hover-menu.js.map +1 -1
  98. package/dist/components/icon-button.d.ts +23 -5
  99. package/dist/components/icon-button.js +7 -8
  100. package/dist/components/icon-button.js.map +1 -1
  101. package/dist/components/inline-confirm.js +2 -1
  102. package/dist/components/inline-confirm.js.map +1 -1
  103. package/dist/components/inline-entity-combobox.js +2 -2
  104. package/dist/components/inline-entity-combobox.js.map +1 -1
  105. package/dist/components/input.js +2 -2
  106. package/dist/components/input.js.map +1 -1
  107. package/dist/components/jump-calendar.js +3 -3
  108. package/dist/components/jump-calendar.js.map +1 -1
  109. package/dist/components/legal.d.ts +13 -1
  110. package/dist/components/legal.js +12 -0
  111. package/dist/components/legal.js.map +1 -1
  112. package/dist/components/legended-series-chart.d.ts +83 -0
  113. package/dist/components/legended-series-chart.js +77 -0
  114. package/dist/components/legended-series-chart.js.map +1 -0
  115. package/dist/components/lightbox.js +2 -1
  116. package/dist/components/lightbox.js.map +1 -1
  117. package/dist/components/mini-calendar.js +13 -5
  118. package/dist/components/mini-calendar.js.map +1 -1
  119. package/dist/components/modal.d.ts +23 -2
  120. package/dist/components/modal.js +24 -6
  121. package/dist/components/modal.js.map +1 -1
  122. package/dist/components/month-picker.d.ts +1 -1
  123. package/dist/components/month-picker.js +6 -6
  124. package/dist/components/month-picker.js.map +1 -1
  125. package/dist/components/multi-entity-combobox.js +2 -2
  126. package/dist/components/multi-entity-combobox.js.map +1 -1
  127. package/dist/components/multi-select.js +2 -6
  128. package/dist/components/multi-select.js.map +1 -1
  129. package/dist/components/number-input.js +2 -2
  130. package/dist/components/number-input.js.map +1 -1
  131. package/dist/components/page-header-layout.d.ts +18 -0
  132. package/dist/components/page-header-layout.js +23 -0
  133. package/dist/components/page-header-layout.js.map +1 -0
  134. package/dist/components/page-header-skeleton.d.ts +41 -0
  135. package/dist/components/page-header-skeleton.js +52 -0
  136. package/dist/components/page-header-skeleton.js.map +1 -0
  137. package/dist/components/page-header.js +4 -17
  138. package/dist/components/page-header.js.map +1 -1
  139. package/dist/components/popover.js +7 -2
  140. package/dist/components/popover.js.map +1 -1
  141. package/dist/components/release-notes-labels.d.ts +16 -0
  142. package/dist/components/release-notes-labels.js +18 -0
  143. package/dist/components/release-notes-labels.js.map +1 -0
  144. package/dist/components/release-notes.d.ts +65 -0
  145. package/dist/components/release-notes.js +65 -0
  146. package/dist/components/release-notes.js.map +1 -0
  147. package/dist/components/select.js +2 -2
  148. package/dist/components/select.js.map +1 -1
  149. package/dist/components/series-chart-labels.d.ts +9 -0
  150. package/dist/components/series-chart-labels.js +3 -1
  151. package/dist/components/series-chart-labels.js.map +1 -1
  152. package/dist/components/series-chart.d.ts +5 -0
  153. package/dist/components/series-chart.js +89 -36
  154. package/dist/components/series-chart.js.map +1 -1
  155. package/dist/components/toggle-group.js +3 -2
  156. package/dist/components/toggle-group.js.map +1 -1
  157. package/dist/components/treemap-layout.js.map +1 -1
  158. package/dist/components/treemap.d.ts +17 -15
  159. package/dist/components/treemap.js +167 -85
  160. package/dist/components/treemap.js.map +1 -1
  161. package/dist/eslint/index.js +1 -1
  162. package/dist/eslint/role-utilities.d.ts +2 -2
  163. package/dist/eslint/role-utilities.js.map +1 -1
  164. package/dist/feedback/feedback-inbox-page.d.ts +260 -0
  165. package/dist/feedback/feedback-inbox-page.js +207 -0
  166. package/dist/feedback/feedback-inbox-page.js.map +1 -0
  167. package/dist/feedback/feedback-vocabulary.js +2 -2
  168. package/dist/feedback/feedback-vocabulary.js.map +1 -1
  169. package/dist/feedback.d.ts +1 -0
  170. package/dist/feedback.js +6 -0
  171. package/dist/feedback.js.map +1 -1
  172. package/dist/hooks/use-debounce.d.ts +32 -5
  173. package/dist/hooks/use-debounce.js +6 -5
  174. package/dist/hooks/use-debounce.js.map +1 -1
  175. package/dist/hooks/use-file-picker.d.ts +3 -1
  176. package/dist/hooks/use-file-picker.js.map +1 -1
  177. package/dist/hooks/use-focus-trap.d.ts +19 -3
  178. package/dist/hooks/use-focus-trap.js +15 -5
  179. package/dist/hooks/use-focus-trap.js.map +1 -1
  180. package/dist/hooks/use-has-camera.d.ts +36 -0
  181. package/dist/hooks/use-has-camera.js +53 -0
  182. package/dist/hooks/use-has-camera.js.map +1 -0
  183. package/dist/hooks/use-hotkey.js +1 -10
  184. package/dist/hooks/use-hotkey.js.map +1 -1
  185. package/dist/hooks/use-overlay-history.d.ts +6 -1
  186. package/dist/hooks/use-overlay-history.js +10 -2
  187. package/dist/hooks/use-overlay-history.js.map +1 -1
  188. package/dist/i18n/defaults.js +11 -1
  189. package/dist/i18n/defaults.js.map +1 -1
  190. package/dist/i18n/german.js +75 -3
  191. package/dist/i18n/german.js.map +1 -1
  192. package/dist/i18n/kit-labels.d.ts +20 -0
  193. package/dist/i18n/kit-labels.js.map +1 -1
  194. package/dist/i18n/locales/en.js +92 -4
  195. package/dist/i18n/locales/en.js.map +3 -3
  196. package/dist/i18n/locales/es.js +71 -3
  197. package/dist/i18n/locales/es.js.map +1 -1
  198. package/dist/i18n/locales/fr.js +72 -2
  199. package/dist/i18n/locales/fr.js.map +1 -1
  200. package/dist/i18n/locales/hu.js +74 -3
  201. package/dist/i18n/locales/hu.js.map +1 -1
  202. package/dist/i18n/locales/it.js +74 -3
  203. package/dist/i18n/locales/it.js.map +1 -1
  204. package/dist/i18n/locales/zh.js +71 -3
  205. package/dist/i18n/locales/zh.js.map +1 -1
  206. package/dist/i18n/review.js +22 -1
  207. package/dist/i18n/review.js.map +1 -1
  208. package/dist/index.d.ts +24 -5
  209. package/dist/index.js +35 -1
  210. package/dist/index.js.map +1 -1
  211. package/dist/landing/landing-labels.d.ts +8 -0
  212. package/dist/landing/landing-labels.js +2 -1
  213. package/dist/landing/landing-labels.js.map +1 -1
  214. package/dist/lib/changelog.d.ts +130 -0
  215. package/dist/lib/changelog.js +137 -0
  216. package/dist/lib/changelog.js.map +1 -0
  217. package/dist/lib/clipboard-minus.js +2 -2
  218. package/dist/lib/clipboard-minus.js.map +1 -1
  219. package/dist/lib/dates.d.ts +29 -3
  220. package/dist/lib/dates.js +41 -12
  221. package/dist/lib/dates.js.map +1 -1
  222. package/dist/lib/editable-content.d.ts +33 -0
  223. package/dist/lib/editable-content.js +15 -0
  224. package/dist/lib/editable-content.js.map +1 -0
  225. package/dist/lib/focus-left.d.ts +47 -1
  226. package/dist/lib/focus-left.js +11 -2
  227. package/dist/lib/focus-left.js.map +1 -1
  228. package/dist/lib/server-wake.d.ts +49 -9
  229. package/dist/lib/server-wake.js +25 -14
  230. package/dist/lib/server-wake.js.map +1 -1
  231. package/dist/lib/session-refresh.d.ts +53 -0
  232. package/dist/lib/session-refresh.js +27 -1
  233. package/dist/lib/session-refresh.js.map +1 -1
  234. package/dist/rhf/fields.js +3 -3
  235. package/dist/rhf/fields.js.map +1 -1
  236. package/dist/shell/app-shell.d.ts +25 -1
  237. package/dist/shell/app-shell.js +3 -1
  238. package/dist/shell/app-shell.js.map +1 -1
  239. package/dist/shell/dev-menu.d.ts +3 -0
  240. package/dist/shell/dev-menu.js +4 -2
  241. package/dist/shell/dev-menu.js.map +1 -1
  242. package/dist/shell/held-changes-banner-labels.d.ts +23 -0
  243. package/dist/shell/held-changes-banner-labels.js +14 -0
  244. package/dist/shell/held-changes-banner-labels.js.map +1 -0
  245. package/dist/shell/held-changes-banner.d.ts +75 -0
  246. package/dist/shell/held-changes-banner.js +106 -0
  247. package/dist/shell/held-changes-banner.js.map +1 -0
  248. package/dist/shell/sync-status-indicator.d.ts +27 -12
  249. package/dist/shell/sync-status-indicator.js +13 -4
  250. package/dist/shell/sync-status-indicator.js.map +1 -1
  251. package/dist/shell/top-bar-parts-labels.d.ts +5 -0
  252. package/dist/shell/top-bar-parts-labels.js +3 -1
  253. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  254. package/dist/shell.d.ts +2 -0
  255. package/dist/shell.js +3 -0
  256. package/dist/shell.js.map +1 -1
  257. package/dist/sync/engine.d.ts +11 -2
  258. package/dist/sync/engine.js +13 -5
  259. package/dist/sync/engine.js.map +1 -1
  260. package/dist/sync/hooks.d.ts +3 -2
  261. package/dist/sync/hooks.js +4 -2
  262. package/dist/sync/hooks.js.map +1 -1
  263. package/dist/testing/css-variables.generated.d.ts +2 -2
  264. package/dist/testing/css-variables.generated.js +1 -1
  265. package/dist/testing/css-variables.generated.js.map +1 -1
  266. package/dist/theme/chart-palette.d.ts +18 -0
  267. package/dist/theme/chart-palette.js +17 -1
  268. package/dist/theme/chart-palette.js.map +1 -1
  269. package/dist/theme/contrast-tokens.d.ts +3 -3
  270. package/dist/theme/contrast-tokens.js.map +1 -1
  271. package/dist/theme/contrast.d.ts +4 -4
  272. package/dist/theme/contrast.js.map +1 -1
  273. package/dist/tour/tour-overlay.js +2 -1
  274. package/dist/tour/tour-overlay.js.map +1 -1
  275. package/package.json +9 -12
  276. package/tokens.css +19 -54
  277. package/src/account/account-parts.ts +0 -47
  278. package/src/account/account-settings-labels.ts +0 -240
  279. package/src/account/account-settings.tsx +0 -698
  280. package/src/account/data-export-setting-labels.ts +0 -20
  281. package/src/account/data-export-setting.tsx +0 -200
  282. package/src/account/delete-account-setting-labels.ts +0 -33
  283. package/src/account/delete-account-setting.tsx +0 -342
  284. package/src/account/email-change-setting-labels.ts +0 -31
  285. package/src/account/email-change-setting.tsx +0 -443
  286. package/src/account/passkeys-setting.tsx +0 -445
  287. package/src/account/sessions-setting-labels.ts +0 -24
  288. package/src/account/sessions-setting.tsx +0 -283
  289. package/src/admin/admin-action-confirm-labels.ts +0 -19
  290. package/src/admin/admin-action-confirm.tsx +0 -509
  291. package/src/admin/admin-action-log-labels.ts +0 -83
  292. package/src/admin/admin-action-log.tsx +0 -464
  293. package/src/admin/admin-area-labels.ts +0 -114
  294. package/src/admin/admin-forbidden.tsx +0 -75
  295. package/src/admin/admin-overview.tsx +0 -258
  296. package/src/admin/admin-parts.ts +0 -68
  297. package/src/admin/admin-sections.tsx +0 -208
  298. package/src/admin/admin-tool-links.tsx +0 -90
  299. package/src/admin/invitations-panel-labels.ts +0 -31
  300. package/src/admin/invitations-panel.tsx +0 -516
  301. package/src/admin/mail-test-card-labels.ts +0 -19
  302. package/src/admin/mail-test-card.tsx +0 -189
  303. package/src/admin/plan-change-labels.ts +0 -5
  304. package/src/admin/plan-change.tsx +0 -474
  305. package/src/admin/reviewer-scope-editor-labels.ts +0 -16
  306. package/src/admin/reviewer-scope-editor.tsx +0 -224
  307. package/src/admin/role-select-labels.ts +0 -16
  308. package/src/admin/role-select.tsx +0 -282
  309. package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
  310. package/src/admin/transfer-ownership-dialog.tsx +0 -162
  311. package/src/admin/user-roster-labels.ts +0 -17
  312. package/src/admin/user-roster.tsx +0 -559
  313. package/src/auth/accept-invitation-labels.ts +0 -21
  314. package/src/auth/accept-invitation.tsx +0 -210
  315. package/src/auth/auth-errors-labels.ts +0 -23
  316. package/src/auth/auth-errors.ts +0 -439
  317. package/src/auth/complete-name-dialog-labels.ts +0 -16
  318. package/src/auth/complete-name-dialog.tsx +0 -253
  319. package/src/auth/email-tag.ts +0 -75
  320. package/src/auth/forgot-password-form-labels.ts +0 -20
  321. package/src/auth/forgot-password-form.tsx +0 -221
  322. package/src/auth/form-rules.ts +0 -40
  323. package/src/auth/new-password-fields.tsx +0 -85
  324. package/src/auth/not-found-page-labels.ts +0 -12
  325. package/src/auth/not-found-page.tsx +0 -95
  326. package/src/auth/register-form-labels.ts +0 -31
  327. package/src/auth/register-form.tsx +0 -456
  328. package/src/auth/reset-password-form-labels.ts +0 -27
  329. package/src/auth/reset-password-form.tsx +0 -341
  330. package/src/auth/sign-in-form-labels.ts +0 -44
  331. package/src/auth/sign-in-form.tsx +0 -858
  332. package/src/auth/status-parts.tsx +0 -132
  333. package/src/auth/verify-email-labels.ts +0 -26
  334. package/src/auth/verify-email.tsx +0 -445
  335. package/src/billing/billing-banner.tsx +0 -258
  336. package/src/billing/billing-labels.ts +0 -381
  337. package/src/billing/billing-lock.ts +0 -108
  338. package/src/billing/billing-overview.ts +0 -157
  339. package/src/billing/billing-standing.ts +0 -80
  340. package/src/billing/cancel-request.ts +0 -97
  341. package/src/billing/cancel-subscription.tsx +0 -98
  342. package/src/billing/checkout-processing.ts +0 -394
  343. package/src/billing/checkout-return.ts +0 -90
  344. package/src/billing/pay-page.ts +0 -330
  345. package/src/billing/plan-card.tsx +0 -562
  346. package/src/billing/plan-change-labels.ts +0 -66
  347. package/src/billing/plan-limit-notice.tsx +0 -148
  348. package/src/billing/plan-limit-toast.tsx +0 -90
  349. package/src/billing/plan-limit.ts +0 -52
  350. package/src/billing/plan-price.ts +0 -98
  351. package/src/billing/plan-switch.tsx +0 -216
  352. package/src/billing/provider-page.ts +0 -84
  353. package/src/billing/subscription-actions.tsx +0 -247
  354. package/src/billing/subscription-status-chip.tsx +0 -95
  355. package/src/chart.ts +0 -103
  356. package/src/components/account-chips-labels.ts +0 -16
  357. package/src/components/account-chips.tsx +0 -474
  358. package/src/components/alert-banner.tsx +0 -670
  359. package/src/components/amount-input.tsx +0 -816
  360. package/src/components/appearance-labels.ts +0 -63
  361. package/src/components/authed-image-labels.ts +0 -11
  362. package/src/components/authed-image.tsx +0 -209
  363. package/src/components/autocomplete.tsx +0 -645
  364. package/src/components/breadcrumbs-labels.ts +0 -10
  365. package/src/components/breadcrumbs.tsx +0 -205
  366. package/src/components/bulk-action-bar-labels.ts +0 -11
  367. package/src/components/bulk-action-bar.tsx +0 -443
  368. package/src/components/button-group.tsx +0 -223
  369. package/src/components/button-look.ts +0 -256
  370. package/src/components/button.tsx +0 -339
  371. package/src/components/calculator.tsx +0 -341
  372. package/src/components/calendar-heatmap-labels.ts +0 -15
  373. package/src/components/calendar-heatmap.tsx +0 -600
  374. package/src/components/card.tsx +0 -377
  375. package/src/components/chart-edge.ts +0 -106
  376. package/src/components/chart-figure.tsx +0 -35
  377. package/src/components/chart-height.ts +0 -30
  378. package/src/components/chart-zoom-core.tsx +0 -627
  379. package/src/components/chart-zoom.tsx +0 -22
  380. package/src/components/chart.tsx +0 -554
  381. package/src/components/checkbox-group.tsx +0 -247
  382. package/src/components/checkbox.tsx +0 -346
  383. package/src/components/chip-input.tsx +0 -370
  384. package/src/components/chip-labels.ts +0 -13
  385. package/src/components/chip.tsx +0 -843
  386. package/src/components/choice-card.tsx +0 -544
  387. package/src/components/column-mapper-labels.ts +0 -38
  388. package/src/components/column-mapper.tsx +0 -655
  389. package/src/components/combobox-core.tsx +0 -1321
  390. package/src/components/combobox-suggestions.tsx +0 -131
  391. package/src/components/combobox.tsx +0 -716
  392. package/src/components/confirm-context.ts +0 -7
  393. package/src/components/confirm-dialog-labels.ts +0 -13
  394. package/src/components/confirm-dialog.tsx +0 -341
  395. package/src/components/copy-button-labels.ts +0 -13
  396. package/src/components/copy-button.tsx +0 -192
  397. package/src/components/country-select-labels.ts +0 -11
  398. package/src/components/country-select.tsx +0 -539
  399. package/src/components/currency-option-list.tsx +0 -188
  400. package/src/components/currency-select.tsx +0 -343
  401. package/src/components/danger-confirm-labels.ts +0 -20
  402. package/src/components/danger-confirm.tsx +0 -987
  403. package/src/components/data-table-cells.tsx +0 -118
  404. package/src/components/data-table-column-settings.tsx +0 -198
  405. package/src/components/data-table-filter-popover.tsx +0 -289
  406. package/src/components/data-table-filters.ts +0 -315
  407. package/src/components/data-table-fit.ts +0 -301
  408. package/src/components/data-table-groups.tsx +0 -288
  409. package/src/components/data-table-head.tsx +0 -280
  410. package/src/components/data-table-labels.ts +0 -198
  411. package/src/components/data-table-leading-row.tsx +0 -58
  412. package/src/components/data-table-mobile.tsx +0 -1117
  413. package/src/components/data-table-pagination.tsx +0 -202
  414. package/src/components/data-table-resize.ts +0 -188
  415. package/src/components/data-table-row-actions.tsx +0 -302
  416. package/src/components/data-table-row.tsx +0 -496
  417. package/src/components/data-table-selection.ts +0 -71
  418. package/src/components/data-table-shared.tsx +0 -287
  419. package/src/components/data-table-sort.ts +0 -163
  420. package/src/components/data-table-virtual.ts +0 -576
  421. package/src/components/data-table.tsx +0 -2598
  422. package/src/components/date-field.tsx +0 -684
  423. package/src/components/date-format-setting.tsx +0 -64
  424. package/src/components/date-picker.tsx +0 -404
  425. package/src/components/date-range-picker.tsx +0 -518
  426. package/src/components/description-list-labels.ts +0 -9
  427. package/src/components/description-list.tsx +0 -386
  428. package/src/components/dialog-frame-labels.ts +0 -7
  429. package/src/components/dialog-frame.tsx +0 -284
  430. package/src/components/disclosure.tsx +0 -476
  431. package/src/components/dropdown.tsx +0 -461
  432. package/src/components/empty-state.tsx +0 -136
  433. package/src/components/entity-combobox.tsx +0 -422
  434. package/src/components/error-boundary-labels.ts +0 -20
  435. package/src/components/error-boundary.tsx +0 -675
  436. package/src/components/facing-pair.ts +0 -93
  437. package/src/components/field-base-labels.ts +0 -20
  438. package/src/components/field-base.tsx +0 -656
  439. package/src/components/field-parts.tsx +0 -825
  440. package/src/components/field-strip.tsx +0 -129
  441. package/src/components/field.tsx +0 -206
  442. package/src/components/file-button.tsx +0 -295
  443. package/src/components/file-dropzone.tsx +0 -559
  444. package/src/components/floating-panel-labels.ts +0 -10
  445. package/src/components/floating-panel.tsx +0 -828
  446. package/src/components/focus-ring.ts +0 -16
  447. package/src/components/form-actions-labels.ts +0 -11
  448. package/src/components/form-actions.tsx +0 -578
  449. package/src/components/full-bleed-dialog.tsx +0 -294
  450. package/src/components/grouped-picker.tsx +0 -184
  451. package/src/components/help-popover.tsx +0 -117
  452. package/src/components/hover-menu.tsx +0 -343
  453. package/src/components/iban-input-labels.ts +0 -14
  454. package/src/components/iban-input.tsx +0 -236
  455. package/src/components/icon-button.tsx +0 -959
  456. package/src/components/icon-picker-labels.ts +0 -13
  457. package/src/components/icon-picker.tsx +0 -232
  458. package/src/components/image-grid-labels.ts +0 -11
  459. package/src/components/image-grid.tsx +0 -202
  460. package/src/components/inline-confirm.tsx +0 -116
  461. package/src/components/inline-edit-field-labels.ts +0 -11
  462. package/src/components/inline-edit-field.tsx +0 -552
  463. package/src/components/inline-entity-combobox.tsx +0 -849
  464. package/src/components/input.tsx +0 -394
  465. package/src/components/jump-calendar.tsx +0 -265
  466. package/src/components/language-select.tsx +0 -93
  467. package/src/components/legal-labels.ts +0 -105
  468. package/src/components/legal-page.tsx +0 -711
  469. package/src/components/legal.tsx +0 -668
  470. package/src/components/lightbox-labels.ts +0 -18
  471. package/src/components/lightbox.tsx +0 -399
  472. package/src/components/line-items-labels.ts +0 -14
  473. package/src/components/line-items.tsx +0 -602
  474. package/src/components/list-labels.ts +0 -12
  475. package/src/components/list.tsx +0 -870
  476. package/src/components/loading-state.tsx +0 -78
  477. package/src/components/measured-grid-labels.ts +0 -25
  478. package/src/components/measured-grid.tsx +0 -837
  479. package/src/components/menu-item.tsx +0 -241
  480. package/src/components/mini-calendar-labels.ts +0 -17
  481. package/src/components/mini-calendar.tsx +0 -792
  482. package/src/components/modal.tsx +0 -534
  483. package/src/components/money-draft.ts +0 -83
  484. package/src/components/money-field.tsx +0 -76
  485. package/src/components/month-grid.tsx +0 -229
  486. package/src/components/month-picker-labels.ts +0 -22
  487. package/src/components/month-picker.tsx +0 -1087
  488. package/src/components/multi-entity-combobox.tsx +0 -369
  489. package/src/components/multi-select.tsx +0 -376
  490. package/src/components/nav-pills.tsx +0 -198
  491. package/src/components/number-field.tsx +0 -327
  492. package/src/components/number-input.tsx +0 -559
  493. package/src/components/numeric-field.ts +0 -169
  494. package/src/components/numpad-sheet.tsx +0 -285
  495. package/src/components/one-time-code-input.tsx +0 -270
  496. package/src/components/page-contents-labels.ts +0 -9
  497. package/src/components/page-contents.tsx +0 -282
  498. package/src/components/page-header-context.ts +0 -8
  499. package/src/components/page-header.tsx +0 -298
  500. package/src/components/password-strength-labels.ts +0 -22
  501. package/src/components/password-strength.tsx +0 -241
  502. package/src/components/phone-input-labels.ts +0 -10
  503. package/src/components/phone-input.tsx +0 -282
  504. package/src/components/picker-sheet.tsx +0 -330
  505. package/src/components/pie-chart-labels.ts +0 -40
  506. package/src/components/pie-chart.tsx +0 -480
  507. package/src/components/popover-labels.ts +0 -14
  508. package/src/components/popover.tsx +0 -268
  509. package/src/components/progress-bar-labels.ts +0 -10
  510. package/src/components/progress-bar.tsx +0 -479
  511. package/src/components/qr-code.tsx +0 -76
  512. package/src/components/reauth-dialog-labels.ts +0 -13
  513. package/src/components/reauth-dialog.tsx +0 -265
  514. package/src/components/row-actions-labels.ts +0 -12
  515. package/src/components/row-actions.tsx +0 -795
  516. package/src/components/scroll-area.tsx +0 -123
  517. package/src/components/search-field.tsx +0 -192
  518. package/src/components/select.tsx +0 -294
  519. package/src/components/separator.tsx +0 -33
  520. package/src/components/series-chart-axes.ts +0 -342
  521. package/src/components/series-chart-budget.ts +0 -150
  522. package/src/components/series-chart-labels.ts +0 -33
  523. package/src/components/series-chart-thin.ts +0 -180
  524. package/src/components/series-chart-ticks.ts +0 -194
  525. package/src/components/series-chart.tsx +0 -1906
  526. package/src/components/server-wake-labels.ts +0 -11
  527. package/src/components/server-wake.tsx +0 -129
  528. package/src/components/settings-fields.tsx +0 -237
  529. package/src/components/share-card-labels.ts +0 -30
  530. package/src/components/share-card.tsx +0 -675
  531. package/src/components/signature-pad-labels.ts +0 -24
  532. package/src/components/signature-pad.tsx +0 -747
  533. package/src/components/signed-amount-labels.ts +0 -10
  534. package/src/components/signed-amount.tsx +0 -336
  535. package/src/components/skeleton.tsx +0 -80
  536. package/src/components/slider.tsx +0 -338
  537. package/src/components/sparkline-labels.ts +0 -14
  538. package/src/components/sparkline.tsx +0 -322
  539. package/src/components/spinner.tsx +0 -81
  540. package/src/components/stat-tile-labels.ts +0 -15
  541. package/src/components/stat-tile.tsx +0 -754
  542. package/src/components/status-dot.tsx +0 -170
  543. package/src/components/swatch-picker-labels.ts +0 -10
  544. package/src/components/swatch-picker.tsx +0 -283
  545. package/src/components/swipeable-row.tsx +0 -386
  546. package/src/components/switch.tsx +0 -273
  547. package/src/components/table-skeleton.tsx +0 -136
  548. package/src/components/table.tsx +0 -647
  549. package/src/components/tabs-labels.ts +0 -13
  550. package/src/components/tabs.tsx +0 -693
  551. package/src/components/text-link.tsx +0 -359
  552. package/src/components/text.tsx +0 -150
  553. package/src/components/textarea.tsx +0 -330
  554. package/src/components/tile-radio.tsx +0 -332
  555. package/src/components/time-input.tsx +0 -121
  556. package/src/components/toast-labels.ts +0 -12
  557. package/src/components/toast.tsx +0 -519
  558. package/src/components/toggle-group.tsx +0 -752
  559. package/src/components/toggle-legend.tsx +0 -394
  560. package/src/components/tooltip.tsx +0 -1149
  561. package/src/components/translation-review-editor.tsx +0 -290
  562. package/src/components/translation-review-labels.ts +0 -181
  563. package/src/components/translation-review-parts.tsx +0 -272
  564. package/src/components/translation-review.tsx +0 -1240
  565. package/src/components/tree-view.tsx +0 -589
  566. package/src/components/treemap-labels.ts +0 -47
  567. package/src/components/treemap-layout.ts +0 -210
  568. package/src/components/treemap.tsx +0 -1184
  569. package/src/components/trigger-aria.ts +0 -44
  570. package/src/components/use-anchor-dir.ts +0 -20
  571. package/src/components/use-mobile-reveal.ts +0 -62
  572. package/src/components/use-table-state.ts +0 -753
  573. package/src/components/user-avatar.tsx +0 -116
  574. package/src/components/wizard-stepper.tsx +0 -42
  575. package/src/components/write-lock-labels.ts +0 -10
  576. package/src/components/write-lock.tsx +0 -253
  577. package/src/currencies.ts +0 -90
  578. package/src/data-table.ts +0 -42
  579. package/src/demo/demo-banner.tsx +0 -153
  580. package/src/demo/demo-countdown.ts +0 -136
  581. package/src/demo/demo-ended.tsx +0 -90
  582. package/src/demo/demo-labels.ts +0 -78
  583. package/src/demo/demo-session.ts +0 -32
  584. package/src/demo/demo-start.tsx +0 -156
  585. package/src/eslint/index.ts +0 -161
  586. package/src/eslint/role-utilities.generated.ts +0 -146
  587. package/src/eslint/role-utilities.ts +0 -233
  588. package/src/feedback/feedback-attachment-download.tsx +0 -77
  589. package/src/feedback/feedback-attachment-labels.ts +0 -37
  590. package/src/feedback/feedback-attachment.tsx +0 -1239
  591. package/src/feedback/feedback-capture.ts +0 -287
  592. package/src/feedback/feedback-comment-thread.tsx +0 -353
  593. package/src/feedback/feedback-context-labels.ts +0 -11
  594. package/src/feedback/feedback-context.tsx +0 -245
  595. package/src/feedback/feedback-crash.ts +0 -547
  596. package/src/feedback/feedback-diagnostics.tsx +0 -41
  597. package/src/feedback/feedback-dialog-labels.ts +0 -29
  598. package/src/feedback/feedback-dialog.tsx +0 -452
  599. package/src/feedback/feedback-entry-file.tsx +0 -150
  600. package/src/feedback/feedback-inbox.tsx +0 -552
  601. package/src/feedback/feedback-labels.ts +0 -144
  602. package/src/feedback/feedback-menu-labels.ts +0 -12
  603. package/src/feedback/feedback-menu.tsx +0 -177
  604. package/src/feedback/feedback-mutation.ts +0 -20
  605. package/src/feedback/feedback-page-link.ts +0 -90
  606. package/src/feedback/feedback-public-labels.ts +0 -81
  607. package/src/feedback/feedback-public-list.tsx +0 -524
  608. package/src/feedback/feedback-public-switch.tsx +0 -102
  609. package/src/feedback/feedback-public-types.ts +0 -101
  610. package/src/feedback/feedback-record.ts +0 -428
  611. package/src/feedback/feedback-replies-context.ts +0 -9
  612. package/src/feedback/feedback-replies.tsx +0 -343
  613. package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
  614. package/src/feedback/feedback-row-detail-labels.ts +0 -31
  615. package/src/feedback/feedback-row-detail.tsx +0 -871
  616. package/src/feedback/feedback-status-undo.ts +0 -109
  617. package/src/feedback/feedback-submit-dialog.tsx +0 -131
  618. package/src/feedback/feedback-submit.tsx +0 -270
  619. package/src/feedback/feedback-swipe.tsx +0 -192
  620. package/src/feedback/feedback-table-labels.ts +0 -27
  621. package/src/feedback/feedback-table.tsx +0 -912
  622. package/src/feedback/feedback-thread-labels.ts +0 -22
  623. package/src/feedback/feedback-thread-parts-labels.ts +0 -41
  624. package/src/feedback/feedback-thread.tsx +0 -905
  625. package/src/feedback/feedback-vocabulary.ts +0 -263
  626. package/src/feedback/feedback-vote-button.tsx +0 -124
  627. package/src/feedback.ts +0 -116
  628. package/src/hooks/use-anchored-panel.ts +0 -396
  629. package/src/hooks/use-anchored-rect.ts +0 -77
  630. package/src/hooks/use-announce.ts +0 -85
  631. package/src/hooks/use-authed-src.ts +0 -167
  632. package/src/hooks/use-body-scroll-lock.ts +0 -119
  633. package/src/hooks/use-breakpoint.ts +0 -133
  634. package/src/hooks/use-close-transition.ts +0 -107
  635. package/src/hooks/use-copy-to-clipboard.ts +0 -122
  636. package/src/hooks/use-debounce.ts +0 -114
  637. package/src/hooks/use-dismiss.ts +0 -371
  638. package/src/hooks/use-document-title.ts +0 -33
  639. package/src/hooks/use-file-drop.ts +0 -121
  640. package/src/hooks/use-file-picker-labels.ts +0 -28
  641. package/src/hooks/use-file-picker.tsx +0 -359
  642. package/src/hooks/use-focus-trap.ts +0 -199
  643. package/src/hooks/use-hotkey.ts +0 -212
  644. package/src/hooks/use-large-text.ts +0 -41
  645. package/src/hooks/use-long-press.ts +0 -140
  646. package/src/hooks/use-media-query.ts +0 -39
  647. package/src/hooks/use-mounted.ts +0 -39
  648. package/src/hooks/use-noindex.ts +0 -37
  649. package/src/hooks/use-overlay-history.ts +0 -714
  650. package/src/hooks/use-row-swipe.ts +0 -207
  651. package/src/hooks/use-search-param-state.ts +0 -434
  652. package/src/hooks/use-windowed-rows.ts +0 -225
  653. package/src/i18n/defaults.ts +0 -267
  654. package/src/i18n/german.ts +0 -2059
  655. package/src/i18n/kit-labels.tsx +0 -1003
  656. package/src/i18n/languages.ts +0 -349
  657. package/src/i18n/locales/de-CH.ts +0 -24
  658. package/src/i18n/locales/en.ts +0 -267
  659. package/src/i18n/locales/es.ts +0 -1999
  660. package/src/i18n/locales/fr.ts +0 -2037
  661. package/src/i18n/locales/hu.ts +0 -2004
  662. package/src/i18n/locales/it.ts +0 -2014
  663. package/src/i18n/locales/zh.ts +0 -1912
  664. package/src/i18n/plurals.ts +0 -86
  665. package/src/i18n/review.ts +0 -475
  666. package/src/i18n/shared-labels.ts +0 -138
  667. package/src/i18n/swiss.ts +0 -29
  668. package/src/index.ts +0 -1191
  669. package/src/landing/access.ts +0 -93
  670. package/src/landing/landing-actions.tsx +0 -97
  671. package/src/landing/landing-labels.ts +0 -59
  672. package/src/landing/landing-sections.tsx +0 -341
  673. package/src/landing/page-seo.ts +0 -261
  674. package/src/landing/public-header.tsx +0 -121
  675. package/src/landing/public-page.tsx +0 -106
  676. package/src/landing/routing.tsx +0 -225
  677. package/src/lib/broadcast.ts +0 -52
  678. package/src/lib/calc.ts +0 -323
  679. package/src/lib/chip-edge-snap.ts +0 -212
  680. package/src/lib/clipboard-minus.ts +0 -107
  681. package/src/lib/clipping.ts +0 -34
  682. package/src/lib/cn.ts +0 -28
  683. package/src/lib/column-mapping.ts +0 -234
  684. package/src/lib/countries.ts +0 -91
  685. package/src/lib/data-attributes.ts +0 -14
  686. package/src/lib/date-format.ts +0 -227
  687. package/src/lib/dates.ts +0 -288
  688. package/src/lib/day-format.ts +0 -96
  689. package/src/lib/decimal-marks.ts +0 -108
  690. package/src/lib/describe-failure.ts +0 -18
  691. package/src/lib/device-settings.ts +0 -147
  692. package/src/lib/direction.ts +0 -74
  693. package/src/lib/document-navigation.ts +0 -17
  694. package/src/lib/document-title.ts +0 -41
  695. package/src/lib/download.ts +0 -172
  696. package/src/lib/float-clearance.ts +0 -70
  697. package/src/lib/floating-stack.ts +0 -70
  698. package/src/lib/focus-left.ts +0 -156
  699. package/src/lib/format.ts +0 -585
  700. package/src/lib/http-status.ts +0 -38
  701. package/src/lib/iban.ts +0 -251
  702. package/src/lib/ime.ts +0 -24
  703. package/src/lib/intl-cache.ts +0 -27
  704. package/src/lib/iso-day.ts +0 -13
  705. package/src/lib/lazy-with-fallback.ts +0 -82
  706. package/src/lib/logger.ts +0 -69
  707. package/src/lib/minus.ts +0 -50
  708. package/src/lib/path-pattern.ts +0 -55
  709. package/src/lib/person-name.ts +0 -155
  710. package/src/lib/phone.ts +0 -208
  711. package/src/lib/plain-text.ts +0 -22
  712. package/src/lib/presence.ts +0 -18
  713. package/src/lib/qr-encode.ts +0 -444
  714. package/src/lib/quiet-focus.ts +0 -32
  715. package/src/lib/reduced-motion.ts +0 -22
  716. package/src/lib/refs.ts +0 -22
  717. package/src/lib/round.ts +0 -43
  718. package/src/lib/safe-storage.ts +0 -119
  719. package/src/lib/server-wake.ts +0 -315
  720. package/src/lib/session-refresh.ts +0 -472
  721. package/src/lib/share-format.ts +0 -18
  722. package/src/lib/status-tone.ts +0 -43
  723. package/src/lib/strip-fade.ts +0 -287
  724. package/src/lib/table-text.ts +0 -554
  725. package/src/lib/text-case.ts +0 -19
  726. package/src/lib/text-match.ts +0 -169
  727. package/src/lib/thenable.ts +0 -19
  728. package/src/lib/translation-review.ts +0 -769
  729. package/src/notifications/device-zone-report.ts +0 -67
  730. package/src/notifications/feedback-notification-types-labels.ts +0 -33
  731. package/src/notifications/feedback-notification-types.ts +0 -71
  732. package/src/notifications/notification-bell.tsx +0 -119
  733. package/src/notifications/notification-inbox.tsx +0 -309
  734. package/src/notifications/notification-parts.tsx +0 -81
  735. package/src/notifications/notification-types-setting.tsx +0 -406
  736. package/src/notifications/notification-types.ts +0 -89
  737. package/src/notifications/notifications-labels.ts +0 -287
  738. package/src/notifications/push-device-setting.tsx +0 -230
  739. package/src/notifications/push-devices-setting.tsx +0 -374
  740. package/src/notifications/push-worker.ts +0 -168
  741. package/src/notifications/quiet-hours-setting.tsx +0 -238
  742. package/src/notifications/unsubscribe-panel.tsx +0 -200
  743. package/src/notifications/use-push-device.ts +0 -448
  744. package/src/offline/local-first.ts +0 -100
  745. package/src/offline/pwa-update-prompt-labels.ts +0 -9
  746. package/src/offline/pwa-update-prompt.tsx +0 -78
  747. package/src/offline/query-persistence.ts +0 -391
  748. package/src/offline/service-worker-updates.ts +0 -81
  749. package/src/offline/shared-computer-labels.ts +0 -8
  750. package/src/offline/shared-computer.tsx +0 -87
  751. package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
  752. package/src/offline/sign-out-pending-dialog.tsx +0 -135
  753. package/src/offline.ts +0 -37
  754. package/src/push-worker.ts +0 -25
  755. package/src/rhf/fields.tsx +0 -2187
  756. package/src/rhf/form-core.tsx +0 -324
  757. package/src/rhf/form.tsx +0 -12
  758. package/src/rhf/line-items.tsx +0 -135
  759. package/src/rhf/use-rhf-wizard-step.ts +0 -104
  760. package/src/rhf.ts +0 -21
  761. package/src/search/command-palette-labels.ts +0 -16
  762. package/src/search/command-palette.tsx +0 -624
  763. package/src/search/global-search-labels.ts +0 -13
  764. package/src/search/global-search.tsx +0 -660
  765. package/src/search/search-index.ts +0 -283
  766. package/src/search/use-command-key.ts +0 -23
  767. package/src/search.ts +0 -14
  768. package/src/settings/device-reset-setting-labels.ts +0 -20
  769. package/src/settings/device-reset-setting.tsx +0 -116
  770. package/src/settings/settings-card-classes.ts +0 -11
  771. package/src/settings/settings-catalogue.ts +0 -150
  772. package/src/settings/settings-context.ts +0 -33
  773. package/src/settings/settings-heading.tsx +0 -67
  774. package/src/settings/settings-labels.ts +0 -87
  775. package/src/settings/settings-layout.tsx +0 -471
  776. package/src/settings/settings-section.tsx +0 -108
  777. package/src/settings/use-account-appearance.ts +0 -148
  778. package/src/settings/use-account-language.ts +0 -146
  779. package/src/settings/use-settings-focus.ts +0 -128
  780. package/src/settings/use-settings-route.ts +0 -258
  781. package/src/shell/account-menu-language.tsx +0 -130
  782. package/src/shell/account-menu-text-size.tsx +0 -80
  783. package/src/shell/admin-menu.tsx +0 -183
  784. package/src/shell/app-shell-labels.ts +0 -11
  785. package/src/shell/app-shell.tsx +0 -1560
  786. package/src/shell/auth-layout.tsx +0 -186
  787. package/src/shell/company-switcher-labels.ts +0 -13
  788. package/src/shell/company-switcher.tsx +0 -136
  789. package/src/shell/dev-menu.tsx +0 -257
  790. package/src/shell/fill-height.tsx +0 -45
  791. package/src/shell/language-code.ts +0 -5
  792. package/src/shell/option-switcher-menu.tsx +0 -84
  793. package/src/shell/sync-status-indicator.tsx +0 -303
  794. package/src/shell/top-bar-actions.tsx +0 -87
  795. package/src/shell/top-bar-brand.tsx +0 -78
  796. package/src/shell/top-bar-parts-labels.ts +0 -148
  797. package/src/shell/top-bar.tsx +0 -40
  798. package/src/shell/topbar-action-menu.tsx +0 -567
  799. package/src/shell/topbar-controls.tsx +0 -269
  800. package/src/shell/tour-menu.tsx +0 -187
  801. package/src/shell.ts +0 -108
  802. package/src/sync/db.ts +0 -129
  803. package/src/sync/engine.ts +0 -1011
  804. package/src/sync/hooks.ts +0 -98
  805. package/src/sync/testing.ts +0 -73
  806. package/src/sync/wire.ts +0 -61
  807. package/src/sync.ts +0 -37
  808. package/src/table-text.ts +0 -8
  809. package/src/testing/css-variables.generated.ts +0 -112
  810. package/src/testing/css-variables.ts +0 -189
  811. package/src/testing/index.ts +0 -29
  812. package/src/testing/react.ts +0 -58
  813. package/src/testing/tour.ts +0 -41
  814. package/src/testing/viewport.ts +0 -357
  815. package/src/theme/chart-palette.ts +0 -232
  816. package/src/theme/color.ts +0 -272
  817. package/src/theme/contrast-tokens.ts +0 -268
  818. package/src/theme/contrast.ts +0 -250
  819. package/src/theme/palette-derive.ts +0 -825
  820. package/src/theme/palette-presets.ts +0 -544
  821. package/src/theme/palette-store.ts +0 -108
  822. package/src/theme/text-size.ts +0 -289
  823. package/src/theme/theme-store.ts +0 -157
  824. package/src/tour/tour-catalogue-labels.ts +0 -75
  825. package/src/tour/tour-catalogue.tsx +0 -335
  826. package/src/tour/tour-dock.ts +0 -134
  827. package/src/tour/tour-engine.ts +0 -37
  828. package/src/tour/tour-gates.ts +0 -218
  829. package/src/tour/tour-guide-button.tsx +0 -64
  830. package/src/tour/tour-guide-labels.ts +0 -15
  831. package/src/tour/tour-info.ts +0 -144
  832. package/src/tour/tour-labels.ts +0 -23
  833. package/src/tour/tour-overlay.tsx +0 -1170
  834. package/src/tour/tour.tsx +0 -750
  835. package/src/tour/use-tour-progress.ts +0 -671
  836. package/src/tour/use-tour-url-sync.ts +0 -266
  837. package/src/tour.ts +0 -21
  838. package/src/vite-env.d.ts +0 -23
  839. package/src/wizard/stepper-nav.tsx +0 -360
  840. package/src/wizard/types.ts +0 -275
  841. package/src/wizard/use-wizard.ts +0 -560
  842. package/src/wizard/validation.ts +0 -39
  843. package/src/wizard/wizard-context.tsx +0 -74
  844. package/src/wizard/wizard-labels.ts +0 -29
  845. package/src/wizard/wizard-step.tsx +0 -76
  846. package/src/wizard/wizard-summary.tsx +0 -84
  847. package/src/wizard.ts +0 -15
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/series-chart.tsx"],"sourcesContent":["// The measurement plot: series against a swept numeric abscissa, any number of y axes,\n// dash patterns, vertical spans, and drag-to-zoom. Lifted out of lenkbank, where every\n// chart on every screen is this one arrangement of the kit's shell — so the arrangement\n// lives here once instead of as thirteen hand-assembled copies drifting apart.\n//\n// Built on `ChartContainer` + `ChartTooltipContent`, so it themes with the rest of the\n// chart kit: series default to the `--chart-N` ramp, axis text and grid take the\n// shell's tokens. It stays domain-free — every unit, title and number format is the\n// caller's, and the few words it can say itself are the `seriesChart` label namespace.\n//\n// **Every series may keep its own scale.** Position runs in millimetres and jerk in\n// hundreds of thousands of them per second cubed; on one axis the position line is\n// flat against the bottom. Normalising each series to its peak makes the y axis mean\n// nothing, so a caller declares an axis per incomparable channel instead, and may hide\n// all but the ones worth a column of numbers.\n//\n// Charts are drawn left-to-right in every writing direction — an abscissa is a number\n// line, not text — so `orientation` below is physical, and only the HTML chrome (the\n// reset button) is placed by logical side.\n//\n// **Bars, areas and periods too (0.8.0).** keksdose drew five money charts in raw\n// recharts — net worth, investments, income/expense, grouped payees, stacked categories\n// — each re-deciding the grid, the tooltip, the axis width and the \"—\" for a gap. They\n// are the same arrangement with a different mark, so a series now says `type: \"bar\" |\n// \"area\"` (and `stack`), and the abscissa may be a row of PERIODS (`x.type:\n// \"category\"`) or real dates (`x.type: \"time\"`) instead of a number the app had to\n// invent. What each of those does to the zoom is decided in one place,\n// `defaultZoomAxes` in `chart-zoom-core.tsx`.\n//\n// **An axis budget (0.15.1).** Every visible axis reserves its band, and four of them\n// leave a phone nothing to plot. A chart draws at most `maxVisibleAxes`, and — on its\n// own, when it is too narrow for the ones it has — one a side; the rest go hidden,\n// still scaling their lines, and their series say the unit the title no longer does.\n// The rule is `series-chart-budget.ts`.\n//\n// **A row budget (0.34, KS U2).** Opt-in: `maxRows` thins a long table to at most that\n// many rows before recharts sees it, by ENVELOPE — each bucket's lowest and highest row\n// of every drawn series — never by stride, which aliases a fast tone into a slow wave.\n// A zoom thins the window on show, so it draws more detail, not the same rows larger.\n// The rule is `series-chart-thin.ts`.\nimport { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode, RefObject } from \"react\";\nimport {\n Area,\n Bar,\n CartesianGrid,\n ComposedChart,\n Label,\n Line,\n ReferenceDot,\n ReferenceLine,\n Rectangle,\n XAxis,\n YAxis,\n usePlotArea,\n useXAxisScale,\n type BarShapeProps,\n} from \"recharts\";\nimport { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from \"./chart\";\nimport { useFigureDescription } from \"./chart-figure\";\nimport { rovingTarget } from \"../lib/direction\";\nimport {\n DEFAULT_Y_AXIS,\n axisExtent,\n withChartZoom,\n type ZoomAxesSetting,\n type ZoomBinding,\n type ZoomFitSource,\n} from \"./chart-zoom-core\";\nimport { STEP_DASH, strokeDash, type LegendEntry } from \"./toggle-legend\";\nimport { DEFAULT_SERIES_CHART_LABELS, type SeriesChartLabels } from \"./series-chart-labels\";\nimport {\n categoryTicks,\n integerTicks,\n niceTicks,\n tickTarget,\n timeTicksWithUnit,\n type TimeTickUnit,\n} from \"./series-chart-ticks\";\n// The tick module stays internal; the one type of it a public prop names is re-exported.\nexport type { TimeTickUnit } from \"./series-chart-ticks\";\nimport { autoAxisBudget, axisUnit, budgetedAxes, type SeriesChartAxisBudget } from \"./series-chart-budget\";\nimport { thinnedRows } from \"./series-chart-thin\";\n// The rule stays internal, like the ticks; the one type a public prop names is re-exported.\nexport type { SeriesChartAxisBudget } from \"./series-chart-budget\";\nimport {\n AXIS_TITLE_OFFSET,\n MIN_TICK_GAP,\n TIME_TICK_FORMAT,\n anchoredBand,\n axisBandWidth,\n extend,\n finite,\n padBand,\n resolveTicks,\n soleSeriesColor,\n tiltedTickBand,\n xModel,\n type XModel,\n} from \"./series-chart-axes\";\n// The pure axis and series helpers live in series-chart-axes.ts (MOD-9); their public\n// names are still this module's, so `/chart` and the barrel export them as before.\nexport {\n AXIS_TICK_WIDTH,\n AXIS_TITLE_STRIP,\n anchoredBand,\n axisBandWidth,\n mergeSeries,\n oneAxis,\n padBand,\n paddedDomain,\n seriesKey,\n soleSeriesColor,\n visibleSeries,\n} from \"./series-chart-axes\";\nexport type { SeriesSource } from \"./series-chart-axes\";\nimport { paletteFor } from \"../theme/chart-palette\";\nimport {\n useKitChartTooltipPlacement,\n useKitLabels,\n useKitLocale,\n type ChartTooltipPlacement,\n type LabelOverride,\n} from \"../i18n/kit-labels\";\nimport { useBreakpoint } from \"../hooks/use-breakpoint\";\nimport { useTextSize } from \"../theme/text-size\";\nimport { chartHeightProps, type ChartHeight } from \"./chart-height\";\nimport { useChartEdge, useEdgesInForce } from \"./chart-edge\";\nimport { cn } from \"../lib/cn\";\nimport { formatWithMinus } from \"../lib/minus\";\n\n/**\n * One line, area or bar run of a {@link SeriesChart}.\n *\n * `TRow` is the chart's row type (0.53, keksdose after 0.52), and only `dot` reads it: its\n * `point.row` is that type. Without a type argument a series is what it was, and a chart\n * of typed rows still takes it — see {@link SeriesChartProps}.\n */\nexport interface SeriesChartSeries<TRow extends object = object> {\n /** The row key this line reads — and the `--color-<key>` it is painted with, so it\n * must be a CSS identifier. Build keys out of data with {@link seriesKey}. */\n key: string;\n label: ReactNode;\n /** Any CSS colour the chart shell accepts (hex, rgb/hsl, `var(--token)`). Default:\n * the kit's categorical ramp by position, `paletteFor(index)`. */\n color?: string;\n /** Marks the PAIRED line of a pair — the return stroke against the out-stroke, the\n * reference against the measurement. Shorthand for `dash: 1`. */\n dashed?: boolean;\n /** Which of {@link STROKE_PATTERNS} this line takes, for charts where the stroke says\n * WHICH QUANTITY and the colour says WHICH MEASUREMENT.\n *\n * Or an SVG `stroke-dasharray` string of the caller's own, for a pattern the five do\n * not have: keksdose's `\"4 3\"`, a tighter dash than the ladder's `\"5 4\"` that its\n * hand-drawn recharts lines used before the kit. The legend\n * entry ({@link seriesLegendEntries}) carries the same string, so it draws the same\n * pattern. */\n dash?: number | string;\n /** `stepAfter`, for a whole-number channel that jumps rather than travels — a\n * straight line between index 0 and index 1 draws an index of 0.5, which does not\n * exist. Drawn in the {@link STEP_DASH} pattern, whatever `dash` says. */\n step?: boolean;\n /** Which of `axes` this line is measured on. Default: `\"y\"`, the single one. */\n axis?: string;\n /**\n * The mark. `\"line\"` (the default) is what every chart before 0.8.0 drew. `\"bar\"` and\n * `\"area\"` are read as a LENGTH from zero, so the axis they stand on always includes\n * zero (see `SeriesChartAxis.includeZero`) and the zoom treats them differently (see\n * `defaultZoomAxes`). Bars without a `stack` stand side by side in each slot — the\n * grouped bars of keksdose's payee report.\n */\n type?: SeriesChartType;\n /**\n * Bars or areas with the same `stack` are drawn on top of each other and the axis is\n * fitted to their SUM (positive and negative layers apart, like recharts'\n * `stackOffset=\"sign\"`). keksdose's spending-by-category area. Ignored on a line:\n * recharts cannot stack one.\n */\n stack?: string;\n /**\n * Marks on the line's (or area's) points. `true` rings every sample — the price\n * history, where a shop has a value only on the days somebody shopped there and the\n * dots are the only thing saying which points were MEASURED. A function decides per\n * point: `true` for the default dot, `false`/`null` for none, or any SVG node drawn\n * as-is at `point.cx`/`point.cy` — a buy/sell marker on keksdose's paper price.\n * Never called for a point with no value. Bars have no points, and ignore it.\n * `point.row` is the caller's own row, typed as the chart's rows are (0.53).\n */\n dot?: boolean | ((point: SeriesChartPoint<TRow>) => ReactNode);\n /** Line (or area outline) weight in px. Default 2, or 1.5 for a `step`. keksdose\n * draws the subject of a chart at 2.5 and the reference it is read against at 1.5. */\n strokeWidth?: number;\n /** `\"linear\"` for a line that must not look smoothed — keksdose's cash-buffer\n * PROJECTION, a straight extrapolation that a monotone curve would dress up as data.\n * Default `\"monotone\"`; `step` wins over both. */\n curve?: \"monotone\" | \"linear\";\n /** An area's or bar's fill opacity. Default: 1 for a bar, 0.55 for a stacked area\n * (the layers must stay tellable apart where they meet) and 0.2 for a single one. */\n fillOpacity?: number;\n /**\n * The dot that follows the pointer along a line or an area. `false` takes it off a\n * series that is not a measurement — keksdose's cash-buffer PROJECTION, where a hover\n * ring on the extrapolated line reads as a sampled value (`cash-buffer-chart.tsx`).\n * `{ r }` sets its radius. Default: recharts' dot. Bars have none, and ignore it.\n */\n activeDot?: boolean | { r?: number };\n /**\n * The shortest a bar of this series is drawn, in px — recharts' `minPointSize`. A\n * zero or a value too small to see keeps a visible stub, so an empty slot still reads\n * as a slot with a value rather than a gap: keksdose's weekday pattern, where a\n * Sunday with no spending drew a 2% stub by hand. Only the DRAWING changes: the axis\n * is fitted to the values, and the tooltip, the keyboard stops and every accessible\n * name still say 0. A hole (no value in the row) stays a hole. Overrides the chart's\n * {@link SeriesChartProps.minBarLength}; `0` turns it off for this series. Meant for\n * unstacked bars — in a `stack` the stub is drawn over the layer above it. Lines and\n * areas ignore it.\n */\n minBarLength?: number;\n}\n\n/** What a series draws. See {@link SeriesChartSeries.type}. */\nexport type SeriesChartType = \"line\" | \"bar\" | \"area\";\n\n/** One point of a series, as a `dot` function is handed it. `TRow` is the chart's row\n * type (0.53); without one, `row` is a {@link SeriesChartRow}, as before. */\nexport interface SeriesChartPoint<TRow extends object = object> {\n /** The series' key. */\n key: string;\n /** The row's position in `rows`. */\n index: number;\n /** The caller's own row, with everything the chart did not plot still in it: the very\n * object in `rows`, typed as `rows` is. */\n row: SeriesChartRowOf<TRow>;\n /** The abscissa in the caller's terms: the number, the category, or (time) a Date. */\n x: SeriesChartXValue;\n value: number;\n /** Where the point is drawn, in the chart's pixels. */\n cx: number;\n cy: number;\n /** The series' paint, `var(--color-<key>)`. */\n color: string;\n}\n\n/** A row of a series chart: one abscissa value and the series' values at it. Anything\n * else in it (a raw ISO period for a drilldown) rides along untouched and is handed\n * back in {@link SeriesChartPoint.row} and {@link SeriesChartHit.row} — typed as the\n * caller's rows are since 0.53, and as this where their type names no keys. */\nexport type SeriesChartRow = Readonly<Record<string, unknown>>;\n\n/**\n * The row a hit or a point hands back, for a chart whose rows are `TRow[]` (0.53, keksdose\n * after 0.52): `TRow` itself, so a drilldown reads `hit.row.rawPeriod` as the string it\n * is. A {@link SeriesChartRow} where `TRow` names no keys — `object`, the default, which\n * keeps `SeriesChartHit` and `SeriesChartPoint` without a type argument what they were, and\n * the `object[]` rows an app passes today; `{}`; and `any` or `never` (`rows={[]}`), which\n * are both assignable to `null` while no object type is.\n *\n * Both tests take `TRow` in the CHECKED position, never in the `extends` one, so TypeScript\n * measures every type below as covariant in it (`SeriesChartSeries`, through `dot`'s\n * parameter, contravariant) and relates two of them by their type arguments alone: a\n * `SeriesChartHit<Month>` is a `SeriesChartHit`, and a handler or a series typed without an\n * argument fits a chart of `Month` rows, though an interface has no index signature and is\n * not, field by field, a `SeriesChartRow`. Written `object extends TRow ?`, the type is\n * invariant and both of those stop type-checking.\n */\ntype SeriesChartRowOf<TRow> = [TRow] extends [null]\n ? SeriesChartRow\n : [keyof TRow] extends [never]\n ? SeriesChartRow\n : TRow;\n\n/** An abscissa value: a number (`x.type: \"number\"`), a category (a string, a number or\n * a Date standing for a period), or a time (a Date, epoch ms or an ISO string). */\nexport type SeriesChartXValue = number | string | Date;\n\n/** Ticks a caller decides — a list, or a function of the domain on show, so a zoom\n * window gets ticks from the same rule instead of none. */\nexport type SeriesChartTickValues<T> = readonly T[] | ((domain: [number, number]) => readonly T[] | undefined);\n\ninterface SeriesChartAxisShape {\n id: string;\n /**\n * Which side of the plot the ticks stand on. Left unless said otherwise — and said\n * otherwise for the right-hand chart of a FACING pair (see `facingAxes`), whose\n * scales go on the outside so neither column of numbers stands between two pictures\n * being compared.\n */\n orientation?: \"left\" | \"right\";\n /** Tints the ticks — and the title too, when exactly one series is measured on this\n * axis (see {@link soleSeriesColor}). */\n color?: string;\n /** What the TICKS need, in px. The title's strip is added on top. Default 48. */\n width?: number;\n /**\n * The unit, bare — `\"mm/s\"`. The title says it while the axis is drawn; when it is not\n * (`hide`, or over the chart's axis budget — see {@link SeriesChartProps.maxVisibleAxes})\n * the series on it say it instead, as \"Velocity (mm/s)\": in the tooltip of a chart\n * whose budget hid the axis, and in the legend {@link seriesLegendEntries} builds when\n * handed the axes. Default: the parenthesised tail of `title` (\"Load (N)\" → \"N\").\n * `\"\"` for a quantity with no unit whose title merely ends in brackets.\n */\n unit?: string;\n /**\n * Pin the scale instead of fitting it to this chart's data. For a ROW of charts\n * read against each other: auto-fitted, a 200 N loop and a 2000 N one draw the\n * identical picture, and the comparison the layout promises is the one it fails.\n */\n domain?: [number, number];\n /** A tick, formatted — as a BARE number. The unit is said once, in the title; the\n * tooltip gets it from `valueFormat`. Default: `Intl.NumberFormat` in the kit's\n * locale, up to two fraction digits. */\n format?: (value: number) => string;\n /**\n * The tick values, instead of the round ones the chart picks. For a grid the DATA\n * dictates — keksdose's price axes tick on whole cents (`pricePaddedDomain`), where a\n * 1/2/5 ladder would print €1.25 under a formatter that can only say €1.3. Values\n * outside the domain on show are dropped; a function is asked again for every zoom\n * window, so the cent grid can refine with it.\n */\n tickValues?: SeriesChartTickValues<number>;\n /**\n * Keep zero inside the fitted band. On by default for an axis carrying a bar or an\n * area — their length IS the value, and a truncated baseline draws 40 as three times\n * 20 — and off for lines, whose shape is the point (a stock price anchored at zero is\n * a hairline). A pinned `domain` is left alone either way.\n */\n includeZero?: boolean;\n /**\n * Tick only on whole numbers — the y counterpart of `SeriesChartX.integerTicks`, and\n * what keksdose's user-count axis (`metrics-panel.tsx`, `wholeTicks`) and its runway\n * in days (`cash-buffer-chart.tsx`, `wholeDayTicks`) each wrote by hand: a band of\n * [0, 3.1] users is ticked 0 1 2 3, not 0 0.5 1 … 3, and a short runway is not ticked\n * 0 / 0.5 / 1 under a rounding formatter that prints \"1\" twice. A (zoom) window that\n * holds no whole number falls back to the ordinary ticks rather than to none.\n *\n * AUTOMATIC by default — on when every value this axis carries is a whole number\n * (counts), because that is where a half tick is a value no sample can have, and it\n * changes nothing on a span wider than about eight, which already ticks on whole\n * steps. `true` forces it over fractional data (days of runway computed as 43.7);\n * `false` keeps fractional ticks for a continuous quantity that merely happens to be\n * whole in this sample. `tickValues` wins over either.\n */\n integerTicks?: boolean;\n}\n\n/**\n * A y axis — and a VISIBLE one says what it measures.\n *\n * A union rather than an optional field, so the rule is the type's: a column of numbers\n * whose quantity and unit are not written down is a column somebody reads as whatever\n * they expected. `title: \"\"` is the explicit opt-out (the right-hand chart of a facing\n * pair, whose neighbour already said it). A HIDDEN axis scales its lines and draws\n * nothing, so there is nowhere for a title to go.\n */\nexport type SeriesChartAxis = SeriesChartAxisShape & ({ title: string; hide?: false } | { title?: string; hide: true });\n\n/**\n * What a tick or the tooltip heading of the abscissa is handed besides its position —\n * the value in the caller's own terms, which on a category or time axis is not the\n * number the plot runs on.\n */\nexport interface SeriesChartXTick {\n /** The number itself, the row's category, or (time) a Date. */\n value: SeriesChartXValue;\n /** The slot, on a category axis: the row's index in `rows`. */\n index?: number;\n /** On a time axis: what one step of the ticks on show is, so a label can say as much\n * as it means — a month start as \"Mar 26\", a midnight as \"14 Mar\". */\n unit?: TimeTickUnit;\n}\n\nexport interface SeriesChartX {\n /**\n * What the abscissa is.\n *\n * - `\"number\"` (the default) — a number line, and all a chart before 0.8.0 could draw.\n * - `\"category\"` — PERIODS or names, one evenly spaced slot per row, in row order:\n * keksdose's months, quarters and budget categories, which it used to hand recharts\n * preformatted. The values stay the caller's own — `\"2026-05\"`, a Date for the\n * month, a category name — and need not be sortable, unique or numeric. The plot\n * runs on the slot INDEX, which is what lets it zoom: a drag across the third to the\n * ninth month shows those months, a tick on each whole slot and the bars clipped at\n * the edge. What else zooms depends on the MARKS, not the axis — see `zoomAxes`.\n * - `\"time\"` — real TIME: a Date, epoch ms or an ISO string per row, placed by when\n * it happened. keksdose's price history and cash buffer, where a slot per row would\n * draw two receipts a day apart and two five months apart the same width. Ticks fall\n * on calendar boundaries (midnights, Mondays, month and quarter starts, new years)\n * in local time; a date-only ISO string is LOCAL midnight, not the UTC one\n * `new Date(\"2026-05-01\")` gives, which lands on the previous day west of Greenwich.\n * Zooms like a number line.\n */\n type?: \"number\" | \"category\" | \"time\";\n /** Row key of the abscissa. Default `\"x\"`, which is what {@link mergeSeries} writes. */\n key?: string;\n /** What the abscissa is, with its unit. Drawn under the axis. */\n title?: string;\n /**\n * A tick, formatted — bare, like the y axes'.\n *\n * `value` is the POSITION on the number line the plot runs on — the number itself,\n * epoch ms, or the slot index — so the one-argument formatters every chart before\n * 0.8.0 passes keep their meaning, and a time axis' `(ms) => …` is the tickFormatter\n * keksdose already has. The caller's own value (the category, the Date) is `tick.value`.\n * Default: the kit's number format; a category as is (a number formatted, a Date as a\n * medium date); a time as much of the date as the tick step means.\n */\n format?: (value: number, tick: SeriesChartXTick) => string;\n /**\n * Whether this chart prints the abscissa's ticks. On by default; off for every chart\n * of a stack sharing one x window but the bottom one, which prints them for all. It\n * costs no alignment: the x mapping is decided by the margins and the y bands.\n */\n ticks?: boolean;\n /** The tooltip's heading. Default: `format` — or, on a time axis, a medium date (with\n * the time for hourly data), since a tick's \"Mar 26\" is not which day it was. */\n label?: (value: number, tick: SeriesChartXTick) => ReactNode;\n /** The ticks instead of the automatic ones, in the caller's terms: numbers, the\n * categories to label, or instants. See `SeriesChartAxis.tickValues`. */\n tickValues?: SeriesChartTickValues<SeriesChartXValue>;\n /**\n * Tilt the tick labels by this many degrees — negative rises to the right. For long\n * category names that do not fit side by side: keksdose's budget performance draws its\n * categories at −45° (`budget-performance-tab.tsx`). The label is anchored by its END\n * for a negative angle and its START for a positive one, so it hangs off the tick\n * instead of being centred across it; the anchor is physical, like the plot (see\n * `ChartContainer`), so it is the same in RTL. The band under the axis grows to the\n * rotated height of the longest label on show, estimated from its length (at most\n * 120 px × the text size's scale, past which a label is clipped). Default 0.\n */\n tickAngle?: number;\n /**\n * On a `\"number\"` axis, tick only on whole numbers: a step of 1 at the least, so a\n * five-point index series reads 0 1 2 3 4 rather than 0 0.5 1 … 4 — ticks at\n * positions no row can have (keksdose's short step series). A zoom window that holds\n * no whole number falls back to the ordinary ticks rather than to none.\n *\n * AUTOMATIC by default — on when every row's x is a whole number — because that is\n * exactly the case the half ticks are wrong in, and it changes nothing elsewhere: a\n * span wider than about eight already ticks on whole steps. `false` for a continuous\n * quantity that merely happens to be sampled on whole numbers (1 Hz steps) and whose\n * zoom should still be ruled in fractions; `true` to force it over rows that are not.\n * Ignored on category (already one tick per slot) and time axes.\n */\n integerTicks?: boolean;\n}\n\n/** Where the tooltip goes — see {@link SeriesChartTooltip.placement}. */\nexport type SeriesChartTooltipPlacement = ChartTooltipPlacement;\n\n/**\n * The placement a chart actually uses: its own, else the provider's, else `\"cursor\"`;\n * `\"auto\"` is `\"above\"` on a phone (`phone`: below `sm`) and `\"cursor\"` from `sm` up.\n */\nexport function resolveTooltipPlacement(\n own: SeriesChartTooltipPlacement | undefined,\n fromProvider: SeriesChartTooltipPlacement | undefined,\n phone: boolean,\n): \"cursor\" | \"above\" | \"below\" {\n const wanted = own ?? fromProvider ?? \"cursor\";\n return wanted === \"auto\" ? (phone ? \"above\" : \"cursor\") : wanted;\n}\n\n/** Room for the tooltip beyond the chart — see {@link SeriesChartProps.tooltip}. */\nexport interface SeriesChartTooltip {\n /**\n * Where the values under the pointer are shown (keksdose #359: on a phone the box\n * sat under the finger, on the very data it was reporting).\n * - `\"cursor\"` (the default): the floating box that follows the pointer.\n * - `\"above\"` / `\"below\"`: a READOUT row — the same heading and values, flat — in\n * room reserved over or under the plot from the first render, so nothing jumps on\n * the first tap. It follows hover, a tap and the keyboard's stops; the cursor line\n * and the active dot stay on the plot, and no box floats. Idle, it lists the series\n * with \"—\" under the x axis' title. The row is taken out of the chart's `height`\n * (the plot gets shorter, the page around it does not move).\n * - `\"auto\"`: `\"above\"` below Tailwind's `sm` (640 px), `\"cursor\"` from there up.\n *\n * Default: the provider's `chartTooltipPlacement`, else `\"cursor\"`.\n *\n * The row is deliberately NOT an `aria-live` region: scrubbing a line announces a\n * value per pixel of travel. A keyboard reader already hears each stop's name\n * (\"period — series: value\") from the stop itself, and the row stays in the\n * document for a screen reader to read on its way past.\n */\n placement?: SeriesChartTooltipPlacement;\n /** Let the tooltip run past the chart's own box on that axis instead of recharts\n * clamping it inside. Default: `{ x: true }` when `boundary` is set, else neither. */\n allowEscapeViewBox?: { x?: boolean; y?: boolean };\n /**\n * The element that actually CLIPS the chart — usually a horizontal-scroll wrapper\n * around a chart wider than the card. The tooltip then flips to the left of the cursor\n * when it would spill past that element's visible right edge (see\n * `ChartTooltipContent`'s `boundaryRef`), rather than against the wide chart's far edge\n * the reader has not scrolled to. keksdose's budget performance, which keeps a scroll\n * wrapper and a per-category `minWidth` (`budget-performance-tab.tsx`).\n */\n boundary?: RefObject<HTMLElement | null>;\n}\n\n/**\n * A vertical segment in data coordinates — two y at one x, which a row-per-abscissa\n * chart structurally cannot draw. For CLOSING a shape the series already drew: the\n * turnarounds of a hysteresis loop, where the abscissa stands still while the value\n * falls from one branch to the other.\n */\nexport interface SeriesChartSpan {\n /** Distinct within the chart. */\n key: string;\n /** Which y axis `from`/`to` are measured on. Default `\"y\"`. */\n axis?: string;\n x: number;\n from: number;\n to: number;\n /** Default: `var(--text-muted)`. */\n color?: string;\n}\n\n/** The colours a reference or a marker can take by name — the kit's semantic tokens,\n * so a threshold reads the same on every chart and flips with the theme. */\nexport type SeriesChartTone =\n \"muted\" | \"brand\" | \"income\" | \"expense\" | \"net\" | \"success\" | \"warning\" | \"danger\" | \"info\";\n\nconst TONE_COLOR: Record<SeriesChartTone, string> = {\n muted: \"var(--text-muted)\",\n brand: \"var(--brand)\",\n income: \"var(--money-income)\",\n expense: \"var(--money-expense)\",\n net: \"var(--money-net)\",\n success: \"var(--success)\",\n warning: \"var(--warning)\",\n danger: \"var(--danger)\",\n info: \"var(--info)\",\n};\n\n/**\n * A line across the whole plot at one value: a threshold, a target, an event.\n *\n * keksdose's cash buffer draws \"one month of runway\" across at y = 30 and the projected\n * depletion date down at its x. Unlike a {@link SeriesChartSpan}, which closes a shape\n * in data coordinates, a reference spans the plot, whatever the zoom.\n *\n * A reference is part of the FITTED band: one outside the data widens the axis to show\n * it, because a threshold the reader cannot see is not a threshold. A pinned domain or a\n * zoom window does not widen — there it is discarded when outside, like a span.\n */\nexport interface SeriesChartReference {\n /** Distinct within the chart. Default: its position in the list. */\n key?: string;\n /** `\"x\"` for a vertical line at an abscissa, otherwise the id of the y axis the value\n * is measured on. Default `\"y\"`, the single one — so no y axis may be called `\"x\"`. */\n axis?: string;\n /** An abscissa in the x axis' own terms (a category, a Date) for `axis: \"x\"`, a\n * number on that axis otherwise. A category the rows do not have draws nothing. */\n value: SeriesChartXValue;\n /** Written along the line, inside the plot at its top-left. SVG text: a string. */\n label?: string;\n /** Default `\"muted\"`. `color` wins over it. */\n tone?: SeriesChartTone;\n color?: string;\n /** Which of `STROKE_PATTERNS`. Default 1, dashed: a reference is not data, and a\n * solid line reads as a series nobody put in the legend. */\n dash?: number;\n}\n\n/**\n * A single labelled point — today's figure on keksdose's cash buffer, the month the\n * projection runs dry. For a mark on EVERY sample, or on the samples that meet a test,\n * use the series' `dot` instead; a marker is for a point that is a fact of its own.\n * Fitted like a reference: it widens the band it would otherwise fall outside of.\n */\nexport interface SeriesChartMarker {\n /** Distinct within the chart. Default: its position in the list. */\n key?: string;\n /** In the x axis' own terms, like a reference's `value`. */\n x: SeriesChartXValue;\n y: number;\n /** The y axis `y` is measured on. Default `\"y\"`. */\n axis?: string;\n /** Written above the point. */\n label?: string;\n /** Default `\"brand\"`. `color` wins over it. */\n tone?: SeriesChartTone;\n color?: string;\n /** Radius in px. Default 4.5. */\n r?: number;\n}\n\n/** What a click on the plot picked. `TRow` is the chart's row type (0.53); without one,\n * `row` is a {@link SeriesChartRow}, as before. */\nexport interface SeriesChartHit<TRow extends object = object> {\n /** The row's position in `rows`. */\n index: number;\n /** The caller's own row — with its `rawPeriod`, id or whatever the drilldown needs: the\n * very object in `rows`, typed as `rows` is, so it is read without a cast. */\n row: SeriesChartRowOf<TRow>;\n x: SeriesChartXValue;\n /** The series, when the click landed ON a bar. A click anywhere else picks the slot\n * (the period), not a series. */\n key?: string;\n}\n\n/**\n * The props of {@link SeriesChart} and {@link StaticSeriesChart}, for rows of type `TRow`.\n *\n * `TRow` is inferred from `rows` (0.53, keksdose after 0.52), and what the chart hands back\n * — `hit.row` in `onPointClick`, `point.row` in a series' `dot` — is that type, so a\n * drilldown reads its own fields without narrowing an `unknown`. Without a type argument,\n * `SeriesChartProps` is what it was: any object is a row, and a row comes back as a\n * {@link SeriesChartRow}. So is `ComponentProps<typeof SeriesChart>`, which reads the\n * constraint, `object`. A series, a handler or a `dot` typed without an argument fits a\n * chart of typed rows too.\n */\nexport interface SeriesChartProps<TRow extends object = object> {\n /**\n * One row per abscissa value. A missing key is a hole (see `connectNulls`).\n *\n * Any object (0.52, refactor audit 2026-10-30, API-2): an `interface` has no index\n * signature, so a typed sweep did not fit `SeriesChartRow` and Kurvenschmiede cast its\n * Ackermann rows `as unknown as Record<string, number>[]`. The chart reads the keys\n * `series` and `x` name, and hands the row back typed as these are (0.53).\n */\n rows: readonly TRow[];\n series: readonly SeriesChartSeries<TRow>[];\n /** Default: one untitled axis, `\"y\"`. */\n axes?: readonly SeriesChartAxis[];\n x?: SeriesChartX;\n /** A value in the tooltip, where a number stands on its own and needs its unit.\n * Default: `Intl.NumberFormat` in the kit's locale. */\n valueFormat?: (value: number) => string;\n /**\n * The chart's height: a CSS length, a Tailwind height class, or px. Default `h-72`\n * (18rem). The empty state takes it too, so a chart losing its last line does not\n * relayout the page under it.\n *\n * - **A CSS length** (0.32) — `\"20rem\"`, `\"min(20rem, 60dvh)\"` — set inline. The form\n * for a height that should grow with the text size and still stop at the screen\n * (docs/text-size-harmonization.md §10.10): `min(30rem, 60dvh)` is 480 px at Normal\n * on a desktop and never more than 60 % of a phone at Extra large, where a scaled\n * 480 px would be 720.\n * - **A Tailwind class** — `\"h-72\"`, `\"h-64 md:h-80\"` — as before.\n * - **A number** is px, set inline, and does NOT follow the text size: kept for a\n * height the caller holds as a number (keksdose's report charts take\n * `height = 260` as a prop). Prefer `\"16.25rem\"`, or a `min()` with a viewport cap.\n */\n height?: ChartHeight;\n /** Bridge holes left by sources sampled on different grids. See {@link mergeSeries}. */\n connectNulls?: boolean;\n /** Shown, centred at the chart's height, instead of an empty chart. Default: the\n * `seriesChart.empty` label. `null` shows nothing. */\n empty?: ReactNode;\n /**\n * Milliseconds for a line to draw itself in. Off by default: a chart beside a live\n * editor re-renders on every keystroke, and an animation restarted mid-flight reads\n * as the curve twitching. Turn it on where series come and go by choice.\n */\n animationMs?: number;\n spans?: readonly SeriesChartSpan[];\n /** Lines across the plot at one value. */\n references?: readonly SeriesChartReference[];\n /** Single labelled points. */\n markers?: readonly SeriesChartMarker[];\n /**\n * Which axes a drag may zoom: `\"both\"`, `\"x\"`, `\"y\"` or `\"none\"`. Default: read off\n * the marks — see `defaultZoomAxes` (lines both, areas x, bars none). An axis carrying\n * bars or areas never takes a DRAGGED y window: it refits to the x window, from zero.\n * Ignored by `StaticSeriesChart`, which does not zoom.\n */\n zoomAxes?: ZoomAxesSetting;\n /**\n * A click on the plot: the slot under the pointer, and the series when it landed on a\n * bar. keksdose's drilldowns — a payee's month, a budget line, a spending category.\n * A drag that zoomed is not a click.\n *\n * The keyboard's stops are there either way (0.52, DSP-5): one per bar, or per slot of\n * a chart without bars, named \"period — series: value\", behind ONE tab stop. With this\n * they are buttons that Enter and Space activate; without, images to read.\n */\n onPointClick?: (hit: SeriesChartHit<TRow>) => void;\n /** Where the tooltip may go: for a chart inside a scroll wrapper. See\n * {@link SeriesChartTooltip}. */\n tooltip?: SeriesChartTooltip;\n /**\n * The most y axes the chart DRAWS: a total, or `{ left, right }` per side. Axes over it\n * are drawn as `hide: true` ones are — they still scale their lines and the zoom still\n * refits them, but they draw no ticks or title and reserve no width — in declaration\n * order, so the first axis of each side is the last to go (`series-chart-budget.ts`).\n * The series on a hidden axis say its unit instead (see {@link SeriesChartAxis.unit}).\n * Default: no cap — only the automatic one of `axisBudget`.\n */\n maxVisibleAxes?: SeriesChartAxisBudget;\n /**\n * `\"auto\"` (the default): a chart so narrow that its axes' bands would leave the plot\n * under 160 px (`MIN_PLOT_WIDTH`, × the text size's scale) draws ONE axis a side —\n * lenkbank's four-axis curve plot on a phone, whose plot was 10 px wide. And a chart\n * with an axis on EACH side that one a side still leaves too narrow (0.32: at 150 % a\n * 390 px phone's plot kept about 80 px between its two bands) drops the right-hand,\n * secondary axis too. Measured on the chart's own box (`ResizeObserver`), and applied\n * on top of `maxVisibleAxes`. Either way the series on an axis it hid say the axis'\n * unit in the tooltip and the readout (\"Rack load (N)\"), and in a legend built by\n * {@link seriesLegendEntries} with `onAxisBudget`'s ids.\n *\n * On by default because it cannot touch a layout that works: it needs a plot that\n * would otherwise be under 160 px — a four-axis chart below about 440 px at Normal, a\n * two-left-axis one below about 300, a one-a-side one below about 290 — and the\n * left-hand axis always stays. A chart with one axis (each chart of a facing pair,\n * every single-axis chart) is never budgeted, at any width. `\"off\"` keeps every\n * declared axis whatever the width: for a stack of multi-axis charts that must keep\n * identical bands, or a caller budgeting itself. Without layout (jsdom, SSR) nothing is\n * measured and nothing is hidden.\n */\n axisBudget?: \"auto\" | \"off\";\n /**\n * The ids of the axes the budget hid (not those declared `hide`), every time that set\n * changes — for a legend that says their units: pass it to {@link seriesLegendEntries}\n * as `budgeted`. Called after the render that hid them; empty once the chart is wide\n * again.\n */\n onAxisBudget?: (hidden: readonly string[]) => void;\n /** Supplied by `withChartZoom` and by nothing else. */\n zoom?: ZoomBinding;\n /** Per-chart strings over `<UiKitProvider labels={{ seriesChart }}>`. */\n labels?: LabelOverride<SeriesChartLabels>;\n /** BCP 47 tag for the default number formats. Default: the provider's. */\n locale?: string;\n /**\n * The chart's name. The chart is a `role=\"figure\"` (0.52, refactor audit 2026-10-30,\n * DSP-5), and a figure is found and told apart by its name — \"Net worth\", \"Load over\n * travel\". Its values are read stop by stop (see {@link SeriesChartProps.onPointClick}).\n */\n \"aria-label\"?: string;\n /**\n * What the picture SHOWS, in a sentence — \"Spending rose 12 % in May, led by rent.\" —\n * the figure's accessible description: a line, an area and a ruler are nothing a screen\n * reader can say. Followed, on a zoomable chart, by the drag gesture (`zoomHint`). Not\n * drawn; a caption the eye should read too belongs in the page.\n */\n description?: string;\n /** Onto the chart's root (`ChartContainer`) — e.g. an app's own grid ink. */\n className?: string;\n /** The shortest bar drawn, in px, for every bar series that does not set its own\n * {@link SeriesChartSeries.minBarLength}. Drawing only: domain, tooltip and names\n * keep the real value. Default: none — a zero draws nothing. */\n minBarLength?: number;\n /**\n * The most rows the chart hands recharts (0.34, KS U2). A longer table is THINNED, by\n * envelope: cut into buckets, and from each the row where each drawn series is lowest\n * and the row where it is highest, plus each series' first and last sample — so every\n * line still reaches every peak and dip the table has, and a tone faster than the\n * buckets draws as the band it fills, never as the slow wave a stride would alias it\n * into. Nothing is averaged or invented; every point drawn is one of `rows`. There is\n * no stride option, on purpose.\n *\n * Opt-in. Default: none — every row is drawn, as before. Kurvenschmiede draws 2000 for\n * a 200-second profile at 1 kHz; a few thousand is about what a plot's pixels can show.\n *\n * - **Zoom** thins the window on show (with one row past each edge), so zooming in\n * draws more of the samples there — all of them, once the window holds fewer than\n * `maxRows` — rather than the same rows larger. That needs an abscissa that never\n * decreases; where it doubles back (a loop against position) the whole table is\n * thinned once, and the abscissa is enveloped too, so the path's turning points stay.\n * - **Fitting** is not thinned: the axes, the zoom's refit and the automatic whole\n * ticks read every row, so a pinned or fitted band is the same either way.\n * - **Indices** stay the caller's: a `dot` function's `point.index` and a click's\n * `hit.index` are positions in `rows`, not in the rows drawn.\n * - **A category axis** (`x.type: \"category\"`) is never thinned: a slot is a period, and\n * a period left out is a gap. Meant for lines and areas; stacked layers are each\n * enveloped on their own.\n *\n * The budget is a cap for any `maxRows` of at least 2 + 4 × the drawn series (the\n * fewest rows an envelope can be drawn with); a smaller one is raised to that.\n */\n maxRows?: number;\n}\n\n/** A series' name with its unit after it: \"Velocity (mm/s)\" — unless the name already\n * ends with it. lenkbank's motion series carry \"(mm/s)\" in their label for the desktop\n * tooltip, where every axis is drawn; the budget then read \"… (mm/s) (mm/s)\" (0.15.1).\n * A label that says its unit keeps saying it once, whichever of the two an app chose. */\nfunction withUnit(label: ReactNode, unit: string | undefined): ReactNode {\n if (!unit) return label;\n if (typeof label === \"string\" || typeof label === \"number\") {\n const text = String(label);\n return text.trimEnd().endsWith(`(${unit})`) ? label : `${text} (${unit})`;\n }\n return (\n <>\n {label} ({unit})\n </>\n );\n}\n\n/** Where a legend learns which axes are not drawn — see {@link seriesLegendEntries}. */\nexport interface SeriesLegendAxes {\n /** The chart's axes. A series on one that is `hide`, or `budgeted`, says its unit. */\n axes?: readonly SeriesChartAxis[];\n /** What the chart's `onAxisBudget` last said. */\n budgeted?: readonly string[];\n}\n\n/**\n * The `ToggleLegend` entries for a chart's FULL series list — colours resolved the way\n * the chart resolves them, and a stroke mark for a line drawn in a pattern (dashed,\n * step) so the key promises the stroke the plot draws. A bar or an area is a swatch.\n * Pair with {@link visibleSeries} for the chart itself.\n *\n * Handed the chart's `axes` (and the `budgeted` ids its `onAxisBudget` reports), a\n * series whose axis is not drawn says the unit that axis would have: \"Velocity (mm/s)\"\n * — see {@link SeriesChartAxis.unit}. Without them, the labels are as given.\n */\nexport function seriesLegendEntries<TRow extends object>(\n // Generic only so a typed list fits (0.53): `SeriesChartSeries<Month>` is not a\n // `SeriesChartSeries`, whose `dot` would be handed rows that are not `Month`s.\n series: readonly SeriesChartSeries<TRow>[],\n { axes, budgeted }: SeriesLegendAxes = {},\n): LegendEntry[] {\n const undrawn = new Map<string, string | undefined>();\n for (const axis of axes ?? []) {\n if (axis.hide || budgeted?.includes(axis.id)) undrawn.set(axis.id, axisUnit(axis));\n }\n return series.map((entry, index) => {\n // A custom dash array goes to the legend as it is, so the swatch draws what the plot does.\n const own = entry.dash ?? (entry.dashed ? 1 : 0);\n const dash = entry.step ? STEP_DASH : own;\n const line = (entry.type ?? \"line\") === \"line\";\n return {\n key: entry.key,\n label: withUnit(entry.label, undrawn.get(entry.axis ?? DEFAULT_Y_AXIS)),\n color: entry.color ?? paletteFor(index),\n ...(line && dash !== 0 ? { marker: \"stroke\" as const, dash } : {}),\n };\n });\n}\n\n/** The number format every default falls back to. */\nfunction useDefaultFormat(localeProp: string | undefined): (value: number) => string {\n const locale = useKitLocale(localeProp);\n return useMemo(() => {\n const format = new Intl.NumberFormat(locale, { maximumFractionDigits: 2 });\n // U+2212 on a negative tick and in the tooltip (0.49, KIT-1).\n return (value: number) => formatWithMinus(format, value);\n }, [locale]);\n}\n\n/** The Y-axis list a chart draws when the caller gave none. */\nconst ONE_UNTITLED_AXIS: SeriesChartAxis[] = [{ id: DEFAULT_Y_AXIS, title: \"\" }];\n\n/** The two numbers every mark type needs to agree on for the chart to read as one. */\nconst LINE_WIDTH = 2;\nconst STEP_WIDTH = 1.5;\n\n/** Bars round their FREE end only, and a stacked bar has none but the top layer's —\n * which recharts cannot tell apart per cell, so stacks stay square. */\nconst BAR_RADIUS: [number, number, number, number] = [3, 3, 0, 0];\n\n/**\n * One keyboard stop: a bar, or (a chart with no bars) a whole slot. `from`/`to` bound its\n * slot on the plotted number line — half way to each neighbour, or to the edge of the\n * window on show.\n */\ninterface PointStop {\n index: number;\n /** The bar's series; absent for a slot. */\n key?: string;\n from: number;\n to: number;\n /** The accessible name: where it is and what it says. Asked only of a stop that is\n * drawn — see {@link ALL_STOPS_UP_TO}. */\n name: () => string;\n}\n\n/**\n * Up to this many stops, every one is drawn; past it, only the roving one, its two\n * neighbours and the two ends (0.52, DSP-5) — every stop is still reached, by the arrows,\n * Home and End. Since every chart has stops, a measurement chart has one per row:\n * Kurvenschmiede draws 2000-row profiles (`maxRows`), and 2000 named `<rect>`s, each\n * named through `Intl` on every render, are a DOM and an accessibility tree nobody walks\n * one by one. A year of months, or of weeks, stays whole for browse mode.\n */\nconst ALL_STOPS_UP_TO = 100;\n\n/**\n * The shape of a series whose bar has keyboard focus: recharts' own rectangle, with an\n * outline on the one bar at `index` — drawn at the bar's exact geometry, which an\n * overlay could only guess at. Not `activeBar`: that follows the tooltip's active index,\n * which recharts stops taking from `defaultIndex` once a pointer has hovered the chart.\n */\nfunction focusedBarShape(index: number) {\n return function FocusedBar(props: BarShapeProps) {\n const focused = props.originalDataIndex === index;\n return <Rectangle {...props} {...(focused ? { stroke: \"var(--text-primary)\", strokeWidth: 2 } : {})} />;\n };\n}\n\n/** A marker label's size in px at Normal — the one place both the text and its width\n * estimate read it from. × the text size's scale where it is drawn (§10.10). */\nconst MARKER_LABEL_SIZE = 11;\n\n/** A reference line's label, in px at Normal, × the scale likewise. */\nconst REFERENCE_LABEL_SIZE = 10;\n\n/**\n * A marker's label, centred over its point but clamped inside the plot. recharts'\n * `position: \"top\"` centres on the point no matter where it is, so a marker near the\n * plot's end (the last sample, a projection's end point) had half its label cut off by\n * the card — \"over the c\" on a phone. The width is measured once drawn; the first\n * frame (and a DOM without layout) uses a 0.6em-per-character estimate, which errs wide.\n */\nfunction MarkerLabel({ viewBox, value }: { viewBox?: { x?: number; y?: number; width?: number }; value?: ReactNode }) {\n const plot = usePlotArea();\n const ref = useRef<SVGTextElement>(null);\n const [measured, setMeasured] = useState<number>();\n const fontSize = MARKER_LABEL_SIZE * useTextSize().scale;\n const text = value == null ? \"\" : String(value);\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || typeof el.getComputedTextLength !== \"function\") return;\n const w = el.getComputedTextLength();\n if (w > 0 && w !== measured) setMeasured(w);\n }, [text, measured, fontSize]);\n if (!viewBox || viewBox.x == null || viewBox.y == null || text === \"\") return null;\n const cx = viewBox.x + (viewBox.width ?? 0) / 2;\n const half = (measured ?? text.length * fontSize * 0.6) / 2;\n // The start clamp applied last: a label wider than the plot keeps its start on screen.\n const x = plot ? Math.max(plot.x + half, Math.min(cx, plot.x + plot.width - half)) : cx;\n return (\n <text\n ref={ref}\n x={x}\n y={viewBox.y - 5}\n textAnchor=\"middle\"\n fontSize={fontSize}\n fontWeight={600}\n fill=\"var(--text-primary)\"\n className=\"recharts-label\"\n >\n {text}\n </text>\n );\n}\n\n/**\n * The keyboard's way onto a chart: one focusable `<rect>` per bar, or per slot when there\n * are no bars, laid over the plot INSIDE the recharts chart, where the x scale answers.\n *\n * keksdose drew its weekday pattern as seven real `<button>`s (spending-tab.tsx) because\n * a recharts bar is reachable by nothing but the pointer. This is that, for every chart:\n *\n * - ONE tab stop (roving `tabIndex`): Tab moves past the chart, not through 30 bars.\n * - ←/→ step through the stops in order, ↑/↓ between the bars of one slot, Home/End.\n * - Each is named \"period — series: value\".\n * - With `onPointClick` (`onPick`) each is a `role=\"button\"`, and ↵ and Space report the\n * stop as a click would — with the series for a bar. Without (0.52, refactor audit\n * 2026-10-30, DSP-5) each is a `role=\"img\"` to read, as PieChart's slices are: before,\n * such a chart was recharts' unnamed `role=\"application\"` stop, whose arrows moved a\n * tooltip nothing announced.\n *\n * The stops take NO pointer events, so the drag-to-zoom layer, the tooltip and the\n * pointer's own clicks underneath behave exactly as they did. Focus is shown by the\n * slot tinted and, for a bar, its own outline (`focusedBarShape`) — and by the tooltip,\n * which recharts' own pointer is stood on the stop for (`pointAt`).\n */\nfunction PointKeys({\n stops,\n current,\n label,\n onFocusStop,\n onBlurStops,\n onPick,\n}: {\n stops: readonly PointStop[];\n current: number;\n label: string;\n onFocusStop: (at: number) => void;\n onBlurStops: () => void;\n onPick?: (stop: PointStop) => void;\n}) {\n const plot = usePlotArea();\n const scale = useXAxisScale();\n const refs = useRef<(SVGRectElement | null)[]>([]);\n if (!plot || !scale || plot.width <= 0 || plot.height <= 0) return null;\n\n const onKeyDown = (at: number) => (event: KeyboardEvent<SVGRectElement>) => {\n const stop = stops[at];\n // ↑/↓ stay in the slot: the next or previous bar of the same period. The stops are\n // in slot order, so a slot's bars are neighbours. ←/→, Home and End as Treemap's tiles\n // take them (0.52 code review, deep, charts, finding 14): → is the next stop in any\n // page, since the plot runs left to right in an RTL one too (see `ChartContainer`).\n const inSlot = (step: 1 | -1) => (stops[at + step]?.index === stop.index ? at + step : at);\n const target =\n event.key === \"ArrowDown\"\n ? inSlot(1)\n : event.key === \"ArrowUp\"\n ? inSlot(-1)\n : rovingTarget(event.key, \"ltr\", at, stops.length, false);\n if (target !== undefined) {\n event.preventDefault();\n refs.current[target]?.focus();\n } else if (onPick && (event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n onPick(stop);\n }\n };\n\n const left = plot.x;\n const right = plot.x + plot.width;\n const middle = plot.y + plot.height / 2;\n // Every target an arrow, Home or End can name from the roving stop — see ALL_STOPS_UP_TO.\n const drawn =\n stops.length <= ALL_STOPS_UP_TO ? undefined : new Set([0, current - 1, current, current + 1, stops.length - 1]);\n return (\n <g role=\"group\" aria-label={label}>\n {stops.map((stop, at) => {\n if (drawn && !drawn.has(at)) return null;\n // An edge with no neighbour runs to the plot's edge.\n const a = finite(scale(stop.from)) ?? left;\n const b = finite(scale(stop.to)) ?? right;\n const x0 = Math.max(left, Math.min(a, b));\n const x1 = Math.min(right, Math.max(a, b));\n return (\n <rect\n key={`${stop.index}:${stop.key ?? \"\"}`}\n ref={(node) => {\n refs.current[at] = node;\n }}\n role={onPick ? \"button\" : \"img\"}\n tabIndex={at === current ? 0 : -1}\n aria-label={stop.name()}\n data-point-key={stop.key}\n x={x0}\n y={plot.y}\n width={Math.max(0, x1 - x0)}\n height={plot.height}\n fill=\"transparent\"\n // Focus only: the pointer's drag, hover and click belong to what is below.\n pointerEvents=\"none\"\n strokeWidth={2}\n className={cn(\n \"outline-none focus-visible:fill-[var(--brand)]/10\",\n // A bar outlines ITSELF (see `FOCUSED_BAR`); a slot has nothing else to.\n stop.key === undefined && \"focus-visible:stroke-[var(--brand)]\",\n )}\n onFocus={(event) => {\n onFocusStop(at);\n pointAt(event.currentTarget, (x0 + x1) / 2, middle);\n }}\n onBlur={(event) => {\n onBlurStops();\n // On to another stop: that one stands the pointer on itself. (`refs` holds a\n // null for every stop not drawn, so a blur to nowhere is no stop.)\n const next = event.relatedTarget as SVGRectElement | null;\n if (!next || !refs.current.includes(next)) {\n pointAt(event.currentTarget, left - 1, middle);\n }\n }}\n onKeyDown={onKeyDown(at)}\n />\n );\n })}\n </g>\n );\n}\n\n/**\n * Stands recharts' pointer at (`x`, `y`) in the chart's own px, as a mouse moved there\n * would — what the keyboard's stops show their tooltip by (0.52 code review, deep, charts,\n * finding 4). Their `defaultIndex` alone moved it only until a pointer had hovered the\n * chart: recharts reads it no more once a hover has an index, and a mouse that has left\n * keeps its index. After one hover the arrows moved the tint, and the tooltip, the one\n * place the value is drawn, stayed where the mouse had left it. recharts' own keyboard\n * layer, which these stops replaced (DSP-5), drove the tooltip through its own state.\n *\n * A point off the plot (`x` left of it) takes the pointer off the chart: recharts hides\n * its tooltip there, through the same frame-throttled path a pending move takes, so a\n * blur right after a focus is never overtaken by it. recharts reads the pointer against\n * its wrapper's box, scaled as the box is drawn (`getRelativeCoordinate`); the point is\n * put back into that box.\n */\nfunction pointAt(within: Element, x: number, y: number) {\n const wrapper = within.closest<HTMLElement>(\".recharts-wrapper\");\n if (!wrapper) return;\n const box = wrapper.getBoundingClientRect();\n const scaleX = wrapper.offsetWidth > 0 ? box.width / wrapper.offsetWidth : 1;\n const scaleY = wrapper.offsetHeight > 0 ? box.height / wrapper.offsetHeight : 1;\n wrapper.dispatchEvent(\n new MouseEvent(\"mousemove\", { bubbles: true, clientX: box.left + x * scaleX, clientY: box.top + y * scaleY }),\n );\n}\n\ninterface PlotProps extends Omit<SeriesChartProps, \"rows\" | \"x\"> {\n /** The rows AS PLOTTED — what the zoom fits on. The caller's are `model.source`. */\n rows: readonly SeriesChartRow[];\n /** What the zoom fits on: the plotted key. */\n x: { key: string };\n model: XModel;\n xAxis: SeriesChartX;\n}\n\n/** The chart proper, over an abscissa already reduced to numbers (see {@link XModel}). */\nfunction SeriesPlot({\n model,\n xAxis,\n series,\n axes = ONE_UNTITLED_AXIS,\n valueFormat,\n height = \"h-72\",\n connectNulls,\n empty,\n animationMs = 0,\n spans,\n references,\n markers,\n onPointClick,\n tooltip,\n zoom,\n labels: labelsProp,\n locale: localeProp,\n className,\n minBarLength,\n maxVisibleAxes,\n axisBudget = \"auto\",\n onAxisBudget,\n maxRows,\n \"aria-label\": ariaLabel,\n description,\n}: PlotProps) {\n const labels = useKitLabels(\"seriesChart\", DEFAULT_SERIES_CHART_LABELS, labelsProp);\n const locale = useKitLocale(localeProp);\n const number = useDefaultFormat(localeProp);\n // The text size (docs/text-size-harmonization.md §3.2, §4, §10.10): the axis bands, the\n // tick spacing and the labels drawn in px grow with it — the tick text is `text-xs` and\n // grows by itself — and the axes aim at three ticks instead of five from Large up.\n // Strokes, dashes and the grid stay px.\n const { scale } = useTextSize();\n const edgeFor = useChartEdge();\n // The tiles' rule (0.52, DSP-18, Marcel's decision 3): the ink edge under More contrast\n // only — at Standard it fell on 5 of 8 hues in light and on 2 in dark, the unevenness\n // #642 took off the tiles.\n const edges = useEdgesInForce(\"auto\");\n const ticksAim = tickTarget(scale);\n const grow = (px: number) => (scale === 1 ? px : Math.round(px * scale));\n // The keyboard stops' roving tab stop, and the one that has focus (see `PointKeys`).\n // Up here, above the empty state's early return, like every hook.\n const [keyStop, setKeyStop] = useState(0);\n const [keyFocus, setKeyFocus] = useState<number | undefined>(undefined);\n // Where the tooltip goes, and — off the plot — the row it is portalled into.\n // Below `sm` (`max-sm:`, at the text size in force) — where `\"auto\"` takes the tooltip\n // off the plot. Narrower than the phone layout on purpose: a tablet's plot is wide\n // enough that the box beside the finger leaves the data in view; a phone's is not.\n const phone = useBreakpoint(\"max-sm\", false);\n const placement = resolveTooltipPlacement(tooltip?.placement, useKitChartTooltipPlacement(), phone);\n const [readout, setReadout] = useState<HTMLDivElement | null>(null);\n\n // The chart's own width, for the automatic axis budget. Its box, not the plot's: the\n // box does not change when an axis is hidden, so the rule cannot oscillate. Nothing\n // measured (jsdom, the first frame) is no automatic budget.\n const [box, setBox] = useState<HTMLDivElement | null>(null);\n const [width, setWidth] = useState<number | undefined>(undefined);\n useLayoutEffect(() => {\n if (!box || axisBudget === \"off\" || typeof ResizeObserver === \"undefined\") return;\n const measure = () => setWidth(box.getBoundingClientRect().width || undefined);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(box);\n return () => observer.disconnect();\n }, [box, axisBudget]);\n // The caller's cap first, then — on what is left — the automatic one.\n const capped = budgetedAxes(axes, maxVisibleAxes);\n const afterCap = capped.length\n ? axes.map((axis) => (capped.includes(axis.id) ? { ...axis, hide: true as const } : axis))\n : axes;\n const auto =\n axisBudget === \"off\"\n ? []\n : budgetedAxes(\n afterCap,\n autoAxisBudget(afterCap, width, (axis) => axisBandWidth(axis.width, Boolean(axis.title), scale), scale),\n );\n const budgeted = [...capped, ...auto];\n const budgetKey = budgeted.join(\"\\n\");\n\n // The rows drawn under `maxRows` (KS U2, `series-chart-thin.ts`): their indices into\n // the caller's rows, or `undefined` for all of them. Up here, above the empty state's\n // early return, like every hook; worked out again only when the rows, the series\n // drawn, the budget or the x window change — not on every render of a drag.\n const thinKeys = series.map((entry) => entry.key).join(\"\\n\");\n const [windowFrom, windowTo] = zoom?.xDomain ?? [undefined, undefined];\n const thin = useMemo(() => {\n if (model.kind === \"category\" || maxRows === undefined) return undefined;\n const keys = thinKeys ? thinKeys.split(\"\\n\") : [];\n const window: [number, number] | undefined =\n windowFrom !== undefined && windowTo !== undefined ? [windowFrom, windowTo] : undefined;\n const kept = thinnedRows(model.rows, model.plotKey, keys, maxRows, window);\n if (!kept) return undefined;\n return {\n kept,\n plotted: kept.map((index) => model.rows[index]),\n source: kept.map((index) => model.source[index]),\n };\n }, [model, thinKeys, maxRows, windowFrom, windowTo]);\n\n // Reported when the SET changes, not on every render — an inline callback is a new\n // function each time, and the guard keeps it from being called again for nothing.\n const reported = useRef(\"\");\n useEffect(() => {\n if (budgetKey === reported.current) return;\n reported.current = budgetKey;\n onAxisBudget?.(budgetKey ? budgetKey.split(\"\\n\") : []);\n }, [budgetKey, onAxisBudget]);\n\n // A number or a CSS length is set inline; any other string is a class. Either way the\n // one value sizes both the chart and its empty state.\n const { className: heightClass, style: heightStyle } = chartHeightProps(height);\n\n // A named figure, described by the caller's sentence and — where a drag zooms — the\n // gesture (0.52, refactor audit 2026-10-30, DSP-5). The hint used to be the name of the\n // zoom layer's rect, a `role=\"application\"` that could not take focus. The description\n // is `hidden`: read through `aria-describedby`, never twice in browse mode.\n const drawable = model.source.length > 0 && series.length > 0;\n const spoken = [description, drawable && zoom?.layer ? labels.zoomHint : undefined].filter(Boolean).join(\" \");\n // Inside the root, not after it as a sibling: a StaticSeriesChart then stopped being its\n // parent's last child, and a stack's `space-y-*` / `divide-y` gave it a margin or a rule\n // it never had (0.52 code review, deep, charts, findings 7 and 14 — Treemap's copy of this\n // went the same way). The plot's root is `ChartContainer`, which takes the sentence itself.\n const about = useFigureDescription(spoken || undefined);\n const figure = { role: \"figure\", \"aria-label\": ariaLabel, \"aria-describedby\": about.describedBy } as const;\n\n // The empty state takes the chart's own height and is centred in it: a chart that\n // shrank to its \"nothing to draw\" sentence moved everything under it up the page\n // the moment a legend entry was switched off.\n if (!drawable) {\n return (\n <div\n {...figure}\n className={cn(\"flex w-full items-center justify-center px-2 text-center\", heightClass)}\n style={heightStyle}\n >\n {empty !== undefined ? empty : <p className=\"text-xs text-muted\">{labels.empty}</p>}\n {about.node}\n </div>\n );\n }\n\n const x = xAxis;\n const xKey = model.plotKey;\n // What is DRAWN — the thinned rows under `maxRows`, else the caller's — and what is\n // FITTED: every row, so a band, a whole-number tick and the zoom's refit are the same\n // with a budget as without one.\n const plotted = thin?.plotted ?? model.rows;\n const rows = thin?.source ?? model.source;\n const allPlotted = model.rows;\n /** A drawn row's position in the CALLER's rows, which dots and hits report. */\n const origin = (index: number) => thin?.kept[index] ?? index;\n // What the budget took off the chart: an axis drawn as `hide` — and its unit, which\n // the tooltip names now that no title says it. Axes the caller hid keep their series'\n // labels as given, as they always did.\n const drawnAxes = budgeted.length\n ? axes.map((axis) => (budgeted.includes(axis.id) ? { ...axis, hide: true as const } : axis))\n : axes;\n const lostUnit = new Map(axes.filter((axis) => budgeted.includes(axis.id)).map((axis) => [axis.id, axisUnit(axis)]));\n const config: ChartConfig = Object.fromEntries(\n series.map((entry, index) => [\n entry.key,\n {\n label: withUnit(entry.label, lostUnit.get(entry.axis ?? DEFAULT_Y_AXIS)),\n color: entry.color ?? paletteFor(index),\n },\n ]),\n );\n const visible = drawnAxes.filter((axis) => !axis.hide);\n // The grid hangs its horizontal rules off ONE y axis, and recharts looks for the one\n // whose id is its own default (`0`). Every axis here is named, so without saying\n // which, it finds none and draws no horizontal rules at all. The first visible axis,\n // because those are the ticks a reader puts a ruler on.\n const gridAxis = (visible[0] ?? drawnAxes[0])?.id ?? DEFAULT_Y_AXIS;\n const onLeft = visible.some((axis) => (axis.orientation ?? \"left\") === \"left\");\n const onRight = visible.some((axis) => axis.orientation === \"right\");\n // The margins are what is left once the axes have their bands: an axis band IS the\n // gutter on its side, so a margin beside one is a second gutter. What remains is the\n // overhang of the first/last x tick where no y axis covers it.\n const margin = {\n // Room for a marker's label over a point at the top of the band.\n top: markers?.some((marker) => marker.label) ? grow(22) : 8,\n // The first and last x tick's overhang: text, so it grows with it.\n right: onRight ? 0 : grow(10),\n left: onLeft ? 0 : grow(10),\n // Under the ticks, not under the whole axis: whatever comes next owns the gap.\n bottom: x.title ? grow(18) : 2,\n };\n\n const refs = references ?? [];\n const xRefs = refs.filter((ref) => ref.axis === \"x\");\n const yRefs = refs.filter((ref) => ref.axis !== \"x\");\n const xPos = (value: SeriesChartXValue) => model.position(value);\n\n // Fitted with air around it, unless the reader has zoomed or the caller pinned it.\n // Ticks are the round values INSIDE whichever domain that is (see\n // `series-chart-ticks.ts`), so a zoom window still gets round numbers, just finer.\n // A category axis is its slots, each half a slot of air either side — room for a\n // bar, and the tick under the middle of it.\n const fittedX: [number, number] | undefined =\n zoom?.xDomain ??\n (model.kind === \"category\"\n ? [-0.5, rows.length - 0.5]\n : padBand(\n ...(extend(undefined, [\n ...allPlotted.map((row) => finite(row[xKey])),\n ...xRefs.map((ref) => xPos(ref.value)),\n ...(markers ?? []).map((marker) => xPos(marker.x)),\n ]) ?? [Infinity, -Infinity]),\n ));\n\n const timeUnit = model.kind === \"time\" ? timeTicksWithUnit(fittedX, ticksAim) : undefined;\n // Whole-number ticks on a number line whose rows are all whole numbers — see\n // `SeriesChartX.integerTicks`.\n const integerX =\n model.kind === \"number\" &&\n (x.integerTicks ??\n allPlotted.every((row) => {\n const value = finite(row[xKey]);\n return value === undefined || Number.isInteger(value);\n }));\n const xTicks =\n resolveTicks(x.tickValues, fittedX, xPos) ??\n (model.kind === \"category\"\n ? categoryTicks(fittedX, rows.length)\n : model.kind === \"time\"\n ? timeUnit?.ticks\n : integerX\n ? (integerTicks(fittedX, ticksAim) ?? niceTicks(fittedX, ticksAim))\n : niceTicks(fittedX, ticksAim));\n\n // Ticks and the tooltip heading, back in the caller's terms.\n const timeFormat = new Intl.DateTimeFormat(locale, TIME_TICK_FORMAT[timeUnit?.unit ?? \"day\"]);\n const dateFormat = new Intl.DateTimeFormat(locale, {\n dateStyle: \"medium\",\n ...(timeUnit?.unit === \"hour\" ? { timeStyle: \"short\" } : {}),\n });\n const categoryText = (value: SeriesChartXValue) =>\n value instanceof Date ? dateFormat.format(value) : typeof value === \"number\" ? number(value) : String(value ?? \"\");\n const tickAt = (position: number): SeriesChartXTick => ({\n value: model.valueAt(position),\n ...(model.kind === \"category\" ? { index: Math.round(position) } : {}),\n ...(timeUnit ? { unit: timeUnit.unit } : {}),\n });\n const defaultFormat = (position: number, tick: SeriesChartXTick) =>\n model.kind === \"category\"\n ? categoryText(tick.value)\n : model.kind === \"time\"\n ? timeFormat.format(position)\n : number(position);\n const format = x.format ?? defaultFormat;\n const xFormat = (position: number) => format(position, tickAt(position));\n const label = x.label ?? (model.kind === \"time\" ? (position: number) => dateFormat.format(position) : format);\n const xLabel = (position: number) => label(position, tickAt(position));\n\n const tickAngle = x.ticks === false ? 0 : (x.tickAngle ?? 0);\n const tickBand = tiltedTickBand(\n (xTicks ?? []).map((tick) => xFormat(tick)),\n tickAngle,\n scale,\n );\n\n const source: ZoomFitSource = {\n rows: allPlotted,\n series,\n axes,\n xKey,\n };\n // An axis a bar or an area stands on is read from zero (see `includeZero`).\n const anchored = (axis: SeriesChartAxis) =>\n axis.includeZero ??\n series.some((entry) => (entry.axis ?? DEFAULT_Y_AXIS) === axis.id && (entry.type ?? \"line\") !== \"line\");\n // Whole-number ticks on an axis whose values are all whole — see\n // `SeriesChartAxis.integerTicks`. A stack of whole layers sums to a whole number, so\n // the layers are enough to look at.\n const wholeOnly = (axis: SeriesChartAxis) =>\n axis.integerTicks ??\n series\n .filter((entry) => (entry.axis ?? DEFAULT_Y_AXIS) === axis.id)\n .every((entry) =>\n allPlotted.every((row) => {\n const value = finite(row[entry.key]);\n return value === undefined || Number.isInteger(value);\n }),\n );\n const onAxis = (axisId: string) => (ref: { axis?: string }) => (ref.axis ?? DEFAULT_Y_AXIS) === axisId;\n const fittedY = (axis: SeriesChartAxis): [number, number] | undefined => {\n const own = [\n ...yRefs.filter(onAxis(axis.id)).map((ref) => finite(ref.value)),\n ...(markers ?? []).filter(onAxis(axis.id)).map((marker) => finite(marker.y)),\n ];\n if (anchored(axis)) {\n // Never a dragged y window: refitted to the x window, still from zero.\n if (zoom?.xDomain) return anchoredBand(axisExtent(source, axis.id, zoom.xDomain)) ?? axis.domain;\n return axis.domain ?? anchoredBand(extend(axisExtent(source, axis.id), own));\n }\n return (\n zoom?.yDomains[axis.id] ??\n axis.domain ??\n padBand(...(extend(axisExtent(source, axis.id), own) ?? [Infinity, -Infinity]))\n );\n };\n\n // The abscissa of a row in the caller's terms: a category is its slot, which is\n // its index; a time or a number is read back from where it was plotted.\n const xOf = (index: number): SeriesChartXValue =>\n model.kind === \"category\"\n ? (rows[index][model.sourceKey] as SeriesChartXValue)\n : model.valueAt(finite(plotted[index][xKey]) ?? NaN);\n const hitAt = (index: number, key?: string): SeriesChartHit | undefined => {\n const row = rows[index];\n return row ? { index: origin(index), row, x: xOf(index), key } : undefined;\n };\n\n // The keyboard stops — every bar with a value, slot by slot; or, with no bars, every\n // slot with any value. Only what is inside the window on show. Named on demand: past\n // ALL_STOPS_UP_TO only five are drawn, and naming is a date and a number format each.\n const stops: PointStop[] = [];\n {\n const valueText = valueFormat ?? number;\n const nameOf = (entry: SeriesChartSeries) =>\n typeof entry.label === \"string\" || typeof entry.label === \"number\" ? String(entry.label) : entry.key;\n const cellText = (entry: SeriesChartSeries, value: number) => {\n const name = nameOf(entry);\n return name ? `${name}: ${valueText(value)}` : valueText(value);\n };\n const bars = series.filter((entry) => entry.type === \"bar\");\n const [low, high] = fittedX ?? [-Infinity, Infinity];\n const placed = plotted\n .map((row, index) => ({ index, at: model.kind === \"category\" ? index : finite(row[xKey]) }))\n .filter(\n (slot): slot is { index: number; at: number } => slot.at !== undefined && slot.at >= low && slot.at <= high,\n )\n .sort((a, b) => a.at - b.at);\n placed.forEach(({ index, at }, k) => {\n const from = k > 0 ? (placed[k - 1].at + at) / 2 : low;\n const to = k < placed.length - 1 ? (placed[k + 1].at + at) / 2 : high;\n // The heading the tooltip would give it, when that is text; else the tick.\n const where = () => {\n const heading = xLabel(at);\n return typeof heading === \"string\" && heading ? heading : xFormat(at);\n };\n const valued = (bars.length ? bars : series)\n .map((entry) => ({ entry, value: finite(rows[index]?.[entry.key]) }))\n .filter((cell): cell is { entry: SeriesChartSeries; value: number } => cell.value !== undefined);\n if (bars.length) {\n for (const { entry, value } of valued) {\n stops.push({ index, key: entry.key, from, to, name: () => `${where()} — ${cellText(entry, value)}` });\n }\n } else if (valued.length) {\n stops.push({\n index,\n from,\n to,\n name: () => `${where()} — ${valued.map(({ entry, value }) => cellText(entry, value)).join(\", \")}`,\n });\n }\n });\n }\n const focusedStop = keyFocus === undefined ? undefined : stops[keyFocus];\n\n const dotFor = (entry: SeriesChartSeries) => {\n const want = entry.dot;\n if (!want) return false;\n const color = `var(--color-${entry.key})`;\n return (props: { cx?: number; cy?: number; index: number }) => {\n const { cx, cy, index } = props;\n const value = finite(rows[index]?.[entry.key]);\n if (value === undefined || !Number.isFinite(cx) || !Number.isFinite(cy)) return <g />;\n const point: SeriesChartPoint = {\n key: entry.key,\n index: origin(index),\n row: rows[index],\n x: xOf(index),\n value,\n cx: cx!,\n cy: cy!,\n color,\n };\n const drawn = want === true ? true : want(point);\n if (drawn === true) {\n return (\n <circle\n className=\"recharts-dot\"\n cx={cx}\n cy={cy}\n r={3}\n fill={color}\n // Ringed in the surface, so a dot on a crossing line still reads as a dot.\n stroke=\"var(--bg-surface)\"\n strokeWidth={1.5}\n />\n );\n }\n if (drawn === false || drawn == null) return <g />;\n return <g>{drawn}</g>;\n };\n };\n\n const animation = {\n isAnimationActive: animationMs > 0,\n animationDuration: animationMs,\n animationEasing: \"ease-out\" as const,\n };\n\n const inRow = placement !== \"cursor\";\n const chart = (\n <ChartContainer\n {...(inRow ? {} : { role: \"figure\", \"aria-label\": ariaLabel, description: spoken || undefined })}\n ref={setBox}\n data-axis-budget={budgeted.length ? budgetKey.replace(/\\n/g, \" \") : undefined}\n // \"drawn/all\" while `maxRows` thins: what a reader of the DOM (a test, a bug\n // report) needs to know the picture is an envelope.\n data-thinned={thin ? `${thin.kept.length}/${allPlotted.length}` : undefined}\n config={config}\n className={cn(\n \"w-full\",\n // With a readout the chart's height is the whole block's, and the plot takes\n // what the row leaves.\n inRow ? \"min-h-0 flex-1\" : heightClass,\n className,\n onPointClick && \"cursor-pointer\",\n )}\n style={inRow ? undefined : heightStyle}\n >\n <ComposedChart\n data={plotted as Record<string, unknown>[]}\n margin={margin}\n // Positive and negative layers stacked apart, as `axisExtent` fits them — a\n // month's expenses hang below the axis instead of eating into its income.\n stackOffset=\"sign\"\n // recharts' own keyboard layer makes the whole surface an unnamed\n // `role=\"application\"` tab stop whose arrows move a tooltip nothing announces —\n // a second stop beside `PointKeys`, which every chart has since 0.52 (DSP-5).\n accessibilityLayer={false}\n onClick={\n onPointClick\n ? (state) => {\n const index = Number(state?.activeTooltipIndex ?? state?.activeIndex);\n const hit = Number.isInteger(index) ? hitAt(index) : undefined;\n if (hit) onPointClick(hit);\n }\n : undefined\n }\n >\n {/* Both ways: a measurement plot is read by putting a ruler on it, and a\n horizontal-only grid answers half of those questions. */}\n <CartesianGrid yAxisId={gridAxis} />\n <XAxis\n dataKey={xKey}\n // Numeric, not categorical: a measured sweep is unevenly spaced, and a\n // category axis would straighten exactly the curvature the chart is for.\n // A category chart is numeric too — on the slot index — which is what lets\n // it zoom and keeps its ticks under the middle of each bar group.\n type=\"number\"\n domain={fittedX ?? [\"dataMin\", \"dataMax\"]}\n ticks={xTicks}\n // Clip the lines to a zoom window instead of recharts widening it back out.\n allowDataOverflow={zoom?.xDomain !== undefined || model.kind === \"category\"}\n tickLine={false}\n axisLine={false}\n minTickGap={grow(MIN_TICK_GAP)}\n // Where the ticks crowd, drop every Nth rather than recharts' default\n // `preserveEnd`, which drops whichever single tick collides: a phone's whole-week\n // axis came out 2 4 6 8 _ 12, a doubled gap that reads as a missing week. Every\n // other tick, keeping the last, gives 4 8 12 — still an even ruler.\n interval=\"equidistantPreserveEnd\"\n tick={x.ticks === false ? false : undefined}\n {...(tickAngle ? { angle: tickAngle, textAnchor: tickAngle < 0 ? \"end\" : \"start\" } : {})}\n // With neither ticks nor title there is nothing to reserve the band for, and\n // recharts' own 30 px would leave a gap under every chart of a stack.\n height={x.ticks === false && !x.title ? 4 : tickBand}\n tickFormatter={(value: number) => xFormat(Number(value))}\n >\n {x.title && (\n <Label value={x.title} position=\"insideBottom\" offset={-grow(12)} className=\"fill-muted text-caption\" />\n )}\n </XAxis>\n {drawnAxes.map((axis) => {\n const domain = fittedY(axis);\n const zoomed = anchored(axis) ? zoom?.xDomain !== undefined : zoom?.yDomains[axis.id] !== undefined;\n return (\n <YAxis\n key={axis.id}\n yAxisId={axis.id}\n hide={axis.hide}\n domain={domain}\n ticks={\n resolveTicks(axis.tickValues, domain, finite) ??\n (wholeOnly(axis)\n ? (integerTicks(domain, ticksAim) ?? niceTicks(domain, ticksAim))\n : niceTicks(domain, ticksAim))\n }\n allowDataOverflow={zoomed}\n orientation={axis.orientation ?? \"left\"}\n // Nothing for a hidden axis. An axis that turns hidden on a MOUNTED chart —\n // what the budget does on every resize across its threshold — kept its old\n // width in recharts' stacking of that side, and pushed the axes still drawn\n // off the chart's edge. A zero width leaves nothing stale to count.\n width={axis.hide ? 0 : axisBandWidth(axis.width, Boolean(axis.title), scale)}\n tickLine={false}\n axisLine={false}\n tickFormatter={axis.format ?? number}\n // With an axis per channel the tint is the only thing saying which\n // numbers belong to which line.\n tick={axis.color ? { fill: axis.color } : undefined}\n >\n {axis.title && !axis.hide && (\n <Label\n value={axis.title}\n // Rotated so both sides read upward from the bottom of their axis.\n angle={axis.orientation === \"right\" ? 90 : -90}\n position={axis.orientation === \"right\" ? \"insideRight\" : \"insideLeft\"}\n // Inline, so a sole series' colour beats the class's neutral fill —\n // and absent for a shared axis, so the class draws it.\n style={{ textAnchor: \"middle\", fill: soleSeriesColor(axis, series) }}\n offset={grow(AXIS_TITLE_OFFSET)}\n className=\"fill-muted text-caption\"\n />\n )}\n </YAxis>\n );\n })}\n {inRow ? (\n // Not before the row exists: without its own portal recharts would float this\n // content over the plot for the first frame.\n readout && (\n <ChartTooltip\n portal={readout}\n // recharts hides an inactive tooltip; the row shows its idle state instead.\n wrapperStyle={{ visibility: \"visible\" }}\n defaultIndex={focusedStop?.index}\n content={\n <ChartTooltipContent\n variant=\"readout\"\n idleKeys={series.map((entry) => entry.key)}\n idleLabel={x.title || undefined}\n labelFormatter={(value) => xLabel(Number(value))}\n valueFormatter={valueFormat ?? number}\n />\n }\n />\n )\n ) : (\n <ChartTooltip\n {...(tooltip?.allowEscapeViewBox || tooltip?.boundary\n ? { allowEscapeViewBox: tooltip.allowEscapeViewBox ?? { x: true } }\n : {})}\n // The content shifts itself 12 px off the cursor (or flips) against the\n // boundary; recharts' own offset on top would double it.\n {...(tooltip?.boundary ? { offset: 0 } : {})}\n // The keyboard's stop shows its tooltip as the pointer's would.\n defaultIndex={focusedStop?.index}\n content={\n <ChartTooltipContent\n labelFormatter={(value) => xLabel(Number(value))}\n valueFormatter={valueFormat ?? number}\n boundaryRef={tooltip?.boundary}\n />\n }\n />\n )}\n {series.map((entry) => {\n const type = entry.type ?? \"line\";\n const yAxisId = entry.axis ?? DEFAULT_Y_AXIS;\n const color = `var(--color-${entry.key})`;\n // Under More contrast, a filled mark in a hue under 3:1 against the ground gets\n // a 1px ink edge (WCAG 1.4.11, anyplot's rule) — measured on the colour the\n // config paints. At Standard none does (see `edges`).\n const edge = edges === \"contrast\" ? edgeFor(config[entry.key]?.color) : undefined;\n const own = entry.dash ?? (entry.dashed ? 1 : 0);\n const dash = entry.step ? strokeDash(STEP_DASH) : typeof own === \"string\" ? own : strokeDash(own);\n const curve = entry.step ? \"stepAfter\" : (entry.curve ?? \"monotone\");\n const width = entry.strokeWidth ?? (entry.step ? STEP_WIDTH : LINE_WIDTH);\n if (type === \"bar\") {\n const stub = entry.minBarLength ?? minBarLength;\n return (\n <Bar\n key={entry.key}\n yAxisId={yAxisId}\n dataKey={entry.key}\n stackId={entry.stack}\n fill={color}\n fillOpacity={entry.fillOpacity}\n {...(edge ? { stroke: edge, strokeWidth: 1 } : {})}\n radius={entry.stack === undefined ? BAR_RADIUS : 0}\n // Read off the row rather than recharts' `value`: in a stack that is the\n // layer's running top, which a hole has too — and a hole gets no stub.\n {...(stub\n ? {\n minPointSize: (_value: unknown, index: number) =>\n finite(plotted[index]?.[entry.key]) === undefined ? 0 : stub,\n }\n : {})}\n // Only the focused stop's series swaps its shape, and only for as long\n // as it has focus: every other bar keeps recharts' own.\n {...(focusedStop?.key === entry.key ? { shape: focusedBarShape(focusedStop.index) } : {})}\n onClick={\n onPointClick\n ? (_bar, index, event) => {\n // The plot's own click would report the same slot again,\n // without the series.\n event.stopPropagation();\n const hit = hitAt(index, entry.key);\n if (hit) onPointClick(hit);\n }\n : undefined\n }\n {...animation}\n />\n );\n }\n if (type === \"area\") {\n return (\n <Area\n key={entry.key}\n yAxisId={yAxisId}\n type={curve}\n dataKey={entry.key}\n stackId={entry.stack}\n // The edge replaces the hue on the area's outline only; the fill keeps it,\n // and the outline its width (0.52, DSP-18: it was 1px, whatever\n // `strokeWidth` said).\n stroke={edge ?? color}\n strokeWidth={width}\n strokeDasharray={dash}\n fill={color}\n fillOpacity={entry.fillOpacity ?? (entry.stack !== undefined ? 0.55 : 0.2)}\n dot={dotFor(entry)}\n {...(entry.activeDot !== undefined ? { activeDot: entry.activeDot } : {})}\n connectNulls={connectNulls}\n {...animation}\n />\n );\n }\n return (\n <Line\n key={entry.key}\n yAxisId={yAxisId}\n type={curve}\n dataKey={entry.key}\n stroke={color}\n strokeWidth={width}\n strokeDasharray={dash}\n dot={dotFor(entry)}\n {...(entry.activeDot !== undefined ? { activeDot: entry.activeDot } : {})}\n connectNulls={connectNulls}\n {...animation}\n />\n );\n })}\n {spans?.map((span) => (\n <ReferenceLine\n key={span.key}\n yAxisId={span.axis ?? DEFAULT_Y_AXIS}\n segment={[\n { x: span.x, y: span.from },\n { x: span.x, y: span.to },\n ]}\n stroke={span.color ?? \"var(--text-muted)\"}\n strokeWidth={2}\n // Discarded rather than clamped when zoomed past: a span clamped to the\n // window's edge draws a vertical line at an abscissa it never stood at.\n ifOverflow=\"discard\"\n />\n ))}\n {refs.map((ref, index) => {\n const vertical = ref.axis === \"x\";\n const at = vertical ? xPos(ref.value) : finite(ref.value);\n if (at === undefined) return null;\n const color = ref.color ?? TONE_COLOR[ref.tone ?? \"muted\"];\n return (\n <ReferenceLine\n key={ref.key ?? `reference-${index}`}\n // A vertical line still needs a y axis to be drawn against, and every\n // axis here is named — the grid's is always there.\n yAxisId={vertical ? gridAxis : (ref.axis ?? DEFAULT_Y_AXIS)}\n {...(vertical ? { x: at } : { y: at })}\n stroke={color}\n strokeWidth={1}\n strokeDasharray={strokeDash(ref.dash ?? 1)}\n ifOverflow=\"discard\"\n label={\n ref.label\n ? {\n value: ref.label,\n position: \"insideTopLeft\",\n fontSize: REFERENCE_LABEL_SIZE * scale,\n fill: color,\n }\n : undefined\n }\n />\n );\n })}\n {markers?.map((marker, index) => {\n const at = xPos(marker.x);\n if (at === undefined || finite(marker.y) === undefined) return null;\n const color = marker.color ?? TONE_COLOR[marker.tone ?? \"brand\"];\n return (\n <ReferenceDot\n key={marker.key ?? `marker-${index}`}\n yAxisId={marker.axis ?? DEFAULT_Y_AXIS}\n x={at}\n y={marker.y}\n r={marker.r ?? 4.5}\n fill={color}\n stroke=\"var(--bg-surface)\"\n strokeWidth={1.5}\n ifOverflow=\"discard\"\n label={marker.label ? { value: marker.label, position: \"top\", content: <MarkerLabel /> } : undefined}\n />\n );\n })}\n {stops.length > 0 && (\n <PointKeys\n stops={stops}\n current={Math.min(keyStop, stops.length - 1)}\n label={labels.points}\n onFocusStop={(at) => {\n setKeyStop(at);\n setKeyFocus(at);\n }}\n onBlurStops={() => setKeyFocus(undefined)}\n onPick={\n onPointClick\n ? (stop) => {\n const hit = hitAt(stop.index, stop.key);\n if (hit) onPointClick(hit);\n }\n : undefined\n }\n />\n )}\n {zoom?.layer}\n </ComposedChart>\n </ChartContainer>\n );\n if (!inRow) return chart;\n // The row's own box, reserved from the first render: its idle state has the cells the\n // active one will, so the first tap fills it in rather than pushing the plot down.\n const row = (\n <div\n ref={setReadout}\n data-tooltip-readout={placement}\n className={cn(\n \"shrink-0\",\n // Above, the heading line shares the top corner with the zoom's reset button.\n placement === \"above\" ? \"pb-2 [&_[data-readout-heading]]:pe-32\" : \"pt-2\",\n )}\n />\n );\n return (\n <div {...figure} className={cn(\"flex w-full flex-col\", heightClass)} style={heightStyle}>\n {placement === \"above\" && row}\n {chart}\n {placement === \"below\" && row}\n {about.node}\n </div>\n );\n}\n\nconst ZoomablePlot = withChartZoom(SeriesPlot);\n\n/**\n * The caller's props, with the abscissa reduced to numbers for the plot and the zoom.\n * The reduction is kept while the rows and the two settings it reads stay the same — a\n * category or time chart otherwise re-maps every row on every render, and `maxRows`'\n * envelope would be worked out again with it.\n */\nfunction usePlotProps<TRow extends object>(typed: SeriesChartProps<TRow>): PlotProps {\n // `TRow` types only what the caller is handed back, and that is its own row objects,\n // untouched (0.53): the plot reads them as the `object` rows they are. Through `unknown`\n // because the two are not comparable for an unresolved `TRow`: `SeriesChartSeries` is\n // contravariant in it (its `dot` is handed rows) and `rows` covariant.\n const props = typed as unknown as SeriesChartProps;\n const x = props.x ?? {};\n const { rows } = props;\n const { type, key } = x;\n // Read by key, so any object is a row (API-2); `SeriesChartRow` is how the plot reads it.\n const model = useMemo(() => xModel(rows as readonly SeriesChartRow[], { type, key }), [rows, type, key]);\n return { ...props, rows: model.rows, x: { key: model.plotKey }, model, xAxis: x };\n}\n\n/**\n * {@link SeriesChart} without the zoom: the same picture, no drag layer, no reset\n * button. For a thumbnail, a print view, or a chart the consumer wraps in its own\n * interaction.\n */\nexport function StaticSeriesChart<TRow extends object = object>(props: SeriesChartProps<TRow>) {\n return <SeriesPlot {...usePlotProps(props)} />;\n}\n\n/**\n * The series chart, zoomable. Drag across the plot to zoom (the drag's shape picks the\n * axes), double-click or press the reset button to go back; wrap several in\n * `SharedXZoom` to move their x windows together. Which axes zoom depends on the marks\n * — see {@link SeriesChartProps.zoomAxes}.\n *\n * Generic in its rows (0.53): `hit.row` and a `dot`'s `point.row` are typed as `rows` is —\n * see {@link SeriesChartProps}. A plain function, so the generic survives: a `memo` or a\n * `forwardRef` around it would read `TRow` as its constraint.\n */\nexport function SeriesChart<TRow extends object = object>(props: SeriesChartProps<TRow>) {\n // The zoom fits the PLOTTED rows — slot indices and epoch ms, not the caller's labels.\n return <ZoomablePlot {...usePlotProps(props)} />;\n}\n"],"mappings":"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","names":["anchoredBand","axisBandWidth","padBand","soleSeriesColor","row","width"]}
1
+ {"version":3,"sources":["../../src/components/series-chart.tsx"],"sourcesContent":["// The measurement plot: series against a swept numeric abscissa, any number of y axes,\n// dash patterns, vertical spans, and drag-to-zoom. Lifted out of lenkbank, where every\n// chart on every screen is this one arrangement of the kit's shell — so the arrangement\n// lives here once instead of as thirteen hand-assembled copies drifting apart.\n//\n// Built on `ChartContainer` + `ChartTooltipContent`, so it themes with the rest of the\n// chart kit: series default to the `--chart-N` ramp, axis text and grid take the\n// shell's tokens. It stays domain-free — every unit, title and number format is the\n// caller's, and the few words it can say itself are the `seriesChart` label namespace.\n//\n// **Every series may keep its own scale.** Position runs in millimetres and jerk in\n// hundreds of thousands of them per second cubed; on one axis the position line is\n// flat against the bottom. Normalising each series to its peak makes the y axis mean\n// nothing, so a caller declares an axis per incomparable channel instead, and may hide\n// all but the ones worth a column of numbers.\n//\n// Charts are drawn left-to-right in every writing direction — an abscissa is a number\n// line, not text — so `orientation` below is physical, and only the HTML chrome (the\n// reset button) is placed by logical side.\n//\n// **Bars, areas and periods too (0.8.0).** keksdose drew five money charts in raw\n// recharts — net worth, investments, income/expense, grouped payees, stacked categories\n// — each re-deciding the grid, the tooltip, the axis width and the \"—\" for a gap. They\n// are the same arrangement with a different mark, so a series now says `type: \"bar\" |\n// \"area\"` (and `stack`), and the abscissa may be a row of PERIODS (`x.type:\n// \"category\"`) or real dates (`x.type: \"time\"`) instead of a number the app had to\n// invent. What each of those does to the zoom is decided in one place,\n// `defaultZoomAxes` in `chart-zoom-core.tsx`.\n//\n// **An axis budget (0.15.1).** Every visible axis reserves its band, and four of them\n// leave a phone nothing to plot. A chart draws at most `maxVisibleAxes`, and — on its\n// own, when it is too narrow for the ones it has — one a side; the rest go hidden,\n// still scaling their lines, and their series say the unit the title no longer does.\n// The rule is `series-chart-budget.ts`.\n//\n// **A row budget (0.34, KS U2).** Opt-in: `maxRows` thins a long table to at most that\n// many rows before recharts sees it, by ENVELOPE — each bucket's lowest and highest row\n// of every drawn series — never by stride, which aliases a fast tone into a slow wave.\n// A zoom thins the window on show, so it draws more detail, not the same rows larger.\n// The rule is `series-chart-thin.ts`.\nimport { memo, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport type { ComponentProps, KeyboardEvent, ReactNode, RefObject } from \"react\";\nimport {\n Area,\n Bar,\n CartesianGrid,\n ComposedChart,\n Label,\n Line,\n ReferenceDot,\n ReferenceLine,\n Rectangle,\n XAxis,\n YAxis,\n usePlotArea,\n useXAxisScale,\n type BarShapeProps,\n} from \"recharts\";\nimport { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from \"./chart\";\nimport { useFigureDescription } from \"./chart-figure\";\nimport { rovingTarget } from \"../lib/direction\";\nimport {\n DEFAULT_Y_AXIS,\n axisExtent,\n withChartZoom,\n type ZoomAxesSetting,\n type ZoomBinding,\n type ZoomFitSource,\n} from \"./chart-zoom-core\";\nimport { STEP_DASH, strokeDash, type LegendEntry } from \"./toggle-legend\";\nimport { DEFAULT_SERIES_CHART_LABELS, type SeriesChartLabels } from \"./series-chart-labels\";\nimport {\n categoryTicks,\n integerTicks,\n niceTicks,\n tickTarget,\n timeTicksWithUnit,\n type TimeTickUnit,\n} from \"./series-chart-ticks\";\n// The tick module stays internal; the one type of it a public prop names is re-exported.\nexport type { TimeTickUnit } from \"./series-chart-ticks\";\nimport { autoAxisBudget, axisUnit, budgetedAxes, type SeriesChartAxisBudget } from \"./series-chart-budget\";\nimport { thinnedRows } from \"./series-chart-thin\";\n// The rule stays internal, like the ticks; the one type a public prop names is re-exported.\nexport type { SeriesChartAxisBudget } from \"./series-chart-budget\";\nimport {\n AXIS_TITLE_OFFSET,\n MIN_TICK_GAP,\n TIME_TICK_FORMAT,\n anchoredBand,\n axisBandWidth,\n extend,\n finite,\n padBand,\n resolveTicks,\n soleSeriesColor,\n tiltedTickBand,\n xModel,\n type XModel,\n} from \"./series-chart-axes\";\n// The pure axis and series helpers live in series-chart-axes.ts (MOD-9); their public\n// names are still this module's, so `/chart` and the barrel export them as before.\nexport {\n AXIS_TICK_WIDTH,\n AXIS_TITLE_STRIP,\n anchoredBand,\n axisBandWidth,\n mergeSeries,\n oneAxis,\n padBand,\n paddedDomain,\n seriesKey,\n soleSeriesColor,\n visibleSeries,\n} from \"./series-chart-axes\";\nexport type { SeriesSource } from \"./series-chart-axes\";\nimport { paletteFor } from \"../theme/chart-palette\";\nimport {\n useKitChartTooltipPlacement,\n useKitLabels,\n useKitLocale,\n type ChartTooltipPlacement,\n type LabelOverride,\n} from \"../i18n/kit-labels\";\nimport { useBreakpoint } from \"../hooks/use-breakpoint\";\nimport { useTextSize } from \"../theme/text-size\";\nimport { chartHeightProps, type ChartHeight } from \"./chart-height\";\nimport { useChartShade, useEdgesInForce } from \"./chart-edge\";\nimport { cn } from \"../lib/cn\";\nimport { formatWithMinus } from \"../lib/minus\";\n\n/**\n * One line, area or bar run of a {@link SeriesChart}.\n *\n * `TRow` is the chart's row type (0.53, keksdose after 0.52), and only `dot` reads it: its\n * `point.row` is that type. Without a type argument a series is what it was, and a chart\n * of typed rows still takes it — see {@link SeriesChartProps}.\n */\nexport interface SeriesChartSeries<TRow extends object = object> {\n /** The row key this line reads — and the `--color-<key>` it is painted with, so it\n * must be a CSS identifier. Build keys out of data with {@link seriesKey}. */\n key: string;\n label: ReactNode;\n /** Any CSS colour the chart shell accepts (hex, rgb/hsl, `var(--token)`). Default:\n * the kit's categorical ramp by position, `paletteFor(index)`. */\n color?: string;\n /** Marks the PAIRED line of a pair — the return stroke against the out-stroke, the\n * reference against the measurement. Shorthand for `dash: 1`. */\n dashed?: boolean;\n /** Which of {@link STROKE_PATTERNS} this line takes, for charts where the stroke says\n * WHICH QUANTITY and the colour says WHICH MEASUREMENT.\n *\n * Or an SVG `stroke-dasharray` string of the caller's own, for a pattern the five do\n * not have: keksdose's `\"4 3\"`, a tighter dash than the ladder's `\"5 4\"` that its\n * hand-drawn recharts lines used before the kit. The legend\n * entry ({@link seriesLegendEntries}) carries the same string, so it draws the same\n * pattern. */\n dash?: number | string;\n /** `stepAfter`, for a whole-number channel that jumps rather than travels — a\n * straight line between index 0 and index 1 draws an index of 0.5, which does not\n * exist. Drawn in the {@link STEP_DASH} pattern, whatever `dash` says. */\n step?: boolean;\n /** Which of `axes` this line is measured on. Default: `\"y\"`, the single one. */\n axis?: string;\n /**\n * The mark. `\"line\"` (the default) is what every chart before 0.8.0 drew. `\"bar\"` and\n * `\"area\"` are read as a LENGTH from zero, so the axis they stand on always includes\n * zero (see `SeriesChartAxis.includeZero`) and the zoom treats them differently (see\n * `defaultZoomAxes`). Bars without a `stack` stand side by side in each slot — the\n * grouped bars of keksdose's payee report.\n */\n type?: SeriesChartType;\n /**\n * Bars or areas with the same `stack` are drawn on top of each other and the axis is\n * fitted to their SUM (positive and negative layers apart, like recharts'\n * `stackOffset=\"sign\"`). keksdose's spending-by-category area. Ignored on a line:\n * recharts cannot stack one.\n */\n stack?: string;\n /**\n * Marks on the line's (or area's) points. `true` rings every sample — the price\n * history, where a shop has a value only on the days somebody shopped there and the\n * dots are the only thing saying which points were MEASURED. A function decides per\n * point: `true` for the default dot, `false`/`null` for none, or any SVG node drawn\n * as-is at `point.cx`/`point.cy` — a buy/sell marker on keksdose's paper price.\n * Never called for a point with no value. Bars have no points, and ignore it.\n * `point.row` is the caller's own row, typed as the chart's rows are (0.53).\n */\n dot?: boolean | ((point: SeriesChartPoint<TRow>) => ReactNode);\n /** Line (or area outline) weight in px. Default 2, or 1.5 for a `step`. keksdose\n * draws the subject of a chart at 2.5 and the reference it is read against at 1.5. */\n strokeWidth?: number;\n /** `\"linear\"` for a line that must not look smoothed — keksdose's cash-buffer\n * PROJECTION, a straight extrapolation that a monotone curve would dress up as data.\n * Default `\"monotone\"`; `step` wins over both. */\n curve?: \"monotone\" | \"linear\";\n /** An area's or bar's fill opacity. Default: 1 for a bar, 0.55 for a stacked area\n * (the layers must stay tellable apart where they meet) and 0.2 for a single one. */\n fillOpacity?: number;\n /**\n * The dot that follows the pointer along a line or an area. `false` takes it off a\n * series that is not a measurement — keksdose's cash-buffer PROJECTION, where a hover\n * ring on the extrapolated line reads as a sampled value (`cash-buffer-chart.tsx`).\n * `{ r }` sets its radius. Default: recharts' dot. Bars have none, and ignore it.\n */\n activeDot?: boolean | { r?: number };\n /**\n * The shortest a bar of this series is drawn, in px — recharts' `minPointSize`. A\n * zero or a value too small to see keeps a visible stub, so an empty slot still reads\n * as a slot with a value rather than a gap: keksdose's weekday pattern, where a\n * Sunday with no spending drew a 2% stub by hand. Only the DRAWING changes: the axis\n * is fitted to the values, and the tooltip, the keyboard stops and every accessible\n * name still say 0. A hole (no value in the row) stays a hole. Overrides the chart's\n * {@link SeriesChartProps.minBarLength}; `0` turns it off for this series. Meant for\n * unstacked bars — in a `stack` the stub is drawn over the layer above it. Lines and\n * areas ignore it.\n */\n minBarLength?: number;\n}\n\n/** What a series draws. See {@link SeriesChartSeries.type}. */\nexport type SeriesChartType = \"line\" | \"bar\" | \"area\";\n\n/** One point of a series, as a `dot` function is handed it. `TRow` is the chart's row\n * type (0.53); without one, `row` is a {@link SeriesChartRow}, as before. */\nexport interface SeriesChartPoint<TRow extends object = object> {\n /** The series' key. */\n key: string;\n /** The row's position in `rows`. */\n index: number;\n /** The caller's own row, with everything the chart did not plot still in it: the very\n * object in `rows`, typed as `rows` is. */\n row: SeriesChartRowOf<TRow>;\n /** The abscissa in the caller's terms: the number, the category, or (time) a Date. */\n x: SeriesChartXValue;\n value: number;\n /** Where the point is drawn, in the chart's pixels. */\n cx: number;\n cy: number;\n /** The series' paint, `var(--color-<key>)`. */\n color: string;\n}\n\n/** A row of a series chart: one abscissa value and the series' values at it. Anything\n * else in it (a raw ISO period for a drilldown) rides along untouched and is handed\n * back in {@link SeriesChartPoint.row} and {@link SeriesChartHit.row} — typed as the\n * caller's rows are since 0.53, and as this where their type names no keys. */\nexport type SeriesChartRow = Readonly<Record<string, unknown>>;\n\n/**\n * The row a hit or a point hands back, for a chart whose rows are `TRow[]` (0.53, keksdose\n * after 0.52): `TRow` itself, so a drilldown reads `hit.row.rawPeriod` as the string it\n * is. A {@link SeriesChartRow} where `TRow` names no keys — `object`, the default, which\n * keeps `SeriesChartHit` and `SeriesChartPoint` without a type argument what they were, and\n * the `object[]` rows an app passes today; `{}`; and `any` or `never` (`rows={[]}`), which\n * are both assignable to `null` while no object type is.\n *\n * Both tests take `TRow` in the CHECKED position, never in the `extends` one, so TypeScript\n * measures every type below as covariant in it (`SeriesChartSeries`, through `dot`'s\n * parameter, contravariant) and relates two of them by their type arguments alone: a\n * `SeriesChartHit<Month>` is a `SeriesChartHit`, and a handler or a series typed without an\n * argument fits a chart of `Month` rows, though an interface has no index signature and is\n * not, field by field, a `SeriesChartRow`. Written `object extends TRow ?`, the type is\n * invariant and both of those stop type-checking.\n */\ntype SeriesChartRowOf<TRow> = [TRow] extends [null]\n ? SeriesChartRow\n : [keyof TRow] extends [never]\n ? SeriesChartRow\n : TRow;\n\n/** An abscissa value: a number (`x.type: \"number\"`), a category (a string, a number or\n * a Date standing for a period), or a time (a Date, epoch ms or an ISO string). */\nexport type SeriesChartXValue = number | string | Date;\n\n/** Ticks a caller decides — a list, or a function of the domain on show, so a zoom\n * window gets ticks from the same rule instead of none. */\nexport type SeriesChartTickValues<T> = readonly T[] | ((domain: [number, number]) => readonly T[] | undefined);\n\ninterface SeriesChartAxisShape {\n id: string;\n /**\n * Which side of the plot the ticks stand on. Left unless said otherwise — and said\n * otherwise for the right-hand chart of a FACING pair (see `facingAxes`), whose\n * scales go on the outside so neither column of numbers stands between two pictures\n * being compared.\n */\n orientation?: \"left\" | \"right\";\n /** Tints the ticks — and the title too, when exactly one series is measured on this\n * axis (see {@link soleSeriesColor}). */\n color?: string;\n /** What the TICKS need, in px. The title's strip is added on top. Default 48. */\n width?: number;\n /**\n * The unit, bare — `\"mm/s\"`. The title says it while the axis is drawn; when it is not\n * (`hide`, or over the chart's axis budget — see {@link SeriesChartProps.maxVisibleAxes})\n * the series on it say it instead, as \"Velocity (mm/s)\": in the tooltip of a chart\n * whose budget hid the axis, and in the legend {@link seriesLegendEntries} builds when\n * handed the axes. Default: the parenthesised tail of `title` (\"Load (N)\" → \"N\").\n * `\"\"` for a quantity with no unit whose title merely ends in brackets.\n */\n unit?: string;\n /**\n * Pin the scale instead of fitting it to this chart's data. For a ROW of charts\n * read against each other: auto-fitted, a 200 N loop and a 2000 N one draw the\n * identical picture, and the comparison the layout promises is the one it fails.\n */\n domain?: [number, number];\n /** A tick, formatted — as a BARE number. The unit is said once, in the title; the\n * tooltip gets it from `valueFormat`. Default: `Intl.NumberFormat` in the kit's\n * locale, up to two fraction digits. */\n format?: (value: number) => string;\n /**\n * The tick values, instead of the round ones the chart picks. For a grid the DATA\n * dictates — keksdose's price axes tick on whole cents (`pricePaddedDomain`), where a\n * 1/2/5 ladder would print €1.25 under a formatter that can only say €1.3. Values\n * outside the domain on show are dropped; a function is asked again for every zoom\n * window, so the cent grid can refine with it.\n */\n tickValues?: SeriesChartTickValues<number>;\n /**\n * Keep zero inside the fitted band. On by default for an axis carrying a bar or an\n * area — their length IS the value, and a truncated baseline draws 40 as three times\n * 20 — and off for lines, whose shape is the point (a stock price anchored at zero is\n * a hairline). A pinned `domain` is left alone either way.\n */\n includeZero?: boolean;\n /**\n * Tick only on whole numbers — the y counterpart of `SeriesChartX.integerTicks`, and\n * what keksdose's user-count axis (`metrics-panel.tsx`, `wholeTicks`) and its runway\n * in days (`cash-buffer-chart.tsx`, `wholeDayTicks`) each wrote by hand: a band of\n * [0, 3.1] users is ticked 0 1 2 3, not 0 0.5 1 … 3, and a short runway is not ticked\n * 0 / 0.5 / 1 under a rounding formatter that prints \"1\" twice. A (zoom) window that\n * holds no whole number falls back to the ordinary ticks rather than to none.\n *\n * AUTOMATIC by default — on when every value this axis carries is a whole number\n * (counts), because that is where a half tick is a value no sample can have, and it\n * changes nothing on a span wider than about eight, which already ticks on whole\n * steps. `true` forces it over fractional data (days of runway computed as 43.7);\n * `false` keeps fractional ticks for a continuous quantity that merely happens to be\n * whole in this sample. `tickValues` wins over either.\n */\n integerTicks?: boolean;\n}\n\n/**\n * A y axis — and a VISIBLE one says what it measures.\n *\n * A union rather than an optional field, so the rule is the type's: a column of numbers\n * whose quantity and unit are not written down is a column somebody reads as whatever\n * they expected. `title: \"\"` is the explicit opt-out (the right-hand chart of a facing\n * pair, whose neighbour already said it). A HIDDEN axis scales its lines and draws\n * nothing, so there is nowhere for a title to go.\n */\nexport type SeriesChartAxis = SeriesChartAxisShape & ({ title: string; hide?: false } | { title?: string; hide: true });\n\n/**\n * What a tick or the tooltip heading of the abscissa is handed besides its position —\n * the value in the caller's own terms, which on a category or time axis is not the\n * number the plot runs on.\n */\nexport interface SeriesChartXTick {\n /** The number itself, the row's category, or (time) a Date. */\n value: SeriesChartXValue;\n /** The slot, on a category axis: the row's index in `rows`. */\n index?: number;\n /** On a time axis: what one step of the ticks on show is, so a label can say as much\n * as it means — a month start as \"Mar 26\", a midnight as \"14 Mar\". */\n unit?: TimeTickUnit;\n}\n\nexport interface SeriesChartX {\n /**\n * What the abscissa is.\n *\n * - `\"number\"` (the default) — a number line, and all a chart before 0.8.0 could draw.\n * - `\"category\"` — PERIODS or names, one evenly spaced slot per row, in row order:\n * keksdose's months, quarters and budget categories, which it used to hand recharts\n * preformatted. The values stay the caller's own — `\"2026-05\"`, a Date for the\n * month, a category name — and need not be sortable, unique or numeric. The plot\n * runs on the slot INDEX, which is what lets it zoom: a drag across the third to the\n * ninth month shows those months, a tick on each whole slot and the bars clipped at\n * the edge. What else zooms depends on the MARKS, not the axis — see `zoomAxes`.\n * - `\"time\"` — real TIME: a Date, epoch ms or an ISO string per row, placed by when\n * it happened. keksdose's price history and cash buffer, where a slot per row would\n * draw two receipts a day apart and two five months apart the same width. Ticks fall\n * on calendar boundaries (midnights, Mondays, month and quarter starts, new years)\n * in local time; a date-only ISO string is LOCAL midnight, not the UTC one\n * `new Date(\"2026-05-01\")` gives, which lands on the previous day west of Greenwich.\n * Zooms like a number line.\n */\n type?: \"number\" | \"category\" | \"time\";\n /** Row key of the abscissa. Default `\"x\"`, which is what {@link mergeSeries} writes. */\n key?: string;\n /** What the abscissa is, with its unit. Drawn under the axis. */\n title?: string;\n /**\n * A tick, formatted — bare, like the y axes'.\n *\n * `value` is the POSITION on the number line the plot runs on — the number itself,\n * epoch ms, or the slot index — so the one-argument formatters every chart before\n * 0.8.0 passes keep their meaning, and a time axis' `(ms) => …` is the tickFormatter\n * keksdose already has. The caller's own value (the category, the Date) is `tick.value`.\n * Default: the kit's number format; a category as is (a number formatted, a Date as a\n * medium date); a time as much of the date as the tick step means.\n */\n format?: (value: number, tick: SeriesChartXTick) => string;\n /**\n * Whether this chart prints the abscissa's ticks. On by default; off for every chart\n * of a stack sharing one x window but the bottom one, which prints them for all. It\n * costs no alignment: the x mapping is decided by the margins and the y bands.\n */\n ticks?: boolean;\n /** The tooltip's heading. Default: `format` — or, on a time axis, a medium date (with\n * the time for hourly data), since a tick's \"Mar 26\" is not which day it was. */\n label?: (value: number, tick: SeriesChartXTick) => ReactNode;\n /** The ticks instead of the automatic ones, in the caller's terms: numbers, the\n * categories to label, or instants. See `SeriesChartAxis.tickValues`. */\n tickValues?: SeriesChartTickValues<SeriesChartXValue>;\n /**\n * Tilt the tick labels by this many degrees — negative rises to the right. For long\n * category names that do not fit side by side: keksdose's budget performance draws its\n * categories at −45° (`budget-performance-tab.tsx`). The label is anchored by its END\n * for a negative angle and its START for a positive one, so it hangs off the tick\n * instead of being centred across it; the anchor is physical, like the plot (see\n * `ChartContainer`), so it is the same in RTL. The band under the axis grows to the\n * rotated height of the longest label on show, estimated from its length (at most\n * 120 px × the text size's scale, past which a label is clipped). Default 0.\n */\n tickAngle?: number;\n /**\n * On a `\"number\"` axis, tick only on whole numbers: a step of 1 at the least, so a\n * five-point index series reads 0 1 2 3 4 rather than 0 0.5 1 … 4 — ticks at\n * positions no row can have (keksdose's short step series). A zoom window that holds\n * no whole number falls back to the ordinary ticks rather than to none.\n *\n * AUTOMATIC by default — on when every row's x is a whole number — because that is\n * exactly the case the half ticks are wrong in, and it changes nothing elsewhere: a\n * span wider than about eight already ticks on whole steps. `false` for a continuous\n * quantity that merely happens to be sampled on whole numbers (1 Hz steps) and whose\n * zoom should still be ruled in fractions; `true` to force it over rows that are not.\n * Ignored on category (already one tick per slot) and time axes.\n */\n integerTicks?: boolean;\n}\n\n/** Where the tooltip goes — see {@link SeriesChartTooltip.placement}. */\nexport type SeriesChartTooltipPlacement = ChartTooltipPlacement;\n\n/**\n * The placement a chart actually uses: its own, else the provider's, else `\"cursor\"`;\n * `\"auto\"` is `\"above\"` on a phone (`phone`: below `sm`) and `\"cursor\"` from `sm` up.\n */\nexport function resolveTooltipPlacement(\n own: SeriesChartTooltipPlacement | undefined,\n fromProvider: SeriesChartTooltipPlacement | undefined,\n phone: boolean,\n): \"cursor\" | \"above\" | \"below\" {\n const wanted = own ?? fromProvider ?? \"cursor\";\n return wanted === \"auto\" ? (phone ? \"above\" : \"cursor\") : wanted;\n}\n\n/** Room for the tooltip beyond the chart — see {@link SeriesChartProps.tooltip}. */\nexport interface SeriesChartTooltip {\n /**\n * Where the values under the pointer are shown (keksdose #359: on a phone the box\n * sat under the finger, on the very data it was reporting).\n * - `\"cursor\"` (the default): the floating box that follows the pointer.\n * - `\"above\"` / `\"below\"`: a READOUT row — the same heading and values, flat — in\n * room reserved over or under the plot from the first render, so nothing jumps on\n * the first tap. It follows hover, a tap and the keyboard's stops; the cursor line\n * and the active dot stay on the plot, and no box floats. Idle, it lists the series\n * with \"—\" under the x axis' title. The row is taken out of the chart's `height`\n * (the plot gets shorter, the page around it does not move).\n * - `\"auto\"`: `\"above\"` below Tailwind's `sm` (640 px), `\"cursor\"` from there up.\n *\n * Default: the provider's `chartTooltipPlacement`, else `\"cursor\"`.\n *\n * The row is deliberately NOT an `aria-live` region: scrubbing a line announces a\n * value per pixel of travel. A keyboard reader already hears each stop's name\n * (\"period — series: value\") from the stop itself, and the row stays in the\n * document for a screen reader to read on its way past.\n */\n placement?: SeriesChartTooltipPlacement;\n /** Let the tooltip run past the chart's own box on that axis instead of recharts\n * clamping it inside. Default: `{ x: true }` when `boundary` is set, else neither. */\n allowEscapeViewBox?: { x?: boolean; y?: boolean };\n /**\n * The element that actually CLIPS the chart — usually a horizontal-scroll wrapper\n * around a chart wider than the card. The tooltip then flips to the left of the cursor\n * when it would spill past that element's visible right edge (see\n * `ChartTooltipContent`'s `boundaryRef`), rather than against the wide chart's far edge\n * the reader has not scrolled to. keksdose's budget performance, which keeps a scroll\n * wrapper and a per-category `minWidth` (`budget-performance-tab.tsx`).\n */\n boundary?: RefObject<HTMLElement | null>;\n}\n\n/**\n * A vertical segment in data coordinates — two y at one x, which a row-per-abscissa\n * chart structurally cannot draw. For CLOSING a shape the series already drew: the\n * turnarounds of a hysteresis loop, where the abscissa stands still while the value\n * falls from one branch to the other.\n */\nexport interface SeriesChartSpan {\n /** Distinct within the chart. */\n key: string;\n /** Which y axis `from`/`to` are measured on. Default `\"y\"`. */\n axis?: string;\n x: number;\n from: number;\n to: number;\n /** Default: `var(--text-muted)`. */\n color?: string;\n}\n\n/** The colours a reference or a marker can take by name — the kit's semantic tokens,\n * so a threshold reads the same on every chart and flips with the theme. */\nexport type SeriesChartTone =\n \"muted\" | \"brand\" | \"income\" | \"expense\" | \"net\" | \"success\" | \"warning\" | \"danger\" | \"info\";\n\nconst TONE_COLOR: Record<SeriesChartTone, string> = {\n muted: \"var(--text-muted)\",\n brand: \"var(--brand)\",\n income: \"var(--money-income)\",\n expense: \"var(--money-expense)\",\n net: \"var(--money-net)\",\n success: \"var(--success)\",\n warning: \"var(--warning)\",\n danger: \"var(--danger)\",\n info: \"var(--info)\",\n};\n\n/**\n * A line across the whole plot at one value: a threshold, a target, an event.\n *\n * keksdose's cash buffer draws \"one month of runway\" across at y = 30 and the projected\n * depletion date down at its x. Unlike a {@link SeriesChartSpan}, which closes a shape\n * in data coordinates, a reference spans the plot, whatever the zoom.\n *\n * A reference is part of the FITTED band: one outside the data widens the axis to show\n * it, because a threshold the reader cannot see is not a threshold. A pinned domain or a\n * zoom window does not widen — there it is discarded when outside, like a span.\n */\nexport interface SeriesChartReference {\n /** Distinct within the chart. Default: its position in the list. */\n key?: string;\n /** `\"x\"` for a vertical line at an abscissa, otherwise the id of the y axis the value\n * is measured on. Default `\"y\"`, the single one — so no y axis may be called `\"x\"`. */\n axis?: string;\n /** An abscissa in the x axis' own terms (a category, a Date) for `axis: \"x\"`, a\n * number on that axis otherwise. A category the rows do not have draws nothing. */\n value: SeriesChartXValue;\n /** Written along the line, inside the plot at its top-left. SVG text: a string. */\n label?: string;\n /** Default `\"muted\"`. `color` wins over it. */\n tone?: SeriesChartTone;\n color?: string;\n /** Which of `STROKE_PATTERNS`. Default 1, dashed: a reference is not data, and a\n * solid line reads as a series nobody put in the legend. */\n dash?: number;\n}\n\n/**\n * A single labelled point — today's figure on keksdose's cash buffer, the month the\n * projection runs dry. For a mark on EVERY sample, or on the samples that meet a test,\n * use the series' `dot` instead; a marker is for a point that is a fact of its own.\n * Fitted like a reference: it widens the band it would otherwise fall outside of.\n */\nexport interface SeriesChartMarker {\n /** Distinct within the chart. Default: its position in the list. */\n key?: string;\n /** In the x axis' own terms, like a reference's `value`. */\n x: SeriesChartXValue;\n y: number;\n /** The y axis `y` is measured on. Default `\"y\"`. */\n axis?: string;\n /** Written above the point. */\n label?: string;\n /** Default `\"brand\"`. `color` wins over it. */\n tone?: SeriesChartTone;\n color?: string;\n /** Radius in px. Default 4.5. */\n r?: number;\n}\n\n/** What a click on the plot picked. `TRow` is the chart's row type (0.53); without one,\n * `row` is a {@link SeriesChartRow}, as before. */\nexport interface SeriesChartHit<TRow extends object = object> {\n /** The row's position in `rows`. */\n index: number;\n /** The caller's own row — with its `rawPeriod`, id or whatever the drilldown needs: the\n * very object in `rows`, typed as `rows` is, so it is read without a cast. */\n row: SeriesChartRowOf<TRow>;\n x: SeriesChartXValue;\n /** The series, when the click landed ON a bar. A click anywhere else picks the slot\n * (the period), not a series. */\n key?: string;\n}\n\n/**\n * The props of {@link SeriesChart} and {@link StaticSeriesChart}, for rows of type `TRow`.\n *\n * `TRow` is inferred from `rows` (0.53, keksdose after 0.52), and what the chart hands back\n * — `hit.row` in `onPointClick`, `point.row` in a series' `dot` — is that type, so a\n * drilldown reads its own fields without narrowing an `unknown`. Without a type argument,\n * `SeriesChartProps` is what it was: any object is a row, and a row comes back as a\n * {@link SeriesChartRow}. So is `ComponentProps<typeof SeriesChart>`, which reads the\n * constraint, `object`. A series, a handler or a `dot` typed without an argument fits a\n * chart of typed rows too.\n */\nexport interface SeriesChartProps<TRow extends object = object> {\n /**\n * One row per abscissa value. A missing key is a hole (see `connectNulls`).\n *\n * Any object (0.52, refactor audit 2026-10-30, API-2): an `interface` has no index\n * signature, so a typed sweep did not fit `SeriesChartRow` and Kurvenschmiede cast its\n * Ackermann rows `as unknown as Record<string, number>[]`. The chart reads the keys\n * `series` and `x` name, and hands the row back typed as these are (0.53).\n */\n rows: readonly TRow[];\n series: readonly SeriesChartSeries<TRow>[];\n /** Default: one untitled axis, `\"y\"`. */\n axes?: readonly SeriesChartAxis[];\n x?: SeriesChartX;\n /** A value in the tooltip, where a number stands on its own and needs its unit.\n * Default: `Intl.NumberFormat` in the kit's locale. */\n valueFormat?: (value: number) => string;\n /**\n * The chart's height: a CSS length, a Tailwind height class, or px. Default `h-72`\n * (18rem). The empty state takes it too, so a chart losing its last line does not\n * relayout the page under it.\n *\n * - **A CSS length** (0.32) — `\"20rem\"`, `\"min(20rem, 60dvh)\"` — set inline. The form\n * for a height that should grow with the text size and still stop at the screen\n * (docs/text-size-harmonization.md §10.10): `min(30rem, 60dvh)` is 480 px at Normal\n * on a desktop and never more than 60 % of a phone at Extra large, where a scaled\n * 480 px would be 720.\n * - **A Tailwind class** — `\"h-72\"`, `\"h-64 md:h-80\"` — as before.\n * - **A number** is px, set inline, and does NOT follow the text size: kept for a\n * height the caller holds as a number (keksdose's report charts take\n * `height = 260` as a prop). Prefer `\"16.25rem\"`, or a `min()` with a viewport cap.\n */\n height?: ChartHeight;\n /** Bridge holes left by sources sampled on different grids. See {@link mergeSeries}. */\n connectNulls?: boolean;\n /** Shown, centred at the chart's height, instead of an empty chart. Default: the\n * `seriesChart.empty` label. `null` shows nothing. */\n empty?: ReactNode;\n /**\n * Milliseconds for a line to draw itself in. Off by default: a chart beside a live\n * editor re-renders on every keystroke, and an animation restarted mid-flight reads\n * as the curve twitching. Turn it on where series come and go by choice.\n */\n animationMs?: number;\n spans?: readonly SeriesChartSpan[];\n /** Lines across the plot at one value. */\n references?: readonly SeriesChartReference[];\n /** Single labelled points. */\n markers?: readonly SeriesChartMarker[];\n /**\n * Which axes a drag may zoom: `\"both\"`, `\"x\"`, `\"y\"` or `\"none\"`. Default: read off\n * the marks — see `defaultZoomAxes` (lines both, areas x, bars none). An axis carrying\n * bars or areas never takes a DRAGGED y window: it refits to the x window, from zero.\n * Ignored by `StaticSeriesChart`, which does not zoom.\n */\n zoomAxes?: ZoomAxesSetting;\n /**\n * A click on the plot: the slot under the pointer, and the series when it landed on a\n * bar. keksdose's drilldowns — a payee's month, a budget line, a spending category.\n * A drag that zoomed is not a click.\n *\n * The keyboard's stops are there either way (0.52, DSP-5): one per bar, or per slot of\n * a chart without bars, named \"period — series: value\", behind ONE tab stop. With this\n * they are buttons that Enter and Space activate; without, images to read.\n */\n onPointClick?: (hit: SeriesChartHit<TRow>) => void;\n /** Where the tooltip may go: for a chart inside a scroll wrapper. See\n * {@link SeriesChartTooltip}. */\n tooltip?: SeriesChartTooltip;\n /**\n * The most y axes the chart DRAWS: a total, or `{ left, right }` per side. Axes over it\n * are drawn as `hide: true` ones are — they still scale their lines and the zoom still\n * refits them, but they draw no ticks or title and reserve no width — in declaration\n * order, so the first axis of each side is the last to go (`series-chart-budget.ts`).\n * The series on a hidden axis say its unit instead (see {@link SeriesChartAxis.unit}).\n * Default: no cap — only the automatic one of `axisBudget`.\n */\n maxVisibleAxes?: SeriesChartAxisBudget;\n /**\n * `\"auto\"` (the default): a chart so narrow that its axes' bands would leave the plot\n * under 160 px (`MIN_PLOT_WIDTH`, × the text size's scale) draws ONE axis a side —\n * lenkbank's four-axis curve plot on a phone, whose plot was 10 px wide. And a chart\n * with an axis on EACH side that one a side still leaves too narrow (0.32: at 150 % a\n * 390 px phone's plot kept about 80 px between its two bands) drops the right-hand,\n * secondary axis too. Measured on the chart's own box (`ResizeObserver`), and applied\n * on top of `maxVisibleAxes`. Either way the series on an axis it hid say the axis'\n * unit in the tooltip and the readout (\"Rack load (N)\"), and in a legend built by\n * {@link seriesLegendEntries} with `onAxisBudget`'s ids.\n *\n * On by default because it cannot touch a layout that works: it needs a plot that\n * would otherwise be under 160 px — a four-axis chart below about 440 px at Normal, a\n * two-left-axis one below about 300, a one-a-side one below about 290 — and the\n * left-hand axis always stays. A chart with one axis (each chart of a facing pair,\n * every single-axis chart) is never budgeted, at any width. `\"off\"` keeps every\n * declared axis whatever the width: for a stack of multi-axis charts that must keep\n * identical bands, or a caller budgeting itself. Without layout (jsdom, SSR) nothing is\n * measured and nothing is hidden.\n */\n axisBudget?: \"auto\" | \"off\";\n /**\n * The ids of the axes the budget hid (not those declared `hide`), every time that set\n * changes — for a legend that says their units: pass it to {@link seriesLegendEntries}\n * as `budgeted`. Called after the render that hid them; empty once the chart is wide\n * again.\n */\n onAxisBudget?: (hidden: readonly string[]) => void;\n /** Supplied by `withChartZoom` and by nothing else. */\n zoom?: ZoomBinding;\n /** Per-chart strings over `<UiKitProvider labels={{ seriesChart }}>`. */\n labels?: LabelOverride<SeriesChartLabels>;\n /** BCP 47 tag for the default number formats. Default: the provider's. */\n locale?: string;\n /**\n * The chart's name. The chart is a `role=\"figure\"` (0.52, refactor audit 2026-10-30,\n * DSP-5), and a figure is found and told apart by its name — \"Net worth\", \"Load over\n * travel\". Its values are read stop by stop (see {@link SeriesChartProps.onPointClick}).\n *\n * Default (0.55, Kurvenschmiede 0.52 adoption): the axes' titles — the drawn y axes' as\n * a list in the chart's locale, over the abscissa's: \"Rack force (N) over Travel (mm)\"\n * (`seriesChart.nameFromAxes`). A chart without an x title — an upper chart of a stack —\n * is named by its ordinates alone; one without a titled y axis has no name, as before.\n */\n \"aria-label\"?: string;\n /**\n * What the picture SHOWS, in a sentence — \"Spending rose 12 % in May, led by rent.\" —\n * the figure's accessible description: a line, an area and a ruler are nothing a screen\n * reader can say. Followed, on a zoomable chart, by the drag gesture (`zoomHint`). Not\n * drawn; a caption the eye should read too belongs in the page.\n */\n description?: string;\n /** Onto the chart's root (`ChartContainer`) — e.g. an app's own grid ink. */\n className?: string;\n /** The shortest bar drawn, in px, for every bar series that does not set its own\n * {@link SeriesChartSeries.minBarLength}. Drawing only: domain, tooltip and names\n * keep the real value. Default: none — a zero draws nothing. */\n minBarLength?: number;\n /**\n * The most rows the chart hands recharts (0.34, KS U2). A longer table is THINNED, by\n * envelope: cut into buckets, and from each the row where each drawn series is lowest\n * and the row where it is highest, plus each series' first and last sample — so every\n * line still reaches every peak and dip the table has, and a tone faster than the\n * buckets draws as the band it fills, never as the slow wave a stride would alias it\n * into. Nothing is averaged or invented; every point drawn is one of `rows`. There is\n * no stride option, on purpose.\n *\n * Opt-in. Default: none — every row is drawn, as before. Kurvenschmiede draws 2000 for\n * a 200-second profile at 1 kHz; a few thousand is about what a plot's pixels can show.\n *\n * - **Zoom** thins the window on show (with one row past each edge), so zooming in\n * draws more of the samples there — all of them, once the window holds fewer than\n * `maxRows` — rather than the same rows larger. That needs an abscissa that never\n * decreases; where it doubles back (a loop against position) the whole table is\n * thinned once, and the abscissa is enveloped too, so the path's turning points stay.\n * - **Fitting** is not thinned: the axes, the zoom's refit and the automatic whole\n * ticks read every row, so a pinned or fitted band is the same either way.\n * - **Indices** stay the caller's: a `dot` function's `point.index` and a click's\n * `hit.index` are positions in `rows`, not in the rows drawn.\n * - **A category axis** (`x.type: \"category\"`) is never thinned: a slot is a period, and\n * a period left out is a gap. Meant for lines and areas; stacked layers are each\n * enveloped on their own.\n *\n * The budget is a cap for any `maxRows` of at least 2 + 4 × the drawn series (the\n * fewest rows an envelope can be drawn with); a smaller one is raised to that.\n */\n maxRows?: number;\n}\n\n/** A series' name with its unit after it: \"Velocity (mm/s)\" — unless the name already\n * ends with it. lenkbank's motion series carry \"(mm/s)\" in their label for the desktop\n * tooltip, where every axis is drawn; the budget then read \"… (mm/s) (mm/s)\" (0.15.1).\n * A label that says its unit keeps saying it once, whichever of the two an app chose. */\nfunction withUnit(label: ReactNode, unit: string | undefined): ReactNode {\n if (!unit) return label;\n if (typeof label === \"string\" || typeof label === \"number\") {\n const text = String(label);\n return text.trimEnd().endsWith(`(${unit})`) ? label : `${text} (${unit})`;\n }\n return (\n <>\n {label} ({unit})\n </>\n );\n}\n\n/**\n * The name of a chart the caller does not name (0.55, Kurvenschmiede 0.52 adoption): the\n * titles of the drawn y axes as a list in `locale`, over the abscissa's title, in the\n * catalogue's words. Kurvenschmiede's SeriesChart wrapper named every chart so: its axes\n * carry their titles and units anyway, and a name written a second time at each call site\n * drifts from the axes it describes. A hidden axis and an untitled one\n * (`title: \"\"`, a facing pair's second chart) say nothing, and with no titled y axis there\n * is no name: an abscissa alone does not say what is measured. The DECLARED axes, not the\n * budget's: the name does not change with the chart's width.\n */\nfunction axesName(\n axes: readonly SeriesChartAxis[],\n abscissa: string | undefined,\n locale: string | undefined,\n nameFromAxes: SeriesChartLabels[\"nameFromAxes\"],\n): string | undefined {\n const titles = axes.flatMap((axis) => (!axis.hide && axis.title ? [axis.title] : []));\n if (titles.length === 0) return undefined;\n const ordinates = new Intl.ListFormat(locale, { type: \"conjunction\" }).format(titles);\n return nameFromAxes(ordinates, abscissa || undefined);\n}\n\n/** Where a legend learns which axes are not drawn — see {@link seriesLegendEntries}. */\nexport interface SeriesLegendAxes {\n /** The chart's axes. A series on one that is `hide`, or `budgeted`, says its unit. */\n axes?: readonly SeriesChartAxis[];\n /** What the chart's `onAxisBudget` last said. */\n budgeted?: readonly string[];\n}\n\n/**\n * The `ToggleLegend` entries for a chart's FULL series list — colours resolved the way\n * the chart resolves them, and a stroke mark for a line drawn in a pattern (dashed,\n * step) so the key promises the stroke the plot draws. A bar or an area is a swatch.\n * Pair with {@link visibleSeries} for the chart itself.\n *\n * Handed the chart's `axes` (and the `budgeted` ids its `onAxisBudget` reports), a\n * series whose axis is not drawn says the unit that axis would have: \"Velocity (mm/s)\"\n * — see {@link SeriesChartAxis.unit}. Without them, the labels are as given.\n */\nexport function seriesLegendEntries<TRow extends object>(\n // Generic only so a typed list fits (0.53): `SeriesChartSeries<Month>` is not a\n // `SeriesChartSeries`, whose `dot` would be handed rows that are not `Month`s.\n series: readonly SeriesChartSeries<TRow>[],\n { axes, budgeted }: SeriesLegendAxes = {},\n): LegendEntry[] {\n const undrawn = new Map<string, string | undefined>();\n for (const axis of axes ?? []) {\n if (axis.hide || budgeted?.includes(axis.id)) undrawn.set(axis.id, axisUnit(axis));\n }\n return series.map((entry, index) => {\n // A custom dash array goes to the legend as it is, so the swatch draws what the plot does.\n const own = entry.dash ?? (entry.dashed ? 1 : 0);\n const dash = entry.step ? STEP_DASH : own;\n const line = (entry.type ?? \"line\") === \"line\";\n return {\n key: entry.key,\n label: withUnit(entry.label, undrawn.get(entry.axis ?? DEFAULT_Y_AXIS)),\n color: entry.color ?? paletteFor(index),\n ...(line && dash !== 0 ? { marker: \"stroke\" as const, dash } : {}),\n };\n });\n}\n\n/** The number format every default falls back to. */\nfunction useDefaultFormat(localeProp: string | undefined): (value: number) => string {\n const locale = useKitLocale(localeProp);\n return useMemo(() => {\n const format = new Intl.NumberFormat(locale, { maximumFractionDigits: 2 });\n // U+2212 on a negative tick and in the tooltip (0.49, KIT-1).\n return (value: number) => formatWithMinus(format, value);\n }, [locale]);\n}\n\n/** The Y-axis list a chart draws when the caller gave none. */\nconst ONE_UNTITLED_AXIS: SeriesChartAxis[] = [{ id: DEFAULT_Y_AXIS, title: \"\" }];\n\n/** The two numbers every mark type needs to agree on for the chart to read as one. */\nconst LINE_WIDTH = 2;\nconst STEP_WIDTH = 1.5;\n\n/** Bars round their FREE end only, and a stacked bar has none but the top layer's —\n * which recharts cannot tell apart per cell, so stacks stay square. */\nconst BAR_RADIUS: [number, number, number, number] = [3, 3, 0, 0];\n\n/**\n * One keyboard stop: a bar, or (a chart with no bars) a whole slot. `from`/`to` bound its\n * slot on the plotted number line — half way to each neighbour, or to the edge of the\n * window on show.\n */\ninterface PointStop {\n index: number;\n /** The bar's series; absent for a slot. */\n key?: string;\n from: number;\n to: number;\n /** The accessible name: where it is and what it says. Asked only of a stop that is\n * drawn — see {@link ALL_STOPS_UP_TO}. */\n name: () => string;\n}\n\n/**\n * Up to this many stops, every one is drawn; past it, only the roving one, its two\n * neighbours and the two ends (0.52, DSP-5) — every stop is still reached, by the arrows,\n * Home and End. Since every chart has stops, a measurement chart has one per row:\n * Kurvenschmiede draws 2000-row profiles (`maxRows`), and 2000 named `<rect>`s, each\n * named through `Intl` on every render, are a DOM and an accessibility tree nobody walks\n * one by one. A year of months, or of weeks, stays whole for browse mode.\n */\nconst ALL_STOPS_UP_TO = 100;\n\n/** What a bar whose stop has keyboard focus is outlined with. */\nconst FOCUSED_BAR = { stroke: \"var(--text-primary)\", strokeWidth: 2 };\n\n/** A marker label's size in px at Normal — the one place both the text and its width\n * estimate read it from. × the text size's scale where it is drawn (§10.10). */\nconst MARKER_LABEL_SIZE = 11;\n\n/** A reference line's label, in px at Normal, × the scale likewise. */\nconst REFERENCE_LABEL_SIZE = 10;\n\n/**\n * A marker's label, centred over its point but clamped inside the plot. recharts'\n * `position: \"top\"` centres on the point no matter where it is, so a marker near the\n * plot's end (the last sample, a projection's end point) had half its label cut off by\n * the card — \"over the c\" on a phone. The width is measured once drawn; the first\n * frame (and a DOM without layout) uses a 0.6em-per-character estimate, which errs wide.\n */\nfunction MarkerLabel({ viewBox, value }: { viewBox?: { x?: number; y?: number; width?: number }; value?: ReactNode }) {\n const plot = usePlotArea();\n const ref = useRef<SVGTextElement>(null);\n const [measured, setMeasured] = useState<number>();\n const fontSize = MARKER_LABEL_SIZE * useTextSize().scale;\n const text = value == null ? \"\" : String(value);\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || typeof el.getComputedTextLength !== \"function\") return;\n const w = el.getComputedTextLength();\n if (w > 0 && w !== measured) setMeasured(w);\n }, [text, measured, fontSize]);\n if (!viewBox || viewBox.x == null || viewBox.y == null || text === \"\") return null;\n const cx = viewBox.x + (viewBox.width ?? 0) / 2;\n const half = (measured ?? text.length * fontSize * 0.6) / 2;\n // The start clamp applied last: a label wider than the plot keeps its start on screen.\n const x = plot ? Math.max(plot.x + half, Math.min(cx, plot.x + plot.width - half)) : cx;\n return (\n <text\n ref={ref}\n x={x}\n y={viewBox.y - 5}\n textAnchor=\"middle\"\n fontSize={fontSize}\n fontWeight={600}\n fill=\"var(--text-primary)\"\n className=\"recharts-label\"\n >\n {text}\n </text>\n );\n}\n\n/**\n * The keyboard's roving stop and the stop that has focus, as indices into the chart's\n * stops: a store, not the plot's state (0.55, held back from 0.52's review). Kept as state,\n * every arrow-key step — which moves the tooltip — re-rendered the whole plot, and\n * recharts drew every series, dot, axis and tick again; now only what reads the store\n * draws again: the stops themselves, the tooltip they stand on, and the bar they outline.\n */\ninterface StopStore {\n /** The roving stop: the one Tab lands on. */\n stop: () => number;\n /** The stop that has focus, or `undefined`. */\n focus: () => number | undefined;\n subscribe: (onChange: () => void) => () => void;\n focused: (at: number) => void;\n blurred: () => void;\n}\n\nfunction createStopStore(): StopStore {\n let stop = 0;\n let focus: number | undefined;\n const listeners = new Set<() => void>();\n const emit = () => listeners.forEach((onChange) => onChange());\n return {\n stop: () => stop,\n focus: () => focus,\n subscribe: (onChange) => {\n listeners.add(onChange);\n return () => listeners.delete(onChange);\n },\n focused: (at) => {\n if (stop === at && focus === at) return;\n stop = at;\n focus = at;\n emit();\n },\n blurred: () => {\n if (focus === undefined) return;\n focus = undefined;\n emit();\n },\n };\n}\n\n/** The stop that has keyboard focus, read from the store: re-renders its reader only when\n * that stop changes. */\nfunction useFocusedStop(keys: StopStore, stops: readonly PointStop[]): PointStop | undefined {\n const at = useSyncExternalStore(keys.subscribe, keys.focus, keys.focus);\n return at === undefined ? undefined : stops[at];\n}\n\n/**\n * The plot's tooltip, standing on the stop that has keyboard focus as the pointer's would\n * (`defaultIndex`, and `pointAt` for a pointer that has hovered). Reads the stop from the\n * store, so a step re-renders the tooltip and not the plot round it.\n */\nfunction StopTooltip({\n keys,\n stops,\n ...props\n}: ComponentProps<typeof ChartTooltip> & { keys: StopStore; stops: readonly PointStop[] }) {\n const focused = useFocusedStop(keys, stops);\n return <ChartTooltip {...props} defaultIndex={focused?.index} />;\n}\n\n/**\n * One bar: recharts' own rectangle, outlined while the bar's stop has keyboard focus —\n * drawn at the bar's exact geometry, which an overlay could only guess at. Not\n * `activeBar`: that follows the tooltip's active index, which recharts stops taking from\n * `defaultIndex` once a pointer has hovered the chart.\n *\n * Every bar is drawn through it (0.55) and reads the store itself, so a step re-renders\n * the bar it leaves and the bar it lands on. Up to 0.54 the focused series swapped its\n * `shape` for one that outlined the bar at an index: a new prop of the `<Bar>`, which\n * recharts registers in its store, so each step refitted and drew the axes again.\n */\nfunction StopRect({\n keys,\n stops,\n seriesKey,\n ...props\n}: BarShapeProps & { keys: StopStore; stops: readonly PointStop[]; seriesKey: string }) {\n const focused = useSyncExternalStore(\n keys.subscribe,\n () => {\n const at = keys.focus();\n const stop = at === undefined ? undefined : stops[at];\n return stop !== undefined && stop.key === seriesKey && stop.index === props.originalDataIndex;\n },\n () => false,\n );\n return <Rectangle {...props} {...(focused ? FOCUSED_BAR : {})} />;\n}\n\n/**\n * The keyboard's way onto a chart: one focusable `<rect>` per bar, or per slot when there\n * are no bars, laid over the plot INSIDE the recharts chart, where the x scale answers.\n *\n * keksdose drew its weekday pattern as seven real `<button>`s (spending-tab.tsx) because\n * a recharts bar is reachable by nothing but the pointer. This is that, for every chart:\n *\n * - ONE tab stop (roving `tabIndex`): Tab moves past the chart, not through 30 bars.\n * - ←/→ step through the stops in order, ↑/↓ between the bars of one slot, Home/End.\n * - Each is named \"period — series: value\".\n * - With `onPointClick` (`onPick`) each is a `role=\"button\"`, and ↵ and Space report the\n * stop as a click would — with the series for a bar. Without (0.52, refactor audit\n * 2026-10-30, DSP-5) each is a `role=\"img\"` to read, as PieChart's slices are: before,\n * such a chart was recharts' unnamed `role=\"application\"` stop, whose arrows moved a\n * tooltip nothing announced.\n *\n * The stops take NO pointer events, so the drag-to-zoom layer, the tooltip and the\n * pointer's own clicks underneath behave exactly as they did. Focus is shown by the\n * slot tinted and, for a bar, its own outline (`focusedBarShape`) — and by the tooltip,\n * which recharts' own pointer is stood on the stop for (`pointAt`).\n */\nfunction PointKeys({\n stops,\n keys,\n label,\n onPick,\n}: {\n stops: readonly PointStop[];\n /** The roving stop and the focused one (see {@link StopStore}). */\n keys: StopStore;\n label: string;\n onPick?: (stop: PointStop) => void;\n}) {\n const plot = usePlotArea();\n const scale = useXAxisScale();\n const refs = useRef<(SVGRectElement | null)[]>([]);\n const current = Math.min(useSyncExternalStore(keys.subscribe, keys.stop, keys.stop), stops.length - 1);\n if (!plot || !scale || plot.width <= 0 || plot.height <= 0) return null;\n\n const onKeyDown = (at: number) => (event: KeyboardEvent<SVGRectElement>) => {\n const stop = stops[at];\n // ↑/↓ stay in the slot: the next or previous bar of the same period. The stops are\n // in slot order, so a slot's bars are neighbours. ←/→, Home and End as Treemap's tiles\n // take them (0.52 code review, deep, charts, finding 14): → is the next stop in any\n // page, since the plot runs left to right in an RTL one too (see `ChartContainer`).\n const inSlot = (step: 1 | -1) => (stops[at + step]?.index === stop.index ? at + step : at);\n const target =\n event.key === \"ArrowDown\"\n ? inSlot(1)\n : event.key === \"ArrowUp\"\n ? inSlot(-1)\n : rovingTarget(event.key, \"ltr\", at, stops.length, false);\n if (target !== undefined) {\n event.preventDefault();\n refs.current[target]?.focus();\n } else if (onPick && (event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n onPick(stop);\n }\n };\n\n const left = plot.x;\n const right = plot.x + plot.width;\n const middle = plot.y + plot.height / 2;\n // Every target an arrow, Home or End can name from the roving stop — see ALL_STOPS_UP_TO.\n const drawn =\n stops.length <= ALL_STOPS_UP_TO ? undefined : new Set([0, current - 1, current, current + 1, stops.length - 1]);\n return (\n <g role=\"group\" aria-label={label}>\n {stops.map((stop, at) => {\n if (drawn && !drawn.has(at)) return null;\n // An edge with no neighbour runs to the plot's edge.\n const a = finite(scale(stop.from)) ?? left;\n const b = finite(scale(stop.to)) ?? right;\n const x0 = Math.max(left, Math.min(a, b));\n const x1 = Math.min(right, Math.max(a, b));\n return (\n <rect\n key={`${stop.index}:${stop.key ?? \"\"}`}\n ref={(node) => {\n refs.current[at] = node;\n }}\n role={onPick ? \"button\" : \"img\"}\n tabIndex={at === current ? 0 : -1}\n aria-label={stop.name()}\n data-point-key={stop.key}\n x={x0}\n y={plot.y}\n width={Math.max(0, x1 - x0)}\n height={plot.height}\n fill=\"transparent\"\n // Focus only: the pointer's drag, hover and click belong to what is below.\n pointerEvents=\"none\"\n strokeWidth={2}\n className={cn(\n \"outline-none focus-visible:fill-[var(--brand)]/10\",\n // A bar outlines ITSELF (see `FOCUSED_BAR`); a slot has nothing else to.\n stop.key === undefined && \"focus-visible:stroke-[var(--brand)]\",\n )}\n onFocus={(event) => {\n keys.focused(at);\n pointAt(event.currentTarget, (x0 + x1) / 2, middle);\n }}\n onBlur={(event) => {\n keys.blurred();\n // On to another stop: that one stands the pointer on itself. (`refs` holds a\n // null for every stop not drawn, so a blur to nowhere is no stop.)\n const next = event.relatedTarget as SVGRectElement | null;\n if (!next || !refs.current.includes(next)) {\n pointAt(event.currentTarget, left - 1, middle);\n }\n }}\n onKeyDown={onKeyDown(at)}\n />\n );\n })}\n </g>\n );\n}\n\n/**\n * Stands recharts' pointer at (`x`, `y`) in the chart's own px, as a mouse moved there\n * would — what the keyboard's stops show their tooltip by (0.52 code review, deep, charts,\n * finding 4). Their `defaultIndex` alone moved it only until a pointer had hovered the\n * chart: recharts reads it no more once a hover has an index, and a mouse that has left\n * keeps its index. After one hover the arrows moved the tint, and the tooltip, the one\n * place the value is drawn, stayed where the mouse had left it. recharts' own keyboard\n * layer, which these stops replaced (DSP-5), drove the tooltip through its own state.\n *\n * A point off the plot (`x` left of it) takes the pointer off the chart: recharts hides\n * its tooltip there, through the same frame-throttled path a pending move takes, so a\n * blur right after a focus is never overtaken by it. recharts reads the pointer against\n * its wrapper's box, scaled as the box is drawn (`getRelativeCoordinate`); the point is\n * put back into that box.\n */\nfunction pointAt(within: Element, x: number, y: number) {\n const wrapper = within.closest<HTMLElement>(\".recharts-wrapper\");\n if (!wrapper) return;\n const box = wrapper.getBoundingClientRect();\n const scaleX = wrapper.offsetWidth > 0 ? box.width / wrapper.offsetWidth : 1;\n const scaleY = wrapper.offsetHeight > 0 ? box.height / wrapper.offsetHeight : 1;\n wrapper.dispatchEvent(\n new MouseEvent(\"mousemove\", { bubbles: true, clientX: box.left + x * scaleX, clientY: box.top + y * scaleY }),\n );\n}\n\ninterface PlotProps extends Omit<SeriesChartProps, \"rows\" | \"x\"> {\n /** The rows AS PLOTTED — what the zoom fits on. The caller's are `model.source`. */\n rows: readonly SeriesChartRow[];\n /** What the zoom fits on: the plotted key. */\n x: { key: string };\n model: XModel;\n xAxis: SeriesChartX;\n}\n\n/**\n * The chart proper, over an abscissa already reduced to numbers (see {@link XModel}).\n *\n * Memoised (0.55, held back from 0.52's review, which saw the plot drawn again on every\n * render of the page): it draws again when one of its props is new — the caller's, as\n * given, compared by identity as `memo` compares — or when its own box changes. Its\n * keyboard state is a store the stops read (`StopStore`), so a step draws only them, the\n * tooltip and the focused bar. A caller that wants a render of its page to cost the chart\n * nothing keeps its `rows`, `series`, `axes`, `x` and formatters the same between renders\n * (`useMemo`, `useCallback`, or a module constant): a list or a function written inline\n * is a new one each time, and the chart cannot know it says the same.\n */\nconst SeriesPlotView = memo(SeriesPlot);\n\nfunction SeriesPlot({\n model,\n xAxis,\n series,\n axes = ONE_UNTITLED_AXIS,\n valueFormat,\n height = \"h-72\",\n connectNulls,\n empty,\n animationMs = 0,\n spans,\n references,\n markers,\n onPointClick,\n tooltip,\n zoom,\n labels: labelsProp,\n locale: localeProp,\n className,\n minBarLength,\n maxVisibleAxes,\n axisBudget = \"auto\",\n onAxisBudget,\n maxRows,\n \"aria-label\": ariaLabel,\n description,\n}: PlotProps) {\n const labels = useKitLabels(\"seriesChart\", DEFAULT_SERIES_CHART_LABELS, labelsProp);\n const locale = useKitLocale(localeProp);\n const number = useDefaultFormat(localeProp);\n // The text size (docs/text-size-harmonization.md §3.2, §4, §10.10): the axis bands, the\n // tick spacing and the labels drawn in px grow with it — the tick text is `text-xs` and\n // grows by itself — and the axes aim at three ticks instead of five from Large up.\n // Strokes, dashes and the grid stay px.\n const { scale } = useTextSize();\n // The edge of a bar or an area in a hue under 3:1: its own darker shade (0.55).\n const edgeFor = useChartShade();\n // The tiles' rule (0.52, DSP-18, Marcel's decision 3): the edge under More contrast only\n // — at Standard it fell on 5 of 8 hues in light and on 2 in dark, the unevenness #642\n // took off the tiles.\n const edges = useEdgesInForce(\"auto\");\n const ticksAim = tickTarget(scale);\n const grow = (px: number) => (scale === 1 ? px : Math.round(px * scale));\n // The keyboard stops' roving tab stop, and the one that has focus (see `PointKeys`): a\n // store, so a step does not draw the plot again (see `StopStore`). Up here, above the\n // empty state's early return, like every hook.\n const [keys] = useState(createStopStore);\n // Where the tooltip goes, and — off the plot — the row it is portalled into.\n // Below `sm` (`max-sm:`, at the text size in force) — where `\"auto\"` takes the tooltip\n // off the plot. Narrower than the phone layout on purpose: a tablet's plot is wide\n // enough that the box beside the finger leaves the data in view; a phone's is not.\n const phone = useBreakpoint(\"max-sm\", false);\n const placement = resolveTooltipPlacement(tooltip?.placement, useKitChartTooltipPlacement(), phone);\n const [readout, setReadout] = useState<HTMLDivElement | null>(null);\n\n // The chart's own width, for the automatic axis budget. Its box, not the plot's: the\n // box does not change when an axis is hidden, so the rule cannot oscillate. Nothing\n // measured (jsdom, the first frame) is no automatic budget.\n const [box, setBox] = useState<HTMLDivElement | null>(null);\n const [width, setWidth] = useState<number | undefined>(undefined);\n useLayoutEffect(() => {\n if (!box || axisBudget === \"off\" || typeof ResizeObserver === \"undefined\") return;\n const measure = () => setWidth(box.getBoundingClientRect().width || undefined);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(box);\n return () => observer.disconnect();\n }, [box, axisBudget]);\n // The caller's cap first, then — on what is left — the automatic one.\n const capped = budgetedAxes(axes, maxVisibleAxes);\n const afterCap = capped.length\n ? axes.map((axis) => (capped.includes(axis.id) ? { ...axis, hide: true as const } : axis))\n : axes;\n const auto =\n axisBudget === \"off\"\n ? []\n : budgetedAxes(\n afterCap,\n autoAxisBudget(afterCap, width, (axis) => axisBandWidth(axis.width, Boolean(axis.title), scale), scale),\n );\n const budgeted = [...capped, ...auto];\n const budgetKey = budgeted.join(\"\\n\");\n\n // The rows drawn under `maxRows` (KS U2, `series-chart-thin.ts`): their indices into\n // the caller's rows, or `undefined` for all of them. Up here, above the empty state's\n // early return, like every hook; worked out again only when the rows, the series\n // drawn, the budget or the x window change — not on every render of a drag.\n const thinKeys = series.map((entry) => entry.key).join(\"\\n\");\n const [windowFrom, windowTo] = zoom?.xDomain ?? [undefined, undefined];\n const thin = useMemo(() => {\n if (model.kind === \"category\" || maxRows === undefined) return undefined;\n const keys = thinKeys ? thinKeys.split(\"\\n\") : [];\n const window: [number, number] | undefined =\n windowFrom !== undefined && windowTo !== undefined ? [windowFrom, windowTo] : undefined;\n const kept = thinnedRows(model.rows, model.plotKey, keys, maxRows, window);\n if (!kept) return undefined;\n return {\n kept,\n plotted: kept.map((index) => model.rows[index]),\n source: kept.map((index) => model.source[index]),\n };\n }, [model, thinKeys, maxRows, windowFrom, windowTo]);\n\n // Reported when the SET changes, not on every render — an inline callback is a new\n // function each time, and the guard keeps it from being called again for nothing.\n const reported = useRef(\"\");\n useEffect(() => {\n if (budgetKey === reported.current) return;\n reported.current = budgetKey;\n onAxisBudget?.(budgetKey ? budgetKey.split(\"\\n\") : []);\n }, [budgetKey, onAxisBudget]);\n\n // A number or a CSS length is set inline; any other string is a class. Either way the\n // one value sizes both the chart and its empty state.\n const { className: heightClass, style: heightStyle } = chartHeightProps(height);\n\n // A named figure, described by the caller's sentence and — where a drag zooms — the\n // gesture (0.52, refactor audit 2026-10-30, DSP-5). The hint used to be the name of the\n // zoom layer's rect, a `role=\"application\"` that could not take focus. The description\n // is `hidden`: read through `aria-describedby`, never twice in browse mode.\n const drawable = model.source.length > 0 && series.length > 0;\n const spoken = [description, drawable && zoom?.layer ? labels.zoomHint : undefined].filter(Boolean).join(\" \");\n // Inside the root, not after it as a sibling: a StaticSeriesChart then stopped being its\n // parent's last child, and a stack's `space-y-*` / `divide-y` gave it a margin or a rule\n // it never had (0.52 code review, deep, charts, findings 7 and 14 — Treemap's copy of this\n // went the same way). The plot's root is `ChartContainer`, which takes the sentence itself.\n const about = useFigureDescription(spoken || undefined);\n // The caller's name, else the axes' (0.55, Kurvenschmiede 0.52 adoption). `aria-label=\"\"`\n // is a name the caller gave too, and stays.\n const chartName = ariaLabel ?? axesName(axes, xAxis.title, locale, labels.nameFromAxes);\n const figure = { role: \"figure\", \"aria-label\": chartName, \"aria-describedby\": about.describedBy } as const;\n\n // The empty state takes the chart's own height and is centred in it: a chart that\n // shrank to its \"nothing to draw\" sentence moved everything under it up the page\n // the moment a legend entry was switched off.\n if (!drawable) {\n return (\n <div\n {...figure}\n className={cn(\"flex w-full items-center justify-center px-2 text-center\", heightClass)}\n style={heightStyle}\n >\n {empty !== undefined ? empty : <p className=\"text-xs text-muted\">{labels.empty}</p>}\n {about.node}\n </div>\n );\n }\n\n const x = xAxis;\n const xKey = model.plotKey;\n // What is DRAWN — the thinned rows under `maxRows`, else the caller's — and what is\n // FITTED: every row, so a band, a whole-number tick and the zoom's refit are the same\n // with a budget as without one.\n const plotted = thin?.plotted ?? model.rows;\n const rows = thin?.source ?? model.source;\n const allPlotted = model.rows;\n /** A drawn row's position in the CALLER's rows, which dots and hits report. */\n const origin = (index: number) => thin?.kept[index] ?? index;\n // What the budget took off the chart: an axis drawn as `hide` — and its unit, which\n // the tooltip names now that no title says it. Axes the caller hid keep their series'\n // labels as given, as they always did.\n const drawnAxes = budgeted.length\n ? axes.map((axis) => (budgeted.includes(axis.id) ? { ...axis, hide: true as const } : axis))\n : axes;\n const lostUnit = new Map(axes.filter((axis) => budgeted.includes(axis.id)).map((axis) => [axis.id, axisUnit(axis)]));\n const config: ChartConfig = Object.fromEntries(\n series.map((entry, index) => [\n entry.key,\n {\n label: withUnit(entry.label, lostUnit.get(entry.axis ?? DEFAULT_Y_AXIS)),\n color: entry.color ?? paletteFor(index),\n },\n ]),\n );\n const visible = drawnAxes.filter((axis) => !axis.hide);\n // The grid hangs its horizontal rules off ONE y axis, and recharts looks for the one\n // whose id is its own default (`0`). Every axis here is named, so without saying\n // which, it finds none and draws no horizontal rules at all. The first visible axis,\n // because those are the ticks a reader puts a ruler on.\n const gridAxis = (visible[0] ?? drawnAxes[0])?.id ?? DEFAULT_Y_AXIS;\n const onLeft = visible.some((axis) => (axis.orientation ?? \"left\") === \"left\");\n const onRight = visible.some((axis) => axis.orientation === \"right\");\n // The margins are what is left once the axes have their bands: an axis band IS the\n // gutter on its side, so a margin beside one is a second gutter. What remains is the\n // overhang of the first/last x tick where no y axis covers it.\n const margin = {\n // Room for a marker's label over a point at the top of the band.\n top: markers?.some((marker) => marker.label) ? grow(22) : 8,\n // The first and last x tick's overhang: text, so it grows with it.\n right: onRight ? 0 : grow(10),\n left: onLeft ? 0 : grow(10),\n // Under the ticks, not under the whole axis: whatever comes next owns the gap.\n bottom: x.title ? grow(18) : 2,\n };\n\n const refs = references ?? [];\n const xRefs = refs.filter((ref) => ref.axis === \"x\");\n const yRefs = refs.filter((ref) => ref.axis !== \"x\");\n const xPos = (value: SeriesChartXValue) => model.position(value);\n\n // Fitted with air around it, unless the reader has zoomed or the caller pinned it.\n // Ticks are the round values INSIDE whichever domain that is (see\n // `series-chart-ticks.ts`), so a zoom window still gets round numbers, just finer.\n // A category axis is its slots, each half a slot of air either side — room for a\n // bar, and the tick under the middle of it.\n const fittedX: [number, number] | undefined =\n zoom?.xDomain ??\n (model.kind === \"category\"\n ? [-0.5, rows.length - 0.5]\n : padBand(\n ...(extend(undefined, [\n ...allPlotted.map((row) => finite(row[xKey])),\n ...xRefs.map((ref) => xPos(ref.value)),\n ...(markers ?? []).map((marker) => xPos(marker.x)),\n ]) ?? [Infinity, -Infinity]),\n ));\n\n const timeUnit = model.kind === \"time\" ? timeTicksWithUnit(fittedX, ticksAim) : undefined;\n // Whole-number ticks on a number line whose rows are all whole numbers — see\n // `SeriesChartX.integerTicks`.\n const integerX =\n model.kind === \"number\" &&\n (x.integerTicks ??\n allPlotted.every((row) => {\n const value = finite(row[xKey]);\n return value === undefined || Number.isInteger(value);\n }));\n const xTicks =\n resolveTicks(x.tickValues, fittedX, xPos) ??\n (model.kind === \"category\"\n ? categoryTicks(fittedX, rows.length)\n : model.kind === \"time\"\n ? timeUnit?.ticks\n : integerX\n ? (integerTicks(fittedX, ticksAim) ?? niceTicks(fittedX, ticksAim))\n : niceTicks(fittedX, ticksAim));\n\n // Ticks and the tooltip heading, back in the caller's terms.\n const timeFormat = new Intl.DateTimeFormat(locale, TIME_TICK_FORMAT[timeUnit?.unit ?? \"day\"]);\n const dateFormat = new Intl.DateTimeFormat(locale, {\n dateStyle: \"medium\",\n ...(timeUnit?.unit === \"hour\" ? { timeStyle: \"short\" } : {}),\n });\n const categoryText = (value: SeriesChartXValue) =>\n value instanceof Date ? dateFormat.format(value) : typeof value === \"number\" ? number(value) : String(value ?? \"\");\n const tickAt = (position: number): SeriesChartXTick => ({\n value: model.valueAt(position),\n ...(model.kind === \"category\" ? { index: Math.round(position) } : {}),\n ...(timeUnit ? { unit: timeUnit.unit } : {}),\n });\n const defaultFormat = (position: number, tick: SeriesChartXTick) =>\n model.kind === \"category\"\n ? categoryText(tick.value)\n : model.kind === \"time\"\n ? timeFormat.format(position)\n : number(position);\n const format = x.format ?? defaultFormat;\n const xFormat = (position: number) => format(position, tickAt(position));\n const label = x.label ?? (model.kind === \"time\" ? (position: number) => dateFormat.format(position) : format);\n const xLabel = (position: number) => label(position, tickAt(position));\n\n const tickAngle = x.ticks === false ? 0 : (x.tickAngle ?? 0);\n const tickBand = tiltedTickBand(\n (xTicks ?? []).map((tick) => xFormat(tick)),\n tickAngle,\n scale,\n );\n\n const source: ZoomFitSource = {\n rows: allPlotted,\n series,\n axes,\n xKey,\n };\n // An axis a bar or an area stands on is read from zero (see `includeZero`).\n const anchored = (axis: SeriesChartAxis) =>\n axis.includeZero ??\n series.some((entry) => (entry.axis ?? DEFAULT_Y_AXIS) === axis.id && (entry.type ?? \"line\") !== \"line\");\n // Whole-number ticks on an axis whose values are all whole — see\n // `SeriesChartAxis.integerTicks`. A stack of whole layers sums to a whole number, so\n // the layers are enough to look at.\n const wholeOnly = (axis: SeriesChartAxis) =>\n axis.integerTicks ??\n series\n .filter((entry) => (entry.axis ?? DEFAULT_Y_AXIS) === axis.id)\n .every((entry) =>\n allPlotted.every((row) => {\n const value = finite(row[entry.key]);\n return value === undefined || Number.isInteger(value);\n }),\n );\n const onAxis = (axisId: string) => (ref: { axis?: string }) => (ref.axis ?? DEFAULT_Y_AXIS) === axisId;\n const fittedY = (axis: SeriesChartAxis): [number, number] | undefined => {\n const own = [\n ...yRefs.filter(onAxis(axis.id)).map((ref) => finite(ref.value)),\n ...(markers ?? []).filter(onAxis(axis.id)).map((marker) => finite(marker.y)),\n ];\n if (anchored(axis)) {\n // Never a dragged y window: refitted to the x window, still from zero.\n if (zoom?.xDomain) return anchoredBand(axisExtent(source, axis.id, zoom.xDomain)) ?? axis.domain;\n return axis.domain ?? anchoredBand(extend(axisExtent(source, axis.id), own));\n }\n return (\n zoom?.yDomains[axis.id] ??\n axis.domain ??\n padBand(...(extend(axisExtent(source, axis.id), own) ?? [Infinity, -Infinity]))\n );\n };\n\n // The abscissa of a row in the caller's terms: a category is its slot, which is\n // its index; a time or a number is read back from where it was plotted.\n const xOf = (index: number): SeriesChartXValue =>\n model.kind === \"category\"\n ? (rows[index][model.sourceKey] as SeriesChartXValue)\n : model.valueAt(finite(plotted[index][xKey]) ?? NaN);\n const hitAt = (index: number, key?: string): SeriesChartHit | undefined => {\n const row = rows[index];\n return row ? { index: origin(index), row, x: xOf(index), key } : undefined;\n };\n\n // The keyboard stops — every bar with a value, slot by slot; or, with no bars, every\n // slot with any value. Only what is inside the window on show. Named on demand: past\n // ALL_STOPS_UP_TO only five are drawn, and naming is a date and a number format each.\n const stops: PointStop[] = [];\n {\n const valueText = valueFormat ?? number;\n const nameOf = (entry: SeriesChartSeries) =>\n typeof entry.label === \"string\" || typeof entry.label === \"number\" ? String(entry.label) : entry.key;\n const cellText = (entry: SeriesChartSeries, value: number) => {\n const name = nameOf(entry);\n return name ? `${name}: ${valueText(value)}` : valueText(value);\n };\n const bars = series.filter((entry) => entry.type === \"bar\");\n const [low, high] = fittedX ?? [-Infinity, Infinity];\n const placed = plotted\n .map((row, index) => ({ index, at: model.kind === \"category\" ? index : finite(row[xKey]) }))\n .filter(\n (slot): slot is { index: number; at: number } => slot.at !== undefined && slot.at >= low && slot.at <= high,\n )\n .sort((a, b) => a.at - b.at);\n placed.forEach(({ index, at }, k) => {\n const from = k > 0 ? (placed[k - 1].at + at) / 2 : low;\n const to = k < placed.length - 1 ? (placed[k + 1].at + at) / 2 : high;\n // The heading the tooltip would give it, when that is text; else the tick.\n const where = () => {\n const heading = xLabel(at);\n return typeof heading === \"string\" && heading ? heading : xFormat(at);\n };\n const valued = (bars.length ? bars : series)\n .map((entry) => ({ entry, value: finite(rows[index]?.[entry.key]) }))\n .filter((cell): cell is { entry: SeriesChartSeries; value: number } => cell.value !== undefined);\n if (bars.length) {\n for (const { entry, value } of valued) {\n stops.push({ index, key: entry.key, from, to, name: () => `${where()} — ${cellText(entry, value)}` });\n }\n } else if (valued.length) {\n stops.push({\n index,\n from,\n to,\n name: () => `${where()} — ${valued.map(({ entry, value }) => cellText(entry, value)).join(\", \")}`,\n });\n }\n });\n }\n\n const dotFor = (entry: SeriesChartSeries) => {\n const want = entry.dot;\n if (!want) return false;\n const color = `var(--color-${entry.key})`;\n return (props: { cx?: number; cy?: number; index: number }) => {\n const { cx, cy, index } = props;\n const value = finite(rows[index]?.[entry.key]);\n if (value === undefined || !Number.isFinite(cx) || !Number.isFinite(cy)) return <g />;\n const point: SeriesChartPoint = {\n key: entry.key,\n index: origin(index),\n row: rows[index],\n x: xOf(index),\n value,\n cx: cx!,\n cy: cy!,\n color,\n };\n const drawn = want === true ? true : want(point);\n if (drawn === true) {\n return (\n <circle\n className=\"recharts-dot\"\n cx={cx}\n cy={cy}\n r={3}\n fill={color}\n // Ringed in the surface, so a dot on a crossing line still reads as a dot.\n stroke=\"var(--bg-surface)\"\n strokeWidth={1.5}\n />\n );\n }\n if (drawn === false || drawn == null) return <g />;\n return <g>{drawn}</g>;\n };\n };\n\n const animation = {\n isAnimationActive: animationMs > 0,\n animationDuration: animationMs,\n animationEasing: \"ease-out\" as const,\n };\n\n const inRow = placement !== \"cursor\";\n const chart = (\n <ChartContainer\n {...(inRow ? {} : { role: \"figure\", \"aria-label\": chartName, description: spoken || undefined })}\n ref={setBox}\n data-axis-budget={budgeted.length ? budgetKey.replace(/\\n/g, \" \") : undefined}\n // \"drawn/all\" while `maxRows` thins: what a reader of the DOM (a test, a bug\n // report) needs to know the picture is an envelope.\n data-thinned={thin ? `${thin.kept.length}/${allPlotted.length}` : undefined}\n config={config}\n className={cn(\n \"w-full\",\n // With a readout the chart's height is the whole block's, and the plot takes\n // what the row leaves.\n inRow ? \"min-h-0 flex-1\" : heightClass,\n className,\n onPointClick && \"cursor-pointer\",\n )}\n style={inRow ? undefined : heightStyle}\n >\n <ComposedChart\n data={plotted as Record<string, unknown>[]}\n margin={margin}\n // Positive and negative layers stacked apart, as `axisExtent` fits them — a\n // month's expenses hang below the axis instead of eating into its income.\n stackOffset=\"sign\"\n // recharts' own keyboard layer makes the whole surface an unnamed\n // `role=\"application\"` tab stop whose arrows move a tooltip nothing announces —\n // a second stop beside `PointKeys`, which every chart has since 0.52 (DSP-5).\n accessibilityLayer={false}\n onClick={\n onPointClick\n ? (state) => {\n const index = Number(state?.activeTooltipIndex ?? state?.activeIndex);\n const hit = Number.isInteger(index) ? hitAt(index) : undefined;\n if (hit) onPointClick(hit);\n }\n : undefined\n }\n >\n {/* Both ways: a measurement plot is read by putting a ruler on it, and a\n horizontal-only grid answers half of those questions. */}\n <CartesianGrid yAxisId={gridAxis} />\n <XAxis\n dataKey={xKey}\n // Numeric, not categorical: a measured sweep is unevenly spaced, and a\n // category axis would straighten exactly the curvature the chart is for.\n // A category chart is numeric too — on the slot index — which is what lets\n // it zoom and keeps its ticks under the middle of each bar group.\n type=\"number\"\n domain={fittedX ?? [\"dataMin\", \"dataMax\"]}\n ticks={xTicks}\n // Clip the lines to a zoom window instead of recharts widening it back out.\n allowDataOverflow={zoom?.xDomain !== undefined || model.kind === \"category\"}\n tickLine={false}\n axisLine={false}\n minTickGap={grow(MIN_TICK_GAP)}\n // Where the ticks crowd, drop every Nth rather than recharts' default\n // `preserveEnd`, which drops whichever single tick collides: a phone's whole-week\n // axis came out 2 4 6 8 _ 12, a doubled gap that reads as a missing week. Every\n // other tick, keeping the last, gives 4 8 12 — still an even ruler.\n interval=\"equidistantPreserveEnd\"\n tick={x.ticks === false ? false : undefined}\n {...(tickAngle ? { angle: tickAngle, textAnchor: tickAngle < 0 ? \"end\" : \"start\" } : {})}\n // With neither ticks nor title there is nothing to reserve the band for, and\n // recharts' own 30 px would leave a gap under every chart of a stack.\n height={x.ticks === false && !x.title ? 4 : tickBand}\n tickFormatter={(value: number) => xFormat(Number(value))}\n >\n {x.title && (\n <Label value={x.title} position=\"insideBottom\" offset={-grow(12)} className=\"fill-muted text-caption\" />\n )}\n </XAxis>\n {drawnAxes.map((axis) => {\n const domain = fittedY(axis);\n const zoomed = anchored(axis) ? zoom?.xDomain !== undefined : zoom?.yDomains[axis.id] !== undefined;\n return (\n <YAxis\n key={axis.id}\n yAxisId={axis.id}\n hide={axis.hide}\n domain={domain}\n ticks={\n resolveTicks(axis.tickValues, domain, finite) ??\n (wholeOnly(axis)\n ? (integerTicks(domain, ticksAim) ?? niceTicks(domain, ticksAim))\n : niceTicks(domain, ticksAim))\n }\n allowDataOverflow={zoomed}\n orientation={axis.orientation ?? \"left\"}\n // Nothing for a hidden axis. An axis that turns hidden on a MOUNTED chart —\n // what the budget does on every resize across its threshold — kept its old\n // width in recharts' stacking of that side, and pushed the axes still drawn\n // off the chart's edge. A zero width leaves nothing stale to count.\n width={axis.hide ? 0 : axisBandWidth(axis.width, Boolean(axis.title), scale)}\n tickLine={false}\n axisLine={false}\n tickFormatter={axis.format ?? number}\n // With an axis per channel the tint is the only thing saying which\n // numbers belong to which line.\n tick={axis.color ? { fill: axis.color } : undefined}\n >\n {axis.title && !axis.hide && (\n <Label\n value={axis.title}\n // Rotated so both sides read upward from the bottom of their axis.\n angle={axis.orientation === \"right\" ? 90 : -90}\n position={axis.orientation === \"right\" ? \"insideRight\" : \"insideLeft\"}\n // Inline, so a sole series' colour beats the class's neutral fill —\n // and absent for a shared axis, so the class draws it.\n style={{ textAnchor: \"middle\", fill: soleSeriesColor(axis, series) }}\n offset={grow(AXIS_TITLE_OFFSET)}\n className=\"fill-muted text-caption\"\n />\n )}\n </YAxis>\n );\n })}\n {inRow ? (\n // Not before the row exists: without its own portal recharts would float this\n // content over the plot for the first frame.\n readout && (\n <StopTooltip\n keys={keys}\n stops={stops}\n portal={readout}\n // recharts hides an inactive tooltip; the row shows its idle state instead.\n wrapperStyle={{ visibility: \"visible\" }}\n content={\n <ChartTooltipContent\n variant=\"readout\"\n idleKeys={series.map((entry) => entry.key)}\n idleLabel={x.title || undefined}\n labelFormatter={(value) => xLabel(Number(value))}\n valueFormatter={valueFormat ?? number}\n />\n }\n />\n )\n ) : (\n <StopTooltip\n // The keyboard's stop shows its tooltip as the pointer's would.\n keys={keys}\n stops={stops}\n {...(tooltip?.allowEscapeViewBox || tooltip?.boundary\n ? { allowEscapeViewBox: tooltip.allowEscapeViewBox ?? { x: true } }\n : {})}\n // The content shifts itself 12 px off the cursor (or flips) against the\n // boundary; recharts' own offset on top would double it.\n {...(tooltip?.boundary ? { offset: 0 } : {})}\n content={\n <ChartTooltipContent\n labelFormatter={(value) => xLabel(Number(value))}\n valueFormatter={valueFormat ?? number}\n boundaryRef={tooltip?.boundary}\n />\n }\n />\n )}\n {series.map((entry) => {\n const type = entry.type ?? \"line\";\n const yAxisId = entry.axis ?? DEFAULT_Y_AXIS;\n const color = `var(--color-${entry.key})`;\n // Under More contrast, a filled mark in a hue under 3:1 against the card or the page\n // (WCAG 1.4.11) is edged in its own shade that clears it, darker on a light page and\n // lighter on a dark one (`chartShade`, 0.55): a bar with a 1px edge, an area with\n // its line, the fill keeping the hue the legend shows. Measured on the colour the\n // config paints. At Standard nothing is (see `edges`). Up to 0.54 the edge was the\n // ink, which on an area's line read as a black line where the series was coloured.\n const edge = edges === \"contrast\" ? edgeFor(config[entry.key]?.color) : undefined;\n const own = entry.dash ?? (entry.dashed ? 1 : 0);\n const dash = entry.step ? strokeDash(STEP_DASH) : typeof own === \"string\" ? own : strokeDash(own);\n const curve = entry.step ? \"stepAfter\" : (entry.curve ?? \"monotone\");\n const width = entry.strokeWidth ?? (entry.step ? STEP_WIDTH : LINE_WIDTH);\n if (type === \"bar\") {\n const stub = entry.minBarLength ?? minBarLength;\n return (\n <Bar\n key={entry.key}\n yAxisId={yAxisId}\n dataKey={entry.key}\n stackId={entry.stack}\n fill={color}\n fillOpacity={entry.fillOpacity}\n {...(edge ? { stroke: edge, strokeWidth: 1 } : {})}\n radius={entry.stack === undefined ? BAR_RADIUS : 0}\n // Outlined while its stop has keyboard focus (`StopRect`).\n shape={(bar: BarShapeProps) => <StopRect {...bar} keys={keys} stops={stops} seriesKey={entry.key} />}\n // Read off the row rather than recharts' `value`: in a stack that is the\n // layer's running top, which a hole has too — and a hole gets no stub.\n {...(stub\n ? {\n minPointSize: (_value: unknown, index: number) =>\n finite(plotted[index]?.[entry.key]) === undefined ? 0 : stub,\n }\n : {})}\n onClick={\n onPointClick\n ? (_bar, index, event) => {\n // The plot's own click would report the same slot again,\n // without the series.\n event.stopPropagation();\n const hit = hitAt(index, entry.key);\n if (hit) onPointClick(hit);\n }\n : undefined\n }\n {...animation}\n />\n );\n }\n if (type === \"area\") {\n return (\n <Area\n key={entry.key}\n yAxisId={yAxisId}\n type={curve}\n dataKey={entry.key}\n stackId={entry.stack}\n // The edge's shade replaces the hue on the area's outline only; the fill\n // keeps it, and the outline its width (0.52, DSP-18: it was 1px, whatever\n // `strokeWidth` said).\n stroke={edge ?? color}\n strokeWidth={width}\n strokeDasharray={dash}\n fill={color}\n fillOpacity={entry.fillOpacity ?? (entry.stack !== undefined ? 0.55 : 0.2)}\n dot={dotFor(entry)}\n {...(entry.activeDot !== undefined ? { activeDot: entry.activeDot } : {})}\n connectNulls={connectNulls}\n {...animation}\n />\n );\n }\n return (\n <Line\n key={entry.key}\n yAxisId={yAxisId}\n type={curve}\n dataKey={entry.key}\n stroke={color}\n strokeWidth={width}\n strokeDasharray={dash}\n dot={dotFor(entry)}\n {...(entry.activeDot !== undefined ? { activeDot: entry.activeDot } : {})}\n connectNulls={connectNulls}\n {...animation}\n />\n );\n })}\n {spans?.map((span) => (\n <ReferenceLine\n key={span.key}\n yAxisId={span.axis ?? DEFAULT_Y_AXIS}\n segment={[\n { x: span.x, y: span.from },\n { x: span.x, y: span.to },\n ]}\n stroke={span.color ?? \"var(--text-muted)\"}\n strokeWidth={2}\n // Discarded rather than clamped when zoomed past: a span clamped to the\n // window's edge draws a vertical line at an abscissa it never stood at.\n ifOverflow=\"discard\"\n />\n ))}\n {refs.map((ref, index) => {\n const vertical = ref.axis === \"x\";\n const at = vertical ? xPos(ref.value) : finite(ref.value);\n if (at === undefined) return null;\n const color = ref.color ?? TONE_COLOR[ref.tone ?? \"muted\"];\n return (\n <ReferenceLine\n key={ref.key ?? `reference-${index}`}\n // A vertical line still needs a y axis to be drawn against, and every\n // axis here is named — the grid's is always there.\n yAxisId={vertical ? gridAxis : (ref.axis ?? DEFAULT_Y_AXIS)}\n {...(vertical ? { x: at } : { y: at })}\n stroke={color}\n strokeWidth={1}\n strokeDasharray={strokeDash(ref.dash ?? 1)}\n ifOverflow=\"discard\"\n label={\n ref.label\n ? {\n value: ref.label,\n position: \"insideTopLeft\",\n fontSize: REFERENCE_LABEL_SIZE * scale,\n fill: color,\n }\n : undefined\n }\n />\n );\n })}\n {markers?.map((marker, index) => {\n const at = xPos(marker.x);\n if (at === undefined || finite(marker.y) === undefined) return null;\n const color = marker.color ?? TONE_COLOR[marker.tone ?? \"brand\"];\n return (\n <ReferenceDot\n key={marker.key ?? `marker-${index}`}\n yAxisId={marker.axis ?? DEFAULT_Y_AXIS}\n x={at}\n y={marker.y}\n r={marker.r ?? 4.5}\n fill={color}\n stroke=\"var(--bg-surface)\"\n strokeWidth={1.5}\n ifOverflow=\"discard\"\n label={marker.label ? { value: marker.label, position: \"top\", content: <MarkerLabel /> } : undefined}\n />\n );\n })}\n {stops.length > 0 && (\n <PointKeys\n stops={stops}\n keys={keys}\n label={labels.points}\n onPick={\n onPointClick\n ? (stop) => {\n const hit = hitAt(stop.index, stop.key);\n if (hit) onPointClick(hit);\n }\n : undefined\n }\n />\n )}\n {zoom?.layer}\n </ComposedChart>\n </ChartContainer>\n );\n if (!inRow) return chart;\n // The row's own box, reserved from the first render: its idle state has the cells the\n // active one will, so the first tap fills it in rather than pushing the plot down.\n const row = (\n <div\n ref={setReadout}\n data-tooltip-readout={placement}\n className={cn(\n \"shrink-0\",\n // Above, the heading line shares the top corner with the zoom's reset button.\n placement === \"above\" ? \"pb-2 [&_[data-readout-heading]]:pe-32\" : \"pt-2\",\n )}\n />\n );\n return (\n <div {...figure} className={cn(\"flex w-full flex-col\", heightClass)} style={heightStyle}>\n {placement === \"above\" && row}\n {chart}\n {placement === \"below\" && row}\n {about.node}\n </div>\n );\n}\n\nconst ZoomablePlot = withChartZoom(SeriesPlotView);\n\n/** The abscissa of a chart that describes none, one object for every render. */\nconst NO_X: SeriesChartX = {};\n\n/**\n * The caller's props, with the abscissa reduced to numbers for the plot and the zoom.\n * The reduction is kept while the rows and the two settings it reads stay the same — a\n * category or time chart otherwise re-maps every row on every render, and `maxRows`'\n * envelope would be worked out again with it. So is every prop it adds (0.55): the plot is\n * memoised, and a new `x` per render was a new prop that drew it all again.\n */\nfunction usePlotProps<TRow extends object>(typed: SeriesChartProps<TRow>): PlotProps {\n // `TRow` types only what the caller is handed back, and that is its own row objects,\n // untouched (0.53): the plot reads them as the `object` rows they are. Through `unknown`\n // because the two are not comparable for an unresolved `TRow`: `SeriesChartSeries` is\n // contravariant in it (its `dot` is handed rows) and `rows` covariant.\n const props = typed as unknown as SeriesChartProps;\n const x = props.x ?? NO_X;\n const { rows } = props;\n const { type, key } = x;\n // Read by key, so any object is a row (API-2); `SeriesChartRow` is how the plot reads it.\n const model = useMemo(() => xModel(rows as readonly SeriesChartRow[], { type, key }), [rows, type, key]);\n const plotted = useMemo(() => ({ key: model.plotKey }), [model.plotKey]);\n return { ...props, rows: model.rows, x: plotted, model, xAxis: x };\n}\n\n/**\n * {@link SeriesChart} without the zoom: the same picture, no drag layer, no reset\n * button. For a thumbnail, a print view, or a chart the consumer wraps in its own\n * interaction.\n */\nexport function StaticSeriesChart<TRow extends object = object>(props: SeriesChartProps<TRow>) {\n return <SeriesPlotView {...usePlotProps(props)} />;\n}\n\n/**\n * The series chart, zoomable. Drag across the plot to zoom (the drag's shape picks the\n * axes), double-click or press the reset button to go back; wrap several in\n * `SharedXZoom` to move their x windows together. Which axes zoom depends on the marks\n * — see {@link SeriesChartProps.zoomAxes}.\n *\n * Generic in its rows (0.53): `hit.row` and a `dot`'s `point.row` are typed as `rows` is —\n * see {@link SeriesChartProps}. A plain function, so the generic survives: a `memo` or a\n * `forwardRef` around it would read `TRow` as its constraint.\n */\nexport function SeriesChart<TRow extends object = object>(props: SeriesChartProps<TRow>) {\n // The zoom fits the PLOTTED rows — slot indices and epoch ms, not the caller's labels.\n return <ZoomablePlot {...usePlotProps(props)} />;\n}\n"],"mappings":"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","names":["anchoredBand","axisBandWidth","padBand","soleSeriesColor","seriesKey","keys","row","width"]}