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,6 +1,8 @@
1
1
  import { Group } from '@visx/group'
2
2
  import type { PointerEvent, ReactNode } from 'react'
3
3
  import { memo, useMemo, useState } from 'react'
4
+ import { assertRequiredProps } from '../../common/validate'
5
+ import type { BasaltProps } from '../../common/props'
4
6
  import {
5
7
  ChartTooltipFloat,
6
8
  TooltipBody,
@@ -8,6 +10,10 @@ import {
8
10
  TooltipRow,
9
11
  } from '../primitives/ChartTooltip'
10
12
  import { ChartFrame } from '../primitives/ChartFrame'
13
+ import { useChartTierMetrics } from '../primitives/chart-tier'
14
+ import type { ChartState } from '../primitives/ChartPending'
15
+ import { maxTextWidth } from '../utils/measure-text'
16
+ import { thinLabels, xLabelPxFor } from '../utils/ticks'
11
17
  import { VX, alpha } from '../../tokens'
12
18
 
13
19
  /** A single resolved heatmap cell — the unit the tooltip and hover operate on. */
@@ -16,7 +22,7 @@ type HeatmapCell = { row: string; col: string; value: number }
16
22
  /** A hovered cell plus the viewport anchor `ChartTooltipFloat` positions against. */
17
23
  type HeatmapTip = HeatmapCell & { anchor: { x: number; y: number } }
18
24
 
19
- export type HeatmapProps<T> = {
25
+ export type HeatmapProps<T> = BasaltProps & {
20
26
  data: T[]
21
27
  /** Fixed height in pixels. Used when neither `aspectRatio` nor `fill` is set. Default 240. */
22
28
  height?: number
@@ -57,6 +63,9 @@ export type HeatmapProps<T> = {
57
63
  ariaLabel?: string
58
64
  /** Forwarded to `ChartFrame` — see `ChartPending`'s JSDoc for the three-state rationale. */
59
65
  isPending?: boolean
66
+ /** The three "nothing to draw" states in one prop — pending → error → empty. See
67
+ * `ChartState`; `isPending` stays a supported alias for `state={{ pending: true }}`. */
68
+ state?: ChartState
60
69
  }
61
70
 
62
71
  /** Build a first-seen-ordered list of unique keys from data via an accessor. */
@@ -85,6 +94,10 @@ const LABEL_FONT_FAMILY = 'var(--basalt-font-mono)'
85
94
  const PAD_LEFT = 44
86
95
  const PAD_BOTTOM = 24
87
96
  const PAD_TOP = 8
97
+
98
+ /** Line box of one category label at `fontPx` — the vertical room a row label needs, and so the
99
+ * pitch below which the row labels thin (`thinLabels`). Same 1.35em line box `autoMargin` uses. */
100
+ const labelLineHeight = (fontPx: number): number => Math.ceil(fontPx * 1.35)
88
101
  // Height of the optional gradient legend strip (+ its label line).
89
102
  const LEGEND_H = 8
90
103
  const LEGEND_LABEL_H = 16
@@ -94,14 +107,22 @@ const LEGEND_LABEL_H = 16
94
107
  * color at an opacity derived from its value; empty cells stay a faint neutral track.
95
108
  * Generalizes argo's day-of-week × hour-of-day heatmap. Categorical axes are rendered as
96
109
  * plain themed `<text>` (cells are not date-categorical, so there's no shared cursor here) —
97
- * per-cell hover drives the local tooltip directly.
110
+ * per-cell hover drives the local tooltip directly. Painting them outside the `Axis*` primitives
111
+ * does NOT exempt them from §1's measured law: both runs thin through {@link thinLabels} and the
112
+ * right gutter reserves half the widest column label, so no two painted labels overlap and the
113
+ * last one cannot clip.
98
114
  *
99
115
  * Composes `ChartFrame` purely for measuring (`height`/`aspectRatio`/`fill`, the same three
100
116
  * sizing modes every other kind exposes) — `legend={false}` and an empty `series` opt out of
101
117
  * `ChartFrame`'s own derived legend, since Heatmap already ships its own gradient strip.
102
118
  */
103
119
  function HeatmapInner<T>(props: HeatmapProps<T>) {
104
- const { chartId, height, aspectRatio, fill, ariaLabel, isPending } = props
120
+ // F-ERR-1: name the component and the prop. Without this a missing accessor surfaces
121
+ // from inside visx as `undefined is not a function`, which `BasaltErrorBoundary`
122
+ // swallows into a blank subtree that names nothing.
123
+ assertRequiredProps('Heatmap', props, ['data', 'getRow', 'getCol', 'getValue'])
124
+ const { chartId, height, aspectRatio, fill, ariaLabel, isPending, state, className, style } =
125
+ props
105
126
 
106
127
  return (
107
128
  <ChartFrame
@@ -113,6 +134,9 @@ function HeatmapInner<T>(props: HeatmapProps<T>) {
113
134
  {...(fill !== undefined && { fill })}
114
135
  {...(ariaLabel !== undefined && { ariaLabel })}
115
136
  {...(isPending !== undefined && { isPending })}
137
+ {...(state !== undefined && { state })}
138
+ {...(className !== undefined && { className })}
139
+ {...(style !== undefined && { style })}
116
140
  >
117
141
  {(plot) => <HeatmapPlot {...props} plot={plot} />}
118
142
  </ChartFrame>
@@ -147,6 +171,11 @@ function HeatmapPlot<T>(props: HeatmapPlotProps<T>) {
147
171
  } = props
148
172
  const { width, height } = plot
149
173
 
174
+ // The row/column labels and the gradient legend's endpoints read like axis ticks, so they take
175
+ // the tier's tick font for the same reason `Axes.tsx` does — a 360px heatmap that painted its
176
+ // categories at the desktop size would be the one chart still ignoring §8.
177
+ const { axisFont } = useChartTierMetrics()
178
+
150
179
  const [tip, setTip] = useState<HeatmapTip | null>(null)
151
180
 
152
181
  const rows = useMemo(() => rowsProp ?? firstSeen(data, getRow), [rowsProp, data, getRow])
@@ -164,13 +193,33 @@ function HeatmapPlot<T>(props: HeatmapPlotProps<T>) {
164
193
  return { lookup: map, max: m }
165
194
  }, [data, getRow, getCol, getValue])
166
195
 
196
+ const rowLabels = useMemo(() => rows.map(rowLabel), [rows, rowLabel])
197
+ const colLabels = useMemo(() => cols.map(colLabel), [cols, colLabel])
198
+
167
199
  const legendH = legend ? LEGEND_H + LEGEND_LABEL_H : 0
168
- const gridW = Math.max(0, width - PAD_LEFT)
200
+ // The last column label is CENTRED on the last cell, so half of it hangs past the grid — the
201
+ // same reason `autoMargin` reserves half the widest x label on the right. Measured, not a
202
+ // constant: at 390px `19:00` used to print straight off the SVG's own clip edge.
203
+ const padRight = Math.ceil(maxTextWidth(colLabels, axisFont) / 2)
204
+ const gridW = Math.max(0, width - PAD_LEFT - padRight)
169
205
  const gridH = Math.max(0, height - PAD_TOP - PAD_BOTTOM - legendH)
170
206
  const cellW = cols.length > 0 ? gridW / cols.length : 0
171
207
  const cellH = rows.length > 0 ? gridH / rows.length : 0
172
208
  const legendGradientId = `${chartId}-heat-legend`
173
209
 
210
+ // §1's measured law, applied to the one kind that paints its labels as plain `<text>` rather
211
+ // than through the `Axis*` primitives: a label every `ceil(labelPx / cellPitch)` bands, so two
212
+ // painted neighbours can never overlap. Columns thin horizontally by the widest label, rows
213
+ // vertically by the line box.
214
+ const keptCols = useMemo(
215
+ () => thinLabels(colLabels, cellW, xLabelPxFor(colLabels, axisFont)),
216
+ [colLabels, cellW, axisFont],
217
+ )
218
+ const keptRows = useMemo(
219
+ () => thinLabels(rowLabels, cellH, labelLineHeight(axisFont)),
220
+ [rowLabels, cellH, axisFont],
221
+ )
222
+
174
223
  const show = (row: string, col: string, value: number, event: PointerEvent<SVGRectElement>) => {
175
224
  setTip({ row, col, value, anchor: { x: event.clientX, y: event.clientY } })
176
225
  }
@@ -206,36 +255,40 @@ function HeatmapPlot<T>(props: HeatmapPlotProps<T>) {
206
255
 
207
256
  {/* Row labels (left). */}
208
257
  <Group left={0} top={PAD_TOP}>
209
- {rows.map((row, ri) => (
210
- <text
211
- key={row}
212
- x={PAD_LEFT - 6}
213
- y={ri * cellH + cellH / 2 + 4}
214
- textAnchor="end"
215
- fontSize={VX.axisFont}
216
- fontFamily={LABEL_FONT_FAMILY}
217
- fill={VX.faint}
218
- >
219
- {rowLabel(row)}
220
- </text>
221
- ))}
258
+ {rows.map((row, ri) =>
259
+ keptRows.has(ri) ? (
260
+ <text
261
+ key={row}
262
+ x={PAD_LEFT - 6}
263
+ y={ri * cellH + cellH / 2 + 4}
264
+ textAnchor="end"
265
+ fontSize={axisFont}
266
+ fontFamily={LABEL_FONT_FAMILY}
267
+ fill={VX.faint}
268
+ >
269
+ {rowLabels[ri]}
270
+ </text>
271
+ ) : null,
272
+ )}
222
273
  </Group>
223
274
 
224
275
  {/* Column labels (bottom). */}
225
276
  <Group left={PAD_LEFT} top={PAD_TOP + gridH}>
226
- {cols.map((col, ci) => (
227
- <text
228
- key={col}
229
- x={ci * cellW + cellW / 2}
230
- y={16}
231
- textAnchor="middle"
232
- fontSize={VX.axisFont}
233
- fontFamily={LABEL_FONT_FAMILY}
234
- fill={VX.faint}
235
- >
236
- {colLabel(col)}
237
- </text>
238
- ))}
277
+ {cols.map((col, ci) =>
278
+ keptCols.has(ci) ? (
279
+ <text
280
+ key={col}
281
+ x={ci * cellW + cellW / 2}
282
+ y={16}
283
+ textAnchor="middle"
284
+ fontSize={axisFont}
285
+ fontFamily={LABEL_FONT_FAMILY}
286
+ fill={VX.faint}
287
+ >
288
+ {colLabels[ci]}
289
+ </text>
290
+ ) : null,
291
+ )}
239
292
  </Group>
240
293
 
241
294
  {/* Optional gradient legend strip below the grid. */}
@@ -252,7 +305,7 @@ function HeatmapPlot<T>(props: HeatmapPlotProps<T>) {
252
305
  x={0}
253
306
  y={LEGEND_H + 12}
254
307
  textAnchor="start"
255
- fontSize={VX.axisFont}
308
+ fontSize={axisFont}
256
309
  fontFamily={LABEL_FONT_FAMILY}
257
310
  fill={VX.faint}
258
311
  >
@@ -262,7 +315,7 @@ function HeatmapPlot<T>(props: HeatmapPlotProps<T>) {
262
315
  x={gridW}
263
316
  y={LEGEND_H + 12}
264
317
  textAnchor="end"
265
- fontSize={VX.axisFont}
318
+ fontSize={axisFont}
266
319
  fontFamily={LABEL_FONT_FAMILY}
267
320
  fill={VX.faint}
268
321
  >
@@ -294,4 +347,8 @@ function HeatmapPlot<T>(props: HeatmapPlotProps<T>) {
294
347
  * Hand-memoized: React Compiler does not process the shipped dist, so the hot Heatmap kind is
295
348
  * wrapped in `React.memo` to retain auto-memoization (parity with ZonedLine / Bars).
296
349
  */
297
- export const Heatmap = memo(HeatmapInner) as typeof HeatmapInner
350
+ const HeatmapMemo = memo(HeatmapInner)
351
+ // Without it every kind reads as `Memo` in React DevTools (audit A16) — a profiler flame
352
+ // graph of nine identically-named nodes names nothing.
353
+ HeatmapMemo.displayName = 'Heatmap'
354
+ export const Heatmap = HeatmapMemo as typeof HeatmapInner
@@ -2,6 +2,8 @@ import { Group } from '@visx/group'
2
2
  import { scaleLinear } from '@visx/scale'
3
3
  import { memo, useMemo } from 'react'
4
4
  import type { ReactNode } from 'react'
5
+ import { assertRequiredProps } from '../../common/validate'
6
+ import type { BasaltProps } from '../../common/props'
5
7
  import { VX, alpha } from '../../tokens'
6
8
  import type { ChartMargin } from '../../tokens'
7
9
  import type { CursorResolution } from '../cursor/resolve'
@@ -19,6 +21,7 @@ import {
19
21
  import { Crosshair } from '../primitives/Crosshair'
20
22
  import { HatchPattern, hatchFill, hatchSizeFor } from '../primitives/HatchPattern'
21
23
  import { HoverOverlay } from '../primitives/HoverOverlay'
24
+ import type { ChartState } from '../primitives/ChartPending'
22
25
  import { deriveTooltipRows } from '../series'
23
26
  import type { ChartLegendConfig, ChartSeries } from '../series'
24
27
  import { fmtAxisDate } from '../utils/format'
@@ -47,7 +50,7 @@ export type MirroredBarPane = {
47
50
  format: (v: number) => string
48
51
  }
49
52
 
50
- export type MirroredBarsProps<T> = {
53
+ export type MirroredBarsProps<T> = BasaltProps & {
51
54
  data: readonly T[]
52
55
  chartId: string
53
56
  /** Extracts the x-domain key — a slot start, hence the `'leading'` cursor default. */
@@ -92,6 +95,9 @@ export type MirroredBarsProps<T> = {
92
95
  margin?: Partial<ChartMargin>
93
96
  ariaLabel?: string
94
97
  isPending?: boolean
98
+ /** The three "nothing to draw" states in one prop — pending → error → empty. See
99
+ * `ChartState`; `isPending` stays a supported alias for `state={{ pending: true }}`. */
100
+ state?: ChartState
95
101
  }
96
102
 
97
103
  const DEFAULT_UP_FRACTION = 0.35
@@ -137,7 +143,12 @@ function assertPaneKey<T>(
137
143
  * `useBandPlot` choreography instead, which is where the sharing actually belongs.
138
144
  */
139
145
  function MirroredBarsInner<T>(props: MirroredBarsProps<T>) {
140
- const { series, chartId, height, fill, legend, ariaLabel, isPending } = props
146
+ // F-ERR-1: name the component and the prop. Without this a missing accessor surfaces
147
+ // from inside visx as `undefined is not a function`, which `BasaltErrorBoundary`
148
+ // swallows into a blank subtree that names nothing.
149
+ assertRequiredProps('MirroredBars', props, ['data', 'getX', 'series', 'up', 'down'])
150
+ const { series, chartId, height, fill, legend, ariaLabel, isPending, state, className, style } =
151
+ props
141
152
 
142
153
  return (
143
154
  <ChartFrame
@@ -147,6 +158,9 @@ function MirroredBarsInner<T>(props: MirroredBarsProps<T>) {
147
158
  {...(fill !== undefined && { fill })}
148
159
  {...(ariaLabel !== undefined && { ariaLabel })}
149
160
  {...(isPending !== undefined && { isPending })}
161
+ {...(state !== undefined && { state })}
162
+ {...(className !== undefined && { className })}
163
+ {...(style !== undefined && { style })}
150
164
  legend={resolveLegend(legend)}
151
165
  >
152
166
  {(plot) => <MirroredBarsPlot {...props} plot={plot} />}
@@ -488,4 +502,8 @@ function usePaneMax<T>(
488
502
  * Hand-memoized: React Compiler does not process the shipped dist, so the hot kind is wrapped in
489
503
  * `React.memo` to retain the auto-memoization it had as source (parity with `DualPanel`).
490
504
  */
491
- export const MirroredBars = memo(MirroredBarsInner) as typeof MirroredBarsInner
505
+ const MirroredBarsMemo = memo(MirroredBarsInner)
506
+ // Without it every kind reads as `Memo` in React DevTools (audit A16) — a profiler flame
507
+ // graph of nine identically-named nodes names nothing.
508
+ MirroredBarsMemo.displayName = 'MirroredBars'
509
+ export const MirroredBars = MirroredBarsMemo as typeof MirroredBarsInner
@@ -1,17 +1,19 @@
1
- import { curveMonotoneX } from '@visx/curve'
2
1
  import { LinePath } from '@visx/shape'
3
2
  import { memo, useCallback, useMemo } from 'react'
4
3
  import type { ReactNode } 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 type { CartesianTooltipConfig, AxisConfig, PlotContext } from '../primitives/CartesianChart'
7
8
  import { CartesianChart } from '../primitives/CartesianChart'
8
9
  import type { XZoneSpec } from '../primitives/XZoneRects'
9
10
  import type { ZoneSpec } from '../primitives/ZoneRects'
10
- import { LINE_OVERLAY_STROKE_WIDTH } from '../series'
11
+ import type { ChartState } from '../primitives/ChartPending'
12
+ import { curveFor, definedOn, LINE_OVERLAY_STROKE_WIDTH, toPlotPoint } from '../series'
11
13
  import type { ChartLegendConfig, ChartSeries } from '../series'
12
14
  import { VX } from '../../tokens'
13
15
 
14
- export type MultiLineProps<T> = {
16
+ export type MultiLineProps<T> = BasaltProps & {
15
17
  data: T[]
16
18
  /** Fixed height in pixels, forwarded to `CartesianChart`. Default 240. */
17
19
  height?: number
@@ -42,6 +44,9 @@ export type MultiLineProps<T> = {
42
44
  xTickValues?: (keys: readonly string[], xMax: number) => readonly string[]
43
45
  /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
44
46
  formatX?: (key: string) => string
47
+ /** Tilt the x tick labels 45° or 90°, or `0` to opt out of the phone tier's auto-rotation —
48
+ * see `CartesianChartProps.xLabelRotate`. */
49
+ xLabelRotate?: 0 | 45 | 90
45
50
  /**
46
51
  * How a sibling chart's broadcast cursor key resolves against this chart's points. Default
47
52
  * `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
@@ -60,6 +65,9 @@ export type MultiLineProps<T> = {
60
65
  ariaLabel?: string
61
66
  /** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
62
67
  isPending?: boolean
68
+ /** The three "nothing to draw" states in one prop — pending → error → empty. See
69
+ * `ChartState`; `isPending` stays a supported alias for `state={{ pending: true }}`. */
70
+ state?: ChartState
63
71
  }
64
72
 
65
73
  const STAR_R = 6
@@ -76,16 +84,17 @@ function starPath(cx: number, cy: number, r: number): string {
76
84
  return `M${pts.join('L')}Z`
77
85
  }
78
86
 
79
- type LinePt<T> = { __d: T; __y: number }
87
+ type LinePt<T> = { __d: T; __y: number | null }
80
88
 
81
- /** Per-series valid points (null-value gaps dropped). Reused by the lines and the markers. */
89
+ /**
90
+ * Every row, in x order, with `__y: null` where the series reports no value. The null row STAYS in
91
+ * the array: `ChartSeries.getValue` documents null as a line GAP, and dropping the row instead
92
+ * makes `LinePath` join straight across a coverage hole — drawing a measurement that was never
93
+ * taken. `defined` on the consuming shape is what turns it back into a gap. Reused by the lines
94
+ * and the markers.
95
+ */
82
96
  function seriesPoints<T>(series: ChartSeries<T>, data: readonly T[]): LinePt<T>[] {
83
- const pts: LinePt<T>[] = []
84
- for (const d of data) {
85
- const v = series.getValue(d)
86
- if (v !== null && v !== undefined && !Number.isNaN(v)) pts.push({ __d: d, __y: v })
87
- }
88
- return pts
97
+ return data.map((d) => ({ __d: d, __y: toPlotPoint(series.getValue(d)) }))
89
98
  }
90
99
 
91
100
  /**
@@ -99,9 +108,14 @@ function seriesPoints<T>(series: ChartSeries<T>, data: readonly T[]): LinePt<T>[
99
108
  * plotted lines, the legend, and the tooltip rows.
100
109
  *
101
110
  * X-axis is built from the full `data` array so the calendar is preserved even when a series
102
- * has nulls; each series line skips null points (creating visual gaps).
111
+ * has nulls; each series line BREAKS at a null point, leaving a real gap rather than interpolating
112
+ * across it.
103
113
  */
104
114
  function MultiLineInner<T>(props: MultiLineProps<T>) {
115
+ // F-ERR-1: name the component and the prop. Without this a missing accessor surfaces
116
+ // from inside visx as `undefined is not a function`, which `BasaltErrorBoundary`
117
+ // swallows into a blank subtree that names nothing.
118
+ assertRequiredProps('MultiLine', props, ['data', 'getX', 'series'])
105
119
  const {
106
120
  data,
107
121
  chartId,
@@ -115,6 +129,7 @@ function MultiLineInner<T>(props: MultiLineProps<T>) {
115
129
  xTicks,
116
130
  xTickValues,
117
131
  formatX,
132
+ xLabelRotate,
118
133
  cursorResolution,
119
134
  tooltip,
120
135
  markerShape = 'circle',
@@ -122,6 +137,9 @@ function MultiLineInner<T>(props: MultiLineProps<T>) {
122
137
  legend,
123
138
  ariaLabel,
124
139
  isPending,
140
+ state,
141
+ className,
142
+ style,
125
143
  } = props
126
144
 
127
145
  // Default line overlays to the redesign's 1.9px stroke (docs/DESIGN-SPEC.md §5) — applied once
@@ -145,12 +163,16 @@ function MultiLineInner<T>(props: MultiLineProps<T>) {
145
163
  {...(xTicks !== undefined && { xTicks })}
146
164
  {...(xTickValues !== undefined && { xTickValues })}
147
165
  {...(formatX !== undefined && { formatX })}
166
+ {...(xLabelRotate !== undefined && { xLabelRotate })}
148
167
  {...(cursorResolution !== undefined && { cursorResolution })}
149
168
  {...(tooltip !== undefined && { tooltip })}
150
169
  {...(height !== undefined && { height })}
151
170
  {...(legend !== undefined && { legend })}
152
171
  {...(ariaLabel !== undefined && { ariaLabel })}
153
172
  {...(isPending !== undefined && { isPending })}
173
+ {...(state !== undefined && { state })}
174
+ {...(className !== undefined && { className })}
175
+ {...(style !== undefined && { style })}
154
176
  >
155
177
  {(ctx: PlotContext<T>) => <MultiLineMarks getX={getX} markerShape={markerShape} ctx={ctx} />}
156
178
  </CartesianChart>
@@ -209,10 +231,16 @@ function MultiLineMarks<T>({
209
231
  const op = dimOpacity(s)
210
232
  const markers: ReactNode[] = []
211
233
  for (const p of pointsBySeries.get(s.key) ?? []) {
234
+ // A null point is an absence: no dot, no marker — the same claim the line's `defined`
235
+ // makes by breaking there.
236
+ if (p.__y === null) continue
212
237
  const m = getMarker(p.__d)
213
238
  if (m === null) continue
214
239
  const cx = xScale(getX(p.__d)) ?? 0
215
240
  const cy = scale(p.__y)
241
+ // A non-positive value on a log axis (or any input a scale can't place) maps to NaN —
242
+ // skip the marker rather than paint one at `cy="NaN"`.
243
+ if (!Number.isFinite(cy)) continue
216
244
  const color = m.color ?? s.color
217
245
  const r = m.r ?? (markerShape === 'star' ? STAR_R : VX.dotR)
218
246
  const ring = m.ring ?? true
@@ -247,20 +275,31 @@ function MultiLineMarks<T>({
247
275
  return (
248
276
  <>
249
277
  {visible.map((s) => {
250
- const valid = pointsBySeries.get(s.key) ?? []
251
- if (valid.length === 0) return null
278
+ const pts = pointsBySeries.get(s.key) ?? []
279
+ // A series that measured nothing (the legend-only `getValue: () => null` idiom) draws no
280
+ // path at all, rather than an empty one.
281
+ if (!pts.some((p) => p.__y !== null)) return null
252
282
  const scale = scaleFor(s)
253
283
  return (
254
284
  <LinePath<LinePt<T>>
255
285
  key={`line-${s.key}`}
256
- data={valid}
286
+ data={pts}
257
287
  x={(p) => xScale(getX(p.__d)) ?? 0}
258
- y={(p) => scale(p.__y)}
288
+ // Never reached with a null `__y`: d3's line generator calls the position accessors
289
+ // only for points `defined` accepted. The `NaN` floor is a type-level one, and it can
290
+ // never paint at zero the way a `?? 0` would.
291
+ y={(p) => scale(p.__y ?? NaN)}
292
+ // Two absences, one guard. A null value is a documented GAP (`ChartSeries.getValue`),
293
+ // and a non-positive value on a log axis maps to NaN via `scale(p.__y)` — `defined`
294
+ // breaks the line at both instead of interpolating across the hole (a coverage hole
295
+ // reading as a measured straight line) or emitting a NaN path command, which per SVG
296
+ // error handling blanks the ENTIRE polyline from that point on.
297
+ defined={definedOn(scale)}
259
298
  stroke={s.color}
260
299
  strokeWidth={s.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH}
261
300
  strokeDasharray={s.dash === 'dashed' ? VX.dashArray : undefined}
262
301
  strokeOpacity={dimOpacity(s) * (s.strokeOpacity ?? 1)}
263
- curve={curveMonotoneX}
302
+ curve={curveFor(s.curve)}
264
303
  />
265
304
  )
266
305
  })}
@@ -274,4 +313,8 @@ function MultiLineMarks<T>({
274
313
  * Hand-memoized: React Compiler does not process the shipped dist, so the hot MultiLine kind is
275
314
  * wrapped in `React.memo` to retain the auto-memoization it had as source (parity with ZonedLine).
276
315
  */
277
- export const MultiLine = memo(MultiLineInner) as typeof MultiLineInner
316
+ const MultiLineMemo = memo(MultiLineInner)
317
+ // Without it every kind reads as `Memo` in React DevTools (audit A16) — a profiler flame
318
+ // graph of nine identically-named nodes names nothing.
319
+ MultiLineMemo.displayName = 'MultiLine'
320
+ export const MultiLine = MultiLineMemo as typeof MultiLineInner
@@ -1,12 +1,16 @@
1
- import { curveMonotoneX } from '@visx/curve'
2
1
  import { AreaStack } from '@visx/shape'
3
2
  import { memo, useCallback, useMemo } from 'react'
3
+ import { assertRequiredProps } from '../../common/validate'
4
+ import type { BasaltProps } from '../../common/props'
4
5
  import type { CursorResolution } from '../cursor/resolve'
5
6
  import { CartesianChart } from '../primitives/CartesianChart'
6
7
  import type { AxisConfig, PlotContext } from '../primitives/CartesianChart'
8
+ import type { ChartState } from '../primitives/ChartPending'
9
+ import { curveFor } from '../series'
7
10
  import type { ChartLegendConfig, ChartSeries } from '../series'
11
+ import { isDev } from '../../utils/is-dev'
8
12
 
9
- export type StackedAreaProps<T> = {
13
+ export type StackedAreaProps<T> = BasaltProps & {
10
14
  data: T[]
11
15
  /** Fixed height in pixels, forwarded to `CartesianChart`. Default 240. */
12
16
  height?: number
@@ -18,8 +22,9 @@ export type StackedAreaProps<T> = {
18
22
  /** Axis config for ticks/format/grid. `domain` defaults to the summed per-point stack total
19
23
  * (padded ×1.1, or `autoMaxFloor` if higher) rather than a per-series max — the seam a stacked
20
24
  * chart needs, since the plotted quantity is the cumulative band top, not any one series' own
21
- * value. Pass a fixed tuple or your own function to override. */
22
- y?: AxisConfig<T>
25
+ * value. Pass a fixed tuple or your own function to override. No `scale` — stacking sums bar
26
+ * heights directly and a log axis has no additive zero to sum from. */
27
+ y?: Omit<AxisConfig<T>, 'scale'>
23
28
  /** Exact number of x ticks. Default: as many as fit. Ignored when `xTickValues` is set. */
24
29
  xTicks?: number
25
30
  /** Which domain keys get a tick, from the full key list and the resolved plot width. Takes
@@ -28,6 +33,9 @@ export type StackedAreaProps<T> = {
28
33
  xTickValues?: (keys: readonly string[], xMax: number) => readonly string[]
29
34
  /** X tick label formatter. Default `fmtAxisDate` (DD.MM). */
30
35
  formatX?: (key: string) => string
36
+ /** Tilt the x tick labels 45° or 90°, or `0` to opt out of the phone tier's auto-rotation —
37
+ * see `CartesianChartProps.xLabelRotate`. */
38
+ xLabelRotate?: 0 | 45 | 90
31
39
  /**
32
40
  * How a sibling chart's broadcast cursor key resolves against this chart's points. Default
33
41
  * `'nearest'`. Pass `'leading'` when `getX` returns a bucket's leading edge (a weekly series
@@ -41,12 +49,32 @@ export type StackedAreaProps<T> = {
41
49
  ariaLabel?: string
42
50
  /** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
43
51
  isPending?: boolean
52
+ /** The three "nothing to draw" states in one prop — pending → error → empty. See
53
+ * `ChartState`; `isPending` stays a supported alias for `state={{ pending: true }}`. */
54
+ state?: ChartState
55
+ }
56
+
57
+ /**
58
+ * A stack is only as dense as its sparsest band. A band's value is only meaningful as part of a
59
+ * cumulative total, so a row where ANY visible band reports `null` has no total — every band gaps
60
+ * across it. Reading the missing band as `0` instead would be a positive claim the quantity was
61
+ * measured at zero, which is exactly the absence-as-data lie `ChartSeries.getValue`'s null
62
+ * contract exists to prevent.
63
+ */
64
+ function rowIsDense<T>(d: T, bands: readonly ChartSeries<T>[]): boolean {
65
+ return bands.every((s) => s.getValue(d) !== null)
44
66
  }
45
67
 
46
68
  /**
47
69
  * Multi-series stacked-area chart with an optional derived legend (default on) and legend-hover
48
70
  * dimming. Each band's fillOpacity is dimmed when a different key is highlighted via the legend.
49
71
  *
72
+ * **A stack is only as dense as its sparsest series.** A row where any VISIBLE band is null is
73
+ * dropped from the stack entirely — the bands break across that x, the crosshair reports no
74
+ * cumulative value there, and the axis domain ignores it. Toggling the sparse band off in the
75
+ * legend closes the gap, because density is measured against the visible set. A chart that needs
76
+ * a null band to read as zero must say so in its own `getValue`.
77
+ *
50
78
  * Composes `CartesianChart` (`docs/CHARTS-SPEC.md` §2) — margin, scale, grid, axes, cursor, and
51
79
  * tooltip are the primitive's job. This file draws only the `AreaStack` bands.
52
80
  *
@@ -57,6 +85,10 @@ export type StackedAreaProps<T> = {
57
85
  * to restore the original bottom-to-top stacking order for `AreaStack`'s `keys`.
58
86
  */
59
87
  function StackedAreaInner<T>(props: StackedAreaProps<T>) {
88
+ // F-ERR-1: name the component and the prop. Without this a missing accessor surfaces
89
+ // from inside visx as `undefined is not a function`, which `BasaltErrorBoundary`
90
+ // swallows into a blank subtree that names nothing.
91
+ assertRequiredProps('StackedArea', props, ['data', 'getX', 'series'])
60
92
  const {
61
93
  data,
62
94
  chartId,
@@ -66,13 +98,26 @@ function StackedAreaInner<T>(props: StackedAreaProps<T>) {
66
98
  xTicks,
67
99
  xTickValues,
68
100
  formatX,
101
+ xLabelRotate,
69
102
  cursorResolution,
70
103
  height,
71
104
  legend,
72
105
  ariaLabel,
73
106
  isPending,
107
+ state,
108
+ className,
109
+ style,
74
110
  } = props
75
111
 
112
+ // The stack sums band heights via `getValue` totals directly — a log axis has no additive zero
113
+ // to sum from (`docs/CHARTS-SPEC.md`'s null-gap + log contract, mirrored from `Bars`' own guard).
114
+ if (isDev() && (y as { scale?: string } | undefined)?.scale === 'log') {
115
+ throw new Error(
116
+ 'StackedArea: cannot use a log axis (y.scale: "log") — the stack sums band heights, ' +
117
+ 'and a log axis has no additive zero to sum from.',
118
+ )
119
+ }
120
+
76
121
  // The plotted quantity is the CUMULATIVE stack top, not any one series' value — the built-in
77
122
  // 'auto' domain (per-series max) would clip a multi-band stack. Skipped when the caller already
78
123
  // supplies a fixed tuple or their own domain function.
@@ -87,6 +132,8 @@ function StackedAreaInner<T>(props: StackedAreaProps<T>) {
87
132
  domain: (rows: readonly T[], visible: readonly ChartSeries<T>[]) => {
88
133
  let maxTotal = 0
89
134
  for (const d of rows) {
135
+ // A sparse row is not drawn, so it cannot set the axis top either.
136
+ if (!rowIsDense(d, visible)) continue
90
137
  let total = 0
91
138
  for (const s of visible) total += s.getValue(d) ?? 0
92
139
  if (total > maxTotal) maxTotal = total
@@ -100,6 +147,10 @@ function StackedAreaInner<T>(props: StackedAreaProps<T>) {
100
147
  // tracking — not at the band's own raw value, which sits somewhere inside the fill.
101
148
  const stackedCursorValue = useCallback(
102
149
  (d: T, s: ChartSeries<T>, visible: readonly ChartSeries<T>[]): number | null => {
150
+ // No total on a sparse row — the bands gap there, so a dot would sit on nothing. The
151
+ // per-band tooltip rows keep skipping their own nulls (`deriveTooltipRows`), so a row the
152
+ // stack cannot draw never contributes a value anywhere.
153
+ if (!rowIsDense(d, visible)) return null
103
154
  let total = 0
104
155
  // `visible` arrives top-to-bottom (the `series.toReversed()` handed to the primitive);
105
156
  // stacking accumulates bottom-up.
@@ -128,11 +179,15 @@ function StackedAreaInner<T>(props: StackedAreaProps<T>) {
128
179
  {...(xTicks !== undefined && { xTicks })}
129
180
  {...(xTickValues !== undefined && { xTickValues })}
130
181
  {...(formatX !== undefined && { formatX })}
182
+ {...(xLabelRotate !== undefined && { xLabelRotate })}
131
183
  {...(cursorResolution !== undefined && { cursorResolution })}
132
184
  {...(height !== undefined && { height })}
133
185
  {...(legend !== undefined && { legend })}
134
186
  {...(ariaLabel !== undefined && { ariaLabel })}
135
187
  {...(isPending !== undefined && { isPending })}
188
+ {...(state !== undefined && { state })}
189
+ {...(className !== undefined && { className })}
190
+ {...(style !== undefined && { style })}
136
191
  >
137
192
  {(ctx) => <StackedAreaMarks getX={getX} ctx={ctx} />}
138
193
  </CartesianChart>
@@ -159,6 +214,14 @@ function StackedAreaMarks<T>({ getX, ctx }: { getX: (d: T) => string; ctx: PlotC
159
214
  // `AreaStack` wants a mutable array; `ctx.data` is readonly. Copy once per data change.
160
215
  const rows = useMemo(() => [...ctx.data], [ctx.data])
161
216
 
217
+ // `AreaStack` draws every band from ONE curve — the bands share their boundaries, so two curves
218
+ // would leave gaps and overlaps between them. `visible` is in `reversedSeries` order (top band
219
+ // first), so this resolves to the TOPMOST VISIBLE band that declares a `curve` — the last such
220
+ // entry in the caller's own `series` array. A band declaring none is skipped rather than read as
221
+ // the monotone default, and a HIDDEN one is never consulted, so a legend toggle can hand the
222
+ // stack to the next declarer down. `series.curve.test.tsx` pins all four halves of that.
223
+ const curve = curveFor(visible.find((s) => s.curve !== undefined)?.curve)
224
+
162
225
  return (
163
226
  <AreaStack<T, string>
164
227
  data={rows}
@@ -166,8 +229,12 @@ function StackedAreaMarks<T>({ getX, ctx }: { getX: (d: T) => string; ctx: PlotC
166
229
  x={(d) => xScale(getX(d.data)) ?? 0}
167
230
  y0={(d) => yScale(d[0]) ?? 0}
168
231
  y1={(d) => yScale(d[1]) ?? 0}
232
+ // d3's stack layout needs a number per cell, so a null still enters the layout as 0 — but
233
+ // `defined` keeps that cell out of every band's PATH, so the zero is never drawn. Without it
234
+ // a missing band reads as a measured zero and the bands above it slide down onto it.
169
235
  value={(d, key) => seriesByKey.get(key)?.getValue(d) ?? 0}
170
- curve={curveMonotoneX}
236
+ defined={(d) => rowIsDense(d.data, visible)}
237
+ curve={curve}
171
238
  >
172
239
  {({ stacks, path }) =>
173
240
  stacks.map((stack) => (
@@ -189,4 +256,8 @@ function StackedAreaMarks<T>({ getX, ctx }: { getX: (d: T) => string; ctx: PlotC
189
256
  * hot stacked-area kind in `React.memo` to retain the auto-memoization it had as source
190
257
  * (parity with ZonedLine / Bars / MultiLine).
191
258
  */
192
- export const StackedArea = memo(StackedAreaInner) as typeof StackedAreaInner
259
+ const StackedAreaMemo = memo(StackedAreaInner)
260
+ // Without it every kind reads as `Memo` in React DevTools (audit A16) — a profiler flame
261
+ // graph of nine identically-named nodes names nothing.
262
+ StackedAreaMemo.displayName = 'StackedArea'
263
+ export const StackedArea = StackedAreaMemo as typeof StackedAreaInner