@kerfjs/ui 4.4.1 → 4.5.0-beta.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 (499) hide show
  1. package/README.md +425 -42
  2. package/ai/application-ui-diagnostic-ids-v1.json +92 -0
  3. package/ai/application-ui-profile-sync.cjs +529 -0
  4. package/ai/application-ui-profile.d.mts +1 -0
  5. package/ai/application-ui-profile.d.ts +102 -0
  6. package/ai/application-ui-profile.defaults.json +41 -0
  7. package/ai/application-ui-profile.mjs +626 -0
  8. package/ai/application-ui-profile.schema.json +130 -0
  9. package/ai/catalog-authoring.json +25 -0
  10. package/ai/catalog-authoring.schema.json +61 -0
  11. package/ai/compile-time-contracts-v1.json +102 -0
  12. package/ai/compile-time-contracts-v1.schema.json +49 -0
  13. package/ai/component-catalog-extension-v2.d.ts +7 -0
  14. package/ai/component-catalog-extension-v2.schema.json +7 -0
  15. package/ai/component-catalog-extension.schema.json +79 -0
  16. package/ai/component-catalog-v2-overrides.json +319 -0
  17. package/ai/component-catalog-v2.d.ts +67 -0
  18. package/ai/component-catalog-v2.json +4675 -0
  19. package/ai/component-catalog-v2.schema.json +246 -0
  20. package/ai/component-catalog.json +5826 -0
  21. package/ai/component-catalog.schema.json +95 -0
  22. package/ai/public-api-signatures-v1.md +1719 -0
  23. package/ai/skill.md +129 -21
  24. package/ai/webawesome-jsx-signatures-v1.md +106 -0
  25. package/analyzer/cli.mjs +46 -0
  26. package/analyzer/index.d.mts +45 -0
  27. package/analyzer/index.mjs +737 -0
  28. package/analyzer/report.schema.json +66 -0
  29. package/dist/app-tab.d.ts +14 -2
  30. package/dist/app-tab.js +3 -1
  31. package/dist/browser/app-tab.js +3 -2
  32. package/dist/browser/disclosure-arrow.js +4 -0
  33. package/dist/browser/empty-state.js +3 -3
  34. package/dist/browser/floating-toolbar.js +3 -0
  35. package/dist/browser/list-action-row.js +4 -0
  36. package/dist/browser/list-header.js +6 -0
  37. package/dist/browser/list-inset-control.js +3 -0
  38. package/dist/browser/list-inset-text.js +3 -0
  39. package/dist/browser/list-item.js +4 -0
  40. package/dist/browser/list.js +3 -0
  41. package/dist/browser/loading-spinner.js +2 -2
  42. package/dist/browser/lucide-icon.js +2 -2
  43. package/dist/browser/pane.js +3 -0
  44. package/dist/browser/panel-header.js +7 -0
  45. package/dist/browser/resizable-region.js +2 -2
  46. package/dist/browser/segmented-control.js +3 -2
  47. package/dist/browser/select.js +4 -3
  48. package/dist/browser/skeleton.js +3 -0
  49. package/dist/browser/state-banner.js +3 -2
  50. package/dist/browser/sunken-panel.js +3 -0
  51. package/dist/browser/tab-bar.js +2 -2
  52. package/dist/browser/token-search-field.js +4 -0
  53. package/dist/browser/toolbar-control-group.js +2 -2
  54. package/dist/browser/toolbar-text.js +3 -2
  55. package/dist/browser/toolbar.js +2 -2
  56. package/dist/browser/value-table.js +3 -2
  57. package/dist/catalog-resources.d.ts +34 -0
  58. package/dist/catalog-resources.js +22 -0
  59. package/dist/catalog-resources.js.map +1 -0
  60. package/dist/catalog.d.ts +150 -0
  61. package/dist/catalog.js +377 -0
  62. package/dist/catalog.js.map +1 -0
  63. package/dist/chunk-5VTB2BKP.js +35 -0
  64. package/dist/chunk-5VTB2BKP.js.map +1 -0
  65. package/dist/chunk-6WTETUZ6.js +21 -0
  66. package/dist/chunk-6WTETUZ6.js.map +1 -0
  67. package/dist/chunk-7KEUJIIC.js +218 -0
  68. package/dist/chunk-7KEUJIIC.js.map +1 -0
  69. package/dist/chunk-7XRDUG4Y.js +58 -0
  70. package/dist/chunk-7XRDUG4Y.js.map +1 -0
  71. package/dist/chunk-B3A3IVO5.js +83 -0
  72. package/dist/chunk-B3A3IVO5.js.map +1 -0
  73. package/dist/chunk-DPDBVKNA.js +113 -0
  74. package/dist/chunk-DPDBVKNA.js.map +1 -0
  75. package/dist/chunk-FEAMR7S4.js +68 -0
  76. package/dist/chunk-FEAMR7S4.js.map +1 -0
  77. package/dist/chunk-FEY65TBV.js +15 -0
  78. package/dist/chunk-FEY65TBV.js.map +1 -0
  79. package/dist/{chunk-TRNBHPNW.js → chunk-IJBSZ4NX.js} +11 -8
  80. package/dist/chunk-IJBSZ4NX.js.map +1 -0
  81. package/dist/chunk-J5BFYY7Q.js +35 -0
  82. package/dist/chunk-J5BFYY7Q.js.map +1 -0
  83. package/dist/chunk-JRKSK2HX.js +79 -0
  84. package/dist/chunk-JRKSK2HX.js.map +1 -0
  85. package/dist/chunk-KWWR5VMS.js +45 -0
  86. package/dist/chunk-KWWR5VMS.js.map +1 -0
  87. package/dist/chunk-LPOMRC4C.js +25 -0
  88. package/dist/chunk-LPOMRC4C.js.map +1 -0
  89. package/dist/chunk-M7JBER5U.js +41 -0
  90. package/dist/chunk-M7JBER5U.js.map +1 -0
  91. package/dist/chunk-NENBUYX5.js +79 -0
  92. package/dist/chunk-NENBUYX5.js.map +1 -0
  93. package/dist/chunk-NWSEP5RT.js +117 -0
  94. package/dist/chunk-NWSEP5RT.js.map +1 -0
  95. package/dist/chunk-OJWWHFH3.js +426 -0
  96. package/dist/chunk-OJWWHFH3.js.map +1 -0
  97. package/dist/chunk-PSKN344N.js +114 -0
  98. package/dist/chunk-PSKN344N.js.map +1 -0
  99. package/dist/chunk-PX3YSS5C.js +32 -0
  100. package/dist/chunk-PX3YSS5C.js.map +1 -0
  101. package/dist/chunk-QO55FN2Y.js +20 -0
  102. package/dist/chunk-QO55FN2Y.js.map +1 -0
  103. package/dist/chunk-R7ZWUN64.js +38 -0
  104. package/dist/chunk-R7ZWUN64.js.map +1 -0
  105. package/dist/chunk-RKVQEH4J.js +61 -0
  106. package/dist/chunk-RKVQEH4J.js.map +1 -0
  107. package/dist/chunk-SRSJO5QE.js +40 -0
  108. package/dist/chunk-SRSJO5QE.js.map +1 -0
  109. package/dist/chunk-SYDMYBPG.js +31 -0
  110. package/dist/chunk-SYDMYBPG.js.map +1 -0
  111. package/dist/chunk-TB6DY7H5.js +25 -0
  112. package/dist/chunk-TB6DY7H5.js.map +1 -0
  113. package/dist/chunk-UFZKLBCF.js +108 -0
  114. package/dist/chunk-UFZKLBCF.js.map +1 -0
  115. package/dist/{chunk-MQIZAD4A.js → chunk-UKKSMZYT.js} +76 -22
  116. package/dist/chunk-UKKSMZYT.js.map +1 -0
  117. package/dist/chunk-W5L2JSBY.js +40 -0
  118. package/dist/chunk-W5L2JSBY.js.map +1 -0
  119. package/dist/chunk-Y45PPBDV.js +105 -0
  120. package/dist/chunk-Y45PPBDV.js.map +1 -0
  121. package/dist/chunk-Y6LYKFXY.js +43 -0
  122. package/dist/chunk-Y6LYKFXY.js.map +1 -0
  123. package/dist/collapsible-panel.d.ts +66 -0
  124. package/dist/collapsible-panel.js +63 -0
  125. package/dist/collapsible-panel.js.map +1 -0
  126. package/dist/device-class.d.ts +62 -0
  127. package/dist/device-class.js +103 -0
  128. package/dist/device-class.js.map +1 -0
  129. package/dist/disclosure-arrow.d.ts +14 -0
  130. package/dist/disclosure-arrow.js +4 -0
  131. package/dist/disclosure-arrow.js.map +1 -0
  132. package/dist/divider-sides-267FA7sY.d.ts +4 -0
  133. package/dist/empty-state.d.ts +1 -1
  134. package/dist/empty-state.js +1 -1
  135. package/dist/floating-toolbar.d.ts +28 -0
  136. package/dist/floating-toolbar.js +3 -0
  137. package/dist/floating-toolbar.js.map +1 -0
  138. package/dist/index.d.ts +20 -9
  139. package/dist/index.js +29 -18
  140. package/dist/list-action-row.d.ts +52 -0
  141. package/dist/list-action-row.js +5 -0
  142. package/dist/list-action-row.js.map +1 -0
  143. package/dist/list-header.d.ts +64 -0
  144. package/dist/list-header.js +7 -0
  145. package/dist/list-header.js.map +1 -0
  146. package/dist/list-inset-control.d.ts +16 -0
  147. package/dist/list-inset-control.js +3 -0
  148. package/dist/list-inset-control.js.map +1 -0
  149. package/dist/list-inset-text.d.ts +25 -0
  150. package/dist/list-inset-text.js +3 -0
  151. package/dist/list-inset-text.js.map +1 -0
  152. package/dist/list-item.d.ts +33 -0
  153. package/dist/list-item.js +5 -0
  154. package/dist/list-item.js.map +1 -0
  155. package/dist/list.d.ts +19 -0
  156. package/dist/list.js +3 -0
  157. package/dist/list.js.map +1 -0
  158. package/dist/loading-spinner.js +1 -1
  159. package/dist/nav-stack.d.ts +38 -0
  160. package/dist/nav-stack.js +5 -0
  161. package/dist/nav-stack.js.map +1 -0
  162. package/dist/pane.d.ts +49 -0
  163. package/dist/pane.js +4 -0
  164. package/dist/pane.js.map +1 -0
  165. package/dist/panel-header.d.ts +42 -0
  166. package/dist/panel-header.js +7 -0
  167. package/dist/panel-header.js.map +1 -0
  168. package/dist/resizable-region.d.ts +3 -1
  169. package/dist/resizable-region.js +1 -1
  170. package/dist/segmented-control.d.ts +8 -6
  171. package/dist/segmented-control.js +2 -1
  172. package/dist/select-register.d.ts +5 -1
  173. package/dist/select-register.js +3 -0
  174. package/dist/select-register.js.map +1 -1
  175. package/dist/select.d.ts +15 -6
  176. package/dist/select.js +2 -1
  177. package/dist/skeleton.d.ts +24 -0
  178. package/dist/skeleton.js +3 -0
  179. package/dist/skeleton.js.map +1 -0
  180. package/dist/split-view.d.ts +42 -0
  181. package/dist/split-view.js +81 -0
  182. package/dist/split-view.js.map +1 -0
  183. package/dist/state-banner.d.ts +8 -3
  184. package/dist/state-banner.js +2 -1
  185. package/dist/styles/app-tab.css +152 -0
  186. package/dist/styles/catalog.css +575 -0
  187. package/dist/styles/collapsible-panel.css +146 -0
  188. package/dist/styles/disclosure-arrow.css +23 -0
  189. package/dist/styles/empty-state.css +47 -0
  190. package/dist/styles/floating-toolbar.css +38 -0
  191. package/dist/styles/foundation.css +362 -0
  192. package/dist/styles/layout.css +55 -0
  193. package/dist/styles/list-action-row.css +160 -0
  194. package/dist/styles/list-header.css +160 -0
  195. package/dist/styles/list-inset-control.css +7 -0
  196. package/dist/styles/list-inset-text.css +14 -0
  197. package/dist/styles/list-item.css +123 -0
  198. package/dist/styles/list.css +43 -0
  199. package/dist/styles/loading-spinner.css +21 -0
  200. package/dist/styles/lucide-icon.css +6 -0
  201. package/dist/styles/nav-stack.css +111 -0
  202. package/dist/styles/pane.css +62 -0
  203. package/dist/styles/panel-header.css +64 -0
  204. package/dist/styles/resizable-region.css +111 -0
  205. package/{src → dist/styles}/segmented-control.css +58 -31
  206. package/dist/styles/select.css +140 -0
  207. package/dist/styles/skeleton.css +31 -0
  208. package/dist/styles/split-view.css +35 -0
  209. package/dist/styles/state-banner.css +198 -0
  210. package/dist/styles/styles.css +24 -0
  211. package/dist/styles/sunken-panel.css +22 -0
  212. package/dist/styles/tab-bar.css +45 -0
  213. package/dist/styles/tab-scaffold.css +84 -0
  214. package/dist/styles/token-search-field.css +289 -0
  215. package/dist/styles/toolbar-control-group.css +225 -0
  216. package/dist/styles/toolbar-text.css +92 -0
  217. package/dist/styles/toolbar.css +97 -0
  218. package/dist/styles/value-table.css +75 -0
  219. package/dist/styles/webawesome.css +399 -0
  220. package/dist/styles/workbench.css +94 -0
  221. package/dist/sunken-panel.d.ts +19 -0
  222. package/dist/sunken-panel.js +3 -0
  223. package/dist/sunken-panel.js.map +1 -0
  224. package/dist/tab-bar.d.ts +10 -2
  225. package/dist/tab-bar.js +1 -1
  226. package/dist/tab-scaffold.d.ts +30 -0
  227. package/dist/tab-scaffold.js +51 -0
  228. package/dist/tab-scaffold.js.map +1 -0
  229. package/dist/token-search-field.d.ts +59 -0
  230. package/dist/token-search-field.js +4 -0
  231. package/dist/token-search-field.js.map +1 -0
  232. package/dist/toolbar-control-group.d.ts +11 -5
  233. package/dist/toolbar-control-group.js +1 -1
  234. package/dist/toolbar-text.d.ts +31 -4
  235. package/dist/toolbar-text.js +2 -1
  236. package/dist/toolbar.d.ts +5 -3
  237. package/dist/toolbar.js +1 -1
  238. package/dist/value-table.d.ts +13 -3
  239. package/dist/value-table.js +2 -1
  240. package/dist/webawesome.d.ts +100 -0
  241. package/dist/webawesome.js +3 -0
  242. package/dist/webawesome.js.map +1 -0
  243. package/dist/wire-catalog.d.ts +57 -0
  244. package/dist/wire-catalog.js +302 -0
  245. package/dist/wire-catalog.js.map +1 -0
  246. package/dist/wire-nav-stack.d.ts +15 -0
  247. package/dist/wire-nav-stack.js +103 -0
  248. package/dist/wire-nav-stack.js.map +1 -0
  249. package/dist/wire-resizable-regions.d.ts +1 -1
  250. package/dist/wire-resizable-regions.js +1 -1
  251. package/dist/wire-sidebar.d.ts +43 -0
  252. package/dist/wire-sidebar.js +128 -0
  253. package/dist/wire-sidebar.js.map +1 -0
  254. package/dist/wire-tab-bars.d.ts +18 -2
  255. package/dist/wire-tab-bars.js +1 -1
  256. package/dist/wire-tab-scaffold.d.ts +11 -0
  257. package/dist/wire-tab-scaffold.js +21 -0
  258. package/dist/wire-tab-scaffold.js.map +1 -0
  259. package/dist/wire-token-search-fields.d.ts +111 -0
  260. package/dist/wire-token-search-fields.js +5 -0
  261. package/dist/wire-token-search-fields.js.map +1 -0
  262. package/dist/workbench.d.ts +33 -0
  263. package/dist/workbench.js +64 -0
  264. package/dist/workbench.js.map +1 -0
  265. package/docs/accessibility.md +124 -4
  266. package/docs/app-layouts.md +61 -0
  267. package/docs/catalog.md +364 -0
  268. package/docs/collapsible-panel.md +129 -0
  269. package/docs/component-contract.md +312 -5
  270. package/docs/component-selection.md +219 -0
  271. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  272. package/docs/design/templates/empty-state/filtered.svg +1 -0
  273. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  274. package/docs/design/templates/empty-state/with-action.svg +1 -0
  275. package/docs/design/templates/empty-state-dark.svg +1 -0
  276. package/docs/design/templates/empty-state.svg +1 -0
  277. package/docs/design/templates/list/compact-dark.svg +1 -0
  278. package/docs/design/templates/list/compact.svg +1 -0
  279. package/docs/design/templates/list/stack-dark.svg +1 -0
  280. package/docs/design/templates/list/stack.svg +1 -0
  281. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  282. package/docs/design/templates/list-action-row/default.svg +1 -0
  283. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  284. package/docs/design/templates/list-action-row/selected.svg +1 -0
  285. package/docs/design/templates/list-action-row-dark.svg +1 -0
  286. package/docs/design/templates/list-action-row.svg +1 -0
  287. package/docs/design/templates/list-dark.svg +1 -0
  288. package/docs/design/templates/list-header/action-dark.svg +1 -0
  289. package/docs/design/templates/list-header/action.svg +1 -0
  290. package/docs/design/templates/list-header/count-dark.svg +1 -0
  291. package/docs/design/templates/list-header/count.svg +1 -0
  292. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  293. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  294. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  295. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  296. package/docs/design/templates/list-header-dark.svg +1 -0
  297. package/docs/design/templates/list-header.svg +1 -0
  298. package/docs/design/templates/list-item/default-dark.svg +1 -0
  299. package/docs/design/templates/list-item/default.svg +1 -0
  300. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  301. package/docs/design/templates/list-item/multiline.svg +1 -0
  302. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  303. package/docs/design/templates/list-item/selected.svg +1 -0
  304. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  305. package/docs/design/templates/list-item/trailing.svg +1 -0
  306. package/docs/design/templates/list-item-dark.svg +1 -0
  307. package/docs/design/templates/list-item.svg +1 -0
  308. package/docs/design/templates/list.svg +1 -0
  309. package/docs/design/templates/panel-header/icon-actions-dark.svg +1 -0
  310. package/docs/design/templates/panel-header/icon-actions.svg +1 -0
  311. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +1 -0
  312. package/docs/design/templates/panel-header/icon-summary-actions.svg +1 -0
  313. package/docs/design/templates/panel-header/no-icon-dark.svg +1 -0
  314. package/docs/design/templates/panel-header/no-icon.svg +1 -0
  315. package/docs/design/templates/panel-header/page-heading-dark.svg +1 -0
  316. package/docs/design/templates/panel-header/page-heading.svg +1 -0
  317. package/docs/design/templates/panel-header/title-only-dark.svg +1 -0
  318. package/docs/design/templates/panel-header/title-only.svg +1 -0
  319. package/docs/design/templates/panel-header-dark.svg +1 -0
  320. package/docs/design/templates/panel-header.svg +1 -0
  321. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  322. package/docs/design/templates/segmented-control/equal.svg +1 -0
  323. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  324. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  325. package/docs/design/templates/segmented-control-dark.svg +1 -0
  326. package/docs/design/templates/segmented-control.svg +1 -0
  327. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  328. package/docs/design/templates/skeleton/avatar.svg +1 -0
  329. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  330. package/docs/design/templates/skeleton/block.svg +1 -0
  331. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  332. package/docs/design/templates/skeleton/lines.svg +1 -0
  333. package/docs/design/templates/skeleton-dark.svg +1 -0
  334. package/docs/design/templates/skeleton.svg +1 -0
  335. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  336. package/docs/design/templates/state-banner/danger.svg +1 -0
  337. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  338. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  339. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  340. package/docs/design/templates/state-banner/info.svg +1 -0
  341. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  342. package/docs/design/templates/state-banner/success.svg +1 -0
  343. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  344. package/docs/design/templates/state-banner/warning.svg +1 -0
  345. package/docs/design/templates/state-banner-dark.svg +1 -0
  346. package/docs/design/templates/state-banner.svg +1 -0
  347. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  348. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  349. package/docs/design/templates/tab-bar-dark.svg +1 -0
  350. package/docs/design/templates/tab-bar.svg +1 -0
  351. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  352. package/docs/design/templates/token-search-field/empty.svg +1 -0
  353. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  354. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  355. package/docs/design/templates/token-search-field-dark.svg +1 -0
  356. package/docs/design/templates/token-search-field.svg +1 -0
  357. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  358. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  359. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  360. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  361. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  362. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  363. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  364. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  365. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  366. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  367. package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
  368. package/docs/design/templates/toolbar-control-group.svg +1 -0
  369. package/docs/design/templates/toolbar-dark.svg +1 -0
  370. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  371. package/docs/design/templates/toolbar-text/default.svg +1 -0
  372. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  373. package/docs/design/templates/toolbar-text/large.svg +1 -0
  374. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  375. package/docs/design/templates/toolbar-text/small.svg +1 -0
  376. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  377. package/docs/design/templates/toolbar-text.svg +1 -0
  378. package/docs/design/templates/toolbar.svg +1 -0
  379. package/docs/design/templates/value-table/details-dark.svg +1 -0
  380. package/docs/design/templates/value-table/details.svg +1 -0
  381. package/docs/design/templates/value-table-dark.svg +1 -0
  382. package/docs/design/templates/value-table.svg +1 -0
  383. package/docs/design/templates.md +130 -0
  384. package/docs/design-philosophy.md +59 -1
  385. package/docs/device-class.md +54 -0
  386. package/docs/examples/application-ui-profile.json +60 -0
  387. package/docs/examples/command-palette-adapter.tsx +120 -0
  388. package/docs/examples/component-catalog-extension-v2.json +81 -0
  389. package/docs/examples/component-catalog-extension.json +45 -0
  390. package/docs/layout.md +150 -0
  391. package/docs/nav-stack.md +56 -0
  392. package/docs/recipes.md +167 -0
  393. package/docs/split-view.md +49 -0
  394. package/docs/sunken-panel.md +53 -0
  395. package/docs/tab-scaffold.md +50 -0
  396. package/docs/type-contracts.md +102 -0
  397. package/docs/ui-analyzer.md +86 -0
  398. package/docs/ui-doctor.md +84 -0
  399. package/docs/ui-evaluator.md +122 -0
  400. package/docs/ux-demo.md +23 -9
  401. package/docs/webawesome-theme.md +87 -7
  402. package/docs/workbench.md +73 -0
  403. package/doctor/cli.mjs +115 -0
  404. package/doctor/config.schema.json +68 -0
  405. package/doctor/eslint-diagnostics.d.mts +8 -0
  406. package/doctor/eslint-diagnostics.mjs +7 -0
  407. package/doctor/index.d.mts +116 -0
  408. package/doctor/index.mjs +1257 -0
  409. package/doctor/report.schema.json +118 -0
  410. package/evaluator/cli.mjs +89 -0
  411. package/evaluator/index.d.mts +90 -0
  412. package/evaluator/index.mjs +1138 -0
  413. package/evaluator/report.schema.json +152 -0
  414. package/llms.txt +197 -14
  415. package/package.json +228 -46
  416. package/traversal-exclusions.mjs +27 -0
  417. package/ux-demo/recipes/app-shell.tsx +228 -0
  418. package/ux-demo/recipes/collapsible-sidebar.tsx +223 -0
  419. package/ux-demo/recipes/compact-toolbar.tsx +145 -0
  420. package/ux-demo/recipes/composer-form.tsx +151 -0
  421. package/ux-demo/recipes/list-detail-dialog.tsx +181 -0
  422. package/ux-demo/recipes/list-workspace-states.tsx +183 -0
  423. package/ux-demo/recipes/loaders.ts +36 -0
  424. package/ux-demo/recipes/loading-inspector.tsx +164 -0
  425. package/ux-demo/recipes/mount-recipe.ts +64 -0
  426. package/ux-demo/recipes/navigation-sidebar.tsx +137 -0
  427. package/ux-demo/recipes/navigation-stack.tsx +118 -0
  428. package/ux-demo/recipes/recipes.css +448 -0
  429. package/ux-demo/recipes/types.ts +19 -0
  430. package/ux-demo/recipes/workspace-header.tsx +67 -0
  431. package/dist/browser/dialog-header.js +0 -3
  432. package/dist/browser/menu-header.js +0 -3
  433. package/dist/browser/menu-item.js +0 -3
  434. package/dist/browser/page-header.js +0 -3
  435. package/dist/chunk-2PES33HS.js +0 -13
  436. package/dist/chunk-2PES33HS.js.map +0 -1
  437. package/dist/chunk-3O7ZEUW2.js +0 -27
  438. package/dist/chunk-3O7ZEUW2.js.map +0 -1
  439. package/dist/chunk-4HHCYSGT.js +0 -79
  440. package/dist/chunk-4HHCYSGT.js.map +0 -1
  441. package/dist/chunk-55DATV3A.js +0 -10
  442. package/dist/chunk-55DATV3A.js.map +0 -1
  443. package/dist/chunk-723YNJBH.js +0 -17
  444. package/dist/chunk-723YNJBH.js.map +0 -1
  445. package/dist/chunk-DAFFDO33.js +0 -14
  446. package/dist/chunk-DAFFDO33.js.map +0 -1
  447. package/dist/chunk-GY5WH7TO.js +0 -10
  448. package/dist/chunk-GY5WH7TO.js.map +0 -1
  449. package/dist/chunk-MBR3TYNL.js +0 -14
  450. package/dist/chunk-MBR3TYNL.js.map +0 -1
  451. package/dist/chunk-MFKMHK5W.js +0 -10
  452. package/dist/chunk-MFKMHK5W.js.map +0 -1
  453. package/dist/chunk-MQIZAD4A.js.map +0 -1
  454. package/dist/chunk-NHXX4JI5.js +0 -28
  455. package/dist/chunk-NHXX4JI5.js.map +0 -1
  456. package/dist/chunk-OPCJRCYO.js +0 -19
  457. package/dist/chunk-OPCJRCYO.js.map +0 -1
  458. package/dist/chunk-T5XNMVOI.js +0 -24
  459. package/dist/chunk-T5XNMVOI.js.map +0 -1
  460. package/dist/chunk-TRNBHPNW.js.map +0 -1
  461. package/dist/chunk-VHW5YNIB.js +0 -17
  462. package/dist/chunk-VHW5YNIB.js.map +0 -1
  463. package/dist/chunk-VKH2JLDZ.js +0 -10
  464. package/dist/chunk-VKH2JLDZ.js.map +0 -1
  465. package/dist/chunk-WVPYVDXY.js +0 -15
  466. package/dist/chunk-WVPYVDXY.js.map +0 -1
  467. package/dist/chunk-WY4CAEPG.js +0 -14
  468. package/dist/chunk-WY4CAEPG.js.map +0 -1
  469. package/dist/dialog-header.d.ts +0 -14
  470. package/dist/dialog-header.js +0 -3
  471. package/dist/dialog-header.js.map +0 -1
  472. package/dist/menu-header.d.ts +0 -15
  473. package/dist/menu-header.js +0 -3
  474. package/dist/menu-header.js.map +0 -1
  475. package/dist/menu-item.d.ts +0 -22
  476. package/dist/menu-item.js +0 -3
  477. package/dist/menu-item.js.map +0 -1
  478. package/dist/page-header.d.ts +0 -9
  479. package/dist/page-header.js +0 -3
  480. package/dist/page-header.js.map +0 -1
  481. package/src/app-tab.css +0 -20
  482. package/src/dialog-header.css +0 -9
  483. package/src/empty-state.css +0 -6
  484. package/src/foundation.css +0 -106
  485. package/src/loading-spinner.css +0 -4
  486. package/src/lucide-icon.css +0 -1
  487. package/src/menu-header.css +0 -13
  488. package/src/menu-item.css +0 -12
  489. package/src/page-header.css +0 -3
  490. package/src/resizable-region.css +0 -19
  491. package/src/select.css +0 -18
  492. package/src/state-banner.css +0 -31
  493. package/src/styles.css +0 -18
  494. package/src/tab-bar.css +0 -4
  495. package/src/toolbar-control-group.css +0 -25
  496. package/src/toolbar-text.css +0 -4
  497. package/src/toolbar.css +0 -9
  498. package/src/value-table.css +0 -5
  499. package/src/webawesome.css +0 -178
@@ -2,17 +2,221 @@
2
2
 
3
3
  `@kerfjs/ui` components are plain functions that return Kerf `SafeHtml`. They have no component instance or lifecycle.
4
4
 
5
+ ## Selection boundary
6
+
7
+ Begin with the [need-first component matrix](./component-selection.md). Reuse a
8
+ primitive only when purpose, anatomy, state, and interaction match. Compose
9
+ public primitives for recurring layout; add a thin application adapter for
10
+ product state and policy; use custom markup when the semantic contract differs.
11
+ Recurring cross-product custom patterns belong in an upstream component or
12
+ recipe request, not in duplicated markup or selectors for undocumented anatomy.
13
+
14
+ The shipped [`component-catalog.json`](../ai/component-catalog.json) is the
15
+ canonical machine-readable inventory. Its facts are projected into the UX
16
+ catalog deterministically; package checks compare them with runtime exports,
17
+ package delivery paths, Web Awesome's installed manifest, AI guidance, and
18
+ documentation links. Nuanced prose in this contract and the selection guide
19
+ remains authored rather than generated.
20
+
21
+ ### Composition catalog v2
22
+
23
+ [`component-catalog-v2.json`](../ai/component-catalog-v2.json) adds a formal,
24
+ machine-evaluable composition layer without changing the v1 selection and
25
+ delivery contract. Every v1 entry projects once, in order, under the stable
26
+ qualified key `package:id`. Each v2 entry explicitly covers parents/contexts,
27
+ named zones and cardinality, child concepts, state ownership, required wiring,
28
+ responsive ownership, layout and geometry, accessibility obligations, public
29
+ CSS boundaries, diagnostics, and provenance.
30
+
31
+ The generator starts with permissive defaults. An `any` mode records that the
32
+ catalog has no defensible prohibition; it does not claim every composition is
33
+ recommended. Objective rules live in
34
+ `component-catalog-v2-overrides.json` and may carry stable `KUI-C###`
35
+ diagnostics. A tool reports a diagnostic only after proving its exact `when`
36
+ condition. Subjective choice, product policy, and visual taste remain prose.
37
+
38
+ V1 consumers continue unchanged. V2 consumers read v1 for selection/delivery
39
+ and v2 for composition. `npm run catalog:sync` projects every new component,
40
+ recipe, and supported Web Awesome entry, and the completeness gate prevents
41
+ silent omissions. Downstream catalogs use the v2 extension schema and types,
42
+ retain their own package identity, and qualify cross-catalog references. See
43
+ the checked
44
+ [`component-catalog-extension-v2.json`](./examples/component-catalog-extension-v2.json)
45
+ application-owned example.
46
+
47
+ ### Compile-time contract boundary
48
+
49
+ The versioned
50
+ [`compile-time-contracts-v1.json`](../ai/compile-time-contracts-v1.json)
51
+ artifact maps stable `KUI-T###` ids to public imports, emitted symbols, and
52
+ catalog identities. Its positive/negative fixture compiles against both source
53
+ and a freshly packed package, so source declarations and shipped declarations
54
+ cannot silently diverge. See [Compile-time contracts](./type-contracts.md) for
55
+ the full audit, migration guidance, and the relationships deliberately left to
56
+ runtime/catalog checks because TypeScript cannot prove them.
57
+
58
+ ### Application UI profile
59
+
60
+ The component catalogs describe what packages provide; an application profile
61
+ describes which supported choices a project has approved. A workspace may
62
+ check in `.kerf-ui-profile.json` conforming to
63
+ [`application-ui-profile.schema.json`](../ai/application-ui-profile.schema.json).
64
+ Keep package-qualified catalog locations and recurring-concept preferences,
65
+ allowed color schemes and density, public semantic-token overrides,
66
+ layout/responsive conventions, and narrow rule exceptions there. Product
67
+ records, copy, permissions, user preferences, and transport state do not belong
68
+ in this policy file.
69
+
70
+ Every catalog location names a v2 composition artifact. `selection` is optional
71
+ for consumer packages whose generated metadata declares v1 selection guidance
72
+ not applicable; `@kerfjs/ui` retains its required v1 selection artifact. This
73
+ lets a generated `component-catalog-v2.json` participate directly without a
74
+ fabricated compatibility file.
75
+
76
+ Discovery and precedence are deterministic:
77
+
78
+ 1. Load `application-ui-profile.defaults.json` from `@kerfjs/ui`.
79
+ 2. Load `.kerf-ui-profile.json` at the workspace root when present.
80
+ 3. Walk from the workspace root toward the target directory and load each
81
+ directory-local profile in parent-to-child order.
82
+
83
+ Later scalar and object-map values win. Catalogs merge by package; preferences
84
+ and token overrides merge by key; exceptions merge by stable id. Lists such as
85
+ allowed themes/densities replace the earlier list rather than accumulating.
86
+ Every resolved field retains its source file. The shipped
87
+ `application-ui-profile.mjs` API implements discovery, merge, loading, and
88
+ validation and reports actionable originating file + JSON-path diagnostics for stale
89
+ catalogs, unknown component/rule/token references, preference conflicts, and
90
+ broad exceptions. Each raw layer is validated against the catalogs effective at
91
+ that exact precedence point before merge, so a broken parent catalog, stale
92
+ parent reference, invalid value, or unknown field cannot disappear merely
93
+ because a child profile replaces it. The shipped
94
+ `application-ui-profile-sync.cjs` projects the same merge and validation contract
95
+ for synchronous hosts such as ESLint rules; it deliberately performs no async
96
+ I/O.
97
+ See the
98
+ [`application-ui-profile.json`](./examples/application-ui-profile.json) example.
99
+
100
+ Catalog detail footers use one standard resource vocabulary and order. Build
101
+ them with `catalogResources()` from `@kerfjs/ui/catalog-resources`: `Demo source`
102
+ first, optional `Component source` and `Design template`, then `Guidance`.
103
+ Third-party entries use the typed `integrationGuidance` kind, which renders
104
+ `Integration guidance`, and omit `Component source` when the implementation is
105
+ not owned by the catalog's project. Prefer these semantic kinds over local labels
106
+ such as “View source” or “Read UI guidance”; the helper makes that convention a
107
+ compile-time choice while still returning ordinary `CatalogResource[]` values.
108
+
5
109
  ## Ownership boundaries
6
110
 
111
+ ### Geometry ownership metadata
112
+
113
+ The canonical [`component-catalog.json`](../ai/component-catalog.json) records
114
+ the margin, border, and padding owner for every component and composition under
115
+ `geometry`. Read it before adding a wrapper or local spacing rule:
116
+
117
+ - `self` means the entry's public visual contract supplies that geometry.
118
+ - `parent` means the embedding layout must supply it.
119
+ - `child` means composed descendants supply it; the entry's outer shell does not.
120
+ - `none` means that dimension is intentionally absent from the standard contract.
121
+ - `conditional` means a variant, part, or configuration changes ownership; the
122
+ accompanying `notes` explain the boundary.
123
+
124
+ The values describe public ownership, including themed shadow parts, rather
125
+ than merely asking whether a CSS declaration appears on the host element.
126
+ Recipes are exempt because they arrange entries whose individual ownership is
127
+ already cataloged.
128
+
129
+ Downstream packages and applications should publish the same contract for their
130
+ reusable visual components. Use
131
+ [`component-catalog-extension.schema.json`](../ai/component-catalog-extension.schema.json)
132
+ and copy the structure of the checked
133
+ [`component-catalog-extension.json`](./examples/component-catalog-extension.json)
134
+ example. Keep app and Kerf entries as package-qualified inputs, then let people
135
+ or AI tools search their combined entries and compare `geometry` before adding
136
+ wrappers or insets. Do not add app-owned entries to Kerf's canonical catalog or
137
+ claim Kerf delivery paths for them.
138
+
7
139
  - Components own semantic markup, stable anatomy, documented variants, ARIA projection, and package CSS hooks.
8
140
  - Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
9
141
  - Actions are `data-action` strings. Wire them at a stable root with `delegate()` or `delegateActions()` and retain the disposer.
10
142
  - A reusable component never owns per-instance mutable module state.
11
- - Consumers style through `--kui-*` semantic tokens and public component classes. Foundation tokens provide opinionated neutral, brand/info, success, warning, and danger fill/border/foreground roles. Stateful components expose local override variables; do not target private descendants when a documented variant or token exists.
143
+ - Consumers style through `--kui-*` semantic tokens and public component classes. Foundation tokens provide opinionated neutral, brand/info, success, warning, and danger fill/border/foreground roles. Stateful components expose local override variables; prefer an equivalent prop or token before writing a selector.
144
+
145
+ `ListItem.rootAttributes`, `ListActionRow.rootAttributes`,
146
+ `ListHeader.rootAttributes`, `AppTab.rootAttributes`,
147
+ `CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` accept
148
+ application-owned `data-*` metadata without
149
+ adding product fields to the shared API. A `ListActionRow` trailing action uses
150
+ `trailingActionAttributes`, and a `ListHeader` action/disclosure uses
151
+ `triggerAttributes`, for `data-*`, native popover target/action attributes, and
152
+ the corresponding `aria-controls`/`aria-haspopup` relationship. These slots do
153
+ not accept roles or component-owned action, selection, disclosure, accessible
154
+ name, disabled, or icon fields. Extension objects are filtered at runtime,
155
+ including case-insensitive rejection of protected `data-*` names, and the
156
+ component or helper writes its protected attributes after the accepted metadata. Typed,
157
+ structurally widened, and JavaScript callers therefore cannot replace its
158
+ contract.
159
+
160
+ `AppTab.closeIcon` and `ResizableRegion.handleIcon` replace dormant decorative
161
+ glyph content only. They must not contain controls or interactive roles. The
162
+ component continues to own the named close button or focusable separator, and
163
+ `wireTabBars()` / `wireResizableRegions()` continue to own transient behavior
164
+ and disposal.
165
+
166
+ `ListItem.trailing`, `ListActionRow.label`, `ListActionRow.icon`, and
167
+ `ListActionRow.trailingActionIcon` are dormant SafeHtml slots. They must not
168
+ contain controls. When a row needs an independently interactive trailing
169
+ region, `ListActionRow` owns the noninteractive root and the two sibling native
170
+ buttons; the application owns their delegated behavior and controlled state.
171
+ Both row components align a leading icon with the first label line when
172
+ `multiline` allows the label to wrap; additional lines extend below that fixed
173
+ visual anchor.
174
+
175
+ ### Public CSS anatomy
176
+
177
+ The `publicClasses` array on each entry in
178
+ [`component-catalog.json`](../ai/component-catalog.json) is the exact supported
179
+ anatomy boundary. A scoped selector may join documented public classes, such as
180
+ `.workspace .kui-toolbar .kui-toolbar__trailing`, when composition-specific
181
+ layout cannot be expressed by a prop or token. A class being public does not
182
+ make copied component markup an invocation or transfer state and accessibility
183
+ ownership to the application.
184
+
185
+ The v2 composition catalog additionally requires `boundaries.rootClass` to be
186
+ either one exact member of `publicClasses` or `null` when the entry has no
187
+ rendered class root. Runtime geometry tooling uses this explicit field; array
188
+ order never implies root ownership.
189
+
190
+ Do not select a component's descendant by element name, id, attribute alone, or
191
+ an unlisted implementation class. Selectors such as `.kui-state-banner span`,
192
+ `.kui-list-item [data-state]`, and `.kui-list-item .local-label` depend on
193
+ private structure. If no prop, token, or cataloged class expresses a recurring
194
+ need, request a supported hook instead of inferring one from rendered markup.
195
+
196
+ `ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
197
+ default while retaining the row's 44px minimum interactive target. Multiline
198
+ rows align that 18px visual with the first inherited text line.
199
+
200
+ `DisclosureArrow` uses an 18px root-scaled visual by default. Override
201
+ `--kui-disclosure-arrow-size` on the component or its containing scope when a
202
+ consumer needs another size. Kerf `Select` uses a separate Web Awesome expand
203
+ glyph contract, `--kui-disclosure-icon-scale: .5`; changing one contract does
204
+ not implicitly change the other. Direction changes take the shortest rotation
205
+ path; a 180-degree closed-to-open tie uses counterclockwise rotation.
206
+
207
+ In `ListHeader` toggle mode, omitting `actionIcon` composes the production
208
+ `DisclosureArrow` and derives its visual direction from `expanded`. The app
209
+ must update that controlled state and reveal or hide real content. Passing a
210
+ custom `actionIcon` replaces the default rather than layering or rotating both.
211
+ The root fills the available inline width after its standard margins. A
212
+ separate action stays at the logical end in its 44px target while the visible
213
+ glyph defaults to 18px through `--kui-list-header-action-icon-size`.
12
214
 
13
215
  `StateBanner` exposes instance-level `--kui-state-banner-background`,
14
216
  `--kui-state-banner-border`, `--kui-state-banner-foreground`,
15
- `--kui-state-banner-detail`, and action background variables. Its five built-in
217
+ `--kui-state-banner-detail`, `--kui-state-banner-badge-background`,
218
+ `--kui-state-banner-badge-foreground`, and action background variables. Its optional
219
+ badge is a compact pill beside the title and follows the banner tone by default. Its five built-in
16
220
  tones can be rethemed globally with
17
221
  `--kui-state-banner-{tone}-{background|border|foreground}`. Toolbar control,
18
222
  segmented-control, app-tab, and tab-bar colors likewise use their public
@@ -27,11 +231,61 @@ separator with a compact grip that appears on hover or keyboard focus. Override
27
231
  `--kui-resizable-region-handle-active-color` on a region when its containing
28
232
  surface needs a different contrast level.
29
233
 
234
+ `Pane` defines one structural model for sidebars, main areas, inspectors, and
235
+ dialogs. Its `.kui-pane` root is unpadded and contains an optional vertical
236
+ header, one scrolling vertical `.kui-pane__content`, and an optional footer.
237
+ Logical-edge separator lines are independently opt-in and default off.
238
+ `@kerfjs/ui/layout.css` retains the pane roles and supplies the related content
239
+ geometry classes.
240
+ `List` is the corresponding layout-only vertical stack: its children stretch by
241
+ default, while `gap`, `flex`, and `scrollable` opt into standard/custom spacing,
242
+ flex growth, and vertical scroll ownership. `dividerSides` accepts canonical
243
+ physical top/right/bottom/left combinations such as `tr` and `trbl`; the stack
244
+ adds no list semantics, margin, or padding of its own. String props receive
245
+ browser CSS, so use `gap="var(--kui-space-2xs)"` for the root-scaled 4px token or
246
+ `gap="0.25rem"`; source-only `remify(4px)` is not valid at runtime.
247
+ `.kui-content` gives major children 24px vertical separation.
248
+ `.kui-content-item` gives one child 8px inline margin, a real 1px border,
249
+ 8px padding, and 12px corners; border and background may be transparent without
250
+ changing geometry. `.kui-content-item--pill` selects the 22px radius.
251
+
252
+ `ToolbarControlGroup` is the unit of toolbar organization, even for dormant
253
+ text. Each group reserves `calc(2px + remify(42px))`, or 44px, with 8px between
254
+ groups and inside items. For an ordinary icon/action control inside a group, use
255
+ a plain `<button>` — the group styles `> button` fully, and it keeps the group
256
+ free of a Web Awesome dependency and shadow DOM. Reach for `wa-button` only when
257
+ you need a Web Awesome feature, chiefly the `slot="trigger"` button of a
258
+ `wa-dropdown` popup menu. `ListHeader` similarly separates its dormant title and
259
+ optional count or badge from its optional 44px action. Use the mutually
260
+ exclusive `count`/`countLabel` pair for non-negative safe-integer section
261
+ quantities; reserve `badge` for non-count `SafeHtml`. Do not concatenate counts
262
+ into the section label. Do not add padding to pane shells,
263
+ double child-owned geometry with wrapper insets, or create competing scroll
264
+ owners. The [layout contract](./layout.md) lists the public roles and tokens.
265
+
266
+ `PanelHeader` is a plain top `Toolbar` used as a panel, dialog, or page heading;
267
+ it overrides no Toolbar styles. The leading zone holds an optional icon (a normal
268
+ bordered `ToolbarControlGroup` given a brand fill with a matching border) and the
269
+ title as extra-large `ToolbarText`, and the app's `actions` go straight into the
270
+ trailing zone (typically as a `ToolbarControlGroup`). The icon group is omitted
271
+ when no icon is passed. The optional summary is a separate row aligned below the
272
+ title, so it cannot pull the icon group out of vertical alignment with the
273
+ title and action row.
274
+
275
+ `ValueTable` composes typed `ValueTableRow` entries. A row owns its `dt`/`dd`
276
+ semantics and may receive a leading `SafeHtml` icon. Every row keeps 8px of
277
+ root-scaled padding above and below its content; the shared item-padding token
278
+ continues to own its inline inset. Separators follow the content they introduce:
279
+ 8px from either edge for an iconless row, or 40px from the left edge (8px
280
+ padding + 24px icon + 8px gap) and 8px from the right edge for an icon-bearing
281
+ row. Applications own the values, formatting, and whether an icon is decorative
282
+ or meaningfully labeled.
283
+
30
284
  ## Imports and side effects
31
285
 
32
286
  Every component has an explicit JS and CSS subpath. In CSS-aware browser builds,
33
287
  the JS component subpath resolves to a generated wrapper that imports the
34
- foundation, the component stylesheet, and styles for its reachable UI
288
+ foundation, the compiled component stylesheet from `dist/styles`, and styles for its reachable UI
35
289
  subcomponents. The source graph derives those transitive styles at build time;
36
290
  an application root never maintains that list. Unused component subpaths and
37
291
  their CSS remain unreachable. The root barrel and `@kerfjs/ui/unstyled` stay
@@ -41,23 +295,76 @@ overrides load later in the cascade or set scoped `--kui-*` variables. JavaScrip
41
295
  modules are pure except the browser style wrappers and `@kerfjs/ui/select/register`,
42
296
  which registers exactly the Web Awesome elements used by `Select`. Eventful
43
297
  helpers such as `wireResizableRegions` and `wireTabBars` attach listeners only
44
- when called and return disposers. CSS, the generated wrappers that make it
298
+ when called and return disposers. `wireTokenSearchFields` goes one step further:
299
+ by default it also owns the collapsible field's transient expand/collapse/focus
300
+ (activate to reveal and focus, Escape or empty blur to collapse), holding that
301
+ state in a signal it exposes on the returned handle. An app reads that signal in
302
+ render, hands in its own via `collapsible.signals`, drives it through
303
+ `handle.open`/`handle.close`, or disables any individual behavior — so transient
304
+ UI is consistent by default without every app reinventing it.
305
+
306
+ `wireTokenSearchFields` is a deliberate exception, not the rule for `wire…`
307
+ helpers. Its collapse behavior was _rich and error-prone_ — reveal, focus
308
+ transfer, Escape, empty-blur collapse, focus return — the kind of transient chrome
309
+ apps kept reimplementing inconsistently, so the helper owns it. Everywhere else the
310
+ app's state is **domain or persisted, not transient chrome, and stays app-owned**: a
311
+ `NavStack`'s view stack is navigation history, a `TabBar`/`TabScaffold`'s selection
312
+ and tab order are data, a `ResizableRegion`'s committed size and a
313
+ `Workbench`/`SplitView` rail's `collapsed` flag are persisted layout preferences.
314
+ Each helper already owns only the _ephemeral mechanics_ around that state —
315
+ `wireNavStack` the push/pop animation, `wireTabBars` the overflow autoscroll and
316
+ drag preview, `wireResizableRegions` the live drag preview — and reports committed
317
+ changes through callbacks. A `ListHeader` `toggle` disclosure's `expanded` is
318
+ likewise app-owned: it is a one-line boolean the app already tracks and must read to
319
+ render the section body, so a managed helper would remove no real complexity. Reach
320
+ for a managed default only when the transient behavior is substantial enough that
321
+ hand-rolling it produces genuine, inconsistent variation.
322
+
323
+ CSS, the generated wrappers that make it
45
324
  reachable, and the registration module are the package's only declared side
46
325
  effects.
47
326
 
327
+ A value-bearing component's `placeholder` prop is a first-class loading mode: the
328
+ component renders its own real chrome (labels, icon and action affordances,
329
+ container geometry) while replacing each **value** slot with a subtle, deliberately
330
+ unanimated `Skeleton` block and disabling its own interactive controls
331
+ (`aria-busy`, dropped `data-action`, disabled buttons). Sizes and shapes stay
332
+ identical to the populated component, so a parent composes a faithful loading view —
333
+ an inspector, a detail pane — from placeholder children without hand-rebuilding
334
+ markup. The application still owns the loading lifecycle (when to pass `placeholder`)
335
+ and which slots are unknown; the standalone `Skeleton` covers custom slots. It is a
336
+ placeholder, not progress: use `LoadingSpinner` for known busy activity, and never
337
+ animate the skeleton.
338
+
339
+ Package source styles express root-scaled geometry with `remify(<px>)`; the
340
+ build converts it against the 16px authoring baseline and exposes only ordinary
341
+ `rem` CSS. Literal pixels remain for intentional hairlines, and `em` remains
342
+ explicit when a value is relative to its component's current font size. The UX
343
+ catalog applies the same transform to source CSS under Vite so `npm run dev`
344
+ retains hot module replacement.
345
+
48
346
  `@kerfjs/ui/webawesome.css` is a separate, optional CSS boundary. It imports
49
347
  Web Awesome's public base stylesheet and overrides its semantic theme layer to
50
348
  match the Kerf/Hot Sheet 2 system. It never imports component JavaScript.
349
+ `import type {} from '@kerfjs/ui/webawesome'` is the matching side-effect-free
350
+ Kerf JSX declaration boundary for every catalog-supported `wa-*` tag.
51
351
  Consumers register only the individual Web Awesome modules they render and can
52
352
  override `--wa-*` values after the theme import. The shared `--wa-*` values feed
53
353
  both Web Awesome controls and Kerf's `--kui-*` foundation aliases, preventing a
54
354
  second application palette.
55
355
 
356
+ `Select` owns its custom-element reconciliation seam. It gives each slotted
357
+ option icon a stable key and leaves the upgraded Web Awesome-owned slot subtree
358
+ untouched on later Kerf renders. Its custom selected slot is keyed by the
359
+ controlled value so changed selections replace that content. Applications
360
+ should pass ordinary `choices` and `renderSelected` output rather than adding
361
+ their own morph-control attributes.
362
+
56
363
  `kerfjs` is a peer dependency and remains external in every build. Importing a toolbar must not bundle a second Kerf runtime, another UI component, Web Awesome registration, the UX catalog, or development tooling.
57
364
 
58
365
  ## Extracted versus application-specific
59
366
 
60
- The package set is intentionally domain-neutral: icon rendering, toolbar primitives, controlled segmented choices, menu rows/headers, resizable regions and wiring, controlled reorderable tab bars, headers, loading, select, banners, empty states, dialog headers, and value tables.
367
+ The package set is intentionally domain-neutral: icon rendering, toolbar primitives, controlled segmented choices, a controlled token-chip search field with DOM read/caret helpers, menu rows/headers, resizable regions and wiring, controlled reorderable tab bars, headers, loading, select, banners, empty states, dialog headers, and typed value-table rows.
61
368
 
62
369
  Keep product adapters outside the package: connection-state maps, ticket empty-state copy, project/terminal/chat tab actions, saved pane sizes, provider or repository models, and application-specific palettes. An adapter may compose these primitives, map product state into their props, and override semantic CSS variables.
63
370