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
@@ -0,0 +1,4 @@
1
+ import type { ScaffoldFlags } from './index.js';
2
+ /** Scaffold all managed files into the consumer repo, then write the manifest. Idempotent. Returns 0. */
3
+ export declare function init(cwd?: string, scaffoldFlags?: ScaffoldFlags): number;
4
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,SAAS,CAAA;AA4C7D,yGAAyG;AACzG,wBAAgB,IAAI,CAAC,GAAG,GAAE,MAAsB,EAAE,aAAa,GAAE,aAAkB,GAAG,MAAM,CAgM3F"}
@@ -0,0 +1,165 @@
1
+ import { existsSync } from "node:fs";
2
+ import { relative, resolve } from "node:path";
3
+ import { deriveSpacing } from "../tokens/index.js";
4
+ import {
5
+ MANIFEST_PATH,
6
+ findBasaltInstall,
7
+ managedFiles,
8
+ mergeOxlintExtends,
9
+ normalizeForLedger,
10
+ patchPackageJson,
11
+ pruneRetiredManagedFiles,
12
+ readManifest,
13
+ reconcileRoots,
14
+ relativePosix,
15
+ renderContext,
16
+ reportPrune,
17
+ resolvePeerFlags,
18
+ resolvePlacement,
19
+ rootsNotices,
20
+ sha256,
21
+ shippedAssetPath,
22
+ unitState,
23
+ writeFileEnsuringDir,
24
+ writeUnit
25
+ } from "./index.js";
26
+ import { readOxlintPresetPlugins } from "./sync.js";
27
+ const KEPT_FILE_COST = {
28
+ ".oxlintrc.json": "the shipped oxlint preset (the basalt/* design rules AND the jsx-a11y / import / promise / unicorn plugins) is NOT active \u2014 nothing else turns it on, and every gate stays green without it. Re-run with `--merge-lint` to splice the extends in, or add it by hand.",
29
+ "lefthook.yml": "the pre-commit oxlint / oxfmt / check-theme jobs are not wired \u2014 add `extends: [<preset>]` to your own file.",
30
+ ".github/workflows/check.yml": "CI does not run check-theme or the sync drift gate \u2014 copy those steps into your own workflow.",
31
+ ".oxfmtrc.json": "your existing formatter config stands; basalt formats nothing on its own.",
32
+ "DESIGN.md": "the design brief Claude reads is yours, not the seeded one."
33
+ };
34
+ function init(cwd = process.cwd(), scaffoldFlags = {}) {
35
+ const install = findBasaltInstall(cwd);
36
+ if (install.dir === null) {
37
+ console.error(
38
+ `\u26A0 basalt-ui init: basalt-ui does not resolve from ${cwd} or any directory above it \u2014 the seeded \`extends\` paths and CI steps are being written against the repo root by assumption. Install basalt-ui here (or at the repo root) and re-run \`basalt-ui init\` so they resolve.`
39
+ );
40
+ }
41
+ const rootsState = reconcileRoots(cwd, { write: true });
42
+ const ctx = renderContext(cwd);
43
+ const lintScript = `oxlint . && ${ctx.vars.BASALT_BIN} check-theme`;
44
+ const seededLintScript = patchPackageJson(cwd, (pkg) => {
45
+ const scripts = pkg["scripts"] ?? {};
46
+ if (scripts["lint:basalt"] !== void 0) return false;
47
+ pkg["scripts"] = { ...scripts, "lint:basalt": lintScript };
48
+ return true;
49
+ });
50
+ const manifest = readManifest(cwd);
51
+ const peers = resolvePeerFlags(cwd, scaffoldFlags);
52
+ const placement = resolvePlacement(cwd);
53
+ const files = managedFiles(peers, placement);
54
+ const writtenFiles = [];
55
+ const keptFiles = [];
56
+ const missingSources = [];
57
+ for (const file of files) {
58
+ const state = unitState(file, cwd, ctx);
59
+ if (state.desired === null) {
60
+ missingSources.push(file.source);
61
+ continue;
62
+ }
63
+ const destExists = existsSync(resolve(cwd, file.dest));
64
+ if (!file.markers && destExists) {
65
+ manifest.files[file.dest] = sha256(normalizeForLedger(state.desired));
66
+ keptFiles.push(file.dest);
67
+ continue;
68
+ }
69
+ const hash = writeUnit(file, cwd, state.desired);
70
+ manifest.files[file.dest] = hash;
71
+ writtenFiles.push(file.dest);
72
+ }
73
+ const pruned = pruneRetiredManagedFiles(cwd, manifest, files);
74
+ const mergeLint = scaffoldFlags.mergeLint === true ? mergeOxlintExtends(cwd, ctx.vars.OXLINT_PRESET_PATH) : null;
75
+ manifest.basaltVersion = ctx.vars.BASALT_VERSION;
76
+ manifest.spacingScale = { ...deriveSpacing(0).scale };
77
+ writeFileEnsuringDir(resolve(cwd, MANIFEST_PATH), `${JSON.stringify(manifest, null, 2)}
78
+ `);
79
+ console.log(
80
+ `basalt-ui init: ${writtenFiles.length} written, ${keptFiles.length} kept, manifest at ${MANIFEST_PATH}`
81
+ );
82
+ reportPrune(pruned);
83
+ if (missingSources.length > 0) {
84
+ console.log(
85
+ `basalt-ui init: ${missingSources.length} shipped asset(s) not present, skipped: ${missingSources.join(", ")}`
86
+ );
87
+ }
88
+ if (keptFiles.length > 0) {
89
+ console.log(`
90
+ Kept (already present \u2014 basalt did not touch them):`);
91
+ for (const dest of keptFiles) {
92
+ const cost = KEPT_FILE_COST[dest];
93
+ console.log(cost === void 0 ? ` \xB7 ${dest}` : ` \xB7 ${dest} \u2014 ${cost}`);
94
+ }
95
+ }
96
+ if (mergeLint !== null) {
97
+ const mergeMessage = {
98
+ added: `spliced "${ctx.vars.OXLINT_PRESET_PATH}" into the existing .oxlintrc.json extends`,
99
+ already: ".oxlintrc.json already extends the shipped preset \u2014 nothing to do",
100
+ absent: "no existing .oxlintrc.json to merge into (the seeded one already extends the preset)",
101
+ unreadable: ".oxlintrc.json is not valid JSON \u2014 merge the extends entry by hand",
102
+ "has-comments": `.oxlintrc.json carries comments; rewriting it would delete them (usually the reason each rule is off). Add "extends": ["${ctx.vars.OXLINT_PRESET_PATH}"] as the first entry by hand.`
103
+ };
104
+ console.log(`basalt-ui init: --merge-lint \u2014 ${mergeMessage[mergeLint]}`);
105
+ }
106
+ const rootsMessages = rootsNotices(rootsState);
107
+ for (const line of rootsMessages.log) console.log(`basalt-ui init: ${line}`);
108
+ for (const line of rootsMessages.error) console.error(`\u26A0 basalt-ui init: ${line}`);
109
+ if (seededLintScript) {
110
+ console.log(`basalt-ui init: added the "lint:basalt" script (${lintScript}) to package.json.`);
111
+ }
112
+ if (!placement.isPackageRepoRoot) {
113
+ console.log(
114
+ `basalt-ui init: skipped lefthook.yml (this package is not the repo root \u2014 repo root detected at ${placement.repoRoot}) \u2014 lefthook only reads config at the repo root; extend ${ctx.vars.LEFTHOOK_PRESET_PATH} from your root lefthook.yml instead, and give its check-theme command \`env: { BASALT_CWD: ${relativePosix(placement.repoRoot, cwd)} }\` so the guard runs where your basalt config actually lives.`
115
+ );
116
+ console.log(
117
+ `basalt-ui init: skipped .github/workflows/check.yml (this package is not the repo root \u2014 repo root detected at ${placement.repoRoot}) \u2014 GitHub Actions only reads .github/ at the repo root; copy the steps from ${shippedAssetPath(install, placement.repoRoot, "configs/check.yml")} into your root CI workflow instead.`
118
+ );
119
+ }
120
+ if (placement.relocatedQueryClient !== null) {
121
+ console.log(
122
+ `basalt-ui init: skipped src/query-client.ts (found an existing query client at ${relative(cwd, placement.relocatedQueryClient)}) \u2014 import it from there instead of re-seeding at the original path.`
123
+ );
124
+ }
125
+ if (!peers.hasQuery) {
126
+ console.log(
127
+ "basalt-ui init: skipped src/query-client.ts (no @tanstack/react-query dependency detected) \u2014 install it, or re-run with --with-query, to scaffold it."
128
+ );
129
+ }
130
+ if (!peers.hasRouter || !peers.hasQuery) {
131
+ console.log(
132
+ "basalt-ui init: skipped src/routes/__root.tsx (needs both @tanstack/react-router and @tanstack/react-query) \u2014 install both, or re-run with --with-router --with-query, to scaffold it."
133
+ );
134
+ }
135
+ console.log(
136
+ `
137
+ Theme guard hook: add to .claude/settings.json \u2192 hooks.PreToolUse to catch violations before they land:
138
+ "hooks": {
139
+ "PreToolUse": [
140
+ {
141
+ "matcher": "Write|Edit|MultiEdit",
142
+ "hooks": [{ "type": "command", "command": "${ctx.vars.BASALT_BIN} guard-hook" }]
143
+ }
144
+ ]
145
+ }`
146
+ );
147
+ const presetPlugins = readOxlintPresetPlugins(ctx.pkgRoot);
148
+ if (presetPlugins.length > 0) {
149
+ console.log(
150
+ `
151
+ Lint debt: adopting the shipped oxlint preset on an EXISTING app is not a no-op \u2014 it turns on ${presetPlugins.length} plugins (${presetPlugins.join(", ")}) plus the basalt/* design rules, on code never linted against them. Run \`oxlint .\` now and triage the count before your next commit; turn a rule off in your own .oxlintrc.json with a written reason rather than blanket-disabling a plugin.`
152
+ );
153
+ }
154
+ console.log(
155
+ "Activate the hooks: `lefthook install` \u2014 the seeded lefthook.yml is inert until the git hooks are written, and looks configured either way."
156
+ );
157
+ console.log(
158
+ `
159
+ First run: run \`${ctx.vars.BASALT_BIN} check-theme\` next (or \`bun run lint:basalt\`), then tune the per-rule \`basalt.*\` config keys in package.json for anything that fires \u2014 do not mass-\`theme-allow\` findings. Then \`basalt-ui doctor\` to confirm the wiring actually took.`
160
+ );
161
+ return 0;
162
+ }
163
+ export {
164
+ init
165
+ };
@@ -0,0 +1,43 @@
1
+ /** The oxlint plugins the shipped preset switches on — read from the preset, never restated. */
2
+ export declare function readOxlintPresetPlugins(pkgRoot: string): string[];
3
+ export type SyncOptions = {
4
+ force?: boolean;
5
+ check?: boolean;
6
+ /** The raw flag list, read for `--tokens-only` / `--framework` exactly as check-theme reads it. */
7
+ flags?: readonly string[];
8
+ };
9
+ /**
10
+ * The nearest ANCESTOR of `dir` (exclusive) carrying a basalt manifest, or null.
11
+ *
12
+ * `resolveProjectDir` resolves to exactly one directory — `BASALT_CWD` when set, else the
13
+ * invocation cwd — and never walks. The shape that produced this function is the one that resolver
14
+ * doesn't cover: a consumer standing in `apps/dashboard`, the package that actually depends on
15
+ * basalt-ui, whose install lives at the repo root above it. With nothing walking up, `sync` read
16
+ * "no manifest here" as "nothing scaffolded yet" and wrote a complete second consumer beside the
17
+ * real one.
18
+ */
19
+ /**
20
+ * The sentence `sync` prints when the cwd carries no install but an ancestor does.
21
+ *
22
+ * Shared with `doctor` deliberately. The two commands already share `resolveProjectDir`, but not
23
+ * the ADVICE: `sync` named the parent install (1.22.0's "stop scaffolding a second consumer" fix)
24
+ * while `doctor`, in the same directory, kept prescribing `basalt-ui init` — so following doctor
25
+ * literally performed the exact mistake that fix exists to prevent. One function, one sentence.
26
+ */
27
+ export declare function parentInstallAdvice(cwd: string, parent: string, verb: string): string;
28
+ export declare function findManifestAbove(dir: string): string | null;
29
+ /**
30
+ * Reconcile managed files with the shipped versions via a sha256 three-way compare.
31
+ *
32
+ * - `--check` makes NO writes; exits non-zero if any managed file is out-of-date or locally drifted
33
+ * (a CI freshness gate), exit 0 when all current.
34
+ * - `--force` overwrites locally-drifted files instead of skipping them.
35
+ *
36
+ * Runs against `resolveProjectDir(cwd)`, exactly as `check-theme` and `doctor` do — and then
37
+ * REFUSES rather than scaffolding when the resolved project has no manifest. See
38
+ * {@link findManifestAbove} for the failure that bought this: `sync` is the drift refresh and
39
+ * `init` is the scaffold, so placing twenty files on a cwd that was never a consumer is a decision
40
+ * `sync` does not get to make silently.
41
+ */
42
+ export declare function sync(opts?: SyncOptions, invocationCwd?: string): number;
43
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"AA2CA,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CASjE;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mGAAmG;IACnG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,WAAgB,EAAE,aAAa,GAAE,MAAsB,GAAG,MAAM,CAqN1F"}
@@ -0,0 +1,206 @@
1
+ import { existsSync } from "node:fs";
2
+ import { relative, resolve } from "node:path";
3
+ import { deriveSpacing } from "../tokens/index.js";
4
+ import {
5
+ MANIFEST_PATH,
6
+ basaltPresetEntry,
7
+ classify,
8
+ conflictingProfileFlags,
9
+ declaredProfile,
10
+ diffSummary,
11
+ findBasaltInstall,
12
+ inspectLefthookGate,
13
+ isStringArray,
14
+ managedFiles,
15
+ normalizeForLedger,
16
+ parseJsonc,
17
+ pruneRetiredManagedFiles,
18
+ readBasaltConfig,
19
+ readIfExists,
20
+ readManifest,
21
+ readSource,
22
+ reconcileRoots,
23
+ relativePosix,
24
+ renderContext,
25
+ reportPrune,
26
+ resolvePeerFlags,
27
+ resolvePlacement,
28
+ resolveProjectDir,
29
+ rootsNotices,
30
+ sha256,
31
+ shippedAssetPath,
32
+ unitState,
33
+ writeFileEnsuringDir,
34
+ writeUnit
35
+ } from "./index.js";
36
+ function readOxlintPresetPlugins(pkgRoot) {
37
+ const raw = readSource(pkgRoot, "configs/oxlint.json");
38
+ if (raw === null) return [];
39
+ try {
40
+ const plugins = JSON.parse(raw).plugins;
41
+ return isStringArray(plugins) ? plugins : [];
42
+ } catch {
43
+ return [];
44
+ }
45
+ }
46
+ function parentInstallAdvice(cwd, parent, verb) {
47
+ return `This repo's install is at ${relativePosix(cwd, parent)} (${parent}) \u2014 run ${verb} there, or set BASALT_CWD to it.`;
48
+ }
49
+ function findManifestAbove(dir) {
50
+ let current = resolve(dir, "..");
51
+ for (; ; ) {
52
+ if (existsSync(resolve(current, MANIFEST_PATH))) return current;
53
+ const parent = resolve(current, "..");
54
+ if (parent === current) return null;
55
+ current = parent;
56
+ }
57
+ }
58
+ function sync(opts = {}, invocationCwd = process.cwd()) {
59
+ const syncFlags = opts.flags ?? [];
60
+ if (conflictingProfileFlags(syncFlags)) {
61
+ console.error("basalt-ui sync: --tokens-only and --framework are alternatives \u2014 pass one.");
62
+ return 1;
63
+ }
64
+ const project = resolveProjectDir(invocationCwd);
65
+ const cwd = project.dir;
66
+ if (project.relocatedFrom !== null) {
67
+ console.log(`basalt-ui sync: BASALT_CWD relocated from ${project.relocatedFrom} to ${cwd}.`);
68
+ }
69
+ if (declaredProfile(readBasaltConfig(cwd), syncFlags) === "tokens-only") {
70
+ console.log(
71
+ `basalt-ui sync: ${MANIFEST_PATH}: n/a \u2014 a tokens-only consumer has no scaffold to reconcile. The token layer is refreshed by re-running \`basalt-ui tokens:css\`, and \`tokens:css --check\` is its drift gate. Pass --framework to force the full profile.`
72
+ );
73
+ return 0;
74
+ }
75
+ if (!existsSync(resolve(cwd, MANIFEST_PATH))) {
76
+ const elsewhere = findManifestAbove(cwd);
77
+ const wouldWrite = managedFiles(resolvePeerFlags(cwd, {}), resolvePlacement(cwd)).length;
78
+ console.error(
79
+ `\u2716 basalt-ui sync: no ${MANIFEST_PATH} at ${cwd} \u2014 refusing to scaffold. \`sync\` refreshes an EXISTING basalt install; creating one is \`basalt-ui init\`'s decision, and continuing here would write ${wouldWrite} managed file(s) into this directory.` + (elsewhere === null ? " No manifest exists at any ancestor either \u2014 run `basalt-ui init` here if this package really is meant to be a consumer." : ` ${parentInstallAdvice(cwd, elsewhere, "sync")}`)
80
+ );
81
+ return 1;
82
+ }
83
+ const rootsState = reconcileRoots(cwd, { write: opts.check !== true });
84
+ const ctx = renderContext(cwd);
85
+ const manifest = readManifest(cwd);
86
+ const peers = resolvePeerFlags(cwd, {});
87
+ const placement = resolvePlacement(cwd);
88
+ const files = managedFiles(peers, placement);
89
+ let updated = 0;
90
+ let created = 0;
91
+ let recreated = 0;
92
+ let skippedDrift = 0;
93
+ let staleForCheck = 0;
94
+ const driftLines = [];
95
+ const missingSources = [];
96
+ for (const file of files) {
97
+ const state = unitState(file, cwd, ctx);
98
+ if (state.desired === null) {
99
+ missingSources.push(file.source);
100
+ continue;
101
+ }
102
+ const tracked = manifest.files[file.dest] !== void 0;
103
+ if (file.mode === "seed") {
104
+ if (state.current === null && !opts.check) {
105
+ manifest.files[file.dest] = writeUnit(file, cwd, state.desired);
106
+ if (tracked) recreated++;
107
+ else created++;
108
+ }
109
+ continue;
110
+ }
111
+ const kind = classify(state, manifest.files[file.dest]);
112
+ if (kind === "current") {
113
+ manifest.files[file.dest] = sha256(normalizeForLedger(state.desired));
114
+ continue;
115
+ }
116
+ if (kind === "drifted" && !opts.force) {
117
+ driftLines.push(diffSummary(file, state));
118
+ staleForCheck++;
119
+ skippedDrift++;
120
+ continue;
121
+ }
122
+ staleForCheck++;
123
+ if (opts.check) continue;
124
+ manifest.files[file.dest] = writeUnit(file, cwd, state.desired);
125
+ if (kind !== "missing") updated++;
126
+ else if (tracked) recreated++;
127
+ else created++;
128
+ }
129
+ const pruned = pruneRetiredManagedFiles(cwd, manifest, files, {
130
+ dryRun: opts.check === true,
131
+ force: opts.force === true
132
+ });
133
+ staleForCheck += pruned.removed.length + pruned.drifted.length;
134
+ if (!placement.isPackageRepoRoot) {
135
+ console.log(
136
+ `basalt-ui sync: skipped lefthook.yml (this package is not the repo root \u2014 repo root detected at ${placement.repoRoot}) \u2014 lefthook only reads config at the repo root; extend node_modules/basalt-ui/configs/lefthook.yml from your root lefthook.yml instead.`
137
+ );
138
+ console.log(
139
+ `basalt-ui sync: skipped .github/workflows/check.yml (this package is not the repo root \u2014 repo root detected at ${placement.repoRoot}) \u2014 GitHub Actions only reads .github/ at the repo root; extend node_modules/basalt-ui/configs/check.yml from your root CI workflow instead.`
140
+ );
141
+ }
142
+ if (placement.relocatedQueryClient !== null) {
143
+ console.log(
144
+ `basalt-ui sync: skipped src/query-client.ts (found an existing query client at ${relative(cwd, placement.relocatedQueryClient)}) \u2014 import it from there instead of re-seeding at the original path.`
145
+ );
146
+ }
147
+ const rootsMessages = rootsNotices(rootsState);
148
+ for (const line of rootsMessages.log) console.log(`basalt-ui sync: ${line}`);
149
+ for (const line of rootsMessages.error) console.error(`\u26A0 basalt-ui sync: ${line}`);
150
+ const install = findBasaltInstall(cwd);
151
+ const lefthookGate = inspectLefthookGate(placement.repoRoot);
152
+ if (lefthookGate.kind === "absent") {
153
+ console.error(
154
+ `\u26A0 basalt-ui sync: ${lefthookGate.file}: \`lefthook dump\` resolves the merged config and no pre-commit command runs check-theme \u2014 there is no pre-commit gate. Add "extends: [${shippedAssetPath(install, placement.repoRoot, "configs/lefthook.yml")}]".`
155
+ );
156
+ }
157
+ const oxlintrcRaw = readIfExists(resolve(cwd, ".oxlintrc.json"));
158
+ const oxlintEntry = oxlintrcRaw === null ? null : basaltPresetEntry(parseJsonc(oxlintrcRaw)?.["extends"]);
159
+ if (oxlintEntry !== null && !existsSync(resolve(cwd, oxlintEntry))) {
160
+ console.error(
161
+ `\u26A0 basalt-ui sync: .oxlintrc.json extends "${oxlintEntry}", which does not exist \u2014 oxlint refuses to start on a missing extends target (\`NotFound\`). Repoint it at "${shippedAssetPath(install, cwd, "configs/oxlint.json")}".`
162
+ );
163
+ }
164
+ if (opts.check) {
165
+ if (driftLines.length > 0) {
166
+ console.error("basalt-ui sync --check: locally-drifted managed files:");
167
+ for (const l of driftLines) console.error(l);
168
+ }
169
+ const retired = [...pruned.removed, ...pruned.drifted];
170
+ if (retired.length > 0) {
171
+ console.error(
172
+ `basalt-ui sync --check: ${retired.length} retired rule/skill file(s) still present: ${retired.join(", ")} \u2014 run \`basalt-ui sync\`.`
173
+ );
174
+ }
175
+ if (staleForCheck > 0) {
176
+ console.error(`basalt-ui sync --check: ${staleForCheck} managed file(s) out of date.`);
177
+ return 1;
178
+ }
179
+ console.log("\u2713 basalt-ui sync --check: all managed files current.");
180
+ return 0;
181
+ }
182
+ manifest.basaltVersion = ctx.vars.BASALT_VERSION;
183
+ manifest.spacingScale = { ...deriveSpacing(0).scale };
184
+ writeFileEnsuringDir(resolve(cwd, MANIFEST_PATH), `${JSON.stringify(manifest, null, 2)}
185
+ `);
186
+ console.log(
187
+ `basalt-ui sync: ${updated} updated, ${created} created, ${recreated} recreated, ${skippedDrift} skipped (drift), ${pruned.removed.length} retired.`
188
+ );
189
+ reportPrune(pruned);
190
+ if (driftLines.length > 0) {
191
+ console.log("Locally-edited files were skipped (run with --force to overwrite):");
192
+ for (const l of driftLines) console.log(l);
193
+ }
194
+ if (missingSources.length > 0) {
195
+ console.log(
196
+ `basalt-ui sync: ${missingSources.length} shipped asset(s) not present, skipped: ${missingSources.join(", ")}`
197
+ );
198
+ }
199
+ return 0;
200
+ }
201
+ export {
202
+ findManifestAbove,
203
+ parentInstallAdvice,
204
+ readOxlintPresetPlugins,
205
+ sync
206
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Space- and number-normalize the argument list of a legacy color function so the emitted file
3
+ * survives a normal repo's formatter.
4
+ *
5
+ * This is FORMATTING ONLY and deliberately the CLI's single deviation from "print exactly what
6
+ * `buildPaletteCss` returned": `rgba(255,255,255,0.6)` and `rgba(255, 255, 255, 0.6)` are the same
7
+ * colour, the shipped palette emits the first form on the dark side and the second on the light
8
+ * side, and a consumer committing the output ate a lint-ignore entry for the difference. The token
9
+ * VALUES are untouched — nothing here can change what basalt's tokens are.
10
+ *
11
+ * Trailing zeros go the same way and for the same reason: prettier rewrites `0.10` → `0.1`, so the
12
+ * two `rgba(28, 25, 23, 0.10)` alphas in the light shadow tokens were the whole reason the one
13
+ * framework-free consumer still could not lint its committed sheet — `--fix` and `tokens:css
14
+ * --check` disagreed forever, and the lint-ignore entry survived two releases. Only a bare decimal
15
+ * literal is touched (never a `%`, a `var()` or a unit), and `0.10`/`0.1` are the same number.
16
+ *
17
+ * Exported for tests, so the expectation can be computed rather than restated.
18
+ */
19
+ export declare function normalizeColorFunctions(css: string): string;
20
+ /**
21
+ * tokens:css — emit the `--vx-*` stylesheet, optionally retargeted.
22
+ *
23
+ * The escape hatch from installing anything: a static site runs this once (`bunx basalt-ui
24
+ * tokens:css --selector-attribute data-theme --out src/tokens.css`) and consumes basalt's token
25
+ * system as plain CSS, with no package in its dependency tree at all. `basalt-ui/tokens.css` is the
26
+ * same artifact for a consumer that does install; this command exists for the ones that shouldn't
27
+ * have to just to change a selector.
28
+ *
29
+ * It parses flags and calls `buildPaletteCss` for the token VALUES — the CLI and the API must not
30
+ * be able to disagree about what basalt's tokens are. What it adds is strictly file framing for an
31
+ * artifact a consumer COMMITS: the `@generated` header (the guard's skip marker), a trailing
32
+ * newline, and `rgba()` argument spacing. All three were reported by the one framework-free
33
+ * consumer as the reasons the output could not simply be committed.
34
+ */
35
+ export declare function tokensCss(flags: string[], cwd?: string): number;
36
+ /**
37
+ * fonts:css — emit the shipped `--basalt-font-*` stacks as plain CSS.
38
+ *
39
+ * The typeface half of the framework-free route, which had no supported path at all: `tokens.css`
40
+ * emits no font vars, `styles.css` is the one place the defaults live and a framework-free consumer
41
+ * is told not to import it, and `buildFontsCss` returns `''` unless the caller already knows the
42
+ * stacks. The one non-Mantine consumer lost its font identity entirely and hardcoded the stacks —
43
+ * which the theme guard then flagged as `raw-font-family`.
44
+ *
45
+ * The declarations are READ from the shipped stylesheet rather than restated here, so this command
46
+ * and `basalt-ui/styles.css` can never name different typefaces. Note the fonts themselves are
47
+ * `@fontsource-variable/*` packages: without them the stacks fall through to their own system
48
+ * fallbacks, which is the intended framework-free behaviour.
49
+ */
50
+ export declare function fontsCss(flags: string[], cwd?: string): number;
51
+ //# sourceMappingURL=tokens-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens-css.d.ts","sourceRoot":"","sources":["../../src/cli/tokens-css.ts"],"names":[],"mappings":"AAkCA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3D;AA4DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CA4E9E;AAgBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAa7E"}
@@ -0,0 +1,165 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
3
+ import { GENERATED_HEADER_LINE } from "../guard/index.js";
4
+ import { buildPaletteCss } from "../tokens/index.js";
5
+ import { packageRoot, readFrameworkVersion, readIfExists, readSource } from "./index.js";
6
+ function flagValue(flags, name) {
7
+ const i = flags.indexOf(name);
8
+ if (i === -1) return void 0;
9
+ const value = flags[i + 1];
10
+ return value === void 0 || value.startsWith("--") ? void 0 : value;
11
+ }
12
+ function generatedHeader(version, command, flags) {
13
+ const shown = flags.filter((f) => f !== "--check");
14
+ const invocation = shown.length === 0 ? command : `${command} ${shown.join(" ")}`;
15
+ return `${GENERATED_HEADER_LINE}
16
+ /* basalt-ui ${version} \u2014 \`basalt-ui ${invocation}\` */
17
+ `;
18
+ }
19
+ function normalizeColorFunctions(css) {
20
+ return css.replace(/\b(rgba?|hsla?)\(([^()]*)\)/g, (_match, fn, args) => {
21
+ const parts = args.split(",").map((part) => normalizeCssNumber(part.trim()));
22
+ return `${fn}(${parts.join(", ")})`;
23
+ });
24
+ }
25
+ function normalizeCssNumber(arg) {
26
+ if (!/^\d+\.\d+$/.test(arg)) return arg;
27
+ return arg.replace(/\.?0+$/, "");
28
+ }
29
+ const SCHEME_CLASS_SENTINEL = "data-basalt-scheme-class";
30
+ function emitGeneratedCss(content, flags, cwd, command) {
31
+ const out = flagValue(flags, "--out");
32
+ const check = flags.includes("--check");
33
+ if (out === void 0) {
34
+ if (check) {
35
+ console.error(
36
+ `${command}: --check needs --out <path> \u2014 there is nothing to compare stdout to.`
37
+ );
38
+ return 1;
39
+ }
40
+ process.stdout.write(content);
41
+ return 0;
42
+ }
43
+ const target = isAbsolute(out) ? out : resolve(cwd, out);
44
+ const shown = relative(cwd, target) || target;
45
+ if (check) {
46
+ const onDisk = readIfExists(target);
47
+ if (onDisk === null) {
48
+ console.error(
49
+ `\u2716 ${command} --check: ${shown} does not exist \u2014 run without --check to write it.`
50
+ );
51
+ return 1;
52
+ }
53
+ if (onDisk === content) {
54
+ console.log(`\u2713 ${command} --check: ${shown} is up to date.`);
55
+ return 0;
56
+ }
57
+ const diskLines = onDisk.split("\n");
58
+ const wantLines = content.split("\n");
59
+ console.error(
60
+ `\u2716 ${command} --check: ${shown} differs from what \`basalt-ui ${command}\` emits today (on disk ${diskLines.length} lines, emitted ${wantLines.length}) \u2014 re-run the same command without --check and commit the result. A basalt-ui release moves the \`@generated\` header line, so this is byte-exact \u2014 expect a no-op commit on every upgrade that ships a committed generated sheet.`
61
+ );
62
+ return 1;
63
+ }
64
+ mkdirSync(dirname(target), { recursive: true });
65
+ writeFileSync(target, content);
66
+ console.log(`wrote ${content.split("\n").length} lines \u2192 ${shown}`);
67
+ return 0;
68
+ }
69
+ function tokensCss(flags, cwd = process.cwd()) {
70
+ const attribute = flagValue(flags, "--selector-attribute");
71
+ const schemeClass = flagValue(flags, "--selector-class");
72
+ const lightClass = flagValue(flags, "--light-class");
73
+ const darkValue = flagValue(flags, "--dark-value");
74
+ const lightValue = flagValue(flags, "--light-value");
75
+ const defaultScheme = flagValue(flags, "--default-scheme");
76
+ const only = flagValue(flags, "--only");
77
+ if (defaultScheme !== void 0 && !["dark", "light", "none"].includes(defaultScheme)) {
78
+ console.error(
79
+ `tokens:css: --default-scheme must be dark, light or none (got '${defaultScheme}')`
80
+ );
81
+ return 1;
82
+ }
83
+ if (only !== void 0 && !["core", "all"].includes(only)) {
84
+ console.error(`tokens:css: --only must be core or all (got '${only}')`);
85
+ return 1;
86
+ }
87
+ if (schemeClass !== void 0 && attribute !== void 0) {
88
+ console.error(
89
+ "tokens:css: --selector-class and --selector-attribute are alternatives \u2014 pass one."
90
+ );
91
+ return 1;
92
+ }
93
+ if (schemeClass !== void 0 && /[^\w-]/.test(schemeClass)) {
94
+ console.error(
95
+ `tokens:css: --selector-class must be a plain CSS class name (got '${schemeClass}')`
96
+ );
97
+ return 1;
98
+ }
99
+ if (lightClass !== void 0 && /[^\w-]/.test(lightClass)) {
100
+ console.error(`tokens:css: --light-class must be a plain CSS class name (got '${lightClass}')`);
101
+ return 1;
102
+ }
103
+ const resolvedDarkValue = schemeClass !== void 0 ? schemeClass : darkValue;
104
+ const resolvedLightValue = schemeClass !== void 0 ? lightClass ?? "light" : lightValue;
105
+ const resolvedAttribute = schemeClass !== void 0 ? SCHEME_CLASS_SENTINEL : attribute;
106
+ const scheme = {
107
+ ...resolvedAttribute === void 0 ? {} : { attribute: resolvedAttribute },
108
+ ...resolvedDarkValue === void 0 ? {} : { darkValue: resolvedDarkValue },
109
+ ...resolvedLightValue === void 0 ? {} : { lightValue: resolvedLightValue }
110
+ };
111
+ let css = buildPaletteCss({
112
+ ...Object.keys(scheme).length === 0 ? {} : { scheme },
113
+ ...defaultScheme === void 0 ? {} : { defaultScheme },
114
+ ...flags.includes("--media-fallback") ? { mediaFallback: true } : {},
115
+ ...only === void 0 ? {} : { only },
116
+ // The tokens-only consumer is exactly the one who writes these names by hand, so they are also
117
+ // the one who wants the deprecated camelCase aliases gone — and this command is their only
118
+ // entry point. Without the flag the CLI and the API could disagree about what basalt's tokens
119
+ // are, which is the one thing this command is documented never to allow.
120
+ ...flags.includes("--no-legacy-aliases") ? { legacyAliases: false } : {}
121
+ });
122
+ if (schemeClass !== void 0) {
123
+ css = css.replace(
124
+ new RegExp(`\\[${SCHEME_CLASS_SENTINEL}='([\\w-]+)'\\]`, "g"),
125
+ (_match, value) => `.${value}`
126
+ );
127
+ }
128
+ const version = readFrameworkVersion(packageRoot());
129
+ const content = `${generatedHeader(version, "tokens:css", flags)}${normalizeColorFunctions(css)}
130
+ `;
131
+ return emitGeneratedCss(content, flags, cwd, "tokens:css");
132
+ }
133
+ function readShippedFontDecls(pkgRoot) {
134
+ const css = readSource(pkgRoot, "dist/styles.css") ?? readSource(pkgRoot, "src/styles.css");
135
+ if (css === null) return [];
136
+ const decls = [];
137
+ for (const match of css.matchAll(/(--basalt-font[\w-]*)\s*:\s*([^;]+);/g)) {
138
+ decls.push({
139
+ name: match[1],
140
+ value: match[2].replace(/\s+/g, " ").trim()
141
+ });
142
+ }
143
+ return decls;
144
+ }
145
+ function fontsCss(flags, cwd = process.cwd()) {
146
+ const pkgRoot = packageRoot();
147
+ const decls = readShippedFontDecls(pkgRoot);
148
+ if (decls.length === 0) {
149
+ console.error(
150
+ "fonts:css: could not read the shipped font stacks from styles.css \u2014 this is a packaging bug in basalt-ui, not a config error."
151
+ );
152
+ return 1;
153
+ }
154
+ const body = `:root {
155
+ ${decls.map((d) => ` ${d.name}: ${d.value};`).join("\n")}
156
+ }
157
+ `;
158
+ const header = generatedHeader(readFrameworkVersion(pkgRoot), "fonts:css", flags);
159
+ return emitGeneratedCss(`${header}${body}`, flags, cwd, "fonts:css");
160
+ }
161
+ export {
162
+ fontsCss,
163
+ normalizeColorFunctions,
164
+ tokensCss
165
+ };
@@ -1,4 +1,4 @@
1
- import { isDev } from "../utils/is-dev.js";
1
+ import { isDev } from "../common/is-dev.js";
2
2
  let activeCommands = {};
3
3
  function defineCommands(spec) {
4
4
  activeCommands = spec;
@@ -1,6 +1,6 @@
1
1
  import { useEffect } from "react";
2
2
  import { missingLayer } from "../common/errors.js";
3
- import { isDev } from "../utils/is-dev.js";
3
+ import { isDev } from "../common/is-dev.js";
4
4
  let modalsPromise;
5
5
  function loadModals() {
6
6
  modalsPromise ??= import("@mantine/modals").then((m) => m.modals).catch(() => void 0);