basalt-ui 1.27.0 → 1.28.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 (1063) hide show
  1. package/AGENTS.md +23 -23
  2. package/CHANGELOG.md +59 -0
  3. package/MIGRATING.md +613 -20
  4. package/README.md +33 -3
  5. package/agent/rules/basalt-batteries.md +25 -10
  6. package/agent/rules/basalt-controls.md +56 -31
  7. package/agent/rules/basalt-mantine.md +17 -6
  8. package/agent/rules/basalt-tokens.md +1 -1
  9. package/configs/oxlint-plugin.js +1056 -28
  10. package/configs/oxlint-plugin.test.ts +1066 -0
  11. package/configs/oxlint.json +7 -0
  12. package/dist/agent/coalesce.d.ts.map +1 -1
  13. package/dist/agent/coalesce.js +2 -1
  14. package/dist/agent/merge.d.ts.map +1 -1
  15. package/dist/agent/merge.js +2 -1
  16. package/dist/agent/part-list.d.ts.map +1 -1
  17. package/dist/agent/part-list.js +2 -0
  18. package/dist/agent/stick-to-bottom.d.ts +3 -6
  19. package/dist/agent/stick-to-bottom.d.ts.map +1 -1
  20. package/dist/agent/stick-to-bottom.js +6 -3
  21. package/dist/agent-chat/composer.d.ts +6 -2
  22. package/dist/agent-chat/composer.d.ts.map +1 -1
  23. package/dist/agent-chat/composer.js +49 -33
  24. package/dist/agent-chat/relative-time.d.ts +0 -9
  25. package/dist/agent-chat/relative-time.d.ts.map +1 -1
  26. package/dist/agent-chat/relative-time.js +2 -1
  27. package/dist/agent-chat/thread-detail-panel.d.ts +3 -2
  28. package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
  29. package/dist/agent-chat/thread-detail-panel.js +8 -5
  30. package/dist/agent-chat/thread-feed-row.d.ts +2 -1
  31. package/dist/agent-chat/thread-feed-row.d.ts.map +1 -1
  32. package/dist/agent-chat/thread-feed-row.js +92 -92
  33. package/dist/agent-chat/thread-feed.d.ts +3 -2
  34. package/dist/agent-chat/thread-feed.d.ts.map +1 -1
  35. package/dist/agent-chat/thread-feed.js +8 -3
  36. package/dist/agent-chat/thread-message.d.ts +4 -3
  37. package/dist/agent-chat/thread-message.d.ts.map +1 -1
  38. package/dist/agent-chat/thread-message.js +70 -31
  39. package/dist/agent-chat/thread-outcome-card.d.ts +3 -2
  40. package/dist/agent-chat/thread-outcome-card.d.ts.map +1 -1
  41. package/dist/agent-chat/thread-outcome-card.js +9 -2
  42. package/dist/agent-chat/thread-workspace.d.ts +7 -2
  43. package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
  44. package/dist/agent-chat/thread-workspace.js +62 -29
  45. package/dist/agent-chat/tool-chip.d.ts +3 -2
  46. package/dist/agent-chat/tool-chip.d.ts.map +1 -1
  47. package/dist/agent-chat/tool-chip.js +7 -2
  48. package/dist/charts/hooks/useBandPlot.d.ts.map +1 -1
  49. package/dist/charts/hooks/useBandPlot.js +15 -8
  50. package/dist/charts/index.d.ts +8 -7
  51. package/dist/charts/index.d.ts.map +1 -1
  52. package/dist/charts/index.js +45 -5
  53. package/dist/charts/kinds/BandStrip.d.ts +10 -7
  54. package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
  55. package/dist/charts/kinds/BandStrip.js +12 -7
  56. package/dist/charts/kinds/Bars.d.ts +12 -6
  57. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  58. package/dist/charts/kinds/Bars.js +37 -11
  59. package/dist/charts/kinds/Donut.d.ts +6 -5
  60. package/dist/charts/kinds/Donut.d.ts.map +1 -1
  61. package/dist/charts/kinds/Donut.js +19 -2
  62. package/dist/charts/kinds/DualPanel.d.ts +6 -5
  63. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  64. package/dist/charts/kinds/DualPanel.js +36 -8
  65. package/dist/charts/kinds/Heatmap.d.ts +10 -6
  66. package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
  67. package/dist/charts/kinds/Heatmap.js +58 -31
  68. package/dist/charts/kinds/MirroredBars.d.ts +6 -5
  69. package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
  70. package/dist/charts/kinds/MirroredBars.js +9 -2
  71. package/dist/charts/kinds/MultiLine.d.ts +11 -6
  72. package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
  73. package/dist/charts/kinds/MultiLine.js +24 -15
  74. package/dist/charts/kinds/StackedArea.d.ts +18 -8
  75. package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
  76. package/dist/charts/kinds/StackedArea.js +29 -4
  77. package/dist/charts/kinds/ZonedLine.d.ts +12 -8
  78. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  79. package/dist/charts/kinds/ZonedLine.js +33 -23
  80. package/dist/charts/layout/auto-margin.d.ts +65 -8
  81. package/dist/charts/layout/auto-margin.d.ts.map +1 -1
  82. package/dist/charts/layout/auto-margin.js +45 -10
  83. package/dist/charts/layout/log-ticks.d.ts +27 -0
  84. package/dist/charts/layout/log-ticks.d.ts.map +1 -0
  85. package/dist/charts/layout/log-ticks.js +42 -0
  86. package/dist/charts/primitives/Axes.d.ts +11 -2
  87. package/dist/charts/primitives/Axes.d.ts.map +1 -1
  88. package/dist/charts/primitives/Axes.js +15 -5
  89. package/dist/charts/primitives/CartesianChart.d.ts +45 -7
  90. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  91. package/dist/charts/primitives/CartesianChart.js +86 -28
  92. package/dist/charts/primitives/ChartCard.d.ts +27 -2
  93. package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
  94. package/dist/charts/primitives/ChartCard.js +37 -17
  95. package/dist/charts/primitives/ChartFrame.d.ts +30 -4
  96. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  97. package/dist/charts/primitives/ChartFrame.js +45 -15
  98. package/dist/charts/primitives/ChartLegend.d.ts +13 -2
  99. package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
  100. package/dist/charts/primitives/ChartLegend.js +33 -13
  101. package/dist/charts/primitives/ChartPending.d.ts +77 -4
  102. package/dist/charts/primitives/ChartPending.d.ts.map +1 -1
  103. package/dist/charts/primitives/ChartPending.js +100 -6
  104. package/dist/charts/primitives/ChartTooltip.d.ts +7 -0
  105. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  106. package/dist/charts/primitives/ChartTooltip.js +18 -5
  107. package/dist/charts/primitives/Crosshair.d.ts +3 -0
  108. package/dist/charts/primitives/Crosshair.d.ts.map +1 -1
  109. package/dist/charts/primitives/Crosshair.js +3 -1
  110. package/dist/charts/primitives/chart-frame-layout.d.ts +95 -0
  111. package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -0
  112. package/dist/charts/primitives/chart-frame-layout.js +89 -0
  113. package/dist/charts/primitives/chart-tier.d.ts +16 -0
  114. package/dist/charts/primitives/chart-tier.d.ts.map +1 -0
  115. package/dist/charts/primitives/chart-tier.js +20 -0
  116. package/dist/charts/series.d.ts +55 -1
  117. package/dist/charts/series.d.ts.map +1 -1
  118. package/dist/charts/series.js +27 -1
  119. package/dist/charts/sparklines/BarSparkline.d.ts +3 -3
  120. package/dist/charts/sparklines/BarSparkline.d.ts.map +1 -1
  121. package/dist/charts/sparklines/BarSparkline.js +9 -3
  122. package/dist/charts/sparklines/LineSparkline.d.ts +3 -3
  123. package/dist/charts/sparklines/LineSparkline.d.ts.map +1 -1
  124. package/dist/charts/sparklines/LineSparkline.js +15 -3
  125. package/dist/charts/sparklines/index.d.ts +2 -2
  126. package/dist/charts/sparklines/index.d.ts.map +1 -1
  127. package/dist/charts/utils/format.d.ts +92 -2
  128. package/dist/charts/utils/format.d.ts.map +1 -1
  129. package/dist/charts/utils/format.js +64 -1
  130. package/dist/charts/utils/ticks.d.ts +81 -2
  131. package/dist/charts/utils/ticks.d.ts.map +1 -1
  132. package/dist/charts/utils/ticks.js +54 -4
  133. package/dist/cli/index.d.ts.map +1 -1
  134. package/dist/cli/index.js +2 -2
  135. package/dist/commands/ShortcutsHelp.d.ts +3 -2
  136. package/dist/commands/ShortcutsHelp.d.ts.map +1 -1
  137. package/dist/commands/ShortcutsHelp.js +8 -2
  138. package/dist/commands/define-commands.d.ts.map +1 -1
  139. package/dist/commands/define-commands.js +2 -2
  140. package/dist/commands/define-overlays.d.ts +102 -0
  141. package/dist/commands/define-overlays.d.ts.map +1 -1
  142. package/dist/commands/define-overlays.js +102 -2
  143. package/dist/commands/index.d.ts +10 -1
  144. package/dist/commands/index.d.ts.map +1 -1
  145. package/dist/commands/index.js +3 -1
  146. package/dist/commands/overlays-mount.d.ts +13 -6
  147. package/dist/commands/overlays-mount.d.ts.map +1 -1
  148. package/dist/commands/overlays-mount.js +23 -14
  149. package/dist/common/errors.d.ts +34 -0
  150. package/dist/common/errors.d.ts.map +1 -0
  151. package/dist/common/errors.js +36 -0
  152. package/dist/common/index.d.ts +15 -0
  153. package/dist/common/index.d.ts.map +1 -0
  154. package/dist/common/index.js +29 -0
  155. package/dist/common/props.d.ts +63 -0
  156. package/dist/common/props.d.ts.map +1 -0
  157. package/dist/common/props.js +6 -0
  158. package/dist/common/query-state-like.d.ts +43 -0
  159. package/dist/common/query-state-like.d.ts.map +1 -0
  160. package/dist/common/query-state-like.js +20 -0
  161. package/dist/common/refs.d.ts +29 -0
  162. package/dist/common/refs.d.ts.map +1 -0
  163. package/dist/common/refs.js +29 -0
  164. package/dist/common/scroll-parent.d.ts +23 -0
  165. package/dist/common/scroll-parent.d.ts.map +1 -0
  166. package/dist/common/scroll-parent.js +21 -0
  167. package/dist/common/validate.d.ts +38 -0
  168. package/dist/common/validate.d.ts.map +1 -0
  169. package/dist/common/validate.js +36 -0
  170. package/dist/connectivity/connectivity-indicator.d.ts +3 -1
  171. package/dist/connectivity/connectivity-indicator.d.ts.map +1 -1
  172. package/dist/connectivity/connectivity-indicator.js +3 -1
  173. package/dist/connectivity/connectivity-provider.d.ts.map +1 -1
  174. package/dist/connectivity/connectivity-provider.js +4 -1
  175. package/dist/connectivity/index.d.ts +1 -0
  176. package/dist/connectivity/index.d.ts.map +1 -1
  177. package/dist/connectivity/types.d.ts +2 -2
  178. package/dist/connectivity/types.d.ts.map +1 -1
  179. package/dist/connectivity/use-connectivity.d.ts.map +1 -1
  180. package/dist/content/article-layout.module.css +11 -4
  181. package/dist/content/callout.d.ts +8 -4
  182. package/dist/content/callout.d.ts.map +1 -1
  183. package/dist/content/callout.js +15 -8
  184. package/dist/content/guide.d.ts +5 -4
  185. package/dist/content/guide.d.ts.map +1 -1
  186. package/dist/content/guide.js +13 -4
  187. package/dist/content/heading-anchor.d.ts +24 -2
  188. package/dist/content/heading-anchor.d.ts.map +1 -1
  189. package/dist/content/heading-anchor.js +23 -9
  190. package/dist/content/index.d.ts.map +1 -1
  191. package/dist/content/markdown.d.ts.map +1 -1
  192. package/dist/content/markdown.js +2 -0
  193. package/dist/content/prose.module.css +9 -7
  194. package/dist/content/reading-progress.d.ts +10 -4
  195. package/dist/content/reading-progress.d.ts.map +1 -1
  196. package/dist/content/reading-progress.js +26 -10
  197. package/dist/content/slug.d.ts +4 -0
  198. package/dist/content/slug.d.ts.map +1 -1
  199. package/dist/content/toc.d.ts +11 -0
  200. package/dist/content/toc.d.ts.map +1 -1
  201. package/dist/content/toc.js +23 -10
  202. package/dist/controls/actions.d.ts +49 -6
  203. package/dist/controls/actions.d.ts.map +1 -1
  204. package/dist/controls/actions.js +39 -8
  205. package/dist/controls/compare-filter.d.ts +3 -2
  206. package/dist/controls/compare-filter.d.ts.map +1 -1
  207. package/dist/controls/compare-filter.js +17 -2
  208. package/dist/controls/control-group.d.ts +3 -3
  209. package/dist/controls/control-group.d.ts.map +1 -1
  210. package/dist/controls/control-group.js +9 -2
  211. package/dist/controls/controls.module.css +169 -186
  212. package/dist/controls/controls.module.css.d.ts +9 -11
  213. package/dist/controls/enum-filter.d.ts +3 -2
  214. package/dist/controls/enum-filter.d.ts.map +1 -1
  215. package/dist/controls/enum-filter.js +28 -13
  216. package/dist/controls/filter-context.d.ts +8 -4
  217. package/dist/controls/filter-context.d.ts.map +1 -1
  218. package/dist/controls/filter-pill.d.ts +3 -3
  219. package/dist/controls/filter-pill.d.ts.map +1 -1
  220. package/dist/controls/filter-pill.js +4 -1
  221. package/dist/controls/filter-set.d.ts +3 -2
  222. package/dist/controls/filter-set.d.ts.map +1 -1
  223. package/dist/controls/filter-set.js +66 -41
  224. package/dist/controls/filter-sheet.d.ts +20 -80
  225. package/dist/controls/filter-sheet.d.ts.map +1 -1
  226. package/dist/controls/filter-sheet.js +9 -95
  227. package/dist/controls/index.d.ts +2 -0
  228. package/dist/controls/index.d.ts.map +1 -1
  229. package/dist/controls/index.js +4 -0
  230. package/dist/controls/multi-select-filter.d.ts +18 -2
  231. package/dist/controls/multi-select-filter.d.ts.map +1 -1
  232. package/dist/controls/multi-select-filter.js +122 -20
  233. package/dist/controls/number-filter.d.ts +7 -5
  234. package/dist/controls/number-filter.d.ts.map +1 -1
  235. package/dist/controls/number-filter.js +40 -11
  236. package/dist/controls/panel-row.d.ts +132 -0
  237. package/dist/controls/panel-row.d.ts.map +1 -0
  238. package/dist/controls/panel-row.js +173 -0
  239. package/dist/controls/panel-row.module.css +86 -0
  240. package/dist/controls/panel-row.module.css.d.ts +13 -0
  241. package/dist/controls/range-filter.d.ts +2 -1
  242. package/dist/controls/range-filter.d.ts.map +1 -1
  243. package/dist/controls/range-filter.js +57 -35
  244. package/dist/controls/search-filter.d.ts +3 -2
  245. package/dist/controls/search-filter.d.ts.map +1 -1
  246. package/dist/controls/search-filter.js +25 -10
  247. package/dist/controls/select-filter.d.ts +2 -1
  248. package/dist/controls/select-filter.d.ts.map +1 -1
  249. package/dist/controls/select-filter.js +4 -0
  250. package/dist/controls/slider-control.d.ts +36 -0
  251. package/dist/controls/slider-control.d.ts.map +1 -0
  252. package/dist/controls/slider-control.js +64 -0
  253. package/dist/controls/sync-button.d.ts +3 -2
  254. package/dist/controls/sync-button.d.ts.map +1 -1
  255. package/dist/controls/sync-button.js +16 -3
  256. package/dist/controls/toggle-filter.d.ts +3 -2
  257. package/dist/controls/toggle-filter.d.ts.map +1 -1
  258. package/dist/controls/toggle-filter.js +28 -11
  259. package/dist/controls/view-tabs.d.ts +3 -2
  260. package/dist/controls/view-tabs.d.ts.map +1 -1
  261. package/dist/controls/view-tabs.js +43 -11
  262. package/dist/controls-dates/date-range-picker.d.ts +1 -1
  263. package/dist/controls-dates/date-range-picker.d.ts.map +1 -1
  264. package/dist/controls-dates/date-range-picker.js +6 -1
  265. package/dist/dashboard/delta-badge.d.ts +5 -1
  266. package/dist/dashboard/delta-badge.d.ts.map +1 -1
  267. package/dist/dashboard/empty-state.d.ts +10 -3
  268. package/dist/dashboard/empty-state.d.ts.map +1 -1
  269. package/dist/dashboard/empty-state.js +37 -6
  270. package/dist/dashboard/index.d.ts +6 -4
  271. package/dist/dashboard/index.d.ts.map +1 -1
  272. package/dist/dashboard/index.js +7 -1
  273. package/dist/dashboard/query-state.d.ts +48 -27
  274. package/dist/dashboard/query-state.d.ts.map +1 -1
  275. package/dist/dashboard/query-state.js +111 -57
  276. package/dist/dashboard/settings-section.d.ts +19 -9
  277. package/dist/dashboard/settings-section.d.ts.map +1 -1
  278. package/dist/dashboard/settings-section.js +74 -25
  279. package/dist/dashboard/stat-card.d.ts +44 -38
  280. package/dist/dashboard/stat-card.d.ts.map +1 -1
  281. package/dist/dashboard/stat-card.js +55 -42
  282. package/dist/dashboard/stat-card.module.css +46 -31
  283. package/dist/dashboard/stat-card.module.css.d.ts +1 -0
  284. package/dist/dashboard/stat-group.d.ts +41 -0
  285. package/dist/dashboard/stat-group.d.ts.map +1 -0
  286. package/dist/dashboard/stat-group.js +30 -0
  287. package/dist/dashboard/stat-group.module.css +66 -0
  288. package/dist/dashboard/stat-group.module.css.d.ts +8 -0
  289. package/dist/dashboard/widget-grid.d.ts +27 -0
  290. package/dist/dashboard/widget-grid.d.ts.map +1 -0
  291. package/dist/dashboard/widget-grid.js +41 -0
  292. package/dist/dashboard/widget-grid.module.css +53 -0
  293. package/dist/dashboard/widget-grid.module.css.d.ts +9 -0
  294. package/dist/data/data-table.d.ts +151 -12
  295. package/dist/data/data-table.d.ts.map +1 -1
  296. package/dist/data/data-table.js +384 -138
  297. package/dist/data/data-table.module.css +64 -0
  298. package/dist/data/data-table.module.css.d.ts +11 -0
  299. package/dist/data/index.d.ts +2 -2
  300. package/dist/data/index.d.ts.map +1 -1
  301. package/dist/data/index.js +24 -2
  302. package/dist/data/query-branch.d.ts +28 -0
  303. package/dist/data/query-branch.d.ts.map +1 -0
  304. package/dist/data/query-branch.js +10 -0
  305. package/dist/data/table.d.ts +2 -2
  306. package/dist/data/table.d.ts.map +1 -1
  307. package/dist/data/virtual-list.d.ts +65 -6
  308. package/dist/data/virtual-list.d.ts.map +1 -1
  309. package/dist/data/virtual-list.js +89 -38
  310. package/dist/data/virtual.d.ts +1 -1
  311. package/dist/data/virtual.d.ts.map +1 -1
  312. package/dist/forms/FormErrorSummary.d.ts +4 -3
  313. package/dist/forms/FormErrorSummary.d.ts.map +1 -1
  314. package/dist/forms/FormErrorSummary.js +6 -4
  315. package/dist/forms/create-form.d.ts +2 -2
  316. package/dist/forms/field.d.ts +46 -6
  317. package/dist/forms/field.d.ts.map +1 -1
  318. package/dist/forms/field.js +10 -5
  319. package/dist/forms/form-layout.d.ts +142 -0
  320. package/dist/forms/form-layout.d.ts.map +1 -0
  321. package/dist/forms/form-layout.js +110 -0
  322. package/dist/forms/form-layout.module.css +145 -0
  323. package/dist/forms/form-layout.module.css.d.ts +20 -0
  324. package/dist/forms/form-state.d.ts +42 -0
  325. package/dist/forms/form-state.d.ts.map +1 -0
  326. package/dist/forms/form-state.js +26 -0
  327. package/dist/forms/index.d.ts +22 -6
  328. package/dist/forms/index.d.ts.map +1 -1
  329. package/dist/forms/index.js +19 -3
  330. package/dist/forms/use-field-array.d.ts +60 -0
  331. package/dist/forms/use-field-array.d.ts.map +1 -0
  332. package/dist/forms/use-field-array.js +20 -0
  333. package/dist/forms/use-form-draft.d.ts +25 -10
  334. package/dist/forms/use-form-draft.d.ts.map +1 -1
  335. package/dist/forms/use-form-draft.js +55 -18
  336. package/dist/forms/use-form-submit.d.ts +88 -0
  337. package/dist/forms/use-form-submit.d.ts.map +1 -0
  338. package/dist/forms/use-form-submit.js +63 -0
  339. package/dist/guard/index.d.ts.map +1 -1
  340. package/dist/guard/index.js +26 -6
  341. package/dist/index.d.ts +10 -8
  342. package/dist/index.d.ts.map +1 -1
  343. package/dist/index.js +44 -4
  344. package/dist/nav/types.d.ts +15 -6
  345. package/dist/nav/types.d.ts.map +1 -1
  346. package/dist/notifications/bell.d.ts +3 -2
  347. package/dist/notifications/bell.d.ts.map +1 -1
  348. package/dist/notifications/bell.js +73 -56
  349. package/dist/notifications/center.d.ts +15 -4
  350. package/dist/notifications/center.d.ts.map +1 -1
  351. package/dist/notifications/center.js +5 -2
  352. package/dist/notifications/define-notifications.d.ts +56 -14
  353. package/dist/notifications/define-notifications.d.ts.map +1 -1
  354. package/dist/notifications/define-notifications.js +2 -1
  355. package/dist/notifications/index.d.ts +6 -2
  356. package/dist/notifications/index.d.ts.map +1 -1
  357. package/dist/notifications/index.js +5 -1
  358. package/dist/notifications/mount-guard.d.ts +8 -0
  359. package/dist/notifications/mount-guard.d.ts.map +1 -0
  360. package/dist/notifications/mount-guard.js +19 -0
  361. package/dist/notifications/notify.d.ts +58 -1
  362. package/dist/notifications/notify.d.ts.map +1 -1
  363. package/dist/notifications/notify.js +46 -2
  364. package/dist/notifications/overlay.d.ts.map +1 -1
  365. package/dist/notifications/overlay.js +2 -0
  366. package/dist/notifications/store.d.ts +7 -0
  367. package/dist/notifications/store.d.ts.map +1 -1
  368. package/dist/provider/index.d.ts +37 -5
  369. package/dist/provider/index.d.ts.map +1 -1
  370. package/dist/provider/index.js +66 -28
  371. package/dist/provider/lab-theme.d.ts.map +1 -1
  372. package/dist/provider/lab-theme.js +2 -1
  373. package/dist/query/devtools.d.ts.map +1 -1
  374. package/dist/query/devtools.js +1 -0
  375. package/dist/router-tanstack/field.d.ts +1 -1
  376. package/dist/router-tanstack/field.d.ts.map +1 -1
  377. package/dist/router-tanstack/search-store.d.ts.map +1 -1
  378. package/dist/router-tanstack/search-store.js +1 -1
  379. package/dist/router-tanstack/use-nav.d.ts.map +1 -1
  380. package/dist/router-tanstack/use-nav.js +1 -1
  381. package/dist/section/index.d.ts +1 -1
  382. package/dist/section/index.d.ts.map +1 -1
  383. package/dist/section/section.d.ts +36 -2
  384. package/dist/section/section.d.ts.map +1 -1
  385. package/dist/section/section.js +49 -57
  386. package/dist/section/section.module.css +11 -0
  387. package/dist/shell/account-types.d.ts +5 -2
  388. package/dist/shell/account-types.d.ts.map +1 -1
  389. package/dist/shell/app-brand.d.ts +13 -0
  390. package/dist/shell/app-brand.d.ts.map +1 -0
  391. package/dist/shell/app-brand.js +94 -0
  392. package/dist/shell/app-brand.module.css +109 -0
  393. package/dist/shell/app-brand.module.css.d.ts +14 -0
  394. package/dist/shell/app-breadcrumbs.d.ts +4 -2
  395. package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
  396. package/dist/shell/app-breadcrumbs.js +33 -22
  397. package/dist/shell/app-header.module.css +10 -5
  398. package/dist/shell/app-main.module.css +107 -0
  399. package/dist/shell/app-main.module.css.d.ts +11 -0
  400. package/dist/shell/app-mobile-nav.d.ts +3 -2
  401. package/dist/shell/app-mobile-nav.d.ts.map +1 -1
  402. package/dist/shell/app-mobile-nav.js +29 -15
  403. package/dist/shell/app-mobile-nav.module.css +48 -27
  404. package/dist/shell/app-mobile-nav.module.css.d.ts +0 -1
  405. package/dist/shell/app-sidebar-account.d.ts +2 -1
  406. package/dist/shell/app-sidebar-account.d.ts.map +1 -1
  407. package/dist/shell/app-sidebar-account.js +57 -22
  408. package/dist/shell/app-sidebar.d.ts +9 -3
  409. package/dist/shell/app-sidebar.d.ts.map +1 -1
  410. package/dist/shell/app-sidebar.js +55 -109
  411. package/dist/shell/app-sidebar.module.css +53 -96
  412. package/dist/shell/app-sidebar.module.css.d.ts +0 -5
  413. package/dist/shell/index.d.ts +14 -6
  414. package/dist/shell/index.d.ts.map +1 -1
  415. package/dist/shell/index.js +47 -12
  416. package/dist/shell/isomorphic-layout-effect.d.ts +14 -0
  417. package/dist/shell/isomorphic-layout-effect.d.ts.map +1 -0
  418. package/dist/shell/isomorphic-layout-effect.js +5 -0
  419. package/dist/shell/mobile-nav-model.d.ts.map +1 -1
  420. package/dist/shell/mobile-nav-model.js +27 -6
  421. package/dist/shell/nav-count-badge.d.ts +5 -3
  422. package/dist/shell/nav-count-badge.d.ts.map +1 -1
  423. package/dist/shell/nav-count-badge.js +3 -1
  424. package/dist/shell/page-aside.d.ts +43 -0
  425. package/dist/shell/page-aside.d.ts.map +1 -0
  426. package/dist/shell/page-aside.js +202 -0
  427. package/dist/shell/page-aside.module.css +174 -0
  428. package/dist/shell/page-aside.module.css.d.ts +14 -0
  429. package/dist/shell/page-bar.d.ts +55 -15
  430. package/dist/shell/page-bar.d.ts.map +1 -1
  431. package/dist/shell/page-bar.js +130 -41
  432. package/dist/shell/page-bar.module.css +107 -13
  433. package/dist/shell/page-bar.module.css.d.ts +4 -1
  434. package/dist/shell/sidebar-search.d.ts +4 -2
  435. package/dist/shell/sidebar-search.d.ts.map +1 -1
  436. package/dist/shell/sidebar-search.js +9 -4
  437. package/dist/shell/sidebar-search.module.css +1 -1
  438. package/dist/state/fields.d.ts +23 -3
  439. package/dist/state/fields.d.ts.map +1 -1
  440. package/dist/state/fields.js +13 -2
  441. package/dist/state/persisted-or-local.d.ts +9 -0
  442. package/dist/state/persisted-or-local.d.ts.map +1 -0
  443. package/dist/state/persisted-or-local.js +24 -0
  444. package/dist/state.d.ts +1 -1
  445. package/dist/state.d.ts.map +1 -1
  446. package/dist/state.js +2 -6
  447. package/dist/surfaces.d.ts +12 -11
  448. package/dist/surfaces.d.ts.map +1 -1
  449. package/dist/surfaces.js +42 -12
  450. package/dist/theme/ctl-theme.d.ts.map +1 -1
  451. package/dist/theme/index.d.ts.map +1 -1
  452. package/dist/theme/index.js +102 -17
  453. package/dist/theme/nav-link.module.css +37 -26
  454. package/dist/theme/segmented-control.module.css +22 -0
  455. package/dist/theme/segmented-control.module.css.d.ts +1 -0
  456. package/dist/theme-lab/boot.d.ts +66 -0
  457. package/dist/theme-lab/boot.d.ts.map +1 -0
  458. package/dist/theme-lab/boot.js +82 -0
  459. package/dist/theme-lab/index.d.ts +4 -43
  460. package/dist/theme-lab/index.d.ts.map +1 -1
  461. package/dist/theme-lab/index.js +9 -69
  462. package/dist/theme-toggle/index.d.ts +3 -2
  463. package/dist/theme-toggle/index.d.ts.map +1 -1
  464. package/dist/theme-toggle/index.js +8 -2
  465. package/dist/tokens/index.d.ts +42 -0
  466. package/dist/tokens/index.d.ts.map +1 -1
  467. package/dist/tokens/index.js +35 -6
  468. package/dist/tokens/palette.d.ts +45 -25
  469. package/dist/tokens/palette.d.ts.map +1 -1
  470. package/dist/tokens/palette.js +31 -14
  471. package/dist/tokens.css +4 -5
  472. package/dist/utils/is-dev.d.ts +3 -0
  473. package/dist/utils/is-dev.d.ts.map +1 -0
  474. package/dist/utils/is-dev.js +6 -0
  475. package/dist/widget-header/delta-badge.d.ts +7 -1
  476. package/dist/widget-header/delta-badge.d.ts.map +1 -1
  477. package/dist/widget-header/delta-badge.js +8 -1
  478. package/dist/widget-header/index.d.ts +2 -2
  479. package/dist/widget-header/index.d.ts.map +1 -1
  480. package/dist/widget-header/index.js +3 -1
  481. package/dist/widget-header/widget-header.d.ts +69 -4
  482. package/dist/widget-header/widget-header.d.ts.map +1 -1
  483. package/dist/widget-header/widget-header.js +42 -27
  484. package/dist/widget-header/widget-header.module.css +72 -7
  485. package/llms.txt +6 -6
  486. package/package.json +49 -25
  487. package/src/agent/coalesce.ts +2 -1
  488. package/src/agent/merge.ts +2 -1
  489. package/src/agent/part-list.tsx +2 -0
  490. package/src/agent/stick-to-bottom.tsx +9 -11
  491. package/src/agent-chat/composer.tsx +124 -103
  492. package/src/agent-chat/relative-time.ts +2 -1
  493. package/src/agent-chat/thread-detail-panel.tsx +9 -5
  494. package/src/agent-chat/thread-feed-row.tsx +17 -9
  495. package/src/agent-chat/thread-feed.tsx +9 -3
  496. package/src/agent-chat/thread-message.tsx +48 -13
  497. package/src/agent-chat/thread-outcome-card.tsx +9 -1
  498. package/src/agent-chat/thread-workspace.tsx +72 -33
  499. package/src/agent-chat/tool-chip.tsx +8 -2
  500. package/src/charts/hooks/useBandPlot.ts +26 -8
  501. package/src/charts/index.ts +39 -4
  502. package/src/charts/kinds/BandStrip.tsx +36 -14
  503. package/src/charts/kinds/Bars.tsx +67 -16
  504. package/src/charts/kinds/Donut.tsx +30 -3
  505. package/src/charts/kinds/DualPanel.tsx +56 -10
  506. package/src/charts/kinds/Heatmap.tsx +90 -33
  507. package/src/charts/kinds/MirroredBars.tsx +21 -3
  508. package/src/charts/kinds/MultiLine.tsx +61 -18
  509. package/src/charts/kinds/StackedArea.tsx +77 -6
  510. package/src/charts/kinds/ZonedLine.tsx +71 -31
  511. package/src/charts/layout/auto-margin.ts +134 -21
  512. package/src/charts/layout/log-ticks.ts +90 -0
  513. package/src/charts/primitives/Axes.tsx +33 -5
  514. package/src/charts/primitives/CartesianChart.tsx +194 -41
  515. package/src/charts/primitives/ChartCard.tsx +66 -25
  516. package/src/charts/primitives/ChartFrame.tsx +107 -26
  517. package/src/charts/primitives/ChartLegend.tsx +43 -13
  518. package/src/charts/primitives/ChartPending.tsx +185 -7
  519. package/src/charts/primitives/ChartTooltip.tsx +37 -5
  520. package/src/charts/primitives/Crosshair.tsx +6 -3
  521. package/src/charts/primitives/chart-frame-layout.ts +212 -0
  522. package/src/charts/primitives/chart-tier.tsx +37 -0
  523. package/src/charts/series.ts +77 -1
  524. package/src/charts/sparklines/BarSparkline.tsx +11 -3
  525. package/src/charts/sparklines/LineSparkline.tsx +18 -4
  526. package/src/charts/sparklines/index.ts +2 -2
  527. package/src/charts/utils/format.ts +163 -2
  528. package/src/charts/utils/ticks.ts +149 -4
  529. package/src/cli/index.ts +8 -3
  530. package/src/commands/ShortcutsHelp.tsx +10 -3
  531. package/src/commands/define-commands.ts +2 -2
  532. package/src/commands/define-overlays.ts +216 -1
  533. package/src/commands/index.ts +12 -0
  534. package/src/commands/overlays-mount.tsx +60 -26
  535. package/src/common/errors.ts +73 -0
  536. package/src/common/index.ts +21 -0
  537. package/src/common/props.ts +71 -0
  538. package/src/common/query-state-like.ts +64 -0
  539. package/src/common/refs.ts +58 -0
  540. package/src/common/scroll-parent.ts +42 -0
  541. package/src/common/validate.ts +94 -0
  542. package/src/connectivity/connectivity-indicator.tsx +6 -1
  543. package/src/connectivity/connectivity-provider.tsx +4 -1
  544. package/src/connectivity/index.ts +1 -0
  545. package/src/connectivity/types.ts +5 -2
  546. package/src/connectivity/use-connectivity.ts +3 -2
  547. package/src/content/article-layout.module.css +11 -4
  548. package/src/content/callout.tsx +13 -7
  549. package/src/content/guide.tsx +14 -4
  550. package/src/content/heading-anchor.tsx +14 -3
  551. package/src/content/index.ts +2 -0
  552. package/src/content/markdown.tsx +2 -0
  553. package/src/content/prose.module.css +9 -7
  554. package/src/content/reading-progress.tsx +40 -15
  555. package/src/content/slug.ts +4 -0
  556. package/src/content/toc.tsx +47 -10
  557. package/src/controls/actions.tsx +89 -9
  558. package/src/controls/compare-filter.tsx +20 -3
  559. package/src/controls/control-group.tsx +11 -4
  560. package/src/controls/controls.module.css +169 -186
  561. package/src/controls/controls.module.css.d.ts +9 -11
  562. package/src/controls/enum-filter.tsx +32 -16
  563. package/src/controls/filter-context.tsx +14 -6
  564. package/src/controls/filter-pill.tsx +6 -3
  565. package/src/controls/filter-set.tsx +32 -13
  566. package/src/controls/filter-sheet.tsx +44 -194
  567. package/src/controls/index.ts +7 -0
  568. package/src/controls/multi-select-filter.tsx +177 -27
  569. package/src/controls/number-filter.tsx +61 -23
  570. package/src/controls/panel-row.module.css +86 -0
  571. package/src/controls/panel-row.module.css.d.ts +13 -0
  572. package/src/controls/panel-row.tsx +392 -0
  573. package/src/controls/range-filter.tsx +76 -39
  574. package/src/controls/search-filter.tsx +30 -12
  575. package/src/controls/select-filter.tsx +11 -1
  576. package/src/controls/slider-control.tsx +159 -0
  577. package/src/controls/sync-button.tsx +13 -3
  578. package/src/controls/toggle-filter.tsx +36 -16
  579. package/src/controls/view-tabs.tsx +63 -11
  580. package/src/controls-dates/date-range-picker.tsx +8 -1
  581. package/src/dashboard/delta-badge.tsx +5 -1
  582. package/src/dashboard/empty-state.tsx +72 -25
  583. package/src/dashboard/index.ts +13 -1
  584. package/src/dashboard/query-state.tsx +154 -84
  585. package/src/dashboard/settings-section.tsx +87 -31
  586. package/src/dashboard/stat-card.module.css +46 -31
  587. package/src/dashboard/stat-card.module.css.d.ts +1 -0
  588. package/src/dashboard/stat-card.tsx +185 -127
  589. package/src/dashboard/stat-group.module.css +66 -0
  590. package/src/dashboard/stat-group.module.css.d.ts +8 -0
  591. package/src/dashboard/stat-group.tsx +74 -0
  592. package/src/dashboard/widget-grid.module.css +53 -0
  593. package/src/dashboard/widget-grid.module.css.d.ts +9 -0
  594. package/src/dashboard/widget-grid.tsx +127 -0
  595. package/src/data/data-table.module.css +64 -0
  596. package/src/data/data-table.module.css.d.ts +11 -0
  597. package/src/data/data-table.tsx +919 -346
  598. package/src/data/index.ts +30 -2
  599. package/src/data/query-branch.ts +53 -0
  600. package/src/data/table.ts +5 -0
  601. package/src/data/virtual-list.tsx +189 -55
  602. package/src/data/virtual.ts +5 -1
  603. package/src/forms/FormErrorSummary.tsx +13 -6
  604. package/src/forms/create-form.ts +2 -2
  605. package/src/forms/field.ts +60 -11
  606. package/src/forms/form-layout.module.css +145 -0
  607. package/src/forms/form-layout.module.css.d.ts +20 -0
  608. package/src/forms/form-layout.tsx +305 -0
  609. package/src/forms/form-state.tsx +94 -0
  610. package/src/forms/index.ts +38 -7
  611. package/src/forms/use-field-array.ts +94 -0
  612. package/src/forms/use-form-draft.ts +145 -53
  613. package/src/forms/use-form-submit.ts +199 -0
  614. package/src/guard/index.ts +73 -18
  615. package/src/index.ts +74 -10
  616. package/src/nav/types.ts +15 -6
  617. package/src/notifications/bell.tsx +18 -4
  618. package/src/notifications/center.tsx +18 -5
  619. package/src/notifications/define-notifications.ts +64 -18
  620. package/src/notifications/index.ts +12 -1
  621. package/src/notifications/mount-guard.ts +41 -0
  622. package/src/notifications/notify.tsx +122 -3
  623. package/src/notifications/overlay.tsx +2 -0
  624. package/src/notifications/store.ts +7 -0
  625. package/src/provider/index.tsx +101 -13
  626. package/src/provider/lab-theme.ts +2 -1
  627. package/src/query/devtools.tsx +1 -0
  628. package/src/router-tanstack/field.ts +1 -0
  629. package/src/router-tanstack/search-store.ts +3 -10
  630. package/src/router-tanstack/use-nav.ts +18 -13
  631. package/src/section/index.ts +1 -1
  632. package/src/section/section.module.css +11 -0
  633. package/src/section/section.tsx +163 -96
  634. package/src/shell/account-types.ts +5 -2
  635. package/src/shell/app-brand.module.css +109 -0
  636. package/src/shell/app-brand.module.css.d.ts +14 -0
  637. package/src/shell/app-brand.tsx +140 -0
  638. package/src/shell/app-breadcrumbs.tsx +19 -9
  639. package/src/shell/app-header.module.css +10 -5
  640. package/src/shell/app-main.module.css +107 -0
  641. package/src/shell/app-main.module.css.d.ts +11 -0
  642. package/src/shell/app-mobile-nav.module.css +48 -27
  643. package/src/shell/app-mobile-nav.module.css.d.ts +0 -1
  644. package/src/shell/app-mobile-nav.tsx +43 -11
  645. package/src/shell/app-sidebar-account.tsx +29 -6
  646. package/src/shell/app-sidebar.module.css +53 -96
  647. package/src/shell/app-sidebar.module.css.d.ts +0 -5
  648. package/src/shell/app-sidebar.tsx +40 -113
  649. package/src/shell/index.tsx +156 -65
  650. package/src/shell/isomorphic-layout-effect.ts +14 -0
  651. package/src/shell/mobile-nav-model.ts +66 -10
  652. package/src/shell/nav-count-badge.tsx +6 -1
  653. package/src/shell/page-aside.module.css +174 -0
  654. package/src/shell/page-aside.module.css.d.ts +14 -0
  655. package/src/shell/page-aside.tsx +377 -0
  656. package/src/shell/page-bar.module.css +107 -13
  657. package/src/shell/page-bar.module.css.d.ts +4 -1
  658. package/src/shell/page-bar.tsx +294 -94
  659. package/src/shell/sidebar-search.module.css +1 -1
  660. package/src/shell/sidebar-search.tsx +13 -4
  661. package/src/state/fields.ts +43 -10
  662. package/src/state/persisted-or-local.ts +50 -0
  663. package/src/state.ts +0 -9
  664. package/src/surfaces.ts +42 -12
  665. package/src/theme/ctl-theme.tsx +10 -0
  666. package/src/theme/index.ts +129 -16
  667. package/src/theme/nav-link.module.css +37 -26
  668. package/src/theme/segmented-control.module.css +22 -0
  669. package/src/theme/segmented-control.module.css.d.ts +1 -0
  670. package/src/theme-lab/boot.ts +140 -0
  671. package/src/theme-lab/index.tsx +21 -112
  672. package/src/theme-toggle/index.tsx +10 -3
  673. package/src/tokens/index.ts +50 -6
  674. package/src/tokens/palette.ts +58 -30
  675. package/src/utils/is-dev.ts +4 -0
  676. package/src/widget-header/delta-badge.tsx +25 -5
  677. package/src/widget-header/index.ts +10 -2
  678. package/src/widget-header/widget-header.module.css +72 -7
  679. package/src/widget-header/widget-header.tsx +150 -71
  680. package/dist/agent/adapter.test.d.ts +0 -2
  681. package/dist/agent/adapter.test.d.ts.map +0 -1
  682. package/dist/agent/ai-sdk-transport.test.d.ts +0 -2
  683. package/dist/agent/ai-sdk-transport.test.d.ts.map +0 -1
  684. package/dist/agent/coalesce.test.d.ts +0 -2
  685. package/dist/agent/coalesce.test.d.ts.map +0 -1
  686. package/dist/agent/foreign.test.d.ts +0 -2
  687. package/dist/agent/foreign.test.d.ts.map +0 -1
  688. package/dist/agent/id.test.d.ts +0 -2
  689. package/dist/agent/id.test.d.ts.map +0 -1
  690. package/dist/agent/merge.test.d.ts +0 -2
  691. package/dist/agent/merge.test.d.ts.map +0 -1
  692. package/dist/agent/part-list.test.d.ts +0 -2
  693. package/dist/agent/part-list.test.d.ts.map +0 -1
  694. package/dist/agent/parts.test.d.ts +0 -2
  695. package/dist/agent/parts.test.d.ts.map +0 -1
  696. package/dist/agent/thread.test.d.ts +0 -2
  697. package/dist/agent/thread.test.d.ts.map +0 -1
  698. package/dist/agent/transport.test.d.ts +0 -2
  699. package/dist/agent/transport.test.d.ts.map +0 -1
  700. package/dist/agent/use-agent-stream.test.d.ts +0 -2
  701. package/dist/agent/use-agent-stream.test.d.ts.map +0 -1
  702. package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +0 -2
  703. package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +0 -1
  704. package/dist/agent/use-agent-thread-runs.resume.test.d.ts +0 -2
  705. package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +0 -1
  706. package/dist/agent/use-agent-thread-runs.test.d.ts +0 -2
  707. package/dist/agent/use-agent-thread-runs.test.d.ts.map +0 -1
  708. package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +0 -2
  709. package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +0 -1
  710. package/dist/agent-chat/composer.test.d.ts +0 -2
  711. package/dist/agent-chat/composer.test.d.ts.map +0 -1
  712. package/dist/agent-chat/relative-time.test.d.ts +0 -2
  713. package/dist/agent-chat/relative-time.test.d.ts.map +0 -1
  714. package/dist/agent-chat/thread-feed-row.test.d.ts +0 -2
  715. package/dist/agent-chat/thread-feed-row.test.d.ts.map +0 -1
  716. package/dist/agent-chat/thread-feed.test.d.ts +0 -2
  717. package/dist/agent-chat/thread-feed.test.d.ts.map +0 -1
  718. package/dist/agent-chat/thread-message.test.d.ts +0 -2
  719. package/dist/agent-chat/thread-message.test.d.ts.map +0 -1
  720. package/dist/agent-chat/thread-workspace.test.d.ts +0 -2
  721. package/dist/agent-chat/thread-workspace.test.d.ts.map +0 -1
  722. package/dist/agent-chat/tool-chip.test.d.ts +0 -2
  723. package/dist/agent-chat/tool-chip.test.d.ts.map +0 -1
  724. package/dist/agent-chat/virtualize.type-guard.test.d.ts +0 -2
  725. package/dist/agent-chat/virtualize.type-guard.test.d.ts.map +0 -1
  726. package/dist/charts/cursor/resolve.test.d.ts +0 -2
  727. package/dist/charts/cursor/resolve.test.d.ts.map +0 -1
  728. package/dist/charts/cursor/store.test.d.ts +0 -2
  729. package/dist/charts/cursor/store.test.d.ts.map +0 -1
  730. package/dist/charts/kinds/BandStrip.test.d.ts +0 -2
  731. package/dist/charts/kinds/BandStrip.test.d.ts.map +0 -1
  732. package/dist/charts/kinds/Bars.test.d.ts +0 -2
  733. package/dist/charts/kinds/Bars.test.d.ts.map +0 -1
  734. package/dist/charts/kinds/DualPanel.test.d.ts +0 -2
  735. package/dist/charts/kinds/DualPanel.test.d.ts.map +0 -1
  736. package/dist/charts/kinds/MirroredBars.test.d.ts +0 -2
  737. package/dist/charts/kinds/MirroredBars.test.d.ts.map +0 -1
  738. package/dist/charts/kinds/MultiLine.test.d.ts +0 -2
  739. package/dist/charts/kinds/MultiLine.test.d.ts.map +0 -1
  740. package/dist/charts/kinds/StackedArea.test.d.ts +0 -2
  741. package/dist/charts/kinds/StackedArea.test.d.ts.map +0 -1
  742. package/dist/charts/kinds/ZonedLine.test.d.ts +0 -2
  743. package/dist/charts/kinds/ZonedLine.test.d.ts.map +0 -1
  744. package/dist/charts/layout/auto-margin.test.d.ts +0 -2
  745. package/dist/charts/layout/auto-margin.test.d.ts.map +0 -1
  746. package/dist/charts/primitives/CartesianChart.test.d.ts +0 -2
  747. package/dist/charts/primitives/CartesianChart.test.d.ts.map +0 -1
  748. package/dist/charts/primitives/ChartCard.test.d.ts +0 -2
  749. package/dist/charts/primitives/ChartCard.test.d.ts.map +0 -1
  750. package/dist/charts/primitives/ChartFrame.test.d.ts +0 -2
  751. package/dist/charts/primitives/ChartFrame.test.d.ts.map +0 -1
  752. package/dist/charts/primitives/ChartLegend.test.d.ts +0 -2
  753. package/dist/charts/primitives/ChartLegend.test.d.ts.map +0 -1
  754. package/dist/charts/primitives/ChartTooltip.test.d.ts +0 -2
  755. package/dist/charts/primitives/ChartTooltip.test.d.ts.map +0 -1
  756. package/dist/charts/primitives/XZoneRects.test.d.ts +0 -2
  757. package/dist/charts/primitives/XZoneRects.test.d.ts.map +0 -1
  758. package/dist/charts/series.test.d.ts +0 -2
  759. package/dist/charts/series.test.d.ts.map +0 -1
  760. package/dist/charts/utils/domain.test.d.ts +0 -2
  761. package/dist/charts/utils/domain.test.d.ts.map +0 -1
  762. package/dist/charts/utils/measure-text.test.d.ts +0 -2
  763. package/dist/charts/utils/measure-text.test.d.ts.map +0 -1
  764. package/dist/cli/check-coverage.test.d.ts +0 -2
  765. package/dist/cli/check-coverage.test.d.ts.map +0 -1
  766. package/dist/cli/check-theme.test.d.ts +0 -2
  767. package/dist/cli/check-theme.test.d.ts.map +0 -1
  768. package/dist/cli/help.test.d.ts +0 -2
  769. package/dist/cli/help.test.d.ts.map +0 -1
  770. package/dist/cli/init-sync.test.d.ts +0 -2
  771. package/dist/cli/init-sync.test.d.ts.map +0 -1
  772. package/dist/cli/placement-engine.test.d.ts +0 -2
  773. package/dist/cli/placement-engine.test.d.ts.map +0 -1
  774. package/dist/cli/shipped-versions.test.d.ts +0 -2
  775. package/dist/cli/shipped-versions.test.d.ts.map +0 -1
  776. package/dist/cli/tarball-parity.test.d.ts +0 -2
  777. package/dist/cli/tarball-parity.test.d.ts.map +0 -1
  778. package/dist/cli/template-format.test.d.ts +0 -2
  779. package/dist/cli/template-format.test.d.ts.map +0 -1
  780. package/dist/cli/template-ledger.test.d.ts +0 -2
  781. package/dist/cli/template-ledger.test.d.ts.map +0 -1
  782. package/dist/cli/tokens-css.test.d.ts +0 -2
  783. package/dist/cli/tokens-css.test.d.ts.map +0 -1
  784. package/dist/cli/toolchain-wiring.test.d.ts +0 -2
  785. package/dist/cli/toolchain-wiring.test.d.ts.map +0 -1
  786. package/dist/cli/waiver-audit.test.d.ts +0 -2
  787. package/dist/cli/waiver-audit.test.d.ts.map +0 -1
  788. package/dist/content/article-actions.test.d.ts +0 -2
  789. package/dist/content/article-actions.test.d.ts.map +0 -1
  790. package/dist/content/article-model.test.d.ts +0 -2
  791. package/dist/content/article-model.test.d.ts.map +0 -1
  792. package/dist/content/block-split.test.d.ts +0 -2
  793. package/dist/content/block-split.test.d.ts.map +0 -1
  794. package/dist/content/heading-components.test.d.ts +0 -2
  795. package/dist/content/heading-components.test.d.ts.map +0 -1
  796. package/dist/content/markdown.test.d.ts +0 -2
  797. package/dist/content/markdown.test.d.ts.map +0 -1
  798. package/dist/content/prose.module.css.test.d.ts +0 -2
  799. package/dist/content/prose.module.css.test.d.ts.map +0 -1
  800. package/dist/content/sanitize.test.d.ts +0 -2
  801. package/dist/content/sanitize.test.d.ts.map +0 -1
  802. package/dist/content/slug.test.d.ts +0 -2
  803. package/dist/content/slug.test.d.ts.map +0 -1
  804. package/dist/controls/actions.test.d.ts +0 -2
  805. package/dist/controls/actions.test.d.ts.map +0 -1
  806. package/dist/controls/actions.type-guard.test.d.ts +0 -2
  807. package/dist/controls/actions.type-guard.test.d.ts.map +0 -1
  808. package/dist/controls/control-group.test.d.ts +0 -2
  809. package/dist/controls/control-group.test.d.ts.map +0 -1
  810. package/dist/controls/controls.router.test.d.ts +0 -2
  811. package/dist/controls/controls.router.test.d.ts.map +0 -1
  812. package/dist/controls/filter-set.test.d.ts +0 -2
  813. package/dist/controls/filter-set.test.d.ts.map +0 -1
  814. package/dist/controls/peer-boundary.test.d.ts +0 -2
  815. package/dist/controls/peer-boundary.test.d.ts.map +0 -1
  816. package/dist/controls/props-contract.test.d.ts +0 -2
  817. package/dist/controls/props-contract.test.d.ts.map +0 -1
  818. package/dist/controls/range-filter.type-guard.test.d.ts +0 -2
  819. package/dist/controls/range-filter.type-guard.test.d.ts.map +0 -1
  820. package/dist/controls/sync-button.test.d.ts +0 -2
  821. package/dist/controls/sync-button.test.d.ts.map +0 -1
  822. package/dist/dashboard/query-state.test.d.ts +0 -2
  823. package/dist/dashboard/query-state.test.d.ts.map +0 -1
  824. package/dist/dashboard/settings-section.test.d.ts +0 -2
  825. package/dist/dashboard/settings-section.test.d.ts.map +0 -1
  826. package/dist/dashboard/stat-card.test.d.ts +0 -2
  827. package/dist/dashboard/stat-card.test.d.ts.map +0 -1
  828. package/dist/data/data-table.test.d.ts +0 -2
  829. package/dist/data/data-table.test.d.ts.map +0 -1
  830. package/dist/guard/check-source.test.d.ts +0 -2
  831. package/dist/guard/check-source.test.d.ts.map +0 -1
  832. package/dist/guard/grace.test.d.ts +0 -20
  833. package/dist/guard/grace.test.d.ts.map +0 -1
  834. package/dist/guard/guard-hook.test.d.ts +0 -2
  835. package/dist/guard/guard-hook.test.d.ts.map +0 -1
  836. package/dist/provider/index.test.d.ts +0 -2
  837. package/dist/provider/index.test.d.ts.map +0 -1
  838. package/dist/provider/lab-theme.test.d.ts +0 -2
  839. package/dist/provider/lab-theme.test.d.ts.map +0 -1
  840. package/dist/query/error-message.test.d.ts +0 -2
  841. package/dist/query/error-message.test.d.ts.map +0 -1
  842. package/dist/router-tanstack/multi-search-param-store.test.d.ts +0 -2
  843. package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +0 -1
  844. package/dist/router-tanstack/nav.test.d.ts +0 -2
  845. package/dist/router-tanstack/nav.test.d.ts.map +0 -1
  846. package/dist/router-tanstack/search-param-store.test.d.ts +0 -2
  847. package/dist/router-tanstack/search-param-store.test.d.ts.map +0 -1
  848. package/dist/router-tanstack/search-store.router.test.d.ts +0 -2
  849. package/dist/router-tanstack/search-store.router.test.d.ts.map +0 -1
  850. package/dist/router-tanstack/search-store.test.d.ts +0 -2
  851. package/dist/router-tanstack/search-store.test.d.ts.map +0 -1
  852. package/dist/router-tanstack/use-nav.test.d.ts +0 -2
  853. package/dist/router-tanstack/use-nav.test.d.ts.map +0 -1
  854. package/dist/section/section.test.d.ts +0 -2
  855. package/dist/section/section.test.d.ts.map +0 -1
  856. package/dist/shell/app-mobile-nav.test.d.ts +0 -2
  857. package/dist/shell/app-mobile-nav.test.d.ts.map +0 -1
  858. package/dist/shell/app-sidebar.test.d.ts +0 -2
  859. package/dist/shell/app-sidebar.test.d.ts.map +0 -1
  860. package/dist/shell/index.test.d.ts +0 -2
  861. package/dist/shell/index.test.d.ts.map +0 -1
  862. package/dist/shell/mobile-nav-model.test.d.ts +0 -2
  863. package/dist/shell/mobile-nav-model.test.d.ts.map +0 -1
  864. package/dist/shell/page-bar.test.d.ts +0 -2
  865. package/dist/shell/page-bar.test.d.ts.map +0 -1
  866. package/dist/state/fields.test.d.ts +0 -2
  867. package/dist/state/fields.test.d.ts.map +0 -1
  868. package/dist/state/persisted.test.d.ts +0 -2
  869. package/dist/state/persisted.test.d.ts.map +0 -1
  870. package/dist/styles.floor.test.d.ts +0 -2
  871. package/dist/styles.floor.test.d.ts.map +0 -1
  872. package/dist/theme/border-coverage.test.d.ts +0 -18
  873. package/dist/theme/border-coverage.test.d.ts.map +0 -1
  874. package/dist/theme/contrast.test.d.ts +0 -2
  875. package/dist/theme/contrast.test.d.ts.map +0 -1
  876. package/dist/theme/ctl-theme.test.d.ts +0 -2
  877. package/dist/theme/ctl-theme.test.d.ts.map +0 -1
  878. package/dist/theme/ctl-tier-coverage.test.d.ts +0 -2
  879. package/dist/theme/ctl-tier-coverage.test.d.ts.map +0 -1
  880. package/dist/theme/density-option.test.d.ts +0 -2
  881. package/dist/theme/density-option.test.d.ts.map +0 -1
  882. package/dist/theme/density-relations.test.d.ts +0 -2
  883. package/dist/theme/density-relations.test.d.ts.map +0 -1
  884. package/dist/theme/derive-theme.test.d.ts +0 -2
  885. package/dist/theme/derive-theme.test.d.ts.map +0 -1
  886. package/dist/theme/divider-law.test.d.ts +0 -2
  887. package/dist/theme/divider-law.test.d.ts.map +0 -1
  888. package/dist/theme/fonts-option.test.d.ts +0 -2
  889. package/dist/theme/fonts-option.test.d.ts.map +0 -1
  890. package/dist/theme/icon-slot.test.d.ts +0 -2
  891. package/dist/theme/icon-slot.test.d.ts.map +0 -1
  892. package/dist/theme/layout-rhythm-css.test.d.ts +0 -2
  893. package/dist/theme/layout-rhythm-css.test.d.ts.map +0 -1
  894. package/dist/theme/radius-option.test.d.ts +0 -2
  895. package/dist/theme/radius-option.test.d.ts.map +0 -1
  896. package/dist/theme/radius.test.d.ts +0 -2
  897. package/dist/theme/radius.test.d.ts.map +0 -1
  898. package/dist/theme/shadow-surfaces.test.d.ts +0 -26
  899. package/dist/theme/shadow-surfaces.test.d.ts.map +0 -1
  900. package/dist/theme/spacing.test.d.ts +0 -2
  901. package/dist/theme/spacing.test.d.ts.map +0 -1
  902. package/dist/theme/use-basalt-spacing.test.d.ts +0 -2
  903. package/dist/theme/use-basalt-spacing.test.d.ts.map +0 -1
  904. package/dist/theme-lab/derive-controls.test.d.ts +0 -2
  905. package/dist/theme-lab/derive-controls.test.d.ts.map +0 -1
  906. package/dist/theme-lab/derive-state.test.d.ts +0 -2
  907. package/dist/theme-lab/derive-state.test.d.ts.map +0 -1
  908. package/dist/theme-lab/theme-lab.test.d.ts +0 -2
  909. package/dist/theme-lab/theme-lab.test.d.ts.map +0 -1
  910. package/dist/tokens/build-fonts-css.test.d.ts +0 -2
  911. package/dist/tokens/build-fonts-css.test.d.ts.map +0 -1
  912. package/dist/tokens/build-radius-css.test.d.ts +0 -2
  913. package/dist/tokens/build-radius-css.test.d.ts.map +0 -1
  914. package/dist/tokens/chart-margin.test.d.ts +0 -2
  915. package/dist/tokens/chart-margin.test.d.ts.map +0 -1
  916. package/dist/tokens/density.test.d.ts +0 -2
  917. package/dist/tokens/density.test.d.ts.map +0 -1
  918. package/dist/tokens/derive-radius.test.d.ts +0 -2
  919. package/dist/tokens/derive-radius.test.d.ts.map +0 -1
  920. package/dist/tokens/derive.test.d.ts +0 -2
  921. package/dist/tokens/derive.test.d.ts.map +0 -1
  922. package/dist/tokens/palette.test.d.ts +0 -2
  923. package/dist/tokens/palette.test.d.ts.map +0 -1
  924. package/dist/tokens/text-scale.test.d.ts +0 -2
  925. package/dist/tokens/text-scale.test.d.ts.map +0 -1
  926. package/dist/vite-color-mix.test.d.ts +0 -2
  927. package/dist/vite-color-mix.test.d.ts.map +0 -1
  928. package/dist/vite.test.d.ts +0 -2
  929. package/dist/vite.test.d.ts.map +0 -1
  930. package/dist/widget-header/delta-badge.test.d.ts +0 -2
  931. package/dist/widget-header/delta-badge.test.d.ts.map +0 -1
  932. package/dist/widget-header/no-mantine.test.d.ts +0 -2
  933. package/dist/widget-header/no-mantine.test.d.ts.map +0 -1
  934. package/dist/widget-header/widget-header.test.d.ts +0 -2
  935. package/dist/widget-header/widget-header.test.d.ts.map +0 -1
  936. package/src/agent/adapter.test.ts +0 -1640
  937. package/src/agent/ai-sdk-transport.test.ts +0 -658
  938. package/src/agent/coalesce.test.ts +0 -387
  939. package/src/agent/foreign.test.ts +0 -51
  940. package/src/agent/id.test.ts +0 -169
  941. package/src/agent/merge.test.ts +0 -206
  942. package/src/agent/part-list.test.tsx +0 -112
  943. package/src/agent/parts.test.ts +0 -720
  944. package/src/agent/thread.test.ts +0 -220
  945. package/src/agent/transport.test.ts +0 -70
  946. package/src/agent/use-agent-stream.test.tsx +0 -287
  947. package/src/agent/use-agent-thread-runs.foreign.test.tsx +0 -138
  948. package/src/agent/use-agent-thread-runs.resume.test.tsx +0 -294
  949. package/src/agent/use-agent-thread-runs.test.tsx +0 -1120
  950. package/src/agent/use-agent-thread-runs.wedge.test.tsx +0 -387
  951. package/src/agent-chat/composer.test.tsx +0 -924
  952. package/src/agent-chat/relative-time.test.ts +0 -95
  953. package/src/agent-chat/thread-feed-row.test.tsx +0 -510
  954. package/src/agent-chat/thread-feed.test.tsx +0 -241
  955. package/src/agent-chat/thread-message.test.tsx +0 -1285
  956. package/src/agent-chat/thread-workspace.test.tsx +0 -169
  957. package/src/agent-chat/tool-chip.test.tsx +0 -139
  958. package/src/agent-chat/virtualize.type-guard.test.ts +0 -49
  959. package/src/charts/cursor/resolve.test.ts +0 -151
  960. package/src/charts/cursor/store.test.ts +0 -64
  961. package/src/charts/kinds/BandStrip.test.tsx +0 -282
  962. package/src/charts/kinds/Bars.test.tsx +0 -183
  963. package/src/charts/kinds/DualPanel.test.tsx +0 -527
  964. package/src/charts/kinds/MirroredBars.test.tsx +0 -232
  965. package/src/charts/kinds/MultiLine.test.tsx +0 -218
  966. package/src/charts/kinds/StackedArea.test.tsx +0 -114
  967. package/src/charts/kinds/ZonedLine.test.tsx +0 -147
  968. package/src/charts/layout/auto-margin.test.ts +0 -42
  969. package/src/charts/primitives/CartesianChart.test.tsx +0 -647
  970. package/src/charts/primitives/ChartCard.test.tsx +0 -66
  971. package/src/charts/primitives/ChartFrame.test.tsx +0 -142
  972. package/src/charts/primitives/ChartLegend.test.tsx +0 -78
  973. package/src/charts/primitives/ChartTooltip.test.tsx +0 -44
  974. package/src/charts/primitives/XZoneRects.test.tsx +0 -123
  975. package/src/charts/series.test.ts +0 -112
  976. package/src/charts/utils/domain.test.ts +0 -54
  977. package/src/charts/utils/measure-text.test.ts +0 -36
  978. package/src/cli/check-coverage.test.ts +0 -297
  979. package/src/cli/check-theme.test.ts +0 -837
  980. package/src/cli/help.test.ts +0 -170
  981. package/src/cli/init-sync.test.ts +0 -343
  982. package/src/cli/placement-engine.test.ts +0 -298
  983. package/src/cli/shipped-versions.test.ts +0 -83
  984. package/src/cli/tarball-parity.test.ts +0 -44
  985. package/src/cli/template-format.test.ts +0 -64
  986. package/src/cli/template-ledger.test.ts +0 -219
  987. package/src/cli/tokens-css.test.ts +0 -249
  988. package/src/cli/toolchain-wiring.test.ts +0 -1358
  989. package/src/cli/waiver-audit.test.ts +0 -215
  990. package/src/content/article-actions.test.ts +0 -78
  991. package/src/content/article-model.test.ts +0 -119
  992. package/src/content/block-split.test.ts +0 -75
  993. package/src/content/heading-components.test.tsx +0 -65
  994. package/src/content/markdown.test.tsx +0 -603
  995. package/src/content/prose.module.css.test.ts +0 -39
  996. package/src/content/sanitize.test.ts +0 -659
  997. package/src/content/slug.test.ts +0 -62
  998. package/src/controls/actions.test.tsx +0 -252
  999. package/src/controls/actions.type-guard.test.ts +0 -63
  1000. package/src/controls/control-group.test.tsx +0 -229
  1001. package/src/controls/controls.router.test.tsx +0 -1053
  1002. package/src/controls/filter-set.test.tsx +0 -472
  1003. package/src/controls/peer-boundary.test.ts +0 -85
  1004. package/src/controls/props-contract.test.tsx +0 -137
  1005. package/src/controls/range-filter.type-guard.test.tsx +0 -122
  1006. package/src/controls/sync-button.test.tsx +0 -183
  1007. package/src/dashboard/query-state.test.tsx +0 -152
  1008. package/src/dashboard/settings-section.test.tsx +0 -56
  1009. package/src/dashboard/stat-card.test.tsx +0 -385
  1010. package/src/data/data-table.test.tsx +0 -434
  1011. package/src/guard/check-source.test.ts +0 -3388
  1012. package/src/guard/grace.test.ts +0 -158
  1013. package/src/guard/guard-hook.test.ts +0 -203
  1014. package/src/provider/index.test.tsx +0 -101
  1015. package/src/provider/lab-theme.test.ts +0 -147
  1016. package/src/query/error-message.test.ts +0 -67
  1017. package/src/router-tanstack/multi-search-param-store.test.ts +0 -124
  1018. package/src/router-tanstack/nav.test.ts +0 -111
  1019. package/src/router-tanstack/search-param-store.test.ts +0 -135
  1020. package/src/router-tanstack/search-store.router.test.tsx +0 -882
  1021. package/src/router-tanstack/search-store.test.ts +0 -578
  1022. package/src/router-tanstack/use-nav.test.tsx +0 -187
  1023. package/src/section/section.test.tsx +0 -204
  1024. package/src/shell/app-mobile-nav.test.tsx +0 -403
  1025. package/src/shell/app-sidebar.test.tsx +0 -509
  1026. package/src/shell/index.test.tsx +0 -428
  1027. package/src/shell/mobile-nav-model.test.ts +0 -517
  1028. package/src/shell/page-bar.test.tsx +0 -316
  1029. package/src/state/fields.test.tsx +0 -512
  1030. package/src/state/persisted.test.ts +0 -91
  1031. package/src/styles.floor.test.ts +0 -36
  1032. package/src/theme/border-coverage.test.ts +0 -272
  1033. package/src/theme/contrast.test.ts +0 -354
  1034. package/src/theme/ctl-theme.test.tsx +0 -275
  1035. package/src/theme/ctl-tier-coverage.test.ts +0 -170
  1036. package/src/theme/density-option.test.ts +0 -96
  1037. package/src/theme/density-relations.test.ts +0 -506
  1038. package/src/theme/derive-theme.test.ts +0 -101
  1039. package/src/theme/divider-law.test.ts +0 -259
  1040. package/src/theme/fonts-option.test.ts +0 -75
  1041. package/src/theme/icon-slot.test.tsx +0 -275
  1042. package/src/theme/layout-rhythm-css.test.ts +0 -72
  1043. package/src/theme/radius-option.test.ts +0 -86
  1044. package/src/theme/radius.test.ts +0 -142
  1045. package/src/theme/shadow-surfaces.test.ts +0 -488
  1046. package/src/theme/spacing.test.ts +0 -495
  1047. package/src/theme/use-basalt-spacing.test.tsx +0 -55
  1048. package/src/theme-lab/derive-controls.test.ts +0 -94
  1049. package/src/theme-lab/derive-state.test.ts +0 -71
  1050. package/src/theme-lab/theme-lab.test.ts +0 -46
  1051. package/src/tokens/build-fonts-css.test.ts +0 -52
  1052. package/src/tokens/build-radius-css.test.ts +0 -25
  1053. package/src/tokens/chart-margin.test.ts +0 -39
  1054. package/src/tokens/density.test.ts +0 -259
  1055. package/src/tokens/derive-radius.test.ts +0 -62
  1056. package/src/tokens/derive.test.ts +0 -30
  1057. package/src/tokens/palette.test.ts +0 -114
  1058. package/src/tokens/text-scale.test.ts +0 -51
  1059. package/src/vite-color-mix.test.ts +0 -46
  1060. package/src/vite.test.ts +0 -423
  1061. package/src/widget-header/delta-badge.test.tsx +0 -60
  1062. package/src/widget-header/no-mantine.test.ts +0 -33
  1063. package/src/widget-header/widget-header.test.tsx +0 -187
@@ -1,14 +1,16 @@
1
- import { curveMonotoneX } from '@visx/curve'
2
1
  import { AreaClosed, LinePath } from '@visx/shape'
3
2
  import { Threshold } from '@visx/threshold'
4
3
  import { memo, useMemo } from 'react'
4
+ import { assertRequiredProps } from '../../common/validate'
5
+ import type { BasaltProps } from '../../common/props'
5
6
  import type { CursorResolution } from '../cursor/resolve'
6
7
  import { AreaGradient, areaFillUrl } from '../primitives/AreaGradient'
7
8
  import type { CartesianTooltipConfig, AxisConfig, PlotContext } from '../primitives/CartesianChart'
8
9
  import { CartesianChart } from '../primitives/CartesianChart'
9
10
  import type { XZoneSpec } from '../primitives/XZoneRects'
10
11
  import type { ZoneSpec } from '../primitives/ZoneRects'
11
- import { LINE_OVERLAY_STROKE_WIDTH } from '../series'
12
+ import type { ChartState } from '../primitives/ChartPending'
13
+ import { curveFor, definedOn, LINE_OVERLAY_STROKE_WIDTH, toPlotPoint } from '../series'
12
14
  import type { ChartLegendConfig, ChartSeries } from '../series'
13
15
  import { VX } from '../../tokens'
14
16
 
@@ -30,7 +32,7 @@ export type ZonedLineRefLine = {
30
32
  dashed?: boolean
31
33
  }
32
34
 
33
- export type ZonedLineProps<T> = {
35
+ export type ZonedLineProps<T> = BasaltProps & {
34
36
  data: T[]
35
37
  /** Fixed height in pixels, forwarded to `CartesianChart`. Default 240. */
36
38
  height?: number
@@ -58,6 +60,9 @@ export type ZonedLineProps<T> = {
58
60
  xTickValues?: (keys: readonly string[], xMax: number) => readonly string[]
59
61
  /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
60
62
  formatX?: (key: string) => string
63
+ /** Tilt the x tick labels 45° or 90°, or `0` to opt out of the phone tier's auto-rotation —
64
+ * see `CartesianChartProps.xLabelRotate`. */
65
+ xLabelRotate?: 0 | 45 | 90
61
66
  /**
62
67
  * How a sibling chart's broadcast cursor key resolves against this chart's points. Default
63
68
  * `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
@@ -81,21 +86,22 @@ export type ZonedLineProps<T> = {
81
86
  ariaLabel?: string
82
87
  /** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
83
88
  isPending?: boolean
89
+ /** The three "nothing to draw" states in one prop — pending → error → empty. See
90
+ * `ChartState`; `isPending` stays a supported alias for `state={{ pending: true }}`. */
91
+ state?: ChartState
84
92
  }
85
93
 
86
- type Valid<T> = T & { __y: number }
94
+ type Pt<T> = T & { __y: number | null }
87
95
 
88
- /** The primary (and only) series' valid points — null values are dropped, creating line gaps. */
89
- function validPoints<T>(series: ChartSeries<T> | undefined, data: readonly T[]): Valid<T>[] {
96
+ /**
97
+ * Every row, in x order, with `__y: null` where the series reports no value. The null row STAYS in
98
+ * the array — see `MultiLine`'s `seriesPoints`: dropping it makes `LinePath`/`AreaClosed`/
99
+ * `Threshold` join straight across a coverage hole, drawing a measurement that was never taken.
100
+ * The shared `defined` guard below is what turns it back into a gap.
101
+ */
102
+ function linePoints<T>(series: ChartSeries<T> | undefined, data: readonly T[]): Pt<T>[] {
90
103
  if (!series) return []
91
- const out: Valid<T>[] = []
92
- for (const d of data) {
93
- const y = series.getValue(d)
94
- if (y !== null && y !== undefined && !Number.isNaN(y)) {
95
- out.push(Object.assign({}, d, { __y: y }) as Valid<T>)
96
- }
97
- }
98
- return out
104
+ return data.map((d) => Object.assign({}, d, { __y: toPlotPoint(series.getValue(d)) }) as Pt<T>)
99
105
  }
100
106
 
101
107
  /**
@@ -107,11 +113,15 @@ function validPoints<T>(series: ChartSeries<T> | undefined, data: readonly T[]):
107
113
  * and the derived tooltip — this kind draws ONLY the marks (thresholds, area fill, and the line).
108
114
  * Single-series, so the legend is optional in practice but present by default.
109
115
  *
110
- * X-axis is built from the full `data` array so the calendar is preserved even
111
- * when the series has nulls; the line itself skips null points (creating
112
- * visual gaps).
116
+ * X-axis is built from the full `data` array so the calendar is preserved even when the series has
117
+ * nulls; the line, the area fill and the threshold fills all BREAK at a null point, leaving a real
118
+ * gap rather than interpolating across it.
113
119
  */
114
120
  function ZonedLineInner<T>(props: ZonedLineProps<T>) {
121
+ // F-ERR-1: name the component and the prop. Without this a missing accessor surfaces
122
+ // from inside visx as `undefined is not a function`, which `BasaltErrorBoundary`
123
+ // swallows into a blank subtree that names nothing.
124
+ assertRequiredProps('ZonedLine', props, ['data', 'getX', 'series'])
115
125
  const {
116
126
  data,
117
127
  chartId,
@@ -125,6 +135,7 @@ function ZonedLineInner<T>(props: ZonedLineProps<T>) {
125
135
  xTicks,
126
136
  xTickValues,
127
137
  formatX,
138
+ xLabelRotate,
128
139
  cursorResolution,
129
140
  tooltip,
130
141
  areaFill,
@@ -132,6 +143,9 @@ function ZonedLineInner<T>(props: ZonedLineProps<T>) {
132
143
  legend,
133
144
  ariaLabel,
134
145
  isPending,
146
+ state,
147
+ className,
148
+ style,
135
149
  } = props
136
150
 
137
151
  // Default the line overlay to the redesign's 1.9px stroke (docs/DESIGN-SPEC.md §5) — applied
@@ -158,12 +172,16 @@ function ZonedLineInner<T>(props: ZonedLineProps<T>) {
158
172
  {...(xTicks !== undefined && { xTicks })}
159
173
  {...(xTickValues !== undefined && { xTickValues })}
160
174
  {...(formatX !== undefined && { formatX })}
175
+ {...(xLabelRotate !== undefined && { xLabelRotate })}
161
176
  {...(cursorResolution !== undefined && { cursorResolution })}
162
177
  {...(tooltip !== undefined && { tooltip })}
163
178
  {...(height !== undefined && { height })}
164
179
  {...(legend !== undefined && { legend })}
165
180
  {...(ariaLabel !== undefined && { ariaLabel })}
166
181
  {...(isPending !== undefined && { isPending })}
182
+ {...(state !== undefined && { state })}
183
+ {...(className !== undefined && { className })}
184
+ {...(style !== undefined && { style })}
167
185
  >
168
186
  {(ctx: PlotContext<T>) => (
169
187
  <ZonedLineMarks
@@ -197,7 +215,22 @@ function ZonedLineMarks<T>({
197
215
  const primary = visible[0]
198
216
  // Memoized: the shared cursor re-renders every chart on every pointer frame, and this both
199
217
  // walks the full series and clones an object per point.
200
- const valid = useMemo(() => validPoints(primary, data), [primary, data])
218
+ const pts = useMemo(() => linePoints(primary, data), [primary, data])
219
+
220
+ // ONE guard for all three shapes below, covering two absences. A null value is a documented GAP
221
+ // (`ChartSeries.getValue`), and a non-positive value on a log axis maps to NaN via `yScale` —
222
+ // without `defined` the first is drawn as an interpolated straight line across a coverage hole
223
+ // and the second emits a NaN path command, which per SVG error handling blanks the ENTIRE path
224
+ // from that point on.
225
+ const defined = definedOn(yScale)
226
+ // ONE curve for all three shapes: the threshold band, the area fill and the line are the SAME
227
+ // series drawn three ways, so a step line over a monotone fill would be two different readings
228
+ // of one measurement.
229
+ const curve = curveFor(primary?.curve)
230
+ // Never reached with a null `__y`: d3's line/area generators call the position accessors only
231
+ // for points `defined` accepted. The `NaN` floor is a type-level one, and it can never paint at
232
+ // zero the way a `?? 0` would.
233
+ const yOf = (d: Pt<T>) => yScale(d.__y ?? NaN)
201
234
 
202
235
  // Area is opt-in: pass a color token to get a cohesive single-hue fill under the line.
203
236
  // (A neutral fill under the neutral line just reads as grey haze, so there is no default-on.)
@@ -208,16 +241,17 @@ function ZonedLineMarks<T>({
208
241
  return (
209
242
  <>
210
243
  {thresholds.map((t, i) => (
211
- <Threshold<Valid<T>>
244
+ <Threshold<Pt<T>>
212
245
  key={`thr-${i}`}
213
246
  id={`${chartId}-thr-${i}`}
214
- data={valid}
247
+ data={pts}
248
+ defined={defined}
215
249
  x={(d) => xScale(getX(d)) ?? 0}
216
250
  y0={() => yScale(t.value)}
217
- y1={(d) => yScale(d.__y)}
251
+ y1={yOf}
218
252
  clipAboveTo={0}
219
253
  clipBelowTo={yMax}
220
- curve={curveMonotoneX}
254
+ curve={curve}
221
255
  belowAreaProps={{ fill: t.side === 'above' ? t.fill : 'transparent' }}
222
256
  aboveAreaProps={{ fill: t.side === 'below' ? t.fill : 'transparent' }}
223
257
  />
@@ -228,27 +262,29 @@ function ZonedLineMarks<T>({
228
262
  <defs>
229
263
  <AreaGradient id={areaId} color={areaColor} />
230
264
  </defs>
231
- <AreaClosed<Valid<T>>
232
- data={valid}
265
+ <AreaClosed<Pt<T>>
266
+ data={pts}
267
+ defined={defined}
233
268
  x={(d) => xScale(getX(d)) ?? 0}
234
- y={(d) => yScale(d.__y)}
269
+ y={yOf}
235
270
  yScale={yScale}
236
- curve={curveMonotoneX}
271
+ curve={curve}
237
272
  fill={areaFillUrl(areaId)}
238
273
  />
239
274
  </>
240
275
  )}
241
276
 
242
277
  {primary && (
243
- <LinePath<Valid<T>>
244
- data={valid}
278
+ <LinePath<Pt<T>>
279
+ data={pts}
280
+ defined={defined}
245
281
  x={(d) => xScale(getX(d)) ?? 0}
246
- y={(d) => yScale(d.__y)}
282
+ y={yOf}
247
283
  stroke={primary.color}
248
284
  strokeWidth={primary.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH}
249
285
  strokeDasharray={primary.dash === 'dashed' ? VX.dashArray : undefined}
250
286
  strokeOpacity={primary.strokeOpacity ?? 1}
251
- curve={curveMonotoneX}
287
+ curve={curve}
252
288
  />
253
289
  )}
254
290
  </>
@@ -259,4 +295,8 @@ function ZonedLineMarks<T>({
259
295
  * Hand-memoized: React Compiler does not process the shipped dist, so the hot ZonedLine kind is
260
296
  * wrapped in `React.memo` to retain the auto-memoization it had as source (parity with Bars).
261
297
  */
262
- export const ZonedLine = memo(ZonedLineInner) as typeof ZonedLineInner
298
+ const ZonedLineMemo = memo(ZonedLineInner)
299
+ // Without it every kind reads as `Memo` in React DevTools (audit A16) — a profiler flame
300
+ // graph of nine identically-named nodes names nothing.
301
+ ZonedLineMemo.displayName = 'ZonedLine'
302
+ export const ZonedLine = ZonedLineMemo as typeof ZonedLineInner
@@ -13,6 +13,7 @@ import { scaleLinear } from '@visx/scale'
13
13
  import { VX } from '../../tokens'
14
14
  import type { ChartMargin } from '../../tokens'
15
15
  import { maxTextWidth } from '../utils/measure-text'
16
+ import { logTickValues, niceLogDomain } from './log-ticks'
16
17
 
17
18
  /**
18
19
  * Distance from the plot edge to the near edge of a tick LABEL: visx's default `tickLength` (8)
@@ -24,6 +25,95 @@ const AXIS_TICK_GAP = 12
24
25
  /** Line box of a single-line tick label at `fontPx`. */
25
26
  const lineHeight = (fontPx: number): number => Math.ceil(fontPx * 1.35)
26
27
 
28
+ /**
29
+ * The line box split at the baseline. Only the DESCENT falls below it and only the ASCENT reaches
30
+ * back over the anchor, and a rotated label needs the two apart — its box is measured from the
31
+ * baseline point the axis anchors it at, not from a centred line box. The two ratios sum to
32
+ * {@link lineHeight}'s 1.35em, so nothing moves for the unrotated case.
33
+ */
34
+ const DESCENT_RATIO = 0.3
35
+ const descent = (fontPx: number): number => fontPx * DESCENT_RATIO
36
+ const ascent = (fontPx: number): number => lineHeight(fontPx) - descent(fontPx)
37
+
38
+ /**
39
+ * visx's own `tickLength` (`@visx/axis`'s `Axis` default) and the extra drop `Ticks` applies to a
40
+ * bottom-axis label — `to.y + max(10, fontSize)`. Together they are the distance from the axis LINE
41
+ * to the tick label's BASELINE, which is where a rotated label's box is measured from.
42
+ */
43
+ const AXIS_TICK_LENGTH = 8
44
+ const VISX_MIN_LABEL_FONT = 10
45
+
46
+ /**
47
+ * The `dx`/`dy` nudge `primitives/Axes.tsx` paints a rotated tick label through — the d3 idiom
48
+ * that puts a 45° label under its tick's lower-left and centres a 90° one on its vertical line.
49
+ *
50
+ * It lives HERE, and the axis imports it, because it is the one number that must be in both
51
+ * places: the nudge was applied at paint and absent from the measure, so §1's measured-equals-
52
+ * painted law broke in exactly the rotated case §8 introduced (the first label crossed the SVG's
53
+ * left edge by 3.2px at 390 and 5.7px at 320, and every rotated label's descender row sat on the
54
+ * bottom clip line). Move a value here and the gutter moves with it.
55
+ */
56
+ export const ROTATED_LABEL_OFFSET: Record<45 | 90, { dx: number; dy: number }> = {
57
+ 45: { dx: -6, dy: 2 },
58
+ 90: { dx: -4, dy: 4 },
59
+ }
60
+
61
+ /** Breathing room between a rotated label's painted box and the SVG's own clip edge. One px reads
62
+ * as flush; two is the smallest gap that reads as deliberate. */
63
+ const ROTATED_CLEARANCE = 2
64
+
65
+ const rotatedOffset = (rotate: number): { dx: number; dy: number } =>
66
+ ROTATED_LABEL_OFFSET[rotate as 45 | 90] ?? { dx: 0, dy: 0 }
67
+
68
+ /**
69
+ * How far a rotated x label reaches LEFT of the plot's left edge, and how far BELOW the axis line —
70
+ * measured from the baseline point the axis anchors it at, through the same `dx`/`dy` the axis
71
+ * paints it with.
72
+ *
73
+ * `AxisBottomDate` anchors a rotated label at its right edge (`textAnchor: 'end'`) and rotates it
74
+ * counter-clockwise about that point, so the string runs down-and-to-the-LEFT from the tick it
75
+ * belongs to. The FIRST tick sits at the plot's left edge, so its label hangs into the left gutter;
76
+ * the LAST row of glyphs hangs below the axis. Rotating the label's box about its anchor gives both
77
+ * extents exactly:
78
+ *
79
+ * - left = `cos θ · (width + ascent) − dx` — zero at 90°, where the string runs straight down.
80
+ * - below = `tickLength + max(10, fontPx) + dy + sin θ · width + cos θ · descent`.
81
+ *
82
+ * Both carry {@link ROTATED_CLEARANCE} so the painted box clears the SVG's clip rather than
83
+ * touching it.
84
+ */
85
+ export function rotatedLabelExtents(input: {
86
+ /** Width of the widest x tick label, already measured at the painted font. */
87
+ labelWidth: number
88
+ fontPx: number
89
+ rotate: number
90
+ }): { left: number; below: number } {
91
+ const { labelWidth, fontPx, rotate } = input
92
+ if (rotate === 0) return { left: 0, below: 0 }
93
+ const radians = (rotate * Math.PI) / 180
94
+ const cos = Math.abs(Math.cos(radians))
95
+ const sin = Math.abs(Math.sin(radians))
96
+ const { dx, dy } = rotatedOffset(rotate)
97
+ return {
98
+ left: cos * (labelWidth + ascent(fontPx)) - dx + ROTATED_CLEARANCE,
99
+ below:
100
+ AXIS_TICK_LENGTH +
101
+ Math.max(VISX_MIN_LABEL_FONT, fontPx) +
102
+ dy +
103
+ sin * labelWidth +
104
+ cos * descent(fontPx) +
105
+ ROTATED_CLEARANCE,
106
+ }
107
+ }
108
+
109
+ /**
110
+ * The grouped-thousands default for a log axis with no explicit `format` — parity with the linear
111
+ * branch's own `probe.tickFormat(ticks)`, which already groups (`"100,000"`). Unbounded fraction
112
+ * digits (rather than `toLocaleString`'s default of 3) so a sub-unit log tick (`1e-7`) still prints
113
+ * its digits instead of truncating to `"0"`.
114
+ */
115
+ const LOG_TICK_FORMAT = new Intl.NumberFormat('en-US', { maximumFractionDigits: 20 })
116
+
27
117
  export type AutoMarginInput = {
28
118
  /** Left-axis tick labels, already formatted. */
29
119
  left?: readonly string[]
@@ -33,8 +123,16 @@ export type AutoMarginInput = {
33
123
  bottom?: readonly string[]
34
124
  /** Degrees of counter-clockwise rotation applied to the x tick labels. Default 0. */
35
125
  rotate?: number
36
- /** Tick-label font size. Default `VX.axisFont`. */
126
+ /** Tick-label font size. Default `VX.axisFont`. A phone-tier chart passes its own smaller size
127
+ * (`chartTierMetrics().axisFont`) — the measured label must be the painted label. */
37
128
  fontPx?: number
129
+ /**
130
+ * Per-side FLOORS. Default `VX.margin`. The phone tier passes its tightened set
131
+ * (`chartTierMetrics().margin`) so a static 44px left gutter does not spend an eighth of a 360px
132
+ * chart on a three-character label. The law itself does not move: a side may still only ever
133
+ * grow past its floor.
134
+ */
135
+ floor?: ChartMargin
38
136
  /** Explicit per-side overrides — applied LAST, so an escape hatch always wins. */
39
137
  override?: Partial<ChartMargin>
40
138
  }
@@ -42,44 +140,50 @@ export type AutoMarginInput = {
42
140
  /**
43
141
  * Resolve the four margins from measured labels.
44
142
  *
45
- * Law, per side:
46
- * - `left` — widest left label + gap, floored at `VX.margin.left`.
47
- * - `right` — with a right axis: widest right label + gap. Without one: half the widest x label,
48
- * so the LAST x tick (centered on the plot's right edge) cannot clip. Both floored at
49
- * `VX.margin.right`.
50
- * - `bottom` — one label line (or the rotated bounding height) + gap, floored at
51
- * `VX.margin.bottom`.
143
+ * Law, per side (the floors are `VX.margin` by default; a tier may tighten them via `floor`):
144
+ * - `left` — widest left label + gap, floored at `VX.margin.left`. When the x labels are ROTATED
145
+ * they also reach into this gutter, so the left side additionally clears their leftward
146
+ * extent — see {@link rotatedLabelExtents}.
147
+ * - `right` — with a right axis: widest right label + gap. Without one, and the x labels are NOT
148
+ * rotated: half the widest x label, so the LAST x tick (centered on the plot's right edge)
149
+ * cannot clip. Without one AND rotated: nothing — a rotated label is anchored at its right edge
150
+ * (`textAnchor: 'end'`, same as {@link rotatedLabelExtents}), so it hangs left of its tick, not
151
+ * right, and reserving half its width would pad a side nothing paints into. Every case is
152
+ * floored at `VX.margin.right`.
153
+ * - `bottom` — one label line + gap; when ROTATED, the label's measured drop below the axis line
154
+ * ({@link rotatedLabelExtents}) instead. Floored at `VX.margin.bottom`.
52
155
  * - `top` — `VX.margin.top`. Nothing measures into it; a chart that draws into the top gutter
53
156
  * passes an override.
54
157
  */
55
158
  export function autoMargin(input: AutoMarginInput = {}): ChartMargin {
56
159
  const fontPx = input.fontPx ?? VX.axisFont
57
- const { left = [], right = [], bottom = [], rotate = 0, override } = input
160
+ const { left = [], right = [], bottom = [], rotate = 0, floor = VX.margin, override } = input
58
161
 
59
162
  const leftWidth = maxTextWidth(left, fontPx)
60
163
  const rightWidth = maxTextWidth(right, fontPx)
61
164
  const bottomWidth = maxTextWidth(bottom, fontPx)
62
165
 
63
- const radians = (rotate * Math.PI) / 180
64
- const bottomExtent =
65
- rotate === 0
66
- ? lineHeight(fontPx)
67
- : Math.ceil(
68
- Math.abs(bottomWidth * Math.sin(radians)) +
69
- Math.abs(lineHeight(fontPx) * Math.cos(radians)),
70
- )
166
+ // Measured EXACTLY as painted: through the same `dx`/`dy` `primitives/Axes.tsx` nudges a rotated
167
+ // label by, and from the baseline the axis anchors it at.
168
+ const rotated = rotatedLabelExtents({ labelWidth: bottomWidth, fontPx, rotate })
169
+ const bottomExtent = rotate === 0 ? lineHeight(fontPx) + AXIS_TICK_GAP : rotated.below
71
170
 
72
171
  return {
73
- top: override?.top ?? VX.margin.top,
172
+ top: override?.top ?? floor.top,
74
173
  right:
75
174
  override?.right ??
76
175
  Math.ceil(
77
- Math.max(VX.margin.right, right.length > 0 ? rightWidth + AXIS_TICK_GAP : bottomWidth / 2),
176
+ Math.max(
177
+ floor.right,
178
+ right.length > 0 ? rightWidth + AXIS_TICK_GAP : rotate === 0 ? bottomWidth / 2 : 0,
179
+ ),
78
180
  ),
79
- bottom: override?.bottom ?? Math.ceil(Math.max(VX.margin.bottom, bottomExtent + AXIS_TICK_GAP)),
181
+ bottom: override?.bottom ?? Math.ceil(Math.max(floor.bottom, bottomExtent)),
80
182
  left:
81
183
  override?.left ??
82
- Math.ceil(Math.max(VX.margin.left, left.length > 0 ? leftWidth + AXIS_TICK_GAP : 0)),
184
+ Math.ceil(
185
+ Math.max(floor.left, left.length > 0 ? leftWidth + AXIS_TICK_GAP : 0, rotated.left),
186
+ ),
83
187
  }
84
188
  }
85
189
 
@@ -99,7 +203,16 @@ export function probeAxisLabels(opts: {
99
203
  format?: (v: number) => string
100
204
  /** Must match the real scale's `nice` — niceing changes which ticks exist. */
101
205
  nice?: boolean
206
+ /** `'log'` measures through {@link logTickValues} instead of a linear probe scale — the same
207
+ * helper the axis paints from (CHARTS-SPEC §1: measured labels == painted labels). Default
208
+ * `'linear'`. */
209
+ scale?: 'linear' | 'log'
102
210
  }): { labels: string[]; format: (v: number) => string } {
211
+ if (opts.scale === 'log') {
212
+ const domain = opts.nice === true ? niceLogDomain(opts.domain) : opts.domain
213
+ const format = opts.format ?? ((v: number) => LOG_TICK_FORMAT.format(v))
214
+ return { labels: logTickValues(domain, opts.ticks).map(format), format }
215
+ }
103
216
  const probe = scaleLinear<number>({
104
217
  domain: opts.domain,
105
218
  range: [1, 0],
@@ -0,0 +1,90 @@
1
+ /**
2
+ * 1-2-5 mantissa tick law for a log axis (`docs/CHARTS-SPEC.md` §2).
3
+ *
4
+ * d3's own `scaleLog().ticks()` multiplies the mantissa density by the number of decades the
5
+ * domain spans, so a wide financial range (e.g. $10k–$300k) reads `$316,228 / $100,000 / $31,623 /
6
+ * $10,000` — every finance reference instead ticks a log price axis at `{1, 2, 5} × 10^n`
7
+ * (`$10,000 · $20,000 · $50,000 · $100,000`). Pure, no visx dependency, so both the measured
8
+ * (`probeAxisLabels`) and painted (`CartesianChart`) sides can share the exact same tick list.
9
+ */
10
+
11
+ /**
12
+ * Escalating mantissa sets: the strict {1, 2, 5} law first, then progressively denser sets used
13
+ * only when the stricter one leaves too few in-domain candidates to read — a short span (a
14
+ * one-year BTC window, say, $58k–$139k) collapses {1, 2, 5} to a single tick, which is
15
+ * unreadable. Each set is ascending and never crosses a decade boundary within itself
16
+ * (`9 × 10^k < 1 × 10^(k+1)`), so the flatMap output stays sorted with no explicit sort.
17
+ */
18
+ const MANTISSA_SETS = [
19
+ [1, 2, 5],
20
+ [1, 1.5, 2, 3, 4, 5, 7],
21
+ [1, 1.5, 2, 2.5, 3, 4, 5, 6, 7, 8, 9],
22
+ ] as const
23
+
24
+ /** Below this many in-domain candidates, escalate to the next denser mantissa set. */
25
+ const DENSIFY_BELOW = 4
26
+
27
+ /** Every base-10 exponent whose decade touches `[min, max]`. */
28
+ function decadeExponents(min: number, max: number): number[] {
29
+ const lo = Math.floor(Math.log10(min))
30
+ const hi = Math.ceil(Math.log10(max))
31
+ const exponents: number[] = []
32
+ for (let k = lo; k <= hi; k++) exponents.push(k)
33
+ return exponents
34
+ }
35
+
36
+ /**
37
+ * Thin an ascending, over-budget value list toward `ticks`, keeping both extremes — a stride
38
+ * derived from the budget (`Math.ceil(length / ticks)`) rather than a fixed 2, so the result
39
+ * actually tracks `ticks` instead of only ever halving regardless of how far over budget the input
40
+ * is. May return one more than `ticks` when the last value doesn't land on the stride (an even
41
+ * decade count, say): keeping the axis's top labeled matters more than the exact count.
42
+ */
43
+ function thinToBudget(values: number[], ticks: number): number[] {
44
+ if (values.length <= ticks) return values
45
+ const stride = Math.ceil(values.length / ticks)
46
+ const thinned = values.filter((_, i) => i % stride === 0)
47
+ const last = values[values.length - 1] as number
48
+ return thinned[thinned.length - 1] === last ? thinned : [...thinned, last]
49
+ }
50
+
51
+ /**
52
+ * Every `{1, 2, 5} × 10^k` value for every decade touching `[min, max]`, filtered to the domain —
53
+ * escalating through {@link MANTISSA_SETS} while a set leaves fewer than {@link DENSIFY_BELOW}
54
+ * candidates (a short span collapses the strict law to one tick). The exact same list is what
55
+ * `probeAxisLabels` measures and what `CartesianChart` paints, so the two can never disagree.
56
+ * An over-budget result collapses to whole decades only when the decades ALONE form a readable
57
+ * axis ({@link DENSIFY_BELOW}+ in-domain); otherwise it is thinned by a budget-derived stride
58
+ * (may exceed `ticks` by one — see {@link thinToBudget}). Collapsing to decades unconditionally
59
+ * is the bug this ordering exists to prevent: a 4-year BTC window ($15.5k–$139k) holds ONE whole
60
+ * decade, so the collapse produced a single-tick axis. Never returns a non-positive value; a
61
+ * non-positive or inverted domain (a log axis has no zero and no reversed extent) returns `[]`.
62
+ */
63
+ export function logTickValues([min, max]: readonly [number, number], ticks: number): number[] {
64
+ if (min <= 0 || max <= 0 || min >= max) return []
65
+
66
+ const exponents = decadeExponents(min, max)
67
+ const inDomain = (v: number): boolean => v >= min && v <= max
68
+ const collect = (mantissas: readonly number[]): number[] =>
69
+ exponents.flatMap((k) => mantissas.map((m) => m * 10 ** k)).filter(inDomain)
70
+
71
+ let resolved: number[] = []
72
+ for (const mantissas of MANTISSA_SETS) {
73
+ resolved = collect(mantissas)
74
+ if (resolved.length >= DENSIFY_BELOW) break
75
+ }
76
+
77
+ if (resolved.length <= ticks) return resolved
78
+
79
+ const decades = exponents.map((k) => 10 ** k).filter(inDomain)
80
+ if (decades.length >= DENSIFY_BELOW) return thinToBudget(decades, ticks)
81
+
82
+ return thinToBudget(resolved, ticks)
83
+ }
84
+
85
+ /** Round a domain outward to the nearest enclosing power-of-10 bounds — the log analog of
86
+ * `scale.nice()`, used to keep `probeAxisLabels` (measurement) and the real niced scale
87
+ * (rendering) computing ticks from the same rounded domain. */
88
+ export function niceLogDomain([min, max]: readonly [number, number]): [number, number] {
89
+ return [10 ** Math.floor(Math.log10(min)), 10 ** Math.ceil(Math.log10(max))]
90
+ }
@@ -1,7 +1,9 @@
1
1
  import { AxisBottom, AxisLeft, AxisRight } from '@visx/axis'
2
2
  import type { AxisScale, TickFormatter } from '@visx/axis'
3
3
  import { VX } from '../../tokens'
4
+ import { ROTATED_LABEL_OFFSET } from '../layout/auto-margin'
4
5
  import { fmtAxisDate } from '../utils/format'
6
+ import { useChartTierMetrics } from './chart-tier'
5
7
 
6
8
  /**
7
9
  * Tick label font — mono, per `docs/DESIGN-SPEC.md` §5 ("ticks mono 10.5px faint"). Not a `VX.*`
@@ -10,7 +12,10 @@ import { fmtAxisDate } from '../utils/format'
10
12
  */
11
13
  const TICK_FONT_FAMILY = 'var(--basalt-font-mono)'
12
14
 
13
- /** Themed left numeric axis — baked-in theme colors + font size. */
15
+ /** Themed left numeric axis — baked-in theme colors + font size. The tick font tracks the ambient
16
+ * chart tier (`docs/CHARTS-SPEC.md` §8); a caller measuring its own gutter must measure at the
17
+ * SAME size (`chartTierMetrics().axisFont` into `autoMargin`'s `fontPx`), or the measured label
18
+ * and the painted one stop being the same string's width. */
14
19
  export function AxisLeftNumeric({
15
20
  scale,
16
21
  numTicks = 5,
@@ -20,6 +25,7 @@ export function AxisLeftNumeric({
20
25
  numTicks?: number
21
26
  tickFormat?: TickFormatter<number>
22
27
  }) {
28
+ const { axisFont } = useChartTierMetrics()
23
29
  return (
24
30
  <AxisLeft
25
31
  scale={scale}
@@ -28,7 +34,7 @@ export function AxisLeftNumeric({
28
34
  tickLabelProps={{
29
35
  fill: VX.faint,
30
36
  fontFamily: TICK_FONT_FAMILY,
31
- fontSize: VX.axisFont,
37
+ fontSize: axisFont,
32
38
  dx: -4,
33
39
  }}
34
40
  stroke={VX.surface.border}
@@ -50,6 +56,7 @@ export function AxisRightNumeric({
50
56
  numTicks?: number
51
57
  tickFormat?: TickFormatter<number>
52
58
  }) {
59
+ const { axisFont } = useChartTierMetrics()
53
60
  return (
54
61
  <AxisRight
55
62
  left={left}
@@ -59,7 +66,7 @@ export function AxisRightNumeric({
59
66
  tickLabelProps={{
60
67
  fill: VX.faint,
61
68
  fontFamily: TICK_FONT_FAMILY,
62
- fontSize: VX.axisFont,
69
+ fontSize: axisFont,
63
70
  dx: 4,
64
71
  }}
65
72
  stroke={VX.surface.border}
@@ -68,12 +75,23 @@ export function AxisRightNumeric({
68
75
  )
69
76
  }
70
77
 
78
+ /**
79
+ * Nudge a rotated tick label back onto its tick. Both are the d3 idiom for the angle: a 45° label
80
+ * hangs from the tick's lower-left, a 90° one is centred on the tick's vertical line.
81
+ *
82
+ * Imported, never re-declared: `autoMargin` measures the gutter THROUGH this same nudge
83
+ * (`rotatedLabelExtents`), and a second copy here is exactly how the painted label came to sit
84
+ * 6px left of the box the measurement had reserved (`docs/CHARTS-SPEC.md` §1).
85
+ */
86
+ const ROTATED_OFFSET = ROTATED_LABEL_OFFSET
87
+
71
88
  /** Themed bottom date axis — baked-in smartTicks + DD.MM formatting. */
72
89
  export function AxisBottomDate({
73
90
  scale,
74
91
  top,
75
92
  tickValues,
76
93
  tickFormat = fmtAxisDate,
94
+ rotate,
77
95
  }: {
78
96
  scale: AxisScale
79
97
  top: number
@@ -83,7 +101,15 @@ export function AxisBottomDate({
83
101
  * tick to the same label.
84
102
  */
85
103
  tickFormat?: TickFormatter<string>
104
+ /**
105
+ * Tilt each tick label counter-clockwise by 45° or 90°, anchored at its right edge — the answer
106
+ * to labels too wide to sit side by side. The caller owns the deepened bottom gutter it needs
107
+ * (`autoMargin({ rotate })`, `docs/CHARTS-SPEC.md` §1); this only paints them.
108
+ */
109
+ rotate?: 45 | 90
86
110
  }) {
111
+ const { axisFont } = useChartTierMetrics()
112
+ const rotated = rotate === undefined ? undefined : ROTATED_OFFSET[rotate]
87
113
  return (
88
114
  <AxisBottom
89
115
  top={top}
@@ -93,8 +119,10 @@ export function AxisBottomDate({
93
119
  tickLabelProps={{
94
120
  fill: VX.faint,
95
121
  fontFamily: TICK_FONT_FAMILY,
96
- fontSize: VX.axisFont,
97
- textAnchor: 'middle',
122
+ fontSize: axisFont,
123
+ textAnchor: rotated === undefined ? 'middle' : 'end',
124
+ ...(rotate !== undefined && { angle: -rotate }),
125
+ ...(rotated !== undefined && { dx: rotated.dx, dy: rotated.dy }),
98
126
  }}
99
127
  stroke={VX.surface.border}
100
128
  tickStroke={VX.surface.border}