basalt-ui 1.26.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 (1069) hide show
  1. package/AGENTS.md +23 -23
  2. package/CHANGELOG.md +67 -0
  3. package/MIGRATING.md +896 -37
  4. package/README.md +33 -3
  5. package/agent/rules/basalt-batteries.md +25 -10
  6. package/agent/rules/basalt-controls.md +73 -43
  7. package/agent/rules/basalt-mantine.md +17 -6
  8. package/agent/rules/basalt-state.md +5 -0
  9. package/agent/rules/basalt-tokens.md +1 -1
  10. package/configs/oxlint-plugin.js +1286 -73
  11. package/configs/oxlint-plugin.test.ts +1338 -29
  12. package/configs/oxlint.json +12 -5
  13. package/dist/agent/coalesce.d.ts.map +1 -1
  14. package/dist/agent/coalesce.js +2 -1
  15. package/dist/agent/merge.d.ts.map +1 -1
  16. package/dist/agent/merge.js +2 -1
  17. package/dist/agent/part-list.d.ts.map +1 -1
  18. package/dist/agent/part-list.js +2 -0
  19. package/dist/agent/stick-to-bottom.d.ts +3 -6
  20. package/dist/agent/stick-to-bottom.d.ts.map +1 -1
  21. package/dist/agent/stick-to-bottom.js +6 -3
  22. package/dist/agent-chat/composer.d.ts +6 -2
  23. package/dist/agent-chat/composer.d.ts.map +1 -1
  24. package/dist/agent-chat/composer.js +49 -33
  25. package/dist/agent-chat/relative-time.d.ts +0 -9
  26. package/dist/agent-chat/relative-time.d.ts.map +1 -1
  27. package/dist/agent-chat/relative-time.js +2 -1
  28. package/dist/agent-chat/thread-detail-panel.d.ts +3 -2
  29. package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
  30. package/dist/agent-chat/thread-detail-panel.js +8 -5
  31. package/dist/agent-chat/thread-feed-row.d.ts +2 -1
  32. package/dist/agent-chat/thread-feed-row.d.ts.map +1 -1
  33. package/dist/agent-chat/thread-feed-row.js +92 -92
  34. package/dist/agent-chat/thread-feed.d.ts +3 -2
  35. package/dist/agent-chat/thread-feed.d.ts.map +1 -1
  36. package/dist/agent-chat/thread-feed.js +8 -3
  37. package/dist/agent-chat/thread-message.d.ts +4 -3
  38. package/dist/agent-chat/thread-message.d.ts.map +1 -1
  39. package/dist/agent-chat/thread-message.js +70 -31
  40. package/dist/agent-chat/thread-outcome-card.d.ts +3 -2
  41. package/dist/agent-chat/thread-outcome-card.d.ts.map +1 -1
  42. package/dist/agent-chat/thread-outcome-card.js +9 -2
  43. package/dist/agent-chat/thread-workspace.d.ts +7 -2
  44. package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
  45. package/dist/agent-chat/thread-workspace.js +62 -29
  46. package/dist/agent-chat/tool-chip.d.ts +3 -2
  47. package/dist/agent-chat/tool-chip.d.ts.map +1 -1
  48. package/dist/agent-chat/tool-chip.js +7 -2
  49. package/dist/charts/hooks/useBandPlot.d.ts.map +1 -1
  50. package/dist/charts/hooks/useBandPlot.js +15 -8
  51. package/dist/charts/index.d.ts +8 -7
  52. package/dist/charts/index.d.ts.map +1 -1
  53. package/dist/charts/index.js +45 -5
  54. package/dist/charts/kinds/BandStrip.d.ts +10 -7
  55. package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
  56. package/dist/charts/kinds/BandStrip.js +12 -7
  57. package/dist/charts/kinds/Bars.d.ts +12 -6
  58. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  59. package/dist/charts/kinds/Bars.js +37 -11
  60. package/dist/charts/kinds/Donut.d.ts +6 -5
  61. package/dist/charts/kinds/Donut.d.ts.map +1 -1
  62. package/dist/charts/kinds/Donut.js +19 -2
  63. package/dist/charts/kinds/DualPanel.d.ts +6 -5
  64. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  65. package/dist/charts/kinds/DualPanel.js +36 -8
  66. package/dist/charts/kinds/Heatmap.d.ts +10 -6
  67. package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
  68. package/dist/charts/kinds/Heatmap.js +58 -31
  69. package/dist/charts/kinds/MirroredBars.d.ts +6 -5
  70. package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
  71. package/dist/charts/kinds/MirroredBars.js +9 -2
  72. package/dist/charts/kinds/MultiLine.d.ts +11 -6
  73. package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
  74. package/dist/charts/kinds/MultiLine.js +24 -15
  75. package/dist/charts/kinds/StackedArea.d.ts +18 -8
  76. package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
  77. package/dist/charts/kinds/StackedArea.js +29 -4
  78. package/dist/charts/kinds/ZonedLine.d.ts +12 -8
  79. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  80. package/dist/charts/kinds/ZonedLine.js +33 -23
  81. package/dist/charts/layout/auto-margin.d.ts +65 -8
  82. package/dist/charts/layout/auto-margin.d.ts.map +1 -1
  83. package/dist/charts/layout/auto-margin.js +45 -10
  84. package/dist/charts/layout/log-ticks.d.ts +27 -0
  85. package/dist/charts/layout/log-ticks.d.ts.map +1 -0
  86. package/dist/charts/layout/log-ticks.js +42 -0
  87. package/dist/charts/primitives/Axes.d.ts +11 -2
  88. package/dist/charts/primitives/Axes.d.ts.map +1 -1
  89. package/dist/charts/primitives/Axes.js +15 -5
  90. package/dist/charts/primitives/CartesianChart.d.ts +45 -7
  91. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  92. package/dist/charts/primitives/CartesianChart.js +86 -28
  93. package/dist/charts/primitives/ChartCard.d.ts +27 -2
  94. package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
  95. package/dist/charts/primitives/ChartCard.js +37 -17
  96. package/dist/charts/primitives/ChartFrame.d.ts +30 -4
  97. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  98. package/dist/charts/primitives/ChartFrame.js +45 -15
  99. package/dist/charts/primitives/ChartLegend.d.ts +13 -2
  100. package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
  101. package/dist/charts/primitives/ChartLegend.js +33 -13
  102. package/dist/charts/primitives/ChartPending.d.ts +77 -4
  103. package/dist/charts/primitives/ChartPending.d.ts.map +1 -1
  104. package/dist/charts/primitives/ChartPending.js +100 -6
  105. package/dist/charts/primitives/ChartTooltip.d.ts +7 -0
  106. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  107. package/dist/charts/primitives/ChartTooltip.js +18 -5
  108. package/dist/charts/primitives/Crosshair.d.ts +3 -0
  109. package/dist/charts/primitives/Crosshair.d.ts.map +1 -1
  110. package/dist/charts/primitives/Crosshair.js +3 -1
  111. package/dist/charts/primitives/chart-frame-layout.d.ts +95 -0
  112. package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -0
  113. package/dist/charts/primitives/chart-frame-layout.js +89 -0
  114. package/dist/charts/primitives/chart-tier.d.ts +16 -0
  115. package/dist/charts/primitives/chart-tier.d.ts.map +1 -0
  116. package/dist/charts/primitives/chart-tier.js +20 -0
  117. package/dist/charts/series.d.ts +55 -1
  118. package/dist/charts/series.d.ts.map +1 -1
  119. package/dist/charts/series.js +27 -1
  120. package/dist/charts/sparklines/BarSparkline.d.ts +3 -3
  121. package/dist/charts/sparklines/BarSparkline.d.ts.map +1 -1
  122. package/dist/charts/sparklines/BarSparkline.js +9 -3
  123. package/dist/charts/sparklines/LineSparkline.d.ts +3 -3
  124. package/dist/charts/sparklines/LineSparkline.d.ts.map +1 -1
  125. package/dist/charts/sparklines/LineSparkline.js +15 -3
  126. package/dist/charts/sparklines/index.d.ts +2 -2
  127. package/dist/charts/sparklines/index.d.ts.map +1 -1
  128. package/dist/charts/utils/format.d.ts +92 -2
  129. package/dist/charts/utils/format.d.ts.map +1 -1
  130. package/dist/charts/utils/format.js +64 -1
  131. package/dist/charts/utils/ticks.d.ts +81 -2
  132. package/dist/charts/utils/ticks.d.ts.map +1 -1
  133. package/dist/charts/utils/ticks.js +54 -4
  134. package/dist/cli/index.d.ts.map +1 -1
  135. package/dist/cli/index.js +2 -2
  136. package/dist/commands/ShortcutsHelp.d.ts +3 -2
  137. package/dist/commands/ShortcutsHelp.d.ts.map +1 -1
  138. package/dist/commands/ShortcutsHelp.js +8 -2
  139. package/dist/commands/define-commands.d.ts.map +1 -1
  140. package/dist/commands/define-commands.js +2 -2
  141. package/dist/commands/define-overlays.d.ts +102 -0
  142. package/dist/commands/define-overlays.d.ts.map +1 -1
  143. package/dist/commands/define-overlays.js +102 -2
  144. package/dist/commands/index.d.ts +10 -1
  145. package/dist/commands/index.d.ts.map +1 -1
  146. package/dist/commands/index.js +3 -1
  147. package/dist/commands/overlays-mount.d.ts +13 -6
  148. package/dist/commands/overlays-mount.d.ts.map +1 -1
  149. package/dist/commands/overlays-mount.js +23 -14
  150. package/dist/common/errors.d.ts +34 -0
  151. package/dist/common/errors.d.ts.map +1 -0
  152. package/dist/common/errors.js +36 -0
  153. package/dist/common/index.d.ts +15 -0
  154. package/dist/common/index.d.ts.map +1 -0
  155. package/dist/common/index.js +29 -0
  156. package/dist/common/props.d.ts +63 -0
  157. package/dist/common/props.d.ts.map +1 -0
  158. package/dist/common/props.js +6 -0
  159. package/dist/common/query-state-like.d.ts +43 -0
  160. package/dist/common/query-state-like.d.ts.map +1 -0
  161. package/dist/common/query-state-like.js +20 -0
  162. package/dist/common/refs.d.ts +29 -0
  163. package/dist/common/refs.d.ts.map +1 -0
  164. package/dist/common/refs.js +29 -0
  165. package/dist/common/scroll-parent.d.ts +23 -0
  166. package/dist/common/scroll-parent.d.ts.map +1 -0
  167. package/dist/common/scroll-parent.js +21 -0
  168. package/dist/common/validate.d.ts +38 -0
  169. package/dist/common/validate.d.ts.map +1 -0
  170. package/dist/common/validate.js +36 -0
  171. package/dist/connectivity/connectivity-indicator.d.ts +3 -1
  172. package/dist/connectivity/connectivity-indicator.d.ts.map +1 -1
  173. package/dist/connectivity/connectivity-indicator.js +3 -1
  174. package/dist/connectivity/connectivity-provider.d.ts.map +1 -1
  175. package/dist/connectivity/connectivity-provider.js +4 -1
  176. package/dist/connectivity/index.d.ts +1 -0
  177. package/dist/connectivity/index.d.ts.map +1 -1
  178. package/dist/connectivity/types.d.ts +2 -2
  179. package/dist/connectivity/types.d.ts.map +1 -1
  180. package/dist/connectivity/use-connectivity.d.ts.map +1 -1
  181. package/dist/content/article-layout.module.css +11 -4
  182. package/dist/content/callout.d.ts +8 -4
  183. package/dist/content/callout.d.ts.map +1 -1
  184. package/dist/content/callout.js +15 -8
  185. package/dist/content/guide.d.ts +5 -4
  186. package/dist/content/guide.d.ts.map +1 -1
  187. package/dist/content/guide.js +13 -4
  188. package/dist/content/heading-anchor.d.ts +24 -2
  189. package/dist/content/heading-anchor.d.ts.map +1 -1
  190. package/dist/content/heading-anchor.js +23 -9
  191. package/dist/content/index.d.ts.map +1 -1
  192. package/dist/content/markdown.d.ts.map +1 -1
  193. package/dist/content/markdown.js +2 -0
  194. package/dist/content/prose.module.css +9 -7
  195. package/dist/content/reading-progress.d.ts +10 -4
  196. package/dist/content/reading-progress.d.ts.map +1 -1
  197. package/dist/content/reading-progress.js +26 -10
  198. package/dist/content/slug.d.ts +4 -0
  199. package/dist/content/slug.d.ts.map +1 -1
  200. package/dist/content/toc.d.ts +11 -0
  201. package/dist/content/toc.d.ts.map +1 -1
  202. package/dist/content/toc.js +23 -10
  203. package/dist/controls/actions.d.ts +49 -6
  204. package/dist/controls/actions.d.ts.map +1 -1
  205. package/dist/controls/actions.js +39 -8
  206. package/dist/controls/compare-filter.d.ts +3 -2
  207. package/dist/controls/compare-filter.d.ts.map +1 -1
  208. package/dist/controls/compare-filter.js +17 -2
  209. package/dist/controls/control-group.d.ts +3 -3
  210. package/dist/controls/control-group.d.ts.map +1 -1
  211. package/dist/controls/control-group.js +9 -2
  212. package/dist/controls/controls.module.css +169 -186
  213. package/dist/controls/controls.module.css.d.ts +9 -11
  214. package/dist/controls/enum-filter.d.ts +13 -3
  215. package/dist/controls/enum-filter.d.ts.map +1 -1
  216. package/dist/controls/enum-filter.js +32 -15
  217. package/dist/controls/filter-context.d.ts +15 -6
  218. package/dist/controls/filter-context.d.ts.map +1 -1
  219. package/dist/controls/filter-pill.d.ts +3 -3
  220. package/dist/controls/filter-pill.d.ts.map +1 -1
  221. package/dist/controls/filter-pill.js +4 -1
  222. package/dist/controls/filter-set.d.ts +3 -2
  223. package/dist/controls/filter-set.d.ts.map +1 -1
  224. package/dist/controls/filter-set.js +66 -41
  225. package/dist/controls/filter-sheet.d.ts +20 -80
  226. package/dist/controls/filter-sheet.d.ts.map +1 -1
  227. package/dist/controls/filter-sheet.js +9 -95
  228. package/dist/controls/index.d.ts +3 -0
  229. package/dist/controls/index.d.ts.map +1 -1
  230. package/dist/controls/index.js +6 -0
  231. package/dist/controls/multi-select-filter.d.ts +18 -2
  232. package/dist/controls/multi-select-filter.d.ts.map +1 -1
  233. package/dist/controls/multi-select-filter.js +124 -22
  234. package/dist/controls/number-filter.d.ts +28 -0
  235. package/dist/controls/number-filter.d.ts.map +1 -0
  236. package/dist/controls/number-filter.js +172 -0
  237. package/dist/controls/panel-row.d.ts +132 -0
  238. package/dist/controls/panel-row.d.ts.map +1 -0
  239. package/dist/controls/panel-row.js +173 -0
  240. package/dist/controls/panel-row.module.css +86 -0
  241. package/dist/controls/panel-row.module.css.d.ts +13 -0
  242. package/dist/controls/range-filter.d.ts +20 -5
  243. package/dist/controls/range-filter.d.ts.map +1 -1
  244. package/dist/controls/range-filter.js +75 -38
  245. package/dist/controls/search-filter.d.ts +3 -2
  246. package/dist/controls/search-filter.d.ts.map +1 -1
  247. package/dist/controls/search-filter.js +26 -11
  248. package/dist/controls/select-filter.d.ts +2 -1
  249. package/dist/controls/select-filter.d.ts.map +1 -1
  250. package/dist/controls/select-filter.js +4 -0
  251. package/dist/controls/slider-control.d.ts +36 -0
  252. package/dist/controls/slider-control.d.ts.map +1 -0
  253. package/dist/controls/slider-control.js +64 -0
  254. package/dist/controls/sync-button.d.ts +3 -2
  255. package/dist/controls/sync-button.d.ts.map +1 -1
  256. package/dist/controls/sync-button.js +16 -3
  257. package/dist/controls/toggle-filter.d.ts +3 -2
  258. package/dist/controls/toggle-filter.d.ts.map +1 -1
  259. package/dist/controls/toggle-filter.js +29 -12
  260. package/dist/controls/view-tabs.d.ts +3 -2
  261. package/dist/controls/view-tabs.d.ts.map +1 -1
  262. package/dist/controls/view-tabs.js +43 -11
  263. package/dist/controls-dates/date-range-picker.d.ts +1 -1
  264. package/dist/controls-dates/date-range-picker.d.ts.map +1 -1
  265. package/dist/controls-dates/date-range-picker.js +6 -1
  266. package/dist/dashboard/delta-badge.d.ts +5 -1
  267. package/dist/dashboard/delta-badge.d.ts.map +1 -1
  268. package/dist/dashboard/empty-state.d.ts +10 -3
  269. package/dist/dashboard/empty-state.d.ts.map +1 -1
  270. package/dist/dashboard/empty-state.js +37 -6
  271. package/dist/dashboard/index.d.ts +6 -4
  272. package/dist/dashboard/index.d.ts.map +1 -1
  273. package/dist/dashboard/index.js +10 -2
  274. package/dist/dashboard/query-state.d.ts +48 -27
  275. package/dist/dashboard/query-state.d.ts.map +1 -1
  276. package/dist/dashboard/query-state.js +111 -57
  277. package/dist/dashboard/settings-section.d.ts +19 -9
  278. package/dist/dashboard/settings-section.d.ts.map +1 -1
  279. package/dist/dashboard/settings-section.js +74 -25
  280. package/dist/dashboard/stat-card.d.ts +76 -19
  281. package/dist/dashboard/stat-card.d.ts.map +1 -1
  282. package/dist/dashboard/stat-card.js +78 -38
  283. package/dist/dashboard/stat-card.module.css +112 -26
  284. package/dist/dashboard/stat-card.module.css.d.ts +5 -0
  285. package/dist/dashboard/stat-group.d.ts +41 -0
  286. package/dist/dashboard/stat-group.d.ts.map +1 -0
  287. package/dist/dashboard/stat-group.js +30 -0
  288. package/dist/dashboard/stat-group.module.css +66 -0
  289. package/dist/dashboard/stat-group.module.css.d.ts +8 -0
  290. package/dist/dashboard/widget-grid.d.ts +27 -0
  291. package/dist/dashboard/widget-grid.d.ts.map +1 -0
  292. package/dist/dashboard/widget-grid.js +41 -0
  293. package/dist/dashboard/widget-grid.module.css +53 -0
  294. package/dist/dashboard/widget-grid.module.css.d.ts +9 -0
  295. package/dist/data/data-table.d.ts +151 -12
  296. package/dist/data/data-table.d.ts.map +1 -1
  297. package/dist/data/data-table.js +392 -138
  298. package/dist/data/data-table.module.css +64 -0
  299. package/dist/data/data-table.module.css.d.ts +11 -0
  300. package/dist/data/index.d.ts +2 -2
  301. package/dist/data/index.d.ts.map +1 -1
  302. package/dist/data/index.js +24 -2
  303. package/dist/data/query-branch.d.ts +28 -0
  304. package/dist/data/query-branch.d.ts.map +1 -0
  305. package/dist/data/query-branch.js +10 -0
  306. package/dist/data/table.d.ts +2 -2
  307. package/dist/data/table.d.ts.map +1 -1
  308. package/dist/data/virtual-list.d.ts +65 -6
  309. package/dist/data/virtual-list.d.ts.map +1 -1
  310. package/dist/data/virtual-list.js +89 -38
  311. package/dist/data/virtual.d.ts +1 -1
  312. package/dist/data/virtual.d.ts.map +1 -1
  313. package/dist/forms/FormErrorSummary.d.ts +4 -3
  314. package/dist/forms/FormErrorSummary.d.ts.map +1 -1
  315. package/dist/forms/FormErrorSummary.js +6 -4
  316. package/dist/forms/create-form.d.ts +2 -2
  317. package/dist/forms/field.d.ts +46 -6
  318. package/dist/forms/field.d.ts.map +1 -1
  319. package/dist/forms/field.js +10 -5
  320. package/dist/forms/form-layout.d.ts +142 -0
  321. package/dist/forms/form-layout.d.ts.map +1 -0
  322. package/dist/forms/form-layout.js +110 -0
  323. package/dist/forms/form-layout.module.css +145 -0
  324. package/dist/forms/form-layout.module.css.d.ts +20 -0
  325. package/dist/forms/form-state.d.ts +42 -0
  326. package/dist/forms/form-state.d.ts.map +1 -0
  327. package/dist/forms/form-state.js +26 -0
  328. package/dist/forms/index.d.ts +22 -6
  329. package/dist/forms/index.d.ts.map +1 -1
  330. package/dist/forms/index.js +19 -3
  331. package/dist/forms/use-field-array.d.ts +60 -0
  332. package/dist/forms/use-field-array.d.ts.map +1 -0
  333. package/dist/forms/use-field-array.js +20 -0
  334. package/dist/forms/use-form-draft.d.ts +25 -10
  335. package/dist/forms/use-form-draft.d.ts.map +1 -1
  336. package/dist/forms/use-form-draft.js +55 -18
  337. package/dist/forms/use-form-submit.d.ts +88 -0
  338. package/dist/forms/use-form-submit.d.ts.map +1 -0
  339. package/dist/forms/use-form-submit.js +63 -0
  340. package/dist/guard/index.d.ts +1 -1
  341. package/dist/guard/index.d.ts.map +1 -1
  342. package/dist/guard/index.js +27 -11
  343. package/dist/index.d.ts +10 -8
  344. package/dist/index.d.ts.map +1 -1
  345. package/dist/index.js +44 -4
  346. package/dist/nav/types.d.ts +15 -6
  347. package/dist/nav/types.d.ts.map +1 -1
  348. package/dist/notifications/bell.d.ts +3 -2
  349. package/dist/notifications/bell.d.ts.map +1 -1
  350. package/dist/notifications/bell.js +73 -56
  351. package/dist/notifications/center.d.ts +15 -4
  352. package/dist/notifications/center.d.ts.map +1 -1
  353. package/dist/notifications/center.js +5 -2
  354. package/dist/notifications/define-notifications.d.ts +56 -14
  355. package/dist/notifications/define-notifications.d.ts.map +1 -1
  356. package/dist/notifications/define-notifications.js +2 -1
  357. package/dist/notifications/index.d.ts +6 -2
  358. package/dist/notifications/index.d.ts.map +1 -1
  359. package/dist/notifications/index.js +5 -1
  360. package/dist/notifications/mount-guard.d.ts +8 -0
  361. package/dist/notifications/mount-guard.d.ts.map +1 -0
  362. package/dist/notifications/mount-guard.js +19 -0
  363. package/dist/notifications/notify.d.ts +58 -1
  364. package/dist/notifications/notify.d.ts.map +1 -1
  365. package/dist/notifications/notify.js +46 -2
  366. package/dist/notifications/overlay.d.ts.map +1 -1
  367. package/dist/notifications/overlay.js +2 -0
  368. package/dist/notifications/store.d.ts +7 -0
  369. package/dist/notifications/store.d.ts.map +1 -1
  370. package/dist/provider/index.d.ts +37 -5
  371. package/dist/provider/index.d.ts.map +1 -1
  372. package/dist/provider/index.js +66 -28
  373. package/dist/provider/lab-theme.d.ts.map +1 -1
  374. package/dist/provider/lab-theme.js +2 -1
  375. package/dist/query/devtools.d.ts.map +1 -1
  376. package/dist/query/devtools.js +1 -0
  377. package/dist/router-tanstack/field.d.ts +1 -1
  378. package/dist/router-tanstack/field.d.ts.map +1 -1
  379. package/dist/router-tanstack/index.d.ts +1 -1
  380. package/dist/router-tanstack/index.d.ts.map +1 -1
  381. package/dist/router-tanstack/search-store.d.ts +4 -1
  382. package/dist/router-tanstack/search-store.d.ts.map +1 -1
  383. package/dist/router-tanstack/search-store.js +92 -8
  384. package/dist/router-tanstack/use-nav.d.ts.map +1 -1
  385. package/dist/router-tanstack/use-nav.js +1 -1
  386. package/dist/section/index.d.ts +1 -1
  387. package/dist/section/index.d.ts.map +1 -1
  388. package/dist/section/section.d.ts +36 -2
  389. package/dist/section/section.d.ts.map +1 -1
  390. package/dist/section/section.js +49 -57
  391. package/dist/section/section.module.css +11 -0
  392. package/dist/shell/account-types.d.ts +5 -2
  393. package/dist/shell/account-types.d.ts.map +1 -1
  394. package/dist/shell/app-brand.d.ts +13 -0
  395. package/dist/shell/app-brand.d.ts.map +1 -0
  396. package/dist/shell/app-brand.js +94 -0
  397. package/dist/shell/app-brand.module.css +109 -0
  398. package/dist/shell/app-brand.module.css.d.ts +14 -0
  399. package/dist/shell/app-breadcrumbs.d.ts +4 -2
  400. package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
  401. package/dist/shell/app-breadcrumbs.js +33 -22
  402. package/dist/shell/app-header.module.css +10 -5
  403. package/dist/shell/app-main.module.css +107 -0
  404. package/dist/shell/app-main.module.css.d.ts +11 -0
  405. package/dist/shell/app-mobile-nav.d.ts +3 -2
  406. package/dist/shell/app-mobile-nav.d.ts.map +1 -1
  407. package/dist/shell/app-mobile-nav.js +29 -15
  408. package/dist/shell/app-mobile-nav.module.css +48 -27
  409. package/dist/shell/app-mobile-nav.module.css.d.ts +0 -1
  410. package/dist/shell/app-sidebar-account.d.ts +2 -1
  411. package/dist/shell/app-sidebar-account.d.ts.map +1 -1
  412. package/dist/shell/app-sidebar-account.js +57 -22
  413. package/dist/shell/app-sidebar.d.ts +9 -3
  414. package/dist/shell/app-sidebar.d.ts.map +1 -1
  415. package/dist/shell/app-sidebar.js +55 -109
  416. package/dist/shell/app-sidebar.module.css +53 -96
  417. package/dist/shell/app-sidebar.module.css.d.ts +0 -5
  418. package/dist/shell/index.d.ts +14 -6
  419. package/dist/shell/index.d.ts.map +1 -1
  420. package/dist/shell/index.js +47 -12
  421. package/dist/shell/isomorphic-layout-effect.d.ts +14 -0
  422. package/dist/shell/isomorphic-layout-effect.d.ts.map +1 -0
  423. package/dist/shell/isomorphic-layout-effect.js +5 -0
  424. package/dist/shell/mobile-nav-model.d.ts.map +1 -1
  425. package/dist/shell/mobile-nav-model.js +27 -6
  426. package/dist/shell/nav-count-badge.d.ts +5 -3
  427. package/dist/shell/nav-count-badge.d.ts.map +1 -1
  428. package/dist/shell/nav-count-badge.js +3 -1
  429. package/dist/shell/page-aside.d.ts +43 -0
  430. package/dist/shell/page-aside.d.ts.map +1 -0
  431. package/dist/shell/page-aside.js +202 -0
  432. package/dist/shell/page-aside.module.css +174 -0
  433. package/dist/shell/page-aside.module.css.d.ts +14 -0
  434. package/dist/shell/page-bar.d.ts +55 -15
  435. package/dist/shell/page-bar.d.ts.map +1 -1
  436. package/dist/shell/page-bar.js +130 -41
  437. package/dist/shell/page-bar.module.css +107 -13
  438. package/dist/shell/page-bar.module.css.d.ts +4 -1
  439. package/dist/shell/sidebar-search.d.ts +4 -2
  440. package/dist/shell/sidebar-search.d.ts.map +1 -1
  441. package/dist/shell/sidebar-search.js +9 -4
  442. package/dist/shell/sidebar-search.module.css +1 -1
  443. package/dist/state/fields.d.ts +227 -34
  444. package/dist/state/fields.d.ts.map +1 -1
  445. package/dist/state/fields.js +77 -30
  446. package/dist/state/persisted-or-local.d.ts +9 -0
  447. package/dist/state/persisted-or-local.d.ts.map +1 -0
  448. package/dist/state/persisted-or-local.js +24 -0
  449. package/dist/state/persisted.d.ts +12 -0
  450. package/dist/state/persisted.d.ts.map +1 -1
  451. package/dist/state/persisted.js +36 -18
  452. package/dist/state.d.ts +1 -1
  453. package/dist/state.d.ts.map +1 -1
  454. package/dist/state.js +2 -6
  455. package/dist/surfaces.d.ts +12 -11
  456. package/dist/surfaces.d.ts.map +1 -1
  457. package/dist/surfaces.js +43 -12
  458. package/dist/theme/ctl-theme.d.ts.map +1 -1
  459. package/dist/theme/index.d.ts.map +1 -1
  460. package/dist/theme/index.js +102 -17
  461. package/dist/theme/nav-link.module.css +37 -26
  462. package/dist/theme/segmented-control.module.css +22 -0
  463. package/dist/theme/segmented-control.module.css.d.ts +1 -0
  464. package/dist/theme-lab/boot.d.ts +66 -0
  465. package/dist/theme-lab/boot.d.ts.map +1 -0
  466. package/dist/theme-lab/boot.js +82 -0
  467. package/dist/theme-lab/index.d.ts +4 -43
  468. package/dist/theme-lab/index.d.ts.map +1 -1
  469. package/dist/theme-lab/index.js +9 -69
  470. package/dist/theme-toggle/index.d.ts +3 -2
  471. package/dist/theme-toggle/index.d.ts.map +1 -1
  472. package/dist/theme-toggle/index.js +8 -2
  473. package/dist/tokens/index.d.ts +42 -0
  474. package/dist/tokens/index.d.ts.map +1 -1
  475. package/dist/tokens/index.js +35 -6
  476. package/dist/tokens/palette.d.ts +45 -25
  477. package/dist/tokens/palette.d.ts.map +1 -1
  478. package/dist/tokens/palette.js +31 -14
  479. package/dist/tokens.css +4 -5
  480. package/dist/utils/is-dev.d.ts +3 -0
  481. package/dist/utils/is-dev.d.ts.map +1 -0
  482. package/dist/utils/is-dev.js +6 -0
  483. package/dist/widget-header/delta-badge.d.ts +7 -1
  484. package/dist/widget-header/delta-badge.d.ts.map +1 -1
  485. package/dist/widget-header/delta-badge.js +8 -1
  486. package/dist/widget-header/index.d.ts +2 -2
  487. package/dist/widget-header/index.d.ts.map +1 -1
  488. package/dist/widget-header/index.js +3 -1
  489. package/dist/widget-header/widget-header.d.ts +99 -4
  490. package/dist/widget-header/widget-header.d.ts.map +1 -1
  491. package/dist/widget-header/widget-header.js +45 -18
  492. package/dist/widget-header/widget-header.module.css +87 -7
  493. package/dist/widget-header/widget-header.module.css.d.ts +1 -0
  494. package/llms.txt +6 -6
  495. package/package.json +49 -25
  496. package/src/agent/coalesce.ts +2 -1
  497. package/src/agent/merge.ts +2 -1
  498. package/src/agent/part-list.tsx +2 -0
  499. package/src/agent/stick-to-bottom.tsx +9 -11
  500. package/src/agent-chat/composer.tsx +124 -103
  501. package/src/agent-chat/relative-time.ts +2 -1
  502. package/src/agent-chat/thread-detail-panel.tsx +9 -5
  503. package/src/agent-chat/thread-feed-row.tsx +17 -9
  504. package/src/agent-chat/thread-feed.tsx +9 -3
  505. package/src/agent-chat/thread-message.tsx +48 -13
  506. package/src/agent-chat/thread-outcome-card.tsx +9 -1
  507. package/src/agent-chat/thread-workspace.tsx +72 -33
  508. package/src/agent-chat/tool-chip.tsx +8 -2
  509. package/src/charts/hooks/useBandPlot.ts +26 -8
  510. package/src/charts/index.ts +39 -4
  511. package/src/charts/kinds/BandStrip.tsx +36 -14
  512. package/src/charts/kinds/Bars.tsx +67 -16
  513. package/src/charts/kinds/Donut.tsx +30 -3
  514. package/src/charts/kinds/DualPanel.tsx +56 -10
  515. package/src/charts/kinds/Heatmap.tsx +90 -33
  516. package/src/charts/kinds/MirroredBars.tsx +21 -3
  517. package/src/charts/kinds/MultiLine.tsx +61 -18
  518. package/src/charts/kinds/StackedArea.tsx +77 -6
  519. package/src/charts/kinds/ZonedLine.tsx +71 -31
  520. package/src/charts/layout/auto-margin.ts +134 -21
  521. package/src/charts/layout/log-ticks.ts +90 -0
  522. package/src/charts/primitives/Axes.tsx +33 -5
  523. package/src/charts/primitives/CartesianChart.tsx +194 -41
  524. package/src/charts/primitives/ChartCard.tsx +66 -25
  525. package/src/charts/primitives/ChartFrame.tsx +107 -26
  526. package/src/charts/primitives/ChartLegend.tsx +43 -13
  527. package/src/charts/primitives/ChartPending.tsx +185 -7
  528. package/src/charts/primitives/ChartTooltip.tsx +37 -5
  529. package/src/charts/primitives/Crosshair.tsx +6 -3
  530. package/src/charts/primitives/chart-frame-layout.ts +212 -0
  531. package/src/charts/primitives/chart-tier.tsx +37 -0
  532. package/src/charts/series.ts +77 -1
  533. package/src/charts/sparklines/BarSparkline.tsx +11 -3
  534. package/src/charts/sparklines/LineSparkline.tsx +18 -4
  535. package/src/charts/sparklines/index.ts +2 -2
  536. package/src/charts/utils/format.ts +163 -2
  537. package/src/charts/utils/ticks.ts +149 -4
  538. package/src/cli/index.ts +8 -3
  539. package/src/commands/ShortcutsHelp.tsx +10 -3
  540. package/src/commands/define-commands.ts +2 -2
  541. package/src/commands/define-overlays.ts +216 -1
  542. package/src/commands/index.ts +12 -0
  543. package/src/commands/overlays-mount.tsx +60 -26
  544. package/src/common/errors.ts +73 -0
  545. package/src/common/index.ts +21 -0
  546. package/src/common/props.ts +71 -0
  547. package/src/common/query-state-like.ts +64 -0
  548. package/src/common/refs.ts +58 -0
  549. package/src/common/scroll-parent.ts +42 -0
  550. package/src/common/validate.ts +94 -0
  551. package/src/connectivity/connectivity-indicator.tsx +6 -1
  552. package/src/connectivity/connectivity-provider.tsx +4 -1
  553. package/src/connectivity/index.ts +1 -0
  554. package/src/connectivity/types.ts +5 -2
  555. package/src/connectivity/use-connectivity.ts +3 -2
  556. package/src/content/article-layout.module.css +11 -4
  557. package/src/content/callout.tsx +13 -7
  558. package/src/content/guide.tsx +14 -4
  559. package/src/content/heading-anchor.tsx +14 -3
  560. package/src/content/index.ts +2 -0
  561. package/src/content/markdown.tsx +2 -0
  562. package/src/content/prose.module.css +9 -7
  563. package/src/content/reading-progress.tsx +40 -15
  564. package/src/content/slug.ts +4 -0
  565. package/src/content/toc.tsx +47 -10
  566. package/src/controls/actions.tsx +89 -9
  567. package/src/controls/compare-filter.tsx +20 -3
  568. package/src/controls/control-group.tsx +11 -4
  569. package/src/controls/controls.module.css +169 -186
  570. package/src/controls/controls.module.css.d.ts +9 -11
  571. package/src/controls/enum-filter.tsx +46 -19
  572. package/src/controls/filter-context.tsx +21 -8
  573. package/src/controls/filter-pill.tsx +6 -3
  574. package/src/controls/filter-set.tsx +32 -13
  575. package/src/controls/filter-sheet.tsx +44 -194
  576. package/src/controls/index.ts +8 -0
  577. package/src/controls/multi-select-filter.tsx +179 -29
  578. package/src/controls/number-filter.tsx +329 -0
  579. package/src/controls/panel-row.module.css +86 -0
  580. package/src/controls/panel-row.module.css.d.ts +13 -0
  581. package/src/controls/panel-row.tsx +392 -0
  582. package/src/controls/range-filter.tsx +133 -43
  583. package/src/controls/search-filter.tsx +31 -13
  584. package/src/controls/select-filter.tsx +11 -1
  585. package/src/controls/slider-control.tsx +159 -0
  586. package/src/controls/sync-button.tsx +13 -3
  587. package/src/controls/toggle-filter.tsx +37 -17
  588. package/src/controls/view-tabs.tsx +63 -11
  589. package/src/controls-dates/date-range-picker.tsx +8 -1
  590. package/src/dashboard/delta-badge.tsx +5 -1
  591. package/src/dashboard/empty-state.tsx +72 -25
  592. package/src/dashboard/index.ts +19 -2
  593. package/src/dashboard/query-state.tsx +154 -84
  594. package/src/dashboard/settings-section.tsx +87 -31
  595. package/src/dashboard/stat-card.module.css +112 -26
  596. package/src/dashboard/stat-card.module.css.d.ts +5 -0
  597. package/src/dashboard/stat-card.tsx +207 -68
  598. package/src/dashboard/stat-group.module.css +66 -0
  599. package/src/dashboard/stat-group.module.css.d.ts +8 -0
  600. package/src/dashboard/stat-group.tsx +74 -0
  601. package/src/dashboard/widget-grid.module.css +53 -0
  602. package/src/dashboard/widget-grid.module.css.d.ts +9 -0
  603. package/src/dashboard/widget-grid.tsx +127 -0
  604. package/src/data/data-table.module.css +64 -0
  605. package/src/data/data-table.module.css.d.ts +11 -0
  606. package/src/data/data-table.tsx +927 -346
  607. package/src/data/index.ts +30 -2
  608. package/src/data/query-branch.ts +53 -0
  609. package/src/data/table.ts +5 -0
  610. package/src/data/virtual-list.tsx +189 -55
  611. package/src/data/virtual.ts +5 -1
  612. package/src/forms/FormErrorSummary.tsx +13 -6
  613. package/src/forms/create-form.ts +2 -2
  614. package/src/forms/field.ts +60 -11
  615. package/src/forms/form-layout.module.css +145 -0
  616. package/src/forms/form-layout.module.css.d.ts +20 -0
  617. package/src/forms/form-layout.tsx +305 -0
  618. package/src/forms/form-state.tsx +94 -0
  619. package/src/forms/index.ts +38 -7
  620. package/src/forms/use-field-array.ts +94 -0
  621. package/src/forms/use-form-draft.ts +145 -53
  622. package/src/forms/use-form-submit.ts +199 -0
  623. package/src/guard/index.ts +91 -23
  624. package/src/index.ts +79 -10
  625. package/src/nav/types.ts +15 -6
  626. package/src/notifications/bell.tsx +18 -4
  627. package/src/notifications/center.tsx +18 -5
  628. package/src/notifications/define-notifications.ts +64 -18
  629. package/src/notifications/index.ts +12 -1
  630. package/src/notifications/mount-guard.ts +41 -0
  631. package/src/notifications/notify.tsx +122 -3
  632. package/src/notifications/overlay.tsx +2 -0
  633. package/src/notifications/store.ts +7 -0
  634. package/src/provider/index.tsx +101 -13
  635. package/src/provider/lab-theme.ts +2 -1
  636. package/src/query/devtools.tsx +1 -0
  637. package/src/router-tanstack/field.ts +5 -0
  638. package/src/router-tanstack/index.ts +4 -0
  639. package/src/router-tanstack/search-store.ts +171 -12
  640. package/src/router-tanstack/use-nav.ts +18 -13
  641. package/src/section/index.ts +1 -1
  642. package/src/section/section.module.css +11 -0
  643. package/src/section/section.tsx +163 -96
  644. package/src/shell/account-types.ts +5 -2
  645. package/src/shell/app-brand.module.css +109 -0
  646. package/src/shell/app-brand.module.css.d.ts +14 -0
  647. package/src/shell/app-brand.tsx +140 -0
  648. package/src/shell/app-breadcrumbs.tsx +19 -9
  649. package/src/shell/app-header.module.css +10 -5
  650. package/src/shell/app-main.module.css +107 -0
  651. package/src/shell/app-main.module.css.d.ts +11 -0
  652. package/src/shell/app-mobile-nav.module.css +48 -27
  653. package/src/shell/app-mobile-nav.module.css.d.ts +0 -1
  654. package/src/shell/app-mobile-nav.tsx +43 -11
  655. package/src/shell/app-sidebar-account.tsx +29 -6
  656. package/src/shell/app-sidebar.module.css +53 -96
  657. package/src/shell/app-sidebar.module.css.d.ts +0 -5
  658. package/src/shell/app-sidebar.tsx +40 -113
  659. package/src/shell/index.tsx +156 -65
  660. package/src/shell/isomorphic-layout-effect.ts +14 -0
  661. package/src/shell/mobile-nav-model.ts +66 -10
  662. package/src/shell/nav-count-badge.tsx +6 -1
  663. package/src/shell/page-aside.module.css +174 -0
  664. package/src/shell/page-aside.module.css.d.ts +14 -0
  665. package/src/shell/page-aside.tsx +377 -0
  666. package/src/shell/page-bar.module.css +107 -13
  667. package/src/shell/page-bar.module.css.d.ts +4 -1
  668. package/src/shell/page-bar.tsx +294 -94
  669. package/src/shell/sidebar-search.module.css +1 -1
  670. package/src/shell/sidebar-search.tsx +13 -4
  671. package/src/state/fields.ts +360 -69
  672. package/src/state/persisted-or-local.ts +50 -0
  673. package/src/state/persisted.ts +76 -26
  674. package/src/state.ts +4 -7
  675. package/src/surfaces.ts +43 -12
  676. package/src/theme/ctl-theme.tsx +10 -0
  677. package/src/theme/index.ts +129 -16
  678. package/src/theme/nav-link.module.css +37 -26
  679. package/src/theme/segmented-control.module.css +22 -0
  680. package/src/theme/segmented-control.module.css.d.ts +1 -0
  681. package/src/theme-lab/boot.ts +140 -0
  682. package/src/theme-lab/index.tsx +21 -112
  683. package/src/theme-toggle/index.tsx +10 -3
  684. package/src/tokens/index.ts +50 -6
  685. package/src/tokens/palette.ts +58 -30
  686. package/src/utils/is-dev.ts +4 -0
  687. package/src/widget-header/delta-badge.tsx +25 -5
  688. package/src/widget-header/index.ts +10 -2
  689. package/src/widget-header/widget-header.module.css +87 -7
  690. package/src/widget-header/widget-header.module.css.d.ts +1 -0
  691. package/src/widget-header/widget-header.tsx +166 -42
  692. package/dist/agent/adapter.test.d.ts +0 -2
  693. package/dist/agent/adapter.test.d.ts.map +0 -1
  694. package/dist/agent/ai-sdk-transport.test.d.ts +0 -2
  695. package/dist/agent/ai-sdk-transport.test.d.ts.map +0 -1
  696. package/dist/agent/coalesce.test.d.ts +0 -2
  697. package/dist/agent/coalesce.test.d.ts.map +0 -1
  698. package/dist/agent/foreign.test.d.ts +0 -2
  699. package/dist/agent/foreign.test.d.ts.map +0 -1
  700. package/dist/agent/id.test.d.ts +0 -2
  701. package/dist/agent/id.test.d.ts.map +0 -1
  702. package/dist/agent/merge.test.d.ts +0 -2
  703. package/dist/agent/merge.test.d.ts.map +0 -1
  704. package/dist/agent/part-list.test.d.ts +0 -2
  705. package/dist/agent/part-list.test.d.ts.map +0 -1
  706. package/dist/agent/parts.test.d.ts +0 -2
  707. package/dist/agent/parts.test.d.ts.map +0 -1
  708. package/dist/agent/thread.test.d.ts +0 -2
  709. package/dist/agent/thread.test.d.ts.map +0 -1
  710. package/dist/agent/transport.test.d.ts +0 -2
  711. package/dist/agent/transport.test.d.ts.map +0 -1
  712. package/dist/agent/use-agent-stream.test.d.ts +0 -2
  713. package/dist/agent/use-agent-stream.test.d.ts.map +0 -1
  714. package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +0 -2
  715. package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +0 -1
  716. package/dist/agent/use-agent-thread-runs.resume.test.d.ts +0 -2
  717. package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +0 -1
  718. package/dist/agent/use-agent-thread-runs.test.d.ts +0 -2
  719. package/dist/agent/use-agent-thread-runs.test.d.ts.map +0 -1
  720. package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +0 -2
  721. package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +0 -1
  722. package/dist/agent-chat/composer.test.d.ts +0 -2
  723. package/dist/agent-chat/composer.test.d.ts.map +0 -1
  724. package/dist/agent-chat/relative-time.test.d.ts +0 -2
  725. package/dist/agent-chat/relative-time.test.d.ts.map +0 -1
  726. package/dist/agent-chat/thread-feed-row.test.d.ts +0 -2
  727. package/dist/agent-chat/thread-feed-row.test.d.ts.map +0 -1
  728. package/dist/agent-chat/thread-feed.test.d.ts +0 -2
  729. package/dist/agent-chat/thread-feed.test.d.ts.map +0 -1
  730. package/dist/agent-chat/thread-message.test.d.ts +0 -2
  731. package/dist/agent-chat/thread-message.test.d.ts.map +0 -1
  732. package/dist/agent-chat/thread-workspace.test.d.ts +0 -2
  733. package/dist/agent-chat/thread-workspace.test.d.ts.map +0 -1
  734. package/dist/agent-chat/tool-chip.test.d.ts +0 -2
  735. package/dist/agent-chat/tool-chip.test.d.ts.map +0 -1
  736. package/dist/agent-chat/virtualize.type-guard.test.d.ts +0 -2
  737. package/dist/agent-chat/virtualize.type-guard.test.d.ts.map +0 -1
  738. package/dist/charts/cursor/resolve.test.d.ts +0 -2
  739. package/dist/charts/cursor/resolve.test.d.ts.map +0 -1
  740. package/dist/charts/cursor/store.test.d.ts +0 -2
  741. package/dist/charts/cursor/store.test.d.ts.map +0 -1
  742. package/dist/charts/kinds/BandStrip.test.d.ts +0 -2
  743. package/dist/charts/kinds/BandStrip.test.d.ts.map +0 -1
  744. package/dist/charts/kinds/Bars.test.d.ts +0 -2
  745. package/dist/charts/kinds/Bars.test.d.ts.map +0 -1
  746. package/dist/charts/kinds/DualPanel.test.d.ts +0 -2
  747. package/dist/charts/kinds/DualPanel.test.d.ts.map +0 -1
  748. package/dist/charts/kinds/MirroredBars.test.d.ts +0 -2
  749. package/dist/charts/kinds/MirroredBars.test.d.ts.map +0 -1
  750. package/dist/charts/kinds/MultiLine.test.d.ts +0 -2
  751. package/dist/charts/kinds/MultiLine.test.d.ts.map +0 -1
  752. package/dist/charts/kinds/StackedArea.test.d.ts +0 -2
  753. package/dist/charts/kinds/StackedArea.test.d.ts.map +0 -1
  754. package/dist/charts/kinds/ZonedLine.test.d.ts +0 -2
  755. package/dist/charts/kinds/ZonedLine.test.d.ts.map +0 -1
  756. package/dist/charts/layout/auto-margin.test.d.ts +0 -2
  757. package/dist/charts/layout/auto-margin.test.d.ts.map +0 -1
  758. package/dist/charts/primitives/CartesianChart.test.d.ts +0 -2
  759. package/dist/charts/primitives/CartesianChart.test.d.ts.map +0 -1
  760. package/dist/charts/primitives/ChartCard.test.d.ts +0 -2
  761. package/dist/charts/primitives/ChartCard.test.d.ts.map +0 -1
  762. package/dist/charts/primitives/ChartFrame.test.d.ts +0 -2
  763. package/dist/charts/primitives/ChartFrame.test.d.ts.map +0 -1
  764. package/dist/charts/primitives/ChartLegend.test.d.ts +0 -2
  765. package/dist/charts/primitives/ChartLegend.test.d.ts.map +0 -1
  766. package/dist/charts/primitives/ChartTooltip.test.d.ts +0 -2
  767. package/dist/charts/primitives/ChartTooltip.test.d.ts.map +0 -1
  768. package/dist/charts/primitives/XZoneRects.test.d.ts +0 -2
  769. package/dist/charts/primitives/XZoneRects.test.d.ts.map +0 -1
  770. package/dist/charts/series.test.d.ts +0 -2
  771. package/dist/charts/series.test.d.ts.map +0 -1
  772. package/dist/charts/utils/domain.test.d.ts +0 -2
  773. package/dist/charts/utils/domain.test.d.ts.map +0 -1
  774. package/dist/charts/utils/measure-text.test.d.ts +0 -2
  775. package/dist/charts/utils/measure-text.test.d.ts.map +0 -1
  776. package/dist/cli/check-coverage.test.d.ts +0 -2
  777. package/dist/cli/check-coverage.test.d.ts.map +0 -1
  778. package/dist/cli/check-theme.test.d.ts +0 -2
  779. package/dist/cli/check-theme.test.d.ts.map +0 -1
  780. package/dist/cli/help.test.d.ts +0 -2
  781. package/dist/cli/help.test.d.ts.map +0 -1
  782. package/dist/cli/init-sync.test.d.ts +0 -2
  783. package/dist/cli/init-sync.test.d.ts.map +0 -1
  784. package/dist/cli/placement-engine.test.d.ts +0 -2
  785. package/dist/cli/placement-engine.test.d.ts.map +0 -1
  786. package/dist/cli/shipped-versions.test.d.ts +0 -2
  787. package/dist/cli/shipped-versions.test.d.ts.map +0 -1
  788. package/dist/cli/tarball-parity.test.d.ts +0 -2
  789. package/dist/cli/tarball-parity.test.d.ts.map +0 -1
  790. package/dist/cli/template-format.test.d.ts +0 -2
  791. package/dist/cli/template-format.test.d.ts.map +0 -1
  792. package/dist/cli/template-ledger.test.d.ts +0 -2
  793. package/dist/cli/template-ledger.test.d.ts.map +0 -1
  794. package/dist/cli/tokens-css.test.d.ts +0 -2
  795. package/dist/cli/tokens-css.test.d.ts.map +0 -1
  796. package/dist/cli/toolchain-wiring.test.d.ts +0 -2
  797. package/dist/cli/toolchain-wiring.test.d.ts.map +0 -1
  798. package/dist/cli/waiver-audit.test.d.ts +0 -2
  799. package/dist/cli/waiver-audit.test.d.ts.map +0 -1
  800. package/dist/content/article-actions.test.d.ts +0 -2
  801. package/dist/content/article-actions.test.d.ts.map +0 -1
  802. package/dist/content/article-model.test.d.ts +0 -2
  803. package/dist/content/article-model.test.d.ts.map +0 -1
  804. package/dist/content/block-split.test.d.ts +0 -2
  805. package/dist/content/block-split.test.d.ts.map +0 -1
  806. package/dist/content/heading-components.test.d.ts +0 -2
  807. package/dist/content/heading-components.test.d.ts.map +0 -1
  808. package/dist/content/markdown.test.d.ts +0 -2
  809. package/dist/content/markdown.test.d.ts.map +0 -1
  810. package/dist/content/prose.module.css.test.d.ts +0 -2
  811. package/dist/content/prose.module.css.test.d.ts.map +0 -1
  812. package/dist/content/sanitize.test.d.ts +0 -2
  813. package/dist/content/sanitize.test.d.ts.map +0 -1
  814. package/dist/content/slug.test.d.ts +0 -2
  815. package/dist/content/slug.test.d.ts.map +0 -1
  816. package/dist/controls/actions.test.d.ts +0 -2
  817. package/dist/controls/actions.test.d.ts.map +0 -1
  818. package/dist/controls/actions.type-guard.test.d.ts +0 -2
  819. package/dist/controls/actions.type-guard.test.d.ts.map +0 -1
  820. package/dist/controls/control-group.test.d.ts +0 -2
  821. package/dist/controls/control-group.test.d.ts.map +0 -1
  822. package/dist/controls/controls.router.test.d.ts +0 -2
  823. package/dist/controls/controls.router.test.d.ts.map +0 -1
  824. package/dist/controls/filter-set.test.d.ts +0 -2
  825. package/dist/controls/filter-set.test.d.ts.map +0 -1
  826. package/dist/controls/peer-boundary.test.d.ts +0 -2
  827. package/dist/controls/peer-boundary.test.d.ts.map +0 -1
  828. package/dist/controls/props-contract.test.d.ts +0 -2
  829. package/dist/controls/props-contract.test.d.ts.map +0 -1
  830. package/dist/controls/sync-button.test.d.ts +0 -2
  831. package/dist/controls/sync-button.test.d.ts.map +0 -1
  832. package/dist/dashboard/query-state.test.d.ts +0 -2
  833. package/dist/dashboard/query-state.test.d.ts.map +0 -1
  834. package/dist/dashboard/settings-section.test.d.ts +0 -2
  835. package/dist/dashboard/settings-section.test.d.ts.map +0 -1
  836. package/dist/dashboard/stat-card.test.d.ts +0 -2
  837. package/dist/dashboard/stat-card.test.d.ts.map +0 -1
  838. package/dist/data/data-table.test.d.ts +0 -2
  839. package/dist/data/data-table.test.d.ts.map +0 -1
  840. package/dist/guard/check-source.test.d.ts +0 -2
  841. package/dist/guard/check-source.test.d.ts.map +0 -1
  842. package/dist/guard/grace.test.d.ts +0 -20
  843. package/dist/guard/grace.test.d.ts.map +0 -1
  844. package/dist/guard/guard-hook.test.d.ts +0 -2
  845. package/dist/guard/guard-hook.test.d.ts.map +0 -1
  846. package/dist/provider/index.test.d.ts +0 -2
  847. package/dist/provider/index.test.d.ts.map +0 -1
  848. package/dist/provider/lab-theme.test.d.ts +0 -2
  849. package/dist/provider/lab-theme.test.d.ts.map +0 -1
  850. package/dist/query/error-message.test.d.ts +0 -2
  851. package/dist/query/error-message.test.d.ts.map +0 -1
  852. package/dist/router-tanstack/multi-search-param-store.test.d.ts +0 -2
  853. package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +0 -1
  854. package/dist/router-tanstack/nav.test.d.ts +0 -2
  855. package/dist/router-tanstack/nav.test.d.ts.map +0 -1
  856. package/dist/router-tanstack/search-param-store.test.d.ts +0 -2
  857. package/dist/router-tanstack/search-param-store.test.d.ts.map +0 -1
  858. package/dist/router-tanstack/search-store.router.test.d.ts +0 -2
  859. package/dist/router-tanstack/search-store.router.test.d.ts.map +0 -1
  860. package/dist/router-tanstack/search-store.test.d.ts +0 -2
  861. package/dist/router-tanstack/search-store.test.d.ts.map +0 -1
  862. package/dist/router-tanstack/use-nav.test.d.ts +0 -2
  863. package/dist/router-tanstack/use-nav.test.d.ts.map +0 -1
  864. package/dist/section/section.test.d.ts +0 -2
  865. package/dist/section/section.test.d.ts.map +0 -1
  866. package/dist/shell/app-mobile-nav.test.d.ts +0 -2
  867. package/dist/shell/app-mobile-nav.test.d.ts.map +0 -1
  868. package/dist/shell/app-sidebar.test.d.ts +0 -2
  869. package/dist/shell/app-sidebar.test.d.ts.map +0 -1
  870. package/dist/shell/index.test.d.ts +0 -2
  871. package/dist/shell/index.test.d.ts.map +0 -1
  872. package/dist/shell/mobile-nav-model.test.d.ts +0 -2
  873. package/dist/shell/mobile-nav-model.test.d.ts.map +0 -1
  874. package/dist/shell/page-bar.test.d.ts +0 -2
  875. package/dist/shell/page-bar.test.d.ts.map +0 -1
  876. package/dist/state/fields.test.d.ts +0 -2
  877. package/dist/state/fields.test.d.ts.map +0 -1
  878. package/dist/styles.floor.test.d.ts +0 -2
  879. package/dist/styles.floor.test.d.ts.map +0 -1
  880. package/dist/theme/border-coverage.test.d.ts +0 -18
  881. package/dist/theme/border-coverage.test.d.ts.map +0 -1
  882. package/dist/theme/contrast.test.d.ts +0 -2
  883. package/dist/theme/contrast.test.d.ts.map +0 -1
  884. package/dist/theme/ctl-theme.test.d.ts +0 -2
  885. package/dist/theme/ctl-theme.test.d.ts.map +0 -1
  886. package/dist/theme/ctl-tier-coverage.test.d.ts +0 -2
  887. package/dist/theme/ctl-tier-coverage.test.d.ts.map +0 -1
  888. package/dist/theme/density-option.test.d.ts +0 -2
  889. package/dist/theme/density-option.test.d.ts.map +0 -1
  890. package/dist/theme/density-relations.test.d.ts +0 -2
  891. package/dist/theme/density-relations.test.d.ts.map +0 -1
  892. package/dist/theme/derive-theme.test.d.ts +0 -2
  893. package/dist/theme/derive-theme.test.d.ts.map +0 -1
  894. package/dist/theme/divider-law.test.d.ts +0 -2
  895. package/dist/theme/divider-law.test.d.ts.map +0 -1
  896. package/dist/theme/fonts-option.test.d.ts +0 -2
  897. package/dist/theme/fonts-option.test.d.ts.map +0 -1
  898. package/dist/theme/icon-slot.test.d.ts +0 -2
  899. package/dist/theme/icon-slot.test.d.ts.map +0 -1
  900. package/dist/theme/layout-rhythm-css.test.d.ts +0 -2
  901. package/dist/theme/layout-rhythm-css.test.d.ts.map +0 -1
  902. package/dist/theme/radius-option.test.d.ts +0 -2
  903. package/dist/theme/radius-option.test.d.ts.map +0 -1
  904. package/dist/theme/radius.test.d.ts +0 -2
  905. package/dist/theme/radius.test.d.ts.map +0 -1
  906. package/dist/theme/shadow-surfaces.test.d.ts +0 -26
  907. package/dist/theme/shadow-surfaces.test.d.ts.map +0 -1
  908. package/dist/theme/spacing.test.d.ts +0 -2
  909. package/dist/theme/spacing.test.d.ts.map +0 -1
  910. package/dist/theme/use-basalt-spacing.test.d.ts +0 -2
  911. package/dist/theme/use-basalt-spacing.test.d.ts.map +0 -1
  912. package/dist/theme-lab/derive-controls.test.d.ts +0 -2
  913. package/dist/theme-lab/derive-controls.test.d.ts.map +0 -1
  914. package/dist/theme-lab/derive-state.test.d.ts +0 -2
  915. package/dist/theme-lab/derive-state.test.d.ts.map +0 -1
  916. package/dist/theme-lab/theme-lab.test.d.ts +0 -2
  917. package/dist/theme-lab/theme-lab.test.d.ts.map +0 -1
  918. package/dist/tokens/build-fonts-css.test.d.ts +0 -2
  919. package/dist/tokens/build-fonts-css.test.d.ts.map +0 -1
  920. package/dist/tokens/build-radius-css.test.d.ts +0 -2
  921. package/dist/tokens/build-radius-css.test.d.ts.map +0 -1
  922. package/dist/tokens/chart-margin.test.d.ts +0 -2
  923. package/dist/tokens/chart-margin.test.d.ts.map +0 -1
  924. package/dist/tokens/density.test.d.ts +0 -2
  925. package/dist/tokens/density.test.d.ts.map +0 -1
  926. package/dist/tokens/derive-radius.test.d.ts +0 -2
  927. package/dist/tokens/derive-radius.test.d.ts.map +0 -1
  928. package/dist/tokens/derive.test.d.ts +0 -2
  929. package/dist/tokens/derive.test.d.ts.map +0 -1
  930. package/dist/tokens/palette.test.d.ts +0 -2
  931. package/dist/tokens/palette.test.d.ts.map +0 -1
  932. package/dist/tokens/text-scale.test.d.ts +0 -2
  933. package/dist/tokens/text-scale.test.d.ts.map +0 -1
  934. package/dist/vite-color-mix.test.d.ts +0 -2
  935. package/dist/vite-color-mix.test.d.ts.map +0 -1
  936. package/dist/vite.test.d.ts +0 -2
  937. package/dist/vite.test.d.ts.map +0 -1
  938. package/dist/widget-header/delta-badge.test.d.ts +0 -2
  939. package/dist/widget-header/delta-badge.test.d.ts.map +0 -1
  940. package/dist/widget-header/no-mantine.test.d.ts +0 -2
  941. package/dist/widget-header/no-mantine.test.d.ts.map +0 -1
  942. package/dist/widget-header/widget-header.test.d.ts +0 -2
  943. package/dist/widget-header/widget-header.test.d.ts.map +0 -1
  944. package/src/agent/adapter.test.ts +0 -1640
  945. package/src/agent/ai-sdk-transport.test.ts +0 -658
  946. package/src/agent/coalesce.test.ts +0 -387
  947. package/src/agent/foreign.test.ts +0 -51
  948. package/src/agent/id.test.ts +0 -169
  949. package/src/agent/merge.test.ts +0 -206
  950. package/src/agent/part-list.test.tsx +0 -112
  951. package/src/agent/parts.test.ts +0 -720
  952. package/src/agent/thread.test.ts +0 -220
  953. package/src/agent/transport.test.ts +0 -70
  954. package/src/agent/use-agent-stream.test.tsx +0 -287
  955. package/src/agent/use-agent-thread-runs.foreign.test.tsx +0 -138
  956. package/src/agent/use-agent-thread-runs.resume.test.tsx +0 -294
  957. package/src/agent/use-agent-thread-runs.test.tsx +0 -1120
  958. package/src/agent/use-agent-thread-runs.wedge.test.tsx +0 -387
  959. package/src/agent-chat/composer.test.tsx +0 -924
  960. package/src/agent-chat/relative-time.test.ts +0 -95
  961. package/src/agent-chat/thread-feed-row.test.tsx +0 -510
  962. package/src/agent-chat/thread-feed.test.tsx +0 -241
  963. package/src/agent-chat/thread-message.test.tsx +0 -1285
  964. package/src/agent-chat/thread-workspace.test.tsx +0 -169
  965. package/src/agent-chat/tool-chip.test.tsx +0 -139
  966. package/src/agent-chat/virtualize.type-guard.test.ts +0 -49
  967. package/src/charts/cursor/resolve.test.ts +0 -151
  968. package/src/charts/cursor/store.test.ts +0 -64
  969. package/src/charts/kinds/BandStrip.test.tsx +0 -282
  970. package/src/charts/kinds/Bars.test.tsx +0 -183
  971. package/src/charts/kinds/DualPanel.test.tsx +0 -527
  972. package/src/charts/kinds/MirroredBars.test.tsx +0 -232
  973. package/src/charts/kinds/MultiLine.test.tsx +0 -218
  974. package/src/charts/kinds/StackedArea.test.tsx +0 -114
  975. package/src/charts/kinds/ZonedLine.test.tsx +0 -147
  976. package/src/charts/layout/auto-margin.test.ts +0 -42
  977. package/src/charts/primitives/CartesianChart.test.tsx +0 -647
  978. package/src/charts/primitives/ChartCard.test.tsx +0 -66
  979. package/src/charts/primitives/ChartFrame.test.tsx +0 -142
  980. package/src/charts/primitives/ChartLegend.test.tsx +0 -78
  981. package/src/charts/primitives/ChartTooltip.test.tsx +0 -44
  982. package/src/charts/primitives/XZoneRects.test.tsx +0 -123
  983. package/src/charts/series.test.ts +0 -112
  984. package/src/charts/utils/domain.test.ts +0 -54
  985. package/src/charts/utils/measure-text.test.ts +0 -36
  986. package/src/cli/check-coverage.test.ts +0 -297
  987. package/src/cli/check-theme.test.ts +0 -837
  988. package/src/cli/help.test.ts +0 -170
  989. package/src/cli/init-sync.test.ts +0 -343
  990. package/src/cli/placement-engine.test.ts +0 -298
  991. package/src/cli/shipped-versions.test.ts +0 -83
  992. package/src/cli/tarball-parity.test.ts +0 -44
  993. package/src/cli/template-format.test.ts +0 -64
  994. package/src/cli/template-ledger.test.ts +0 -219
  995. package/src/cli/tokens-css.test.ts +0 -249
  996. package/src/cli/toolchain-wiring.test.ts +0 -1358
  997. package/src/cli/waiver-audit.test.ts +0 -215
  998. package/src/content/article-actions.test.ts +0 -78
  999. package/src/content/article-model.test.ts +0 -119
  1000. package/src/content/block-split.test.ts +0 -75
  1001. package/src/content/heading-components.test.tsx +0 -65
  1002. package/src/content/markdown.test.tsx +0 -603
  1003. package/src/content/prose.module.css.test.ts +0 -39
  1004. package/src/content/sanitize.test.ts +0 -659
  1005. package/src/content/slug.test.ts +0 -62
  1006. package/src/controls/actions.test.tsx +0 -252
  1007. package/src/controls/actions.type-guard.test.ts +0 -63
  1008. package/src/controls/control-group.test.tsx +0 -229
  1009. package/src/controls/controls.router.test.tsx +0 -637
  1010. package/src/controls/filter-set.test.tsx +0 -472
  1011. package/src/controls/peer-boundary.test.ts +0 -85
  1012. package/src/controls/props-contract.test.tsx +0 -106
  1013. package/src/controls/sync-button.test.tsx +0 -183
  1014. package/src/dashboard/query-state.test.tsx +0 -152
  1015. package/src/dashboard/settings-section.test.tsx +0 -56
  1016. package/src/dashboard/stat-card.test.tsx +0 -154
  1017. package/src/data/data-table.test.tsx +0 -434
  1018. package/src/guard/check-source.test.ts +0 -3355
  1019. package/src/guard/grace.test.ts +0 -149
  1020. package/src/guard/guard-hook.test.ts +0 -203
  1021. package/src/provider/index.test.tsx +0 -101
  1022. package/src/provider/lab-theme.test.ts +0 -147
  1023. package/src/query/error-message.test.ts +0 -67
  1024. package/src/router-tanstack/multi-search-param-store.test.ts +0 -124
  1025. package/src/router-tanstack/nav.test.ts +0 -111
  1026. package/src/router-tanstack/search-param-store.test.ts +0 -135
  1027. package/src/router-tanstack/search-store.router.test.tsx +0 -661
  1028. package/src/router-tanstack/search-store.test.ts +0 -418
  1029. package/src/router-tanstack/use-nav.test.tsx +0 -187
  1030. package/src/section/section.test.tsx +0 -204
  1031. package/src/shell/app-mobile-nav.test.tsx +0 -403
  1032. package/src/shell/app-sidebar.test.tsx +0 -509
  1033. package/src/shell/index.test.tsx +0 -428
  1034. package/src/shell/mobile-nav-model.test.ts +0 -517
  1035. package/src/shell/page-bar.test.tsx +0 -316
  1036. package/src/state/fields.test.tsx +0 -258
  1037. package/src/styles.floor.test.ts +0 -36
  1038. package/src/theme/border-coverage.test.ts +0 -272
  1039. package/src/theme/contrast.test.ts +0 -354
  1040. package/src/theme/ctl-theme.test.tsx +0 -275
  1041. package/src/theme/ctl-tier-coverage.test.ts +0 -170
  1042. package/src/theme/density-option.test.ts +0 -96
  1043. package/src/theme/density-relations.test.ts +0 -506
  1044. package/src/theme/derive-theme.test.ts +0 -101
  1045. package/src/theme/divider-law.test.ts +0 -259
  1046. package/src/theme/fonts-option.test.ts +0 -75
  1047. package/src/theme/icon-slot.test.tsx +0 -275
  1048. package/src/theme/layout-rhythm-css.test.ts +0 -72
  1049. package/src/theme/radius-option.test.ts +0 -86
  1050. package/src/theme/radius.test.ts +0 -142
  1051. package/src/theme/shadow-surfaces.test.ts +0 -488
  1052. package/src/theme/spacing.test.ts +0 -495
  1053. package/src/theme/use-basalt-spacing.test.tsx +0 -55
  1054. package/src/theme-lab/derive-controls.test.ts +0 -94
  1055. package/src/theme-lab/derive-state.test.ts +0 -71
  1056. package/src/theme-lab/theme-lab.test.ts +0 -46
  1057. package/src/tokens/build-fonts-css.test.ts +0 -52
  1058. package/src/tokens/build-radius-css.test.ts +0 -25
  1059. package/src/tokens/chart-margin.test.ts +0 -39
  1060. package/src/tokens/density.test.ts +0 -259
  1061. package/src/tokens/derive-radius.test.ts +0 -62
  1062. package/src/tokens/derive.test.ts +0 -30
  1063. package/src/tokens/palette.test.ts +0 -114
  1064. package/src/tokens/text-scale.test.ts +0 -51
  1065. package/src/vite-color-mix.test.ts +0 -46
  1066. package/src/vite.test.ts +0 -423
  1067. package/src/widget-header/delta-badge.test.tsx +0 -60
  1068. package/src/widget-header/no-mantine.test.ts +0 -33
  1069. package/src/widget-header/widget-header.test.tsx +0 -187
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Internal — one disclosure flag that persists only when the caller named a key.
3
+ *
4
+ * `Section`'s collapse and `PageAside`'s fold are the same hook written twice: an optional
5
+ * `persistKey` decides whether the flag survives a reload, and both a `useState` and a
6
+ * `createPersistedState` hook are ALWAYS called so the hook order is stable across a key appearing
7
+ * or disappearing. Only the branch the caller asked for is returned, so an unpersisted surface
8
+ * never writes to storage.
9
+ *
10
+ * `scope` stays a parameter rather than being folded into `key`: it is what keeps
11
+ * `basalt:section:<key>` and `basalt:aside:<key>` from colliding when two surfaces on one page
12
+ * persist under the same name.
13
+ *
14
+ * Not exported from `../state` — this is an internal hook, not part of the `./state` surface.
15
+ */
16
+ import { useMemo, useState } from 'react'
17
+ import { createPersistedState } from './persisted'
18
+
19
+ /** The key an unpersisted caller parks on — never read, because that branch returns local state. */
20
+ const UNPERSISTED_KEY = '__local__'
21
+
22
+ export function usePersistedOrLocal<T>({
23
+ scope,
24
+ persistKey,
25
+ initial,
26
+ }: {
27
+ /** The storage namespace — `section`, `aside`. Prefixed onto `persistKey`. */
28
+ scope: string
29
+ /** Persist under `basalt:<scope>:<persistKey>`. Omitted → local state, nothing written. */
30
+ persistKey: string | undefined
31
+ /** First-render value, respected only while nothing is persisted. */
32
+ initial: T
33
+ }): readonly [T, (next: T) => void] {
34
+ const [local, setLocal] = useState(initial)
35
+ // `createPersistedState` is a per-key module FACTORY, so it is memoized rather than called during
36
+ // render — the same reason `shell/index.tsx` memoizes its collapse store.
37
+ const usePersisted = useMemo(
38
+ () =>
39
+ createPersistedState<T>({
40
+ key: `${scope}:${persistKey ?? UNPERSISTED_KEY}`,
41
+ version: 1,
42
+ initial,
43
+ }),
44
+ [scope, persistKey, initial],
45
+ )
46
+ const [persisted, setPersisted] = usePersisted()
47
+
48
+ if (persistKey !== undefined) return [persisted, setPersisted] as const
49
+ return [local, setLocal] as const
50
+ }
@@ -32,6 +32,42 @@ export type PersistedStateOptions<T> = {
32
32
  readonly schema?: StandardSchemaV1<unknown, T>
33
33
  }
34
34
 
35
+ /**
36
+ * Every subscriber for ONE storage key, shared by every `createPersistedState` instance over that
37
+ * key — plus the single `storage` event listener the key needs.
38
+ *
39
+ * Module-level rather than per-instance because two instances of the same key are ordinary, not a
40
+ * mistake: a page's `createSearchStore` and a widget's `createPersistedState` legitimately name the
41
+ * same key, and a consumer re-exporting a store from two modules ends up there by accident. With
42
+ * per-instance listener sets a write through one instance updated localStorage and notified only
43
+ * its own hooks, so the other instance's components kept rendering the stale value until something
44
+ * else re-rendered them — in the SAME tab, while the cross-tab path (the `storage` event) worked.
45
+ *
46
+ * The map is keyed by the NAMESPACED key and holds no window reference; a channel is created on
47
+ * first subscribe, which only happens in the browser (`subscribe` is never passed on the server).
48
+ */
49
+ type KeyChannel = {
50
+ readonly listeners: Set<() => void>
51
+ handler: ((e: StorageEvent) => void) | null
52
+ }
53
+
54
+ const channels = new Map<string, KeyChannel>()
55
+
56
+ /** Wake every hook on a key, whichever instance holds it. */
57
+ function notify(storageKey: string): void {
58
+ const channel = channels.get(storageKey)
59
+ if (channel === undefined) return
60
+ for (const listener of channel.listeners) listener()
61
+ }
62
+
63
+ function channelFor(storageKey: string): KeyChannel {
64
+ const existing = channels.get(storageKey)
65
+ if (existing !== undefined) return existing
66
+ const created: KeyChannel = { listeners: new Set(), handler: null }
67
+ channels.set(storageKey, created)
68
+ return created
69
+ }
70
+
35
71
  /** The envelope stored in localStorage: `{ v: number, value: unknown }`. */
36
72
  type Envelope = { v: number; value: unknown }
37
73
 
@@ -73,16 +109,19 @@ function parseStorage<T>(raw: string | null, opts: PersistedStateOptions<T>): T
73
109
  }
74
110
  }
75
111
 
76
- function writeStorage<T>(opts: PersistedStateOptions<T>, next: T): void {
77
- const storageKey = `basalt:${opts.key}`
112
+ function writeEnvelope(storageKey: string, version: number, value: unknown): void {
78
113
  try {
79
- const envelope: Envelope = { v: opts.version, value: next }
114
+ const envelope: Envelope = { v: version, value }
80
115
  window.localStorage.setItem(storageKey, JSON.stringify(envelope))
81
116
  } catch {
82
117
  // Silently fail (storage full, private browsing, etc.)
83
118
  }
84
119
  }
85
120
 
121
+ function writeStorage<T>(opts: PersistedStateOptions<T>, next: T): void {
122
+ writeEnvelope(`basalt:${opts.key}`, opts.version, next)
123
+ }
124
+
86
125
  /**
87
126
  * Versioned, Standard-Schema-validated localStorage state via useSyncExternalStore (no zustand).
88
127
  * SSR-safe (getServerSnapshot returns `initial`). Cross-tab via the storage event.
@@ -100,32 +139,25 @@ export function createPersistedState<T>(
100
139
  ): () => readonly [T, (next: T) => void] {
101
140
  const storageKey = `basalt:${opts.key}`
102
141
 
103
- // One Set of subscriber callbacks — mirrors notifications/store.ts single-listener-to-Set pattern.
104
- const listeners = new Set<() => void>()
105
-
106
- // ONE module-scoped 'storage' event listener per key, registered lazily on first subscriber.
107
- // Removed when the last subscriber unsubscribes (cleanup semantics preserved).
108
- let storageHandler: ((e: StorageEvent) => void) | null = null
109
-
110
142
  const subscribe = (cb: () => void): (() => void) => {
111
- listeners.add(cb)
112
-
113
- // Attach the shared window listener on the first subscriber.
114
- if (storageHandler === null) {
115
- storageHandler = (e: StorageEvent): void => {
116
- if (e.key === storageKey) {
117
- for (const listener of listeners) listener()
118
- }
143
+ // The subscriber set is the KEY's, not this instance's — see `KeyChannel`.
144
+ const channel = channelFor(storageKey)
145
+ channel.listeners.add(cb)
146
+
147
+ // ONE 'storage' event listener per key, registered lazily on the first subscriber and removed
148
+ // when the last one leaves (cleanup semantics preserved).
149
+ if (channel.handler === null) {
150
+ channel.handler = (e: StorageEvent): void => {
151
+ if (e.key === storageKey) notify(storageKey)
119
152
  }
120
- window.addEventListener('storage', storageHandler)
153
+ window.addEventListener('storage', channel.handler)
121
154
  }
122
155
 
123
156
  return () => {
124
- listeners.delete(cb)
125
- // Detach the shared window listener when the last subscriber unsubscribes.
126
- if (listeners.size === 0 && storageHandler !== null) {
127
- window.removeEventListener('storage', storageHandler)
128
- storageHandler = null
157
+ channel.listeners.delete(cb)
158
+ if (channel.listeners.size === 0 && channel.handler !== null) {
159
+ window.removeEventListener('storage', channel.handler)
160
+ channel.handler = null
129
161
  }
130
162
  }
131
163
  }
@@ -158,8 +190,9 @@ export function createPersistedState<T>(
158
190
 
159
191
  const setState = (next: T): void => {
160
192
  writeStorage(opts, next)
161
- // Notify in-tab listeners (the 'storage' event only fires in OTHER tabs)
162
- for (const cb of listeners) cb()
193
+ // Notify every in-tab listener on this KEY — the 'storage' event fires in OTHER tabs only, and
194
+ // a second instance of the same key has its own hooks to wake.
195
+ notify(storageKey)
163
196
  }
164
197
 
165
198
  // Detect SSR once at creation time — the environment doesn't change between renders.
@@ -209,3 +242,20 @@ export function readPersistedValue(key: string, version?: number): unknown | nul
209
242
  return null
210
243
  }
211
244
  }
245
+
246
+ /**
247
+ * Write a value under the namespaced key `basalt:<key>` in the same versioned envelope
248
+ * `createPersistedState` writes, and wake every hook on that key — the write half of
249
+ * `readPersistedValue`, and plain in the same way: no React required.
250
+ *
251
+ * The one call site is a store field's `clear()`, which has to DELETE its key from the store's
252
+ * record from an event handler, where the hook's setter is not in reach. Not exported from the
253
+ * `basalt-ui/state` barrel: the two store factories are the API, this is their seam.
254
+ *
255
+ * @internal
256
+ */
257
+ export function writePersistedValue(key: string, version: number, value: unknown): void {
258
+ const storageKey = `basalt:${key}`
259
+ writeEnvelope(storageKey, version, value)
260
+ notify(storageKey)
261
+ }
package/src/state.ts CHANGED
@@ -30,6 +30,10 @@ export {
30
30
  type RangeValue,
31
31
  type RangeParams,
32
32
  type RangePresets,
33
+ type RangeWindow,
34
+ type RangeWindows,
35
+ type FieldFallback,
36
+ type FieldSetOptions,
33
37
  type EnumField,
34
38
  type MultiField,
35
39
  type RangeField,
@@ -42,11 +46,4 @@ export {
42
46
  type FieldHandle,
43
47
  type SearchValues,
44
48
  type StoredValues,
45
- // @internal — the seam `createSearchStore` is built on, not a consumer API.
46
- type FieldCodec,
47
- type StoreEntry,
48
- type StoreCoreOptions,
49
- type StoreCore,
50
- resolveFieldCodec,
51
- createStoreCore,
52
49
  } from './state/fields'
package/src/surfaces.ts CHANGED
@@ -48,12 +48,19 @@ export const PLUGIN_RULE_ID_LIST = [
48
48
  'raw-scroll-container',
49
49
  'hand-rolled-filter',
50
50
  'control-outside-home',
51
+ 'bound-control-outside-home',
51
52
  'control-size-literal',
52
53
  'page-bar-budget',
53
54
  'in-body-page-title',
54
55
  'responsive-twin',
55
56
  'search-literal-link',
56
57
  'use-search-from-literal',
58
+ 'provider-above-router',
59
+ 'duplicate-notifications-mount',
60
+ 'query-dual-import',
61
+ 'query-fn-unwrap',
62
+ 'deprecated-export',
63
+ 'forms-field-key',
57
64
  'visx-boundary',
58
65
  'visx-tooltip',
59
66
  'token-layer-boundary',
@@ -78,7 +85,7 @@ export type SkillName = 'basalt-app' | 'basalt-design' | 'basalt-charts'
78
85
  * @example
79
86
  * const l: Layer = 'headless'
80
87
  */
81
- export type Layer = 'mantine-coupled' | 'headless' | 'app-global' | 'non-js-asset'
88
+ export type Layer = 'mantine-coupled' | 'headless' | 'app-global' | 'non-js-asset' | 'build-tooling'
82
89
 
83
90
  /**
84
91
  * A single import ban. `{ctx}` in the message is filled per target so shipped/repo wording
@@ -267,9 +274,22 @@ export const SURFACES = {
267
274
  'raw-scroll-container',
268
275
  'page-bar-budget',
269
276
  'shadow-basalt-export',
277
+ // The two mount-order laws, guarded as of 1.28.0 (F5) — both same-file static ancestry, so
278
+ // both `warn`. `deprecated-export` sits here too: the ledger it reads spans subpaths, and
279
+ // `BasaltProvider`'s three flattened connectivity props are most of it.
280
+ 'provider-above-router',
281
+ 'duplicate-notifications-mount',
282
+ 'deprecated-export',
283
+ ],
284
+ // agent/rules/basalt-mantine.md — stated, not guarded. The other two laws that stood here
285
+ // gained `provider-above-router` / `duplicate-notifications-mount` at 1.28.0; this one has no
286
+ // AST form left to catch, because `cssVariablesResolver` is now `Omit`ted from the accepted
287
+ // prop type and a hand-built `createTheme` is a consumer's own call to make.
288
+ advisoryLaws: [
289
+ "no second cssVariablesResolver — don't hand-build createTheme or re-add the resolver basalt already installs",
270
290
  ],
271
291
  description:
272
- 'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, PageBar, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, WidgetHeader, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)',
292
+ 'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, PageBar, PageAside, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, WidgetHeader, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)',
273
293
  optionalPeers: [
274
294
  'react-markdown',
275
295
  'remark-gfm',
@@ -358,7 +378,7 @@ export const SURFACES = {
358
378
  },
359
379
  './vite': {
360
380
  kind: 'tooling',
361
- layer: 'mantine-coupled',
381
+ layer: 'build-tooling',
362
382
  description:
363
383
  'basaltViteConfig(opts) — Vite preset for basalt-ui consumer apps; basaltAppPlugin(opts) — PWA head, manifest, and icon metadata derived from the token palette',
364
384
  optionalPeers: ['vite-plugin-pwa'],
@@ -381,7 +401,10 @@ export const SURFACES = {
381
401
  rule: 'batteries',
382
402
  skill: ['basalt-app'],
383
403
  guardKinds: [],
384
- pluginRules: [],
404
+ // Both laws this surface used to declare advisory (F5), guarded as of 1.28.0 and both `warn`:
405
+ // `query-dual-import`'s softer half reads intent ("this file is already a basalt file") and
406
+ // `query-fn-unwrap` is a text heuristic inside a syntactic range. See their grace entries.
407
+ pluginRules: ['query-dual-import', 'query-fn-unwrap'],
385
408
  description: 'createBasaltQueryClient, transport-agnostic unwrap, lazy BasaltQueryDevtools',
386
409
  optionalPeers: ['@tanstack/react-query-devtools'],
387
410
  globs: {
@@ -415,9 +438,13 @@ export const SURFACES = {
415
438
  rule: 'batteries',
416
439
  skill: ['basalt-design'],
417
440
  guardKinds: [],
418
- pluginRules: [],
441
+ // The one change in the 1.28.0 forms minor a compiler cannot see: `inputProps` stopped
442
+ // returning `key`, and the pre-1.28.0 spread still type-checks, renders and validates — it
443
+ // only stops resetting. `warn` through the 1.30.0 grace because it fires on what every
444
+ // consumer ships today (`PLUGIN_RULE_GRACE`).
445
+ pluginRules: ['forms-field-key'],
419
446
  description:
420
- 'Mantine form adapter: useBasaltForm, field, FormErrorSummary, useFormDraft (Standard Schema)',
447
+ 'Mantine form layer: useBasaltForm + inputProps/fieldKey (two calls — a spread `key` is a React 19 warning), the FormSection/FormRow/FormGroup/FormActions layout (FormRow is law C1’s form row), useFormSubmit (submit state, decoded errors, server fieldErrors, focus-first-error, validateAsync), FormStateProvider disable propagation, useFieldArray, FormErrorSummary, useFormDraft with autosave (Standard Schema; deprecated `field` alias for `inputProps` until the surface next changes)',
421
448
  optionalPeers: ['@mantine/form'],
422
449
  forbiddenImports: [],
423
450
  },
@@ -553,12 +580,16 @@ export const SURFACES = {
553
580
  // The text lane of law C1 — the plugin's `control-outside-home` seen through a 12-line host-tag
554
581
  // window, since a regex scan has no ancestry. Same law, same wave, same promotion.
555
582
  guardKinds: ['raw-selection-control'],
556
- // The control tier itself (laws C1/C3/C5/C9). `hand-rolled-filter` ships `error` — "inside a
557
- // slot" is structural; the other three are grace entries in `PLUGIN_RULE_GRACE` until 1.27.0.
558
- // The budget rules live on `.` with `PageBar` itself.
583
+ // The control tier itself (laws C1/C3/C5/C9). `hand-rolled-filter`, `control-size-literal` and
584
+ // `responsive-twin` all ship `error`; the two C1 placement rules are the grace entries in
585
+ // `PLUGIN_RULE_GRACE`, both promoting at 1.30.0 — `control-outside-home` re-dated against the
586
+ // wave-7 measurement, `bound-control-outside-home` new since 1.28.0 (ASIDE-SPEC G5: the basalt
587
+ // half of C1, where a bound control in a section body rendered as a stray pill). The budget
588
+ // rules live on `.` with `PageBar` itself.
559
589
  pluginRules: [
560
590
  'hand-rolled-filter',
561
591
  'control-outside-home',
592
+ 'bound-control-outside-home',
562
593
  'control-size-literal',
563
594
  'responsive-twin',
564
595
  ],
@@ -571,7 +602,7 @@ export const SURFACES = {
571
602
  'C12 — one shape for refresh/sync (SyncButton); only the alias table sees a renamed copy',
572
603
  ],
573
604
  description:
574
- 'The control tier (docs/CONTROLS-SPEC.md §3): FilterSet (nowrap row + measured +N fold + the mobile Filters (n) sheet), RangeFilter/CompareFilter/SelectFilter/MultiSelectFilter/SearchFilter/ToggleFilter (each bound to a FieldHandle — no value/onChange/size, law C2/C5), ViewTabs, and the action/sync family (ActionGroup, OverflowMenu, SyncButton, BarAction/GlobalAction). Every control owns its own desktop/mobile swap in CSS (C9) and renders size="ctl" internally. Resolves and renders with NO @mantine/dates installed — the custom date picker is injected through RangeFilter.customPicker from ./controls-dates.',
605
+ 'The control tier (docs/CONTROLS-SPEC.md §3): FilterSet (nowrap row + measured +N fold + the mobile Filters (n) sheet), RangeFilter/CompareFilter/SelectFilter/MultiSelectFilter/NumberFilter/SearchFilter/ToggleFilter (each bound to a FieldHandle — no value/onChange/size, law C2/C5; NumberFilter is the field.number lane, a radio list over `options` or a stepper without), ViewTabs, and the action/sync family (ActionGroup, OverflowMenu, SyncButton, BarAction/GlobalAction). THREE surfaces, picked by the home and never by a prop (useFilterSurface): pill in a PageBar row, sheet in the mobile Filters (n) drawer, panel in a PageAside body — where every control renders an inspector/facet ROW instead of a chip (docs/ASIDE-SPEC.md §3). PanelRow is that row primitive (label above, hint, mono readout, an `end` control on the label line) and SliderControl is the one bound control with no pill form at all; the counts/max props on MultiSelectFilter render the Foundry facet list there. Every control owns its own desktop/mobile swap in CSS (C9) and renders size="ctl" internally. Resolves and renders with NO @mantine/dates installed — the custom date picker is injected through RangeFilter.customPicker from ./controls-dates.',
575
606
  optionalPeers: [],
576
607
  forbiddenImports: [],
577
608
  },
@@ -599,10 +630,10 @@ export const SURFACES = {
599
630
  optionalPeers: [],
600
631
  // Consumers import basalt-ui/state from node_modules (lint-ignored), so there is nothing to
601
632
  // enforce consumer-side, and a shipped **/state* glob would wrongly hit consumers' own
602
- // Mantine-using state files. Enforce only basalt's own src/state.ts.
633
+ // Mantine-using state files. Enforce basalt's own barrel AND its implementation files.
603
634
  globs: {
604
635
  shipped: [],
605
- repo: ['packages/basalt-ui/src/state.ts'],
636
+ repo: ['packages/basalt-ui/src/state.ts', 'packages/basalt-ui/src/state/**'],
606
637
  },
607
638
  // @visx/* ban dropped — `basalt/visx-boundary` now bans it universally outside charts.
608
639
  forbiddenImports: [...MANTINE_BANS],
@@ -78,6 +78,16 @@ export const CTL_THEME: MantineThemeOverride = {
78
78
  },
79
79
  }
80
80
 
81
+ /**
82
+ * **`Slider` is deliberately NOT here, and `--slider-size-ctl` still is** (`theme/index.ts`). The
83
+ * tier's var set is what the size means, and `controls/slider-control.tsx` states `size="ctl"`
84
+ * itself the way every control on `./controls` does. Putting it in this map instead would widen
85
+ * `basalt/control-size-literal` — the rule is scoped to `CTL_THEME_TAGS`, ships at `error`, and a
86
+ * widened `error` rule lands its new form with no grace period at all (C16, `docs/CONTROLS-SPEC.md`
87
+ * §6). A `Slider` a consumer sizes by hand in a slot therefore keeps working; the one basalt draws
88
+ * is on the tier because it says so.
89
+ */
90
+
81
91
  /**
82
92
  * The `tier="widget"` slot theme — ActionIcon-ONLY, at the 24px `size="icon"` step
83
93
  * (`--ai-size-icon` → `--vx-space-control-height-widget`, `docs/CONTROLS-SPEC.md` §5).
@@ -19,6 +19,7 @@ import {
19
19
  Accordion,
20
20
  ActionIcon,
21
21
  Alert,
22
+ AppShell,
22
23
  Badge,
23
24
  Breadcrumbs,
24
25
  Button,
@@ -547,6 +548,24 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
547
548
  },
548
549
  },
549
550
  }),
551
+ // Region seams (docs/DESIGN-SPEC.md §5, §8 #12): the ONE lever for every AppShell edge —
552
+ // Mantine declares `--app-shell-border-color` on the shell element per scheme, which beats
553
+ // an inherited `:root` value, so a theme-level `vars` override (merged into the root's
554
+ // inline style) wins. Sections keep their default `withBorder: true`; the color is this.
555
+ // `styles` would also land on the same root style attribute, just through Mantine's own
556
+ // `[key: string]: any` index rather than a typed field.
557
+ // Cast: `AppShellCssVariables` declares only `--app-shell-transition-duration` /
558
+ // `-timing-function`, yet Mantine's OWN AppShell.css sets `--app-shell-border-color` on the
559
+ // same root.
560
+ AppShell: AppShell.extend({
561
+ vars: () =>
562
+ ({ root: { '--app-shell-border-color': 'var(--vx-divider)' } }) as unknown as {
563
+ root: Record<
564
+ '--app-shell-transition-duration' | '--app-shell-transition-timing-function',
565
+ string | undefined
566
+ >
567
+ },
568
+ }),
550
569
  // "Ink earns its color" — a nav selection is UI state, not the identity accent on the LABEL.
551
570
  // The active item is a SELECTED ROW, not a raised control: the same ink-tint idiom as the
552
571
  // hover state (one step stronger, ink-9%), no panel fill and no `shadow-card` — a raised,
@@ -733,13 +752,32 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
733
752
  classNames: (_theme, props) =>
734
753
  (props.variant ?? 'filled') === 'filled' ? { label: controlsClasses.chipLabel } : {},
735
754
  }),
736
- // Track = ink-6% tint, radius 7, 2px padding; active segment = panel bg + `shadow-ctrl`,
737
- // radius 5. `--sc-radius`/`--sc-color` don't reach the root track background (Mantine
738
- // hardcodes that to a raw gray step), so it's forced via `styles.root` same as Card/Paper.
739
- // The active-only ink label color + weight can't live in the flat `styles.label` object
740
- // (applies to every option regardless of state), so it's in segmented-control.module.css
755
+ // Track = ink-6% tint, radius 7, 2px padding; active segment = an ink-mixed panel fill +
756
+ // `shadow-ctrl`, radius 5. `--sc-radius`/`--sc-color` don't reach the root track background
757
+ // (Mantine hardcodes that to a raw gray step), so it's forced via `styles.root` same as
758
+ // Card/Paper. The active-only ink label color + weight can't live in the flat `styles.label`
759
+ // object (applies to every option regardless of state), so it's in segmented-control.module.css
741
760
  // instead — same pattern as NavLink's active-icon accent.
742
761
  //
762
+ // The indicator's fill is `color-mix(in srgb, var(--vx-ink) 12%, var(--vx-surface-panel))`,
763
+ // not a flat `--vx-surface-panel` — a flat panel fill is indistinguishable from the track's
764
+ // OWN parent on the one surface that IS `--vx-surface-panel` (the aside's `panel` filter
765
+ // surface, `docs/CONTROLS-SPEC.md` §3): the track (ink-6% over panel) and the indicator (panel,
766
+ // flat) then differ by 6% ink with no other cue, and `shadow-ctrl` alone (a bare
767
+ // `0 1px 2px` drop, no ring) reads as "barely there". This is NOT the `raised`-token doctrine
768
+ // in `tokens/palette.ts` (`SHADOW.raised`'s "a default control nested in a Card has no boundary
769
+ // but the drop — raise the drop, do not reintroduce an edge") — that doctrine is scoped to the
770
+ // shared Button/ActionIcon/Input depth token, whose fill is a real surface color a border would
771
+ // outline. The indicator's own fill has no such constraint, so a second ink-mix step (12%, double
772
+ // the track's) is the fix: it holds up on every surface the control mounts on, not only the
773
+ // panel-nested one.
774
+ //
775
+ // `.control`'s `min-width: 0` (`segmented-control.module.css`) is the other half of an even
776
+ // `fullWidth` split — Mantine's own `.control` ships `flex: 1` with no `min-width` override, so
777
+ // the initial `auto` floors every option at its min-content width and a `fullWidth` track splits
778
+ // UNEVENLY. The label already carries `overflow: hidden` + `text-overflow: ellipsis`, so a
779
+ // label that no longer fits its equal share truncates instead of forcing the column wide.
780
+ //
743
781
  // The track's padding is `SPACE_FIXED.segmentedTrackInset`, a plain literal — NOT a
744
782
  // `--vx-space-*` var — because it is density-EXEMPT: it is load-bearing for the nested-corner
745
783
  // law (`RADIUS.card === RADIUS_STEP.tight + segmentedTrackInset`, see that constant's doc in
@@ -748,7 +786,10 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
748
786
  // density.
749
787
  SegmentedControl: SegmentedControl.extend({
750
788
  defaultProps: { radius: radius.card },
751
- classNames: { label: segmentedControlClasses.label },
789
+ classNames: {
790
+ label: segmentedControlClasses.label,
791
+ control: segmentedControlClasses.control,
792
+ },
752
793
  // `label` gets a `ctl`-only min-height (function-form `styles`, same `props.size === …` gate
753
794
  // as Button/ActionIcon/Input's `vars` overrides above) so a `size="ctl"` SegmentedControl
754
795
  // matches the ctl Button/Input box exactly instead of following its own fixed padding — see
@@ -758,21 +799,57 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
758
799
  root: {
759
800
  backgroundColor: 'color-mix(in srgb, var(--vx-ink) 6%, transparent)',
760
801
  padding: `${SPACE_FIXED.segmentedTrackInset}px`,
802
+ // The OUTER safety net a `.control`'s own `min-width: 0` (`segmented-control.module.css`)
803
+ // cannot provide by itself: that rule only lets each SEGMENT shrink below its own label's
804
+ // content width so `fullWidth` can split evenly — it does nothing to stop the WHOLE TRACK
805
+ // from being squeezed by an ANCESTOR flex row with room to spare (a `Section`/`StatCard`
806
+ // header's `actions` slot), which silently clipped "Absolute" to "Absolut" with no
807
+ // ellipsis at all. `min-width: max-content` pins the root to the sum of its labels'
808
+ // natural widths — it now OVERFLOWS a too-narrow ancestor instead of shrinking into it,
809
+ // which is also what makes the overflow MEASURABLE (`panel-row.tsx`'s `useTrackFits`
810
+ // compares the root's rendered width against its parent's available space). Inside that
811
+ // floor, `fullWidth` with room to spare still splits its segments evenly exactly as
812
+ // before — the floor only ever raises the STARTING point flex-grow distributes surplus
813
+ // from, never removes the segments' own equal-share arithmetic.
814
+ minWidth: 'max-content',
761
815
  },
762
816
  indicator: {
763
- backgroundColor: 'var(--vx-surface-panel)',
817
+ backgroundColor: 'color-mix(in srgb, var(--vx-ink) 12%, var(--vx-surface-panel))',
764
818
  boxShadow: 'var(--vx-shadow-ctrl)',
765
819
  borderRadius: 'var(--vx-radius-tight)',
766
820
  },
767
821
  // Conditionally spread the WHOLE key (never a present `label: undefined`) — the package
768
822
  // builds under `exactOptionalPropertyTypes`, which treats a key present-but-`undefined` as
769
823
  // a type error distinct from the key being absent.
824
+ //
825
+ // `width: '100%'` + `minWidth: 0` are load-bearing, not cosmetic: `inline-flex` is a
826
+ // shrink-to-fit box by default (like `inline-block`), so switching `.label` to it for
827
+ // vertical centering ALSO switched its width from "fills `.control`'s box" (a plain
828
+ // `display: block`'s default) to "sized to its own content" — which is invisible until
829
+ // `fullWidth` forces every `.control` to an EQUAL share (`segmented-control.module.css`'s
830
+ // `min-width: 0`): a label wider than that equal share then rendered at its own full
831
+ // content width, overflowing its column and getting hard-clipped by the track's own
832
+ // `overflow: hidden` instead of ellipsizing inside it ("Same period last year" cut off
833
+ // mid-word). `width: 100%` makes the inline-flex box fill `.control` again, and `minWidth:
834
+ // 0` is the same flex-item footgun `.control` itself needed — `.label` is ALSO a flex
835
+ // container's item once `fullWidth`'s `.root { display: flex }` applies, so it inherits an
836
+ // `auto` (content-based) minimum unless told otherwise.
770
837
  ...(props.size === 'ctl'
771
838
  ? {
772
839
  label: {
773
840
  display: 'inline-flex',
774
841
  alignItems: 'center',
775
842
  minHeight: `calc(var(--vx-space-control-height-ctl) * var(--mantine-scale) - ${2 * SPACE_FIXED.segmentedTrackInset}px)`,
843
+ // `width: '100%'` only when `fullWidth` — it is what makes an EQUAL-SPLIT
844
+ // segment's label fill its column instead of shrink-to-fit around its own text
845
+ // (the "Same period last year" clipped-with-no-ellipsis case). A NON-`fullWidth`
846
+ // track (a header's `actions` slot, two or three options) wants the opposite: its
847
+ // label sized to its OWN content, so the root's `min-width: max-content` (below)
848
+ // measures the label's true natural width rather than an equal 1/2 or 1/3 share
849
+ // computed through `.control`'s `flex-basis: 0%` — forcing `width: 100%` there
850
+ // too under-computed the shrink-to-fit root by a few px ("Absolute" clipped to
851
+ // "Absolut" even with the floor in place).
852
+ ...(props.fullWidth === true ? { width: '100%', minWidth: 0 } : {}),
776
853
  },
777
854
  }
778
855
  : {}),
@@ -896,9 +973,13 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
896
973
  },
897
974
  },
898
975
  }),
899
- // Modal/Drawer: overlay surface + overlay shadow on the content. The header goes transparent —
900
- // Mantine paints it `--mantine-color-body`, which read as a grey band over the overlay
901
- // surface. Title = head font; close button = the ghost idiom (floating.module.css).
976
+ // Modal/Drawer: overlay surface + overlay shadow on the content, the SAME surface on the
977
+ // header. Mantine's header is `position: sticky` by default, painted `--mantine-color-body` —
978
+ // basalt used to drop that to `transparent`, which reads fine over a body that never scrolls
979
+ // under it but shows every scrolled row straight through the title once one does (the mobile
980
+ // filter sheet, the shell's "More" nav sheet). The header stays sticky; only its own
981
+ // background moves back to opaque, matching the content box it sits above rather than the page
982
+ // behind it. Title = head font; close button = the ghost idiom (floating.module.css).
902
983
  Modal: Modal.extend({
903
984
  defaultProps: { radius: radius.floating },
904
985
  classNames: { close: floatingClasses.closeButton },
@@ -907,7 +988,7 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
907
988
  backgroundColor: 'var(--vx-surface-overlay)',
908
989
  boxShadow: 'var(--vx-shadow-overlay)',
909
990
  },
910
- header: { backgroundColor: 'transparent' },
991
+ header: { backgroundColor: 'var(--vx-surface-overlay)' },
911
992
  title: {
912
993
  fontFamily: 'var(--basalt-font-head)',
913
994
  fontWeight: 550,
@@ -922,7 +1003,7 @@ function buildTheme(data: PaletteData, options: BuildThemeOptions = {}): Mantine
922
1003
  backgroundColor: 'var(--vx-surface-overlay)',
923
1004
  boxShadow: 'var(--vx-shadow-overlay)',
924
1005
  },
925
- header: { backgroundColor: 'transparent' },
1006
+ header: { backgroundColor: 'var(--vx-surface-overlay)' },
926
1007
  title: {
927
1008
  fontFamily: 'var(--basalt-font-head)',
928
1009
  fontWeight: 550,
@@ -1153,13 +1234,30 @@ const CTL_INPUT_PADDING_Y = 4
1153
1234
  const CTL_SEGMENT_PADDING_Y = 2.5
1154
1235
  /** A `ctl` Combobox chevron. Mantine's own `xs` value; restated because it cannot be referenced. */
1155
1236
  const CTL_CHEVRON_SIZE = 14
1237
+ /**
1238
+ * The `ctl` NumberInput's stepper column, in px — Mantine's own `xs` pair (`--ni-chevron-size-xs`,
1239
+ * `--ni-right-section-width-xs`; `NumberInput.css`), restated for the same reason `CTL_CHEVRON_SIZE`
1240
+ * is: `xs` is Mantine's own `--input-height-xs: 30px`, the ONE built-in size tier that already equals
1241
+ * the `ctl` height, so its stepper column is the size a 30px NumberInput was always meant to carry.
1242
+ * Both vars are load-bearing, not cosmetic — `NumberInput.mjs`'s `varsResolver` sets
1243
+ * `--ni-chevron-size` via `getSize(size, 'ni-chevron-size')` (undeclared at `:root` for a custom
1244
+ * size, so a `size="ctl"` NumberInput fell back to the property's initial value, and
1245
+ * `.controls { max-width: calc(var(--ni-chevron-size) * 1.7) }` — `NumberInput.css:21` — resolved to
1246
+ * an invalid `calc()` and dropped its `max-width` entirely, so the stacked chevrons stretched across
1247
+ * the whole right section), and `rightSectionWidth` defaults to a raw
1248
+ * `` `var(--ni-right-section-width-${size})` `` template (`NumberInput.mjs:412`) rather than a
1249
+ * `getSize` call, so `ctl-tier-coverage.test.ts`'s scan cannot discover it — it is declared here
1250
+ * because the CSS reads it, not because a scan requires it.
1251
+ */
1252
+ const CTL_NUMBER_CHEVRON_SIZE = 10
1253
+ const CTL_NUMBER_RIGHT_SECTION_WIDTH = 17
1156
1254
  /**
1157
1255
  * The `ctl` tier's Radio/Checkbox indicator box, in px — 16, the SAME square
1158
1256
  * `theme/icon-slot.module.css` gives every icon in the tier, and for the same reason: a 13.5px
1159
1257
  * option label needs a mark it reads as part of the row rather than as a control beside it. Mantine's
1160
1258
  * default is `sm` (20px) and its `md` is 24px, both of which made the popover a column of controls
1161
- * (`controls/filter-sheet.tsx`'s `SheetOptionList` doc records the sheet's version of the same
1162
- * finding — there the fix was to remove the indicator entirely).
1259
+ * (the sheet/panel forms found the same thing and went further — `docs/CONTROLS-SPEC.md` §3's
1260
+ * `PanelChoice`/facet rows draw no Radio/Checkbox indicator at all, a hidden native input instead).
1163
1261
  */
1164
1262
  const CTL_TOGGLE_SIZE = 16
1165
1263
  /**
@@ -1183,6 +1281,14 @@ const CTL_SWITCH_THUMB_SIZE = 12
1183
1281
  * the last tier whose label still fits an 18px track. */
1184
1282
  const CTL_SWITCH_TRACK_LABEL_SIZE = 5
1185
1283
  const CTL_SWITCH_TRACK_LABEL_PADDING = 2
1284
+ /**
1285
+ * The `ctl` Slider's TRACK height, in px. The thumb is not a second number: Mantine derives it as
1286
+ * `calc(var(--slider-size) * 2)` (`Slider.mjs`'s `varsResolver`), so 6 lands a 12px thumb — the same
1287
+ * moving part the `ctl` Switch carries, which is what makes a row of inspector rows read as one
1288
+ * family. Mantine's own `md` (8 → a 16px thumb) is the tier's whole icon box, and its `xs`
1289
+ * (4 → 8px) is smaller than the tier's radio dot.
1290
+ */
1291
+ const CTL_SLIDER_TRACK_SIZE = 6
1186
1292
 
1187
1293
  /**
1188
1294
  * The `size="ctl"` / `size="icon"` Mantine size-tier var sets (`docs/CONTROLS-SPEC.md` §5, C5) —
@@ -1241,6 +1347,8 @@ function ctlSizeVars(): Record<string, string> {
1241
1347
  '--sc-padding-ctl': `${pxRem(CTL_SEGMENT_PADDING_Y)} calc(${pxRem(CTL_PADDING_X)} * var(--mantine-scale))`,
1242
1348
  '--combobox-option-padding-ctl': `${pxRem(CTL_SEGMENT_PADDING_Y)} ${pxRem(CTL_PADDING_X)}`,
1243
1349
  '--combobox-chevron-size-ctl': pxRem(CTL_CHEVRON_SIZE),
1350
+ '--ni-chevron-size-ctl': pxRem(CTL_NUMBER_CHEVRON_SIZE),
1351
+ '--ni-right-section-width-ctl': `calc(${pxRem(CTL_NUMBER_RIGHT_SECTION_WIDTH)} * var(--mantine-scale))`,
1244
1352
  '--badge-height-ctl': ctlHeight,
1245
1353
  '--badge-padding-x-ctl': `calc(${pxRem(CTL_PADDING_X)} * var(--mantine-scale))`,
1246
1354
  '--badge-fz-ctl': `calc(${pxRem(VX.text.xs)} * var(--mantine-scale))`,
@@ -1262,6 +1370,10 @@ function ctlSizeVars(): Record<string, string> {
1262
1370
  '--switch-thumb-size-ctl': `calc(${pxRem(CTL_SWITCH_THUMB_SIZE)} * var(--mantine-scale))`,
1263
1371
  '--switch-label-font-size-ctl': pxRem(CTL_SWITCH_TRACK_LABEL_SIZE),
1264
1372
  '--switch-track-label-padding-ctl': pxRem(CTL_SWITCH_TRACK_LABEL_PADDING),
1373
+ // Slider — the inspector row's control (`SliderControl`, `docs/ASIDE-SPEC.md` §1). One prefix
1374
+ // only: `slider-size` is the track, and every other dimension (the thumb, the root's inline
1375
+ // padding, the vertical hit box) is derived from it in `Slider.css`.
1376
+ '--slider-size-ctl': `calc(${pxRem(CTL_SLIDER_TRACK_SIZE)} * var(--mantine-scale))`,
1265
1377
  }
1266
1378
  }
1267
1379
 
@@ -1303,7 +1415,8 @@ function buildCssVariablesResolver(data: PaletteData): CSSVariablesResolver {
1303
1415
  '--mantine-color-default-border': 'transparent',
1304
1416
  '--mantine-color-dimmed': `var(--vx-neutral, ${NEUTRAL.neutral.light})`, // secondary / muted text
1305
1417
  '--mantine-color-text': `var(--vx-ink, ${INK.ink.light})`, // primary body/heading text
1306
- '--app-shell-border-color': `var(--vx-surface-border, ${SURFACE.border.light})`,
1418
+ // `--app-shell-border-color` is set by `components.AppShell.extend({ vars })` above — this
1419
+ // entry was dead (an element-level declaration always beats an inherited `:root` value).
1307
1420
  // THE strict-surface lever. Mantine components do NOT chain border/surface colors through
1308
1421
  // `--mantine-color-default-*`; each hardcodes a RAW ramp step (`--mantine-color-gray-{2,3,4}`
1309
1422
  // on light) directly — which is why AppShell/Table/Input/Divider/Tabs/Popover/Accordion borders
@@ -1330,7 +1443,7 @@ function buildCssVariablesResolver(data: PaletteData): CSSVariablesResolver {
1330
1443
  '--mantine-color-default-border': 'transparent',
1331
1444
  '--mantine-color-dimmed': `var(--vx-neutral, ${NEUTRAL.neutral.dark})`,
1332
1445
  '--mantine-color-text': `var(--vx-ink, ${INK.ink.dark})`,
1333
- '--app-shell-border-color': `var(--vx-surface-border, ${SURFACE.border.dark})`,
1446
+ // See the light block above — `--app-shell-border-color` is set by `AppShell.extend` now.
1334
1447
  // Dark components read `--mantine-color-dark-4` (border) raw. `buildDarkTuple` already sets
1335
1448
  // dark-4, but to a slightly lighter step than the hairline token, so layout borders read
1336
1449
  // marginally heavier than card borders. Pin dark-4 to the SAME "line" token for parity.