@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
package/README.md CHANGED
@@ -2,46 +2,328 @@
2
2
 
3
3
  Accessible, composable UI primitives for [kerf](https://github.com/brianwestphal/kerf). The package ships production components, component-reachable CSS, accessibility and keyboard contracts, an AI-readable guide, and a production-backed UX catalog.
4
4
 
5
+ Start interface work with the [need-first component selection matrix](./docs/component-selection.md). It distinguishes direct reuse, composition, thin application adapters, and genuinely custom semantics, with imports, required wiring, application ownership, alternatives, and recipes for every public primitive.
6
+
7
+ When authoring a component gallery, follow the single
8
+ [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract)
9
+ for focused-versus-composition modes, helper nesting, specimen selection,
10
+ geometry inspection, and metadata ownership. AI tools can discover that
11
+ contract and its public imports through the shipped
12
+ [`catalog-authoring.json`](./ai/catalog-authoring.json) artifact.
13
+
14
+ For connective application patterns, use the seven [production composition
15
+ recipes](./docs/recipes.md). Each has a stable catalog route, runnable state,
16
+ public-subpath source, semantic layout ownership, and explicit application
17
+ customization boundaries. The composer recipe demonstrates one coherent form
18
+ surface with `PanelHeader` hierarchy and field/action controls aligned to the
19
+ shared 8px gutter; only persistent feedback adds a nested semantic
20
+ `StateBanner` surface.
21
+
22
+ When no primitive matches, keep policy application-owned while reusing the
23
+ layout vocabulary. The typed
24
+ [`command-palette-adapter.tsx`](./docs/examples/command-palette-adapter.tsx)
25
+ shows that application boundary explicitly; it is reference source, not a package
26
+ runtime export.
27
+
5
28
  ```bash
6
29
  npm install kerfjs @kerfjs/ui
7
30
  ```
8
31
 
9
32
  ```tsx
10
- import { MenuItem } from '@kerfjs/ui/menu-item';
11
- import { Toolbar } from '@kerfjs/ui/toolbar';
12
- import { ToolbarText } from '@kerfjs/ui/toolbar-text';
13
-
14
- mount(root, () => <>
15
- <Toolbar label="Document" leading={<ToolbarText text="Notes" />} />
16
- <MenuItem action="open-notes" label="Notes" selected />
17
- </>);
33
+ import { ListItem } from "@kerfjs/ui/list-item";
34
+ import { ListHeader } from "@kerfjs/ui/list-header";
35
+ import { ListActionRow } from "@kerfjs/ui/list-action-row";
36
+ import { Toolbar } from "@kerfjs/ui/toolbar";
37
+ import { ToolbarControlGroup } from "@kerfjs/ui/toolbar-control-group";
38
+ import { ToolbarText } from "@kerfjs/ui/toolbar-text";
39
+
40
+ mount(root, () => (
41
+ <>
42
+ <Toolbar
43
+ label="Document"
44
+ leading={
45
+ <ToolbarControlGroup appearance="borderless" single>
46
+ <ToolbarText text="Notes" />
47
+ </ToolbarControlGroup>
48
+ }
49
+ />
50
+ <section>
51
+ <ListHeader
52
+ label="Workspace"
53
+ action="show-workspace-actions"
54
+ actionLabel="Workspace actions"
55
+ rootAttributes={{ "data-section-id": "workspace" }}
56
+ triggerAttributes={{
57
+ popoverTarget: "workspace-actions",
58
+ popoverTargetAction: "toggle",
59
+ "aria-controls": "workspace-actions",
60
+ "aria-haspopup": "dialog",
61
+ }}
62
+ />
63
+ <ListItem
64
+ action="open-notes"
65
+ label="Notes"
66
+ selected
67
+ rootAttributes={{
68
+ "data-command-color": "blue",
69
+ "data-drop-status": "ready",
70
+ }}
71
+ />
72
+ <ListActionRow
73
+ action="open-file"
74
+ itemId="src/main.ts"
75
+ label="src/main.ts"
76
+ trailingAction="open-file-actions"
77
+ trailingActionLabel="Actions for src/main.ts"
78
+ trailingActionIcon={moreIcon}
79
+ />
80
+ <div id="workspace-actions" popover="auto">
81
+ Application-owned actions
82
+ </div>
83
+ </section>
84
+ </>
85
+ ));
18
86
  ```
19
87
 
20
88
  Components return Kerf `SafeHtml`. They do not own application state or attach transient listeners. Actions are stable `data-action` hooks; the application wires them once with `delegate()` or `delegateActions()` and retains the disposer.
21
89
 
90
+ `ListItem.rootAttributes`, `ListHeader.rootAttributes`,
91
+ `ListActionRow.rootAttributes`, `AppTab.rootAttributes`,
92
+ `CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` carry typed
93
+ application `data-*` metadata without
94
+ teaching the package domain fields. `ListHeader.triggerAttributes` and
95
+ `ListActionRow.trailingActionAttributes` additionally support native popover
96
+ target and relationship attributes. Roles and component-owned action, selection,
97
+ disclosure, naming, disabled, icon, and catalog-structure semantics remain protected props; an
98
+ isolated `role="menuitem"` is not an extension shortcut.
99
+ The slots are also filtered at runtime, so structurally widened objects and
100
+ JavaScript callers cannot bypass those protections with case-variant names.
101
+ `ListItem.trailing` is dormant metadata. Use `ListActionRow` when a row needs
102
+ sibling primary and trailing native-button actions with independent names,
103
+ disabled states, focus, and click ownership. Its `label`, `icon`, and
104
+ `trailingActionIcon` slots are dormant content and must not contain controls.
105
+ In either component's multiline mode, the leading icon remains aligned with
106
+ the first text line as the label wraps below it.
107
+ For section quantities, pass a non-negative safe-integer `count` together with
108
+ the localized full spoken phrase in `countLabel`, for example
109
+ `count={3} countLabel="3 notes"`. This renders the standard neutral count pill
110
+ and includes the count in the heading or disclosure button's accessible name.
111
+ Do not concatenate a count into `label` or pass a numeric `badge`; the mutually
112
+ exclusive legacy `badge` slot remains available for non-count `SafeHtml` such
113
+ as a `New` marker.
114
+
22
115
  ## Component subpaths
23
116
 
24
- | Component | Browser import (includes reachable CSS) | Manual CSS export |
25
- | --- | --- | --- |
26
- | `LucideIcon` | `@kerfjs/ui/lucide-icon` | `@kerfjs/ui/lucide-icon.css` |
27
- | `Toolbar` | `@kerfjs/ui/toolbar` | `@kerfjs/ui/toolbar.css` |
28
- | `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
29
- | `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
30
- | `MenuItem` | `@kerfjs/ui/menu-item` | `@kerfjs/ui/menu-item.css` |
31
- | `MenuHeader` | `@kerfjs/ui/menu-header` | `@kerfjs/ui/menu-header.css` |
32
- | `ResizableRegion` | `@kerfjs/ui/resizable-region` | `@kerfjs/ui/resizable-region.css` |
33
- | `wireResizableRegions` | `@kerfjs/ui/wire-resizable-regions` | |
34
- | `AppTab` | `@kerfjs/ui/app-tab` | `@kerfjs/ui/app-tab.css` |
35
- | `TabBar` | `@kerfjs/ui/tab-bar` | `@kerfjs/ui/tab-bar.css` |
36
- | `wireTabBars`, `reorderTabs` | `@kerfjs/ui/wire-tab-bars` | |
37
- | `PageHeader` | `@kerfjs/ui/page-header` | `@kerfjs/ui/page-header.css` |
38
- | `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
39
- | `Select` | `@kerfjs/ui/select` | `@kerfjs/ui/select.css` |
40
- | `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
41
- | `StateBanner` | `@kerfjs/ui/state-banner` | `@kerfjs/ui/state-banner.css` |
42
- | `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
43
- | `DialogHeader` | `@kerfjs/ui/dialog-header` | `@kerfjs/ui/dialog-header.css` |
44
- | `ValueTable` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
117
+ | Component | Browser import (includes reachable CSS) | Manual CSS export |
118
+ | ------------------------------------------------------------------- | --------------------------------------- | -------------------------------------- |
119
+ | `LucideIcon` | `@kerfjs/ui/lucide-icon` | `@kerfjs/ui/lucide-icon.css` |
120
+ | `DisclosureArrow` | `@kerfjs/ui/disclosure-arrow` | `@kerfjs/ui/disclosure-arrow.css` |
121
+ | `Toolbar` | `@kerfjs/ui/toolbar` | `@kerfjs/ui/toolbar.css` |
122
+ | `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
123
+ | `FloatingToolbar` | `@kerfjs/ui/floating-toolbar` | `@kerfjs/ui/floating-toolbar.css` |
124
+ | `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
125
+ | `List` | `@kerfjs/ui/list` | `@kerfjs/ui/list.css` |
126
+ | `ListActionRow` | `@kerfjs/ui/list-action-row` | `@kerfjs/ui/list-action-row.css` |
127
+ | `ListItem` | `@kerfjs/ui/list-item` | `@kerfjs/ui/list-item.css` |
128
+ | `ListHeader` | `@kerfjs/ui/list-header` | `@kerfjs/ui/list-header.css` |
129
+ | `ListInsetControl` | `@kerfjs/ui/list-inset-control` | `@kerfjs/ui/list-inset-control.css` |
130
+ | `ListInsetText` | `@kerfjs/ui/list-inset-text` | `@kerfjs/ui/list-inset-text.css` |
131
+ | `Pane` | `@kerfjs/ui/pane` | `@kerfjs/ui/pane.css` |
132
+ | Content and navigation composition | — | `@kerfjs/ui/layout.css` |
133
+ | `ResizableRegion` | `@kerfjs/ui/resizable-region` | `@kerfjs/ui/resizable-region.css` |
134
+ | `wireResizableRegions` | `@kerfjs/ui/wire-resizable-regions` | |
135
+ | `AppTab` | `@kerfjs/ui/app-tab` | `@kerfjs/ui/app-tab.css` |
136
+ | `TabBar` | `@kerfjs/ui/tab-bar` | `@kerfjs/ui/tab-bar.css` |
137
+ | `wireTabBars`, `reorderTabs` | `@kerfjs/ui/wire-tab-bars` | |
138
+ | `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
139
+ | `Skeleton` | `@kerfjs/ui/skeleton` | `@kerfjs/ui/skeleton.css` |
140
+ | `SunkenPanel` | `@kerfjs/ui/sunken-panel` | `@kerfjs/ui/sunken-panel.css` |
141
+ | `Select` | `@kerfjs/ui/select` | `@kerfjs/ui/select.css` |
142
+ | `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
143
+ | `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret` | `@kerfjs/ui/token-search-field` | `@kerfjs/ui/token-search-field.css` |
144
+ | `wireTokenSearchFields` | `@kerfjs/ui/wire-token-search-fields` | — |
145
+ | `StateBanner` | `@kerfjs/ui/state-banner` | `@kerfjs/ui/state-banner.css` |
146
+ | `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
147
+ | `PanelHeader` | `@kerfjs/ui/panel-header` | `@kerfjs/ui/panel-header.css` |
148
+ | `ValueTable`, `ValueTableRow` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
149
+
150
+ Opt-in application layouts keep JavaScript and CSS explicit. For the
151
+ desktop-class multi-panel shell, import `Workbench` from
152
+ `@kerfjs/ui/workbench` and load `@kerfjs/ui/workbench.css`; its supported
153
+ classes and size tokens are cataloged under the `workbench` entry. See
154
+ [`docs/workbench.md`](./docs/workbench.md) for panel ownership and responsive
155
+ replacement guidance.
156
+
157
+ `PanelHeader` is a plain `Toolbar` used as a panel, dialog, or page heading: an
158
+ optional icon control group (given a brand fill with a matching border), the
159
+ title as extra-large `ToolbarText`, the app's trailing action controls, and an
160
+ optional subtitle on a separate row below the title. It overrides no toolbar
161
+ styles — the app passes its own trailing controls (typically a
162
+ `ToolbarControlGroup`).
163
+
164
+ `DisclosureArrow` defaults to an 18px root-scaled decorative visual. Override
165
+ `--kui-disclosure-arrow-size` at the narrowest useful scope when a consumer
166
+ needs another size; the owning control still supplies interaction, naming, and
167
+ expanded state. Kerf `Select` retains its independent Web Awesome expand-glyph
168
+ scale of `.5` through `--kui-disclosure-icon-scale`. Author replacement
169
+ `DisclosureArrow` icon content facing right before its configured direction
170
+ transform is applied. Direction changes take the shortest rotation path; a
171
+ 180-degree closed-to-open tie uses counterclockwise rotation.
172
+
173
+ `ListHeader` supplies that production `DisclosureArrow` automatically when
174
+ `toggle` is true and `actionIcon` is omitted. Keep `expanded` synchronized with
175
+ real controlled content and preserve the button's stable label; ordinary
176
+ navigation must not display a disclosure arrow. A custom `actionIcon` remains
177
+ an escape hatch and replaces the default arrow entirely. The header fills its
178
+ available inline width, keeping a separate action at the logical end in a 44px
179
+ target. Its visible action glyph defaults to 18px through
180
+ `--kui-list-header-action-icon-size`.
181
+
182
+ ## Machine-readable catalog
183
+
184
+ AI tools can retrieve the shipped [`ai/component-catalog.json`](./ai/component-catalog.json)
185
+ for the exhaustive component and composition inventory. It is the canonical
186
+ source for ids, public exports, purpose and selection guidance, relationships,
187
+ delivery and side effects, companion wiring, application-owned policy,
188
+ variants, accessibility obligations, public CSS hooks, routes, and current
189
+ documentation/recipe links. The adjacent
190
+ [`component-catalog.schema.json`](./ai/component-catalog.schema.json) describes
191
+ the versioned format. Every visual entry also declares who owns its margin,
192
+ border, and padding, so a generator can fit it into Kerf's alignment model
193
+ without guessing from a screenshot or private CSS.
194
+
195
+ Catalog demo authoring is deliberately separate from the entry inventory. Load
196
+ [`catalog-authoring.json`](./ai/catalog-authoring.json) to discover the
197
+ authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract),
198
+ the exact API-signature context, public imports/helpers, and sanctioned metadata
199
+ slot. Keeping this as a companion artifact prevents per-entry selection facts
200
+ from duplicating presentation rules.
201
+
202
+ Tools that evaluate composition may additionally load
203
+ [`component-catalog-v2.json`](./ai/component-catalog-v2.json). It is a
204
+ deterministic, package-qualified projection of every v1 entry with formal
205
+ parent/context, zone/cardinality, child, state ownership, wiring, responsive,
206
+ layout, accessibility, public-boundary, and stable-diagnostic fields. V1
207
+ remains the selection and delivery compatibility surface. V2 defaults are
208
+ deliberately permissive; only documented objective rules receive an
209
+ authoritative override and enforceable diagnostic. The adjacent schema and
210
+ [`component-catalog-v2.d.ts`](./ai/component-catalog-v2.d.ts) types describe
211
+ the same contract.
212
+
213
+ Applications and downstream design systems should publish the same facts for
214
+ their own components. Start from the reusable
215
+ [`component-catalog-extension.schema.json`](./ai/component-catalog-extension.schema.json)
216
+ and the checked
217
+ [`component-catalog-extension.json`](./docs/examples/component-catalog-extension.json)
218
+ example. Give each app-owned component or composition a stable id, selection
219
+ guidance, public hooks, and explicit geometry ownership; then concatenate its
220
+ `entries` with Kerf's shipped `entries` in the AI context. Keep package/source
221
+ identity alongside each input when ids could collide. This makes a combined
222
+ tool reason about both sides of a composition using one vocabulary without
223
+ pretending app-local components are `@kerfjs/ui` exports.
224
+
225
+ Composition-aware consumers use
226
+ [`component-catalog-extension-v2.schema.json`](./ai/component-catalog-extension-v2.schema.json),
227
+ its shipped TypeScript types, and the checked
228
+ [`component-catalog-extension-v2.json`](./docs/examples/component-catalog-extension-v2.json)
229
+ example. Preserve each catalog's package and qualify every identity and
230
+ cross-catalog reference as `package:id`; never merge entries by bare id.
231
+
232
+ [`compile-time-contracts-v1.json`](./ai/compile-time-contracts-v1.json) is the
233
+ matching declaration contract: stable `KUI-T###` ids identify the invalid prop,
234
+ state, identity, accessibility, and protected-attribute combinations TypeScript
235
+ rejects. The package gate compiles one positive/negative consumer fixture against
236
+ both source and declarations extracted from the real packed tarball. The
237
+ [compile-time contract guide](./docs/type-contracts.md) documents migrations and
238
+ the dynamic DOM/children relationships that remain runtime or catalog checks.
239
+ Packages scaffolded by `create-kerf-component` maintain this v2 input from
240
+ `kerf.components.json`: `npm run catalog:generate` emits the catalog and
241
+ `npm run catalog:check` verifies source files, named public exports, explicit
242
+ author decisions, and byte-for-byte drift. Tools index the generated consumer
243
+ entries and this catalog by full key, reject duplicate full keys, search the
244
+ consumer package first, and retain package identity across every reference.
245
+ They must not infer missing semantics or geometry from rendered appearance.
246
+
247
+ ### Application UI profile
248
+
249
+ Applications can check in `.kerf-ui-profile.json` so tools do not have to infer
250
+ project-wide UI policy. Start from the shipped
251
+ [`application-ui-profile.defaults.json`](./ai/application-ui-profile.defaults.json)
252
+ and the checked
253
+ [`application-ui-profile.json`](./docs/examples/application-ui-profile.json)
254
+ workspace example. The versioned
255
+ [`application-ui-profile.schema.json`](./ai/application-ui-profile.schema.json)
256
+ and [`application-ui-profile.d.ts`](./ai/application-ui-profile.d.ts) cover
257
+ catalog locations, concept preferences, allowed theme/density choices, semantic
258
+ token overrides, layout/responsive conventions, and narrow rule exceptions.
259
+ Profiles contain policy only—never product records, user data, or broad styling
260
+ waivers.
261
+
262
+ Catalog declarations always provide a v2 `composition` location. Consumer
263
+ packages generated with composition-only metadata omit `selection`;
264
+ `@kerfjs/ui` continues to require its v1 selection catalog.
265
+
266
+ Node-based AI and static-analysis tools may import the shipped discovery API
267
+ from `@kerfjs/ui/ai/application-ui-profile.mjs`. It discovers package defaults,
268
+ then the workspace profile, then directory profiles from parent to child;
269
+ `mergeApplicationUiProfiles()` applies later scalar/map values, replaces a
270
+ catalog by package and an exception by id, and preserves source provenance.
271
+ `loadApplicationUiProfile()` resolves catalogs and returns diagnostics with the
272
+ originating file plus JSON path. Unknown/stale components, tokens, rules, and
273
+ catalog locations are errors. Every layer is checked against its then-effective
274
+ catalogs, including parent references and catalog paths later overridden by a
275
+ child profile. Synchronous integrations can require the shipped
276
+ `application-ui-profile-sync.cjs` projection and call
277
+ `loadApplicationUiProfileSync()` with already-discovered layers. Consumers that define additional stable
278
+ diagnostics pass their ids through the additive `knownRules` option; those ids
279
+ are merged with catalog diagnostics before exception validation.
280
+
281
+ ### Static CSS and layout ownership analysis
282
+
283
+ Run `kerf-ui-analyze --root . src` (or import
284
+ `@kerfjs/ui/analyzer`) to evaluate cross-file integration facts against the
285
+ composition catalogs and application profile. It catches provable private
286
+ selector reach-through, unknown tokens, competing geometry owners, and nested
287
+ scroll owners; it reports forced dimensions, repeated insets, off-scale literal
288
+ spacing, and dynamic classes separately as review findings. Text, versioned JSON,
289
+ and SARIF outputs carry stable `KUI-L###` ids, repository-relative locations,
290
+ evidence, and ownership chains. See the [analyzer guide](./docs/ui-analyzer.md).
291
+
292
+ ### Browser-backed integration evaluation
293
+
294
+ Run `kerf-ui-evaluate --url <running-app>` (or import
295
+ `@kerfjs/ui/evaluator`) after the static analyzer. Its Playwright-backed
296
+ wide/intermediate/narrow/200%-zoom, light/dark, and reduced-motion matrix checks
297
+ rendered overflow, clipping, reachability, focus/keyboard behavior, accessible
298
+ names, contrast, hit targets, scrolling, alignment, and cataloged runtime
299
+ geometry. The versioned report carries stable `KUI-B###` diagnostics, focused
300
+ DOM/computed-style evidence, hashed screenshot artifacts, explicit timeout and
301
+ retention policy, and a separate unscored human-visual rubric. See the
302
+ [browser evaluator guide](./docs/ui-evaluator.md).
303
+
304
+ ### Unified repair-loop doctor
305
+
306
+ Use `kerf-ui-doctor` for the supported application repair loop across profile/catalog validation, TypeScript, the Kerf UI ESLint preset, static layout analysis, and an optional explicitly authorized browser evaluation. It emits one portable versioned JSON report with deterministic exit codes, exact suppressions, monorepo package selection, changed/full modes, caching, and local-path redaction. See the [UI doctor guide](./docs/ui-doctor.md).
307
+
308
+ For code generation, pair catalog selection guidance with the checked-in
309
+ [`public-api-signatures-v1.md`](./ai/public-api-signatures-v1.md) declaration
310
+ snapshot. It is generated from the emitted `@kerfjs/ui` declarations and the
311
+ installed `kerfjs/actions` declaration, so callback names, props, return values,
312
+ and accepted import paths do not have to be inferred from examples. Direct
313
+ Web Awesome JSX has its own generated
314
+ [`webawesome-jsx-signatures-v1.md`](./ai/webawesome-jsx-signatures-v1.md)
315
+ context so adding the declaration boundary does not mutate a frozen measured
316
+ regression suite.
317
+
318
+ `npm run catalog:sync` deterministically projects the fields used by the UX
319
+ catalog into `ux-demo/catalog.generated.ts`, including the existing guidance
320
+ path and the first-party source path for each main, recipe, or Web Awesome
321
+ specimen. First-party component entries also derive their implementation path
322
+ from the canonical browser import. Do not edit that generated file.
323
+ `npm run check:catalog` rejects stale generated output, exports and package
324
+ paths, Web Awesome manifest/declaration drift, invalid relationships, broken
325
+ links, or a missing AI-guidance entry. Prose remains authored where design
326
+ nuance matters.
45
327
 
46
328
  Import components from their explicit JavaScript subpaths. CSS-aware browser
47
329
  bundlers such as Vite, webpack, and esbuild follow each subpath's `browser`
@@ -57,9 +339,48 @@ that convenience import, also import `@kerfjs/ui/styles.css`, which deliberately
57
339
  contains the complete layer. Non-browser/SSR tools resolve the pure `import`
58
340
  condition automatically; `@kerfjs/ui/unstyled` is the explicit CSS-free root
59
341
  entry for a browser build with a custom styling pipeline. The exported
60
- `foundation.css` and component CSS paths remain available for fully manual
61
- delivery. Load application overrides after package styles, or scope `--kui-*`
62
- variables directly on a component instance.
342
+ `@kerfjs/ui/foundation.css` and component CSS paths remain available for fully
343
+ manual delivery. Its complete supported `--kui-*` token surface is cataloged
344
+ under the `foundation` entry. Load application overrides after package styles,
345
+ or scope variables directly on a component instance.
346
+
347
+ ## Pane and content geometry
348
+
349
+ Import `@kerfjs/ui/layout.css` and use the same structural vocabulary for a
350
+ sidebar, main area, inspector, or dialog. `.kui-pane` is unpadded and contains
351
+ an optional toolbar, one scrolling `.kui-pane__content`, and an optional footer.
352
+ Add `.kui-content` to make its major children a vertical stack with 24px gaps.
353
+
354
+ ```tsx
355
+ <aside class="kui-pane">
356
+ <div class="kui-pane__toolbar"><Toolbar label="Workspace" ... /></div>
357
+ <nav class="kui-pane__content kui-content">
358
+ <section>
359
+ <ListHeader label="Workspace" count={3} countLabel="3 workspaces" />
360
+ <ListItem action="open" label="Inbox" icon={inboxIcon} />
361
+ <ListItem action="open" label="Drafts" />
362
+ </section>
363
+ <div class="kui-content-item">Workspace details</div>
364
+ </nav>
365
+ </aside>
366
+ ```
367
+
368
+ Ordinary children use `.kui-content-item`: 8px inline margin, a real 1px border
369
+ (transparent by default), 8px padding, and 12px rounded corners. The pill
370
+ modifier uses a 22px radius. A component can expose a transparent border or
371
+ background without changing layout. `ListHeader` follows the same rule while
372
+ keeping its dormant title and count-or-badge cluster separate from its optional
373
+ 44px action.
374
+
375
+ ## Spacing and application layout
376
+
377
+ Use 24px only for major vertical separation; use 8px inside content items and
378
+ between toolbar groups. Toolbar groups are 44px outside (`2px + 42px`) and keep
379
+ that geometry when their border/background are transparent. Wrap text and other
380
+ dormant toolbar content in a `ToolbarControlGroup` too. Do not pad the pane
381
+ itself, add competing wrapper insets, or give it more than one scroll owner.
382
+ Reading width and responsive pane placement remain application decisions. See
383
+ the complete [layout contract](./docs/layout.md).
63
384
 
64
385
  ## Web Awesome theme
65
386
 
@@ -67,11 +388,17 @@ Apps using Web Awesome's free components can opt into the same visual universe
67
388
  with one CSS import:
68
389
 
69
390
  ```ts
70
- import '@kerfjs/ui/webawesome.css';
71
- import '@awesome.me/webawesome/dist/components/button/button.js';
72
- import '@awesome.me/webawesome/dist/components/input/input.js';
391
+ import type {} from "@kerfjs/ui/webawesome";
392
+ import "@kerfjs/ui/webawesome.css";
393
+ import "@awesome.me/webawesome/dist/components/button/button.js";
394
+ import "@awesome.me/webawesome/dist/components/input/input.js";
73
395
  ```
74
396
 
397
+ The type-only `@kerfjs/ui/webawesome` import adds Kerf JSX intrinsic-element
398
+ declarations for the same 70 elements tracked by the catalog. It emits no
399
+ runtime code and registers nothing; keep importing only the individual Web
400
+ Awesome modules the application renders.
401
+
75
402
  `webawesome.css` includes Web Awesome's native/base theme and then applies the
76
403
  Hot Sheet 2 palette, surfaces, status colors, focus treatment, form geometry,
77
404
  radii, tooltips, and shadows through Web Awesome's public `--wa-*` contract.
@@ -90,7 +417,7 @@ classes for explicit appearance boundaries:
90
417
  ```css
91
418
  :root {
92
419
  --wa-color-brand-fill-loud: #7540a8;
93
- --wa-form-control-border-radius: .5rem;
420
+ --wa-form-control-border-radius: 0.5rem;
94
421
  }
95
422
  ```
96
423
 
@@ -100,6 +427,10 @@ foreground roles through `--kui-color-*`; stateful components also expose
100
427
  component variables such as `--kui-state-banner-background`. Override the
101
428
  foundation for an application theme, a tone variable for one semantic state, or
102
429
  a component variable on one instance without replacing component selectors.
430
+ Prefer an equivalent prop or token. When composition-specific layout still
431
+ needs a selector, the component catalog's `publicClasses` arrays define the
432
+ exact stable anatomy: public-class-to-public-class selectors are supported;
433
+ descendant tag, id, attribute-only, and unlisted-class selectors are not.
103
434
 
104
435
  `StateBanner` has opinionated `neutral`, `info`, `success`, `warning`, and
105
436
  `danger` palettes. Override an individual banner with
@@ -126,8 +457,8 @@ standalone `filled`/`outlined` appearance with `shape="rounded"` or
126
457
  appearance="toolbar"
127
458
  shape="pill"
128
459
  choices={[
129
- { value: 'list', label: 'List' },
130
- { value: 'columns', label: 'Columns' },
460
+ { value: "list", label: "List" },
461
+ { value: "columns", label: "Columns" },
131
462
  ]}
132
463
  />
133
464
  ```
@@ -137,40 +468,92 @@ value through `data-segment-value`. Override an instance through
137
468
  `--kui-segmented-{background|border|foreground|hover-background}` and
138
469
  `--kui-segmented-selected-{background|foreground|border|shadow}`.
139
470
 
471
+ `TokenSearchField` is a token-controlled contenteditable searchbox that keeps
472
+ free text and ordered filter chips in one field. Its editable text stays
473
+ DOM-owned between token changes so typing does not replace the caret. Tokens
474
+ expose stable edit/remove actions and remain atomic during editing; the app owns
475
+ parsing, suggestions, query execution, and state. Use `readTokenSearchField()`
476
+ after browser input to recover text plus token offsets, and
477
+ `placeTokenSearchCaret()` when restoring focus after a controlled update.
478
+ Call `wireTokenSearchFields()` once at a stable root to make Enter submit through
479
+ `onSubmit` without inserting a contenteditable line break and to preserve focus
480
+ plus the text-relative caret when keyboard deletion of a chip causes controlled
481
+ rendering to replace the editor. A select-all deletion is normalized to a truly
482
+ empty editor even when the browser leaves an atomic chip or line break behind.
483
+ Text still wraps visually when it reaches the field edge.
484
+ Clear actions should empty the editor's `textContent` before clearing app state.
485
+ The leading icon, first text line, clear action, and trailing slot share one
486
+ fixed alignment row; when text wraps, those controls stay pinned to that first
487
+ row instead of recentering against the taller editor.
488
+ Set `collapsible` for the first-class compact presentation: an empty closed
489
+ field renders as one iconic search action, `expanded` reveals the complete
490
+ field, and text or tokens keep it expanded. Width changes animate by default
491
+ and respect reduced-motion preferences. The field works standalone or inside a
492
+ `ToolbarControlGroup`; the application owns the transient focused/open signal,
493
+ focus transfer, and focusout policy. The catalog's Toolbar route demonstrates
494
+ that composition at wide and narrow sizes.
495
+ Override its surface through `--kui-token-search-{background|border}` and its
496
+ chips through `--kui-token-search-token-{background|foreground}`. Override
497
+ `--kui-token-search-line-size` only when the complete first-line geometry must
498
+ change together.
499
+
140
500
  `TabBar` is controlled: pass ordered `AppTab` children, then wire its keyboard
141
501
  and same-bar drag behavior with `wireTabBars(root, { onReorder })`. During a
142
502
  drag, the scroll strip automatically moves toward either edge with speed based
143
503
  on pointer proximity, exposing earlier or later drop targets. Apply the reported
144
504
  change with `reorderTabs()` or application-specific state logic. The application
145
505
  still owns selection, closing, routing, and persistence.
506
+ Use `AppTab.rootAttributes` for domain `data-*` metadata and `closeIcon` for a
507
+ decorative replacement glyph. The runtime rejects roles and case variants of
508
+ the component- or wiring-owned action, tab identity, selection, drag, drop, and
509
+ component markers. Keep the icon free of interactive descendants; the named
510
+ close button retains all close interaction.
146
511
 
147
512
  `Select` uses Web Awesome but does not register anything by itself. Install the optional peer, import the shared theme if desired, and explicitly import the registration entry in the application:
148
513
 
149
514
  ```ts
150
- import '@kerfjs/ui/webawesome.css';
151
- import '@kerfjs/ui/select/register';
515
+ import "@kerfjs/ui/webawesome.css";
516
+ import "@kerfjs/ui/select/register";
152
517
  ```
153
518
 
154
519
  That boundary keeps Web Awesome and its custom-element side effects out of bundles that use unrelated components. Automated consumer-bundle tests enforce it.
520
+ `Select` also owns the Kerf/Web Awesome reconciliation boundary: option icons
521
+ keep stable slotted elements across rerenders, and `renderSelected` content is
522
+ replaced when the controlled value changes. Consumers do not need to add
523
+ `data-key` or `data-morph-skip` workarounds around choice icons.
155
524
 
156
525
  For application choices and panes, prefer Kerf's purpose-built primitives:
157
526
  `Select` over direct Web Awesome selection/dropdown composition,
158
527
  `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web
159
528
  Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over
160
529
  Split Panel. `ResizableRegion` includes Hot Sheet 2's 1px separator and
161
- hover/focus grip. Consider Web Awesome Popup when its anchored-positioning
530
+ hover/focus grip. Its optional `handleIcon` replaces only the decorative glyph;
531
+ the component and `wireResizableRegions()` retain separator semantics and
532
+ pointer/keyboard behavior. Consider Web Awesome Popup when its anchored-positioning
162
533
  engine removes custom placement code; treat Tree, Animated Image, Comparison,
163
534
  Zoomable Frame, and the displaced alternatives above as exceptional rather
164
535
  than default patterns. The detailed rationale lives in the theme contract.
165
536
 
166
537
  ## Design and tool guidance
167
538
 
539
+ - [Component selection and composition](./docs/component-selection.md)
168
540
  - [Design philosophy](./docs/design-philosophy.md)
169
541
  - [Apple HIG translation](./docs/apple-hig.md)
170
542
  - [Accessibility and keyboard contracts](./docs/accessibility.md)
171
543
  - [Component and integration contract](./docs/component-contract.md)
544
+ - [Spacing and application layout](./docs/layout.md)
172
545
  - [Web Awesome theme contract](./docs/webawesome-theme.md)
173
546
  - [UX catalog contract](./docs/ux-demo.md)
174
547
  - [AI guide](./ai/skill.md)
175
548
 
176
- Run `npm run dev` from this directory for the category-grouped master/detail catalog. Every public visual component has a focused route; all 70 free Web Awesome 3.12 components have focused routes under the collapsible ecosystem section. One grouped `Related components` selector contains derived `Uses` / `Used by` navigation across both sets. Run `npm run check` for static/unit/bundle gates and `npm run test:e2e` for the real-browser suite.
549
+ Run `npm run dev` from this directory for the category-grouped master/detail catalog. Every public visual component has a focused route; all 70 free Web Awesome 3.12 components have focused routes under the collapsible ecosystem section. Every detail visibly links its first-party demo source and existing guidance while showing the repository-relative paths; first-party components also link their implementation source, and Web Awesome entries label local guidance as Kerf integration guidance. One grouped `Related components` selector contains derived `Uses` / `Used by` navigation across both sets. Run `npm run check` for static/unit/bundle gates and `npm run test:e2e` for the real-browser suite.
550
+
551
+ Run `npm run format` after editing source or structured content. The narrower
552
+ `npm run format:css` command remains available for style-only work. The normal
553
+ `npm run lint` and `npm run check` gates use Prettier to reject formatting drift.
554
+
555
+ For dimensions that should scale with the root font size, author pixels with
556
+ `remify()`: `gap: remify(17px)` builds to `gap: 1.0625rem` using a fixed 16px
557
+ baseline. Keep intentional 1px borders in pixels and contextual `em` values
558
+ explicit. `npm run build` emits standard CSS to `dist/styles`; `npm run dev`
559
+ applies the same transform directly to source styles and hot-reloads edits.
@@ -0,0 +1,92 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "ids": [
4
+ "KUI-B001",
5
+ "KUI-B010",
6
+ "KUI-B011",
7
+ "KUI-B012",
8
+ "KUI-B020",
9
+ "KUI-B021",
10
+ "KUI-B022",
11
+ "KUI-B023",
12
+ "KUI-B030",
13
+ "KUI-B040",
14
+ "KUI-B050",
15
+ "KUI-B060",
16
+ "KUI-B070",
17
+ "KUI-B080",
18
+ "KUI-C101",
19
+ "KUI-C102",
20
+ "KUI-C103",
21
+ "KUI-C104",
22
+ "KUI-C105",
23
+ "KUI-C106",
24
+ "KUI-C107",
25
+ "KUI-C108",
26
+ "KUI-D001",
27
+ "KUI-D002",
28
+ "KUI-D003",
29
+ "KUI-D010",
30
+ "KUI-D011",
31
+ "KUI-D020",
32
+ "KUI-L001",
33
+ "KUI-L002",
34
+ "KUI-L003",
35
+ "KUI-L004",
36
+ "KUI-L005",
37
+ "KUI-L006",
38
+ "KUI-L007",
39
+ "KUI-L008",
40
+ "KUI-L009",
41
+ "KUI-L090",
42
+ "KUI-L101",
43
+ "KUI-L102",
44
+ "KUI-L201",
45
+ "KUI-L202",
46
+ "KUI-L203",
47
+ "KUI-L301",
48
+ "KUI-L401",
49
+ "KUI-L402",
50
+ "KUI-P001",
51
+ "KUI-P002",
52
+ "KUI-P003",
53
+ "KUI-P004",
54
+ "KUI-P005",
55
+ "KUI-P006",
56
+ "KUI-P007",
57
+ "KUI-P008",
58
+ "KUI-P009",
59
+ "KUI-P010",
60
+ "KUI-P011",
61
+ "KUI-P012",
62
+ "KUI-P013",
63
+ "KUI-P014",
64
+ "KUI-P015",
65
+ "KUI-P016",
66
+ "KUI-P017",
67
+ "KUI-P018",
68
+ "KUI-P019",
69
+ "KUI-P020",
70
+ "KUI-P021",
71
+ "KUI-P022",
72
+ "KUI-P023",
73
+ "KUI-P024",
74
+ "KUI-P025",
75
+ "KUI-P026",
76
+ "KUI-P027",
77
+ "KUI-P028",
78
+ "KUI-P029",
79
+ "KUI-P030",
80
+ "KUI-T001",
81
+ "KUI-T002",
82
+ "KUI-T003",
83
+ "KUI-T004",
84
+ "KUI-T005",
85
+ "KUI-T006",
86
+ "KUI-T007",
87
+ "KUI-T008",
88
+ "KUI-T009",
89
+ "KUI-T010",
90
+ "KUI-T011"
91
+ ]
92
+ }