basalt-ui 1.28.0 → 1.29.1

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 (457) hide show
  1. package/AGENTS.md +12 -19
  2. package/CHANGELOG.md +23 -0
  3. package/MIGRATING.md +171 -7
  4. package/README.md +66 -105
  5. package/agent/rules/basalt-batteries.md +60 -183
  6. package/agent/rules/basalt-charts.md +56 -75
  7. package/agent/rules/basalt-controls.md +38 -69
  8. package/agent/rules/basalt-mantine.md +58 -103
  9. package/agent/rules/basalt-state.md +42 -60
  10. package/agent/rules/basalt-tokens.md +46 -67
  11. package/agent/skills/basalt-app/SKILL.md +2 -0
  12. package/agent/templates/CLAUDE-block.md.tpl +14 -14
  13. package/agent/templates/query-client.ts.tpl +1 -1
  14. package/configs/oxlint-plugin.js +84 -254
  15. package/configs/oxlint-plugin.test.ts +23 -266
  16. package/configs/oxlint.json +0 -2
  17. package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
  18. package/dist/agent/ai-sdk-transport.js +7 -4
  19. package/dist/agent/coalesce.js +1 -1
  20. package/dist/agent/merge.js +1 -1
  21. package/dist/agent/transport.d.ts +13 -2
  22. package/dist/agent/transport.d.ts.map +1 -1
  23. package/dist/agent/use-agent-thread-runs.d.ts +12 -1
  24. package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
  25. package/dist/agent/use-agent-thread-runs.js +20 -6
  26. package/dist/agent-chat/index.d.ts +1 -1
  27. package/dist/agent-chat/index.d.ts.map +1 -1
  28. package/dist/agent-chat/relative-time.js +1 -1
  29. package/dist/agent-chat/thread-detail-panel.js +1 -1
  30. package/dist/agent-chat/thread-feed-row.d.ts +32 -7
  31. package/dist/agent-chat/thread-feed-row.d.ts.map +1 -1
  32. package/dist/agent-chat/thread-feed-row.js +121 -86
  33. package/dist/agent-chat/thread-feed.d.ts +11 -1
  34. package/dist/agent-chat/thread-feed.d.ts.map +1 -1
  35. package/dist/agent-chat/thread-feed.js +10 -6
  36. package/dist/agent-chat/thread-message.js +1 -1
  37. package/dist/agent-chat/virtualize.d.ts +39 -0
  38. package/dist/agent-chat/virtualize.d.ts.map +1 -1
  39. package/dist/agent-chat/virtualize.js +15 -0
  40. package/dist/charts/index.d.ts +3 -3
  41. package/dist/charts/index.d.ts.map +1 -1
  42. package/dist/charts/index.js +8 -4
  43. package/dist/charts/kinds/BandStrip.js +1 -1
  44. package/dist/charts/kinds/Bars.d.ts +1 -3
  45. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  46. package/dist/charts/kinds/Bars.js +1 -1
  47. package/dist/charts/kinds/DualPanel.d.ts +3 -1
  48. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  49. package/dist/charts/kinds/DualPanel.js +1 -1
  50. package/dist/charts/kinds/StackedArea.js +1 -1
  51. package/dist/charts/kinds/ZonedLine.d.ts +1 -3
  52. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  53. package/dist/charts/primitives/Axes.d.ts +21 -2
  54. package/dist/charts/primitives/Axes.d.ts.map +1 -1
  55. package/dist/charts/primitives/Axes.js +34 -2
  56. package/dist/charts/primitives/ChartCard.d.ts +20 -4
  57. package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
  58. package/dist/charts/primitives/ChartCard.js +62 -33
  59. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  60. package/dist/charts/primitives/ChartFrame.js +8 -1
  61. package/dist/charts/primitives/ChartPending.d.ts +12 -6
  62. package/dist/charts/primitives/ChartPending.d.ts.map +1 -1
  63. package/dist/charts/primitives/ChartPending.js +1 -1
  64. package/dist/charts/utils/format.d.ts +5 -92
  65. package/dist/charts/utils/format.d.ts.map +1 -1
  66. package/dist/charts/utils/format.js +10 -80
  67. package/dist/cli/audit-allows.d.ts +24 -0
  68. package/dist/cli/audit-allows.d.ts.map +1 -0
  69. package/dist/cli/audit-allows.js +240 -0
  70. package/dist/cli/check-theme.d.ts +10 -0
  71. package/dist/cli/check-theme.d.ts.map +1 -0
  72. package/dist/cli/check-theme.js +139 -0
  73. package/dist/cli/doctor.d.ts +47 -0
  74. package/dist/cli/doctor.d.ts.map +1 -0
  75. package/dist/cli/doctor.js +197 -0
  76. package/dist/cli/guard-hook.d.ts +9 -0
  77. package/dist/cli/guard-hook.d.ts.map +1 -0
  78. package/dist/cli/guard-hook.js +93 -0
  79. package/dist/cli/help.d.ts +9 -0
  80. package/dist/cli/help.d.ts.map +1 -0
  81. package/dist/cli/help.js +53 -0
  82. package/dist/cli/index.d.ts +360 -270
  83. package/dist/cli/index.d.ts.map +1 -1
  84. package/dist/cli/index.js +85 -1901
  85. package/dist/cli/init.d.ts +4 -0
  86. package/dist/cli/init.d.ts.map +1 -0
  87. package/dist/cli/init.js +165 -0
  88. package/dist/cli/sync.d.ts +43 -0
  89. package/dist/cli/sync.d.ts.map +1 -0
  90. package/dist/cli/sync.js +206 -0
  91. package/dist/cli/tokens-css.d.ts +51 -0
  92. package/dist/cli/tokens-css.d.ts.map +1 -0
  93. package/dist/cli/tokens-css.js +165 -0
  94. package/dist/commands/define-commands.js +1 -1
  95. package/dist/commands/define-overlays.js +1 -1
  96. package/dist/commands/index.d.ts +2 -1
  97. package/dist/commands/index.d.ts.map +1 -1
  98. package/dist/commands/index.js +6 -0
  99. package/dist/commands/overlays-mount.d.ts +7 -9
  100. package/dist/commands/overlays-mount.d.ts.map +1 -1
  101. package/dist/commands/shell-bridge.d.ts +57 -0
  102. package/dist/commands/shell-bridge.d.ts.map +1 -0
  103. package/dist/commands/shell-bridge.js +32 -0
  104. package/dist/common/errors.d.ts +35 -0
  105. package/dist/common/errors.d.ts.map +1 -1
  106. package/dist/common/errors.js +29 -1
  107. package/dist/common/index.d.ts +2 -0
  108. package/dist/common/index.d.ts.map +1 -1
  109. package/dist/common/index.js +6 -0
  110. package/dist/common/is-dev.d.ts.map +1 -0
  111. package/dist/{motion/index.d.ts → common/motion.d.ts} +1 -1
  112. package/dist/common/motion.d.ts.map +1 -0
  113. package/dist/common/props.d.ts +1 -1
  114. package/dist/common/props.d.ts.map +1 -1
  115. package/dist/common/validate.js +1 -1
  116. package/dist/content/markdown.d.ts +3 -4
  117. package/dist/content/markdown.d.ts.map +1 -1
  118. package/dist/content/markdown.js +1 -4
  119. package/dist/controls/actions.d.ts +1 -1
  120. package/dist/controls/actions.d.ts.map +1 -1
  121. package/dist/controls/panel-row.js +1 -1
  122. package/dist/controls/range-filter.js +1 -1
  123. package/dist/dashboard/delta-badge.d.ts +18 -10
  124. package/dist/dashboard/delta-badge.d.ts.map +1 -1
  125. package/dist/dashboard/delta-badge.js +33 -1
  126. package/dist/dashboard/empty-state.d.ts +1 -4
  127. package/dist/dashboard/empty-state.d.ts.map +1 -1
  128. package/dist/dashboard/empty-state.js +1 -2
  129. package/dist/dashboard/index.d.ts +4 -2
  130. package/dist/dashboard/index.d.ts.map +1 -1
  131. package/dist/dashboard/index.js +7 -1
  132. package/dist/dashboard/query-state.d.ts +4 -13
  133. package/dist/dashboard/query-state.d.ts.map +1 -1
  134. package/dist/dashboard/query-state.js +4 -7
  135. package/dist/{section → dashboard}/section.d.ts +2 -2
  136. package/dist/{section → dashboard}/section.d.ts.map +1 -1
  137. package/dist/{section → dashboard}/section.js +2 -2
  138. package/dist/dashboard/settings-section.d.ts +1 -1
  139. package/dist/dashboard/settings-section.d.ts.map +1 -1
  140. package/dist/dashboard/settings-section.js +1 -1
  141. package/dist/dashboard/stat-card.d.ts +1 -1
  142. package/dist/dashboard/stat-card.d.ts.map +1 -1
  143. package/dist/dashboard/stat-card.js +1 -1
  144. package/dist/dashboard/widget-header.d.ts.map +1 -0
  145. package/dist/data/data-table.js +2 -2
  146. package/dist/data/table.d.ts +1 -1
  147. package/dist/data/table.d.ts.map +1 -1
  148. package/dist/data/table.js +2 -16
  149. package/dist/data/virtual.d.ts +3 -3
  150. package/dist/dev-dock.d.ts +26 -0
  151. package/dist/dev-dock.d.ts.map +1 -0
  152. package/dist/dev-dock.js +85 -0
  153. package/dist/format/date.d.ts +62 -0
  154. package/dist/format/date.d.ts.map +1 -0
  155. package/dist/format/date.js +106 -0
  156. package/dist/format/index.d.ts +39 -0
  157. package/dist/format/index.d.ts.map +1 -0
  158. package/dist/format/index.js +54 -0
  159. package/dist/format/measure.d.ts +15 -0
  160. package/dist/format/measure.d.ts.map +1 -0
  161. package/dist/format/measure.js +16 -0
  162. package/dist/format/number.d.ts +69 -0
  163. package/dist/format/number.d.ts.map +1 -0
  164. package/dist/format/number.js +62 -0
  165. package/dist/format/shared.d.ts +27 -0
  166. package/dist/format/shared.d.ts.map +1 -0
  167. package/dist/format/shared.js +29 -0
  168. package/dist/forms/field.d.ts +4 -20
  169. package/dist/forms/field.d.ts.map +1 -1
  170. package/dist/forms/field.js +0 -4
  171. package/dist/forms/form-layout.d.ts +1 -1
  172. package/dist/forms/form-layout.d.ts.map +1 -1
  173. package/dist/forms/form-layout.js +1 -1
  174. package/dist/forms/index.d.ts +1 -1
  175. package/dist/forms/index.d.ts.map +1 -1
  176. package/dist/forms/index.js +1 -2
  177. package/dist/forms/use-form-submit.d.ts +1 -1
  178. package/dist/forms/use-form-submit.js +1 -1
  179. package/dist/guard/index.d.ts +2 -9
  180. package/dist/guard/index.d.ts.map +1 -1
  181. package/dist/guard/index.js +53 -32
  182. package/dist/guard/types.d.ts +8 -10
  183. package/dist/guard/types.d.ts.map +1 -1
  184. package/dist/index.d.ts +16 -11
  185. package/dist/index.d.ts.map +1 -1
  186. package/dist/index.js +23 -29
  187. package/dist/notifications/index.d.ts +5 -5
  188. package/dist/notifications/index.d.ts.map +1 -1
  189. package/dist/notifications/index.js +0 -2
  190. package/dist/notifications/mount-guard.d.ts.map +1 -1
  191. package/dist/notifications/mount-guard.js +2 -2
  192. package/dist/provider/connectivity-indicator.d.ts.map +1 -0
  193. package/dist/{connectivity → provider}/connectivity-provider.d.ts +1 -1
  194. package/dist/provider/connectivity-provider.d.ts.map +1 -0
  195. package/dist/{connectivity/types.d.ts → provider/connectivity-types.d.ts} +1 -1
  196. package/dist/provider/connectivity-types.d.ts.map +1 -0
  197. package/dist/provider/error-fallback.module.css +21 -0
  198. package/dist/provider/error-fallback.module.css.d.ts +9 -0
  199. package/dist/provider/index.d.ts +20 -36
  200. package/dist/provider/index.d.ts.map +1 -1
  201. package/dist/provider/index.js +42 -32
  202. package/dist/provider/lab-theme.js +1 -1
  203. package/dist/provider/use-connectivity.d.ts +3 -0
  204. package/dist/provider/use-connectivity.d.ts.map +1 -0
  205. package/dist/query-client.d.ts +67 -0
  206. package/dist/query-client.d.ts.map +1 -0
  207. package/dist/query-client.js +35 -0
  208. package/dist/{query/devtools.d.ts → query-devtools.d.ts} +2 -2
  209. package/dist/query-devtools.d.ts.map +1 -0
  210. package/dist/register.d.ts +17 -3
  211. package/dist/register.d.ts.map +1 -1
  212. package/dist/router-tanstack/index.d.ts +4 -7
  213. package/dist/router-tanstack/index.d.ts.map +1 -1
  214. package/dist/router-tanstack/index.js +1 -9
  215. package/dist/router-tanstack/nav.d.ts +1 -1
  216. package/dist/router-tanstack/nav.d.ts.map +1 -1
  217. package/dist/router-tanstack/search-store.d.ts +3 -6
  218. package/dist/router-tanstack/search-store.d.ts.map +1 -1
  219. package/dist/router-tanstack/use-nav.d.ts +1 -1
  220. package/dist/router-tanstack/use-nav.d.ts.map +1 -1
  221. package/dist/shell/app-breadcrumbs.d.ts +1 -1
  222. package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
  223. package/dist/shell/app-main.module.css +11 -0
  224. package/dist/shell/app-mobile-nav.d.ts +1 -1
  225. package/dist/shell/app-mobile-nav.d.ts.map +1 -1
  226. package/dist/shell/app-mobile-nav.js +24 -2
  227. package/dist/shell/app-sidebar.d.ts +1 -1
  228. package/dist/shell/app-sidebar.d.ts.map +1 -1
  229. package/dist/shell/app-sidebar.js +31 -2
  230. package/dist/shell/app-sidebar.module.css +10 -0
  231. package/dist/shell/index.d.ts +10 -4
  232. package/dist/shell/index.d.ts.map +1 -1
  233. package/dist/shell/index.js +13 -17
  234. package/dist/shell/mobile-nav-model.d.ts +1 -1
  235. package/dist/shell/mobile-nav-model.d.ts.map +1 -1
  236. package/dist/{nav/types.d.ts → shell/nav-types.d.ts} +1 -1
  237. package/dist/shell/nav-types.d.ts.map +1 -0
  238. package/dist/shell/page-aside.d.ts.map +1 -1
  239. package/dist/shell/page-aside.js +2 -29
  240. package/dist/shell/page-title.d.ts +14 -0
  241. package/dist/shell/page-title.d.ts.map +1 -0
  242. package/dist/shell/page-title.js +25 -0
  243. package/dist/shell/page-title.module.css +33 -0
  244. package/dist/shell/page-title.module.css.d.ts +11 -0
  245. package/dist/shell/sidebar-block-model.d.ts +1 -1
  246. package/dist/shell/sidebar-block-model.d.ts.map +1 -1
  247. package/dist/shell/sidebar-blocks.d.ts +1 -1
  248. package/dist/shell/sidebar-blocks.d.ts.map +1 -1
  249. package/dist/shell/use-breakpoint.d.ts +11 -0
  250. package/dist/shell/use-breakpoint.d.ts.map +1 -0
  251. package/dist/shell/use-breakpoint.js +33 -0
  252. package/dist/state/fields.d.ts +3 -19
  253. package/dist/state/fields.d.ts.map +1 -1
  254. package/dist/state/fields.js +6 -16
  255. package/dist/styles.css +36 -0
  256. package/dist/surfaces.d.ts +18 -41
  257. package/dist/surfaces.d.ts.map +1 -1
  258. package/dist/surfaces.js +48 -60
  259. package/dist/theme/index.d.ts.map +1 -1
  260. package/dist/{theme-toggle/index.d.ts → theme/theme-toggle.d.ts} +1 -1
  261. package/dist/theme/theme-toggle.d.ts.map +1 -0
  262. package/dist/{theme-toggle/index.js → theme/theme-toggle.js} +1 -1
  263. package/dist/tokens/index.d.ts +1 -0
  264. package/dist/tokens/index.d.ts.map +1 -1
  265. package/dist/tokens/index.js +10 -0
  266. package/dist/tokens/palette.d.ts +12 -0
  267. package/dist/tokens/palette.d.ts.map +1 -1
  268. package/dist/tokens/palette.js +13 -1
  269. package/dist/tokens.css +1 -0
  270. package/llms.txt +9 -24
  271. package/package.json +12 -16
  272. package/src/agent/ai-sdk-transport.ts +11 -4
  273. package/src/agent/coalesce.ts +1 -1
  274. package/src/agent/merge.ts +1 -1
  275. package/src/agent/transport.ts +15 -2
  276. package/src/agent/use-agent-thread-runs.ts +65 -15
  277. package/src/agent-chat/index.ts +6 -4
  278. package/src/agent-chat/relative-time.ts +1 -1
  279. package/src/agent-chat/thread-detail-panel.tsx +1 -1
  280. package/src/agent-chat/thread-feed-row.tsx +105 -30
  281. package/src/agent-chat/thread-feed.tsx +51 -25
  282. package/src/agent-chat/thread-message.tsx +1 -1
  283. package/src/agent-chat/virtualize.ts +48 -0
  284. package/src/charts/index.ts +7 -10
  285. package/src/charts/kinds/BandStrip.tsx +1 -1
  286. package/src/charts/kinds/Bars.tsx +2 -5
  287. package/src/charts/kinds/DualPanel.tsx +4 -3
  288. package/src/charts/kinds/StackedArea.tsx +1 -1
  289. package/src/charts/kinds/ZonedLine.tsx +1 -4
  290. package/src/charts/primitives/Axes.tsx +49 -0
  291. package/src/charts/primitives/ChartCard.tsx +49 -6
  292. package/src/charts/primitives/ChartFrame.tsx +5 -1
  293. package/src/charts/primitives/ChartPending.tsx +14 -8
  294. package/src/charts/utils/format.ts +17 -186
  295. package/src/cli/audit-allows.ts +371 -0
  296. package/src/cli/check-theme.ts +197 -0
  297. package/src/cli/doctor.ts +331 -0
  298. package/src/cli/guard-hook.ts +115 -0
  299. package/src/cli/help.ts +101 -0
  300. package/src/cli/index.ts +269 -3439
  301. package/src/cli/init.ts +247 -0
  302. package/src/cli/sync.ts +324 -0
  303. package/src/cli/tokens-css.ts +252 -0
  304. package/src/commands/define-commands.ts +1 -1
  305. package/src/commands/define-overlays.ts +1 -1
  306. package/src/commands/index.ts +10 -1
  307. package/src/commands/overlays-mount.tsx +8 -10
  308. package/src/commands/shell-bridge.ts +86 -0
  309. package/src/common/errors.ts +70 -0
  310. package/src/common/index.ts +2 -0
  311. package/src/common/props.ts +1 -1
  312. package/src/common/validate.ts +1 -1
  313. package/src/content/markdown.tsx +4 -8
  314. package/src/controls/actions.tsx +1 -1
  315. package/src/controls/panel-row.tsx +1 -1
  316. package/src/controls/range-filter.tsx +1 -1
  317. package/src/dashboard/delta-badge.tsx +74 -7
  318. package/src/dashboard/empty-state.tsx +2 -6
  319. package/src/dashboard/index.ts +11 -2
  320. package/src/dashboard/query-state.tsx +5 -18
  321. package/src/{section → dashboard}/section.tsx +4 -4
  322. package/src/dashboard/settings-section.tsx +2 -2
  323. package/src/dashboard/stat-card.tsx +2 -2
  324. package/src/data/data-table.tsx +3 -3
  325. package/src/data/table.ts +6 -25
  326. package/src/data/virtual-list.tsx +1 -1
  327. package/src/data/virtual.ts +3 -3
  328. package/src/dev-dock.tsx +162 -0
  329. package/src/format/date.ts +184 -0
  330. package/src/format/index.ts +69 -0
  331. package/src/format/measure.ts +31 -0
  332. package/src/format/number.ts +129 -0
  333. package/src/format/shared.ts +63 -0
  334. package/src/forms/field.ts +4 -24
  335. package/src/forms/form-layout.tsx +2 -2
  336. package/src/forms/index.ts +1 -2
  337. package/src/forms/use-form-submit.ts +2 -2
  338. package/src/guard/index.ts +80 -69
  339. package/src/guard/types.ts +7 -10
  340. package/src/index.ts +38 -29
  341. package/src/notifications/index.ts +5 -7
  342. package/src/notifications/mount-guard.ts +7 -9
  343. package/src/{connectivity → provider}/connectivity-indicator.tsx +1 -1
  344. package/src/{connectivity → provider}/connectivity-provider.tsx +1 -1
  345. package/src/provider/error-fallback.module.css +21 -0
  346. package/src/provider/error-fallback.module.css.d.ts +9 -0
  347. package/src/provider/index.tsx +71 -71
  348. package/src/provider/lab-theme.ts +1 -1
  349. package/src/{connectivity → provider}/use-connectivity.ts +3 -3
  350. package/src/query-client.ts +105 -0
  351. package/src/{query/devtools.tsx → query-devtools.tsx} +5 -4
  352. package/src/register.ts +20 -4
  353. package/src/router-tanstack/index.ts +4 -15
  354. package/src/router-tanstack/nav.ts +1 -1
  355. package/src/router-tanstack/search-store.ts +3 -4
  356. package/src/router-tanstack/use-nav.ts +1 -1
  357. package/src/shell/app-breadcrumbs.tsx +1 -1
  358. package/src/shell/app-main.module.css +11 -0
  359. package/src/shell/app-mobile-nav.tsx +28 -1
  360. package/src/shell/app-sidebar.module.css +10 -0
  361. package/src/shell/app-sidebar.tsx +31 -2
  362. package/src/shell/index.tsx +23 -28
  363. package/src/shell/mobile-nav-model.ts +1 -1
  364. package/src/shell/page-aside.tsx +2 -52
  365. package/src/shell/page-title.module.css +33 -0
  366. package/src/shell/page-title.module.css.d.ts +11 -0
  367. package/src/shell/page-title.tsx +57 -0
  368. package/src/shell/sidebar-block-model.ts +1 -1
  369. package/src/shell/sidebar-blocks.tsx +1 -1
  370. package/src/shell/use-breakpoint.ts +73 -0
  371. package/src/state/fields.ts +7 -43
  372. package/src/styles.css +36 -0
  373. package/src/surfaces.ts +47 -61
  374. package/src/theme/index.ts +7 -0
  375. package/src/{theme-toggle/index.tsx → theme/theme-toggle.tsx} +1 -1
  376. package/src/tokens/index.ts +10 -0
  377. package/src/tokens/palette.ts +12 -0
  378. package/dist/connectivity/connectivity-indicator.d.ts.map +0 -1
  379. package/dist/connectivity/connectivity-provider.d.ts.map +0 -1
  380. package/dist/connectivity/index.d.ts +0 -14
  381. package/dist/connectivity/index.d.ts.map +0 -1
  382. package/dist/connectivity/index.js +0 -8
  383. package/dist/connectivity/types.d.ts.map +0 -1
  384. package/dist/connectivity/use-connectivity.d.ts +0 -3
  385. package/dist/connectivity/use-connectivity.d.ts.map +0 -1
  386. package/dist/data/index.d.ts +0 -38
  387. package/dist/data/index.d.ts.map +0 -1
  388. package/dist/data/index.js +0 -24
  389. package/dist/motion/index.d.ts.map +0 -1
  390. package/dist/nav/types.d.ts.map +0 -1
  391. package/dist/notifications/overlay.d.ts +0 -20
  392. package/dist/notifications/overlay.d.ts.map +0 -1
  393. package/dist/notifications/overlay.js +0 -14
  394. package/dist/query/devtools.d.ts.map +0 -1
  395. package/dist/query/error-message.d.ts +0 -41
  396. package/dist/query/error-message.d.ts.map +0 -1
  397. package/dist/query/error-message.js +0 -30
  398. package/dist/query/index.d.ts +0 -47
  399. package/dist/query/index.d.ts.map +0 -1
  400. package/dist/query/index.js +0 -56
  401. package/dist/router-tanstack/field.d.ts +0 -14
  402. package/dist/router-tanstack/field.d.ts.map +0 -1
  403. package/dist/router-tanstack/field.js +0 -4
  404. package/dist/router-tanstack/multi-search-param-store.d.ts +0 -43
  405. package/dist/router-tanstack/multi-search-param-store.d.ts.map +0 -1
  406. package/dist/router-tanstack/multi-search-param-store.js +0 -30
  407. package/dist/router-tanstack/search-param-store.d.ts +0 -42
  408. package/dist/router-tanstack/search-param-store.d.ts.map +0 -1
  409. package/dist/router-tanstack/search-param-store.js +0 -25
  410. package/dist/section/index.d.ts +0 -2
  411. package/dist/section/index.d.ts.map +0 -1
  412. package/dist/section/index.js +0 -4
  413. package/dist/theme-toggle/index.d.ts.map +0 -1
  414. package/dist/utils/is-dev.d.ts.map +0 -1
  415. package/dist/widget-header/delta-badge.d.ts +0 -19
  416. package/dist/widget-header/delta-badge.d.ts.map +0 -1
  417. package/dist/widget-header/delta-badge.js +0 -36
  418. package/dist/widget-header/index.d.ts +0 -3
  419. package/dist/widget-header/index.d.ts.map +0 -1
  420. package/dist/widget-header/index.js +0 -8
  421. package/dist/widget-header/widget-header.d.ts.map +0 -1
  422. package/src/connectivity/index.ts +0 -19
  423. package/src/data/index.ts +0 -69
  424. package/src/notifications/overlay.tsx +0 -66
  425. package/src/query/error-message.ts +0 -70
  426. package/src/query/index.ts +0 -97
  427. package/src/router-tanstack/field.ts +0 -36
  428. package/src/router-tanstack/multi-search-param-store.ts +0 -106
  429. package/src/router-tanstack/search-param-store.ts +0 -100
  430. package/src/section/index.ts +0 -1
  431. package/src/widget-header/delta-badge.tsx +0 -77
  432. package/src/widget-header/index.ts +0 -10
  433. /package/dist/{utils → common}/is-dev.d.ts +0 -0
  434. /package/dist/{utils → common}/is-dev.js +0 -0
  435. /package/dist/{motion/index.js → common/motion.js} +0 -0
  436. /package/dist/{section → dashboard}/section.module.css +0 -0
  437. /package/dist/{section → dashboard}/section.module.css.d.ts +0 -0
  438. /package/dist/{widget-header → dashboard}/widget-header.d.ts +0 -0
  439. /package/dist/{widget-header → dashboard}/widget-header.js +0 -0
  440. /package/dist/{widget-header → dashboard}/widget-header.module.css +0 -0
  441. /package/dist/{widget-header → dashboard}/widget-header.module.css.d.ts +0 -0
  442. /package/dist/{connectivity → provider}/connectivity-indicator.d.ts +0 -0
  443. /package/dist/{connectivity → provider}/connectivity-indicator.js +0 -0
  444. /package/dist/{connectivity → provider}/connectivity-provider.js +0 -0
  445. /package/dist/{connectivity/types.js → provider/connectivity-types.js} +0 -0
  446. /package/dist/{connectivity → provider}/use-connectivity.js +0 -0
  447. /package/dist/{query/devtools.js → query-devtools.js} +0 -0
  448. /package/dist/{nav/types.js → shell/nav-types.js} +0 -0
  449. /package/src/{utils → common}/is-dev.ts +0 -0
  450. /package/src/{motion/index.ts → common/motion.ts} +0 -0
  451. /package/src/{section → dashboard}/section.module.css +0 -0
  452. /package/src/{section → dashboard}/section.module.css.d.ts +0 -0
  453. /package/src/{widget-header → dashboard}/widget-header.module.css +0 -0
  454. /package/src/{widget-header → dashboard}/widget-header.module.css.d.ts +0 -0
  455. /package/src/{widget-header → dashboard}/widget-header.tsx +0 -0
  456. /package/src/{connectivity/types.ts → provider/connectivity-types.ts} +0 -0
  457. /package/src/{nav/types.ts → shell/nav-types.ts} +0 -0
@@ -1,10 +1,77 @@
1
1
  /**
2
- * `DeltaBadge` moved to `src/widget-header/` (docs/CONTROLS-SPEC.md §2.2) so `WidgetHeader` can
3
- * compose it Mantine-free. Re-exported here unchanged so this deep import path — and `StatCard`'s
4
- * own `./delta-badge` import — keep working without a wave-3 edit.
2
+ * DeltaBadge — the KPI trend chip (docs/DESIGN-SPEC.md §5): mono 11.5px weight 600, status-color
3
+ * text on a status-13% tint, control radius, 2px/7px padding, optional ▲/▼ glyph at 9px.
4
+ * `polarity` decides the TONE the sign maps to — `'up-good'` (default) reads a rise as success and
5
+ * a fall as danger; `'up-bad'` inverts that for a metric where a rise is the worse reading (a
6
+ * cycle-top index, latency, error rate); `'neutral'` renders every sign in a faint, non-verdict
7
+ * tint. Zero is always faint with no glyph, under every polarity. The label never carries a
8
+ * leading "+"; pass `format` to control the magnitude string (defaults to a one-decimal percentage
9
+ * of the absolute value). The ▲/▼ glyph is DIRECTION, not verdict, and stays polarity-independent —
10
+ * governed only by `withGlyph` and the sign.
5
11
  *
6
- * `basalt-ui/widget-header` is canonical — this alias exists only so `basalt-ui/dashboard`-style
7
- * deep imports keep resolving; the root barrel (`src/index.ts`) sources `DeltaBadge` from
8
- * `../widget-header`, not from here.
12
+ * Mantine-free (plain `<span>` + this folder's CSS module, docs/CONTROLS-SPEC.md §2.2) so
13
+ * `WidgetHeader` can compose it from inside `charts/` without tripping `basalt/token-layer-
14
+ * boundary` or `check-dist-layering.mjs`.
15
+ *
16
+ * @example
17
+ * import { DeltaBadge } from 'basalt-ui'
18
+ *
19
+ * <DeltaBadge value={12.4} /> // ▲ 12.4%, success tint
20
+ * <DeltaBadge value={-3.1} /> // ▼ 3.1%, danger tint
21
+ * <DeltaBadge value={0} /> // 0.0%, neutral faint tint, no glyph
22
+ * <DeltaBadge value={182} format={(v) => `${Math.abs(v)}ms`} withGlyph={false} />
23
+ * <DeltaBadge value={35.9} polarity="up-bad" /> // ▲ 35.9%, danger tint — a rise is bad here
9
24
  */
10
- export { DeltaBadge, type DeltaBadgeProps, type DeltaPolarity } from '../widget-header/delta-badge'
25
+ import { alpha, VX } from '../tokens'
26
+ import classes from './widget-header.module.css'
27
+
28
+ export type DeltaPolarity = 'up-good' | 'up-bad' | 'neutral'
29
+
30
+ export type DeltaBadgeProps = {
31
+ /** Signed delta driving tone (positive/negative/zero) and, by default, the label magnitude. */
32
+ value: number
33
+ /** Which sign reads as the good verdict. `'up-good'` (default) is today's behaviour — positive
34
+ * success, negative danger. `'up-bad'` inverts it for a metric where a rise is the worse reading.
35
+ * `'neutral'` renders every sign in the faint tint — a change with no verdict attached. Zero is
36
+ * always faint regardless. */
37
+ polarity?: DeltaPolarity
38
+ /** Formats the value into the label text. Defaults to `${Math.abs(value).toFixed(1)}%`. */
39
+ format?: (value: number) => string
40
+ /** Render the ▲/▼ direction glyph. Defaults to `true`; a zero value never shows a glyph. */
41
+ withGlyph?: boolean
42
+ /** Optional comparison timeframe rendered directly after the value in a dimmer shade of the same
43
+ * tone (e.g. `MoM`, `WoW`, `YTD`) — states what the delta is measured against without a hover. */
44
+ period?: string | undefined
45
+ }
46
+
47
+ const defaultFormat = (value: number): string => `${Math.abs(value).toFixed(1)}%`
48
+
49
+ function resolveTone(value: number, polarity: DeltaPolarity): string {
50
+ if (value === 0 || polarity === 'neutral') return VX.faint
51
+ const rose = value > 0
52
+ const good = polarity === 'up-good' ? rose : !rose
53
+ return good ? VX.status.good : VX.status.bad
54
+ }
55
+
56
+ export function DeltaBadge({
57
+ value,
58
+ polarity = 'up-good',
59
+ format = defaultFormat,
60
+ withGlyph = true,
61
+ period,
62
+ }: DeltaBadgeProps) {
63
+ const tone = resolveTone(value, polarity)
64
+ const glyph = value > 0 ? '▲' : value < 0 ? '▼' : undefined
65
+ const showGlyph = withGlyph && glyph !== undefined
66
+
67
+ return (
68
+ <span
69
+ className={classes.deltaBadge}
70
+ style={{ backgroundColor: alpha(tone, 0.13), color: tone }}
71
+ >
72
+ {showGlyph && <span className={classes.deltaGlyph}>{glyph}</span>}
73
+ {format(value)}
74
+ {period !== undefined && <span className={classes.deltaPeriod}>{period}</span>}
75
+ </span>
76
+ )
77
+ }
@@ -2,7 +2,7 @@
2
2
  * EmptyState — a centered icon/title/description/action stack for empty data regions (no shipped
3
3
  * illustration assets — `icon` is a plain, faint-rendered `ReactNode` slot). `tier="page"` uses
4
4
  * generous vertical padding for a full-page empty state; `tier="section"` is compact, for an
5
- * empty card/panel region (`variant` is the deprecated spelling of the same prop — audit B #19).
5
+ * empty card/panel region.
6
6
  *
7
7
  * @example
8
8
  * import { EmptyState } from 'basalt-ui'
@@ -41,9 +41,6 @@ export type EmptyStateProps = BasaltProps &
41
41
  /** How loud this state is: `'page'` (default) = generous padding for a full-page state;
42
42
  * `'section'` = compact. */
43
43
  tier?: 'page' | 'section'
44
- /** @deprecated Renamed to `tier` (audit B #19) — `tier` is the package's word for "how loud is
45
- * this". Still honoured; `tier` wins when both are passed. */
46
- variant?: 'page' | 'section'
47
44
  }
48
45
 
49
46
  // The finest density-tracking rhythm step (`--vx-space-stack-xs`, 4px at level 0) scaled by an
@@ -63,12 +60,11 @@ export function EmptyState({
63
60
  description,
64
61
  action,
65
62
  tier,
66
- variant,
67
63
  className,
68
64
  style,
69
65
  classNames,
70
66
  }: EmptyStateProps) {
71
- const resolved = tier ?? variant ?? 'page'
67
+ const resolved = tier ?? 'page'
72
68
  return (
73
69
  <Stack
74
70
  align="center"
@@ -1,4 +1,14 @@
1
- export { DeltaBadge, type DeltaBadgeProps } from './delta-badge'
1
+ export {
2
+ WidgetHeader,
3
+ type WidgetHeaderDeltaProps,
4
+ type WidgetHeaderMetricProps,
5
+ type WidgetHeaderProps,
6
+ type WidgetHeaderSlot,
7
+ type WidgetHeaderTier,
8
+ type WidgetHeaderTitleProps,
9
+ } from './widget-header'
10
+ export { DeltaBadge, type DeltaBadgeProps, type DeltaPolarity } from './delta-badge'
11
+ export { Section, type SectionProps, type SectionSlot } from './section'
2
12
  export {
3
13
  StatCard,
4
14
  type StatCardBreakdownRow,
@@ -30,7 +40,6 @@ export {
30
40
  type QueryStateLike,
31
41
  type QueryStateSlot,
32
42
  type QueryStateTier,
33
- type QueryStateVariant,
34
43
  type QueryEmptyCopy,
35
44
  LoadingState,
36
45
  type LoadingStateProps,
@@ -16,7 +16,7 @@
16
16
  */
17
17
  import { Alert, Button, Center, Group, Loader, Stack, Text } from '@mantine/core'
18
18
  import type { CSSProperties, ReactNode } from 'react'
19
- import { toErrorMessage } from '../query/error-message'
19
+ import { toErrorMessage } from '../common/errors'
20
20
  import { cx } from '../common/props'
21
21
  import type { BasaltProps, SlotStylesProps } from '../common/props'
22
22
  import { EmptyState } from './empty-state'
@@ -29,14 +29,10 @@ import type { QueryStateLike } from '../common/query-state-like'
29
29
  *
30
30
  * Named `tier`, not `variant` (audit B #19): `tier` is already the package's word for "how loud is
31
31
  * this" on `WidgetHeader` and `CtlSlot`, and `'section'` meant two different things across the two
32
- * spellings. {@link QueryStateVariant} stays exported as an alias — nothing is renamed out from
33
- * under a consumer.
32
+ * spellings.
34
33
  */
35
34
  export type QueryStateTier = 'page' | 'section'
36
35
 
37
- /** The former name of {@link QueryStateTier}. Kept as an alias; prefer `QueryStateTier`. */
38
- export type QueryStateVariant = QueryStateTier
39
-
40
36
  /**
41
37
  * The structural subset of a TanStack `UseQueryResult` these components read — defined in
42
38
  * `common/query-state-like.ts` and re-exported here, where consumers have always imported it from.
@@ -61,8 +57,6 @@ export type QueryEmptyCopy = {
61
57
  export type LoadingStateProps = BasaltProps & {
62
58
  /** How loud this state is. Default `'page'`. */
63
59
  tier?: QueryStateTier
64
- /** @deprecated Renamed to `tier` — see {@link QueryStateTier}. Still honoured; `tier` wins. */
65
- variant?: QueryStateTier
66
60
  /** Accessible name for the spinner. Say what is loading. */
67
61
  label?: string
68
62
  }
@@ -70,12 +64,11 @@ export type LoadingStateProps = BasaltProps & {
70
64
  /** A spinner on its own — `tier="page"` centres it in a generous block, `'section'` is bare. */
71
65
  export function LoadingState({
72
66
  tier,
73
- variant,
74
67
  label = 'Loading',
75
68
  className,
76
69
  style,
77
70
  }: LoadingStateProps): ReactNode {
78
- const resolved = tier ?? variant ?? 'page'
71
+ const resolved = tier ?? 'page'
79
72
  if (resolved === 'section') {
80
73
  return (
81
74
  <Loader
@@ -113,8 +106,6 @@ export type ErrorStateProps = BasaltProps & {
113
106
  retrying?: boolean
114
107
  /** How loud this state is. Default `'page'`. */
115
108
  tier?: QueryStateTier
116
- /** @deprecated Renamed to `tier` — see {@link QueryStateTier}. Still honoured; `tier` wins. */
117
- variant?: QueryStateTier
118
109
  /** Extra controls beside Retry (e.g. a "Back to shares" link). */
119
110
  action?: ReactNode
120
111
  }
@@ -130,12 +121,11 @@ export function ErrorState({
130
121
  onRetry,
131
122
  retrying = false,
132
123
  tier,
133
- variant,
134
124
  action,
135
125
  className,
136
126
  style,
137
127
  }: ErrorStateProps): ReactNode {
138
- const resolved = tier ?? variant ?? 'page'
128
+ const resolved = tier ?? 'page'
139
129
  const alert = (
140
130
  <Alert
141
131
  color="red"
@@ -212,8 +202,6 @@ export type QueryStateProps<TData> = BasaltProps &
212
202
  errorAction?: ReactNode
213
203
  /** How loud every branch is. Default `'page'`. */
214
204
  tier?: QueryStateTier
215
- /** @deprecated Renamed to `tier` — see {@link QueryStateTier}. Still honoured; `tier` wins. */
216
- variant?: QueryStateTier
217
205
  /** Replace the default spinner (e.g. with a skeleton grid). */
218
206
  loading?: ReactNode
219
207
  }
@@ -246,14 +234,13 @@ export function QueryState<TData>({
246
234
  errorFallback = 'The request failed.',
247
235
  errorAction,
248
236
  tier,
249
- variant,
250
237
  loading,
251
238
  className,
252
239
  style,
253
240
  classNames,
254
241
  }: QueryStateProps<TData>): ReactNode {
255
242
  assertQueryStateLike('QueryState', query)
256
- const resolvedTier = tier ?? variant ?? 'page'
243
+ const resolvedTier = tier ?? 'page'
257
244
  // One class for every branch — see {@link QueryStateSlot}. `cx` returns `''` when both are
258
245
  // absent, and an empty `className` on a branch that previously carried none would be a DOM diff,
259
246
  // so it collapses back to `undefined`.
@@ -56,11 +56,11 @@ import { CtlSlot } from '../theme'
56
56
  import { BarActionSlot, isBarActionList } from '../controls/actions'
57
57
  import type { SlotActions } from '../controls/actions'
58
58
  import { useFilterSurface } from '../controls/filter-context'
59
- import { QueryState } from '../dashboard/query-state'
60
- import type { QueryEmptyCopy, QueryStateLike } from '../dashboard/query-state'
59
+ import { QueryState } from './query-state'
60
+ import type { QueryEmptyCopy, QueryStateLike } from './query-state'
61
61
  import { usePersistedOrLocal } from '../state/persisted-or-local'
62
- import { WidgetHeader } from '../widget-header'
63
- import type { WidgetHeaderProps } from '../widget-header'
62
+ import { WidgetHeader } from './widget-header'
63
+ import type { WidgetHeaderProps } from './widget-header'
64
64
  import classes from './section.module.css'
65
65
 
66
66
  /**
@@ -30,8 +30,8 @@
30
30
  */
31
31
  import { Card, Stack } from '@mantine/core'
32
32
  import type { ReactNode } from 'react'
33
- import { WidgetHeader } from '../widget-header'
34
- import type { WidgetHeaderTitleProps } from '../widget-header'
33
+ import { WidgetHeader } from './widget-header'
34
+ import type { WidgetHeaderTitleProps } from './widget-header'
35
35
  import { CtlSlot } from '../theme'
36
36
  import { alpha, VX } from '../tokens'
37
37
  import { cx } from '../common/props'
@@ -95,12 +95,12 @@
95
95
  import { Box, Card, VisuallyHidden } from '@mantine/core'
96
96
  import { useEffect, useRef, useState } from 'react'
97
97
  import type { CSSProperties, ReactNode } from 'react'
98
- import { WidgetHeader } from '../widget-header'
98
+ import { WidgetHeader } from './widget-header'
99
99
  import type {
100
100
  WidgetHeaderDeltaProps,
101
101
  WidgetHeaderMetricProps,
102
102
  WidgetHeaderTitleProps,
103
- } from '../widget-header'
103
+ } from './widget-header'
104
104
  import { CtlSlot } from '../theme'
105
105
  import { VX } from '../tokens'
106
106
  import { cx } from '../common/props'
@@ -9,7 +9,7 @@
9
9
  * exactly as before.
10
10
  *
11
11
  * @example
12
- * import { BasaltDataTable } from 'basalt-ui/data'
12
+ * import { BasaltDataTable } from 'basalt-ui/data/table'
13
13
  * import { createColumnHelper } from '@tanstack/react-table'
14
14
  *
15
15
  * type Row = { name: string; age: number }
@@ -88,11 +88,11 @@ import { MultiSelectFilter } from '../controls/multi-select-filter'
88
88
  import { CtlSlot } from '../theme'
89
89
  import { alpha, VX } from '../tokens'
90
90
  import type { EnumField, FieldHandle, MultiField } from '../state'
91
- import { WidgetHeader } from '../widget-header'
91
+ import { WidgetHeader } from '../dashboard'
92
92
  import { ErrorState } from '../dashboard/query-state'
93
93
  import type { QueryStateLike } from '../dashboard/query-state'
94
94
  import { dataQueryBranch } from './query-branch'
95
- import { isDev } from '../utils/is-dev'
95
+ import { isDev } from '../common/is-dev'
96
96
  import classes from './data-table.module.css'
97
97
 
98
98
  // ── Column alignment ──────────────────────────────────────────────────────────
package/src/data/table.ts CHANGED
@@ -31,28 +31,9 @@ export type {
31
31
  DataTableFacetOption,
32
32
  } from './data-table'
33
33
 
34
- // ── @tanstack/react-table convenience re-exports ──────────────────────────────
35
- // These are the handful of table primitives a consumer needs at the call site;
36
- // importing them from basalt-ui/data/table avoids a separate @tanstack/react-table import.
37
- // useReactTable + flexRender + the row-model builders (getCoreRowModel/getSortedRowModel/
38
- // getFilteredRowModel/getPaginationRowModel) are the raw escape hatch: a bespoke, fully custom
39
- // table can be built from this subpath alone, with no direct @tanstack/react-table import in
40
- // consumer code.
41
- export {
42
- createColumnHelper,
43
- useReactTable,
44
- flexRender,
45
- getCoreRowModel,
46
- getSortedRowModel,
47
- getFilteredRowModel,
48
- getPaginationRowModel,
49
- type ColumnDef,
50
- type SortingState,
51
- type ColumnHelper,
52
- type PaginationState,
53
- type ColumnPinningState,
54
- // The selection map `rowSelection`/`onRowSelectionChange` speak — `Record<rowId, boolean>`.
55
- type RowSelectionState,
56
- // The type `onColumnFiltersChange` hands back — needed at the call site for server-side faceting.
57
- type ColumnFiltersState,
58
- } from '@tanstack/react-table'
34
+ // ── @tanstack/react-table convenience re-export ───────────────────────────────
35
+ // `createColumnHelper` is the one raw TanStack symbol every `BasaltDataTable` call site needs to
36
+ // build its `columns` array (C1 consolidation: every OTHER pass-through — `useReactTable`,
37
+ // `flexRender`, the row-model builders, and the type re-exports — was unused by any consumer;
38
+ // import TanStack directly for those).
39
+ export { createColumnHelper } from '@tanstack/react-table'
@@ -5,7 +5,7 @@
5
5
  * set by ./agent-chat's virtualize mode (see ./data/index.ts), so do not lower it.
6
6
  *
7
7
  * @example
8
- * import { BasaltVirtualList } from 'basalt-ui/data'
8
+ * import { BasaltVirtualList } from 'basalt-ui/data/virtual'
9
9
  *
10
10
  * const items = Array.from({ length: 10_000 }, (_, i) => ({ id: i, label: `Row ${i}` }))
11
11
  * <BasaltVirtualList
@@ -3,10 +3,10 @@
3
3
  * rendered with a Mantine Box scroll container.
4
4
  *
5
5
  * Optional peer: @tanstack/react-virtual >=3.13.26 <4. This list works on any 3.x — the floor is
6
- * set by ./agent-chat's virtualize mode (see ./data/index.ts), so do not lower it.
6
+ * set by ./agent-chat's virtualize mode, so do not lower it.
7
7
  *
8
- * Use this fine subpath instead of the `./data` barrel when your app only needs the virtual list
9
- * — it does NOT value-import @tanstack/react-table, so the data-table peer is never required.
8
+ * This subpath does NOT value-import @tanstack/react-table, so the data-table peer is never
9
+ * required — use `./data/table` when your app only needs the table.
10
10
  *
11
11
  * Install with:
12
12
  * bun add @tanstack/react-virtual
@@ -0,0 +1,162 @@
1
+ /**
2
+ * `BasaltDevDock` — a fixed, dev-only bottom drawer hosting the in-app tooling: TanStack Router
3
+ * devtools, TanStack Query devtools (the embeddable `ReactQueryDevtoolsPanel` — NOT
4
+ * `BasaltQueryDevtools`, which wraps the floating-button `ReactQueryDevtools` and would duplicate
5
+ * this dock's own chrome), and the theme lab (`basalt-ui/theme-lab`'s `ThemeLabControls`). Ported
6
+ * from argo's `components/dev-dock.tsx` (91 lines) — same three-tool shape, same "only renders the
7
+ * ACTIVE panel" contract: the launcher (which tool is open) lives wherever the consumer puts it —
8
+ * a `SettingsMenuItem` per tool with `active` set to the currently-open one (C5's
9
+ * `SettingsMenuItem.active`) is the seeded pattern — this component owns only the render.
10
+ *
11
+ * Every dependency is an OPTIONAL peer, loaded lazily so importing (or even rendering, with
12
+ * `tool={null}`) this module never requires `@tanstack/react-router-devtools`,
13
+ * `@tanstack/react-query-devtools` or `@tanstack/react-router` unless a consumer actually opens
14
+ * that tool — same discipline as `BasaltQueryDevtools` (`query-devtools.tsx`) and
15
+ * `ThemeLabControls`'s own `React.lazy` wrapper here. In production this returns `null`
16
+ * immediately, before any dynamic import fires.
17
+ *
18
+ * @example
19
+ * import { BasaltDevDock, type BasaltDevDockTool } from 'basalt-ui'
20
+ * import { useState } from 'react'
21
+ * import { useRouter } from '@tanstack/react-router'
22
+ *
23
+ * function DevTools() {
24
+ * const [tool, setTool] = useState<BasaltDevDockTool | null>(null)
25
+ * const router = useRouter()
26
+ * return <BasaltDevDock tool={tool} onClose={() => setTool(null)} router={router} />
27
+ * }
28
+ * // wire the launchers as settings-menu entries with `active: tool === 'router'` etc.
29
+ */
30
+ import { lazy, Suspense } from 'react'
31
+ import type { ReactNode } from 'react'
32
+ import { Box, CloseButton, Flex, Group, Text } from '@mantine/core'
33
+ import type { BasaltProps } from './common/props'
34
+ import type { ThemeLabControlsProps } from './theme-lab'
35
+
36
+ /** Which panel is open. `null` renders nothing (the dock is unmounted, not hidden). */
37
+ export type BasaltDevDockTool = 'router' | 'query' | 'theme'
38
+
39
+ const TOOL_TITLE: Record<BasaltDevDockTool, string> = {
40
+ router: 'Router Devtools',
41
+ query: 'Query Devtools',
42
+ theme: 'Theme Lab',
43
+ }
44
+
45
+ // Any non-null object — avoids a hard, eager type dependency on `@tanstack/react-router` for a
46
+ // consumer who never renders the `'router'` tool, while still accepting a REAL `Router` class
47
+ // instance with no cast. A narrower structural type (matching a `Router` field, or falling back
48
+ // to `Record<string, unknown>`) used to reject that instance under TS weak-type detection: a
49
+ // class instance declares no index signature, so it has no excess-property overlap with either
50
+ // branch. `TanStackRouterDevtoolsPanel` itself takes the real (much wider) `AnyRouter` type; the
51
+ // devtools panel is the only reader of this prop, so `object` is exactly as wide as it needs to be.
52
+ type DevDockRouter = object
53
+
54
+ const LazyRouterDevtoolsPanel = lazy(() =>
55
+ import('@tanstack/react-router-devtools').then((m) => ({
56
+ default: m.TanStackRouterDevtoolsPanel,
57
+ })),
58
+ )
59
+ Object.assign(LazyRouterDevtoolsPanel, { displayName: 'LazyRouterDevtoolsPanel' })
60
+
61
+ // The embeddable PANEL, not `ReactQueryDevtools` (`BasaltQueryDevtools`'s own wrapped export) —
62
+ // that one renders its own floating trigger button + auto-popup shell, which would duplicate the
63
+ // dock's own chrome. `query-devtools.tsx`'s `BasaltQueryDevtools` stays the answer for a consumer
64
+ // who wants the traditional floating-button devtools instead of a dock tab.
65
+ const LazyQueryDevtoolsPanel = lazy(() =>
66
+ import('@tanstack/react-query-devtools').then((m) => ({ default: m.ReactQueryDevtoolsPanel })),
67
+ )
68
+ Object.assign(LazyQueryDevtoolsPanel, { displayName: 'LazyQueryDevtoolsPanel' })
69
+
70
+ const LazyThemeLabControls = lazy(() =>
71
+ import('./theme-lab').then((m) => ({ default: m.ThemeLabControls })),
72
+ )
73
+ Object.assign(LazyThemeLabControls, { displayName: 'LazyThemeLabControls' })
74
+
75
+ export type BasaltDevDockProps = BasaltProps & {
76
+ /** Which panel to show. `null` renders nothing. */
77
+ tool: BasaltDevDockTool | null
78
+ /** Called when the dock's own close button fires, or a hosted panel asks to close itself
79
+ * (the router devtools' own `setIsOpen`, the query devtools' own `onClose`). */
80
+ onClose: () => void
81
+ /** The active TanStack `Router` instance — required only to render the `'router'` tool; a
82
+ * consumer that never opens it may omit this entirely. */
83
+ router?: DevDockRouter
84
+ /** Forwarded to the hosted `ThemeLabControls` (icons, the copy callback — see its own props). */
85
+ themeLab?: ThemeLabControlsProps
86
+ }
87
+
88
+ /**
89
+ * Lazy, production-excluded dock. Safe to mount unconditionally with `tool={null}` — the dynamic
90
+ * imports for whichever peer a tool needs only fire once that tool is actually selected, and
91
+ * never at all in production.
92
+ */
93
+ export function BasaltDevDock({
94
+ tool,
95
+ onClose,
96
+ router,
97
+ themeLab,
98
+ className,
99
+ style,
100
+ }: BasaltDevDockProps): ReactNode {
101
+ if (process.env['NODE_ENV'] === 'production') return null
102
+ if (tool === null) return null
103
+
104
+ return (
105
+ <Flex
106
+ direction="column"
107
+ {...(className !== undefined && { className })}
108
+ style={{
109
+ position: 'fixed',
110
+ left: 0,
111
+ right: 0,
112
+ bottom: 0,
113
+ height: '42vh',
114
+ zIndex: 400,
115
+ background: 'var(--mantine-color-body)',
116
+ borderTop: '1px solid var(--mantine-color-default-border)',
117
+ // Floating tier: a fixed dock sits above the page like a menu/drawer, so it takes
118
+ // basalt's overlay depth token rather than Mantine's raw shadow ramp.
119
+ boxShadow: 'var(--vx-shadow-overlay)',
120
+ ...style,
121
+ }}
122
+ >
123
+ <Group
124
+ justify="space-between"
125
+ px="sm"
126
+ py={6}
127
+ style={{ borderBottom: '1px solid var(--mantine-color-default-border)' }}
128
+ >
129
+ <Text size="xs" fw={600} tt="uppercase" c="dimmed">
130
+ {TOOL_TITLE[tool]}
131
+ </Text>
132
+ <CloseButton size="sm" onClick={onClose} aria-label="Close devtools" />
133
+ </Group>
134
+ {/* theme-allow raw-scroll-container — hosts third-party devtools panels sized to
135
+ height: 100%; they need a real overflow ancestor, not ScrollArea's custom viewport. */}
136
+ <Box style={{ flex: 1, minHeight: 0, overflow: 'auto' }}>
137
+ <Suspense fallback={null}>
138
+ {tool === 'router' && router !== undefined && (
139
+ <LazyRouterDevtoolsPanel
140
+ // The devtools panel's own `router` prop takes the real `AnyRouter` type;
141
+ // `DevDockRouter` is deliberately the widest structural stand-in (`object`) so this
142
+ // module never eagerly imports the router's types.
143
+ // oxlint-disable-next-line typescript/no-explicit-any -- see above
144
+ router={router as any}
145
+ isOpen
146
+ setIsOpen={onClose}
147
+ style={{ height: '100%' }}
148
+ />
149
+ )}
150
+ {tool === 'query' && (
151
+ <LazyQueryDevtoolsPanel onClose={onClose} style={{ height: '100%' }} />
152
+ )}
153
+ {tool === 'theme' && (
154
+ <Box p="md">
155
+ <LazyThemeLabControls {...themeLab} />
156
+ </Box>
157
+ )}
158
+ </Suspense>
159
+ </Box>
160
+ </Flex>
161
+ )
162
+ }