basalt-ui 1.30.2 → 1.32.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 (357) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +54 -0
  3. package/MIGRATING.md +256 -12
  4. package/agent/rules/basalt-controls.md +19 -19
  5. package/agent/rules/basalt-mantine.md +5 -5
  6. package/configs/oxlint-plugin.js +371 -4
  7. package/configs/oxlint-plugin.test.ts +327 -2
  8. package/configs/oxlint.json +2 -1
  9. package/dist/agent-chat/composer.d.ts.map +1 -1
  10. package/dist/agent-chat/composer.js +41 -43
  11. package/dist/agent-chat/thread-workspace.d.ts +2 -2
  12. package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
  13. package/dist/agent-chat/thread-workspace.js +3 -4
  14. package/dist/agent-chat/use-keyboard-inset.d.ts +2 -0
  15. package/dist/agent-chat/use-keyboard-inset.d.ts.map +1 -0
  16. package/dist/agent-chat/use-keyboard-inset.js +34 -0
  17. package/dist/charts/cursor/touch-pin.d.ts +45 -0
  18. package/dist/charts/cursor/touch-pin.d.ts.map +1 -0
  19. package/dist/charts/cursor/touch-pin.js +79 -0
  20. package/dist/charts/hooks/use-discrete-cursor.d.ts +66 -0
  21. package/dist/charts/hooks/use-discrete-cursor.d.ts.map +1 -0
  22. package/dist/charts/hooks/use-discrete-cursor.js +198 -0
  23. package/dist/charts/hooks/use-hysteresis.d.ts +18 -0
  24. package/dist/charts/hooks/use-hysteresis.d.ts.map +1 -0
  25. package/dist/charts/hooks/use-hysteresis.js +12 -0
  26. package/dist/charts/hooks/useBandPlot.d.ts +7 -0
  27. package/dist/charts/hooks/useBandPlot.d.ts.map +1 -1
  28. package/dist/charts/hooks/useBandPlot.js +62 -18
  29. package/dist/charts/hooks/useChartCursor.d.ts +40 -11
  30. package/dist/charts/hooks/useChartCursor.d.ts.map +1 -1
  31. package/dist/charts/hooks/useChartCursor.js +102 -11
  32. package/dist/charts/index.d.ts +0 -1
  33. package/dist/charts/index.d.ts.map +1 -1
  34. package/dist/charts/index.js +0 -10
  35. package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
  36. package/dist/charts/kinds/BandStrip.js +47 -82
  37. package/dist/charts/kinds/Donut.d.ts +9 -3
  38. package/dist/charts/kinds/Donut.d.ts.map +1 -1
  39. package/dist/charts/kinds/Donut.js +110 -48
  40. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  41. package/dist/charts/kinds/DualPanel.js +138 -145
  42. package/dist/charts/kinds/Heatmap.d.ts +7 -0
  43. package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
  44. package/dist/charts/kinds/Heatmap.js +37 -16
  45. package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
  46. package/dist/charts/kinds/MirroredBars.js +68 -111
  47. package/dist/charts/kinds/band-chrome.d.ts +31 -0
  48. package/dist/charts/kinds/band-chrome.d.ts.map +1 -0
  49. package/dist/charts/kinds/band-chrome.js +71 -0
  50. package/dist/charts/kinds/donut-layout.d.ts +47 -0
  51. package/dist/charts/kinds/donut-layout.d.ts.map +1 -0
  52. package/dist/charts/kinds/donut-layout.js +52 -0
  53. package/dist/charts/layout/auto-margin.d.ts +7 -2
  54. package/dist/charts/layout/auto-margin.d.ts.map +1 -1
  55. package/dist/charts/layout/auto-margin.js +12 -3
  56. package/dist/charts/layout/end-labels.d.ts +64 -0
  57. package/dist/charts/layout/end-labels.d.ts.map +1 -0
  58. package/dist/charts/layout/end-labels.js +76 -0
  59. package/dist/charts/primitives/Axes.d.ts +32 -4
  60. package/dist/charts/primitives/Axes.d.ts.map +1 -1
  61. package/dist/charts/primitives/Axes.js +62 -16
  62. package/dist/charts/primitives/CartesianChart.d.ts +7 -6
  63. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  64. package/dist/charts/primitives/CartesianChart.js +264 -145
  65. package/dist/charts/primitives/ChartCard.d.ts +0 -14
  66. package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
  67. package/dist/charts/primitives/ChartCard.js +56 -21
  68. package/dist/charts/primitives/ChartFrame.d.ts +28 -22
  69. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  70. package/dist/charts/primitives/ChartFrame.js +116 -34
  71. package/dist/charts/primitives/ChartLegend.d.ts +19 -15
  72. package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
  73. package/dist/charts/primitives/ChartLegend.js +86 -73
  74. package/dist/charts/primitives/ChartTooltip.d.ts +5 -0
  75. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  76. package/dist/charts/primitives/ChartTooltip.js +20 -4
  77. package/dist/charts/primitives/Crosshair.js +2 -2
  78. package/dist/charts/primitives/HoverOverlay.d.ts +29 -9
  79. package/dist/charts/primitives/HoverOverlay.d.ts.map +1 -1
  80. package/dist/charts/primitives/HoverOverlay.js +54 -27
  81. package/dist/charts/primitives/HoverOverlay.module.css +13 -0
  82. package/dist/charts/primitives/HoverOverlay.module.css.d.ts +8 -0
  83. package/dist/charts/primitives/chart-card-context.d.ts +33 -0
  84. package/dist/charts/primitives/chart-card-context.d.ts.map +1 -0
  85. package/dist/charts/primitives/chart-card-context.js +18 -0
  86. package/dist/charts/primitives/chart-frame-layout.d.ts +93 -113
  87. package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -1
  88. package/dist/charts/primitives/chart-frame-layout.js +75 -34
  89. package/dist/charts/primitives/chart-layout.d.ts +112 -0
  90. package/dist/charts/primitives/chart-layout.d.ts.map +1 -0
  91. package/dist/charts/primitives/chart-layout.js +175 -0
  92. package/dist/charts/primitives/chart-tier.d.ts +13 -11
  93. package/dist/charts/primitives/chart-tier.d.ts.map +1 -1
  94. package/dist/charts/primitives/chart-tier.js +42 -13
  95. package/dist/charts/primitives/legend-disclosure.d.ts +27 -0
  96. package/dist/charts/primitives/legend-disclosure.d.ts.map +1 -0
  97. package/dist/charts/primitives/legend-disclosure.js +153 -0
  98. package/dist/charts/series.d.ts +4 -1
  99. package/dist/charts/series.d.ts.map +1 -1
  100. package/dist/charts/utils/ticks.d.ts +27 -8
  101. package/dist/charts/utils/ticks.d.ts.map +1 -1
  102. package/dist/charts/utils/ticks.js +35 -11
  103. package/dist/common/errors.d.ts +11 -1
  104. package/dist/common/errors.d.ts.map +1 -1
  105. package/dist/common/errors.js +16 -2
  106. package/dist/common/hit-floor.d.ts +10 -0
  107. package/dist/common/hit-floor.d.ts.map +1 -0
  108. package/dist/common/hit-floor.js +6 -0
  109. package/dist/{shell → common}/isomorphic-layout-effect.d.ts +4 -3
  110. package/dist/common/isomorphic-layout-effect.d.ts.map +1 -0
  111. package/dist/common/use-measured-widths.d.ts +37 -0
  112. package/dist/common/use-measured-widths.d.ts.map +1 -0
  113. package/dist/common/use-measured-widths.js +51 -0
  114. package/dist/common/use-media-query.d.ts +6 -0
  115. package/dist/common/use-media-query.d.ts.map +1 -0
  116. package/dist/common/use-media-query.js +40 -0
  117. package/dist/common/validate.d.ts +9 -0
  118. package/dist/common/validate.d.ts.map +1 -1
  119. package/dist/common/validate.js +9 -4
  120. package/dist/content/article-layout.d.ts +4 -2
  121. package/dist/content/article-layout.d.ts.map +1 -1
  122. package/dist/content/article-layout.js +43 -3
  123. package/dist/content/article-layout.module.css +45 -4
  124. package/dist/content/article-layout.module.css.d.ts +3 -0
  125. package/dist/content/code-block.d.ts.map +1 -1
  126. package/dist/content/code-block.js +40 -2
  127. package/dist/content/code-block.module.css +32 -2
  128. package/dist/content/prose.module.css +13 -8
  129. package/dist/controls/actions.d.ts +29 -6
  130. package/dist/controls/actions.d.ts.map +1 -1
  131. package/dist/controls/actions.js +158 -27
  132. package/dist/controls/actions.module.css +14 -1
  133. package/dist/controls/actions.module.css.d.ts +1 -0
  134. package/dist/controls/controls.module.css +13 -31
  135. package/dist/controls/enum-filter.js +2 -2
  136. package/dist/controls/filter-context.d.ts +10 -0
  137. package/dist/controls/filter-context.d.ts.map +1 -1
  138. package/dist/controls/filter-context.js +2 -0
  139. package/dist/controls/filter-pill.d.ts.map +1 -1
  140. package/dist/controls/filter-pill.js +1 -0
  141. package/dist/controls/index.d.ts +1 -1
  142. package/dist/controls/index.d.ts.map +1 -1
  143. package/dist/controls/index.js +0 -2
  144. package/dist/controls/multi-select-filter.js +2 -2
  145. package/dist/controls/sync-button.module.css +2 -1
  146. package/dist/dashboard/section.d.ts.map +1 -1
  147. package/dist/dashboard/section.js +1 -0
  148. package/dist/dashboard/section.module.css +1 -26
  149. package/dist/dashboard/stat-card.d.ts +1 -1
  150. package/dist/dashboard/stat-card.d.ts.map +1 -1
  151. package/dist/dashboard/stat-card.js +4 -1
  152. package/dist/dashboard/stat-card.module.css +6 -9
  153. package/dist/dashboard/stat-group.module.css +33 -66
  154. package/dist/dashboard/widget-grid.d.ts.map +1 -1
  155. package/dist/dashboard/widget-grid.module.css +11 -38
  156. package/dist/dashboard/widget-header.d.ts +14 -4
  157. package/dist/dashboard/widget-header.d.ts.map +1 -1
  158. package/dist/dashboard/widget-header.js +23 -6
  159. package/dist/dashboard/widget-header.module.css +145 -133
  160. package/dist/dashboard/widget-header.module.css.d.ts +2 -0
  161. package/dist/data/data-table-state.d.ts +83 -0
  162. package/dist/data/data-table-state.d.ts.map +1 -0
  163. package/dist/data/data-table-state.js +139 -0
  164. package/dist/data/data-table.d.ts +56 -2
  165. package/dist/data/data-table.d.ts.map +1 -1
  166. package/dist/data/data-table.js +436 -336
  167. package/dist/data/data-table.module.css +94 -0
  168. package/dist/data/data-table.module.css.d.ts +11 -0
  169. package/dist/data/virtual-list.d.ts.map +1 -1
  170. package/dist/data/virtual-list.js +10 -0
  171. package/dist/forms/form-layout.d.ts.map +1 -1
  172. package/dist/forms/form-layout.js +3 -3
  173. package/dist/forms/form-layout.module.css +20 -5
  174. package/dist/forms/form-layout.module.css.d.ts +1 -0
  175. package/dist/guard/index.d.ts +8 -2
  176. package/dist/guard/index.d.ts.map +1 -1
  177. package/dist/guard/index.js +68 -2
  178. package/dist/guard/types.d.ts +3 -3
  179. package/dist/guard/types.d.ts.map +1 -1
  180. package/dist/index.d.ts +1 -1
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +3 -1
  183. package/dist/notifications/center.d.ts.map +1 -1
  184. package/dist/provider/index.d.ts +20 -1
  185. package/dist/provider/index.d.ts.map +1 -1
  186. package/dist/provider/index.js +30 -8
  187. package/dist/shell/app-brand.d.ts.map +1 -1
  188. package/dist/shell/app-brand.js +1 -0
  189. package/dist/shell/app-brand.module.css +2 -2
  190. package/dist/shell/app-header.module.css +18 -8
  191. package/dist/shell/app-main.module.css +54 -3
  192. package/dist/shell/app-main.module.css.d.ts +1 -0
  193. package/dist/shell/app-mobile-nav.module.css +16 -4
  194. package/dist/shell/app-sidebar.module.css +4 -6
  195. package/dist/shell/aside-docking.d.ts +31 -0
  196. package/dist/shell/aside-docking.d.ts.map +1 -0
  197. package/dist/shell/aside-docking.js +19 -0
  198. package/dist/shell/index.d.ts +1 -0
  199. package/dist/shell/index.d.ts.map +1 -1
  200. package/dist/shell/index.js +56 -16
  201. package/dist/shell/mobile-nav-model.d.ts +1 -1
  202. package/dist/shell/page-aside.d.ts +22 -3
  203. package/dist/shell/page-aside.d.ts.map +1 -1
  204. package/dist/shell/page-aside.js +27 -13
  205. package/dist/shell/page-bar.d.ts.map +1 -1
  206. package/dist/shell/page-bar.js +10 -5
  207. package/dist/shell/page-bar.module.css +10 -34
  208. package/dist/shell/use-breakpoint.d.ts +3 -4
  209. package/dist/shell/use-breakpoint.d.ts.map +1 -1
  210. package/dist/shell/use-breakpoint.js +3 -25
  211. package/dist/shell/use-size-class.d.ts +6 -0
  212. package/dist/shell/use-size-class.d.ts.map +1 -0
  213. package/dist/shell/use-size-class.js +19 -0
  214. package/dist/state/persisted-or-local.d.ts +4 -1
  215. package/dist/state/persisted-or-local.d.ts.map +1 -1
  216. package/dist/state/persisted-or-local.js +4 -3
  217. package/dist/state/persisted.d.ts +10 -0
  218. package/dist/state/persisted.d.ts.map +1 -1
  219. package/dist/state/persisted.js +44 -14
  220. package/dist/styles.css +41 -0
  221. package/dist/surfaces.d.ts +4 -4
  222. package/dist/surfaces.d.ts.map +1 -1
  223. package/dist/surfaces.js +11 -3
  224. package/dist/theme/controls.module.css +7 -0
  225. package/dist/theme/ctl-theme.d.ts +1 -0
  226. package/dist/theme/ctl-theme.d.ts.map +1 -1
  227. package/dist/theme/ctl-theme.js +12 -4
  228. package/dist/theme/floating.module.css +37 -0
  229. package/dist/theme/floating.module.css.d.ts +3 -0
  230. package/dist/theme/index.d.ts +2 -2
  231. package/dist/theme/index.d.ts.map +1 -1
  232. package/dist/theme/index.js +34 -5
  233. package/dist/theme/nav-link.module.css +7 -0
  234. package/dist/theme-lab/derive-controls.d.ts.map +1 -1
  235. package/dist/tokens/index.d.ts +7 -16
  236. package/dist/tokens/index.d.ts.map +1 -1
  237. package/dist/tokens/index.js +23 -28
  238. package/dist/tokens/palette.d.ts +5 -27
  239. package/dist/tokens/palette.d.ts.map +1 -1
  240. package/dist/tokens/palette.js +8 -30
  241. package/dist/tokens/size-classes.d.ts +40 -0
  242. package/dist/tokens/size-classes.d.ts.map +1 -0
  243. package/dist/tokens/size-classes.js +29 -0
  244. package/dist/tokens.css +8 -4
  245. package/llms.txt +3 -3
  246. package/package.json +18 -17
  247. package/src/agent-chat/composer.tsx +74 -47
  248. package/src/agent-chat/thread-workspace.tsx +8 -11
  249. package/src/agent-chat/use-keyboard-inset.ts +68 -0
  250. package/src/charts/cursor/touch-pin.ts +138 -0
  251. package/src/charts/hooks/use-discrete-cursor.ts +335 -0
  252. package/src/charts/hooks/use-hysteresis.ts +26 -0
  253. package/src/charts/hooks/useBandPlot.ts +90 -27
  254. package/src/charts/hooks/useChartCursor.ts +211 -26
  255. package/src/charts/index.ts +0 -8
  256. package/src/charts/kinds/BandStrip.tsx +25 -61
  257. package/src/charts/kinds/Donut.tsx +153 -62
  258. package/src/charts/kinds/DualPanel.tsx +21 -26
  259. package/src/charts/kinds/Heatmap.tsx +61 -22
  260. package/src/charts/kinds/MirroredBars.tsx +23 -65
  261. package/src/charts/kinds/band-chrome.tsx +91 -0
  262. package/src/charts/kinds/donut-layout.ts +82 -0
  263. package/src/charts/layout/auto-margin.ts +24 -5
  264. package/src/charts/layout/end-labels.ts +135 -0
  265. package/src/charts/primitives/Axes.tsx +112 -21
  266. package/src/charts/primitives/CartesianChart.tsx +282 -111
  267. package/src/charts/primitives/ChartCard.tsx +119 -48
  268. package/src/charts/primitives/ChartFrame.tsx +204 -60
  269. package/src/charts/primitives/ChartLegend.tsx +115 -78
  270. package/src/charts/primitives/ChartTooltip.tsx +24 -3
  271. package/src/charts/primitives/Crosshair.tsx +2 -2
  272. package/src/charts/primitives/HoverOverlay.module.css +13 -0
  273. package/src/charts/primitives/HoverOverlay.module.css.d.ts +8 -0
  274. package/src/charts/primitives/HoverOverlay.tsx +62 -20
  275. package/src/charts/primitives/chart-card-context.ts +46 -0
  276. package/src/charts/primitives/chart-frame-layout.ts +207 -182
  277. package/src/charts/primitives/chart-layout.ts +318 -0
  278. package/src/charts/primitives/chart-tier.tsx +66 -21
  279. package/src/charts/primitives/legend-disclosure.tsx +177 -0
  280. package/src/charts/series.ts +4 -1
  281. package/src/charts/utils/ticks.ts +95 -19
  282. package/src/common/errors.ts +25 -1
  283. package/src/common/hit-floor.ts +9 -0
  284. package/src/{shell → common}/isomorphic-layout-effect.ts +4 -3
  285. package/src/common/use-measured-widths.ts +88 -0
  286. package/src/common/use-media-query.ts +56 -0
  287. package/src/common/validate.ts +17 -4
  288. package/src/content/article-layout.module.css +45 -4
  289. package/src/content/article-layout.module.css.d.ts +3 -0
  290. package/src/content/article-layout.tsx +60 -5
  291. package/src/content/code-block.module.css +32 -2
  292. package/src/content/code-block.tsx +47 -3
  293. package/src/content/prose.module.css +13 -8
  294. package/src/controls/actions.module.css +14 -1
  295. package/src/controls/actions.module.css.d.ts +1 -0
  296. package/src/controls/actions.tsx +223 -75
  297. package/src/controls/controls.module.css +13 -31
  298. package/src/controls/enum-filter.tsx +2 -2
  299. package/src/controls/filter-context.tsx +11 -0
  300. package/src/controls/filter-pill.tsx +1 -0
  301. package/src/controls/index.ts +0 -1
  302. package/src/controls/multi-select-filter.tsx +2 -2
  303. package/src/controls/sync-button.module.css +2 -1
  304. package/src/dashboard/section.module.css +1 -26
  305. package/src/dashboard/section.tsx +1 -0
  306. package/src/dashboard/stat-card.module.css +6 -9
  307. package/src/dashboard/stat-card.tsx +6 -3
  308. package/src/dashboard/stat-group.module.css +33 -66
  309. package/src/dashboard/widget-grid.module.css +11 -38
  310. package/src/dashboard/widget-grid.tsx +7 -6
  311. package/src/dashboard/widget-header.module.css +145 -133
  312. package/src/dashboard/widget-header.module.css.d.ts +2 -0
  313. package/src/dashboard/widget-header.tsx +45 -11
  314. package/src/data/data-table-state.ts +218 -0
  315. package/src/data/data-table.module.css +94 -0
  316. package/src/data/data-table.module.css.d.ts +11 -0
  317. package/src/data/data-table.tsx +547 -299
  318. package/src/data/virtual-list.tsx +31 -0
  319. package/src/forms/form-layout.module.css +20 -5
  320. package/src/forms/form-layout.module.css.d.ts +1 -0
  321. package/src/forms/form-layout.tsx +12 -10
  322. package/src/guard/index.ts +188 -3
  323. package/src/guard/types.ts +3 -2
  324. package/src/index.ts +2 -0
  325. package/src/notifications/center.tsx +3 -0
  326. package/src/provider/index.tsx +60 -7
  327. package/src/shell/app-brand.module.css +2 -2
  328. package/src/shell/app-brand.tsx +1 -0
  329. package/src/shell/app-header.module.css +18 -8
  330. package/src/shell/app-main.module.css +54 -3
  331. package/src/shell/app-main.module.css.d.ts +1 -0
  332. package/src/shell/app-mobile-nav.module.css +16 -4
  333. package/src/shell/app-sidebar.module.css +4 -6
  334. package/src/shell/aside-docking.ts +54 -0
  335. package/src/shell/index.tsx +178 -129
  336. package/src/shell/mobile-nav-model.ts +1 -1
  337. package/src/shell/page-aside.tsx +70 -21
  338. package/src/shell/page-bar.module.css +10 -34
  339. package/src/shell/page-bar.tsx +10 -5
  340. package/src/shell/use-breakpoint.ts +9 -45
  341. package/src/shell/use-size-class.ts +31 -0
  342. package/src/state/persisted-or-local.ts +10 -4
  343. package/src/state/persisted.ts +76 -17
  344. package/src/styles.css +41 -0
  345. package/src/surfaces.ts +9 -1
  346. package/src/theme/controls.module.css +7 -0
  347. package/src/theme/ctl-theme.tsx +15 -3
  348. package/src/theme/floating.module.css +37 -0
  349. package/src/theme/floating.module.css.d.ts +3 -0
  350. package/src/theme/index.ts +46 -8
  351. package/src/theme/nav-link.module.css +7 -0
  352. package/src/theme-lab/derive-controls.tsx +2 -0
  353. package/src/tokens/index.ts +20 -30
  354. package/src/tokens/palette.ts +6 -28
  355. package/src/tokens/size-classes.ts +46 -0
  356. package/dist/shell/isomorphic-layout-effect.d.ts.map +0 -1
  357. /package/dist/{shell → common}/isomorphic-layout-effect.js +0 -0
@@ -143,6 +143,7 @@ export const KNOWN_RULE_IDS = new Set([
143
143
  'visx-tooltip',
144
144
  'token-layer-boundary',
145
145
  'no-import-meta-env',
146
+ 'raw-breakpoint',
146
147
  // These three honour `basalt-agent-allow`, never `theme-allow` — but they are real ids, so an
147
148
  // annotation naming one must parse as a (useless) scoped annotation rather than as prose.
148
149
  'agent-resume-guard',
@@ -175,6 +176,7 @@ export const KNOWN_RULE_IDS = new Set([
175
176
  'hidden-inline-style',
176
177
  'in-body-page-title',
177
178
  'raw-selection-control',
179
+ 'raw-media-query',
178
180
  // Retired guard kinds — no longer in GUARD_RULES, but a `theme-allow` naming one must still
179
181
  // parse as a real (dead) waiver rather than an unknown-id typo. See RETIRED_RULE_IDS above.
180
182
  ...RETIRED_RULE_IDS,
@@ -2706,7 +2708,7 @@ const CONTROL_OUTSIDE_HOME_MESSAGE =
2706
2708
  * `@mantine/form` (a form is the third home and its inputs are not filters), and the owner
2707
2709
  * exemption — a file DEFINING a basalt control cannot be told to use one.
2708
2710
  */
2709
- // Ships: warn (grace → 1.31.0)
2711
+ // Ships: warn (grace → 1.33.0)
2710
2712
  const controlOutsideHome = {
2711
2713
  meta: {
2712
2714
  type: 'suggestion',
@@ -3645,8 +3647,20 @@ const queryFnUnwrap = {
3645
3647
  * @type {readonly DeprecatedExport[]}
3646
3648
  */
3647
3649
  export const DEPRECATED_EXPORTS = [
3648
- // Empty since 1.29.0: every 1.28.x deprecation was removed on schedule. The next
3649
- // deprecation adds a row here in the same commit as its @deprecated JSDoc and MIGRATING entry.
3650
+ // The chart phone-tier API (`resolveChartTier`/`chartTierMetrics`/`useChartTier`/
3651
+ // `useChartTierMetrics`/`ChartTierMetrics`/`phoneChartWidth`) is NOT here: MIGRATING.md's own
3652
+ // Unreleased section states it a hard removal with no grace window (zero consumers), and these
3653
+ // exports are no longer reachable from any public barrel in `src/charts`/`src/tokens` — a row
3654
+ // here would nudge a rewrite to an import that no longer resolves, i.e. "it still resolves today"
3655
+ // would be false.
3656
+ {
3657
+ subpath: 'basalt-ui',
3658
+ name: 'useBreakpoint',
3659
+ replacement:
3660
+ 'useSizeClass() for shell chrome; a page’s own layout swap is a container decision — a type="container" SimpleGrid/Grid or an @container rule',
3661
+ removeIn: '1.33.0',
3662
+ fix: false,
3663
+ },
3650
3664
  ]
3651
3665
 
3652
3666
  function deprecatedExportMessage(row) {
@@ -3935,6 +3949,336 @@ const noImportMetaEnv = {
3935
3949
  },
3936
3950
  }
3937
3951
 
3952
+ // ── Rule 32 — raw-breakpoint ─────────────────────────────────────────────────────────────────────
3953
+
3954
+ /** The Mantine responsive-style-prop shorthand keys — `{ base, xs, sm, md, lg, xl }`, never a mix. */
3955
+ const RESPONSIVE_OBJECT_KEYS = new Set(['base', 'xs', 'sm', 'md', 'lg', 'xl'])
3956
+
3957
+ /**
3958
+ * Is `node` a Mantine responsive-style-prop object literal — `{ base: 1, sm: 2 }`? Every property
3959
+ * key has to be one of {@link RESPONSIVE_OBJECT_KEYS}, and there has to be at least one: a random
3960
+ * object that merely happens to have a `sm` key among other, unrelated ones is not this shape, and
3961
+ * an empty object is not a breakpoint decision at all.
3962
+ */
3963
+ function isResponsiveObjectValue(node, namedOnly = false) {
3964
+ if (node === null || node === undefined || node.type !== 'ObjectExpression') return false
3965
+ if (node.properties.length === 0) return false
3966
+ const names = node.properties.map((prop) =>
3967
+ prop.type === 'Property' ? propertyKeyName(prop) : undefined,
3968
+ )
3969
+ if (!names.every((name) => typeof name === 'string' && RESPONSIVE_OBJECT_KEYS.has(name)))
3970
+ return false
3971
+ // Under `type="container"` a lone `base` is the unconditional value, not a breakpoint decision.
3972
+ return !namedOnly || names.some((name) => name !== 'base')
3973
+ }
3974
+
3975
+ /**
3976
+ * Does this prop value CONTAIN a responsive object — itself, nested one level down in a property
3977
+ * (`footer={{ height: { base: 60, sm: 0 } }}`, Mantine's own AppShell idiom), or behind a same-file
3978
+ * `const` binding at either place (`const h = { base: 60, sm: 0 }`, then `footer={{ height: h }}`)?
3979
+ * `consts` is the same-file name→object map, so an Identifier resolves identically wherever it
3980
+ * appears — the top-level attribute value and a nested property value alike. Matching only a nested
3981
+ * `ObjectExpression` left the Identifier-in-a-property shape trivially bypassable.
3982
+ */
3983
+ function containsResponsiveObjectValue(node, consts, namedOnly = false, seen = new Set()) {
3984
+ const resolved =
3985
+ node !== null && node !== undefined && node.type === 'Identifier' ? consts.get(node.name) : node
3986
+ if (resolved === null || resolved === undefined || resolved.type !== 'ObjectExpression')
3987
+ return false
3988
+ if (seen.has(resolved)) return false
3989
+ seen.add(resolved)
3990
+ if (isResponsiveObjectValue(resolved, namedOnly)) return true
3991
+ return resolved.properties.some(
3992
+ (prop) =>
3993
+ prop.type === 'Property' &&
3994
+ containsResponsiveObjectValue(prop.value, consts, namedOnly, seen),
3995
+ )
3996
+ }
3997
+
3998
+ /**
3999
+ * The props each Mantine grid routes through `@container` queries under `type="container"` —
4000
+ * confirmed in `@mantine/core` 9.3 source: `SimpleGridContainerVariables` reads `cols`/`spacing`/
4001
+ * `verticalSpacing`, `GridVariables` reads `gap`/`rowGap`/`columnGap`, `GridColVariables` reads
4002
+ * `span`/`offset`/`order`/`align`. Every OTHER responsive prop on the same element (`p`, `mt`,
4003
+ * `mih`, …) is a Box style prop and still compiles to viewport `@media`, so the container exemption
4004
+ * stops at this set. `Grid`'s own `breakpoints` is the container scale itself, not a viewport key.
4005
+ */
4006
+ const CONTAINER_ROUTED_PROPS = {
4007
+ SimpleGrid: new Set(['cols', 'spacing', 'verticalSpacing']),
4008
+ Grid: new Set(['gap', 'rowGap', 'columnGap', 'breakpoints']),
4009
+ 'Grid.Col': new Set(['span', 'offset', 'order', 'align']),
4010
+ }
4011
+
4012
+ /**
4013
+ * How Mantine 9 resolves a responsive object on this element's grid, read from `@mantine/core`
4014
+ * 9.3 source — the sanctioned answer to this rule, so it has to be exempt exactly where it works:
4015
+ *
4016
+ * - `'container'` — a `<Grid type="container" breakpoints={…}>` (or a `Grid.Col` inside one) whose
4017
+ * map statically resolves to a non-empty object. Keys resolve through that map into
4018
+ * `@container mantine-grid` queries, so an `sm` key is whatever width the map gives it: exempt.
4019
+ * Mantine types the map as `Record<MantineSize, string>`, so the recipe's keys ARE `xs`–`xl` —
4020
+ * exempting by key name instead of by owner would flag the sanctioned answer itself.
4021
+ * - `'simple-grid'` — `<SimpleGrid type="container">`. `SimpleGridContainerVariables` writes each
4022
+ * key VERBATIM as `@container simple-grid (min-width: <key>)` and never consults
4023
+ * `theme.breakpoints`: a `'480px'` key works (and is not a responsive-object key, so it never
4024
+ * reaches here), while `sm` emits `(min-width: sm)` — invalid CSS, a dead query. Flagged.
4025
+ * - `'fallback'` — `<Grid type="container">` whose `breakpoints` is absent, `undefined`, `{}` or not
4026
+ * statically resolvable (or a `Grid.Col` in one). `Grid` takes its container branch only on a
4027
+ * truthy map, and an empty one emits no query at all — so none of these is the container law,
4028
+ * and an unreadable map is reported rather than trusted. Flagged.
4029
+ * - `undefined` — not a container grid; the ordinary viewport law applies.
4030
+ *
4031
+ * `type` has to be the string literal `"container"`; a dynamic value is not a decision this rule
4032
+ * can read. `Grid.Col` takes its grid's mode by walking to the nearest enclosing `Grid` element.
4033
+ * `consts` is the rule's same-file name→object map, so `breakpoints={map}` resolves like any value.
4034
+ */
4035
+ function containerGridMode(opening, mantineImports, consts) {
4036
+ let tag = resolveMantineTag(opening.name, mantineImports)
4037
+ let grid = opening
4038
+ if (tag === 'Grid.Col') {
4039
+ grid = undefined
4040
+ let node = opening.parent?.parent
4041
+ for (let depth = 0; node !== null && node !== undefined; depth++, node = node.parent) {
4042
+ if (depth > ANCESTRY_MAX_DEPTH || node.type === 'Program') break
4043
+ if (node.type !== 'JSXElement') continue
4044
+ if (resolveMantineTag(node.openingElement.name, mantineImports) !== 'Grid') continue
4045
+ grid = node.openingElement
4046
+ tag = 'Grid'
4047
+ break
4048
+ }
4049
+ }
4050
+ if (grid === undefined || (tag !== 'Grid' && tag !== 'SimpleGrid')) return undefined
4051
+ const attr = (name) =>
4052
+ grid.attributes.find((a) => a.type === 'JSXAttribute' && a.name?.name === name)
4053
+ const type = attr('type')
4054
+ if (
4055
+ type === undefined ||
4056
+ !isStringLiteral(attrValue(type)) ||
4057
+ attrValue(type).value !== 'container'
4058
+ )
4059
+ return undefined
4060
+ if (tag === 'SimpleGrid') return 'simple-grid'
4061
+ const breakpoints = attr('breakpoints')
4062
+ if (breakpoints === undefined) return 'fallback'
4063
+ let map = attrValue(breakpoints)
4064
+ if (map?.type === 'Identifier') map = consts.get(map.name)
4065
+ const nonEmpty =
4066
+ map?.type === 'ObjectExpression' && map.properties.some((prop) => prop.type === 'Property')
4067
+ return nonEmpty ? 'container' : 'fallback'
4068
+ }
4069
+
4070
+ /**
4071
+ * The shell components that are `visibleFrom`/`hiddenFrom`'s legitimate home — the size-class
4072
+ * axis's one JSX escape hatch, alongside overlays. Matched by DECLARATION name, the same
4073
+ * owner-by-declaration test `hand-rolled-shell`'s
4074
+ * `notesOwnerDefinition` already uses for "this file IS the framework piece, not a consumer of it"
4075
+ * — a file defining one of these is exempt for the whole file, because deciding which JSX line
4076
+ * inside a shell's own render tree is "the shell deciding its own chrome" vs. "a stray breakpoint"
4077
+ * is not a distinction the shell's own implementation can make about itself. The OTHER legitimate
4078
+ * home is a control implementing its own C9 swap (`ViewTabs`, `ActionGroup`, …) — that half reuses
4079
+ * {@link createControlOwnerProbe} (`controlOwner` below) rather than a second name list.
4080
+ */
4081
+ const SHELL_HOME_NAMES = new Set(['BasaltShell', 'AppSidebar', 'MobileNav', 'AppBrand'])
4082
+
4083
+ /**
4084
+ * The two files exempted by NAME rather than by declaration: `useMediaQuery`'s own implementation
4085
+ * (`common/use-media-query.ts` — the one sanctioned `window.matchMedia` read every other file,
4086
+ * including `useSizeClass`, now funnels through) and `ChartTooltip` (the Mantine-free chart layer's
4087
+ * own pointer-tier read).
4088
+ */
4089
+ const RAW_BREAKPOINT_EXEMPT_FILE = /(?:^|[\\/])(?:use-media-query\.ts|ChartTooltip\.tsx)$/
4090
+
4091
+ /**
4092
+ * The one recipe every raw-breakpoint message points at. A page's own layout keys on its CONTAINER
4093
+ * (`CONTAINER_CLASSES`, `basalt-ui/tokens`: compact 240 / regular 480 / wide 800), never on the
4094
+ * viewport — `useSizeClass()` is the shell's seam, not a page's. Mantine 9's own `type="container"`
4095
+ * grids are the primitive: both self-wrap in an `inline-size` container, so they need no ancestor.
4096
+ * The px literals are `CONTAINER_CLASSES` written out (the plugin cannot import TS source);
4097
+ * `oxlint-plugin.test.ts` asserts every one against it, and the MIGRATING recipe too.
4098
+ */
4099
+ export const RAW_BREAKPOINT_RECIPE =
4100
+ 'A page’s own layout keys on its container: <SimpleGrid type="container" cols={{ base: 1, ' +
4101
+ "'480px': 2, '800px': 3 }}> (px keys = CONTAINER_CLASSES, basalt-ui/tokens), or <Grid " +
4102
+ 'type="container" breakpoints={…}> mapping all five xs–xl onto those px widths, with Grid.Col ' +
4103
+ 'span={{ base: 12, sm: 6 }} keyed through that map; a Flex direction swap becomes that SimpleGrid (equal ' +
4104
+ 'columns), a wrapping Group, or a CSS-module @container basalt-grid rule. useSizeClass() is for ' +
4105
+ 'shell chrome only. Recipes: basalt-ui MIGRATING.md § basalt/raw-breakpoint.'
4106
+
4107
+ const RAW_BREAKPOINT_RESPONSIVE_PROP_MESSAGE =
4108
+ 'Responsive-object prop keyed on theme breakpoints — those are viewport widths. ' +
4109
+ `${RAW_BREAKPOINT_RECIPE} (basalt/raw-breakpoint)`
4110
+
4111
+ const RAW_BREAKPOINT_CONTAINER_KEY_MESSAGE =
4112
+ 'Theme breakpoint name under type="container" — Mantine does not resolve it there: ' +
4113
+ "SimpleGrid uses each key verbatim as a (min-width: …) length, so 'sm' is a dead query, " +
4114
+ 'and Grid only goes container with a breakpoints map (without one it silently falls back to ' +
4115
+ `viewport media queries). ${RAW_BREAKPOINT_RECIPE} (basalt/raw-breakpoint)`
4116
+
4117
+ const RAW_BREAKPOINT_VISIBLE_HIDDEN_MESSAGE =
4118
+ "visibleFrom/hiddenFrom outside a shell home or a control's own C9 swap — a viewport " +
4119
+ `breakpoint the framework cannot see or move. ${RAW_BREAKPOINT_RECIPE} (basalt/raw-breakpoint)`
4120
+
4121
+ const RAW_BREAKPOINT_HOOK_MESSAGE =
4122
+ "useMediaQuery/useMatches/useViewportSize — a raw viewport read outside the framework's " +
4123
+ 'one seam. Shell chrome reads useSizeClass(); a page swapping its own layout (a table for a card ' +
4124
+ `list, a column count) is a container decision. ${RAW_BREAKPOINT_RECIPE} (basalt/raw-breakpoint)`
4125
+
4126
+ const RAW_BREAKPOINT_GLOBAL_MESSAGE =
4127
+ 'window.matchMedia/window.innerWidth read directly — the viewport read useSizeClass() owns ' +
4128
+ `for shell chrome. ${RAW_BREAKPOINT_RECIPE} (basalt/raw-breakpoint)`
4129
+
4130
+ /** The three viewport hooks the law names, whatever module they are imported from. */
4131
+ const RAW_BREAKPOINT_HOOK_NAMES = new Set(['useMediaQuery', 'useMatches', 'useViewportSize'])
4132
+
4133
+ /**
4134
+ * Four independent shapes, one law: a consumer (or basalt itself, outside the shell homes)
4135
+ * reaching past the framework's two sanctioned seams — `useSizeClass()` for shell-only viewport
4136
+ * chrome, a container query for everything else — to read or react to a raw
4137
+ * viewport breakpoint. `visibleFrom`/`hiddenFrom` and the responsive-object shape are reported once
4138
+ * the whole file has been walked ({@link SHELL_HOME_NAMES} may be declared after its first JSX use,
4139
+ * the same ordering hazard `hand-rolled-shell` defers a `Program:exit` report to avoid); the import
4140
+ * and the two global reads carry no such ordering hazard and report immediately. A file that
4141
+ * declares a shell home (or a control's own C9 swap) is exempt for all four shapes uniformly — the
4142
+ * shell's own responsive chrome is the sanctioned use, whatever shape it takes.
4143
+ */
4144
+ // Ships: warn (grace → 1.33.0)
4145
+ const rawBreakpoint = {
4146
+ meta: {
4147
+ type: 'suggestion',
4148
+ docs: {
4149
+ description:
4150
+ 'Disallow a hand-rolled viewport breakpoint — a responsive-object Mantine prop, ' +
4151
+ 'visibleFrom/hiddenFrom outside a shell home, useMediaQuery/useMatches/useViewportSize, or ' +
4152
+ 'a raw window.matchMedia/innerWidth read. All four shapes are exempt inside a file that ' +
4153
+ 'declares a shell-home component (or a control implementing its own C9 swap); a ' +
4154
+ 'responsive object on a Mantine type="container" grid is exempt where Mantine resolves it.',
4155
+ },
4156
+ schema: [],
4157
+ },
4158
+ create(context) {
4159
+ if (isTestFile(context)) return {}
4160
+ if (RAW_BREAKPOINT_EXEMPT_FILE.test(getFilename(context))) return {}
4161
+
4162
+ const mantineImports = new Map()
4163
+ // A control implementing its OWN C9 responsive swap (`ViewTabs`, `ActionGroup`'s file, …) is
4164
+ // the other legitimate visibleFrom/hiddenFrom home, alongside the three named shell pieces —
4165
+ // reuse `responsive-twin`'s existing owner probe rather than hand-listing every control file
4166
+ // here too (`view-tabs.tsx`/`actions.tsx` were both false positives before this reuse).
4167
+ const controlOwner = createControlOwnerProbe()
4168
+ let definesShellHome = false
4169
+ const visibleHiddenCandidates = []
4170
+ const responsiveObjectCandidates = []
4171
+ // Same-file `const NAME = { base, sm }` bindings, resolved when a JSX attribute or a nested
4172
+ // property passes the Identifier — no scope manager here, so this is a flat name→object map.
4173
+ // A name declared more than once in the file is ambiguous (its two bindings cannot be told
4174
+ // apart), so it is dropped from the map entirely rather than guessed at last-wins.
4175
+ const responsiveObjectConsts = new Map()
4176
+ const seenDeclaratorNames = new Set()
4177
+
4178
+ const noteShellHomeOwner = (name) => {
4179
+ if (typeof name === 'string' && SHELL_HOME_NAMES.has(name)) definesShellHome = true
4180
+ }
4181
+
4182
+ return {
4183
+ ImportDeclaration(node) {
4184
+ controlOwner.noteImport(node)
4185
+ collectMantineImports(node, mantineImports)
4186
+ if (node.importKind === 'type') return
4187
+ // `useMatches` collides with `@tanstack/react-router`'s own hook of the same name (basalt's
4188
+ // own `src/router-tanstack/index.ts` imports it) — scope the whole set to a `@mantine/*`
4189
+ // source rather than name alone, the same provenance gate every other Mantine-name rule in
4190
+ // this file already uses (`collectMantineImports`).
4191
+ const source = node.source?.value
4192
+ if (typeof source !== 'string' || !source.startsWith('@mantine/')) return
4193
+ for (const specifier of node.specifiers ?? []) {
4194
+ if (specifier.type !== 'ImportSpecifier') continue
4195
+ if (specifier.importKind === 'type') continue
4196
+ const imported = specifier.imported
4197
+ const importedName = imported.type === 'Identifier' ? imported.name : imported.value
4198
+ if (typeof importedName !== 'string' || !RAW_BREAKPOINT_HOOK_NAMES.has(importedName))
4199
+ continue
4200
+ if (hasThemeAllow(context, specifier, 'raw-breakpoint')) continue
4201
+ context.report({ node: specifier, message: RAW_BREAKPOINT_HOOK_MESSAGE })
4202
+ }
4203
+ },
4204
+ FunctionDeclaration(node) {
4205
+ noteShellHomeOwner(node.id?.name)
4206
+ controlOwner.visitors.FunctionDeclaration(node)
4207
+ },
4208
+ VariableDeclarator(node) {
4209
+ noteShellHomeOwner(node.id?.name)
4210
+ controlOwner.visitors.VariableDeclarator(node)
4211
+ if (node.id?.type !== 'Identifier') return
4212
+ const name = node.id.name
4213
+ if (seenDeclaratorNames.has(name)) {
4214
+ // A redeclared name — drop whatever the first declaration put here, so the ambiguous
4215
+ // binding is never used to flag (or clear) a JSX value it may not even be.
4216
+ responsiveObjectConsts.delete(name)
4217
+ return
4218
+ }
4219
+ seenDeclaratorNames.add(name)
4220
+ if (node.init?.type === 'ObjectExpression') responsiveObjectConsts.set(name, node.init)
4221
+ },
4222
+ JSXAttribute(node) {
4223
+ const name = node.name?.name
4224
+ if (typeof name !== 'string') return
4225
+ if (name === 'visibleFrom' || name === 'hiddenFrom') {
4226
+ visibleHiddenCandidates.push(node)
4227
+ return
4228
+ }
4229
+ // Resolved at `Program:exit` so a `const` declared after its first JSX use still resolves.
4230
+ responsiveObjectCandidates.push(node)
4231
+ },
4232
+ CallExpression(node) {
4233
+ if (node.callee?.type !== 'Identifier' || node.callee.name !== 'matchMedia') return
4234
+ if (hasThemeAllow(context, node, 'raw-breakpoint')) return
4235
+ context.report({ node, message: RAW_BREAKPOINT_GLOBAL_MESSAGE })
4236
+ },
4237
+ MemberExpression(node) {
4238
+ if (node.object?.type !== 'Identifier' || node.object.name !== 'window') return
4239
+ if (node.computed) return
4240
+ const property = node.property?.name
4241
+ if (property !== 'matchMedia' && property !== 'innerWidth') return
4242
+ if (hasThemeAllow(context, node, 'raw-breakpoint')) return
4243
+ context.report({ node, message: RAW_BREAKPOINT_GLOBAL_MESSAGE })
4244
+ },
4245
+ 'Program:exit'() {
4246
+ // A shell home (or a control implementing its own C9 swap) IS the framework piece — the
4247
+ // shell's own responsive chrome is the sanctioned use, so nothing here reports there.
4248
+ if (definesShellHome || controlOwner.isOwner()) return
4249
+ for (const node of responsiveObjectCandidates) {
4250
+ const value = unwrapExpressionContainer(node.value)
4251
+ const owner = node.parent
4252
+ if (owner === null || owner === undefined || owner.type !== 'JSXOpeningElement') continue
4253
+ const tag = resolveMantineTag(owner.name, mantineImports)
4254
+ if (tag === undefined) continue
4255
+ // The container law reaches only the props Mantine routes through the grid's container
4256
+ // queries; a `p={{ base, lg }}` on the same element is still a viewport @media.
4257
+ const routed = Object.hasOwn(CONTAINER_ROUTED_PROPS, tag)
4258
+ ? CONTAINER_ROUTED_PROPS[tag]
4259
+ : undefined
4260
+ const mode = routed?.has(node.name.name)
4261
+ ? containerGridMode(owner, mantineImports, responsiveObjectConsts)
4262
+ : undefined
4263
+ if (mode === 'container') continue
4264
+ if (!containsResponsiveObjectValue(value, responsiveObjectConsts, mode !== undefined))
4265
+ continue
4266
+ if (hasThemeAllow(context, node, 'raw-breakpoint')) continue
4267
+ const message =
4268
+ mode === undefined
4269
+ ? RAW_BREAKPOINT_RESPONSIVE_PROP_MESSAGE
4270
+ : RAW_BREAKPOINT_CONTAINER_KEY_MESSAGE
4271
+ context.report({ node, message })
4272
+ }
4273
+ for (const node of visibleHiddenCandidates) {
4274
+ if (hasThemeAllow(context, node, 'raw-breakpoint')) continue
4275
+ context.report({ node, message: RAW_BREAKPOINT_VISIBLE_HIDDEN_MESSAGE })
4276
+ }
4277
+ },
4278
+ }
4279
+ },
4280
+ }
4281
+
3938
4282
  // ── Grace ledger ────────────────────────────────────────────────────────────────────────────────
3939
4283
 
3940
4284
  /**
@@ -3968,8 +4312,10 @@ const noImportMetaEnv = {
3968
4312
  export const PLUGIN_RULE_GRACE = {
3969
4313
  'control-outside-home': {
3970
4314
  since: '1.26.0',
3971
- promote: '1.31.0',
4315
+ promote: '1.33.0',
3972
4316
  why:
4317
+ "Extended 1.32.0 -> 1.33.0 at the 1.32.0 release, the last extension: basalt's own tree is at 0 (consumer-loop r1 dogfood) and argo is at 2, but RE-MEASURED 2026-09-30 the fleet carries ~33 (image-gen 11, rb 7, image-share 6, weatherorb 5, email-gateway 4, argo 2). The 1.32.0 fleet upgrade clears them while they warn, together with raw-breakpoint, so 1.33.0 promotes all four ids against a measured-clean fleet. " +
4318
+ 'Extended 1.31.0 -> 1.32.0 at the 1.31.0 release: the basalt tree still carries incumbents (data-table, notifications center, theme-lab) and the argo sweep has not run. ' +
3973
4319
  'the wave-6 control guards (docs/CONTROLS-SPEC.md §6). The one openly HEURISTIC rule of the ' +
3974
4320
  'set — "this control has no home" is a claim about layout intent, so its false-positive load ' +
3975
4321
  'is carried by four exemptions (overlay/settings-row ancestor, the overlay FILENAME ' +
@@ -3995,6 +4341,26 @@ export const PLUGIN_RULE_GRACE = {
3995
4341
  "still an overlay's own body declares it with " +
3996
4342
  '`theme-allow-file control-outside-home — overlay`.',
3997
4343
  },
4344
+ 'raw-breakpoint': {
4345
+ since: '1.31.0',
4346
+ promote: '1.33.0',
4347
+ why:
4348
+ 'New in the wave-11 responsive/touch guards. Catches four independent shapes at once — a ' +
4349
+ 'responsive-object Mantine prop, visibleFrom/hiddenFrom outside the three shell homes, the ' +
4350
+ 'three raw viewport hooks, and window.matchMedia/innerWidth — none of which basalt policed ' +
4351
+ 'before this wave, so every consumer on an earlier minor has a green build with all four ' +
4352
+ "shapes already in it. basalt-ui/content's own article-card.tsx (a `SimpleGrid cols={{ base: " +
4353
+ "1, sm: 2, lg }}`) was one incumbent measured in basalt's own tree at ship time — a real " +
4354
+ 'number, not zero, so it shipped warn rather than error. ' +
4355
+ 'Extended 1.32.0 -> 1.33.0: 1.31.0 shipped the rule naming "a container query" but no ' +
4356
+ 'primitive, and MIGRATING never mentioned it (argo: 42 warns, no documented target). 1.32.0 ' +
4357
+ 'is the first minor with a reachable, documented answer (Mantine type="container" grids keyed ' +
4358
+ 'on CONTAINER_CLASSES, exempted here), and promoting in the minor that first makes a rule ' +
4359
+ 'satisfiable hands a consumer zero minors to act on it — the control-outside-home ' +
4360
+ "extension's reasoning. 1.33.0 is when the incumbents are expected to have moved to a " +
4361
+ 'container grid or a theme-allow with a stated reason. Promotes together with its CSS twin, ' +
4362
+ 'the `raw-media-query` guard kind.',
4363
+ },
3998
4364
  }
3999
4365
 
4000
4366
  /**
@@ -4064,5 +4430,6 @@ export default {
4064
4430
  'agent-no-raw-usechat': agentNoRawUseChat,
4065
4431
  'ai-sdk-major': aiSdkMajor,
4066
4432
  'no-import-meta-env': noImportMetaEnv,
4433
+ 'raw-breakpoint': rawBreakpoint,
4067
4434
  },
4068
4435
  }