@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
@@ -0,0 +1,130 @@
1
+ # Design templates — components as self-contained SVGs
2
+
3
+ `docs/design/templates/` holds **SVG design templates** for `@kerfjs/ui`
4
+ components: a faithful, self-contained picture of each component in its common
5
+ presentation combinations, captured from the real rendered HTML/CSS (production
6
+ tokens and styles, representative sample data). They're for design review,
7
+ documentation, figma/paste hand-off, and any surface that wants an accurate
8
+ component picture without running the app.
9
+
10
+ ## Coverage
11
+
12
+ Templated components (each with light + dark variants): `PanelHeader`,
13
+ `ToolbarControlGroup`, `Toolbar`, `ToolbarText`, `List`, `ListItem`, `ListHeader`,
14
+ `ListActionRow`, `ValueTable`, `StateBanner`, `EmptyState`, `Skeleton`,
15
+ `SegmentedControl`, `TabBar`/`AppTab`, and `TokenSearchField`.
16
+
17
+ Deliberately **not** templated (they don't read as a single static component
18
+ picture): `Select` renders a Web Awesome custom element that needs its runtime
19
+ registered, so it has no faithful static capture; `LucideIcon` and
20
+ `DisclosureArrow` are decorative primitives best seen inside the components that
21
+ use them; `ResizableRegion` and the whole-screen layouts (`NavStack`,
22
+ `SplitView`, `Workbench`, `TabScaffold`) and the `Catalog` shell are
23
+ interaction-/viewport-driven screens rather than component cards — the live UX
24
+ catalog and the app-layouts docs cover those.
25
+
26
+ ## Layout
27
+
28
+ ```
29
+ docs/design/templates/
30
+ panel-header.svg ← library: every variant, composed (light)
31
+ panel-header-dark.svg ← library: dark theme
32
+ panel-header/
33
+ icon-summary-actions.svg ← one self-contained variant (light)
34
+ icon-summary-actions-dark.svg ← the same variant, dark theme
35
+ icon-actions.svg
36
+ icon-actions-dark.svg
37
+
38
+ toolbar-control-group.svg
39
+ toolbar-control-group-dark.svg
40
+ toolbar-control-group/
41
+
42
+ ```
43
+
44
+ - Each **variant** is captured in both themes — `<variant>.svg` (light) and
45
+ `<variant>-dark.svg` (dark) — a standalone SVG that scales crisply and drops
46
+ into an `<img>` anywhere. Dark is driven by domotion's `--color-scheme`, which
47
+ foundation.css's `light-dark()` tokens respond to. Captured with
48
+ `--text-mode system-font`, so text is emitted as authored `<text>` painted by the
49
+ viewer's system fonts: real, selectable, and small (no embedded font data). The
50
+ kerf UI design font stack is system-based, so the picture matches; a viewer
51
+ without those fonts falls back to its own.
52
+ - The **library** files (`<component>.svg` light, `<component>-dark.svg` dark) lay
53
+ the variants out with captions. The generator writes a temporary HTML page whose
54
+ `<img>` elements reference the individual variant SVGs, then captures that page
55
+ with domotion and `--flatten-nested-svg`. The final library is self-contained,
56
+ contains positioned groups rather than nested `<svg>` elements, and remains
57
+ reliable in design tools such as Sketch. The individual variant files stay
58
+ independently reusable.
59
+
60
+ ## Building
61
+
62
+ ```sh
63
+ npm run design-templates:build
64
+ ```
65
+
66
+ This renders each component's real `SafeHtml` (with its CSS subpaths + `foundation.css`
67
+ tokens and representative sample data) into a standalone page and captures it with
68
+ [`domotion-svg`](https://github.com/brianwestphal/domotion)'s `domotion capture`.
69
+ The capture command uses `--flatten-nested-svg`, which converts safely flattenable
70
+ inline SVGs (including component icons) to groups so design tools such as Sketch do
71
+ not have to interpret nested `<svg>` elements.
72
+ `domotion` must be reachable: it resolves `DOMOTION_BIN`, then a local
73
+ `node_modules/.bin/domotion`, then a sibling `../domotion` checkout.
74
+
75
+ **Keep the templates current as components change.** The variants live in the
76
+ `COMPONENTS` manifest in `scripts/build-design-templates.mjs` — when a component
77
+ gains or changes a presentation combination (e.g. a new `PanelHeader` slot), add
78
+ or adjust its variant there and re-run the build. Cover the common cases: if a
79
+ component can render with or without an icon, include both.
80
+
81
+ `npm run check:design-templates` (part of `npm run check`) is an offline gate
82
+ that verifies every component + variant in the manifest has its committed output —
83
+ a light and dark SVG per variant plus the two per-component library files — and
84
+ that no stray template files linger for a removed component. It also rejects any
85
+ variant or library capture that still contains nested `<svg>` elements, guarding
86
+ the Sketch compatibility contract. It does **not**
87
+ re-render (that needs domotion + a browser), so it catches a manifest entry whose
88
+ templates were never generated or a half-regenerated set.
89
+
90
+ Deeper **visual drift** — a component changed but its template was not regenerated —
91
+ is caught by `npm run check:design-templates:drift`, a CI-only gate (it runs in a
92
+ dedicated macOS browser job, **not** in the offline `npm run check`). The committed
93
+ templates use system-font text, whose layout metrics differ by operating system, so
94
+ macOS is the canonical exact-render environment for both generation and comparison.
95
+ The capture fixture also pins its monospace token to `Courier New`; otherwise
96
+ `ui-monospace` resolves to different fonts on developer and hosted macOS machines.
97
+ The gate regenerates every template into a throwaway directory and fails if any
98
+ regenerated SVG differs from the committed one, after normalizing the bits that
99
+ legitimately vary between runs (XML comments and the auto-minted element ids / font
100
+ names). If it fails, run `npm run design-templates:build` on macOS and commit the
101
+ updated SVGs.
102
+
103
+ ## Templating your own components
104
+
105
+ Apps that build on `@kerfjs/ui` can produce the same design templates for their
106
+ own application-level components. Copy `scripts/build-design-templates.mjs` as a
107
+ starting point and:
108
+
109
+ 1. Import your component and render it to a `SafeHtml` string with realistic
110
+ sample data (pass icon/action slots as `SafeHtml`, e.g. `LucideIcon({ … })` or
111
+ `raw('<button …>')` — never plain strings, which kerf escapes).
112
+ 2. List the component's CSS (its `@kerfjs/ui` subpaths plus `foundation.css` for
113
+ tokens and `layout.css`), and any of your own component CSS.
114
+ 3. Enumerate the presentation combinations in the per-component manifest.
115
+ 4. Capture each variant with `domotion capture <page.html> --selector <css>
116
+ --text-mode system-font --flatten-nested-svg -o <variant>.svg`, once per theme with
117
+ `--color-scheme light` / `--color-scheme dark` (if your components theme with
118
+ `light-dark()`).
119
+ 5. Build a light and dark HTML library page that references the generated variants
120
+ with `<img src="./component/variant.svg">`, and capture each page with the same
121
+ domotion options, including `--flatten-nested-svg`. Let domotion own embedding,
122
+ id isolation, and flattening instead of hand-assembling SVG markup.
123
+
124
+ Maintaining these next to the components — and reviewing the captured SVGs on
125
+ every component change — keeps the design source of truth honest.
126
+
127
+ ListItem templates retain the shared 18px leading icon and 44px row target;
128
+ regenerate both themes and library sheets when that geometry changes. The browser
129
+ pane/sidebar geometry checks cover the resulting 43px icon-label offset from the
130
+ section edge (17px content inset + 18px icon + 8px gap).
@@ -18,12 +18,63 @@ A reference image defines hierarchy, relationships, and intended feel. It does n
18
18
 
19
19
  ### Continuity is correctness
20
20
 
21
- Unrelated updates must not close controls, move focus, reset a draft, replace a selection, or jump scroll. Give every durable and transient state an explicit owner. Preserve DOM identity when meaning has not changed. Distinguish blocking foreground work from background synchronization.
21
+ Unrelated updates must not close controls, move focus, reset a draft, replace a selection, or jump scroll. Give every durable and transient state an explicit owner. The default owner is the application: domain data and persisted layout preferences — a navigation stack, a selection, a tab order, a pane size, a `collapsed`/`expanded` disclosure flag — are the app's signals, which it reads to render. A `wire…` helper owns only the _ephemeral mechanics_ around that state (a push/pop animation, overflow autoscroll, a live resize preview) and reports committed changes through callbacks. A helper takes over a piece of transient state itself only when hand-rolling that behavior is substantial and error-prone enough to cause real, inconsistent variation across apps — `wireTokenSearchFields`'s collapsible reveal/focus/Escape/blur-collapse is the bar; a one-line boolean toggle is not. Preserve DOM identity when meaning has not changed. Distinguish blocking foreground work from background synchronization.
22
22
 
23
23
  ### Hierarchy precedes decoration
24
24
 
25
25
  Establish one reading order and one dominant action per decision point. Group first with alignment, spacing, typography, and shared surfaces. A border, fill, badge, or nested card must communicate a real distinction.
26
26
 
27
+ ### Reach for the primitive, not for CSS
28
+
29
+ The package is designed to look right _unstyled_. A screen built from the
30
+ primitives, their props, and the semantic tokens should already read well, so
31
+ custom CSS is the exception. Before adding any `padding`, `margin`, `width`,
32
+ `height`, `border`, `background`, wrapper card, or decoration, check whether the
33
+ component, the pane, or the content-item already owns it — it almost always does,
34
+ and adding more usually **double-insets** or fights the component (the most common
35
+ mistake). Trust component defaults: render a control at its natural size and color
36
+ and fix the surrounding layout rather than overriding the control. Legitimate
37
+ custom CSS is limited to genuinely new structure, and even then may only join a
38
+ component's documented `publicClasses` or override documented `--kui-*` tokens at a
39
+ real composition boundary — never size, space, or re-skin a primitive by hand, and
40
+ never build a heading, toolbar, card, or pane geometry that a primitive provides.
41
+
42
+ ### Panes share one child-owned geometry
43
+
44
+ Sidebars, main areas, inspectors, and dialogs use the same unpadded pane. Their
45
+ children own margin, border, background, padding, and radius, so a transparent
46
+ surface occupies exactly the same geometry as a visible one. Major content
47
+ groups use 24px vertical separation; the inside of an item and the gap between
48
+ toolbar groups use 8px. Rows and actions keep 44px targets.
49
+
50
+ Use the package composition so the geometry has one owner:
51
+
52
+ ```tsx
53
+ <Pane element="aside" contentElement="nav" label="Workspace" contentLabel="Workspace pages">
54
+ <section>
55
+ <ListHeader label="Workspace" />
56
+ <ListItem action="open" label="Inbox" icon={inboxIcon} />
57
+ <ListItem action="open" label="Drafts" />
58
+ </section>
59
+ <div class="kui-content-item">Panel contents</div>
60
+ </Pane>
61
+ ```
62
+
63
+ Do not pad the pane and then pad every wrapper. That duplicates the geometry
64
+ and makes transparent borders behave differently from visible ones:
65
+
66
+ ```tsx
67
+ <aside class="pane padded">
68
+ <section class="padded">
69
+ <ListHeader label="Workspace" />
70
+ <div class="panel padded-again">Panel contents</div>
71
+ </section>
72
+ </aside>
73
+ ```
74
+
75
+ Change the shared item tokens at a real composition boundary when a product
76
+ needs different geometry; do not compensate with one-off negative margins.
77
+
27
78
  ### Prefer directness
28
79
 
29
80
  Use the shortest understandable, recoverable interaction. Avoid modes, dialogs, confirmations, and explicit saves when direct manipulation can safely express the same result. Low ceremony still requires a discoverable affordance, visible focus, and honest feedback.
@@ -42,6 +93,13 @@ foregrounds compatible with Hot Sheet 2 and Web Awesome. Consumers may replace
42
93
  the global palette, one semantic role, or one component instance through
43
94
  documented custom properties without rewriting component CSS.
44
95
 
96
+ Spacing is likewise a finite, semantic scale, not a free measurement. Five
97
+ canonical steps — 0, 4, 8, 16, and 24px, each a `--kui-space-*` token — map to a
98
+ single relationship apiece, chosen by how connected two elements are: no
99
+ separation, very minor air, standard within a group, between homogeneous groups,
100
+ and major between heterogeneous groups. Off-scale values (12px, 32px) are
101
+ deliberate exceptions. See [`layout.md`](layout.md) "Spacing scale".
102
+
45
103
  ### Responsive design reprioritizes
46
104
 
47
105
  Protect primary content, readable type, recognizable icons, and usable targets. Relocate secondary information before compressing it below a usable scale. Keep one clear scroll owner per region and test narrow, wide, zoomed, and intermediate layouts.
@@ -0,0 +1,54 @@
1
+ # Device class
2
+
3
+ `@kerfjs/ui/device-class` reports the current viewport as a reactive **device
4
+ class** — a size bucket × orientation × viewport-segment count — so a layout can
5
+ pick its presentation from one signal instead of hand-wiring `matchMedia`. It is
6
+ the foundation the app/dialog layouts build on (see
7
+ [`../../docs/23-app-layouts.md`](../../docs/23-app-layouts.md)).
8
+
9
+ ```ts
10
+ import { deviceClass } from "@kerfjs/ui/device-class";
11
+
12
+ const device = deviceClass(); // ReadonlySignal<DeviceClass>
13
+
14
+ effect(() => {
15
+ if (device.value.compact) showStack();
16
+ else showSplit();
17
+ });
18
+ ```
19
+
20
+ ## `DeviceClass`
21
+
22
+ | Field | Meaning |
23
+ | ------------------------------- | -------------------------------------------------------------------------- |
24
+ | `size` | `xs-mobile` \| `mobile` \| `tablet` \| `desktop` \| `xl-desktop` |
25
+ | `orientation` | `portrait` \| `landscape` |
26
+ | `segments` / `verticalSegments` | viewport segment counts (foldables / dual-screen); `1` on ordinary devices |
27
+ | `handset` | `xs-mobile` or `mobile` |
28
+ | `compact` | "one pane at a time" — a handset or a portrait tablet |
29
+ | `atLeast(size)` | true when the current size is `size` or larger |
30
+
31
+ Reading `device.value` inside an `effect`/`computed` re-runs when the viewport
32
+ crosses a breakpoint, rotates, or changes its segment count. One shared viewport
33
+ source backs every reader.
34
+
35
+ ## Breakpoints
36
+
37
+ Default minimum widths (px): `mobile` 360, `tablet` 720, `desktop` 1024,
38
+ `xl-desktop` 1440. Override per reader:
39
+
40
+ ```ts
41
+ const device = deviceClass({ breakpoints: { tablet: 900 } });
42
+ ```
43
+
44
+ The same numbers are mirrored as CSS custom properties in the foundation
45
+ (`--kui-bp-mobile`, `--kui-bp-tablet`, `--kui-bp-desktop`, `--kui-bp-xl-desktop`)
46
+ so CSS media queries and the JS signal read one source. `classifyViewport(width,
47
+ orientation, segments?, verticalSegments?, breakpoints?)` is exported as the
48
+ pure, DOM-free bucketing core.
49
+
50
+ ## Server rendering
51
+
52
+ Without a DOM, `deviceClass()` resolves to an SSR default (1024×768, landscape,
53
+ one segment) and hydrates to the real class on the client. Override the assumed
54
+ viewport with `deviceClass({ ssr: { width, height } })`.
@@ -0,0 +1,60 @@
1
+ {
2
+ "$schema": "../../ai/application-ui-profile.schema.json",
3
+ "schemaVersion": 1,
4
+ "scope": "workspace",
5
+ "catalogs": [
6
+ {
7
+ "package": "@kerfjs/ui",
8
+ "selection": {
9
+ "path": "../../ai/component-catalog.json",
10
+ "schemaVersion": 1
11
+ },
12
+ "composition": {
13
+ "path": "../../ai/component-catalog-v2.json",
14
+ "schemaVersion": 2
15
+ }
16
+ },
17
+ {
18
+ "package": "@acme/ui",
19
+ "composition": {
20
+ "path": "./component-catalog-extension-v2.json",
21
+ "schemaVersion": 2
22
+ }
23
+ }
24
+ ],
25
+ "preferences": {
26
+ "application-shell": {
27
+ "preferred": "@kerfjs/ui:recipe-app-shell",
28
+ "rationale": "The workspace uses the standard resizable three-region shell."
29
+ },
30
+ "record-inspector": {
31
+ "preferred": "@acme/ui:inspector",
32
+ "rationale": "The application-owned inspector maps record policy onto Kerf panel primitives."
33
+ }
34
+ },
35
+ "theme": {
36
+ "colorScheme": "light",
37
+ "allowedColorSchemes": ["light", "dark"],
38
+ "density": "standard",
39
+ "allowedDensities": ["standard"]
40
+ },
41
+ "tokens": {
42
+ "--kui-color-brand-fill-normal": "oklch(0.62 0.16 255)"
43
+ },
44
+ "layout": {
45
+ "shell": "@kerfjs/ui:recipe-app-shell",
46
+ "pane": "@kerfjs/ui:pane",
47
+ "responsiveStrategy": "device-class",
48
+ "compactNavigation": "nav-stack",
49
+ "scrollOwnership": "one-per-pane",
50
+ "spacingScale": "kerf-five-step"
51
+ },
52
+ "exceptions": [
53
+ {
54
+ "id": "legacy-report-grid",
55
+ "rules": ["KUI-C101"],
56
+ "target": "src/features/legacy-report/report-grid.tsx",
57
+ "rationale": "The embedded report engine owns this isolated toolbar-compatible control row."
58
+ }
59
+ ]
60
+ }
@@ -0,0 +1,120 @@
1
+ import '@kerfjs/ui/layout.css';
2
+
3
+ import { delegate, mount, signal } from 'kerfjs';
4
+ import { delegateActions } from 'kerfjs/actions';
5
+
6
+ export interface AppCommand {
7
+ id: string;
8
+ label: string;
9
+ keywords?: string[];
10
+ }
11
+
12
+ export interface CommandPaletteCallbacks {
13
+ onClose(): void;
14
+ onRun(command: AppCommand): void;
15
+ }
16
+
17
+ /**
18
+ * Application-local example, not an @kerfjs/ui export. The application owns
19
+ * ranking, history, shortcuts, focus policy, command availability, and copy.
20
+ */
21
+ export function mountCommandPaletteAdapter(
22
+ root: HTMLElement,
23
+ commands: AppCommand[],
24
+ { onClose, onRun }: CommandPaletteCallbacks,
25
+ ): () => void {
26
+ const query = signal('');
27
+ const render = () => {
28
+ const needle = query.value.trim().toLocaleLowerCase();
29
+ const matches = commands.filter(
30
+ (command) =>
31
+ !needle ||
32
+ [command.label, ...(command.keywords ?? [])].some((value) =>
33
+ value.toLocaleLowerCase().includes(needle),
34
+ ),
35
+ );
36
+ return (
37
+ <section
38
+ class="app-command-palette kui-content"
39
+ aria-label="Command palette"
40
+ >
41
+ <div class="kui-content-item">
42
+ <label for="app-command-query">Search commands</label>
43
+ <input
44
+ id="app-command-query"
45
+ type="search"
46
+ value={query.value}
47
+ autocomplete="off"
48
+ data-command-query
49
+ />
50
+ </div>
51
+ <p class="kui-content-item" aria-live="polite">
52
+ {matches.length} matching commands
53
+ </p>
54
+ <ul class="kui-content-item" aria-label="Matching commands">
55
+ {matches.map((command) => (
56
+ <li>
57
+ <button
58
+ type="button"
59
+ data-action="run-command"
60
+ data-command-id={command.id}
61
+ >
62
+ {command.label}
63
+ </button>
64
+ </li>
65
+ ))}
66
+ </ul>
67
+ <footer
68
+ class="kui-control-cluster kui-content-item"
69
+ aria-label="Command palette actions"
70
+ >
71
+ <button type="button" data-action="clear-query">
72
+ Clear search
73
+ </button>
74
+ <button type="button" data-action="close-palette">
75
+ Close
76
+ </button>
77
+ </footer>
78
+ </section>
79
+ );
80
+ };
81
+
82
+ const stopMount = mount(root, render);
83
+ const stopActions = delegateActions(root, 'click', {
84
+ 'run-command': (_event, element) => {
85
+ const id = (element as HTMLElement).dataset.commandId;
86
+ const command = commands.find((candidate) => candidate.id === id);
87
+ if (command) onRun(command);
88
+ },
89
+ 'clear-query': () => {
90
+ query.value = '';
91
+ root.querySelector<HTMLInputElement>('[data-command-query]')?.focus();
92
+ },
93
+ 'close-palette': onClose,
94
+ });
95
+ const stopInput = delegate<HTMLInputElement>(
96
+ root,
97
+ 'input',
98
+ '[data-command-query]',
99
+ (_event, input) => {
100
+ query.value = input.value;
101
+ },
102
+ );
103
+ const stopEscape = delegate(
104
+ root,
105
+ 'keydown',
106
+ '[data-command-query]',
107
+ (event) => {
108
+ if ((event as KeyboardEvent).key === 'Escape') onClose();
109
+ },
110
+ );
111
+ let disposed = false;
112
+ return () => {
113
+ if (disposed) return;
114
+ disposed = true;
115
+ stopEscape();
116
+ stopInput();
117
+ stopActions();
118
+ stopMount();
119
+ };
120
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "$schema": "../../ai/component-catalog-extension-v2.schema.json",
3
+ "schemaVersion": 2,
4
+ "package": "@acme/ui",
5
+ "compatibility": {
6
+ "v1Catalog": "./component-catalog-extension.json",
7
+ "identity": "package:id"
8
+ },
9
+ "entries": [
10
+ {
11
+ "key": "@acme/ui:inspector",
12
+ "package": "@acme/ui",
13
+ "id": "inspector",
14
+ "name": "Inspector",
15
+ "kind": "composition",
16
+ "source": "application",
17
+ "parents": { "mode": "listed", "entries": ["@kerfjs/ui:layout"] },
18
+ "contexts": ["record-detail"],
19
+ "zones": [
20
+ {
21
+ "id": "header",
22
+ "accepts": ["@kerfjs/ui:panel-header"],
23
+ "cardinality": { "min": 1, "max": 1 },
24
+ "exclusiveWith": []
25
+ },
26
+ {
27
+ "id": "facts",
28
+ "accepts": ["@kerfjs/ui:value-table"],
29
+ "cardinality": { "min": 1, "max": 1 },
30
+ "exclusiveWith": []
31
+ }
32
+ ],
33
+ "children": {
34
+ "mode": "listed",
35
+ "concepts": ["@kerfjs/ui:panel-header", "@kerfjs/ui:value-table"],
36
+ "requiredConcepts": [
37
+ "@kerfjs/ui:panel-header",
38
+ "@kerfjs/ui:value-table"
39
+ ]
40
+ },
41
+ "state": [
42
+ { "id": "selected-record", "owner": "application", "required": true }
43
+ ],
44
+ "wiring": { "required": false, "helpers": [], "obligations": [] },
45
+ "responsive": {
46
+ "owner": "application",
47
+ "behaviors": [
48
+ "May move between inline-end pane and dialog at the application breakpoint."
49
+ ]
50
+ },
51
+ "layout": {
52
+ "roles": ["inspector"],
53
+ "geometry": {
54
+ "margin": "parent",
55
+ "border": "child",
56
+ "padding": "child"
57
+ }
58
+ },
59
+ "accessibility": {
60
+ "obligations": ["The header names the inspector region."]
61
+ },
62
+ "boundaries": {
63
+ "rootClass": "acme-inspector",
64
+ "publicClasses": ["acme-inspector"],
65
+ "publicTokens": []
66
+ },
67
+ "diagnostics": [
68
+ {
69
+ "id": "KUI-C901",
70
+ "severity": "error",
71
+ "when": "the header or facts zone is absent",
72
+ "message": "Inspector requires exactly one header and one facts region."
73
+ }
74
+ ],
75
+ "provenance": {
76
+ "selection": "docs/inspector.md",
77
+ "composition": "docs/inspector.md#composition-contract"
78
+ }
79
+ }
80
+ ]
81
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "../../ai/component-catalog-extension.schema.json",
3
+ "schemaVersion": 1,
4
+ "package": "@acme/ui",
5
+ "description": "Application-owned components composed with Kerf UI.",
6
+ "entries": [
7
+ {
8
+ "id": "acme-filter-chip",
9
+ "name": "FilterChip",
10
+ "kind": "component",
11
+ "purpose": "A removable application filter displayed inside a token-search workflow.",
12
+ "useWhen": [
13
+ "A saved application filter needs a compact visible label and remove action."
14
+ ],
15
+ "avoidWhen": [
16
+ "The value belongs to TokenSearchField's own controlled token collection."
17
+ ],
18
+ "publicClasses": ["acme-filter-chip"],
19
+ "publicTokens": ["--acme-filter-chip-accent"],
20
+ "geometry": {
21
+ "margin": "none",
22
+ "border": "self",
23
+ "padding": "self"
24
+ },
25
+ "documentation": "docs/filter-chip.md"
26
+ },
27
+ {
28
+ "id": "acme-inspector",
29
+ "name": "Inspector",
30
+ "kind": "composition",
31
+ "purpose": "An application inspector composed from Kerf panel, content, and value primitives.",
32
+ "useWhen": ["A selected record needs a titled fact-and-action region."],
33
+ "avoidWhen": ["A ValueTable alone expresses the complete interaction."],
34
+ "geometry": {
35
+ "margin": "parent",
36
+ "border": "child",
37
+ "padding": "child",
38
+ "notes": [
39
+ "The embedding pane positions the inspector; PanelHeader, ValueTable, and action groups retain their own geometry."
40
+ ]
41
+ },
42
+ "documentation": "docs/inspector.md"
43
+ }
44
+ ]
45
+ }