@kerfjs/ui 5.0.0-beta.4 → 5.0.0-beta.40

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 (498) hide show
  1. package/README.md +342 -108
  2. package/ai/application-ui-diagnostic-ids-v1.json +100 -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 +132 -0
  12. package/ai/compile-time-contracts-v1.schema.json +51 -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 +496 -0
  17. package/ai/component-catalog-v2.d.ts +90 -0
  18. package/ai/component-catalog-v2.json +5678 -0
  19. package/ai/component-catalog-v2.schema.json +298 -0
  20. package/ai/component-catalog.json +2694 -417
  21. package/ai/component-catalog.schema.json +39 -0
  22. package/ai/public-api-signatures-v1.md +1591 -126
  23. package/ai/skill.md +140 -54
  24. package/ai/webawesome-jsx-signatures-v1.md +2 -1
  25. package/analyzer/cli.mjs +49 -0
  26. package/analyzer/index.d.mts +46 -0
  27. package/analyzer/index.mjs +1086 -0
  28. package/analyzer/report.schema.json +66 -0
  29. package/dist/app-tab.d.ts +15 -4
  30. package/dist/app-tab.js +3 -1
  31. package/dist/browser/app-tab.js +1 -0
  32. package/dist/browser/floating-toolbar.js +3 -0
  33. package/dist/browser/list-action-row.js +5 -0
  34. package/dist/browser/list-header.js +7 -0
  35. package/dist/browser/list-inset-control.js +3 -0
  36. package/dist/browser/list-inset-text.js +3 -0
  37. package/dist/browser/list-item.js +5 -0
  38. package/dist/browser/list.js +3 -0
  39. package/dist/browser/pane.js +3 -0
  40. package/dist/browser/row.js +3 -0
  41. package/dist/browser/segmented-control.js +1 -0
  42. package/dist/browser/select.js +1 -0
  43. package/dist/browser/skeleton.js +3 -0
  44. package/dist/browser/spacer.js +3 -0
  45. package/dist/browser/state-banner.js +1 -0
  46. package/dist/browser/sunken-panel.js +3 -0
  47. package/dist/browser/surface-scaffold.js +3 -0
  48. package/dist/browser/text.js +3 -0
  49. package/dist/browser/toolbar-text.js +1 -0
  50. package/dist/browser/value-table.js +1 -0
  51. package/dist/catalog-resources.d.ts +35 -0
  52. package/dist/catalog-resources.js +22 -0
  53. package/dist/catalog-resources.js.map +1 -0
  54. package/dist/catalog.d.ts +151 -0
  55. package/dist/catalog.js +396 -0
  56. package/dist/catalog.js.map +1 -0
  57. package/dist/chunk-2TYUFZUC.js +22 -0
  58. package/dist/chunk-2TYUFZUC.js.map +1 -0
  59. package/dist/chunk-6NDBE2OK.js +32 -0
  60. package/dist/chunk-6NDBE2OK.js.map +1 -0
  61. package/dist/chunk-6WTETUZ6.js +21 -0
  62. package/dist/chunk-6WTETUZ6.js.map +1 -0
  63. package/dist/chunk-AQFWBG23.js +83 -0
  64. package/dist/chunk-AQFWBG23.js.map +1 -0
  65. package/dist/chunk-B6JYRX3P.js +51 -0
  66. package/dist/chunk-B6JYRX3P.js.map +1 -0
  67. package/dist/chunk-C34NZOLJ.js +53 -0
  68. package/dist/chunk-C34NZOLJ.js.map +1 -0
  69. package/dist/chunk-CAB6NQ2T.js +102 -0
  70. package/dist/chunk-CAB6NQ2T.js.map +1 -0
  71. package/dist/chunk-CK6P5AUK.js +136 -0
  72. package/dist/chunk-CK6P5AUK.js.map +1 -0
  73. package/dist/chunk-DAO2VFTT.js +129 -0
  74. package/dist/chunk-DAO2VFTT.js.map +1 -0
  75. package/dist/chunk-DEYOGDE7.js +141 -0
  76. package/dist/chunk-DEYOGDE7.js.map +1 -0
  77. package/dist/chunk-DYBPI5O2.js +25 -0
  78. package/dist/chunk-DYBPI5O2.js.map +1 -0
  79. package/dist/{chunk-TRNBHPNW.js → chunk-E34TE2ZI.js} +12 -8
  80. package/dist/chunk-E34TE2ZI.js.map +1 -0
  81. package/dist/chunk-EYALJQQD.js +25 -0
  82. package/dist/chunk-EYALJQQD.js.map +1 -0
  83. package/dist/chunk-I45QO2IZ.js +88 -0
  84. package/dist/chunk-I45QO2IZ.js.map +1 -0
  85. package/dist/chunk-I4V3UDSA.js +79 -0
  86. package/dist/chunk-I4V3UDSA.js.map +1 -0
  87. package/dist/chunk-OGTJNHRG.js +42 -0
  88. package/dist/chunk-OGTJNHRG.js.map +1 -0
  89. package/dist/chunk-OL4TC3U2.js +156 -0
  90. package/dist/chunk-OL4TC3U2.js.map +1 -0
  91. package/dist/chunk-OMSRSL3B.js +120 -0
  92. package/dist/chunk-OMSRSL3B.js.map +1 -0
  93. package/dist/chunk-R3EBGEAW.js +46 -0
  94. package/dist/chunk-R3EBGEAW.js.map +1 -0
  95. package/dist/chunk-SOK5EUF7.js +25 -0
  96. package/dist/chunk-SOK5EUF7.js.map +1 -0
  97. package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
  98. package/dist/chunk-SRSJO5QE.js.map +1 -0
  99. package/dist/chunk-T7DOWS6T.js +61 -0
  100. package/dist/chunk-T7DOWS6T.js.map +1 -0
  101. package/dist/chunk-TIGSG6BX.js +218 -0
  102. package/dist/chunk-TIGSG6BX.js.map +1 -0
  103. package/dist/chunk-UDHHKZWO.js +41 -0
  104. package/dist/chunk-UDHHKZWO.js.map +1 -0
  105. package/dist/{chunk-MQIZAD4A.js → chunk-UKKSMZYT.js} +76 -22
  106. package/dist/chunk-UKKSMZYT.js.map +1 -0
  107. package/dist/chunk-V6GQKOX2.js +39 -0
  108. package/dist/chunk-V6GQKOX2.js.map +1 -0
  109. package/dist/chunk-V6HCTCVD.js +46 -0
  110. package/dist/chunk-V6HCTCVD.js.map +1 -0
  111. package/dist/chunk-VDUJZF5G.js +515 -0
  112. package/dist/chunk-VDUJZF5G.js.map +1 -0
  113. package/dist/chunk-VXFGMDA7.js +31 -0
  114. package/dist/chunk-VXFGMDA7.js.map +1 -0
  115. package/dist/chunk-WN52USHV.js +115 -0
  116. package/dist/chunk-WN52USHV.js.map +1 -0
  117. package/dist/chunk-WSXUPSID.js +43 -0
  118. package/dist/chunk-WSXUPSID.js.map +1 -0
  119. package/dist/chunk-X5GRDQ7V.js +50 -0
  120. package/dist/chunk-X5GRDQ7V.js.map +1 -0
  121. package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
  122. package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
  123. package/dist/chunk-ZASJJMGV.js +17 -0
  124. package/dist/chunk-ZASJJMGV.js.map +1 -0
  125. package/dist/chunk-ZPWZIVI6.js +47 -0
  126. package/dist/chunk-ZPWZIVI6.js.map +1 -0
  127. package/dist/collapsible-panel.d.ts +77 -0
  128. package/dist/collapsible-panel.js +84 -0
  129. package/dist/collapsible-panel.js.map +1 -0
  130. package/dist/css-values.d.ts +75 -0
  131. package/dist/css-values.js +3 -0
  132. package/dist/css-values.js.map +1 -0
  133. package/dist/device-class.d.ts +62 -0
  134. package/dist/device-class.js +103 -0
  135. package/dist/device-class.js.map +1 -0
  136. package/dist/disclosure-arrow.js +1 -1
  137. package/dist/divider-sides-BzB6rphT.d.ts +6 -0
  138. package/dist/empty-state.d.ts +3 -2
  139. package/dist/empty-state.js +1 -1
  140. package/dist/flex-alignment-CF8NLj7i.d.ts +4 -0
  141. package/dist/floating-toolbar.d.ts +29 -0
  142. package/dist/floating-toolbar.js +3 -0
  143. package/dist/floating-toolbar.js.map +1 -0
  144. package/dist/index.d.ts +28 -14
  145. package/dist/index.js +34 -23
  146. package/dist/{menu-action-row.d.ts → list-action-row.d.ts} +19 -8
  147. package/dist/list-action-row.js +7 -0
  148. package/dist/list-action-row.js.map +1 -0
  149. package/dist/list-header.d.ts +80 -0
  150. package/dist/list-header.js +9 -0
  151. package/dist/list-header.js.map +1 -0
  152. package/dist/list-inset-control.d.ts +20 -0
  153. package/dist/list-inset-control.js +3 -0
  154. package/dist/list-inset-control.js.map +1 -0
  155. package/dist/list-inset-text.d.ts +29 -0
  156. package/dist/list-inset-text.js +3 -0
  157. package/dist/list-inset-text.js.map +1 -0
  158. package/dist/list-item.d.ts +45 -0
  159. package/dist/list-item.js +7 -0
  160. package/dist/list-item.js.map +1 -0
  161. package/dist/list.d.ts +30 -0
  162. package/dist/list.js +5 -0
  163. package/dist/list.js.map +1 -0
  164. package/dist/loading-spinner.js +1 -1
  165. package/dist/nav-stack.d.ts +41 -0
  166. package/dist/nav-stack.js +6 -0
  167. package/dist/nav-stack.js.map +1 -0
  168. package/dist/pane.d.ts +50 -0
  169. package/dist/pane.js +4 -0
  170. package/dist/pane.js.map +1 -0
  171. package/dist/resizable-region.d.ts +21 -3
  172. package/dist/resizable-region.js +1 -1
  173. package/dist/row.d.ts +28 -0
  174. package/dist/row.js +5 -0
  175. package/dist/row.js.map +1 -0
  176. package/dist/segmented-control.d.ts +11 -8
  177. package/dist/segmented-control.js +3 -1
  178. package/dist/select-register.d.ts +5 -1
  179. package/dist/select-register.js +129 -1
  180. package/dist/select-register.js.map +1 -1
  181. package/dist/select.d.ts +34 -8
  182. package/dist/select.js +3 -1
  183. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  184. package/dist/skeleton.d.ts +25 -0
  185. package/dist/skeleton.js +4 -0
  186. package/dist/skeleton.js.map +1 -0
  187. package/dist/spacer.d.ts +16 -0
  188. package/dist/spacer.js +4 -0
  189. package/dist/spacer.js.map +1 -0
  190. package/dist/split-view.d.ts +43 -0
  191. package/dist/split-view.js +82 -0
  192. package/dist/split-view.js.map +1 -0
  193. package/dist/state-banner.d.ts +11 -5
  194. package/dist/state-banner.js +3 -1
  195. package/dist/styles/app-tab.css +26 -0
  196. package/dist/styles/catalog.css +582 -0
  197. package/dist/styles/collapsible-panel.css +212 -0
  198. package/dist/styles/floating-toolbar.css +38 -0
  199. package/dist/styles/foundation.css +80 -0
  200. package/dist/styles/layout.css +2 -20
  201. package/dist/styles/list-action-row.css +224 -0
  202. package/dist/styles/list-header.css +224 -0
  203. package/dist/styles/list-inset-control.css +23 -0
  204. package/dist/styles/list-inset-text.css +30 -0
  205. package/dist/styles/list-item.css +171 -0
  206. package/dist/styles/list.css +118 -0
  207. package/dist/styles/nav-stack.css +141 -0
  208. package/dist/styles/pane.css +62 -0
  209. package/dist/styles/resizable-region.css +158 -0
  210. package/dist/styles/row.css +92 -0
  211. package/dist/styles/segmented-control.css +10 -7
  212. package/dist/styles/select.css +115 -2
  213. package/dist/styles/skeleton.css +31 -0
  214. package/dist/styles/spacer.css +11 -0
  215. package/dist/styles/split-view.css +35 -0
  216. package/dist/styles/state-banner.css +49 -10
  217. package/dist/styles/styles.css +10 -5
  218. package/dist/styles/sunken-panel.css +22 -0
  219. package/dist/styles/surface-scaffold.css +51 -0
  220. package/dist/styles/tab-bar.css +24 -0
  221. package/dist/styles/tab-scaffold.css +85 -0
  222. package/dist/styles/text.css +5 -0
  223. package/dist/styles/token-search-field.css +14 -2
  224. package/dist/styles/toolbar-control-group.css +235 -8
  225. package/dist/styles/toolbar-text.css +65 -2
  226. package/dist/styles/toolbar.css +47 -2
  227. package/dist/styles/webawesome.css +171 -0
  228. package/dist/styles/workbench.css +187 -0
  229. package/dist/sunken-panel.d.ts +20 -0
  230. package/dist/sunken-panel.js +3 -0
  231. package/dist/sunken-panel.js.map +1 -0
  232. package/dist/surface-scaffold.d.ts +26 -0
  233. package/dist/surface-scaffold.js +3 -0
  234. package/dist/surface-scaffold.js.map +1 -0
  235. package/dist/tab-bar.d.ts +24 -6
  236. package/dist/tab-bar.js +1 -1
  237. package/dist/tab-scaffold.d.ts +31 -0
  238. package/dist/tab-scaffold.js +51 -0
  239. package/dist/tab-scaffold.js.map +1 -0
  240. package/dist/text.d.ts +20 -0
  241. package/dist/text.js +3 -0
  242. package/dist/text.js.map +1 -0
  243. package/dist/token-search-field.d.ts +30 -13
  244. package/dist/token-search-field.js +1 -1
  245. package/dist/toolbar-control-group.d.ts +33 -7
  246. package/dist/toolbar-control-group.js +1 -1
  247. package/dist/toolbar-text.d.ts +31 -4
  248. package/dist/toolbar-text.js +3 -1
  249. package/dist/toolbar.d.ts +10 -7
  250. package/dist/toolbar.js +1 -1
  251. package/dist/value-table.d.ts +7 -3
  252. package/dist/value-table.js +3 -1
  253. package/dist/webawesome.d.ts +1 -0
  254. package/dist/wire-catalog.d.ts +57 -0
  255. package/dist/wire-catalog.js +302 -0
  256. package/dist/wire-catalog.js.map +1 -0
  257. package/dist/wire-nav-stack.d.ts +18 -0
  258. package/dist/wire-nav-stack.js +228 -0
  259. package/dist/wire-nav-stack.js.map +1 -0
  260. package/dist/wire-resizable-regions.d.ts +1 -1
  261. package/dist/wire-resizable-regions.js +1 -1
  262. package/dist/wire-sidebar.d.ts +48 -0
  263. package/dist/wire-sidebar.js +147 -0
  264. package/dist/wire-sidebar.js.map +1 -0
  265. package/dist/wire-tab-bars.d.ts +19 -2
  266. package/dist/wire-tab-bars.js +1 -1
  267. package/dist/wire-tab-scaffold.d.ts +11 -0
  268. package/dist/wire-tab-scaffold.js +21 -0
  269. package/dist/wire-tab-scaffold.js.map +1 -0
  270. package/dist/wire-token-search-fields.d.ts +104 -4
  271. package/dist/wire-token-search-fields.js +1 -1
  272. package/dist/workbench.d.ts +44 -0
  273. package/dist/workbench.js +106 -0
  274. package/dist/workbench.js.map +1 -0
  275. package/docs/accessibility.md +155 -20
  276. package/docs/app-layouts.md +61 -0
  277. package/docs/catalog.md +364 -0
  278. package/docs/collapsible-panel.md +142 -0
  279. package/docs/component-contract.md +258 -28
  280. package/docs/component-integration.md +63 -0
  281. package/docs/component-selection.md +219 -57
  282. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  283. package/docs/design/templates/empty-state/filtered.svg +1 -0
  284. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  285. package/docs/design/templates/empty-state/with-action.svg +1 -0
  286. package/docs/design/templates/empty-state-dark.svg +1 -0
  287. package/docs/design/templates/empty-state.svg +1 -0
  288. package/docs/design/templates/list/compact-dark.svg +1 -0
  289. package/docs/design/templates/list/compact.svg +1 -0
  290. package/docs/design/templates/list/stack-dark.svg +1 -0
  291. package/docs/design/templates/list/stack.svg +1 -0
  292. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  293. package/docs/design/templates/list-action-row/default.svg +1 -0
  294. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  295. package/docs/design/templates/list-action-row/selected.svg +1 -0
  296. package/docs/design/templates/list-action-row-dark.svg +1 -0
  297. package/docs/design/templates/list-action-row.svg +1 -0
  298. package/docs/design/templates/list-dark.svg +1 -0
  299. package/docs/design/templates/list-header/action-dark.svg +1 -0
  300. package/docs/design/templates/list-header/action.svg +1 -0
  301. package/docs/design/templates/list-header/count-dark.svg +1 -0
  302. package/docs/design/templates/list-header/count.svg +1 -0
  303. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  304. package/docs/design/templates/list-header/inline-action.svg +1 -0
  305. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  306. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  307. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  308. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  309. package/docs/design/templates/list-header-dark.svg +1 -0
  310. package/docs/design/templates/list-header.svg +1 -0
  311. package/docs/design/templates/list-item/default-dark.svg +1 -0
  312. package/docs/design/templates/list-item/default.svg +1 -0
  313. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  314. package/docs/design/templates/list-item/multiline.svg +1 -0
  315. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  316. package/docs/design/templates/list-item/selected.svg +1 -0
  317. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  318. package/docs/design/templates/list-item/trailing.svg +1 -0
  319. package/docs/design/templates/list-item-dark.svg +1 -0
  320. package/docs/design/templates/list-item.svg +1 -0
  321. package/docs/design/templates/list.svg +1 -0
  322. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  323. package/docs/design/templates/segmented-control/equal.svg +1 -0
  324. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  325. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  326. package/docs/design/templates/segmented-control-dark.svg +1 -0
  327. package/docs/design/templates/segmented-control.svg +1 -0
  328. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  329. package/docs/design/templates/skeleton/avatar.svg +1 -0
  330. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  331. package/docs/design/templates/skeleton/block.svg +1 -0
  332. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  333. package/docs/design/templates/skeleton/lines.svg +1 -0
  334. package/docs/design/templates/skeleton-dark.svg +1 -0
  335. package/docs/design/templates/skeleton.svg +1 -0
  336. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  337. package/docs/design/templates/state-banner/danger.svg +1 -0
  338. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  339. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  340. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  341. package/docs/design/templates/state-banner/info.svg +1 -0
  342. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  343. package/docs/design/templates/state-banner/success.svg +1 -0
  344. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  345. package/docs/design/templates/state-banner/warning.svg +1 -0
  346. package/docs/design/templates/state-banner-dark.svg +1 -0
  347. package/docs/design/templates/state-banner.svg +1 -0
  348. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  349. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  350. package/docs/design/templates/tab-bar-dark.svg +1 -0
  351. package/docs/design/templates/tab-bar.svg +1 -0
  352. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  353. package/docs/design/templates/token-search-field/empty.svg +1 -0
  354. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  355. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  356. package/docs/design/templates/token-search-field-dark.svg +1 -0
  357. package/docs/design/templates/token-search-field.svg +1 -0
  358. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  359. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  360. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  361. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  362. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  363. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  364. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  365. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  366. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  367. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  368. package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
  369. package/docs/design/templates/toolbar-control-group.svg +1 -0
  370. package/docs/design/templates/toolbar-dark.svg +1 -0
  371. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  372. package/docs/design/templates/toolbar-text/default.svg +1 -0
  373. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  374. package/docs/design/templates/toolbar-text/large.svg +1 -0
  375. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  376. package/docs/design/templates/toolbar-text/small.svg +1 -0
  377. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  378. package/docs/design/templates/toolbar-text.svg +1 -0
  379. package/docs/design/templates/toolbar.svg +1 -0
  380. package/docs/design/templates/value-table/details-dark.svg +1 -0
  381. package/docs/design/templates/value-table/details.svg +1 -0
  382. package/docs/design/templates/value-table-dark.svg +1 -0
  383. package/docs/design/templates/value-table.svg +1 -0
  384. package/docs/design/templates.md +128 -0
  385. package/docs/design-philosophy.md +33 -11
  386. package/docs/device-class.md +54 -0
  387. package/docs/examples/application-ui-profile.json +60 -0
  388. package/docs/examples/command-palette-adapter.tsx +68 -17
  389. package/docs/examples/component-catalog-extension-v2.json +80 -0
  390. package/docs/examples/component-catalog-extension.json +45 -0
  391. package/docs/layout.md +169 -38
  392. package/docs/nav-stack.md +77 -0
  393. package/docs/recipes.md +64 -16
  394. package/docs/split-view.md +55 -0
  395. package/docs/sunken-panel.md +53 -0
  396. package/docs/surface-scaffold.md +25 -0
  397. package/docs/tab-scaffold.md +52 -0
  398. package/docs/type-contracts.md +127 -0
  399. package/docs/ui-analyzer.md +118 -0
  400. package/docs/ui-doctor.md +91 -0
  401. package/docs/ui-evaluator.md +122 -0
  402. package/docs/ux-demo.md +29 -10
  403. package/docs/webawesome-theme.md +82 -8
  404. package/docs/workbench.md +123 -0
  405. package/doctor/cli.mjs +115 -0
  406. package/doctor/config.schema.json +68 -0
  407. package/doctor/eslint-diagnostics.d.mts +24 -0
  408. package/doctor/eslint-diagnostics.mjs +24 -0
  409. package/doctor/index.d.mts +116 -0
  410. package/doctor/index.mjs +1272 -0
  411. package/doctor/report.schema.json +118 -0
  412. package/evaluator/cli.mjs +89 -0
  413. package/evaluator/index.d.mts +90 -0
  414. package/evaluator/index.mjs +1138 -0
  415. package/evaluator/report.schema.json +152 -0
  416. package/llms.txt +260 -32
  417. package/package.json +205 -38
  418. package/traversal-exclusions.mjs +27 -0
  419. package/ux-demo/recipes/app-shell.tsx +223 -13
  420. package/ux-demo/recipes/collapsible-sidebar.tsx +230 -0
  421. package/ux-demo/recipes/compact-toolbar.tsx +116 -12
  422. package/ux-demo/recipes/composer-form.tsx +120 -19
  423. package/ux-demo/recipes/list-detail-dialog.tsx +205 -0
  424. package/ux-demo/recipes/list-workspace-states.tsx +176 -9
  425. package/ux-demo/recipes/loaders.ts +13 -4
  426. package/ux-demo/recipes/loading-inspector.tsx +191 -0
  427. package/ux-demo/recipes/mount-recipe.ts +31 -5
  428. package/ux-demo/recipes/navigation-sidebar.tsx +123 -11
  429. package/ux-demo/recipes/navigation-stack.tsx +121 -0
  430. package/ux-demo/recipes/recipes.css +125 -16
  431. package/ux-demo/recipes/types.ts +9 -1
  432. package/ux-demo/recipes/workspace-header.tsx +72 -3
  433. package/dist/browser/dialog-header.js +0 -5
  434. package/dist/browser/menu-action-row.js +0 -3
  435. package/dist/browser/menu-header.js +0 -5
  436. package/dist/browser/menu-item.js +0 -3
  437. package/dist/browser/page-header.js +0 -3
  438. package/dist/chunk-2PES33HS.js +0 -13
  439. package/dist/chunk-2PES33HS.js.map +0 -1
  440. package/dist/chunk-55DATV3A.js +0 -10
  441. package/dist/chunk-55DATV3A.js.map +0 -1
  442. package/dist/chunk-7BR3DO2A.js.map +0 -1
  443. package/dist/chunk-7LDCTU7D.js +0 -134
  444. package/dist/chunk-7LDCTU7D.js.map +0 -1
  445. package/dist/chunk-AQNKJRFH.js +0 -79
  446. package/dist/chunk-AQNKJRFH.js.map +0 -1
  447. package/dist/chunk-CTQKI2XL.js +0 -28
  448. package/dist/chunk-CTQKI2XL.js.map +0 -1
  449. package/dist/chunk-DAFFDO33.js +0 -14
  450. package/dist/chunk-DAFFDO33.js.map +0 -1
  451. package/dist/chunk-EGHL5S4P.js +0 -33
  452. package/dist/chunk-EGHL5S4P.js.map +0 -1
  453. package/dist/chunk-GY5WH7TO.js +0 -10
  454. package/dist/chunk-GY5WH7TO.js.map +0 -1
  455. package/dist/chunk-H5AGGVU5.js +0 -75
  456. package/dist/chunk-H5AGGVU5.js.map +0 -1
  457. package/dist/chunk-K3G72I6D.js +0 -24
  458. package/dist/chunk-K3G72I6D.js.map +0 -1
  459. package/dist/chunk-M5JRI6MN.js +0 -27
  460. package/dist/chunk-M5JRI6MN.js.map +0 -1
  461. package/dist/chunk-MBR3TYNL.js +0 -14
  462. package/dist/chunk-MBR3TYNL.js.map +0 -1
  463. package/dist/chunk-MFKMHK5W.js +0 -10
  464. package/dist/chunk-MFKMHK5W.js.map +0 -1
  465. package/dist/chunk-MQIZAD4A.js.map +0 -1
  466. package/dist/chunk-NPPD2A6O.js +0 -40
  467. package/dist/chunk-NPPD2A6O.js.map +0 -1
  468. package/dist/chunk-R6JHHBKQ.js +0 -19
  469. package/dist/chunk-R6JHHBKQ.js.map +0 -1
  470. package/dist/chunk-S3TPM2LP.js +0 -23
  471. package/dist/chunk-S3TPM2LP.js.map +0 -1
  472. package/dist/chunk-TRNBHPNW.js.map +0 -1
  473. package/dist/chunk-VHW5YNIB.js +0 -17
  474. package/dist/chunk-VHW5YNIB.js.map +0 -1
  475. package/dist/chunk-WVPYVDXY.js +0 -15
  476. package/dist/chunk-WVPYVDXY.js.map +0 -1
  477. package/dist/chunk-XZXRLY5Q.js +0 -33
  478. package/dist/chunk-XZXRLY5Q.js.map +0 -1
  479. package/dist/dialog-header.d.ts +0 -15
  480. package/dist/dialog-header.js +0 -5
  481. package/dist/dialog-header.js.map +0 -1
  482. package/dist/menu-action-row.js +0 -4
  483. package/dist/menu-action-row.js.map +0 -1
  484. package/dist/menu-header.d.ts +0 -41
  485. package/dist/menu-header.js +0 -6
  486. package/dist/menu-header.js.map +0 -1
  487. package/dist/menu-item.d.ts +0 -31
  488. package/dist/menu-item.js +0 -4
  489. package/dist/menu-item.js.map +0 -1
  490. package/dist/page-header.d.ts +0 -9
  491. package/dist/page-header.js +0 -3
  492. package/dist/page-header.js.map +0 -1
  493. package/dist/styles/dialog-header.css +0 -87
  494. package/dist/styles/menu-action-row.css +0 -160
  495. package/dist/styles/menu-header.css +0 -143
  496. package/dist/styles/menu-item.css +0 -123
  497. package/dist/styles/page-header.css +0 -33
  498. package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
@@ -0,0 +1,152 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/evaluator/report.schema.json",
4
+ "title": "Kerf UI browser evaluation report",
5
+ "type": "object",
6
+ "required": [
7
+ "schemaVersion",
8
+ "tool",
9
+ "target",
10
+ "recordedAt",
11
+ "profileFiles",
12
+ "contexts",
13
+ "diagnostics",
14
+ "summary",
15
+ "artifacts",
16
+ "subjectiveReview"
17
+ ],
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "schemaVersion": { "const": 1 },
21
+ "tool": {
22
+ "type": "object",
23
+ "required": ["name", "reportVersion"],
24
+ "additionalProperties": false,
25
+ "properties": {
26
+ "name": { "const": "@kerfjs/ui/evaluator" },
27
+ "reportVersion": { "const": 1 }
28
+ }
29
+ },
30
+ "target": {
31
+ "type": "object",
32
+ "required": ["url"],
33
+ "additionalProperties": false,
34
+ "properties": { "url": { "type": "string", "minLength": 1 } }
35
+ },
36
+ "recordedAt": { "type": "string", "format": "date-time" },
37
+ "profileFiles": { "$ref": "#/$defs/stringList" },
38
+ "contexts": {
39
+ "type": "array",
40
+ "minItems": 1,
41
+ "items": { "$ref": "#/$defs/context" }
42
+ },
43
+ "diagnostics": {
44
+ "type": "array",
45
+ "items": { "$ref": "#/$defs/diagnostic" }
46
+ },
47
+ "summary": { "$ref": "#/$defs/summary" },
48
+ "artifacts": {
49
+ "type": "object",
50
+ "required": ["retention", "files"],
51
+ "additionalProperties": false,
52
+ "properties": {
53
+ "retention": { "enum": ["always", "on-failure", "never"] },
54
+ "files": {
55
+ "type": "array",
56
+ "items": {
57
+ "type": "object",
58
+ "required": ["path", "sha256"],
59
+ "additionalProperties": false,
60
+ "properties": {
61
+ "path": { "type": "string", "minLength": 1 },
62
+ "sha256": {
63
+ "type": "string",
64
+ "pattern": "^[a-f0-9]{64}$"
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ },
71
+ "subjectiveReview": {
72
+ "type": "object",
73
+ "required": ["status", "rubric", "ratings", "note"],
74
+ "additionalProperties": false,
75
+ "properties": {
76
+ "status": { "const": "not-recorded" },
77
+ "rubric": {
78
+ "type": "array",
79
+ "minItems": 6,
80
+ "items": {
81
+ "type": "object",
82
+ "required": ["id", "prompt"],
83
+ "additionalProperties": false,
84
+ "properties": {
85
+ "id": { "type": "string", "minLength": 1 },
86
+ "prompt": { "type": "string", "minLength": 1 }
87
+ }
88
+ }
89
+ },
90
+ "ratings": { "type": "array", "maxItems": 0 },
91
+ "note": { "type": "string", "minLength": 1 }
92
+ }
93
+ }
94
+ },
95
+ "$defs": {
96
+ "stringList": {
97
+ "type": "array",
98
+ "items": { "type": "string", "minLength": 1 },
99
+ "uniqueItems": true
100
+ },
101
+ "summary": {
102
+ "type": "object",
103
+ "required": ["errors", "warnings", "passed"],
104
+ "additionalProperties": false,
105
+ "properties": {
106
+ "errors": { "type": "integer", "minimum": 0 },
107
+ "warnings": { "type": "integer", "minimum": 0 },
108
+ "passed": { "type": "boolean" }
109
+ }
110
+ },
111
+ "context": {
112
+ "type": "object",
113
+ "required": [
114
+ "id",
115
+ "browser",
116
+ "width",
117
+ "height",
118
+ "zoom",
119
+ "colorScheme",
120
+ "reducedMotion",
121
+ "evidence",
122
+ "summary"
123
+ ],
124
+ "additionalProperties": false,
125
+ "properties": {
126
+ "id": { "type": "string", "minLength": 1 },
127
+ "browser": { "enum": ["chromium", "firefox", "webkit"] },
128
+ "width": { "type": "integer", "minimum": 1 },
129
+ "height": { "type": "integer", "minimum": 1 },
130
+ "zoom": { "type": "number", "minimum": 1 },
131
+ "colorScheme": { "enum": ["light", "dark"] },
132
+ "reducedMotion": { "enum": ["reduce", "no-preference"] },
133
+ "evidence": { "type": "object" },
134
+ "summary": { "$ref": "#/$defs/summary" }
135
+ }
136
+ },
137
+ "diagnostic": {
138
+ "type": "object",
139
+ "required": ["code", "severity", "context", "message"],
140
+ "additionalProperties": false,
141
+ "properties": {
142
+ "code": { "type": "string", "pattern": "^KUI-B[0-9]{3}$" },
143
+ "severity": { "enum": ["error", "warning"] },
144
+ "context": { "type": "string", "minLength": 1 },
145
+ "message": { "type": "string", "minLength": 1 },
146
+ "repair": { "type": "string", "minLength": 1 },
147
+ "selector": { "type": "string", "minLength": 1 },
148
+ "evidence": {}
149
+ }
150
+ }
151
+ }
152
+ }
package/llms.txt CHANGED
@@ -1,45 +1,273 @@
1
1
  # @kerfjs/ui
2
2
 
3
- Accessible, production-backed UI primitives for kerf applications.
3
+ > Accessible, production-backed UI primitives for [kerf](https://github.com/brianwestphal/kerf)
4
+ > applications. Components are plain functions returning `SafeHtml`; the app owns
5
+ > state and wires stable `data-action` hooks once. This file orients an LLM to
6
+ > generate correct, good-looking kerf UI — it is not a catalog to browse.
4
7
 
5
- - [Package guide](./README.md)
6
- - [AI skill](./ai/skill.md)
7
- - [Machine-readable component catalog](./ai/component-catalog.json)
8
- - [Public API signature snapshot](./ai/public-api-signatures-v1.md)
9
- - [Web Awesome JSX signature snapshot](./ai/webawesome-jsx-signatures-v1.md)
10
- - [Need-first component selection matrix](./docs/component-selection.md)
11
- - [Production composition recipes](./docs/recipes.md)
12
- - [Component contract](./docs/component-contract.md)
13
- - [Web Awesome theme contract](./docs/webawesome-theme.md)
14
- - [Accessibility and keyboard contracts](./docs/accessibility.md)
15
- - [Design philosophy](./docs/design-philosophy.md)
16
- - [Apple HIG translation](./docs/apple-hig.md)
17
- - [UX catalog](./docs/ux-demo.md)
8
+ ```bash
9
+ npm install kerfjs @kerfjs/ui # kerfjs is a peer; Web Awesome is an optional peer
10
+ ```
18
11
 
19
- The UX catalog is a category-grouped master/detail review surface with a focused route for every public visual component plus composition demos. Its collapsible ecosystem section also lists all 70 free Web Awesome 3.12 components, each with a focused themed route. Related entries use one grouped `Uses` / `Used by` selector across both sets; the shell, display preferences, and selected component share one semantic theme.
12
+ Import each component from its own subpath (`@kerfjs/ui/list-item`, `@kerfjs/ui/toolbar`,
13
+ …); the browser build pulls that component's reachable CSS automatically, so do not
14
+ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
20
15
 
21
- Choose from the interface need: search the catalog, reuse a semantic match, compose existing primitives, add a thin application adapter for product concerns, and use custom markup only for a genuinely different contract. The selection matrix covers every public visual/helper export and the supported-but-not-preferred Web Awesome overlaps, including required wiring, application ownership, import subpaths, alternatives, and recipe links.
16
+ ## How to build a screen (retrieval order)
22
17
 
23
- There is no `@kerfjs/ui` command-palette runtime export or production recipe. The typed application-local example at `docs/examples/command-palette-adapter.tsx` demonstrates how a missing concept can reuse public layout vocabulary without inventing a package API. Ranking, history, permissions, availability, focus policy, actions, and copy stay in the app; propose recurring behavior upstream.
18
+ 1. **Pick the component from the interface need**, not by appearance — read
19
+ [component-selection.md](./docs/component-selection.md) (the problem→component
20
+ matrix, with imports, wiring, ownership, and alternatives).
21
+ 2. **Get exact signatures before emitting code** — read
22
+ [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) (real prop names,
23
+ callback shapes, disposer return types).
24
+ 3. **For exhaustive, structured facts** (ids, exports, variants, `publicClasses`,
25
+ relationships, side effects, and geometry ownership) load the
26
+ [Machine-readable component catalog](./ai/component-catalog.json) — the
27
+ canonical checked-in source; its schema is alongside it. Also load the
28
+ consuming application's catalog extension when present; generate one from the
29
+ [Consumer catalog extension schema](./ai/component-catalog-extension.schema.json)
30
+ when app-owned components must participate in selection or alignment.
31
+ Load the [Composition catalog v2](./ai/component-catalog-v2.json) to
32
+ mechanically evaluate parents, contexts, zones/cardinality, children, state,
33
+ wiring, responsive/layout/accessibility rules, and public boundaries. V1
34
+ remains compatible; v2 joins catalogs by `package:id`. Consumer v2 catalogs
35
+ use [the v2 extension schema](./ai/component-catalog-extension-v2.schema.json).
36
+ Load [compile-time contracts](./ai/compile-time-contracts-v1.json) for stable
37
+ `KUI-T###` ids, exact declaration symbols, and the boundary between rejected
38
+ source states and relationships that still require runtime/catalog checks.
39
+ Before generating application UI, discover `.kerf-ui-profile.json` with the
40
+ shipped [application profile API](./ai/application-ui-profile.mjs). Merge
41
+ package defaults, workspace policy, then parent-to-child directory policy;
42
+ honor its package-qualified preferences, approved theme/density, semantic
43
+ tokens, layout conventions, and narrow source-located exceptions. Validation
44
+ is catalog-aware per layer, including parent values later overridden by a
45
+ child; synchronous hosts use [application-ui-profile-sync.cjs](./ai/application-ui-profile-sync.cjs).
46
+ See the
47
+ [workspace profile example](./docs/examples/application-ui-profile.json).
48
+ A zone's optional `jsx.prop` is its only authoritative JSX binding; never
49
+ infer one from the zone id. Use `children` for one homogeneous primary
50
+ region and explicit named content prop slots for semantic positions or
51
+ replacement content. These slots use the recursive `KerfUiContent` type:
52
+ `SafeHtml`, runtime-empty boolean/nullish values, and readonly nested arrays.
53
+ Put conditionals and mapped component arrays directly in them; do not add a
54
+ `Fragment` only to satisfy types. Arbitrary strings, numbers, and signals are
55
+ rejected unless a component explicitly exposes a text position such as
56
+ `ListInsetText`. These are typed props, not native `<slot>` elements,
57
+ wrapper slot components, or a generic `slots` object. Leave unresolved
58
+ dynamic expressions unknown.
59
+ 4. **When authoring a component gallery**, load
60
+ [catalog-authoring.json](./ai/catalog-authoring.json), then follow its
61
+ authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract).
62
+ 5. **Apply the rules below and in** [skill.md](./ai/skill.md).
63
+ 6. **Before calling an integration complete**, run
64
+ [`kerf-ui-doctor`](./docs/ui-doctor.md). Its portable JSON report merges
65
+ profile/catalog, TypeScript, Kerf ESLint, and static analyzer diagnostics;
66
+ CSS-adjacent component props are checked from catalog `cssValueProps`, so
67
+ prefer its canonical shorthand or typed helper over raw CSS strings;
68
+ repair source-located errors until exit 0. Use full mode for release gates;
69
+ generated `dist`/`coverage`, dependency, cache, evidence, and nested-worktree
70
+ directories are excluded consistently from every static stage.
71
+ [`kerf-ui-analyze`](./docs/ui-analyzer.md) remains available when only static
72
+ layout diagnostics are wanted; its review findings are a bounded human/AI
73
+ review queue rather than an objective aesthetic score.
74
+ 7. **Evaluate the running application** by explicitly enabling the doctor's
75
+ browser stage or directly invoking
76
+ [`kerf-ui-evaluate`](./docs/ui-evaluator.md). Preserve its `KUI-B###`
77
+ browser evidence and screenshots; record hierarchy/rhythm/density/aesthetic
78
+ ratings separately with a named reviewer rather than presenting them as
79
+ objective assertions.
24
80
 
25
- AI tools that need exhaustive retrieval should load `@kerfjs/ui/ai/component-catalog.json`. It is the canonical checked-in source for stable ids, exports, purpose, selection guidance, relationships, delivery and side effects, wiring, application ownership, variants, accessibility, public CSS hooks, catalog routes, and current documentation/recipe links. Its adjacent JSON Schema describes the format.
81
+ ## Core rules (do the right thing)
26
82
 
27
- Prefer an equivalent component prop or `--kui-*` token for customization. When composition-specific layout needs CSS, the catalog's `publicClasses` arrays are the exact supported anatomy boundary: selectors may join documented public classes, but must not reach into a component by tag, id, attribute alone, or an unlisted class.
83
+ - **Reach for the primitive, not for CSS.** The package is built to look right
84
+ _unstyled_. Before adding `padding`, `margin`, `width`, `height`, `border`,
85
+ `background`, a wrapper card, or a decoration, check whether the component, the
86
+ pane, or the content-item already owns it — it almost always does. Prefer a
87
+ component prop or a `--kui-*` token; write CSS only for genuinely new structure,
88
+ and then only join a component's documented `publicClasses` (never reach in by
89
+ tag/id/attribute or an unlisted class).
90
+ - **Never double-inset.** A `.kui-pane` has no padding; its `.kui-content` children
91
+ own the geometry (8px inline margin + 1px border + 8px padding). Do not add a
92
+ container padding on top of a content-item's own margin — pick one owner. Use
93
+ `.kui-content` for 24px major vertical rhythm.
94
+ - **Use `Row` for horizontal and `List` for vertical layout.** Both expose
95
+ physical `hAlign`/`vAlign` props and typed gaps. Row defaults to left/full,
96
+ an `xs` gap, and no wrapping; List retains full/top and zero-gap defaults.
97
+ Use canonical physical `textInsets` or `controlInsets` sides in
98
+ `t`/`r`/`b`/`l` order; text geometry wins on overlapping sides.
99
+ `ListInsetText` and `ListInsetControl` inset every side by default and accept
100
+ the same `sides` grammar for selective edges.
101
+ List additionally supplies
102
+ optional typed `gap`, `flex`, vertical scrolling, and canonical
103
+ `dividerSides` (`t`/`r`/`b`/`l` order). It adds no list semantics; children own
104
+ those, and only one bounded region should own scrolling. Pass a finite spacing
105
+ shorthand (`gap="xs"`, `gap="m"`) or a complete `CssLength` from the CSS-free
106
+ `@kerfjs/ui/css-values` builders; raw CSS strings are rejected. Use `flex()`
107
+ for List flex, typed lengths for Skeleton geometry, and
108
+ `uiColor()`/`colorVar()` for choice-icon colors. These brands are intentionally
109
+ not interchangeable; rows use classes/tokens/props rather than raw `style`.
110
+ - **Keep Web Awesome on the shared inset tiers.** `webawesome.css` uses
111
+ `--kui-wa-control-inset` (8px controls/items) and
112
+ `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside
113
+ Accordion, Card, Details, Callout, and Include), while
114
+ `--kui-wa-container-inset` keeps Tab Panel at 16px. Dialog body and footer use
115
+ the surface (8px) and container (16px) tiers respectively, independent of the
116
+ dialog's shared `--spacing`. Override the tier at the narrowest useful scope
117
+ instead of restyling individual shadow parts.
118
+ When a dialog provides another dismissal affordance, add `hide-actions` to
119
+ the `wa-dialog` host; the theme hides its directly exported `header-actions`
120
+ part without an unsupported chained `::part()` selector.
121
+ Checkbox and Radio Group option regions also receive the shared 8px inline
122
+ outer inset because those groups have no bordered field shell. The Color
123
+ Picker trigger receives the same inset for the same unbordered geometry.
124
+ Slider's complete interactive region uses the shared 8px logical inline outer
125
+ inset without shifting its already-aligned label.
126
+ Known Date's Month/Day/Year captions and bordered text-like field hints align
127
+ with field values at the shared 9px border-plus-padding inset. OTP Input's
128
+ label uses the same uppercase xs/650 treatment and its label and hint share
129
+ that 9px alignment.
130
+ - `Select` requires a visible `label` or an `ariaLabel` for a visually hidden
131
+ accessible name. The package names the internal combobox, including custom
132
+ selected content; consumers do not need shadow-DOM naming workarounds.
133
+ Import `select/register` once for the canonical animation lifecycle: stale
134
+ close/show completions cannot override a later request. Consumers must not
135
+ repair popup timing or anchor placement; raw Web Awesome selects stay native.
136
+ Use `hint` for supporting text below the control and `placeholderText` only
137
+ for the empty value inside it; loading placeholders retain the visible hint.
138
+ - **Trust the defaults.** Render a control at its natural size and color (a
139
+ `LucideIcon` is 24px); if it looks wrong, fix the surrounding layout, not the
140
+ control. Never force a component's width/height to size it — that leaves a halo
141
+ or a stretched oval.
142
+ - **Toolbars hold only `ToolbarText` and `ToolbarControlGroup`.** Never put a bare
143
+ button, input, link, or loose markup in a `leading`/`center`/`trailing` zone.
144
+ Wrap every control — `SegmentedControl`, `Select`, a collapsible
145
+ `TokenSearchField`, Web Awesome controls — inside a `ToolbarControlGroup`. For an
146
+ ordinary icon/action control inside the group use a **plain `<button>`** (the
147
+ group styles it fully) — that is the default; reach for `wa-button` only when you
148
+ need a Web Awesome feature, chiefly the `slot="trigger"` button of a `wa-dropdown`
149
+ popup menu. A toolbar popup menu is a `single` `ToolbarControlGroup` around a
150
+ `wa-dropdown` (its `slot="trigger"` `wa-button` is the toolbar button, kept under
151
+ `data-morph-skip-children`). Compact mixed groups keep standard item padding
152
+ and raised selected chrome without an internal separator; the selected item
153
+ paints over the outer border. For an avatar control, set `content="avatar"` and
154
+ `avatarImage` on the group instead of inserting an `img`; a lone control paints
155
+ the group and a multi-button group paints only its pressed highlight.
156
+ - **Use one direct toolbar composition for panel/dialog/page headings.** Put an
157
+ optional icon in a `ToolbarControlGroup`, an extra-large `ToolbarText` directly
158
+ in the leading zone, and actions in a trailing group. Supporting copy is
159
+ app-owned content below. Do not create a private heading wrapper or restyle the
160
+ toolbar.
161
+ - **Use `Text` for ordinary semantic headings and paragraphs outside toolbar
162
+ title zones.** Pass a required `h1`–`h6` or `p` variant based on document
163
+ meaning. It passes native attributes through and owns the standard transparent
164
+ border plus item padding; keep toolbar titles on `ToolbarText` and list-aligned
165
+ bare prose on `ListInsetText`.
166
+ - **Space by the five-step scale, by relationship not by eye.** `0`
167
+ `--kui-space-none`, `4px` `--kui-space-2xs`, `8px` `--kui-space-xs` (inside a
168
+ group), `16px` `--kui-space-m`, `24px` `--kui-space-l` (between major differing
169
+ regions). 12px/32px are off-scale exceptions. Prefer direct `Row.gap`/`List.gap`
170
+ shorthands for repeated rhythm; use `Spacer` for one typed empty width/height
171
+ or flexible main-axis gap. Use `space`, `px`, `rem`, `em`, `pct`, `lengthVar`, and
172
+ `calc(plus(...))` for typed runtime composition. `remify()` is source-CSS only.
173
+ - **Keep nested highlight corners concentric.** Inset hover and selection surfaces
174
+ follow the owning control's pill or rounded shape; their radius is the outer
175
+ radius minus `--kui-layout-highlight-inset`. Do not give an inner highlight an
176
+ unrelated radius.
177
+ - **Panes share one child-owned geometry.** Sidebars, main areas, inspectors, and
178
+ dialogs all use an unpadded `.kui-pane` (optional `.kui-pane__toolbar`, one
179
+ scrolling `.kui-pane__content`, optional `.kui-pane__footer`). A visible pane owns
180
+ its collapse control; a hidden pane's restore moves to the adjacent main
181
+ toolbar's matching edge — no icon-only rail. Keep one scroll owner per region.
182
+ - **State and behavior live in the app.** Components take semantic `data-action`
183
+ strings and controlled values; wire them once with `delegate()`/`delegateActions()`
184
+ or the disposer-returning `wire…` helpers, and own domain copy, transport, and
185
+ policy in a thin adapter. Every element must earn its place — cut chrome, labels,
186
+ and readouts that do not help a person decide or act.
187
+ - **App state is domain/persisted; helpers own only ephemeral mechanics.** Keep
188
+ navigation stacks, tab selection and order, pane sizes, and `collapsed`/`expanded`
189
+ disclosure flags in the app — they are data or persisted layout, and the app reads
190
+ them to render. The `wire…` helpers own the _ephemeral_ parts: `wireNavStack` the
191
+ content-slide, per-view top/bottom chrome cross-fade, and focus move/restore
192
+ (mark a preferred new-view target with `data-nav-focus`), `wireTabBars` the
193
+ overflow autoscroll, drag preview, and
194
+ replacement focus after controlled automatic tab activation,
195
+ `wireResizableRegions` the live drag preview; they report committed changes via
196
+ callbacks. Managed TokenSearchField clear also preserves open state and replacement
197
+ editor focus before the next input task, so shortcut-letter typing stays in search.
198
+ Select All deletion does the same; deletion
199
+ restoration finishes before the next keystroke rather than on a delayed frame.
200
+ Persist both query and remaining tokens read from an edited field. The one richer case is `wireTokenSearchFields`, which manages the
201
+ collapsible field's expand/collapse/focus by default (on, per-behavior opt-out) and
202
+ exposes the `expanded` signal on its handle — bind it in render or hand in your own
203
+ via `collapsible.signals`. Do not hand-roll open/collapse/focus that helper
204
+ provides; but do keep a plain disclosure toggle (a one-line boolean the app already
205
+ renders from) in the app. For real-app composition it also offers a focusout
206
+ keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn`,
207
+ so a sibling suggestions/date popover does not collapse an empty field), opt-in
208
+ atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via
209
+ `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an
210
+ `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — so the app can drop its own keydown/input
211
+ boilerplate while still owning parsing and controlled token state.
212
+ - **Placeholder loading state, don't rebuild it.** For a value or component that is
213
+ still loading, set `placeholder` on the component (`Select`, `ListHeader`,
214
+ `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`,
215
+ `AppTab`, `ToolbarText`, `ListActionRow`): it renders its real chrome with value
216
+ slots as subtle **unanimated** skeleton blocks and interactivity disabled, so a
217
+ parent composes a faithful loading view (e.g. an inspector) without hand-rebuilding
218
+ markup. Use the standalone `Skeleton` for a custom slot. Prefer it over `wa-skeleton`
219
+ (the pure-Kerf primitives avoid Web Awesome), and never animate it — use
220
+ `LoadingSpinner` for known busy activity instead.
221
+ - **Keep ListItem content inside the row.** The rounded `ListItem` root clips
222
+ overflowing label, status, and dormant trailing content. Set `multiline` when
223
+ the primary label should wrap; use `ListActionRow` instead when trailing content
224
+ must be interactive.
225
+ - **Dialog bodies are lists by default.** Compose rows and sections in `List`,
226
+ use `DialogSurface bodyInset="none"` when those children own their geometry,
227
+ and wrap bare prose in `ListInsetText` so it shares the standard list gutter
228
+ without stacking a second body inset.
229
+ - **Use a StateBanner badge only for compact supporting status.** Pass the
230
+ optional string `badge` for a terse count or status beside the title. It
231
+ inherits the banner tone and is announced with the banner, so keep its text
232
+ meaningful and never rely on color alone.
28
233
 
29
- Before emitting code, load `@kerfjs/ui/ai/public-api-signatures-v1.md` for the exact declaration signatures used by the authoring corpus. It records accepted import paths, prop names, callback shapes, and disposer return types from emitted declarations rather than prose examples.
234
+ ## Public exports
30
235
 
31
- Public components: `LucideIcon`, `DisclosureArrow`, `Toolbar`, `ToolbarControlGroup`, `ToolbarText`, `SegmentedControl`, `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`, `wireTokenSearchFields`, `MenuItem`, `MenuActionRow`, `MenuHeader`, `ResizableRegion`, `wireResizableRegions`, `AppTab`, `TabBar`, `wireTabBars`, `reorderTabs`, `PageHeader`, `LoadingSpinner`, `Select`, `StateBanner`, `EmptyState`, `DialogHeader`, `ValueTable`, and `ValueTableRow`. `MenuItem`, `MenuActionRow`, `MenuHeader`, and `AppTab` accept typed, runtime-filtered application `data-*` metadata through `rootAttributes`; MenuActionRow `trailingActionAttributes` and MenuHeader `triggerAttributes` additionally support native popover target/action and `aria-controls`/`aria-haspopup`, while component-owned action, identity, selection, disclosure, naming, disabled, icon, and role semantics stay protected. `MenuHeader` uses the mutually exclusive `count` plus required localized `countLabel` pair for non-negative safe-integer section quantities, including zero; it renders the shared neutral pill and joins the spoken phrase to the owning heading or disclosure button. Never concatenate a count into `label` or put numeric content in the legacy non-count `badge` SafeHtml slot. In real toggle mode, omitting `actionIcon` supplies one production 18px `DisclosureArrow` driven by `expanded`; a custom icon replaces it, and the app must reveal matching content. Ordinary navigation must not borrow a disclosure chevron. `AppTab.closeIcon` and `ResizableRegion.handleIcon` replace decorative dormant glyphs without taking control ownership. `MenuItem.trailing` is dormant; use `MenuActionRow` for sibling primary/trailing native buttons, keeping its `label`, `icon`, and `trailingActionIcon` SafeHtml dormant too. `ValueTableRow` owns semantic `dt`/`dd` markup, 8px of root-scaled top and bottom padding, and an optional 24px leading icon; its separator begins 8px from the left without an icon or 40px with one and ends 8px from the right. `DisclosureArrow` is a decorative, controlled open/closed indicator with configurable directions, shortest-path rotation (counterclockwise for a 180-degree closed-to-open tie), replaceable right-oriented icon content, an 18px root-scaled default, and a scoped `--kui-disclosure-arrow-size` override; the owning control retains interaction and expanded-state semantics. `SegmentedControl` is controlled and supports toolbar, rounded-rectangle, and pill presentations with native pressed buttons in sequential Tab order. `Select` preserves icon-bearing option slots across Kerf rerenders, keys custom selected content by the controlled value, and separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`. `TokenSearchField` controls tokens while keeping editable text DOM-owned between token changes, combining free text with ordered atomic filter chips while leaving query parsing and results to the application; its leading icon, first text line, clear action, and trailing slot stay aligned to one fixed row when text wraps. Its optional `collapsible` mode animates between an empty iconic action and the complete field, works standalone or inside `ToolbarControlGroup`, and keeps populated searches expanded while the app controls transient focus/open state. Call `wireTokenSearchFields` once to make Enter submit without inserting a contenteditable line break and to preserve focus plus the text-relative caret across controlled keyboard chip deletion; visual wrapping remains available. Semantic state palettes are opinionated, Web Awesome-compatible, and overridable globally, by tone, or per instance.
236
+ `LucideIcon`, `DisclosureArrow`, `Toolbar`, `ToolbarControlGroup`, `FloatingToolbar`, `ToolbarText`, `Text`,
237
+ `ListItem`, `ListActionRow`, `ListHeader`, `ListInsetControl`,
238
+ `ListInsetText`, `SegmentedControl`,
239
+ `Select`, `TokenSearchField` (+ `readTokenSearchField`, `placeTokenSearchCaret`,
240
+ `wireTokenSearchFields`), `AppTab`, `TabBar` (+ `wireTabBars`, `reorderTabs`),
241
+ `ResizableRegion` (+ `wireResizableRegions`), `StateBanner`, `EmptyState`,
242
+ `LoadingSpinner`, `Skeleton`, `ValueTable`, `ValueTableRow`. Whole-screen layouts (opt-in,
243
+ tree-shakeable, declarative with `wire…` helpers, each with a companion CSS import):
244
+ `NavStack`, `SplitView`, `Workbench`, `TabScaffold`, driven by `deviceClass()` from
245
+ `@kerfjs/ui/device-class`. For a standalone collapsible rail/drawer outside a full
246
+ shell, `@kerfjs/ui/collapsible-panel` (`CollapsiblePanel`, `CollapsiblePanelToggle`)
32
247
 
33
- `DialogHeader` composes a real top `Toolbar`: its borderless identity group keeps the optional 24px icon in a 34px circular background and the first title line centered against an automatic action `ToolbarControlGroup`. Pass action children directly and add a localized `actionsLabel` when that group needs a name. The optional `summary`/`summaryId` row remains below the title; the application owns modal focus, dismissal, commands, and action handling.
248
+ - `@kerfjs/ui/wire-sidebar` (`wireSidebar`: toggle, focus, compact overlay, persistence).
249
+ `@kerfjs/ui/catalog` is another opt-in shell — a
250
+ `Catalog` component + `wireCatalog` helper for building a component-gallery catalog
251
+ (collapsible category sidebar + preview stage + resources footer, with an opt-in
252
+ transparent-bound and margin geometry overlay plus focus-preserving active-row
253
+ reveal for long desktop sidebars) from your own
254
+ entries; controlled/stateless like the layouts. For any Catalog demo, follow
255
+ the [authoritative authoring contract](./docs/catalog.md#catalog-demo-authoring-contract)
256
+ rather than inferring structure from the shell or private CSS.
257
+ `@kerfjs/ui/webawesome` is a
258
+ type-only boundary for `wa-*` JSX; `@kerfjs/ui/select/register` and the CSS are the
259
+ declared side effects.
34
260
 
35
- Pane and navigation composition: import `@kerfjs/ui/layout.css` and use an unpadded `.kui-pane` with optional `.kui-pane__toolbar`, one scrolling `.kui-pane__content`, and optional `.kui-pane__footer`. Add `.kui-content` for 24px major vertical gaps. Use `.kui-content-item` for children that own 8px inline margin, 1px transparent-or-visible border, 8px padding, and 12px rounded corners; the pill modifier uses 22px. This vocabulary applies equally to sidebars, main areas, inspectors, and dialogs. A visible collapsible pane owns collapse in its own toolbar. When hidden, move restore into the adjacent main toolbar on the same logical edge—leading for an inline-start pane, trailing for inline-end—and remove the pane instead of leaving an icon-only rail.
261
+ ## Reference
36
262
 
37
- Composer form recipe: keep the form as one visible surface, use `DialogHeader` title/summary ids to label and describe it, and align field and action control edges on the shared 8px inline gutter without a second content-item padding inset. Retain 24px major rhythm. A conditional `StateBanner` is the only nested semantic surface. Do not make every form section another card. When resetting controlled upgraded Web Awesome fields, synchronize their live `value` properties as well as the rendered value attributes.
38
-
39
- Toolbar and split-item geometry: wrap every toolbar item, including dormant text, in `ToolbarControlGroup`. Groups stay 44px outside (`calc(2px + remify(42px))`) even when their border and background are transparent, with 8px between groups and inside items. `MenuHeader` fills the available inline width and separates its dormant title/count-or-badge cluster from its optional logical-end 44px action; the visible action glyph defaults to 18px through `--kui-menu-header-action-icon-size`, while disclosure mode makes the title cluster the action. `MenuActionRow` keeps primary and trailing 44px actions as sibling native buttons inside a noninteractive row. Multiline `MenuItem` and `MenuActionRow` leading icons stay centered on the first text line while later lines extend below. Do not pad pane shells or add competing wrapper insets. See `docs/layout.md`.
40
-
41
- Import visual components from explicit JavaScript subpaths. A CSS-aware browser bundler selects generated wrappers that bring in the foundation, the component CSS, and styles for reachable UI subcomponents; unrelated CSS stays out. The root barrel and `@kerfjs/ui/unstyled` are CSS-free; use `styles.css` with the root barrel only when the complete layer is intentional. Manual CSS exports remain available for custom pipelines, and application overrides follow package styles in the cascade. Direct `wa-*` JSX uses `import type {} from '@kerfjs/ui/webawesome'`, the side-effect-free declaration boundary synchronized with all 70 catalog-supported elements. `@kerfjs/ui/webawesome.css` is the optional CSS-only theme; it includes Web Awesome's base stylesheet, registers no elements, and remains overridable through public `--wa-*` tokens. CSS, its generated browser wrappers, and `@kerfjs/ui/select/register` are the declared side effects. `kerfjs` is an external peer. The Web Awesome peer is optional and needed for its components. `wireTabBars` includes proximity-based horizontal edge autoscroll during same-bar drag reordering.
42
-
43
- The Web Awesome theme renders Tooltip and Popover without pointer arrows by default. Restore them only when the anchor relationship needs the pointer, using `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or one popover's public `--arrow-size`; `without-arrow` remains available for explicit local intent.
44
-
45
- Web Awesome catalog coverage means themed and inspectable, not preferred. Consider Popup when it replaces custom anchored positioning. Prefer Kerf Select over direct Dropdown/Dropdown Item/Select/Option composition, SegmentedControl over Button Group, TabBar or SegmentedControl over Web Awesome Tabs, LucideIcon over Web Awesome Icon, and ResizableRegion over Split Panel. ResizableRegion carries Hot Sheet 2's 1px separator plus hover/focus grip. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame.
263
+ - [skill.md](./ai/skill.md): the full rule set + a common-mistakes table (the shipped AI skill).
264
+ - [design-philosophy.md](./docs/design-philosophy.md): why kerf UI is shaped this way — the decision principles behind the rules above.
265
+ - [layout.md](./docs/layout.md): the pane/content-item geometry, public roles/tokens, and the spacing scale.
266
+ - [component-contract.md](./docs/component-contract.md): what a component owns vs. what the app owns.
267
+ - [accessibility.md](./docs/accessibility.md): keyboard and ARIA contracts per component.
268
+ - [recipes.md](./docs/recipes.md): production compositions (app shell, list-detail dialog, composer form, …) as copyable references.
269
+ - [app-layouts.md](./docs/app-layouts.md): choosing `NavStack`/`SplitView`/`Workbench`/`TabScaffold` by data + interaction + device, and dialog presentation.
270
+ - [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists). The UX sidebar visibly tags superseded and exceptional Web Awesome choices as `Discouraged`; Popup remains an available conditional positioning primitive.
271
+ - [component-catalog.json](./ai/component-catalog.json) + [component-catalog-extension.schema.json](./ai/component-catalog-extension.schema.json) + [catalog-authoring.json](./ai/catalog-authoring.json) + [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) + [webawesome-jsx-signatures-v1.md](./ai/webawesome-jsx-signatures-v1.md): machine-readable selection facts, a reusable app-component extension contract, Catalog authoring discovery, and exact signatures.
272
+ - [compile-time-contracts-v1.json](./ai/compile-time-contracts-v1.json) + [type-contracts.md](./docs/type-contracts.md): stable compile diagnostics, packed-declaration proof, migrations, and explicit non-goals.
273
+ - [README.md](./README.md): package overview and the component subpath table.