@kerfjs/ui 5.0.0-beta.94 → 5.0.0-beta.96

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 (388) hide show
  1. package/README.md +99 -57
  2. package/ai/component-catalog.json +1328 -94
  3. package/ai/component-composition-rules.json +11 -0
  4. package/ai/component-composition.d.ts +3 -0
  5. package/ai/component-composition.json +955 -23
  6. package/ai/component-composition.schema.json +4 -0
  7. package/ai/components/README.md +12 -0
  8. package/ai/components/badge.md +6 -2
  9. package/ai/components/choice-chips.md +80 -0
  10. package/ai/components/column-track.md +78 -0
  11. package/ai/components/combobox.md +88 -0
  12. package/ai/components/content-item.md +2 -0
  13. package/ai/components/content-swap.md +78 -0
  14. package/ai/components/corner-status.md +88 -0
  15. package/ai/components/document-baseline.md +3 -1
  16. package/ai/components/edge-activity-indicator.md +81 -0
  17. package/ai/components/file-picker.md +88 -0
  18. package/ai/components/foundation.md +1 -1
  19. package/ai/components/framed-list.md +80 -0
  20. package/ai/components/grid.md +2 -1
  21. package/ai/components/icon-button.md +82 -0
  22. package/ai/components/icon-toggle-button.md +80 -0
  23. package/ai/components/list-action-row.md +19 -7
  24. package/ai/components/list-item.md +16 -7
  25. package/ai/components/list.md +5 -2
  26. package/ai/components/nav-stack.md +2 -1
  27. package/ai/components/popup-menu.md +2 -2
  28. package/ai/components/row.md +1 -1
  29. package/ai/components/select.md +2 -1
  30. package/ai/components/split-button.md +80 -0
  31. package/ai/components/split-view.md +1 -1
  32. package/ai/components/state-banner.md +4 -2
  33. package/ai/components/summary-row.md +85 -0
  34. package/ai/components/sunken-panel.md +1 -1
  35. package/ai/components/surface-scaffold.md +8 -2
  36. package/ai/components/text.md +3 -0
  37. package/ai/components/toolbar-control-group.md +4 -2
  38. package/ai/components/toolbar-text.md +1 -0
  39. package/ai/components/toolbar.md +1 -0
  40. package/ai/components/value-table.md +9 -2
  41. package/ai/components/wa-button-group.md +2 -1
  42. package/ai/components/wa-button.md +5 -1
  43. package/ai/public-api-signatures-v1.md +1063 -52
  44. package/ai/skill.md +57 -53
  45. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  46. package/dist/anchored-surface.d.ts +13 -2
  47. package/dist/anchored-surface.js +1 -1
  48. package/dist/app-tab.js +1 -1
  49. package/dist/badge.d.ts +31 -2
  50. package/dist/badge.js +2 -1
  51. package/dist/browser/choice-chips.js +3 -0
  52. package/dist/browser/column-track.js +3 -0
  53. package/dist/browser/combobox.js +3 -0
  54. package/dist/browser/content-swap.js +3 -0
  55. package/dist/browser/corner-status.js +3 -0
  56. package/dist/browser/edge-activity-indicator.js +3 -0
  57. package/dist/browser/file-picker.js +3 -0
  58. package/dist/browser/framed-list.js +3 -0
  59. package/dist/browser/icon-button.js +4 -0
  60. package/dist/browser/icon-toggle-button.js +4 -0
  61. package/dist/browser/list-action-row.js +1 -0
  62. package/dist/browser/split-button.js +5 -0
  63. package/dist/browser/summary-row.js +3 -0
  64. package/dist/catalog-resources.d.ts +1 -0
  65. package/dist/catalog.d.ts +1 -0
  66. package/dist/catalog.js +16 -13
  67. package/dist/catalog.js.map +1 -1
  68. package/dist/chip.d.ts +1 -0
  69. package/dist/choice-chips.d.ts +58 -0
  70. package/dist/choice-chips.js +3 -0
  71. package/dist/choice-chips.js.map +1 -0
  72. package/dist/chunk-2MSPNRWJ.js +82 -0
  73. package/dist/chunk-2MSPNRWJ.js.map +1 -0
  74. package/dist/{chunk-3PO7JEK7.js → chunk-36TL6BCR.js} +18 -4
  75. package/dist/chunk-36TL6BCR.js.map +1 -0
  76. package/dist/{chunk-MORVLMDG.js → chunk-44A6LP54.js} +3 -3
  77. package/dist/chunk-44A6LP54.js.map +1 -0
  78. package/dist/{chunk-7QQ3HE47.js → chunk-4LOK4634.js} +7 -3
  79. package/dist/chunk-4LOK4634.js.map +1 -0
  80. package/dist/chunk-4UB5Z3ZZ.js +68 -0
  81. package/dist/chunk-4UB5Z3ZZ.js.map +1 -0
  82. package/dist/{chunk-PGL6TXFW.js → chunk-6BRRUPJY.js} +6 -2
  83. package/dist/chunk-6BRRUPJY.js.map +1 -0
  84. package/dist/{chunk-KAJVVN7Q.js → chunk-6NOLL5KG.js} +2 -2
  85. package/dist/{chunk-KAJVVN7Q.js.map → chunk-6NOLL5KG.js.map} +1 -1
  86. package/dist/{chunk-IOS2NXW7.js → chunk-76PWEN5Y.js} +13 -2
  87. package/dist/chunk-76PWEN5Y.js.map +1 -0
  88. package/dist/{chunk-B3TROLC2.js → chunk-7IUEBNCO.js} +7 -3
  89. package/dist/chunk-7IUEBNCO.js.map +1 -0
  90. package/dist/{chunk-75YOTZ25.js → chunk-AYHC62OZ.js} +10 -6
  91. package/dist/chunk-AYHC62OZ.js.map +1 -0
  92. package/dist/{chunk-RZYQFGMM.js → chunk-BBU2SPRE.js} +4 -4
  93. package/dist/{chunk-RZYQFGMM.js.map → chunk-BBU2SPRE.js.map} +1 -1
  94. package/dist/{chunk-QCLLBMLA.js → chunk-BU23Z5HZ.js} +37 -12
  95. package/dist/chunk-BU23Z5HZ.js.map +1 -0
  96. package/dist/{chunk-BYHGRKC3.js → chunk-CMLPFIC5.js} +3 -1
  97. package/dist/chunk-CMLPFIC5.js.map +1 -0
  98. package/dist/{chunk-3XPGJUUQ.js → chunk-D5RGM3XA.js} +3 -2
  99. package/dist/chunk-D5RGM3XA.js.map +1 -0
  100. package/dist/chunk-EIET4QLK.js +51 -0
  101. package/dist/chunk-EIET4QLK.js.map +1 -0
  102. package/dist/chunk-ETCWQLJV.js +85 -0
  103. package/dist/chunk-ETCWQLJV.js.map +1 -0
  104. package/dist/chunk-FDZNYD4C.js +138 -0
  105. package/dist/chunk-FDZNYD4C.js.map +1 -0
  106. package/dist/{chunk-XKZPBRU7.js → chunk-FOQK4F3L.js} +25 -5
  107. package/dist/chunk-FOQK4F3L.js.map +1 -0
  108. package/dist/{chunk-FL6J644M.js → chunk-GJYQ27C2.js} +4 -2
  109. package/dist/chunk-GJYQ27C2.js.map +1 -0
  110. package/dist/{chunk-DL55BSQX.js → chunk-GZE2XVKC.js} +8 -1
  111. package/dist/chunk-GZE2XVKC.js.map +1 -0
  112. package/dist/{chunk-YP2G67S7.js → chunk-HO6FU3G7.js} +2 -2
  113. package/dist/{chunk-YP2G67S7.js.map → chunk-HO6FU3G7.js.map} +1 -1
  114. package/dist/{chunk-3DXHNLME.js → chunk-IGTWXPTN.js} +25 -8
  115. package/dist/chunk-IGTWXPTN.js.map +1 -0
  116. package/dist/chunk-IKS72C6P.js +53 -0
  117. package/dist/chunk-IKS72C6P.js.map +1 -0
  118. package/dist/chunk-JYD7G4RG.js +130 -0
  119. package/dist/chunk-JYD7G4RG.js.map +1 -0
  120. package/dist/{chunk-LAZLBC2Q.js → chunk-KH4KEMSP.js} +33 -2
  121. package/dist/chunk-KH4KEMSP.js.map +1 -0
  122. package/dist/chunk-LL45C7BB.js +122 -0
  123. package/dist/chunk-LL45C7BB.js.map +1 -0
  124. package/dist/chunk-M2NRCFRO.js +45 -0
  125. package/dist/chunk-M2NRCFRO.js.map +1 -0
  126. package/dist/chunk-MJ5RU6XT.js +173 -0
  127. package/dist/chunk-MJ5RU6XT.js.map +1 -0
  128. package/dist/{chunk-GIUOXAVL.js → chunk-P74VXMB6.js} +39 -19
  129. package/dist/chunk-P74VXMB6.js.map +1 -0
  130. package/dist/{chunk-TKDDTLG5.js → chunk-PBT3CPPY.js} +31 -3
  131. package/dist/chunk-PBT3CPPY.js.map +1 -0
  132. package/dist/chunk-PRG4CL3Q.js +88 -0
  133. package/dist/chunk-PRG4CL3Q.js.map +1 -0
  134. package/dist/chunk-QH5KOFNS.js +39 -0
  135. package/dist/chunk-QH5KOFNS.js.map +1 -0
  136. package/dist/{chunk-CD5TOO22.js → chunk-QIAPOWHH.js} +2 -2
  137. package/dist/{chunk-CD5TOO22.js.map → chunk-QIAPOWHH.js.map} +1 -1
  138. package/dist/chunk-QQ3TTWFH.js +29 -0
  139. package/dist/chunk-QQ3TTWFH.js.map +1 -0
  140. package/dist/chunk-QYMJHS4K.js +36 -0
  141. package/dist/chunk-QYMJHS4K.js.map +1 -0
  142. package/dist/chunk-R42D2BAO.js +44 -0
  143. package/dist/chunk-R42D2BAO.js.map +1 -0
  144. package/dist/chunk-S2XULQEK.js +52 -0
  145. package/dist/chunk-S2XULQEK.js.map +1 -0
  146. package/dist/{chunk-NMWDHZVM.js → chunk-S4Y3YTAI.js} +2 -2
  147. package/dist/{chunk-NMWDHZVM.js.map → chunk-S4Y3YTAI.js.map} +1 -1
  148. package/dist/{chunk-O27D24CA.js → chunk-TDMHA7C3.js} +3 -2
  149. package/dist/chunk-TDMHA7C3.js.map +1 -0
  150. package/dist/chunk-U6QYTMDB.js +85 -0
  151. package/dist/chunk-U6QYTMDB.js.map +1 -0
  152. package/dist/{chunk-QQICWWNX.js → chunk-V6W56V3N.js} +18 -7
  153. package/dist/chunk-V6W56V3N.js.map +1 -0
  154. package/dist/chunk-W4IK7AWD.js +73 -0
  155. package/dist/chunk-W4IK7AWD.js.map +1 -0
  156. package/dist/{chunk-TNG3XKHB.js → chunk-Y3LC7JQO.js} +26 -8
  157. package/dist/chunk-Y3LC7JQO.js.map +1 -0
  158. package/dist/chunk-YWQGSUF2.js +84 -0
  159. package/dist/chunk-YWQGSUF2.js.map +1 -0
  160. package/dist/{chunk-MTCTX25G.js → chunk-YXOMI7ES.js} +1 -1
  161. package/dist/chunk-YXOMI7ES.js.map +1 -0
  162. package/dist/chunk-ZKKO4MHC.js +25 -0
  163. package/dist/chunk-ZKKO4MHC.js.map +1 -0
  164. package/dist/collapsible-panel.d.ts +10 -3
  165. package/dist/collapsible-panel.js +8 -5
  166. package/dist/collapsible-panel.js.map +1 -1
  167. package/dist/column-track.d.ts +41 -0
  168. package/dist/column-track.js +4 -0
  169. package/dist/column-track.js.map +1 -0
  170. package/dist/combobox.d.ts +40 -0
  171. package/dist/combobox.js +3 -0
  172. package/dist/combobox.js.map +1 -0
  173. package/dist/content-item.d.ts +21 -4
  174. package/dist/content-item.js +1 -1
  175. package/dist/content-swap.d.ts +34 -0
  176. package/dist/content-swap.js +3 -0
  177. package/dist/content-swap.js.map +1 -0
  178. package/dist/corner-status.d.ts +36 -0
  179. package/dist/corner-status.js +3 -0
  180. package/dist/corner-status.js.map +1 -0
  181. package/dist/edge-activity-indicator.d.ts +28 -0
  182. package/dist/edge-activity-indicator.js +3 -0
  183. package/dist/edge-activity-indicator.js.map +1 -0
  184. package/dist/extension-attributes-mu8MFUl0.d.ts +13 -0
  185. package/dist/file-picker.d.ts +47 -0
  186. package/dist/file-picker.js +3 -0
  187. package/dist/file-picker.js.map +1 -0
  188. package/dist/framed-list.d.ts +47 -0
  189. package/dist/framed-list.js +4 -0
  190. package/dist/framed-list.js.map +1 -0
  191. package/dist/grid.js +1 -1
  192. package/dist/help-tags-register.js +1 -1
  193. package/dist/icon-button.d.ts +46 -0
  194. package/dist/icon-button.js +6 -0
  195. package/dist/icon-button.js.map +1 -0
  196. package/dist/icon-toggle-button.d.ts +42 -0
  197. package/dist/icon-toggle-button.js +6 -0
  198. package/dist/icon-toggle-button.js.map +1 -0
  199. package/dist/index.d.ts +23 -6
  200. package/dist/index.js +44 -27
  201. package/dist/list-action-row.d.ts +47 -10
  202. package/dist/list-action-row.js +2 -1
  203. package/dist/list-header.js +1 -1
  204. package/dist/list-inset-text.js +1 -1
  205. package/dist/list-item.d.ts +10 -2
  206. package/dist/list-item.js +1 -1
  207. package/dist/list.d.ts +37 -5
  208. package/dist/list.js +1 -1
  209. package/dist/nav-stack.d.ts +1 -0
  210. package/dist/nav-stack.js +2 -1
  211. package/dist/pane.js +2 -1
  212. package/dist/popup-menu-register.js +18 -1
  213. package/dist/popup-menu-register.js.map +1 -1
  214. package/dist/popup-menu.d.ts +28 -3
  215. package/dist/popup-menu.js +1 -1
  216. package/dist/row.d.ts +6 -2
  217. package/dist/row.js +1 -1
  218. package/dist/select-register.js +1 -1
  219. package/dist/select.js +2 -1
  220. package/dist/split-button.d.ts +57 -0
  221. package/dist/split-button.js +7 -0
  222. package/dist/split-button.js.map +1 -0
  223. package/dist/split-view.d.ts +20 -2
  224. package/dist/split-view.js +22 -1
  225. package/dist/split-view.js.map +1 -1
  226. package/dist/state-banner.d.ts +17 -2
  227. package/dist/state-banner.js +2 -1
  228. package/dist/styles/badge.css +27 -0
  229. package/dist/styles/catalog/components/catalog-example.css +7 -3
  230. package/dist/styles/choice-chips.css +154 -0
  231. package/dist/styles/column-track.css +57 -0
  232. package/dist/styles/combobox.css +113 -0
  233. package/dist/styles/components/actions/icon-button/icon-button.css +22 -0
  234. package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +83 -0
  235. package/dist/styles/components/actions/popup-menu/popup-menu.css +69 -1
  236. package/dist/styles/components/actions/split-button/split-button.css +95 -0
  237. package/dist/styles/components/actions/toolbar/toolbar.css +16 -9
  238. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +144 -48
  239. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +23 -0
  240. package/dist/styles/components/collections/framed-list/framed-list.css +47 -0
  241. package/dist/styles/components/collections/list/list.css +44 -0
  242. package/dist/styles/components/collections/list-action-row/list-action-row.css +39 -0
  243. package/dist/styles/components/collections/list-item/list-item.css +45 -0
  244. package/dist/styles/components/collections/summary-row/summary-row.css +161 -0
  245. package/dist/styles/components/data-display/value-table/value-table.css +76 -0
  246. package/dist/styles/components/feedback/badge/badge.css +27 -0
  247. package/dist/styles/components/feedback/corner-status/corner-status.css +60 -0
  248. package/dist/styles/components/feedback/edge-activity-indicator/edge-activity-indicator.css +127 -0
  249. package/dist/styles/components/feedback/state-banner/state-banner.css +38 -0
  250. package/dist/styles/components/forms/choice-chips/choice-chips.css +154 -0
  251. package/dist/styles/components/forms/combobox/combobox.css +113 -0
  252. package/dist/styles/components/forms/file-picker/file-picker.css +81 -0
  253. package/dist/styles/components/forms/token-search-field/token-search-field.css +12 -1
  254. package/dist/styles/components/layout/column-track/column-track.css +57 -0
  255. package/dist/styles/components/layout/content-swap/content-swap.css +154 -0
  256. package/dist/styles/components/layout/pane/pane.css +2 -8
  257. package/dist/styles/components/layout/workbench/workbench.css +2 -8
  258. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +1 -4
  259. package/dist/styles/components/surfaces/content-item/content-item.css +18 -0
  260. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +1 -4
  261. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +119 -0
  262. package/dist/styles/components/typography/text/text.css +62 -0
  263. package/dist/styles/content-item.css +18 -0
  264. package/dist/styles/content-swap.css +154 -0
  265. package/dist/styles/corner-status.css +60 -0
  266. package/dist/styles/document.css +65 -0
  267. package/dist/styles/edge-activity-indicator.css +127 -0
  268. package/dist/styles/file-picker.css +81 -0
  269. package/dist/styles/foundation.css +8 -0
  270. package/dist/styles/framed-list.css +47 -0
  271. package/dist/styles/icon-button.css +22 -0
  272. package/dist/styles/icon-toggle-button.css +83 -0
  273. package/dist/styles/list-action-row.css +39 -0
  274. package/dist/styles/list-item.css +45 -0
  275. package/dist/styles/list.css +44 -0
  276. package/dist/styles/pane.css +2 -8
  277. package/dist/styles/popup-menu.css +69 -1
  278. package/dist/styles/split-button.css +95 -0
  279. package/dist/styles/state-banner.css +38 -0
  280. package/dist/styles/styles.css +12 -0
  281. package/dist/styles/summary-row.css +161 -0
  282. package/dist/styles/sunken-panel.css +1 -4
  283. package/dist/styles/surface-scaffold.css +119 -0
  284. package/dist/styles/tab-navigator.css +1 -4
  285. package/dist/styles/text.css +62 -0
  286. package/dist/styles/token-search-field.css +12 -1
  287. package/dist/styles/toolbar-control-group.css +144 -48
  288. package/dist/styles/toolbar-text.css +23 -0
  289. package/dist/styles/toolbar.css +16 -9
  290. package/dist/styles/value-table.css +76 -0
  291. package/dist/styles/webawesome.css +4 -4
  292. package/dist/styles/workbench.css +2 -8
  293. package/dist/summary-row.d.ts +56 -0
  294. package/dist/summary-row.js +4 -0
  295. package/dist/summary-row.js.map +1 -0
  296. package/dist/sunken-panel.d.ts +8 -1
  297. package/dist/sunken-panel.js +2 -1
  298. package/dist/surface-scaffold-register.js +7 -1
  299. package/dist/surface-scaffold-register.js.map +1 -1
  300. package/dist/surface-scaffold.d.ts +75 -2
  301. package/dist/surface-scaffold.js +2 -1
  302. package/dist/tab-navigator.js +4 -1
  303. package/dist/tab-navigator.js.map +1 -1
  304. package/dist/text.d.ts +39 -4
  305. package/dist/text.js +1 -1
  306. package/dist/toolbar-control-group.d.ts +8 -1
  307. package/dist/toolbar-control-group.js +1 -1
  308. package/dist/toolbar-text.d.ts +14 -1
  309. package/dist/toolbar-text.js +1 -1
  310. package/dist/toolbar.d.ts +14 -3
  311. package/dist/toolbar.js +1 -1
  312. package/dist/value-table.d.ts +20 -2
  313. package/dist/value-table.js +1 -1
  314. package/dist/wire-catalog.d.ts +1 -0
  315. package/dist/wire-comboboxes.d.ts +26 -0
  316. package/dist/wire-comboboxes.js +3 -0
  317. package/dist/wire-comboboxes.js.map +1 -0
  318. package/dist/wire-corner-status.d.ts +11 -0
  319. package/dist/wire-corner-status.js +3 -0
  320. package/dist/wire-corner-status.js.map +1 -0
  321. package/dist/wire-file-pickers.d.ts +26 -0
  322. package/dist/wire-file-pickers.js +3 -0
  323. package/dist/wire-file-pickers.js.map +1 -0
  324. package/dist/wire-list-reorder.d.ts +41 -0
  325. package/dist/wire-list-reorder.js +3 -0
  326. package/dist/wire-list-reorder.js.map +1 -0
  327. package/dist/wire-token-search-fields.js +1 -1
  328. package/dist/workbench.d.ts +1 -0
  329. package/dist/workbench.js +2 -1
  330. package/docs/accessibility.md +45 -2
  331. package/docs/anchored-surface.md +15 -7
  332. package/docs/app-layouts.md +2 -1
  333. package/docs/catalog.md +41 -0
  334. package/docs/component-contract.md +26 -6
  335. package/docs/component-selection.md +149 -13
  336. package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -0
  337. package/docs/design/templates/choice-chips/color-palette.svg +1 -0
  338. package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -0
  339. package/docs/design/templates/choice-chips/compact-icons.svg +1 -0
  340. package/docs/design/templates/choice-chips-dark.svg +1 -0
  341. package/docs/design/templates/choice-chips.svg +1 -0
  342. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -0
  343. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -0
  344. package/docs/design/templates/list-action-row-dark.svg +1 -1
  345. package/docs/design/templates/list-action-row.svg +1 -1
  346. package/docs/design/templates/state-banner/strip-dark.svg +1 -0
  347. package/docs/design/templates/state-banner/strip.svg +1 -0
  348. package/docs/design/templates/state-banner-dark.svg +1 -1
  349. package/docs/design/templates/state-banner.svg +1 -1
  350. package/docs/design/templates.md +1 -1
  351. package/docs/document-baseline.md +51 -0
  352. package/docs/layout.md +52 -1
  353. package/docs/split-view.md +20 -2
  354. package/docs/sunken-panel.md +13 -0
  355. package/docs/surface-scaffold.md +66 -1
  356. package/docs/ux-demo.md +1 -0
  357. package/docs/webawesome-theme.md +6 -2
  358. package/llms.txt +125 -16
  359. package/package.json +89 -1
  360. package/vite-ux-review.d.mts +39 -0
  361. package/vite-ux-review.mjs +75 -20
  362. package/dist/chunk-3DXHNLME.js.map +0 -1
  363. package/dist/chunk-3PO7JEK7.js.map +0 -1
  364. package/dist/chunk-3XPGJUUQ.js.map +0 -1
  365. package/dist/chunk-4Y4L5YEI.js +0 -66
  366. package/dist/chunk-4Y4L5YEI.js.map +0 -1
  367. package/dist/chunk-75YOTZ25.js.map +0 -1
  368. package/dist/chunk-7QQ3HE47.js.map +0 -1
  369. package/dist/chunk-A7DYEERU.js +0 -59
  370. package/dist/chunk-A7DYEERU.js.map +0 -1
  371. package/dist/chunk-B3TROLC2.js.map +0 -1
  372. package/dist/chunk-BYHGRKC3.js.map +0 -1
  373. package/dist/chunk-DL55BSQX.js.map +0 -1
  374. package/dist/chunk-FL6J644M.js.map +0 -1
  375. package/dist/chunk-GIUOXAVL.js.map +0 -1
  376. package/dist/chunk-IOS2NXW7.js.map +0 -1
  377. package/dist/chunk-J3AWE5I4.js +0 -50
  378. package/dist/chunk-J3AWE5I4.js.map +0 -1
  379. package/dist/chunk-LAZLBC2Q.js.map +0 -1
  380. package/dist/chunk-MORVLMDG.js.map +0 -1
  381. package/dist/chunk-MTCTX25G.js.map +0 -1
  382. package/dist/chunk-O27D24CA.js.map +0 -1
  383. package/dist/chunk-PGL6TXFW.js.map +0 -1
  384. package/dist/chunk-QCLLBMLA.js.map +0 -1
  385. package/dist/chunk-QQICWWNX.js.map +0 -1
  386. package/dist/chunk-TKDDTLG5.js.map +0 -1
  387. package/dist/chunk-TNG3XKHB.js.map +0 -1
  388. package/dist/chunk-XKZPBRU7.js.map +0 -1
@@ -46,6 +46,17 @@ type ToolbarTextProps = ToolbarTextBaseProps & (({
46
46
  headingLevel?: HeadingLevel;
47
47
  /** Render an unanimated loading skeleton instead of the text. */
48
48
  placeholder?: boolean;
49
+ /**
50
+ * Quiet, single-line supporting copy under the title ("Changes save
51
+ * automatically."), truncating with an ellipsis. Title and description
52
+ * share the toolbar's control band and the same text start, with or
53
+ * without a leading icon group. With a description, `id` and
54
+ * `headingLevel` apply to the title alone, so a dialog's
55
+ * `aria-labelledby` names only the title.
56
+ */
57
+ description?: string;
58
+ /** Id for the description, for a dialog's `aria-describedby`. */
59
+ descriptionId?: string;
49
60
  } & ToolbarTextWrappingProps) | {
50
61
  /** Render a native button with this delegated action; the app owns editing. */
51
62
  action: string;
@@ -53,7 +64,9 @@ type ToolbarTextProps = ToolbarTextBaseProps & (({
53
64
  placeholder?: never;
54
65
  wrap?: never;
55
66
  maxLines?: never;
67
+ description?: never;
68
+ descriptionId?: never;
56
69
  });
57
- declare function ToolbarText({ text, size, tone, hideBelow, showBelow, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, fill, slot, action, }: ToolbarTextProps): kerfjs.SafeHtml;
70
+ declare function ToolbarText({ text, size, tone, hideBelow, showBelow, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, fill, slot, action, description, descriptionId, }: ToolbarTextProps): kerfjs.SafeHtml;
58
71
 
59
72
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize, type ToolbarTextTone };
@@ -1,4 +1,4 @@
1
- export { ToolbarText } from './chunk-3DXHNLME.js';
1
+ export { ToolbarText } from './chunk-IGTWXPTN.js';
2
2
 
3
3
 
4
4
 
package/dist/toolbar.d.ts CHANGED
@@ -4,6 +4,8 @@ import { S as Sides } from './sides-BPSWde0A.js';
4
4
  import { PaneSeparatorSide } from './pane.js';
5
5
 
6
6
  type ToolbarPosition = 'header' | 'footer';
7
+ /** Control-band density: `default` (60px with 44px groups) or `compact`. */
8
+ type ToolbarDensity = 'default' | 'compact';
7
9
  interface ToolbarProps {
8
10
  leading?: KerfUiContent;
9
11
  center?: KerfUiContent;
@@ -11,6 +13,15 @@ interface ToolbarProps {
11
13
  label?: string;
12
14
  /** Use footer semantics for a bottom toolbar; defaults to header. */
13
15
  position?: ToolbarPosition;
16
+ /**
17
+ * `compact` sizes the toolbar to a 34px control band with 3px block
18
+ * insets — 40px tall — for a header embedded in a panel or card. Fill it
19
+ * with `ToolbarControlGroup size="compact"` groups; inline insets and the
20
+ * gap between zones are unchanged. Composites that render a Toolbar from a
21
+ * `ToolbarConfig` (Workbench, CollapsiblePanel, NavStack, SplitView) forward
22
+ * it and size the groups they compose to match. Defaults to `default`.
23
+ */
24
+ density?: ToolbarDensity;
14
25
  /**
15
26
  * Physical divider edges in canonical top/right/bottom/left order, drawn
16
27
  * always. Defaults to none: a toolbar pinned over or under scrolling content
@@ -59,7 +70,7 @@ interface ToolbarProps {
59
70
  * that renders a `Toolbar` for the app (a Workbench or CollapsiblePanel
60
71
  * toolbar) forwards, so the app configures that toolbar instead of styling it.
61
72
  */
62
- type ToolbarConfig = Pick<ToolbarProps, 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
63
- declare function Toolbar({ leading, center, trailing, label, position, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
73
+ type ToolbarConfig = Pick<ToolbarProps, 'density' | 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
74
+ declare function Toolbar({ leading, center, trailing, label, position, density, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
64
75
 
65
- export { Sides, Toolbar, type ToolbarConfig, type ToolbarPosition, type ToolbarProps };
76
+ export { Sides, Toolbar, type ToolbarConfig, type ToolbarDensity, type ToolbarPosition, type ToolbarProps };
package/dist/toolbar.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Toolbar } from './chunk-BYHGRKC3.js';
1
+ export { Toolbar } from './chunk-CMLPFIC5.js';
2
2
 
3
3
  //# sourceMappingURL=toolbar.js.map
@@ -1,6 +1,7 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
  import { SafeHtml } from 'kerfjs';
3
3
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
4
+ import { CssLength } from './css-values.js';
4
5
 
5
6
  interface ValueTableRowProps {
6
7
  label: string | SafeHtml;
@@ -14,15 +15,32 @@ interface ValueTableRowProps {
14
15
  }
15
16
  declare function ValueTableRow({ label, value, icon, className, placeholder, slot, }: ValueTableRowProps): SafeHtml;
16
17
 
18
+ /** `columns` keeps label and value side by side; `stacked` puts each value under its label. */
19
+ type ValueTablePresentation = 'columns' | 'stacked';
20
+ /** Table width below which columns stack: `compact` is 512px, `narrow` 576px. */
21
+ type ValueTableStackBelow = 'compact' | 'narrow';
17
22
  interface ValueTableProps {
18
23
  label: string;
19
24
  /** Compact row spacing for metadata-dense surfaces. */
20
25
  density?: 'default' | 'compact';
26
+ /**
27
+ * Minimum width of the label column (for example `px(160)`); the value then
28
+ * takes the rest of the row. Omitted, label and value share the row by
29
+ * content.
30
+ */
31
+ labelWidth?: CssLength;
32
+ /** Side-by-side columns (default) or values stacked under their labels. */
33
+ presentation?: ValueTablePresentation;
34
+ /**
35
+ * Stack the rows only while the table itself is narrower than the preset,
36
+ * so one table reads as columns in a wide dialog and stacks on a phone.
37
+ */
38
+ stackBelow?: ValueTableStackBelow;
21
39
  className?: string;
22
40
  children: KerfUiContent;
23
41
  /** Native named-slot assignment when composed inside a web component. */
24
42
  slot?: string;
25
43
  }
26
- declare function ValueTable({ label, density, className, children, slot, }: ValueTableProps): kerfjs.SafeHtml;
44
+ declare function ValueTable({ label, density, labelWidth, presentation, stackBelow, className, children, slot, }: ValueTableProps): kerfjs.SafeHtml;
27
45
 
28
- export { ValueTable, type ValueTableProps, ValueTableRow, type ValueTableRowProps };
46
+ export { ValueTable, type ValueTablePresentation, type ValueTableProps, ValueTableRow, type ValueTableRowProps, type ValueTableStackBelow };
@@ -1,4 +1,4 @@
1
- export { ValueTable, ValueTableRow } from './chunk-DL55BSQX.js';
1
+ export { ValueTable, ValueTableRow } from './chunk-GZE2XVKC.js';
2
2
 
3
3
 
4
4
 
@@ -7,6 +7,7 @@ import './pane.js';
7
7
  import './workbench.js';
8
8
  import './nav-stack-BvSKY448.js';
9
9
  import './list.js';
10
+ import './extension-attributes-mu8MFUl0.js';
10
11
  import './flex-alignment-4ms8ZbV8.js';
11
12
  import './css-values.js';
12
13
  import './panel-toolbar-CL9tYOkh.js';
@@ -0,0 +1,26 @@
1
+ type Root = HTMLElement | Document;
2
+ /** A committed combobox value. */
3
+ interface ComboboxCommit {
4
+ id: string;
5
+ value: string;
6
+ /** True when the value matched no suggestion (the person created it). */
7
+ created: boolean;
8
+ /** The field's input; clear or keep its text after applying the commit. */
9
+ input: HTMLInputElement;
10
+ }
11
+ interface WireComboboxesOptions {
12
+ onCommit: (commit: ComboboxCommit) => void;
13
+ /** Characters that commit the typed text besides Enter. Default `[',']`. */
14
+ commitKeys?: readonly string[];
15
+ }
16
+ /**
17
+ * Wire every `Combobox` below root: typing filters the suggestions (and offers
18
+ * to create the typed text), ArrowDown/ArrowUp move the active option, Enter or
19
+ * a commit key (comma by default) commits the active option or the typed text,
20
+ * a click commits an option, and Escape or leaving the field closes the list.
21
+ * Typed text that matches no suggestion commits only when the field offers
22
+ * creation; otherwise Enter commits the first matching suggestion. Dispose with the owning application.
23
+ */
24
+ declare function wireComboboxes(root: Root, { onCommit, commitKeys }: WireComboboxesOptions): () => void;
25
+
26
+ export { type ComboboxCommit, type WireComboboxesOptions, wireComboboxes };
@@ -0,0 +1,3 @@
1
+ export { wireComboboxes } from './chunk-FDZNYD4C.js';
2
+
3
+ //# sourceMappingURL=wire-comboboxes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"wire-comboboxes.js"}
@@ -0,0 +1,11 @@
1
+ type Root = HTMLElement | Document;
2
+ /**
3
+ * Open every overlay `CornerStatus` below root in the top layer, now and as
4
+ * renders insert them. Opening never moves focus, and a manual popover has no
5
+ * light dismiss or Escape, so the status stays until the application removes
6
+ * it. Where the Popover API is missing the host stays a fixed-position
7
+ * element. Dispose with the owning application.
8
+ */
9
+ declare function wireCornerStatus(root: Root): () => void;
10
+
11
+ export { wireCornerStatus };
@@ -0,0 +1,3 @@
1
+ export { wireCornerStatus } from './chunk-ZKKO4MHC.js';
2
+
3
+ //# sourceMappingURL=wire-corner-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"wire-corner-status.js"}
@@ -0,0 +1,26 @@
1
+ type Root = HTMLElement | Document;
2
+ /** Files a picker reported, and how they arrived. */
3
+ interface FilePickerSelection {
4
+ /** The trigger or drop zone element. */
5
+ picker: HTMLElement;
6
+ /** Its `pickerId`, when set. */
7
+ id?: string;
8
+ files: File[];
9
+ via: 'browse' | 'drop';
10
+ }
11
+ interface WireFilePickersOptions {
12
+ onFiles: (selection: FilePickerSelection) => void;
13
+ }
14
+ /** Whether a file matches a native `accept` list (`.png, image/*, text/plain`). */
15
+ declare function fileMatchesAccept(file: File, accept: string): boolean;
16
+ /**
17
+ * Report files chosen through any `FilePickerTrigger` or `FileDropZone` below
18
+ * root, or dropped on a `FileDropZone`, and mark a zone `data-dragging` while
19
+ * files are dragged over it. Dropped files are filtered by the input's
20
+ * `accept` (and to one when it is not `multiple`); a disabled picker ignores
21
+ * drops. The input is reset after each report, so choosing the same file again
22
+ * reports again. Dispose with the owning application.
23
+ */
24
+ declare function wireFilePickers(root: Root, { onFiles }: WireFilePickersOptions): () => void;
25
+
26
+ export { type FilePickerSelection, type WireFilePickersOptions, fileMatchesAccept, wireFilePickers };
@@ -0,0 +1,3 @@
1
+ export { fileMatchesAccept, wireFilePickers } from './chunk-2MSPNRWJ.js';
2
+
3
+ //# sourceMappingURL=wire-file-pickers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"wire-file-pickers.js"}
@@ -0,0 +1,41 @@
1
+ /** Which edge of the target row the moved rows land beside. */
2
+ type ListDropPosition = 'before' | 'after';
3
+ /** How the person asked for the move. */
4
+ type ListReorderSource = 'pointer' | 'keyboard';
5
+ /** The row the moved rows land beside, and on which side of it. */
6
+ interface ListReorderTarget {
7
+ id: string;
8
+ position: ListDropPosition;
9
+ }
10
+ /** One requested reorder. The application applies it to its own ordered state. */
11
+ interface ListReorder {
12
+ /** The containing list's `data-list-id`, when it has one. */
13
+ listId?: string;
14
+ /** The moved rows' `itemId`s, in their current order. */
15
+ sourceIds: string[];
16
+ target: ListReorderTarget;
17
+ source: ListReorderSource;
18
+ }
19
+ interface WireListReorderOptions {
20
+ /** Apply the change synchronously (for example with `reorderListItems`) and re-render. */
21
+ onReorder: (change: ListReorder) => void;
22
+ }
23
+ /**
24
+ * Move `sourceIds` (kept in their current relative order) to `target`'s side
25
+ * of the target row. Returns a new array; an unknown target, a target that is
26
+ * itself being moved, or no known sources leave the order unchanged.
27
+ */
28
+ declare function reorderListItems<T>(items: readonly T[], getId: (item: T) => string, sourceIds: readonly string[], target: ListReorderTarget): T[];
29
+ /**
30
+ * Wire native drag-and-drop and Alt+Shift+ArrowUp/ArrowDown reordering for
31
+ * draggable `ListItem`, `ListItemLink`, and `ListActionRow` rows below `root`.
32
+ * Rows reorder within their `List` (or parent element) and are identified by
33
+ * `itemId`. Dragging a selected or pressed row moves every selected row of
34
+ * its list. While a pointer drag is in progress the wiring paints the same
35
+ * `data-dragging` / `data-drop-position` attributes the rows' `dragging` and
36
+ * `dropPosition` props render. Order stays application state: `onReorder`
37
+ * reports the change and the application re-renders. Returns a disposer.
38
+ */
39
+ declare function wireListReorder(root: HTMLElement | Document, { onReorder }: WireListReorderOptions): () => void;
40
+
41
+ export { type ListDropPosition, type ListReorder, type ListReorderSource, type ListReorderTarget, type WireListReorderOptions, reorderListItems, wireListReorder };
@@ -0,0 +1,3 @@
1
+ export { reorderListItems, wireListReorder } from './chunk-MJ5RU6XT.js';
2
+
3
+ //# sourceMappingURL=wire-list-reorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"wire-list-reorder.js"}
@@ -1,4 +1,4 @@
1
- export { wireTokenSearchFields } from './chunk-TNG3XKHB.js';
1
+ export { wireTokenSearchFields } from './chunk-Y3LC7JQO.js';
2
2
 
3
3
 
4
4
 
@@ -8,6 +8,7 @@ import { a as PanelToolbar, c as PanelBottomToolbar, b as PanelChromePlacement,
8
8
  import { ToolbarConfig } from './toolbar.js';
9
9
  import './toolbar-text.js';
10
10
  import './css-values.js';
11
+ import './extension-attributes-mu8MFUl0.js';
11
12
  import './flex-alignment-4ms8ZbV8.js';
12
13
  import './sides-BPSWde0A.js';
13
14
  import './lucide-icon.js';
package/dist/workbench.js CHANGED
@@ -1,4 +1,5 @@
1
- export { Workbench } from './chunk-QCLLBMLA.js';
1
+ export { Workbench } from './chunk-BU23Z5HZ.js';
2
+
2
3
 
3
4
 
4
5
 
@@ -256,6 +256,29 @@ light and dark themes. The application owns controlled
256
256
  selection and the lifecycle, focus, and dismissal policy of any related
257
257
  popover or context menu.
258
258
 
259
+ With `trailingMenu`, the trailing control is a `PopupMenu` trigger instead of
260
+ the native trailing button: an icon-only Web Awesome button named by
261
+ `trailingMenu.label`, announced with `aria-haspopup="menu"` and
262
+ `aria-expanded`, in the same primary-then-trailing order. Opening it moves
263
+ focus to the first command; Escape or a choice closes the menu and returns
264
+ focus to the trigger. An interaction-revealed trigger stays visible while its
265
+ menu is open. A pointer opening through `openPopupMenuAt` (for example from
266
+ the row's `contextmenu`) keeps the same keyboard and dismissal behavior.
267
+
268
+ ## Reorderable list rows
269
+
270
+ A `draggable` `ListItem`, `ListItemLink`, or `ListActionRow` is a native HTML
271
+ drag source (a `ListActionRow` is dragged by its noninteractive root, so its two
272
+ buttons keep their own activation). Pointer dragging is never the only way to
273
+ reorder: `wireListReorder()` moves the focused row (or, when it is selected or
274
+ pressed, every selected row of its list) with Alt+Shift+ArrowUp and
275
+ Alt+Shift+ArrowDown, and returns focus to the moved row's focusable control
276
+ after the application re-renders. The dragged rows dim and the drop target
277
+ draws a 2px brand insertion line (system `Highlight` in forced colors), so the
278
+ landing position never relies on color alone. A loading placeholder is never
279
+ draggable. The application owns order, selection, and any announcement of the
280
+ completed move.
281
+
259
282
  ## ResizableRegion
260
283
 
261
284
  Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition
@@ -321,7 +344,11 @@ so screen-reader heading navigation and "main heading" semantics work — the sa
321
344
  role/level pair used throughout Kerf UI. Keep the levels meaningful and
322
345
  non-skipping within a view. Pass trailing
323
346
  controls as a labeled `ToolbarControlGroup` when that group needs an accessible
324
- name. Keep supporting copy as app-owned content below the toolbar.
347
+ name. A short supporting line belongs in the title's `description`: with it,
348
+ `id` and `headingLevel` move to the title span, so `aria-labelledby` names only
349
+ the title, and `descriptionId` gives the description its own id for
350
+ `aria-describedby`. Keep longer supporting copy as app-owned content below the
351
+ toolbar.
325
352
  An editable title can use `ToolbarText action="edit-title"`; it renders a native
326
353
  button whose full text remains its accessible name even when visually truncated.
327
354
  Click, Enter, and Space activate the delegated action. The app owns the input
@@ -423,6 +450,22 @@ icon. The filled track uses the normal neutral text role for readable unselected
423
450
  labels in light and dark themes. Use tabs—not a segmented control—when choices switch page regions that
424
451
  need `tab`/`tabpanel` semantics.
425
452
 
453
+ ## ChoiceChips
454
+
455
+ `ChoiceChips` renders `role="radiogroup"`, named by `label` (`aria-label`) or
456
+ by `labelledBy` (`aria-labelledby`, typically a visible `FieldLabel`). Each
457
+ choice is a native `<input type="radio">` inside its pill `<label>`, so the
458
+ browser owns the interaction: the group is a single Tab stop on the checked
459
+ radio (or the first enabled one when nothing is selected), arrow keys move and
460
+ select, Space selects, and the checked radio submits its value under `name`.
461
+ `required` makes an unselected group fail native form validation, and
462
+ `disabled` (group) or a choice's `disabled` removes it from interaction. The
463
+ radio's accessible name is the visible label; a `swatch` or `icon` is
464
+ `aria-hidden` decoration. The focus ring is drawn on the pill around the
465
+ focused radio, and the checked pill adds a second pixel of border so the
466
+ selection does not rely on hue alone; forced-colors mode paints it with
467
+ `Highlight`.
468
+
426
469
  ## TokenSearchField
427
470
 
428
471
  Use `presentation="form-field"` when a structured search query sits beside
@@ -491,7 +534,7 @@ controlled state), and ArrowRight moves the caret past a trailing chip so typed
491
534
  text lands after it. An optional `onEdit({ id, editor, event })` — with the
492
535
  originating `InputEvent` so a caller can gate on `inputType`/`data` — fires on every editor
493
536
  `input`, letting a caller drop its own `input` listener; the application still
494
- owns query parsing and result-count/loading announcements.
537
+ owns query parsing and result-count/loading announcements. When the app's `onEdit` or `onRemoveToken` changes tokens and the controlled render replaces the focused editor, `wireTokenSearchFields` moves focus and caret to the replacement at the same mutation checkpoint (a caret at the end of the query stays at the end; any other caret keeps its place in the remaining text), so keys typed at full speed are not lost.
495
538
 
496
539
  With a `createTokenSearchModel` passed to the field and registered in
497
540
  `wireTokenSearchFields(root, { models })`, grammar parsing, chips, clear/edit/
@@ -36,13 +36,21 @@ openAnchoredSurfaceAt(
36
36
  );
37
37
  ```
38
38
 
39
- Pass `context` for a pointer opened inside a modal `<dialog>`. For app-owned
40
- dialogs, include `<div data-kerf-overlay-host data-morph-skip></div>` in the
41
- dialog markup so controls in the anchored surface stay interactive. Dialogs
42
- opened by `kerfjs/overlay` get that host automatically. The helper uses the
43
- browser top layer where available, and the shared overlay fallback elsewhere.
44
- Closing an anchor's modal dialog also closes the surface. The temporary pointer
45
- anchor is removed when the surface closes.
39
+ Pass `context` for a pointer opened inside a modal dialog. Inside a Web
40
+ Awesome `wa-dialog` or `wa-drawer`, the surface stays interactive with no extra
41
+ markup: `kerfjs/overlay` finds the modal `<dialog>` in the element's shadow
42
+ root and hosts the surface in the element's light DOM, slotted inside the
43
+ dialog. Dialogs opened by `kerfjs/overlay` get a host automatically too. For an
44
+ app-owned native `<dialog>`, include
45
+ `<div data-kerf-overlay-host data-morph-skip></div>` in the dialog markup so
46
+ controls in the anchored surface stay interactive. For any other modal context,
47
+ pass `container`: an element inside the open modal, where the surface is
48
+ appended instead. The helper uses the browser top layer where available, and
49
+ the shared overlay fallback elsewhere.
50
+
51
+ Closing the anchor's modal dialog also closes the surface. Escape closes only
52
+ the surface; the dialog beneath stays open. The temporary pointer anchor is
53
+ removed when the surface closes.
46
54
 
47
55
  Override `--kui-anchored-surface-inset` and
48
56
  `--kui-anchored-surface-radius` for a theme; content can compose any Kerf UI
@@ -23,7 +23,8 @@ Full-height shells retain `height: 100%` so they remain embeddable. Give a
23
23
  top-level shell a definite height chain by importing `@kerfjs/ui/document.css`
24
24
  and applying `.kui-app-root` to the direct mount container; see the
25
25
  [document baseline](document-baseline.md). Do not replace an embeddable shell's
26
- height with `100dvh`.
26
+ height with `100dvh`; a full-viewport app instead adds `data-viewport="locked"`
27
+ to its `.kui-app-root`, which locks the document (not the shell) to `100dvh`.
27
28
 
28
29
  ## Safe areas
29
30
 
package/docs/catalog.md CHANGED
@@ -542,6 +542,47 @@ wireCatalog(app, {
542
542
  The browser helpers behind it, `uxReviewCaptureUrl` and `loadUxReviewProject`,
543
543
  are exported from `@kerfjs/ui/catalog` for a capture link placed elsewhere.
544
544
 
545
+ ### Catalogs served without Vite
546
+
547
+ A catalog served by the app's own backend (an esbuild bundle behind Hono,
548
+ Express, or a plain Node server) mounts the same endpoint from the same
549
+ Node-only subpath, on its development server only. The catalog requests
550
+ `__ux-review/project.json` relative to its page, so a page at `/ux-demo` asks
551
+ for `/__ux-review/project.json`; both helpers answer at any base path.
552
+
553
+ ```ts
554
+ import {
555
+ resolveUxReviewProject,
556
+ uxReviewMiddleware,
557
+ uxReviewProjectResponse,
558
+ } from "@kerfjs/ui/vite-ux-review";
559
+
560
+ // Resolve once at startup: the repository holding the working directory, or
561
+ // resolveUxReviewProject({ root, projectDirectory }) like the Vite plugin.
562
+ const projectDirectory = resolveUxReviewProject();
563
+
564
+ // Fetch API servers (Hono, Bun, Deno): null means "not this endpoint".
565
+ if (isDev)
566
+ app.use("*", async (c, next) =>
567
+ uxReviewProjectResponse(c.req.raw, projectDirectory) ?? next(),
568
+ );
569
+
570
+ // Node / connect servers (Express, node:http):
571
+ if (isDev) expressApp.use(uxReviewMiddleware(projectDirectory));
572
+ ```
573
+
574
+ - **`resolveUxReviewProject({ root?, projectDirectory? })`** returns the real
575
+ path the Vite plugin would serve: `projectDirectory` resolved against `root`,
576
+ or the repository holding `root` (default `process.cwd()`).
577
+ - **`uxReviewProjectResponse(request, projectDirectory)`** answers a Fetch API
578
+ `Request`: the JSON for a GET, `405` for another method, or `null` for any
579
+ other path.
580
+ - **`uxReviewMiddleware(projectDirectory)`** is the same endpoint as a
581
+ `(request, response, next)` handler; `uxReviewPlugin` mounts it on Vite.
582
+
583
+ Never register the endpoint in production: it reveals a local path, and a
584
+ deployed catalog has no local project to capture into.
585
+
545
586
  ## Custom action names
546
587
 
547
588
  The shell emits `data-action="catalog-select"` (sidebar items),
@@ -114,6 +114,14 @@ package root; `ui-wiring` resolves helper imports through this file, including
114
114
  relative re-export barrels. Every named export must also appear in
115
115
  `wiring.helpers`.
116
116
 
117
+ When a component's required wiring is the application's own root-delegated
118
+ handlers rather than a named helper, list the `data-action` values it must
119
+ handle in `wiring.actions`. Required wiring names at least one helper or action.
120
+ `ui-wiring` accepts an action when a reachable module that imports `delegate`,
121
+ `delegateCapture`, or `delegateActions` (from `kerfjs` or `kerfjs/actions`)
122
+ names it as a string, selector, or table key; a cataloged component's own
123
+ source never counts, because it renders the attribute.
124
+
117
125
  The selection catalog's `wiringProviders` lists public helpers that install
118
126
  other wiring helpers. The `ui-wiring` rule accepts a provider call for each
119
127
  helper it declares; `wireCatalog` provides `wireScrollDividers`.
@@ -316,6 +324,9 @@ and disposal.
316
324
  contain controls. When a row needs an independently interactive trailing
317
325
  region, `ListActionRow` owns the noninteractive root and the two sibling native
318
326
  buttons; the application owns their delegated behavior and controlled state.
327
+ A `ListActionRow` with `trailingMenu` composes a real `PopupMenu` as that
328
+ sibling trailing control instead of a button; the menu styles its trigger in
329
+ the row's context from `popup-menu.css`, and the row never styles it.
319
330
  Both row components align a leading icon with the first label line when
320
331
  `multiline` allows the label to wrap; additional lines extend below that fixed
321
332
  visual anchor.
@@ -550,9 +561,11 @@ a plain `<button>` — the group styles `> button` fully, and it keeps the group
550
561
  free of a Web Awesome dependency and shadow DOM. Use `ToolbarActionLink` when
551
562
  the action must retain native anchor navigation; the group owns its geometry,
552
563
  hover, and focus treatment. Set `overflow="scroll"` when a row of controls must
553
- stay inside the available toolbar width. A disabled native button keeps the
554
- group's geometry, dims to half opacity, uses the `not-allowed` cursor, and
555
- paints neither its own nor a lone group's hover surface.
564
+ stay inside the available toolbar width. A disabled native button — `disabled`,
565
+ or `aria-disabled="true"` when it must stay focusable — keeps the group's
566
+ geometry, dims to half opacity, uses the `not-allowed` cursor, and paints
567
+ neither its own nor a lone group's hover surface; a disabled raw `wa-button`
568
+ likewise paints no hover surface.
556
569
  Set `visibility="compact-only"` for a
557
570
  group that replaces wider toolbar controls below the Toolbar's compact container
558
571
  breakpoint; do not hide the group with an application class.
@@ -560,7 +573,11 @@ Use `sizing="grow"` on an expanded search group in a wrapping zone: it grows fro
560
573
  `growBasis` (19rem by default) into available row space, then takes a whole
561
574
  row at 480px container width or less. The basis remains its intrinsic minimum
562
575
  in a wider, non-stacked Toolbar, so sibling trailing groups can share the
563
- row. The collapsed search stays icon-sized.
576
+ row. The collapsed search stays icon-sized. The group owns the open and
577
+ close motion: its flex size animates while a collapsible `TokenSearchField`
578
+ inside fills it on every frame, laid out at least basis-wide and clipped by the
579
+ group, so a query never wraps or leaves an empty band mid-transition. At 480px
580
+ container width or less, and under reduced motion, it opens in one frame.
564
581
  Use `sizing="fill"` for a group, including a non-search segmented control,
565
582
  that spans its wrapping row. Set `visibility="hide-collapsed-tiny"` on a
566
583
  collapsible group to omit its closed icon at 224px or less; expanded content
@@ -649,8 +666,11 @@ owners. The [layout contract](./layout.md) lists the public roles and tokens.
649
666
  Panel, dialog, and page headings are direct `Toolbar` compositions. The leading
650
667
  zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
651
668
  `ToolbarText`; app actions belong in a trailing `ToolbarControlGroup`. Omit the
652
- icon group when it has no content. Supporting copy is app-owned content below
653
- the toolbar so it cannot pull the icon or actions out of alignment.
669
+ icon group when it has no content. A short supporting line is the title's
670
+ `ToolbarText` `description`: it renders quiet, single-line, truncating copy
671
+ under the title, starting at the title's text with or without an icon group,
672
+ and the title and description share the control band so the icon and actions
673
+ stay aligned. Longer supporting copy is app-owned content below the toolbar.
654
674
  For an editable title, `ToolbarText action="edit-title"` renders a native button
655
675
  directly in the leading zone. It keeps content width when there is room, shrinks
656
676
  and ellipsizes beside a status chip when space is tight, and emits the delegated