@kerfjs/ui 5.0.0-beta.10 → 5.0.0-beta.101

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 (1022) hide show
  1. package/README.md +632 -132
  2. package/ai/application-ui-diagnostic-ids-v1.json +114 -0
  3. package/ai/application-ui-profile-sync.cjs +548 -0
  4. package/ai/application-ui-profile.d.mts +1 -0
  5. package/ai/application-ui-profile.d.ts +106 -0
  6. package/ai/application-ui-profile.defaults.json +96 -0
  7. package/ai/application-ui-profile.mjs +653 -0
  8. package/ai/application-ui-profile.schema.json +140 -0
  9. package/ai/catalog-authoring.json +34 -0
  10. package/ai/catalog-authoring.schema.json +105 -0
  11. package/ai/compile-time-contracts-v1.json +149 -0
  12. package/ai/compile-time-contracts-v1.schema.json +52 -0
  13. package/ai/component-catalog-extension.schema.json +104 -0
  14. package/ai/component-catalog.json +6668 -1002
  15. package/ai/component-catalog.schema.json +94 -1
  16. package/ai/component-class-owners.cjs +83 -0
  17. package/ai/component-composition-extension.d.ts +7 -0
  18. package/ai/component-composition-extension.schema.json +7 -0
  19. package/ai/component-composition-rules.json +551 -0
  20. package/ai/component-composition.d.ts +132 -0
  21. package/ai/component-composition.json +8937 -0
  22. package/ai/component-composition.schema.json +412 -0
  23. package/ai/components/README.md +187 -0
  24. package/ai/components/anchored-surface.md +99 -0
  25. package/ai/components/application-tabs.md +65 -0
  26. package/ai/components/backdrop-image.md +84 -0
  27. package/ai/components/badge.md +76 -0
  28. package/ai/components/chip.md +76 -0
  29. package/ai/components/choice-chips.md +87 -0
  30. package/ai/components/collapsible-panel.md +103 -0
  31. package/ai/components/column-track.md +78 -0
  32. package/ai/components/combobox.md +88 -0
  33. package/ai/components/composer.md +83 -0
  34. package/ai/components/content-item.md +98 -0
  35. package/ai/components/content-swap.md +78 -0
  36. package/ai/components/corner-status.md +88 -0
  37. package/ai/components/disclosure-arrow.md +77 -0
  38. package/ai/components/document-baseline.md +77 -0
  39. package/ai/components/edge-activity-indicator.md +81 -0
  40. package/ai/components/empty-state.md +80 -0
  41. package/ai/components/feedback.md +71 -0
  42. package/ai/components/file-picker.md +88 -0
  43. package/ai/components/floating-toolbar.md +82 -0
  44. package/ai/components/foundation.md +65 -0
  45. package/ai/components/framed-list.md +80 -0
  46. package/ai/components/grid.md +101 -0
  47. package/ai/components/headers.md +63 -0
  48. package/ai/components/icon-button.md +82 -0
  49. package/ai/components/icon-toggle-button.md +80 -0
  50. package/ai/components/layout.md +75 -0
  51. package/ai/components/list-action-row.md +108 -0
  52. package/ai/components/list-header.md +91 -0
  53. package/ai/components/list-inset-control.md +74 -0
  54. package/ai/components/list-inset-text.md +72 -0
  55. package/ai/components/list-item.md +108 -0
  56. package/ai/components/list.md +125 -0
  57. package/ai/components/loading-spinner.md +73 -0
  58. package/ai/components/lucide-icon.md +97 -0
  59. package/ai/components/nav-stack.md +120 -0
  60. package/ai/components/pane.md +125 -0
  61. package/ai/components/popup-menu.md +171 -0
  62. package/ai/components/recipe-app-shell.md +57 -0
  63. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  64. package/ai/components/recipe-compact-toolbar.md +57 -0
  65. package/ai/components/recipe-composer-form.md +57 -0
  66. package/ai/components/recipe-list-detail-dialog.md +57 -0
  67. package/ai/components/recipe-list-workspace-states.md +57 -0
  68. package/ai/components/recipe-loading-inspector.md +57 -0
  69. package/ai/components/recipe-media-detail.md +57 -0
  70. package/ai/components/recipe-navigation-sidebar.md +57 -0
  71. package/ai/components/recipe-navigation-stack.md +57 -0
  72. package/ai/components/recipe-workspace-header.md +57 -0
  73. package/ai/components/resize.md +106 -0
  74. package/ai/components/row.md +96 -0
  75. package/ai/components/segmented-control.md +82 -0
  76. package/ai/components/select.md +116 -0
  77. package/ai/components/skeleton.md +84 -0
  78. package/ai/components/spacer.md +86 -0
  79. package/ai/components/split-button.md +80 -0
  80. package/ai/components/split-view.md +105 -0
  81. package/ai/components/state-banner.md +96 -0
  82. package/ai/components/summary-row.md +85 -0
  83. package/ai/components/sunken-panel.md +79 -0
  84. package/ai/components/surface-scaffold.md +112 -0
  85. package/ai/components/tab-bar.md +114 -0
  86. package/ai/components/tab-navigator.md +105 -0
  87. package/ai/components/tabs.md +95 -0
  88. package/ai/components/text.md +90 -0
  89. package/ai/components/token-search-field.md +107 -0
  90. package/ai/components/toolbar-control-group.md +126 -0
  91. package/ai/components/toolbar-text.md +100 -0
  92. package/ai/components/toolbar.md +103 -0
  93. package/ai/components/value-table.md +80 -0
  94. package/ai/components/wa-accordion-item.md +55 -0
  95. package/ai/components/wa-accordion.md +65 -0
  96. package/ai/components/wa-animated-image.md +55 -0
  97. package/ai/components/wa-animation.md +55 -0
  98. package/ai/components/wa-avatar.md +55 -0
  99. package/ai/components/wa-badge.md +55 -0
  100. package/ai/components/wa-breadcrumb-item.md +53 -0
  101. package/ai/components/wa-breadcrumb.md +55 -0
  102. package/ai/components/wa-button-group.md +60 -0
  103. package/ai/components/wa-button.md +59 -0
  104. package/ai/components/wa-callout.md +58 -0
  105. package/ai/components/wa-card.md +59 -0
  106. package/ai/components/wa-carousel-item.md +53 -0
  107. package/ai/components/wa-carousel.md +55 -0
  108. package/ai/components/wa-checkbox-group.md +55 -0
  109. package/ai/components/wa-checkbox.md +55 -0
  110. package/ai/components/wa-color-picker.md +55 -0
  111. package/ai/components/wa-comparison.md +55 -0
  112. package/ai/components/wa-copy-button.md +55 -0
  113. package/ai/components/wa-details.md +61 -0
  114. package/ai/components/wa-dialog.md +59 -0
  115. package/ai/components/wa-divider.md +53 -0
  116. package/ai/components/wa-drawer.md +55 -0
  117. package/ai/components/wa-dropdown-item.md +60 -0
  118. package/ai/components/wa-dropdown.md +60 -0
  119. package/ai/components/wa-format-bytes.md +53 -0
  120. package/ai/components/wa-format-date.md +53 -0
  121. package/ai/components/wa-format-number.md +53 -0
  122. package/ai/components/wa-icon.md +58 -0
  123. package/ai/components/wa-include.md +53 -0
  124. package/ai/components/wa-input.md +59 -0
  125. package/ai/components/wa-intersection-observer.md +53 -0
  126. package/ai/components/wa-known-date.md +53 -0
  127. package/ai/components/wa-markdown.md +53 -0
  128. package/ai/components/wa-mutation-observer.md +53 -0
  129. package/ai/components/wa-number-input.md +55 -0
  130. package/ai/components/wa-option.md +59 -0
  131. package/ai/components/wa-otp-input.md +53 -0
  132. package/ai/components/wa-page.md +53 -0
  133. package/ai/components/wa-pagination.md +55 -0
  134. package/ai/components/wa-popover.md +55 -0
  135. package/ai/components/wa-popup.md +53 -0
  136. package/ai/components/wa-progress-bar.md +53 -0
  137. package/ai/components/wa-progress-ring.md +53 -0
  138. package/ai/components/wa-qr-code.md +53 -0
  139. package/ai/components/wa-radio-group.md +59 -0
  140. package/ai/components/wa-radio.md +55 -0
  141. package/ai/components/wa-random-content.md +53 -0
  142. package/ai/components/wa-rating.md +55 -0
  143. package/ai/components/wa-relative-time.md +53 -0
  144. package/ai/components/wa-resize-observer.md +53 -0
  145. package/ai/components/wa-scroller.md +53 -0
  146. package/ai/components/wa-select.md +63 -0
  147. package/ai/components/wa-skeleton.md +53 -0
  148. package/ai/components/wa-slider.md +55 -0
  149. package/ai/components/wa-spinner.md +58 -0
  150. package/ai/components/wa-split-panel.md +58 -0
  151. package/ai/components/wa-switch.md +53 -0
  152. package/ai/components/wa-tab-group.md +69 -0
  153. package/ai/components/wa-tab-panel.md +60 -0
  154. package/ai/components/wa-tab.md +59 -0
  155. package/ai/components/wa-tag.md +59 -0
  156. package/ai/components/wa-textarea.md +53 -0
  157. package/ai/components/wa-time-input.md +55 -0
  158. package/ai/components/wa-toast-item.md +60 -0
  159. package/ai/components/wa-toast.md +60 -0
  160. package/ai/components/wa-tooltip.md +55 -0
  161. package/ai/components/wa-tree-item.md +55 -0
  162. package/ai/components/wa-tree.md +55 -0
  163. package/ai/components/wa-zoomable-frame.md +55 -0
  164. package/ai/components/workbench.md +120 -0
  165. package/ai/public-api-signatures-v1.md +4564 -438
  166. package/ai/skill.md +490 -64
  167. package/ai/webawesome-jsx-signatures-v1.md +9 -2
  168. package/analyzer/cli.mjs +49 -0
  169. package/analyzer/component-ownership.d.mts +72 -0
  170. package/analyzer/component-ownership.mjs +429 -0
  171. package/analyzer/index.d.mts +53 -0
  172. package/analyzer/index.mjs +2375 -0
  173. package/analyzer/loud-pairs.d.mts +49 -0
  174. package/analyzer/loud-pairs.mjs +357 -0
  175. package/analyzer/report.schema.json +66 -0
  176. package/analyzer/selectors.d.mts +21 -0
  177. package/analyzer/selectors.mjs +212 -0
  178. package/catalog-projection-cli.mjs +96 -0
  179. package/catalog-projection.d.mts +55 -0
  180. package/catalog-projection.mjs +62 -0
  181. package/dist/anchored-surface.d.ts +69 -0
  182. package/dist/anchored-surface.js +3 -0
  183. package/dist/anchored-surface.js.map +1 -0
  184. package/dist/app-tab.d.ts +39 -4
  185. package/dist/app-tab.js +2 -1
  186. package/dist/backdrop-image.d.ts +132 -0
  187. package/dist/backdrop-image.js +5 -0
  188. package/dist/backdrop-image.js.map +1 -0
  189. package/dist/badge.d.ts +83 -0
  190. package/dist/badge.js +4 -0
  191. package/dist/badge.js.map +1 -0
  192. package/dist/browser/anchored-surface.js +3 -0
  193. package/dist/browser/backdrop-image.js +3 -0
  194. package/dist/browser/badge.js +3 -0
  195. package/dist/browser/catalog.js +28 -0
  196. package/dist/browser/chip.js +3 -0
  197. package/dist/browser/choice-chips.js +3 -0
  198. package/dist/browser/collapsible-panel.js +9 -0
  199. package/dist/browser/column-track.js +3 -0
  200. package/dist/browser/combobox.js +3 -0
  201. package/dist/browser/composer.js +4 -0
  202. package/dist/browser/content-item.js +3 -0
  203. package/dist/browser/content-swap.js +3 -0
  204. package/dist/browser/corner-status.js +3 -0
  205. package/dist/browser/edge-activity-indicator.js +3 -0
  206. package/dist/browser/file-picker.js +3 -0
  207. package/dist/browser/floating-toolbar.js +3 -0
  208. package/dist/browser/framed-list.js +3 -0
  209. package/dist/browser/grid.js +3 -0
  210. package/dist/browser/icon-button.js +4 -0
  211. package/dist/browser/icon-toggle-button.js +4 -0
  212. package/dist/browser/list-action-row.js +2 -0
  213. package/dist/browser/list-header.js +3 -1
  214. package/dist/browser/list-inset-control.js +3 -0
  215. package/dist/browser/list-inset-text.js +3 -0
  216. package/dist/browser/list-item.js +1 -0
  217. package/dist/browser/list.js +3 -0
  218. package/dist/browser/nav-stack.js +11 -0
  219. package/dist/browser/pane.js +3 -0
  220. package/dist/browser/popup-menu.js +3 -0
  221. package/dist/browser/row.js +3 -0
  222. package/dist/browser/segmented-control.js +0 -1
  223. package/dist/browser/select.js +2 -1
  224. package/dist/browser/spacer.js +3 -0
  225. package/dist/browser/split-button.js +5 -0
  226. package/dist/browser/split-view.js +13 -0
  227. package/dist/browser/state-banner.js +1 -0
  228. package/dist/browser/summary-row.js +3 -0
  229. package/dist/browser/sunken-panel.js +3 -0
  230. package/dist/browser/surface-scaffold.js +3 -0
  231. package/dist/browser/tab-navigator.js +4 -0
  232. package/dist/browser/text.js +3 -0
  233. package/dist/browser/toolbar-control-group.js +1 -0
  234. package/dist/browser/workbench.js +14 -0
  235. package/dist/catalog-resources.d.ts +50 -0
  236. package/dist/catalog-resources.js +22 -0
  237. package/dist/catalog-resources.js.map +1 -0
  238. package/dist/catalog.d.ts +134 -101
  239. package/dist/catalog.js +669 -105
  240. package/dist/catalog.js.map +1 -1
  241. package/dist/chip.d.ts +69 -0
  242. package/dist/chip.js +3 -0
  243. package/dist/chip.js.map +1 -0
  244. package/dist/choice-chips.d.ts +82 -0
  245. package/dist/choice-chips.js +3 -0
  246. package/dist/choice-chips.js.map +1 -0
  247. package/dist/chunk-2GOCOLQL.js +270 -0
  248. package/dist/chunk-2GOCOLQL.js.map +1 -0
  249. package/dist/chunk-2MSPNRWJ.js +82 -0
  250. package/dist/chunk-2MSPNRWJ.js.map +1 -0
  251. package/dist/chunk-2PXZBFEC.js +141 -0
  252. package/dist/chunk-2PXZBFEC.js.map +1 -0
  253. package/dist/chunk-34U4ANDJ.js +119 -0
  254. package/dist/chunk-34U4ANDJ.js.map +1 -0
  255. package/dist/chunk-3SKAEPPZ.js +165 -0
  256. package/dist/chunk-3SKAEPPZ.js.map +1 -0
  257. package/dist/{chunk-56RJXPHG.js → chunk-3VXDSIBJ.js} +7 -4
  258. package/dist/chunk-3VXDSIBJ.js.map +1 -0
  259. package/dist/chunk-3WYREXW4.js +120 -0
  260. package/dist/chunk-3WYREXW4.js.map +1 -0
  261. package/dist/chunk-4UB5Z3ZZ.js +68 -0
  262. package/dist/chunk-4UB5Z3ZZ.js.map +1 -0
  263. package/dist/chunk-5NQF35VO.js +67 -0
  264. package/dist/chunk-5NQF35VO.js.map +1 -0
  265. package/dist/chunk-6C6DLP3W.js +31 -0
  266. package/dist/chunk-6C6DLP3W.js.map +1 -0
  267. package/dist/chunk-6E2H2E5A.js +196 -0
  268. package/dist/chunk-6E2H2E5A.js.map +1 -0
  269. package/dist/chunk-7IUEBNCO.js +108 -0
  270. package/dist/chunk-7IUEBNCO.js.map +1 -0
  271. package/dist/chunk-AN5IWMTM.js +24 -0
  272. package/dist/chunk-AN5IWMTM.js.map +1 -0
  273. package/dist/chunk-AV7CPAPT.js +82 -0
  274. package/dist/chunk-AV7CPAPT.js.map +1 -0
  275. package/dist/chunk-B53PS2LE.js +34 -0
  276. package/dist/chunk-B53PS2LE.js.map +1 -0
  277. package/dist/chunk-BYFTHA4I.js +153 -0
  278. package/dist/chunk-BYFTHA4I.js.map +1 -0
  279. package/dist/chunk-CA7LNX3J.js +44 -0
  280. package/dist/chunk-CA7LNX3J.js.map +1 -0
  281. package/dist/chunk-CEJ5FK6G.js +288 -0
  282. package/dist/chunk-CEJ5FK6G.js.map +1 -0
  283. package/dist/chunk-CMLPFIC5.js +46 -0
  284. package/dist/chunk-CMLPFIC5.js.map +1 -0
  285. package/dist/chunk-CVD5IZGB.js +66 -0
  286. package/dist/chunk-CVD5IZGB.js.map +1 -0
  287. package/dist/chunk-D5RGM3XA.js +38 -0
  288. package/dist/chunk-D5RGM3XA.js.map +1 -0
  289. package/dist/chunk-DZJ4GBSP.js +59 -0
  290. package/dist/chunk-DZJ4GBSP.js.map +1 -0
  291. package/dist/chunk-EIET4QLK.js +51 -0
  292. package/dist/chunk-EIET4QLK.js.map +1 -0
  293. package/dist/chunk-EKHDLBRP.js +86 -0
  294. package/dist/chunk-EKHDLBRP.js.map +1 -0
  295. package/dist/chunk-ELCMSQNJ.js +49 -0
  296. package/dist/chunk-ELCMSQNJ.js.map +1 -0
  297. package/dist/chunk-ETCWQLJV.js +85 -0
  298. package/dist/chunk-ETCWQLJV.js.map +1 -0
  299. package/dist/chunk-FDZNYD4C.js +138 -0
  300. package/dist/chunk-FDZNYD4C.js.map +1 -0
  301. package/dist/chunk-FNZQOUZ5.js +52 -0
  302. package/dist/chunk-FNZQOUZ5.js.map +1 -0
  303. package/dist/chunk-FR76ZJQC.js +90 -0
  304. package/dist/chunk-FR76ZJQC.js.map +1 -0
  305. package/dist/chunk-G3J7JDP6.js +29 -0
  306. package/dist/chunk-G3J7JDP6.js.map +1 -0
  307. package/dist/chunk-GS2QD3N7.js +14 -0
  308. package/dist/chunk-GS2QD3N7.js.map +1 -0
  309. package/dist/chunk-HLDRH23D.js +84 -0
  310. package/dist/chunk-HLDRH23D.js.map +1 -0
  311. package/dist/chunk-HQZYKJ56.js +302 -0
  312. package/dist/chunk-HQZYKJ56.js.map +1 -0
  313. package/dist/chunk-HZPHCSCS.js +95 -0
  314. package/dist/chunk-HZPHCSCS.js.map +1 -0
  315. package/dist/chunk-IKS72C6P.js +53 -0
  316. package/dist/chunk-IKS72C6P.js.map +1 -0
  317. package/dist/chunk-IM3GKYOG.js +202 -0
  318. package/dist/chunk-IM3GKYOG.js.map +1 -0
  319. package/dist/chunk-IQSRHXZR.js +164 -0
  320. package/dist/chunk-IQSRHXZR.js.map +1 -0
  321. package/dist/chunk-IXLUZHGT.js +162 -0
  322. package/dist/chunk-IXLUZHGT.js.map +1 -0
  323. package/dist/chunk-JOR5LGYE.js +55 -0
  324. package/dist/chunk-JOR5LGYE.js.map +1 -0
  325. package/dist/chunk-K4AT3V3J.js +545 -0
  326. package/dist/chunk-K4AT3V3J.js.map +1 -0
  327. package/dist/chunk-KCS6NJ3O.js +82 -0
  328. package/dist/chunk-KCS6NJ3O.js.map +1 -0
  329. package/dist/chunk-KH4KEMSP.js +71 -0
  330. package/dist/chunk-KH4KEMSP.js.map +1 -0
  331. package/dist/chunk-LL45C7BB.js +122 -0
  332. package/dist/chunk-LL45C7BB.js.map +1 -0
  333. package/dist/chunk-LOSRXZAH.js +100 -0
  334. package/dist/chunk-LOSRXZAH.js.map +1 -0
  335. package/dist/chunk-LPHU44S3.js +24 -0
  336. package/dist/chunk-LPHU44S3.js.map +1 -0
  337. package/dist/chunk-M5KZ26VV.js +148 -0
  338. package/dist/chunk-M5KZ26VV.js.map +1 -0
  339. package/dist/chunk-MF6ZUUJZ.js +300 -0
  340. package/dist/chunk-MF6ZUUJZ.js.map +1 -0
  341. package/dist/chunk-MHMWQ7RB.js +19 -0
  342. package/dist/chunk-MHMWQ7RB.js.map +1 -0
  343. package/dist/chunk-MJ5RU6XT.js +173 -0
  344. package/dist/chunk-MJ5RU6XT.js.map +1 -0
  345. package/dist/chunk-MXNIVEVL.js +48 -0
  346. package/dist/chunk-MXNIVEVL.js.map +1 -0
  347. package/dist/{chunk-YGN7OMLT.js → chunk-NS2TBYM4.js} +8 -5
  348. package/dist/chunk-NS2TBYM4.js.map +1 -0
  349. package/dist/chunk-NS762OVM.js +222 -0
  350. package/dist/chunk-NS762OVM.js.map +1 -0
  351. package/dist/chunk-OZ6X76G5.js +547 -0
  352. package/dist/chunk-OZ6X76G5.js.map +1 -0
  353. package/dist/chunk-PKL6QJKK.js +835 -0
  354. package/dist/chunk-PKL6QJKK.js.map +1 -0
  355. package/dist/chunk-QDSZTQXL.js +28 -0
  356. package/dist/chunk-QDSZTQXL.js.map +1 -0
  357. package/dist/chunk-QH5KOFNS.js +39 -0
  358. package/dist/chunk-QH5KOFNS.js.map +1 -0
  359. package/dist/chunk-QLA25V2K.js +493 -0
  360. package/dist/chunk-QLA25V2K.js.map +1 -0
  361. package/dist/chunk-QTSMHH5J.js +85 -0
  362. package/dist/chunk-QTSMHH5J.js.map +1 -0
  363. package/dist/chunk-QYMJHS4K.js +36 -0
  364. package/dist/chunk-QYMJHS4K.js.map +1 -0
  365. package/dist/chunk-S2XULQEK.js +52 -0
  366. package/dist/chunk-S2XULQEK.js.map +1 -0
  367. package/dist/chunk-S3ECMF23.js +33 -0
  368. package/dist/chunk-S3ECMF23.js.map +1 -0
  369. package/dist/chunk-S4Y3YTAI.js +35 -0
  370. package/dist/chunk-S4Y3YTAI.js.map +1 -0
  371. package/dist/chunk-S4ZGTDSG.js +18 -0
  372. package/dist/chunk-S4ZGTDSG.js.map +1 -0
  373. package/dist/chunk-SCDWURBO.js +136 -0
  374. package/dist/chunk-SCDWURBO.js.map +1 -0
  375. package/dist/chunk-SIW64V65.js +176 -0
  376. package/dist/chunk-SIW64V65.js.map +1 -0
  377. package/dist/chunk-SQ5DH66U.js +37 -0
  378. package/dist/chunk-SQ5DH66U.js.map +1 -0
  379. package/dist/chunk-TDMHA7C3.js +251 -0
  380. package/dist/chunk-TDMHA7C3.js.map +1 -0
  381. package/dist/chunk-TGLUDQP2.js +138 -0
  382. package/dist/chunk-TGLUDQP2.js.map +1 -0
  383. package/dist/chunk-U6QYTMDB.js +85 -0
  384. package/dist/chunk-U6QYTMDB.js.map +1 -0
  385. package/dist/chunk-VFYO3UGZ.js +45 -0
  386. package/dist/chunk-VFYO3UGZ.js.map +1 -0
  387. package/dist/chunk-W4IK7AWD.js +73 -0
  388. package/dist/chunk-W4IK7AWD.js.map +1 -0
  389. package/dist/chunk-WVS6CUCT.js +48 -0
  390. package/dist/chunk-WVS6CUCT.js.map +1 -0
  391. package/dist/chunk-Y6KT7ZTR.js +109 -0
  392. package/dist/chunk-Y6KT7ZTR.js.map +1 -0
  393. package/dist/chunk-YBWQR2OK.js +526 -0
  394. package/dist/chunk-YBWQR2OK.js.map +1 -0
  395. package/dist/chunk-YMUIQRWK.js +44 -0
  396. package/dist/chunk-YMUIQRWK.js.map +1 -0
  397. package/dist/chunk-YQ2AC4E2.js +59 -0
  398. package/dist/chunk-YQ2AC4E2.js.map +1 -0
  399. package/dist/chunk-ZKKO4MHC.js +25 -0
  400. package/dist/chunk-ZKKO4MHC.js.map +1 -0
  401. package/dist/chunk-ZNROKDSZ.js +54 -0
  402. package/dist/chunk-ZNROKDSZ.js.map +1 -0
  403. package/dist/chunk-ZYU5WRC3.js +230 -0
  404. package/dist/chunk-ZYU5WRC3.js.map +1 -0
  405. package/dist/collapsible-panel.d.ts +96 -17
  406. package/dist/collapsible-panel.js +133 -14
  407. package/dist/collapsible-panel.js.map +1 -1
  408. package/dist/column-track.d.ts +41 -0
  409. package/dist/column-track.js +4 -0
  410. package/dist/column-track.js.map +1 -0
  411. package/dist/combobox.d.ts +40 -0
  412. package/dist/combobox.js +3 -0
  413. package/dist/combobox.js.map +1 -0
  414. package/dist/composer.d.ts +62 -0
  415. package/dist/composer.js +5 -0
  416. package/dist/composer.js.map +1 -0
  417. package/dist/content-item.d.ts +116 -0
  418. package/dist/content-item.js +4 -0
  419. package/dist/content-item.js.map +1 -0
  420. package/dist/content-swap.d.ts +34 -0
  421. package/dist/content-swap.js +3 -0
  422. package/dist/content-swap.js.map +1 -0
  423. package/dist/corner-status.d.ts +36 -0
  424. package/dist/corner-status.js +3 -0
  425. package/dist/corner-status.js.map +1 -0
  426. package/dist/css-values.d.ts +127 -0
  427. package/dist/css-values.js +3 -0
  428. package/dist/css-values.js.map +1 -0
  429. package/dist/device-class.js +34 -6
  430. package/dist/device-class.js.map +1 -1
  431. package/dist/disclosure-arrow.d.ts +6 -1
  432. package/dist/disclosure-arrow.js +2 -1
  433. package/dist/edge-activity-indicator.d.ts +28 -0
  434. package/dist/edge-activity-indicator.js +3 -0
  435. package/dist/edge-activity-indicator.js.map +1 -0
  436. package/dist/empty-state.d.ts +5 -2
  437. package/dist/empty-state.js +2 -1
  438. package/dist/extension-attributes-mu8MFUl0.d.ts +13 -0
  439. package/dist/file-picker.d.ts +47 -0
  440. package/dist/file-picker.js +3 -0
  441. package/dist/file-picker.js.map +1 -0
  442. package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
  443. package/dist/floating-toolbar.d.ts +51 -0
  444. package/dist/floating-toolbar.js +3 -0
  445. package/dist/floating-toolbar.js.map +1 -0
  446. package/dist/framed-list.d.ts +47 -0
  447. package/dist/framed-list.js +4 -0
  448. package/dist/framed-list.js.map +1 -0
  449. package/dist/grid.d.ts +58 -0
  450. package/dist/grid.js +6 -0
  451. package/dist/grid.js.map +1 -0
  452. package/dist/help-tags-register.d.ts +13 -0
  453. package/dist/help-tags-register.js +9 -0
  454. package/dist/help-tags-register.js.map +1 -0
  455. package/dist/icon-button.d.ts +46 -0
  456. package/dist/icon-button.js +6 -0
  457. package/dist/icon-button.js.map +1 -0
  458. package/dist/icon-toggle-button.d.ts +42 -0
  459. package/dist/icon-toggle-button.js +6 -0
  460. package/dist/icon-toggle-button.js.map +1 -0
  461. package/dist/index.d.ts +65 -17
  462. package/dist/index.js +71 -24
  463. package/dist/list-action-row.d.ts +69 -12
  464. package/dist/list-action-row.js +5 -1
  465. package/dist/list-header.d.ts +65 -10
  466. package/dist/list-header.js +4 -1
  467. package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
  468. package/dist/list-inset-control.d.ts +22 -0
  469. package/dist/list-inset-control.js +3 -0
  470. package/dist/list-inset-control.js.map +1 -0
  471. package/dist/list-inset-text.d.ts +30 -0
  472. package/dist/list-inset-text.js +4 -0
  473. package/dist/list-inset-text.js.map +1 -0
  474. package/dist/list-item.d.ts +49 -5
  475. package/dist/list-item.js +4 -1
  476. package/dist/list.d.ts +128 -0
  477. package/dist/list.js +7 -0
  478. package/dist/list.js.map +1 -0
  479. package/dist/loading-spinner.d.ts +12 -2
  480. package/dist/loading-spinner.js +2 -1
  481. package/dist/lucide-icon.d.ts +15 -3
  482. package/dist/lucide-icon.js +2 -1
  483. package/dist/nav-stack-CU_0dKtI.d.ts +194 -0
  484. package/dist/nav-stack.d.ts +15 -38
  485. package/dist/nav-stack.js +14 -1
  486. package/dist/pane.d.ts +225 -0
  487. package/dist/pane.js +6 -0
  488. package/dist/pane.js.map +1 -0
  489. package/dist/panel-toolbar-vg6Ir5Dy.d.ts +77 -0
  490. package/dist/popup-menu-register.d.ts +10 -0
  491. package/dist/popup-menu-register.js +336 -0
  492. package/dist/popup-menu-register.js.map +1 -0
  493. package/dist/popup-menu.d.ts +125 -0
  494. package/dist/popup-menu.js +3 -0
  495. package/dist/popup-menu.js.map +1 -0
  496. package/dist/resizable-region.d.ts +32 -3
  497. package/dist/resizable-region.js +1 -1
  498. package/dist/row.d.ts +53 -0
  499. package/dist/row.js +7 -0
  500. package/dist/row.js.map +1 -0
  501. package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
  502. package/dist/segmented-control.d.ts +12 -9
  503. package/dist/segmented-control.js +1 -2
  504. package/dist/select-register.js +255 -3
  505. package/dist/select-register.js.map +1 -1
  506. package/dist/select.d.ts +103 -8
  507. package/dist/select.js +4 -1
  508. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  509. package/dist/semantic-tone-CdW013KF.d.ts +4 -0
  510. package/dist/sides-BPSWde0A.d.ts +4 -0
  511. package/dist/skeleton.d.ts +14 -7
  512. package/dist/skeleton.js +2 -1
  513. package/dist/spacer.d.ts +18 -0
  514. package/dist/spacer.js +4 -0
  515. package/dist/spacer.js.map +1 -0
  516. package/dist/split-button.d.ts +57 -0
  517. package/dist/split-button.js +7 -0
  518. package/dist/split-button.js.map +1 -0
  519. package/dist/split-view.d.ts +63 -6
  520. package/dist/split-view.js +150 -10
  521. package/dist/split-view.js.map +1 -1
  522. package/dist/state-banner.d.ts +41 -7
  523. package/dist/state-banner.js +4 -1
  524. package/dist/styles/anchored-surface.css +41 -0
  525. package/dist/styles/app-tab.css +232 -0
  526. package/dist/styles/backdrop-image.css +241 -0
  527. package/dist/styles/badge.css +145 -0
  528. package/dist/styles/catalog/components/catalog-example-stack.css +14 -0
  529. package/dist/styles/catalog/components/catalog-example.css +204 -0
  530. package/dist/styles/catalog/components/catalog-stage.css +61 -0
  531. package/dist/styles/catalog/components/catalog.css +26 -0
  532. package/dist/styles/catalog.css +5 -498
  533. package/dist/styles/chip.css +208 -0
  534. package/dist/styles/choice-chips.css +154 -0
  535. package/dist/styles/collapsible-panel.css +450 -16
  536. package/dist/styles/column-track.css +57 -0
  537. package/dist/styles/combobox.css +113 -0
  538. package/dist/styles/components/actions/floating-toolbar/floating-toolbar.css +119 -0
  539. package/dist/styles/components/actions/icon-button/icon-button.css +22 -0
  540. package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +83 -0
  541. package/dist/styles/components/actions/popup-menu/popup-menu.css +370 -0
  542. package/dist/styles/components/actions/split-button/split-button.css +95 -0
  543. package/dist/styles/components/actions/toolbar/toolbar.css +452 -0
  544. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +1197 -0
  545. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +269 -0
  546. package/dist/styles/components/collections/framed-list/framed-list.css +47 -0
  547. package/dist/styles/components/collections/list/list.css +250 -0
  548. package/dist/styles/components/collections/list-action-row/list-action-row.css +466 -0
  549. package/dist/styles/components/collections/list-header/list-header.css +229 -0
  550. package/dist/styles/components/collections/list-inset-control/list-inset-control.css +30 -0
  551. package/dist/styles/components/collections/list-inset-text/list-inset-text.css +29 -0
  552. package/dist/styles/components/collections/list-item/list-item.css +461 -0
  553. package/dist/styles/components/collections/summary-row/summary-row.css +161 -0
  554. package/dist/styles/components/data-display/value-table/value-table.css +183 -0
  555. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +41 -0
  556. package/dist/styles/components/feedback/badge/badge.css +145 -0
  557. package/dist/styles/components/feedback/chip/chip.css +208 -0
  558. package/dist/styles/components/feedback/corner-status/corner-status.css +60 -0
  559. package/dist/styles/components/feedback/edge-activity-indicator/edge-activity-indicator.css +127 -0
  560. package/dist/styles/components/feedback/empty-state/empty-state.css +47 -0
  561. package/dist/styles/components/feedback/loading-spinner/loading-spinner.css +25 -0
  562. package/dist/styles/components/feedback/skeleton/skeleton.css +92 -0
  563. package/dist/styles/components/feedback/state-banner/state-banner.css +297 -0
  564. package/dist/styles/components/forms/choice-chips/choice-chips.css +154 -0
  565. package/dist/styles/components/forms/combobox/combobox.css +113 -0
  566. package/dist/styles/components/forms/composer/composer.css +100 -0
  567. package/dist/styles/components/forms/file-picker/file-picker.css +81 -0
  568. package/dist/styles/components/forms/segmented-control/segmented-control.css +196 -0
  569. package/dist/styles/components/forms/select/select.css +455 -0
  570. package/dist/styles/components/forms/token-search-field/token-search-field.css +432 -0
  571. package/dist/styles/components/layout/collapsible-panel/collapsible-panel.css +580 -0
  572. package/dist/styles/components/layout/column-track/column-track.css +57 -0
  573. package/dist/styles/components/layout/content-swap/content-swap.css +154 -0
  574. package/dist/styles/components/layout/grid/grid.css +88 -0
  575. package/dist/styles/components/layout/pane/pane.css +502 -0
  576. package/dist/styles/components/layout/resizable-region/resizable-region.css +545 -0
  577. package/dist/styles/components/layout/row/row.css +114 -0
  578. package/dist/styles/components/layout/spacer/spacer.css +11 -0
  579. package/dist/styles/components/layout/split-view/split-view.css +146 -0
  580. package/dist/styles/components/layout/workbench/workbench.css +1086 -0
  581. package/dist/styles/components/media/lucide-icon/lucide-icon.css +15 -0
  582. package/dist/styles/components/navigation/app-tab/app-tab.css +384 -0
  583. package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +23 -0
  584. package/dist/styles/components/navigation/nav-stack/nav-stack.css +543 -0
  585. package/dist/styles/components/navigation/tab-bar/tab-bar.css +197 -0
  586. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +443 -0
  587. package/dist/styles/components/surfaces/backdrop-image/backdrop-image.css +241 -0
  588. package/dist/styles/components/surfaces/content-item/content-item.css +138 -0
  589. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +31 -0
  590. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +589 -0
  591. package/dist/styles/components/typography/text/text.css +220 -0
  592. package/dist/styles/composer.css +100 -0
  593. package/dist/styles/content-item.css +138 -0
  594. package/dist/styles/content-swap.css +154 -0
  595. package/dist/styles/corner-status.css +60 -0
  596. package/dist/styles/document.css +98 -0
  597. package/dist/styles/edge-activity-indicator.css +127 -0
  598. package/dist/styles/file-picker.css +81 -0
  599. package/dist/styles/floating-toolbar.css +119 -0
  600. package/dist/styles/foundation.css +419 -46
  601. package/dist/styles/framed-list.css +47 -0
  602. package/dist/styles/grid.css +88 -0
  603. package/dist/styles/icon-button.css +22 -0
  604. package/dist/styles/icon-toggle-button.css +83 -0
  605. package/dist/styles/layout.css +3 -41
  606. package/dist/styles/list-action-row.css +324 -18
  607. package/dist/styles/list-header.css +128 -59
  608. package/dist/styles/list-inset-control.css +30 -0
  609. package/dist/styles/list-inset-text.css +29 -0
  610. package/dist/styles/list-item.css +371 -33
  611. package/dist/styles/list.css +250 -0
  612. package/dist/styles/loading-spinner.css +4 -0
  613. package/dist/styles/lucide-icon.css +9 -0
  614. package/dist/styles/nav-stack.css +479 -47
  615. package/dist/styles/overlay-sheet.css +211 -0
  616. package/dist/styles/pane.css +502 -0
  617. package/dist/styles/popup-menu.css +370 -0
  618. package/dist/styles/resizable-region.css +438 -4
  619. package/dist/styles/row.css +114 -0
  620. package/dist/styles/segmented-control.css +36 -9
  621. package/dist/styles/select.css +338 -21
  622. package/dist/styles/skeleton.css +64 -3
  623. package/dist/styles/spacer.css +11 -0
  624. package/dist/styles/split-button.css +95 -0
  625. package/dist/styles/split-view.css +114 -3
  626. package/dist/styles/state-banner.css +146 -22
  627. package/dist/styles/styles.css +24 -1
  628. package/dist/styles/summary-row.css +161 -0
  629. package/dist/styles/sunken-panel.css +31 -0
  630. package/dist/styles/surface-scaffold.css +589 -0
  631. package/dist/styles/tab-bar.css +161 -9
  632. package/dist/styles/tab-navigator.css +443 -0
  633. package/dist/styles/text.css +220 -0
  634. package/dist/styles/token-search-field.css +202 -59
  635. package/dist/styles/toolbar-control-group.css +1022 -36
  636. package/dist/styles/toolbar-text.css +236 -7
  637. package/dist/styles/toolbar.css +402 -11
  638. package/dist/styles/value-table.css +115 -7
  639. package/dist/styles/webawesome.css +420 -17
  640. package/dist/styles/workbench.css +999 -7
  641. package/dist/summary-row.d.ts +56 -0
  642. package/dist/summary-row.js +4 -0
  643. package/dist/summary-row.js.map +1 -0
  644. package/dist/sunken-panel.d.ts +38 -0
  645. package/dist/sunken-panel.js +4 -0
  646. package/dist/sunken-panel.js.map +1 -0
  647. package/dist/surface-scaffold-register.d.ts +10 -0
  648. package/dist/surface-scaffold-register.js +254 -0
  649. package/dist/surface-scaffold-register.js.map +1 -0
  650. package/dist/surface-scaffold.d.ts +203 -0
  651. package/dist/surface-scaffold.js +4 -0
  652. package/dist/surface-scaffold.js.map +1 -0
  653. package/dist/tab-bar.d.ts +33 -7
  654. package/dist/tab-bar.js +1 -1
  655. package/dist/tab-navigator.d.ts +154 -0
  656. package/dist/tab-navigator.js +131 -0
  657. package/dist/tab-navigator.js.map +1 -0
  658. package/dist/text.d.ts +98 -0
  659. package/dist/text.js +3 -0
  660. package/dist/text.js.map +1 -0
  661. package/dist/token-search-field.d.ts +3 -43
  662. package/dist/token-search-field.js +2 -1
  663. package/dist/token-search-model-aYR0YAei.d.ts +184 -0
  664. package/dist/token-search-model.d.ts +3 -0
  665. package/dist/token-search-model.js +3 -0
  666. package/dist/token-search-model.js.map +1 -0
  667. package/dist/toolbar-control-group.d.ts +107 -7
  668. package/dist/toolbar-control-group.js +3 -1
  669. package/dist/toolbar-text.d.ts +63 -9
  670. package/dist/toolbar-text.js +2 -1
  671. package/dist/toolbar.d.ts +72 -7
  672. package/dist/toolbar.js +1 -1
  673. package/dist/types-CVgIwSdq.d.ts +189 -0
  674. package/dist/value-table.d.ts +30 -4
  675. package/dist/value-table.js +2 -1
  676. package/dist/webawesome.d.ts +8 -1
  677. package/dist/wire-catalog.d.ts +111 -5
  678. package/dist/wire-catalog.js +302 -14
  679. package/dist/wire-catalog.js.map +1 -1
  680. package/dist/wire-comboboxes.d.ts +26 -0
  681. package/dist/wire-comboboxes.js +3 -0
  682. package/dist/wire-comboboxes.js.map +1 -0
  683. package/dist/wire-composers.d.ts +16 -0
  684. package/dist/wire-composers.js +3 -0
  685. package/dist/wire-composers.js.map +1 -0
  686. package/dist/wire-content-items.d.ts +11 -0
  687. package/dist/wire-content-items.js +139 -0
  688. package/dist/wire-content-items.js.map +1 -0
  689. package/dist/wire-corner-status.d.ts +11 -0
  690. package/dist/wire-corner-status.js +3 -0
  691. package/dist/wire-corner-status.js.map +1 -0
  692. package/dist/wire-file-pickers.d.ts +26 -0
  693. package/dist/wire-file-pickers.js +3 -0
  694. package/dist/wire-file-pickers.js.map +1 -0
  695. package/dist/wire-list-focus-scroll.d.ts +16 -0
  696. package/dist/wire-list-focus-scroll.js +3 -0
  697. package/dist/wire-list-focus-scroll.js.map +1 -0
  698. package/dist/wire-list-reorder.d.ts +41 -0
  699. package/dist/wire-list-reorder.js +3 -0
  700. package/dist/wire-list-reorder.js.map +1 -0
  701. package/dist/wire-nav-stack.d.ts +4 -1
  702. package/dist/wire-nav-stack.js +352 -15
  703. package/dist/wire-nav-stack.js.map +1 -1
  704. package/dist/wire-overlay-sheets.d.ts +20 -0
  705. package/dist/wire-overlay-sheets.js +4 -0
  706. package/dist/wire-overlay-sheets.js.map +1 -0
  707. package/dist/wire-resizable-regions.d.ts +2 -1
  708. package/dist/wire-resizable-regions.js +2 -1
  709. package/dist/wire-scroll-dividers.d.ts +87 -0
  710. package/dist/wire-scroll-dividers.js +3 -0
  711. package/dist/wire-scroll-dividers.js.map +1 -0
  712. package/dist/wire-sidebar.d.ts +24 -4
  713. package/dist/wire-sidebar.js +159 -45
  714. package/dist/wire-sidebar.js.map +1 -1
  715. package/dist/wire-tab-bars.d.ts +6 -2
  716. package/dist/wire-tab-bars.js +1 -1
  717. package/dist/wire-tab-navigator.d.ts +13 -0
  718. package/dist/wire-tab-navigator.js +153 -0
  719. package/dist/wire-tab-navigator.js.map +1 -0
  720. package/dist/wire-token-search-fields.d.ts +28 -10
  721. package/dist/wire-token-search-fields.js +2 -1
  722. package/dist/wire-toolbar-visibility.d.ts +13 -0
  723. package/dist/wire-toolbar-visibility.js +3 -0
  724. package/dist/wire-toolbar-visibility.js.map +1 -0
  725. package/dist/wire-workbench.d.ts +116 -0
  726. package/dist/wire-workbench.js +6 -0
  727. package/dist/wire-workbench.js.map +1 -0
  728. package/dist/workbench.d.ts +253 -10
  729. package/dist/workbench.js +21 -15
  730. package/dist/workbench.js.map +1 -1
  731. package/docs/accessibility.md +675 -33
  732. package/docs/anchored-surface.md +101 -0
  733. package/docs/app-layouts.md +172 -10
  734. package/docs/apple-hig.md +2 -0
  735. package/docs/backdrop-image.md +128 -0
  736. package/docs/catalog.md +565 -63
  737. package/docs/collapsible-panel.md +308 -25
  738. package/docs/component-contract.md +818 -53
  739. package/docs/component-integration.md +75 -0
  740. package/docs/component-selection.md +971 -99
  741. package/docs/composer.md +143 -0
  742. package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -0
  743. package/docs/design/templates/choice-chips/color-palette.svg +1 -0
  744. package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -0
  745. package/docs/design/templates/choice-chips/compact-icons.svg +1 -0
  746. package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
  747. package/docs/design/templates/choice-chips/multiple.svg +1 -0
  748. package/docs/design/templates/choice-chips-dark.svg +1 -0
  749. package/docs/design/templates/choice-chips.svg +1 -0
  750. package/docs/design/templates/composer/chat-dark.svg +1 -0
  751. package/docs/design/templates/composer/chat.svg +1 -0
  752. package/docs/design/templates/composer/prompt-dark.svg +1 -0
  753. package/docs/design/templates/composer/prompt.svg +1 -0
  754. package/docs/design/templates/composer-dark.svg +1 -0
  755. package/docs/design/templates/composer.svg +1 -0
  756. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  757. package/docs/design/templates/empty-state/filtered.svg +1 -0
  758. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  759. package/docs/design/templates/empty-state/with-action.svg +1 -0
  760. package/docs/design/templates/empty-state-dark.svg +1 -0
  761. package/docs/design/templates/empty-state.svg +1 -0
  762. package/docs/design/templates/list/compact-dark.svg +1 -0
  763. package/docs/design/templates/list/compact.svg +1 -0
  764. package/docs/design/templates/list/stack-dark.svg +1 -0
  765. package/docs/design/templates/list/stack.svg +1 -0
  766. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  767. package/docs/design/templates/list-action-row/default.svg +1 -0
  768. package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
  769. package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
  770. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  771. package/docs/design/templates/list-action-row/selected.svg +1 -0
  772. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -0
  773. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -0
  774. package/docs/design/templates/list-action-row-dark.svg +1 -0
  775. package/docs/design/templates/list-action-row.svg +1 -0
  776. package/docs/design/templates/list-dark.svg +1 -0
  777. package/docs/design/templates/list-header/action-dark.svg +1 -0
  778. package/docs/design/templates/list-header/action.svg +1 -0
  779. package/docs/design/templates/list-header/count-dark.svg +1 -0
  780. package/docs/design/templates/list-header/count.svg +1 -0
  781. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  782. package/docs/design/templates/list-header/inline-action.svg +1 -0
  783. package/docs/design/templates/list-header/size-l-dark.svg +1 -0
  784. package/docs/design/templates/list-header/size-l.svg +1 -0
  785. package/docs/design/templates/list-header/size-m-dark.svg +1 -0
  786. package/docs/design/templates/list-header/size-m.svg +1 -0
  787. package/docs/design/templates/list-header/size-xl-dark.svg +1 -0
  788. package/docs/design/templates/list-header/size-xl.svg +1 -0
  789. package/docs/design/templates/list-header/size-xs-dark.svg +1 -0
  790. package/docs/design/templates/list-header/size-xs.svg +1 -0
  791. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  792. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  793. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  794. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  795. package/docs/design/templates/list-header-dark.svg +1 -0
  796. package/docs/design/templates/list-header.svg +1 -0
  797. package/docs/design/templates/list-item/default-dark.svg +1 -0
  798. package/docs/design/templates/list-item/default.svg +1 -0
  799. package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
  800. package/docs/design/templates/list-item/icon-tile.svg +1 -0
  801. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  802. package/docs/design/templates/list-item/multiline.svg +1 -0
  803. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  804. package/docs/design/templates/list-item/selected.svg +1 -0
  805. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  806. package/docs/design/templates/list-item/trailing.svg +1 -0
  807. package/docs/design/templates/list-item-dark.svg +1 -0
  808. package/docs/design/templates/list-item.svg +1 -0
  809. package/docs/design/templates/list.svg +1 -0
  810. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  811. package/docs/design/templates/segmented-control/equal.svg +1 -0
  812. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  813. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  814. package/docs/design/templates/segmented-control-dark.svg +1 -0
  815. package/docs/design/templates/segmented-control.svg +1 -0
  816. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  817. package/docs/design/templates/skeleton/avatar.svg +1 -0
  818. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  819. package/docs/design/templates/skeleton/block.svg +1 -0
  820. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  821. package/docs/design/templates/skeleton/lines.svg +1 -0
  822. package/docs/design/templates/skeleton-dark.svg +1 -0
  823. package/docs/design/templates/skeleton.svg +1 -0
  824. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  825. package/docs/design/templates/state-banner/danger.svg +1 -0
  826. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  827. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  828. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  829. package/docs/design/templates/state-banner/info.svg +1 -0
  830. package/docs/design/templates/state-banner/strip-dark.svg +1 -0
  831. package/docs/design/templates/state-banner/strip.svg +1 -0
  832. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  833. package/docs/design/templates/state-banner/success.svg +1 -0
  834. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  835. package/docs/design/templates/state-banner/warning.svg +1 -0
  836. package/docs/design/templates/state-banner-dark.svg +1 -0
  837. package/docs/design/templates/state-banner.svg +1 -0
  838. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  839. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  840. package/docs/design/templates/tab-bar-dark.svg +1 -0
  841. package/docs/design/templates/tab-bar.svg +1 -0
  842. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  843. package/docs/design/templates/token-search-field/empty.svg +1 -0
  844. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  845. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  846. package/docs/design/templates/token-search-field-dark.svg +1 -0
  847. package/docs/design/templates/token-search-field.svg +1 -0
  848. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  849. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  850. package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
  851. package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
  852. package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
  853. package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
  854. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -1
  855. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -1
  856. package/docs/design/templates/toolbar-control-group/glass-dark.svg +1 -0
  857. package/docs/design/templates/toolbar-control-group/glass.svg +1 -0
  858. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -1
  859. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -1
  860. package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
  861. package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
  862. package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
  863. package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
  864. package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
  865. package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
  866. package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
  867. package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
  868. package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
  869. package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
  870. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -1
  871. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -1
  872. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  873. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  874. package/docs/design/templates/toolbar-control-group-dark.svg +1 -11
  875. package/docs/design/templates/toolbar-control-group.svg +1 -11
  876. package/docs/design/templates/toolbar-dark.svg +1 -0
  877. package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
  878. package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
  879. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  880. package/docs/design/templates/toolbar-text/default.svg +1 -0
  881. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  882. package/docs/design/templates/toolbar-text/large.svg +1 -0
  883. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  884. package/docs/design/templates/toolbar-text/small.svg +1 -0
  885. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  886. package/docs/design/templates/toolbar-text.svg +1 -0
  887. package/docs/design/templates/toolbar.svg +1 -0
  888. package/docs/design/templates/value-table/details-dark.svg +1 -0
  889. package/docs/design/templates/value-table/details.svg +1 -0
  890. package/docs/design/templates/value-table-dark.svg +1 -0
  891. package/docs/design/templates/value-table.svg +1 -0
  892. package/docs/design/templates.md +83 -18
  893. package/docs/design-philosophy.md +65 -20
  894. package/docs/device-class.md +10 -9
  895. package/docs/document-baseline.md +93 -0
  896. package/docs/examples/application-ui-profile.json +60 -0
  897. package/docs/examples/command-palette-adapter.tsx +69 -17
  898. package/docs/examples/component-catalog-extension.json +52 -0
  899. package/docs/examples/component-composition-extension.json +80 -0
  900. package/docs/layout.md +926 -53
  901. package/docs/manual-test-plan.md +29 -0
  902. package/docs/nav-stack.md +323 -14
  903. package/docs/recipes.md +153 -73
  904. package/docs/split-view.md +96 -7
  905. package/docs/sunken-panel.md +106 -0
  906. package/docs/surface-scaffold.md +416 -0
  907. package/docs/tab-navigator.md +291 -0
  908. package/docs/type-contracts.md +137 -0
  909. package/docs/ui-analyzer.md +406 -0
  910. package/docs/ui-doctor.md +281 -0
  911. package/docs/ui-evaluator.md +139 -0
  912. package/docs/ux-demo.md +58 -17
  913. package/docs/webawesome-theme.md +215 -16
  914. package/docs/workbench.md +627 -12
  915. package/docs/writing.md +152 -0
  916. package/doctor/cli.mjs +120 -0
  917. package/doctor/component-style-checks.mjs +457 -0
  918. package/doctor/config.schema.json +94 -0
  919. package/doctor/copy-capitalization-checks.mjs +591 -0
  920. package/doctor/eslint-diagnostics.d.mts +24 -0
  921. package/doctor/eslint-diagnostics.mjs +24 -0
  922. package/doctor/index.d.mts +122 -0
  923. package/doctor/index.mjs +1424 -0
  924. package/doctor/report.schema.json +118 -0
  925. package/evaluator/cli.mjs +89 -0
  926. package/evaluator/index.d.mts +90 -0
  927. package/evaluator/index.mjs +1203 -0
  928. package/evaluator/report.schema.json +152 -0
  929. package/llms.txt +808 -50
  930. package/package.json +357 -27
  931. package/scripts/component-catalog-extension-validation.mjs +28 -0
  932. package/traversal-exclusions.mjs +86 -0
  933. package/ux-demo/recipes/app-shell.tsx +204 -16
  934. package/ux-demo/recipes/collapsible-sidebar.tsx +206 -45
  935. package/ux-demo/recipes/compact-toolbar.tsx +135 -14
  936. package/ux-demo/recipes/composer-form.tsx +133 -21
  937. package/ux-demo/recipes/list-detail-dialog.tsx +255 -14
  938. package/ux-demo/recipes/list-workspace-states.tsx +183 -11
  939. package/ux-demo/recipes/loaders.ts +11 -3
  940. package/ux-demo/recipes/loading-inspector.tsx +162 -39
  941. package/ux-demo/recipes/media-detail.tsx +272 -0
  942. package/ux-demo/recipes/mount-recipe.ts +26 -10
  943. package/ux-demo/recipes/navigation-sidebar.tsx +137 -11
  944. package/ux-demo/recipes/navigation-stack.tsx +79 -24
  945. package/ux-demo/recipes/types.ts +17 -2
  946. package/ux-demo/recipes/workspace-header.tsx +86 -5
  947. package/vite-ux-review.d.mts +83 -0
  948. package/vite-ux-review.mjs +120 -0
  949. package/dist/browser/panel-header.js +0 -7
  950. package/dist/chunk-2Z5TWHKQ.js +0 -34
  951. package/dist/chunk-2Z5TWHKQ.js.map +0 -1
  952. package/dist/chunk-37T3VNIZ.js +0 -19
  953. package/dist/chunk-37T3VNIZ.js.map +0 -1
  954. package/dist/chunk-55DATV3A.js +0 -10
  955. package/dist/chunk-55DATV3A.js.map +0 -1
  956. package/dist/chunk-56RJXPHG.js.map +0 -1
  957. package/dist/chunk-7BR3DO2A.js +0 -31
  958. package/dist/chunk-7BR3DO2A.js.map +0 -1
  959. package/dist/chunk-7JB7VPRI.js +0 -34
  960. package/dist/chunk-7JB7VPRI.js.map +0 -1
  961. package/dist/chunk-7LDCTU7D.js +0 -134
  962. package/dist/chunk-7LDCTU7D.js.map +0 -1
  963. package/dist/chunk-AQNKJRFH.js +0 -79
  964. package/dist/chunk-AQNKJRFH.js.map +0 -1
  965. package/dist/chunk-AVZHJN6C.js +0 -14
  966. package/dist/chunk-AVZHJN6C.js.map +0 -1
  967. package/dist/chunk-B24C4A6T.js +0 -22
  968. package/dist/chunk-B24C4A6T.js.map +0 -1
  969. package/dist/chunk-BLK3UEEI.js +0 -23
  970. package/dist/chunk-BLK3UEEI.js.map +0 -1
  971. package/dist/chunk-CVZYNJJ5.js +0 -265
  972. package/dist/chunk-CVZYNJJ5.js.map +0 -1
  973. package/dist/chunk-DAFFDO33.js +0 -14
  974. package/dist/chunk-DAFFDO33.js.map +0 -1
  975. package/dist/chunk-I7INRJO4.js +0 -17
  976. package/dist/chunk-I7INRJO4.js.map +0 -1
  977. package/dist/chunk-L4OKFDJY.js +0 -24
  978. package/dist/chunk-L4OKFDJY.js.map +0 -1
  979. package/dist/chunk-LC3YSAZC.js +0 -39
  980. package/dist/chunk-LC3YSAZC.js.map +0 -1
  981. package/dist/chunk-M5JRI6MN.js +0 -27
  982. package/dist/chunk-M5JRI6MN.js.map +0 -1
  983. package/dist/chunk-MFKMHK5W.js +0 -10
  984. package/dist/chunk-MFKMHK5W.js.map +0 -1
  985. package/dist/chunk-RUNWEPR4.js +0 -10
  986. package/dist/chunk-RUNWEPR4.js.map +0 -1
  987. package/dist/chunk-W2FK7ZNY.js +0 -26
  988. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  989. package/dist/chunk-W5EQ3HYQ.js +0 -42
  990. package/dist/chunk-W5EQ3HYQ.js.map +0 -1
  991. package/dist/chunk-WVPYVDXY.js +0 -15
  992. package/dist/chunk-WVPYVDXY.js.map +0 -1
  993. package/dist/chunk-XXMOARTH.js +0 -229
  994. package/dist/chunk-XXMOARTH.js.map +0 -1
  995. package/dist/chunk-Y5MRDTLC.js +0 -20
  996. package/dist/chunk-Y5MRDTLC.js.map +0 -1
  997. package/dist/chunk-YGN7OMLT.js.map +0 -1
  998. package/dist/panel-header.d.ts +0 -36
  999. package/dist/panel-header.js +0 -7
  1000. package/dist/panel-header.js.map +0 -1
  1001. package/dist/styles/panel-header.css +0 -64
  1002. package/dist/styles/tab-scaffold.css +0 -84
  1003. package/dist/tab-scaffold.d.ts +0 -30
  1004. package/dist/tab-scaffold.js +0 -16
  1005. package/dist/tab-scaffold.js.map +0 -1
  1006. package/dist/wire-tab-scaffold.d.ts +0 -11
  1007. package/dist/wire-tab-scaffold.js +0 -16
  1008. package/dist/wire-tab-scaffold.js.map +0 -1
  1009. package/docs/design/templates/panel-header/icon-actions-dark.svg +0 -1
  1010. package/docs/design/templates/panel-header/icon-actions.svg +0 -1
  1011. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +0 -1
  1012. package/docs/design/templates/panel-header/icon-summary-actions.svg +0 -1
  1013. package/docs/design/templates/panel-header/no-icon-dark.svg +0 -1
  1014. package/docs/design/templates/panel-header/no-icon.svg +0 -1
  1015. package/docs/design/templates/panel-header/page-heading-dark.svg +0 -1
  1016. package/docs/design/templates/panel-header/page-heading.svg +0 -1
  1017. package/docs/design/templates/panel-header/title-only-dark.svg +0 -1
  1018. package/docs/design/templates/panel-header/title-only.svg +0 -1
  1019. package/docs/design/templates/panel-header-dark.svg +0 -13
  1020. package/docs/design/templates/panel-header.svg +0 -13
  1021. package/docs/tab-scaffold.md +0 -41
  1022. package/ux-demo/recipes/recipes.css +0 -448
package/docs/catalog.md CHANGED
@@ -6,127 +6,490 @@ footer that the kerf UI catalog itself uses. Point it at your own components and
6
6
  you get the same shell without rebuilding it. Like the app layouts, it is a
7
7
  subpath-only, tree-shakeable module that adds nothing to the main barrel.
8
8
 
9
+ The shell is a [`Workbench`](workbench.md) built entirely from `@kerfjs/ui`
10
+ components: the sidebar is its left rail and the active entry its work area. So
11
+ the sidebar behaves like any Workbench rail — its standard toggle moves into the
12
+ entry toolbar while it is collapsed, and on a small screen (a Workbench narrower
13
+ than 704px) it overlays the stage, one tap from the entry toolbar, filling the
14
+ width less a 44px strip that closes it, instead of squeezing the stage. Pass the
15
+ app's `collapsed` signal to `wireCatalog` so that overlay closes on Escape, on a
16
+ press outside, and when an entry is chosen from it.
17
+
9
18
  ```bash
10
- npm install @kerfjs/ui # kerfjs is a peer; @kerfjs/ui/select/register is needed only if entries use `related`
19
+ npm install @kerfjs/ui # kerfjs is a peer; @kerfjs/ui/select/register is needed only if entries use `related`
11
20
  ```
12
21
 
13
22
  - `Catalog(props)` returns the shell as `SafeHtml` (a `<main class="kui-catalog">`).
14
- It is **controlled and stateless**: your app owns the `active`, `collapsed`, and
15
- `theme` signals and computes the preview `content` from `active` in its own
23
+ It is **controlled and stateless**: your app owns the `active`, `collapsed`,
24
+ `theme`, and optional display-preference signals and computes the preview `content` from `active` in its own
16
25
  `mount()` render.
17
26
  - `wireCatalog(root, options)` wires the interactions (sidebar selection, the
18
- related-entry popup menu, and the collapse/theme toggles) with one delegated
19
- listener set and returns a disposer; it can also mirror the active id into the
20
- URL.
27
+ related-entry popup menu, the built-in sidebar filter, and the collapse/display
28
+ toggles and background chooser) with one delegated listener set and returns a disposer; it can also
29
+ mirror the active id into the URL and reveal the active sidebar row after a
30
+ controlled render.
21
31
 
22
32
  ## What you supply
23
33
 
24
34
  - **`sections`** — category-grouped entries: `{ category, entries: [{ id, name,
25
- description?, resources?, related? }] }`. Each entry becomes a sidebar `ListItem`
26
- under a `ListHeader` for its category.
35
+ description?, tags?, resources?, related? }] }`. Each entry becomes a sidebar
36
+ `ListItem` under a `ListHeader` for its category. Short `tags` render through
37
+ the row's quiet status treatment for decision metadata such as `Discouraged`.
27
38
  - **`content`** — the rendered preview for the active entry. Keep a map of `id →
28
- () => SafeHtml` in your app and call `renderers[active]()` in your render.
29
- - **`brand`** — `{ title, subtitle?, logoUrl? }` for the sidebar header.
39
+ () => SafeHtml` in your app and call `renderers[active]()` in your render.
40
+ - **`backgroundStyle`** — the preview stage backdrop: `checkerboard` (default,
41
+ 8px squares),
42
+ `vertical-stripes` (alternating 8px bands), `layout-guide` (single-pixel
43
+ vertical rules at 15px, 23px, and 32px from the stage edge), `surface`, or `sunken`. The
44
+ patterned choices share the main Pane's sunken surface and reveal transparent
45
+ specimen edges; `surface` paints an
46
+ opaque backdrop. `sunken` leaves the stage
47
+ transparent so the main Pane's semitransparent sunken surface paints only once.
48
+ A controlled app may pass its current choice on each render.
49
+ - **Display controls** — `increasedContrast` and `reducedMotion` each show a
50
+ pressed-state toggle when their boolean value is supplied. `backgroundControl`
51
+ shows a `PopupMenu` for the five preview backdrops, marking the current
52
+ `backgroundStyle` as checked. These controls share the entry toolbar's compact,
53
+ wrapping display group with the optional theme toggle. Pass callbacks through
54
+ `wireCatalog`'s `onToggleContrast`, `onToggleMotion`, and `onSelectBackground`;
55
+ update your own signals, apply contrast/motion preferences to your app, and
56
+ persist them there if needed. `Catalog` does not change the document theme,
57
+ classes, or storage. Register `@kerfjs/ui/popup-menu/register` when showing the
58
+ background chooser.
59
+ - **`brand`** — `{ title, subtitle?, logoUrl? }` for the sidebar header. The
60
+ optional logo paints through `ToolbarControlGroup.avatarImage`.
30
61
  - **`secondarySections`** — an optional secondary "ecosystem" group shown below the
31
62
  primary sections with a quieter treatment: `{ label, sections, collapsible?,
32
- expanded? }`. When `collapsible`, the label is a disclosure toggle controlling
63
+ expanded? }`. When `collapsible`, the label is a disclosure toggle controlling
33
64
  `expanded` (the app owns it; wire it with `wireCatalog`'s `onToggleSecondary`).
34
65
  - Optional slots: `headerActions` (extra header controls), `sidebarFooter` (extra
35
66
  sidebar content), and `status` (a footer status line).
67
+ - **`settings`** — the active entry's settings (variant and state controls for
68
+ its preview). When supplied, the Catalog renders a **Settings** pane beside the
69
+ stage (its Workbench right rail) with the standard collapse toggle: in the
70
+ pane's header while it is open, at the end of the entry toolbar while it is
71
+ collapsed. Omit it (or pass `null`) for an entry with no settings; neither the
72
+ pane nor its toggle renders. Supply only the controls — compose them from
73
+ `ListInsetControl` + `Select` (or other form components) so they share the
74
+ pane's text column; the Catalog owns the pane, its title, and its toggle.
75
+
76
+ The sidebar includes a `TokenSearchField` in its fixed header for every Catalog
77
+ consumer, so the filter remains visible while the entries scroll. `wireCatalog`
78
+ filters entry names and section headings as text is typed,
79
+ ignoring case. A heading match shows all its entries; a matching secondary
80
+ group heading searches its sections too, even while that group is collapsed.
81
+ Empty sections disappear and an empty-result message appears when nothing
82
+ matches. The query survives controlled Catalog rerenders, with the field's
83
+ placeholder hidden while text remains, and clears through the field's clear
84
+ action. Filtering does not change the selected
85
+ entry or its preview.
36
86
 
37
87
  Per-entry `resources` render as "open in new tab" links in the footer, and
38
- `related` renders a "Related entries" popup menu — a `single` `ToolbarControlGroup`
39
- around a `wa-dropdown` (grouped by each entry's `group`), so register its elements
40
- with `@kerfjs/ui/select/register` when you use it.
88
+ `related` renders a "Related Entries" `PopupMenu` in a `single`
89
+ `ToolbarControlGroup` (grouped by each entry's `group`), so register its elements
90
+ with `@kerfjs/ui/popup-menu/register` when you use it.
91
+
92
+ ## Catalog demo authoring contract
93
+
94
+ This section is the single authoritative contract for tools and people that
95
+ author Catalog previews. The machine-readable discovery entry is
96
+ [`catalog-authoring.json`](../ai/catalog-authoring.json); exact props remain in
97
+ [`public-api-signatures-v1.md`](../ai/public-api-signatures-v1.md#kerfjsuicatalog).
98
+ The component catalog deliberately does not duplicate these rules: it describes
99
+ which component to choose, while this contract describes how to present the
100
+ chosen component.
101
+
102
+ ### Choose the demo mode
41
103
 
42
- ## Preview examples
104
+ Classify every entry before rendering it:
43
105
 
44
- Compose each entry's `content` from `CatalogExample` (and `CatalogExampleStack`)
45
- instead of hand-rolled example markup, so labels, notes, and left-edge alignment
46
- stay consistent:
106
+ | Entry kind | Preview purpose |
107
+ | --------------- | ------------------------------------------------------------------------------------------------------- |
108
+ | **Component** | Show one public component, its meaningful variants, and adverse states. |
109
+ | **Composition** | Show components commonly used together in one focused container or surface. |
110
+ | **Recipe** | Teach the recommended production approach to a specific task, including ownership and application glue. |
111
+
112
+ These three kinds are exhaustive. Theme/foundation showcases use a functional
113
+ category, third-party specimens use source metadata, and state galleries retain
114
+ the kind of the thing they demonstrate; none needs another demo kind.
115
+
116
+ Organize the catalog by functional group, with groups in descending product
117
+ importance. Within every group, list all component demos before all composition
118
+ demos. Order each kind by descending importance where a meaningful distinction
119
+ exists, then alphabetically by display name to break ties. Put recipes after all
120
+ component/composition groups, ordered by the same importance-then-alphabetical
121
+ rule. Treat source order as the authored importance order when no explicit rank
122
+ field exists. Show a `Composition` tag rather than repeating the word in a
123
+ composition's display name; the generic `Catalog` accepts that through the
124
+ entry's `tags` array.
125
+
126
+ ### Required structure
127
+
128
+ - `Catalog` is the one shell. The app owns active-entry state and passes one
129
+ active preview through `content`.
130
+ - `CatalogExampleStack` is the group for one preview's rows. Put route/test
131
+ metadata such as `data-demo` on its rendered root through `rootAttributes`.
132
+ Pass `label` when the stack needs an accessible name: the rendered `section`
133
+ is then exposed as a named region. An unlabeled stack remains an ordinary
134
+ grouping rather than adding an unnecessary landmark.
135
+ A stack holds a 736px reading measure by default; pass `width="full"` for
136
+ application-width compositions (boards, app shells, drawers, split views) so
137
+ the stack spans the stage like a `viewport.width: "full"` row instead of
138
+ clipping them.
139
+ - `CatalogExample` is one row: optional generated `ListHeader` label, optional
140
+ generated note, then one specimen or one intentionally coupled specimen
141
+ cluster. Use one row per variant/state; do not hand-author the helper's private
142
+ classes. A supplied `label` also names the row's `section`, so each specimen
143
+ is a named region that assistive technology and
144
+ `getByRole("region", { name })` can address.
145
+ - Example and stack labels are headings, so they use title style ("Heading
146
+ Identity Stays Whole", "Icon Trigger in a Toolbar Group"); the `note` that
147
+ explains a specimen stays sentence style. Write a label as a name, not a
148
+ sentence. See [Writing interface copy](./writing.md#capitalization);
149
+ `kerf-ui-doctor` reports a sentence-case label as `KUI-D040`.
150
+ - Focused demos do not import local stylesheets, use inline `style`, or invent
151
+ styling-only `demo-*` classes. Prefer a public Kerf component, then a Web
152
+ Awesome surface when Kerf has no equivalent, then ordinary semantic HTML.
153
+ Use `CatalogExample.viewport` for bounded specimen width, height, frame,
154
+ surface, overflow, responsive visibility, and public custom-property values;
155
+ keep those constraints catalog-owned instead of recreating a demo stylesheet.
156
+ Widths run `sidebar` (272px, a production rail, for sidebar-pane content),
157
+ `compact` (440px), `medium` (640px), and `wide` (864px), each capped at the
158
+ stage, plus `full`; `text` and `control` size a single label or control.
159
+ Component heights run `short` (220px) through `tall` (360px); frame an app
160
+ shell, whole-screen layout, or other application-sized recipe with
161
+ `height: "app"` (592px), and give its root `fill` rather than a frame `Pane`.
162
+ An app frame stands in for the screen: it is the containing block for
163
+ screen-fixed chrome, so a compact `CollapsiblePanel` overlay, its backdrop,
164
+ and restore controls dock to the frame's edges rather than the page's.
165
+ `minHeight` (`short`, `medium`, or `app` at 592px) is a floor the frame
166
+ may grow past rather than a definite height.
167
+ - A top-layer specimen (a `popover`, a modal) that production anchors to a
168
+ named region with CSS anchor positioning anchors to the frame instead when
169
+ the frame takes that name: `viewport.anchorName` is a CSS dashed-ident
170
+ (`"--app-shell-main"`, validated; anything else throws) that becomes the
171
+ frame's `anchor-name`, so the specimen's own `position-anchor` rule resolves
172
+ to the frame. Do not wrap the specimen in a stage element to name it. Anchor
173
+ names are document-wide, so give each frame on a page its own. The frame
174
+ only names the anchor: the specimen keeps owning its placement, and as a
175
+ top-layer element it is not clipped by the frame or the stage. Chromium,
176
+ Firefox, and WebKit with CSS anchor positioning place it against the frame;
177
+ an engine without anchor positioning ignores the name, and the specimen
178
+ falls back to whatever placement its own CSS gives it there.
179
+ - For a centered reading column inside a wider frame, set
180
+ `viewport.contentWidth` (`compact` 440px, `medium` 640px, or `wide` 864px,
181
+ each capped at the frame) and `contentAlign: "center"` (the default is
182
+ `start`). Each in-flow child fills that column; `[popover]` children keep
183
+ their own geometry. The column applies to block, `grid`, and `flex-column`
184
+ frames, and `contentAlign` does nothing without `contentWidth`.
47
185
 
48
186
  ```tsx
49
- import { CatalogExample, CatalogExampleStack } from '@kerfjs/ui/catalog';
187
+ <CatalogExample
188
+ label="Request Docked to the Main Column"
189
+ viewport={{
190
+ layout: "flex-column",
191
+ width: "full",
192
+ minHeight: "app",
193
+ anchorName: "--app-shell-main",
194
+ contentWidth: "medium",
195
+ contentAlign: "center",
196
+ }}
197
+ >
198
+ <Transcript />
199
+ <PermissionRequestPopup /> {/* its CSS: position-anchor: --app-shell-main */}
200
+ </CatalogExample>
201
+ ```
202
+
203
+ - The specimen is an immediate child of `CatalogExample`. A focused component
204
+ row should place the component root there, without a decorative card or
205
+ spacing wrapper. A composition row may place the composition root there.
206
+
207
+ Use `align="glyph"` for a bare glyph/text specimen, `align="inline-control"`
208
+ for a control whose own inline padding contributes about 8px, and
209
+ `align="text-trigger"` for a Web Awesome dropdown's text trigger whose visible
210
+ label needs an 8px inset (such as a plain `PopupMenu` trigger). The dropdown host
211
+ has no layout box, so this inset applies to its button child. Use
212
+ `align="none"` (the default) for a content item or composition that owns its
213
+ geometry.
214
+
215
+ ```tsx
216
+ import { CatalogExample, CatalogExampleStack } from "@kerfjs/ui/catalog";
50
217
 
51
218
  const buttonPreview = (
52
- <CatalogExampleStack label="Button variants">
219
+ <CatalogExampleStack
220
+ label="Button Variants"
221
+ rootAttributes={{ "data-demo": "button" }}
222
+ >
53
223
  <CatalogExample label="Icon" note="A bare glyph." align="glyph">
54
224
  <LucideIcon icon={Plus} name="plus" />
55
225
  </CatalogExample>
56
226
  <CatalogExample label="Control" align="inline-control">
57
227
  <SegmentedControl id="view" label="View" value="list" choices={choices} />
58
228
  </CatalogExample>
59
- <CatalogExample label="In composition">
60
- <ValueTable label="Metadata">{rows}</ValueTable>
229
+ <CatalogExample label="Authoring Note" note="Explain the specimen below.">
230
+ <p>Use the public helper contract.</p>
61
231
  </CatalogExample>
62
232
  </CatalogExampleStack>
63
233
  );
64
234
  ```
65
235
 
66
- `label` is optional — omit it for a bare specimen with no `ListHeader`. `align`
67
- lines a specimen's visible left edge up with its label text: `'glyph'`
68
- (16px) for a bare glyph/text specimen, `'inline-control'` (8px) for a control that
69
- already carries ~8px of its own inline padding, and `'none'` (the default) for a
70
- content-item/composition that already owns its geometry. The inset is published as
71
- the `--kui-catalog-example-align` custom property so a debug overlay can exclude it
72
- from a specimen's measured margin.
236
+ ### Metadata ownership
237
+
238
+ Use `rootAttributes` on either helper for authoring metadata such as `data-demo`;
239
+ the metadata lands on that helper's
240
+ rendered root. The slot accepts only `data-*` strings. Structural
241
+ `data-catalog-example`, `data-catalog-example-stack`, and `data-align` semantics
242
+ remain helper-owned and are rejected case-insensitively at runtime, including
243
+ from structurally widened or JavaScript objects. Do not copy the helpers'
244
+ private `kui-catalog-*` classes into preview markup.
245
+
246
+ The app owns entry ids, `kind`, routing, sources, relationships, and test hooks.
247
+ `Catalog.stageRootAttributes` places app-owned `data-*` state on the
248
+ catalog-owned preview stage without an extra wrapper; `data-catalog-stage`
249
+ remains protected.
250
+ The stage is the main Pane's direct scrolling content and fills its available
251
+ scroller height for short specimens, so every backdrop reaches the pane's bottom.
252
+ It grows with tall specimens and scrolls without clipping. The canvas owns the
253
+ 16px inset; the main Pane keeps its sunken appearance without a deep inset. The
254
+ Catalog's shipped CSS supplies this behavior in this package's UX demo and in
255
+ other packages' demos. Consumers should import `@kerfjs/ui/catalog` with its
256
+ browser styles (or the companion CSS subpath for manual CSS pipelines) rather
257
+ than styling Pane or stage internals.
258
+ The helpers own their structural markers, label/note anatomy, alignment marker,
259
+ and private classes. Component metadata such as margin/border/padding ownership
260
+ lives in `component-catalog.json`.
261
+
262
+ ### Component metadata
263
+
264
+ Machine-readable geometry ownership metadata identifies whether the component,
265
+ its parent, or its children are responsible for margin, border, and padding.
266
+ Keep that metadata in `component-catalog.json` and use the rendered specimen to
267
+ review the actual appearance.
268
+
269
+ Catalogs for downstream components should conform to the
270
+ [`component-catalog-extension.schema.json`](../ai/component-catalog-extension.schema.json)
271
+ contract and can start from the checked
272
+ [`component-catalog-extension.json`](./examples/component-catalog-extension.json)
273
+ example; provide those entries beside Kerf's shipped catalog to AI tools.
274
+ Packages that keep a `kerf.components.json` can generate this file instead of
275
+ hand-maintaining it: set `kerfComponentCatalog.selectionOutput` and run
276
+ `kerf-component-catalog` (see `create-kerf-component`'s README).
277
+ An extension entry may declare `uses` with direct Kerf or extension entry ids,
278
+ plus repository-relative `source` and `demoSource` paths. Keep the ids unique
279
+ and resolvable across both catalogs; paths use `/` separators and cannot
280
+ traverse outside the repository. These fields let consumer demos derive source
281
+ links and composition relationships from the catalog.
282
+
283
+ For a consumer UX demo, `@kerfjs/ui/catalog-projection` exports
284
+ `projectConsumerCatalog(extension, kerfCatalog, options)` and
285
+ `projectCatalogEntries(entries, options)`. The projection maps `purpose` to
286
+ `description`, `uses` to related-entry ids, `source` to `componentSource`, and
287
+ `demoSource` to the demo source link. It defaults the source identity to
288
+ `consumer` and category to `Application`. Explicit paths in an extension entry
289
+ take precedence over templates. Template placeholders are `{id}`, `{name}`,
290
+ `{kind}`, and `{package}`. Design templates are omitted unless configured.
291
+
292
+ The package also ships `kerf-catalog-demo` for a committed TypeScript module:
293
+
294
+ ```sh
295
+ kerf-catalog-demo --extension ai/component-catalog-extension.json \
296
+ --out ux-demo/catalog.generated.ts \
297
+ --repo-base https://github.com/acme/app/blob/main/ \
298
+ --source-template 'src/{id}.tsx' \
299
+ --demo-template 'ux-demo/demos/{id}.tsx' --write
300
+ kerf-catalog-demo --extension ai/component-catalog-extension.json \
301
+ --out ux-demo/catalog.generated.ts \
302
+ --repo-base https://github.com/acme/app/blob/main/ \
303
+ --source-template 'src/{id}.tsx' \
304
+ --demo-template 'ux-demo/demos/{id}.tsx' --check
305
+ ```
306
+
307
+ The command uses the Kerf catalog shipped with the package to resolve `uses`;
308
+ `--kerf-catalog` selects another catalog file. `--category`,
309
+ `--documentation-template`, and `--design-template` configure optional row
310
+ fields. `--check` fails if the generated file is missing or stale. The output
311
+ exports `generatedConsumerCatalog` and `catalogRepositoryBlobUrl`; the latter
312
+ is normalized to a trailing slash for source and documentation links.
313
+
314
+ ### Automated conformance and reviewed exceptions
315
+
316
+ Run `npm run check:demo-conformance` after changing a first-party demo, its
317
+ catalog kind, or the shell's overlay logic. The TypeScript-AST gate verifies
318
+ facts that source can prove without guessing at rendered intent:
319
+
320
+ - focused component routes import and use `CatalogExampleStack` and
321
+ `CatalogExample` from the public package;
322
+ - focused route metadata uses the helpers' `rootAttributes` slot and example rows
323
+ are not empty;
324
+ - every `@kerfjs/ui` import is a published package export and relative imports
325
+ do not reach into `ui/src`;
326
+ - focused demos have no relative stylesheet imports, inline style attributes,
327
+ or styling-only `demo-*`, `wa-demo-*`, and token-search class names;
328
+ - demo JSX does not copy private `kui-catalog-*` structural classes;
329
+ - recipe sources (checked by `npm run check:recipes` with the same shared
330
+ analyzer) import no stylesheet other than public `@kerfjs/ui` CSS, set no
331
+ inline style, and name only published layout and Web Awesome classes; each
332
+ recipe declares its catalog frame through an exported `presentation`; and
333
+ - the shell derives the documented demo mode from the active entry's kind.
334
+
335
+ The gate deliberately does not infer component ownership from arbitrary class
336
+ names, margins, borders, or nested descendants. Runtime appearance remains the
337
+ browser suite's job.
338
+
339
+ A focused route may bypass the two public layout helpers only when the route's
340
+ stage geometry is itself the reviewed specimen. Add the narrow waiver to
341
+ [`catalog-conformance-exceptions.json`](../ux-demo/catalog-conformance-exceptions.json)
342
+ with the exact route, source file, stable diagnostic ids, a substantive reason,
343
+ and the reviewing `KF-*` ticket. Only helper/metadata rules are waivable;
344
+ private imports, local styling, private markup, empty examples, and shell-mode
345
+ drift always fail. The gate rejects duplicate, malformed, unused,
346
+ and stale exceptions, so delete a waiver when its route adopts the standard
347
+ helpers.
348
+
349
+ ## Selection reveal
350
+
351
+ Set `revealSelection: true` on `wireCatalog` for a long desktop sidebar. After
352
+ `onSelect` updates controlled state, the helper waits one animation frame, finds
353
+ the exact matching `data-item-id`, and scrolls it into view without changing
354
+ focus. A newer selection or disposal cancels the pending reveal. The default
355
+ media guard follows the Workbench's inline sidebar (`min-width: 44.01rem`), so a
356
+ closed phone overlay is never scrolled behind the user's back.
357
+
358
+ Pass an options object instead of `true` to customize `block`, `inline`,
359
+ `behavior`, or `media`; `media: false` deliberately enables the behavior at all
360
+ sizes. For an initial deep link that did not come through `wireCatalog`, call
361
+ `revealCatalogEntry(app, initialId, { block: "center" })` after the first mount.
73
362
 
74
363
  ## Complete example
75
364
 
76
365
  ```tsx
77
- import { mount, signal } from 'kerfjs';
78
- import { Catalog, type CatalogSection } from '@kerfjs/ui/catalog';
79
- import { wireCatalog } from '@kerfjs/ui/wire-catalog';
80
- import '@kerfjs/ui/styles.css'; // or import each primitive's CSS + @kerfjs/ui/catalog.css
366
+ import { mount, signal, type SafeHtml } from "kerfjs";
367
+ import {
368
+ Catalog,
369
+ CatalogExample,
370
+ CatalogExampleStack,
371
+ type CatalogBackgroundStyle,
372
+ type CatalogSection,
373
+ } from "@kerfjs/ui/catalog";
374
+ import {
375
+ revealCatalogEntry,
376
+ wireCatalog,
377
+ } from "@kerfjs/ui/wire-catalog";
378
+ import "@kerfjs/ui/popup-menu/register"; // for the background chooser
379
+ // A CSS-aware (browser-condition) bundler loads the Catalog's CSS with its import.
81
380
 
82
- // 1. Describe your components once.
83
- const sections: CatalogSection[] = [
381
+ type DemoKind = "component" | "composition";
382
+ type DemoEntry = CatalogSection["entries"][number] & { kind: DemoKind };
383
+
384
+ // 1. Describe selection and overlay mode once.
385
+ const entries: DemoEntry[] = [
84
386
  {
85
- category: 'Controls',
86
- entries: [
87
- { id: 'button', name: 'Button', description: 'A pressable control.',
88
- resources: [{ label: 'Source', href: '/src/button.tsx', detail: 'src/button.tsx' }] },
89
- { id: 'field', name: 'Field', description: 'A labeled input.',
90
- related: [{ id: 'button', name: 'Button', group: 'Used with' }] },
387
+ id: "button",
388
+ name: "Button",
389
+ kind: "component",
390
+ description: "A pressable control.",
391
+ resources: [
392
+ { label: "Source", href: "/src/button.tsx", detail: "src/button.tsx" },
91
393
  ],
92
394
  },
93
- { category: 'Feedback', entries: [{ id: 'toast', name: 'Toast', description: 'A transient message.' }] },
395
+ {
396
+ id: "profile-form",
397
+ name: "Profile form",
398
+ kind: "composition",
399
+ description: "A labeled field and save action working together.",
400
+ },
401
+ ];
402
+ const sections: CatalogSection[] = [
403
+ {
404
+ category: "Examples",
405
+ entries: entries.map(({ kind, ...entry }) => ({
406
+ ...entry,
407
+ tags: kind === "composition" ? ["Composition"] : undefined,
408
+ })),
409
+ },
94
410
  ];
95
411
 
96
- // 2. One preview render per entry id.
97
- const renderers: Record<string, () => ReturnType<typeof Button>> = {
98
- button: () => <Button label="Save" />,
99
- field: () => <Field label="Name" />,
100
- toast: () => <Toast>Saved</Toast>,
412
+ // 2. Every preview uses one public group and public example rows.
413
+ const renderers: Record<string, () => SafeHtml> = {
414
+ button: () => (
415
+ <CatalogExampleStack
416
+ label="Button States"
417
+ rootAttributes={{ "data-demo": "button" }}
418
+ >
419
+ <CatalogExample label="Default" align="inline-control">
420
+ <Button label="Save" />
421
+ </CatalogExample>
422
+ <CatalogExample label="Authoring Note" note="Explain the specimen below.">
423
+ <p>The application owns product copy and actions.</p>
424
+ </CatalogExample>
425
+ </CatalogExampleStack>
426
+ ),
427
+ "profile-form": () => (
428
+ <CatalogExampleStack
429
+ label="Profile Form Composition"
430
+ rootAttributes={{ "data-demo": "profile-form" }}
431
+ >
432
+ <CatalogExample label="Complete Composition">
433
+ <ProfileForm />
434
+ </CatalogExample>
435
+ </CatalogExampleStack>
436
+ ),
101
437
  };
102
438
 
103
- // 3. App-owned state (domain: which entry; transient: collapsed; global: theme).
104
- const initial = new URLSearchParams(location.search).get('c') ?? sections[0].entries[0].id;
439
+ // 3. App-owned state (domain: which entry; transient: collapsed; display preferences).
440
+ const initial =
441
+ new URLSearchParams(location.search).get("c") ?? sections[0].entries[0].id;
105
442
  const active = signal(initial);
106
443
  const collapsed = signal(false);
107
- const theme = signal<'light' | 'dark'>('light');
444
+ const theme = signal<"light" | "dark">("light");
445
+ const increasedContrast = signal(false);
446
+ const reducedMotion = signal(false);
447
+ const backgroundStyle = signal<CatalogBackgroundStyle>("checkerboard");
108
448
 
109
- const app = document.getElementById('app')!;
449
+ const app = document.getElementById("app")!;
110
450
  mount(app, () => (
111
451
  <Catalog
112
- brand={{ title: 'Acme UI', subtitle: 'Design system' }}
452
+ brand={{ title: "Acme UI", subtitle: "Design system" }}
113
453
  sections={sections}
114
454
  active={active.value}
115
455
  content={renderers[active.value]?.() ?? <></>}
116
456
  collapsed={collapsed.value}
117
457
  theme={theme.value}
458
+ increasedContrast={increasedContrast.value}
459
+ reducedMotion={reducedMotion.value}
460
+ backgroundControl
461
+ backgroundStyle={backgroundStyle.value}
118
462
  />
119
463
  ));
120
464
 
121
465
  wireCatalog(app, {
122
- onSelect: (id) => { active.value = id; },
123
- onToggleSidebar: () => { collapsed.value = !collapsed.value; },
466
+ onSelect: (id) => {
467
+ active.value = id;
468
+ },
469
+ onToggleSidebar: () => {
470
+ collapsed.value = !collapsed.value;
471
+ },
124
472
  onToggleTheme: () => {
125
- theme.value = theme.value === 'dark' ? 'light' : 'dark';
473
+ theme.value = theme.value === "dark" ? "light" : "dark";
126
474
  document.documentElement.dataset.theme = theme.value; // apply your theme however you like
127
475
  },
128
- urlParam: 'c', // mirror the active id into ?c=<id>
476
+ onToggleContrast: () => {
477
+ increasedContrast.value = !increasedContrast.value;
478
+ document.documentElement.classList.toggle("increased-contrast", increasedContrast.value);
479
+ },
480
+ onToggleMotion: () => {
481
+ reducedMotion.value = !reducedMotion.value;
482
+ document.documentElement.classList.toggle("reduced-motion", reducedMotion.value);
483
+ },
484
+ onSelectBackground: (style) => {
485
+ backgroundStyle.value = style;
486
+ },
487
+ urlParam: "c", // mirror the active id into ?c=<id>
488
+ revealSelection: true, // reveal long desktop sidebars without moving focus
129
489
  });
490
+
491
+ // Optional for an initial deep link whose row may start outside the viewport.
492
+ revealCatalogEntry(app, initial, { block: "center" });
130
493
  ```
131
494
 
132
495
  ## Ownership boundary
@@ -136,20 +499,159 @@ wireCatalog(app, {
136
499
  - **`active`** is domain state (which entry is shown) — the app's signal, updated in
137
500
  `onSelect`, read to compute `content`.
138
501
  - **`collapsed`** is transient UI — the app's signal, flipped in `onToggleSidebar`.
502
+ Pass the same signal as `wireCatalog`'s `collapsed` option so the sidebar is
503
+ wired as a Workbench rail (transient on small screens, focus handed to the
504
+ relocated toggle).
505
+ - **`headerPlacement` / `footerPlacement`** choose whether the entry toolbar and
506
+ description, and the status + resource footer, stay pinned (`fixed`), scroll with
507
+ the preview (`scroll`), or stay pinned while the entry pane is tall enough and
508
+ scroll with the preview when it is short (`auto`, the default) — so a short
509
+ window or large text never squeezes the preview out.
510
+ The resource footer uses `ToolbarControlGroup overflow="wrap"`: whole links
511
+ move to another row when they do not fit, keeping Guidance and source labels
512
+ readable without horizontal scrolling.
513
+ - **`sidebar`** configures the sidebar rail — it forwards to the Workbench's left
514
+ rail: `size` (default 288px), `resizable` (`true` or `{ min, max }`),
515
+ `separator`, `collapseMotion`, `presentation`, `responsiveOverlayAt` (default
516
+ `narrow`), `compactOverlay` (default `inset`), and `toolbar` (the sidebar
517
+ header's `ToolbarConfig`). A resizable sidebar's width is app state like
518
+ `collapsed`: render your size signal as `sidebar.size` and pass the same signal
519
+ as `wireCatalog`'s `sidebarSize` (plus `sidebarStorageKey` to remember it).
520
+ - **`settingsCollapsed`** is transient UI like `collapsed`: render your signal as
521
+ `settingsCollapsed` and pass the same signal as `wireCatalog`'s
522
+ `settingsCollapsed`. `wireCatalog` then flips it from the toggle (report it
523
+ with `onToggleSettings`, which runs after the flip) and wires the pane as a
524
+ Workbench rail: below the `narrow` breakpoint it starts collapsed and opens as
525
+ an overlay over the stage that Escape or a press outside closes, handing focus
526
+ back to the toggle. The sidebar and settings overlays are exclusive. Without
527
+ the signal, `onToggleSettings` alone reports the press and the app flips its
528
+ own state.
529
+ - **`settingsPanel`** configures the settings pane like `sidebar` configures the
530
+ sidebar: `title` (default `Settings`; it also names the toggle), `size`
531
+ (default 288px), `resizable`, `separator`, `collapseMotion`, `presentation`,
532
+ `responsiveOverlayAt`, `compactOverlay`, and `toolbar`. A resizable pane's
533
+ width is app state: render your signal as `settingsPanel.size` and pass it as
534
+ `wireCatalog`'s `settingsSize` (plus `settingsStorageKey` to remember it).
535
+ - **`mainToolbar` / `footerToolbar`** take the entry toolbar's and the resource
536
+ footer toolbar's `ToolbarConfig` (`dividerSides`, `centerAlign`, `responsive`,
537
+ `responsiveAt`, `safeAreaEdges`). The defaults are a wrapping entry toolbar
538
+ and a footer toolbar that stacks at `narrow`, all without dividers of their
539
+ own: `wireCatalog` wires `wireScrollDividers`, so the shell's panes draw
540
+ their chrome dividers only while scrolled; an omitted or
541
+ `undefined` field keeps them. Configure these instead of styling the shell.
139
542
  - **`theme`** is a global preference — the app's signal; `wireCatalog` only reports
140
543
  the toggle, the app applies the theme (the shell reads `theme` to show the toggle's
141
544
  opposite-state label). Omit `theme` to hide the toggle entirely.
142
545
 
546
+ ## UX Review capture
547
+
548
+ On a local Vite dev or preview server the catalog can offer a **Capture Region**
549
+ header link that starts a UX Review region screenshot, preset with the project
550
+ and the active entry. Static hosting has no local project, so the link never
551
+ appears there. Three pieces wire it:
552
+
553
+ ```ts
554
+ // vite.config.ts — Node only; never part of the browser bundle.
555
+ import { uxReviewPlugin } from "@kerfjs/ui/vite-ux-review";
556
+
557
+ export default defineConfig({ plugins: [uxReviewPlugin()] });
558
+ ```
559
+
560
+ ```tsx
561
+ const uxReviewProject = signal<string | null>(null);
562
+
563
+ mount(app, () => (
564
+ <Catalog
565
+ /* …the props above… */
566
+ uxReview={
567
+ uxReviewProject.value
568
+ ? { projectDirectory: uxReviewProject.value }
569
+ : undefined
570
+ }
571
+ />
572
+ ));
573
+
574
+ wireCatalog(app, {
575
+ onSelect: (id) => (active.value = id),
576
+ onUxReviewProject: (directory) => (uxReviewProject.value = directory),
577
+ });
578
+ ```
579
+
580
+ - **`uxReviewPlugin(options?)`** answers `GET …/__ux-review/project.json` with
581
+ `{ projectDirectory }` on the dev and preview servers, at any base path. The
582
+ directory defaults to the repository holding Vite's `root` (the nearest
583
+ ancestor with `.git`, or `root` itself); pass `projectDirectory` (resolved
584
+ against `root`) to name another.
585
+ - **`wireCatalog`'s `onUxReviewProject`** asks the page's server once and
586
+ reports the directory. It is never called on static hosting or a server
587
+ without the plugin. While wired, following the link stamps the current page
588
+ URL into the capture context.
589
+ - **`Catalog`'s `uxReview`** (`{ projectDirectory, name? }`) renders the link
590
+ after `headerActions`. The capture is titled `<name>: <entry>`, and its
591
+ context names the catalog, the entry's section, and the entry; `name`
592
+ defaults to `brand.title`.
593
+
594
+ The browser helpers behind it, `uxReviewCaptureUrl` and `loadUxReviewProject`,
595
+ are exported from `@kerfjs/ui/catalog` for a capture link placed elsewhere.
596
+
597
+ ### Catalogs served without Vite
598
+
599
+ A catalog served by the app's own backend (an esbuild bundle behind Hono,
600
+ Express, or a plain Node server) mounts the same endpoint from the same
601
+ Node-only subpath, on its development server only. The catalog requests
602
+ `__ux-review/project.json` relative to its page, so a page at `/ux-demo` asks
603
+ for `/__ux-review/project.json`; both helpers answer at any base path.
604
+
605
+ ```ts
606
+ import {
607
+ resolveUxReviewProject,
608
+ uxReviewMiddleware,
609
+ uxReviewProjectResponse,
610
+ } from "@kerfjs/ui/vite-ux-review";
611
+
612
+ // Resolve once at startup: the repository holding the working directory, or
613
+ // resolveUxReviewProject({ root, projectDirectory }) like the Vite plugin.
614
+ const projectDirectory = resolveUxReviewProject();
615
+
616
+ // Fetch API servers (Hono, Bun, Deno): null means "not this endpoint".
617
+ if (isDev)
618
+ app.use("*", async (c, next) =>
619
+ uxReviewProjectResponse(c.req.raw, projectDirectory) ?? next(),
620
+ );
621
+
622
+ // Node / connect servers (Express, node:http):
623
+ if (isDev) expressApp.use(uxReviewMiddleware(projectDirectory));
624
+ ```
625
+
626
+ - **`resolveUxReviewProject({ root?, projectDirectory? })`** returns the real
627
+ path the Vite plugin would serve: `projectDirectory` resolved against `root`,
628
+ or the repository holding `root` (default `process.cwd()`).
629
+ - **`uxReviewProjectResponse(request, projectDirectory)`** answers a Fetch API
630
+ `Request`: the JSON for a GET, `405` for another method, or `null` for any
631
+ other path.
632
+ - **`uxReviewMiddleware(projectDirectory)`** is the same endpoint as a
633
+ `(request, response, next)` handler; `uxReviewPlugin` mounts it on Vite.
634
+
635
+ Never register the endpoint in production: it reveals a local path, and a
636
+ deployed catalog has no local project to capture into.
637
+
143
638
  ## Custom action names
144
639
 
145
640
  The shell emits `data-action="catalog-select"` (sidebar items),
146
- `catalog-toggle-sidebar`, and `catalog-toggle-theme`. Override them with
147
- `selectAction` / `toggleSidebarAction` / `toggleThemeAction` on `Catalog` (and the
148
- matching options on `wireCatalog`) if they collide with your own action table.
641
+ `catalog-toggle-sidebar`, `catalog-toggle-theme`, `catalog-toggle-contrast`,
642
+ `catalog-toggle-motion`, and `catalog-select-background`. Override them with
643
+ the matching `*Action` props on `Catalog` and options on `wireCatalog` if they
644
+ collide with your own action table.
149
645
 
150
646
  ## CSS
151
647
 
152
- `Catalog` composes public primitives (`Toolbar`, `ListHeader`, `ListItem`, `Select`,
153
- …). Import `@kerfjs/ui/styles.css` for the whole layer, or `@kerfjs/ui/catalog.css`
154
- plus each composed primitive's CSS. The shell is theme-aware and responsive: it
155
- stacks the sidebar above the detail below ~832px and hides it when collapsed.
648
+ `Catalog` composes public components (`Workbench`, `Pane`, `Toolbar`, `List`,
649
+ `ListHeader`, `ListItem`, `ListInsetText`, `Text`, …) and owns only the preview stage
650
+ (the checkerboard and left-aligned canvas), the example viewport
651
+ options, and the brand mark's size. A bundler that honors the `browser` export
652
+ condition loads the Catalog's stylesheets and those of every component it renders
653
+ internally with the `@kerfjs/ui/catalog` import alone — no dependence on which other
654
+ subpaths the app happens to import. Without that condition, import
655
+ `@kerfjs/ui/styles.css` for the whole layer, or `@kerfjs/ui/catalog.css` plus
656
+ `@kerfjs/ui/workbench.css` and each composed primitive's CSS. Like any Workbench it needs a definite containing height — the
657
+ `@kerfjs/ui/document.css` baseline's `.kui-app-root`.