@kerfjs/ui 5.0.0-beta.55 → 5.0.0-beta.57

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 (418) hide show
  1. package/README.md +74 -41
  2. package/ai/application-ui-diagnostic-ids-v1.json +9 -1
  3. package/ai/application-ui-profile-sync.cjs +1 -1
  4. package/ai/application-ui-profile.defaults.json +63 -8
  5. package/ai/application-ui-profile.mjs +1 -1
  6. package/ai/compile-time-contracts-v1.json +2 -2
  7. package/ai/component-catalog.json +407 -80
  8. package/ai/component-catalog.schema.json +2 -0
  9. package/ai/component-class-owners.cjs +83 -0
  10. package/ai/component-composition-extension.d.ts +7 -0
  11. package/ai/component-composition-extension.schema.json +7 -0
  12. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +2 -1
  13. package/ai/{component-catalog-v2.d.ts → component-composition.d.ts} +9 -5
  14. package/ai/{component-catalog-v2.json → component-composition.json} +302 -61
  15. package/ai/{component-catalog-v2.schema.json → component-composition.schema.json} +21 -5
  16. package/ai/components/README.md +170 -0
  17. package/ai/components/application-tabs.md +65 -0
  18. package/ai/components/badge.md +72 -0
  19. package/ai/components/collapsible-panel.md +102 -0
  20. package/ai/components/content-item.md +90 -0
  21. package/ai/components/disclosure-arrow.md +77 -0
  22. package/ai/components/document-baseline.md +75 -0
  23. package/ai/components/empty-state.md +80 -0
  24. package/ai/components/feedback.md +71 -0
  25. package/ai/components/floating-toolbar.md +80 -0
  26. package/ai/components/foundation.md +65 -0
  27. package/ai/components/grid.md +93 -0
  28. package/ai/components/headers.md +63 -0
  29. package/ai/components/layout.md +75 -0
  30. package/ai/components/list-action-row.md +91 -0
  31. package/ai/components/list-header.md +89 -0
  32. package/ai/components/list-inset-control.md +74 -0
  33. package/ai/components/list-inset-text.md +72 -0
  34. package/ai/components/list-item.md +88 -0
  35. package/ai/components/list.md +103 -0
  36. package/ai/components/loading-spinner.md +72 -0
  37. package/ai/components/lucide-icon.md +66 -0
  38. package/ai/components/nav-stack.md +103 -0
  39. package/ai/components/pane.md +100 -0
  40. package/ai/components/popup-menu.md +82 -0
  41. package/ai/components/recipe-app-shell.md +57 -0
  42. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  43. package/ai/components/recipe-compact-toolbar.md +57 -0
  44. package/ai/components/recipe-composer-form.md +57 -0
  45. package/ai/components/recipe-list-detail-dialog.md +57 -0
  46. package/ai/components/recipe-list-workspace-states.md +57 -0
  47. package/ai/components/recipe-loading-inspector.md +57 -0
  48. package/ai/components/recipe-navigation-sidebar.md +57 -0
  49. package/ai/components/recipe-navigation-stack.md +57 -0
  50. package/ai/components/recipe-workspace-header.md +57 -0
  51. package/ai/components/resize.md +101 -0
  52. package/ai/components/row.md +96 -0
  53. package/ai/components/segmented-control.md +82 -0
  54. package/ai/components/select.md +107 -0
  55. package/ai/components/skeleton.md +84 -0
  56. package/ai/components/spacer.md +86 -0
  57. package/ai/components/split-view.md +102 -0
  58. package/ai/components/state-banner.md +92 -0
  59. package/ai/components/sunken-panel.md +79 -0
  60. package/ai/components/surface-scaffold.md +78 -0
  61. package/ai/components/tab-bar.md +112 -0
  62. package/ai/components/tab-scaffold.md +94 -0
  63. package/ai/components/tabs.md +90 -0
  64. package/ai/components/text.md +82 -0
  65. package/ai/components/token-search-field.md +101 -0
  66. package/ai/components/toolbar-control-group.md +100 -0
  67. package/ai/components/toolbar-text.md +76 -0
  68. package/ai/components/toolbar.md +95 -0
  69. package/ai/components/value-table.md +72 -0
  70. package/ai/components/wa-accordion-item.md +55 -0
  71. package/ai/components/wa-accordion.md +65 -0
  72. package/ai/components/wa-animated-image.md +55 -0
  73. package/ai/components/wa-animation.md +55 -0
  74. package/ai/components/wa-avatar.md +55 -0
  75. package/ai/components/wa-badge.md +55 -0
  76. package/ai/components/wa-breadcrumb-item.md +53 -0
  77. package/ai/components/wa-breadcrumb.md +55 -0
  78. package/ai/components/wa-button-group.md +59 -0
  79. package/ai/components/wa-button.md +55 -0
  80. package/ai/components/wa-callout.md +58 -0
  81. package/ai/components/wa-card.md +59 -0
  82. package/ai/components/wa-carousel-item.md +53 -0
  83. package/ai/components/wa-carousel.md +55 -0
  84. package/ai/components/wa-checkbox-group.md +55 -0
  85. package/ai/components/wa-checkbox.md +55 -0
  86. package/ai/components/wa-color-picker.md +55 -0
  87. package/ai/components/wa-comparison.md +55 -0
  88. package/ai/components/wa-copy-button.md +55 -0
  89. package/ai/components/wa-details.md +61 -0
  90. package/ai/components/wa-dialog.md +59 -0
  91. package/ai/components/wa-divider.md +53 -0
  92. package/ai/components/wa-drawer.md +55 -0
  93. package/ai/components/wa-dropdown-item.md +60 -0
  94. package/ai/components/wa-dropdown.md +60 -0
  95. package/ai/components/wa-format-bytes.md +53 -0
  96. package/ai/components/wa-format-date.md +53 -0
  97. package/ai/components/wa-format-number.md +53 -0
  98. package/ai/components/wa-icon.md +58 -0
  99. package/ai/components/wa-include.md +53 -0
  100. package/ai/components/wa-input.md +59 -0
  101. package/ai/components/wa-intersection-observer.md +53 -0
  102. package/ai/components/wa-known-date.md +53 -0
  103. package/ai/components/wa-markdown.md +53 -0
  104. package/ai/components/wa-mutation-observer.md +53 -0
  105. package/ai/components/wa-number-input.md +55 -0
  106. package/ai/components/wa-option.md +59 -0
  107. package/ai/components/wa-otp-input.md +53 -0
  108. package/ai/components/wa-page.md +53 -0
  109. package/ai/components/wa-pagination.md +55 -0
  110. package/ai/components/wa-popover.md +55 -0
  111. package/ai/components/wa-popup.md +53 -0
  112. package/ai/components/wa-progress-bar.md +53 -0
  113. package/ai/components/wa-progress-ring.md +53 -0
  114. package/ai/components/wa-qr-code.md +53 -0
  115. package/ai/components/wa-radio-group.md +59 -0
  116. package/ai/components/wa-radio.md +55 -0
  117. package/ai/components/wa-random-content.md +53 -0
  118. package/ai/components/wa-rating.md +55 -0
  119. package/ai/components/wa-relative-time.md +53 -0
  120. package/ai/components/wa-resize-observer.md +53 -0
  121. package/ai/components/wa-scroller.md +53 -0
  122. package/ai/components/wa-select.md +63 -0
  123. package/ai/components/wa-skeleton.md +53 -0
  124. package/ai/components/wa-slider.md +55 -0
  125. package/ai/components/wa-spinner.md +58 -0
  126. package/ai/components/wa-split-panel.md +58 -0
  127. package/ai/components/wa-switch.md +53 -0
  128. package/ai/components/wa-tab-group.md +69 -0
  129. package/ai/components/wa-tab-panel.md +60 -0
  130. package/ai/components/wa-tab.md +59 -0
  131. package/ai/components/wa-tag.md +59 -0
  132. package/ai/components/wa-textarea.md +53 -0
  133. package/ai/components/wa-time-input.md +55 -0
  134. package/ai/components/wa-toast-item.md +60 -0
  135. package/ai/components/wa-toast.md +60 -0
  136. package/ai/components/wa-tooltip.md +55 -0
  137. package/ai/components/wa-tree-item.md +55 -0
  138. package/ai/components/wa-tree.md +55 -0
  139. package/ai/components/wa-zoomable-frame.md +55 -0
  140. package/ai/components/workbench.md +114 -0
  141. package/ai/public-api-signatures-v1.md +572 -101
  142. package/ai/skill.md +107 -52
  143. package/ai/webawesome-jsx-signatures-v1.md +8 -2
  144. package/analyzer/component-ownership.d.mts +56 -0
  145. package/analyzer/component-ownership.mjs +184 -0
  146. package/analyzer/index.d.mts +3 -0
  147. package/analyzer/index.mjs +274 -20
  148. package/analyzer/selectors.d.mts +21 -0
  149. package/analyzer/selectors.mjs +212 -0
  150. package/dist/app-tab.js +1 -1
  151. package/dist/badge.d.ts +35 -7
  152. package/dist/badge.js +1 -1
  153. package/dist/browser/catalog.js +25 -0
  154. package/dist/browser/collapsible-panel.js +7 -0
  155. package/dist/browser/content-item.js +3 -0
  156. package/dist/browser/nav-stack.js +8 -0
  157. package/dist/browser/select.js +1 -0
  158. package/dist/browser/split-view.js +10 -0
  159. package/dist/browser/tab-scaffold.js +4 -0
  160. package/dist/browser/workbench.js +10 -0
  161. package/dist/catalog-resources.d.ts +12 -1
  162. package/dist/catalog.d.ts +14 -3
  163. package/dist/catalog.js +53 -43
  164. package/dist/catalog.js.map +1 -1
  165. package/dist/{chunk-WZ2GLEY4.js → chunk-2G2ZJQYK.js} +2 -14
  166. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  167. package/dist/{chunk-R754MHXX.js → chunk-553ASUK6.js} +8 -8
  168. package/dist/chunk-553ASUK6.js.map +1 -0
  169. package/dist/{chunk-D7GWXIAS.js → chunk-5I7QGQVT.js} +1 -1
  170. package/dist/chunk-5I7QGQVT.js.map +1 -0
  171. package/dist/{chunk-RNRUVPJ3.js → chunk-63ZWBGE3.js} +3 -2
  172. package/dist/chunk-63ZWBGE3.js.map +1 -0
  173. package/dist/{chunk-44IG7PFV.js → chunk-6CINWX2E.js} +3 -3
  174. package/dist/{chunk-44IG7PFV.js.map → chunk-6CINWX2E.js.map} +1 -1
  175. package/dist/{chunk-MTM43SJO.js → chunk-6YFHCLHG.js} +2 -2
  176. package/dist/chunk-6YFHCLHG.js.map +1 -0
  177. package/dist/{chunk-C2FAYFDE.js → chunk-AGXQQFKZ.js} +2 -2
  178. package/dist/{chunk-C2FAYFDE.js.map → chunk-AGXQQFKZ.js.map} +1 -1
  179. package/dist/{chunk-ATHXW6RP.js → chunk-AHEG27M7.js} +2 -2
  180. package/dist/{chunk-ATHXW6RP.js.map → chunk-AHEG27M7.js.map} +1 -1
  181. package/dist/chunk-BFPBS5Y4.js +250 -0
  182. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  183. package/dist/{chunk-5OLVUEND.js → chunk-DG6G5EPF.js} +4 -6
  184. package/dist/chunk-DG6G5EPF.js.map +1 -0
  185. package/dist/{chunk-LZXQVUGN.js → chunk-EVYKTVBQ.js} +5 -14
  186. package/dist/chunk-EVYKTVBQ.js.map +1 -0
  187. package/dist/{chunk-7GUQYHKA.js → chunk-EZVNC4J6.js} +7 -1
  188. package/dist/chunk-EZVNC4J6.js.map +1 -0
  189. package/dist/{chunk-RNZAKSME.js → chunk-F4QMLOXJ.js} +5 -4
  190. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  191. package/dist/{chunk-EAX2GSS4.js → chunk-G2RKFVRB.js} +54 -20
  192. package/dist/chunk-G2RKFVRB.js.map +1 -0
  193. package/dist/chunk-JCV4GXWB.js +249 -0
  194. package/dist/chunk-JCV4GXWB.js.map +1 -0
  195. package/dist/chunk-K47P7QZC.js +17 -0
  196. package/dist/chunk-K47P7QZC.js.map +1 -0
  197. package/dist/{chunk-HMQ2ZDGG.js → chunk-KROD7KZK.js} +3 -2
  198. package/dist/chunk-KROD7KZK.js.map +1 -0
  199. package/dist/{chunk-5NDQABWK.js → chunk-M7QV3IHH.js} +3 -1
  200. package/dist/chunk-M7QV3IHH.js.map +1 -0
  201. package/dist/chunk-MA73TA6D.js +42 -0
  202. package/dist/chunk-MA73TA6D.js.map +1 -0
  203. package/dist/{chunk-ZMBU522F.js → chunk-MEY33VWB.js} +2 -2
  204. package/dist/{chunk-ZMBU522F.js.map → chunk-MEY33VWB.js.map} +1 -1
  205. package/dist/chunk-MP2GDBQZ.js +50 -0
  206. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  207. package/dist/{chunk-3NBL3OUQ.js → chunk-NAPE7WUS.js} +2 -2
  208. package/dist/chunk-NAPE7WUS.js.map +1 -0
  209. package/dist/{chunk-BSKEH3UC.js → chunk-NBYTIVHS.js} +2 -2
  210. package/dist/{chunk-BSKEH3UC.js.map → chunk-NBYTIVHS.js.map} +1 -1
  211. package/dist/{chunk-T22EM4ET.js → chunk-OUK6QRDR.js} +71 -31
  212. package/dist/chunk-OUK6QRDR.js.map +1 -0
  213. package/dist/chunk-PWXNJS2B.js +115 -0
  214. package/dist/chunk-PWXNJS2B.js.map +1 -0
  215. package/dist/{chunk-GUIHMIT2.js → chunk-QOWG4ZCL.js} +5 -4
  216. package/dist/chunk-QOWG4ZCL.js.map +1 -0
  217. package/dist/{chunk-5I22LMCV.js → chunk-VZOFZPSO.js} +2 -2
  218. package/dist/chunk-VZOFZPSO.js.map +1 -0
  219. package/dist/{chunk-4BIMLITI.js → chunk-WLG6SSNT.js} +5 -3
  220. package/dist/chunk-WLG6SSNT.js.map +1 -0
  221. package/dist/{chunk-NE5JAOQS.js → chunk-WOUF7YXM.js} +3 -3
  222. package/dist/{chunk-NE5JAOQS.js.map → chunk-WOUF7YXM.js.map} +1 -1
  223. package/dist/{chunk-N7FHFNT6.js → chunk-XCO6YCYM.js} +34 -5
  224. package/dist/chunk-XCO6YCYM.js.map +1 -0
  225. package/dist/{chunk-TZ5IHWB2.js → chunk-XDKAYSVD.js} +5 -3
  226. package/dist/chunk-XDKAYSVD.js.map +1 -0
  227. package/dist/collapsible-panel.d.ts +14 -3
  228. package/dist/collapsible-panel.js +13 -16
  229. package/dist/collapsible-panel.js.map +1 -1
  230. package/dist/content-item.d.ts +46 -0
  231. package/dist/content-item.js +4 -0
  232. package/dist/content-item.js.map +1 -0
  233. package/dist/css-values.d.ts +5 -11
  234. package/dist/css-values.js +1 -1
  235. package/dist/disclosure-arrow.d.ts +4 -1
  236. package/dist/disclosure-arrow.js +1 -1
  237. package/dist/floating-toolbar.d.ts +17 -6
  238. package/dist/floating-toolbar.js +1 -1
  239. package/dist/grid.js +1 -1
  240. package/dist/help-tags-register.d.ts +13 -0
  241. package/dist/help-tags-register.js +9 -0
  242. package/dist/help-tags-register.js.map +1 -0
  243. package/dist/index.d.ts +7 -5
  244. package/dist/index.js +29 -26
  245. package/dist/list-action-row.js +2 -1
  246. package/dist/list-header.d.ts +14 -1
  247. package/dist/list-header.js +1 -1
  248. package/dist/list-inset-control.d.ts +1 -1
  249. package/dist/list-inset-control.js +1 -1
  250. package/dist/list-inset-text.d.ts +3 -10
  251. package/dist/list-inset-text.js +1 -1
  252. package/dist/list-item.js +2 -1
  253. package/dist/list.d.ts +10 -3
  254. package/dist/list.js +1 -1
  255. package/dist/nav-stack.d.ts +50 -5
  256. package/dist/nav-stack.js +4 -1
  257. package/dist/pane.d.ts +37 -2
  258. package/dist/pane.js +1 -1
  259. package/dist/{panel-toolbar-BFQxFITu.d.ts → panel-toolbar-BN4x0rth.d.ts} +13 -1
  260. package/dist/popup-menu-register.js +3 -2
  261. package/dist/popup-menu-register.js.map +1 -1
  262. package/dist/popup-menu.js +1 -1
  263. package/dist/row.d.ts +1 -1
  264. package/dist/row.js +1 -1
  265. package/dist/select-register.js +70 -3
  266. package/dist/select-register.js.map +1 -1
  267. package/dist/select.d.ts +46 -8
  268. package/dist/select.js +2 -1
  269. package/dist/{divider-sides-BzB6rphT.d.ts → sides-BPSWde0A.d.ts} +1 -3
  270. package/dist/skeleton.js +1 -1
  271. package/dist/spacer.js +1 -1
  272. package/dist/split-view.d.ts +31 -3
  273. package/dist/split-view.js +34 -5
  274. package/dist/split-view.js.map +1 -1
  275. package/dist/state-banner.js +1 -1
  276. package/dist/styles/app-tab.css +31 -0
  277. package/dist/styles/badge.css +32 -11
  278. package/dist/styles/catalog/components/catalog-example.css +1 -1
  279. package/dist/styles/catalog/components/catalog-stage.css +1 -1
  280. package/dist/styles/collapsible-panel.css +199 -42
  281. package/dist/styles/content-item.css +30 -0
  282. package/dist/styles/floating-toolbar.css +26 -2
  283. package/dist/styles/foundation.css +28 -19
  284. package/dist/styles/layout.css +1 -21
  285. package/dist/styles/list-action-row.css +13 -1
  286. package/dist/styles/list-header.css +0 -12
  287. package/dist/styles/list-inset-text.css +1 -2
  288. package/dist/styles/list-item.css +14 -1
  289. package/dist/styles/list.css +5 -5
  290. package/dist/styles/nav-stack.css +63 -71
  291. package/dist/styles/pane.css +83 -1
  292. package/dist/styles/popup-menu.css +229 -0
  293. package/dist/styles/resizable-region.css +70 -15
  294. package/dist/styles/select.css +60 -19
  295. package/dist/styles/skeleton.css +30 -3
  296. package/dist/styles/split-view.css +31 -32
  297. package/dist/styles/state-banner.css +0 -19
  298. package/dist/styles/surface-scaffold.css +8 -3
  299. package/dist/styles/tab-bar.css +79 -28
  300. package/dist/styles/tab-scaffold.css +60 -14
  301. package/dist/styles/text.css +17 -1
  302. package/dist/styles/token-search-field.css +4 -4
  303. package/dist/styles/toolbar-control-group.css +143 -69
  304. package/dist/styles/toolbar-text.css +21 -0
  305. package/dist/styles/toolbar.css +22 -37
  306. package/dist/styles/value-table.css +19 -2
  307. package/dist/styles/webawesome.css +3 -1
  308. package/dist/styles/workbench.css +145 -42
  309. package/dist/tab-scaffold.d.ts +46 -2
  310. package/dist/tab-scaffold.js +52 -16
  311. package/dist/tab-scaffold.js.map +1 -1
  312. package/dist/token-search-field.d.ts +4 -2
  313. package/dist/token-search-field.js +1 -1
  314. package/dist/toolbar-text.d.ts +7 -1
  315. package/dist/toolbar-text.js +1 -1
  316. package/dist/toolbar.d.ts +20 -5
  317. package/dist/toolbar.js +1 -1
  318. package/dist/{types-D6vzj-VT.d.ts → types-BuHELdXR.d.ts} +39 -6
  319. package/dist/value-table.js +1 -1
  320. package/dist/webawesome.d.ts +7 -1
  321. package/dist/wire-catalog.d.ts +15 -2
  322. package/dist/wire-catalog.js +12 -2
  323. package/dist/wire-catalog.js.map +1 -1
  324. package/dist/wire-scroll-dividers.d.ts +69 -0
  325. package/dist/wire-scroll-dividers.js +3 -0
  326. package/dist/wire-scroll-dividers.js.map +1 -0
  327. package/dist/wire-token-search-fields.js +1 -1
  328. package/dist/workbench.d.ts +60 -22
  329. package/dist/workbench.js +1 -1
  330. package/docs/accessibility.md +116 -7
  331. package/docs/app-layouts.md +18 -8
  332. package/docs/catalog.md +26 -7
  333. package/docs/collapsible-panel.md +32 -9
  334. package/docs/component-contract.md +182 -30
  335. package/docs/component-selection.md +59 -46
  336. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  337. package/docs/design/templates/empty-state/with-action.svg +1 -1
  338. package/docs/design/templates/empty-state-dark.svg +1 -1
  339. package/docs/design/templates/empty-state.svg +1 -1
  340. package/docs/design/templates/list/compact-dark.svg +1 -1
  341. package/docs/design/templates/list/compact.svg +1 -1
  342. package/docs/design/templates/list/stack-dark.svg +1 -1
  343. package/docs/design/templates/list/stack.svg +1 -1
  344. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  345. package/docs/design/templates/list-action-row/default.svg +1 -1
  346. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  347. package/docs/design/templates/list-action-row/selected.svg +1 -1
  348. package/docs/design/templates/list-action-row-dark.svg +1 -1
  349. package/docs/design/templates/list-action-row.svg +1 -1
  350. package/docs/design/templates/list-dark.svg +1 -1
  351. package/docs/design/templates/list-item/default-dark.svg +1 -1
  352. package/docs/design/templates/list-item/default.svg +1 -1
  353. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  354. package/docs/design/templates/list-item/selected.svg +1 -1
  355. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  356. package/docs/design/templates/list-item/trailing.svg +1 -1
  357. package/docs/design/templates/list-item-dark.svg +1 -1
  358. package/docs/design/templates/list-item.svg +1 -1
  359. package/docs/design/templates/list.svg +1 -1
  360. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  361. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  362. package/docs/design/templates/tab-bar-dark.svg +1 -1
  363. package/docs/design/templates/tab-bar.svg +1 -1
  364. package/docs/design/templates/value-table/details-dark.svg +1 -1
  365. package/docs/design/templates/value-table/details.svg +1 -1
  366. package/docs/design/templates/value-table-dark.svg +1 -1
  367. package/docs/design/templates/value-table.svg +1 -1
  368. package/docs/design-philosophy.md +31 -4
  369. package/docs/examples/application-ui-profile.json +4 -4
  370. package/docs/examples/command-palette-adapter.tsx +3 -2
  371. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +3 -3
  372. package/docs/layout.md +148 -29
  373. package/docs/nav-stack.md +77 -3
  374. package/docs/recipes.md +4 -3
  375. package/docs/split-view.md +54 -5
  376. package/docs/tab-scaffold.md +73 -2
  377. package/docs/type-contracts.md +21 -20
  378. package/docs/ui-analyzer.md +99 -5
  379. package/docs/ui-doctor.md +10 -0
  380. package/docs/ux-demo.md +2 -2
  381. package/docs/webawesome-theme.md +1 -2
  382. package/docs/workbench.md +57 -11
  383. package/doctor/index.mjs +6 -1
  384. package/llms.txt +117 -24
  385. package/package.json +29 -6
  386. package/ux-demo/recipes/collapsible-sidebar.tsx +3 -3
  387. package/ux-demo/recipes/composer-form.tsx +0 -1
  388. package/ux-demo/recipes/list-detail-dialog.tsx +0 -2
  389. package/ux-demo/recipes/list-workspace-states.tsx +0 -1
  390. package/ux-demo/recipes/loading-inspector.tsx +0 -1
  391. package/ux-demo/recipes/navigation-sidebar.tsx +3 -2
  392. package/ux-demo/recipes/navigation-stack.tsx +3 -2
  393. package/ux-demo/recipes/workspace-header.tsx +0 -1
  394. package/ai/component-catalog-extension-v2.d.ts +0 -7
  395. package/ai/component-catalog-extension-v2.schema.json +0 -7
  396. package/dist/chunk-3NBL3OUQ.js.map +0 -1
  397. package/dist/chunk-4BIMLITI.js.map +0 -1
  398. package/dist/chunk-5I22LMCV.js.map +0 -1
  399. package/dist/chunk-5NDQABWK.js.map +0 -1
  400. package/dist/chunk-5OLVUEND.js.map +0 -1
  401. package/dist/chunk-7GUQYHKA.js.map +0 -1
  402. package/dist/chunk-D7GWXIAS.js.map +0 -1
  403. package/dist/chunk-DQA5FMOX.js +0 -85
  404. package/dist/chunk-DQA5FMOX.js.map +0 -1
  405. package/dist/chunk-EAX2GSS4.js.map +0 -1
  406. package/dist/chunk-GUIHMIT2.js.map +0 -1
  407. package/dist/chunk-HMQ2ZDGG.js.map +0 -1
  408. package/dist/chunk-LZXQVUGN.js.map +0 -1
  409. package/dist/chunk-MTM43SJO.js.map +0 -1
  410. package/dist/chunk-N7FHFNT6.js.map +0 -1
  411. package/dist/chunk-R754MHXX.js.map +0 -1
  412. package/dist/chunk-RNRUVPJ3.js.map +0 -1
  413. package/dist/chunk-RNZAKSME.js.map +0 -1
  414. package/dist/chunk-T22EM4ET.js.map +0 -1
  415. package/dist/chunk-TZ5IHWB2.js.map +0 -1
  416. package/dist/chunk-WZ2GLEY4.js.map +0 -1
  417. package/dist/chunk-XD7DWYXG.js +0 -34
  418. package/dist/chunk-XD7DWYXG.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  # Public API signatures for the UI authoring corpus
2
2
 
3
- Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.55` and `kerfjs@5.0.0-beta.55`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
3
+ Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.57` and `kerfjs@5.0.0-beta.57`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
4
4
 
5
5
  ## `@kerfjs/ui/css-values`
6
6
 
@@ -48,9 +48,8 @@ type CssColor = CssValue & {
48
48
  * a surface. Mint it with {@link uiColor} and a foreground token name
49
49
  * ({@link UiForegroundColorName}) or with {@link foregroundColorVar}. It is a
50
50
  * {@link CssColor}, but a plain `CssColor` is not a foreground color: fill,
51
- * border, and surface tokens (including the `success` / `warning` / `danger` /
52
- * `pop` fill aliases) are pale backgrounds that leave a foreground nearly
53
- * invisible.
51
+ * border, and surface tokens are pale backgrounds that leave a foreground
52
+ * nearly invisible.
54
53
  */
55
54
  type CssForegroundColor = CssColor & {
56
55
  readonly [cssForegroundColorBrand]: 'CssForegroundColor';
@@ -60,16 +59,11 @@ type CssFlexBasis = CssLength | 'auto' | 'content' | 'min-content' | 'max-conten
60
59
  type CssSizeKeyword = 'auto' | 'min-content' | 'max-content' | 'fit-content';
61
60
  /** A complete width/height value accepted by dimension-valued UI props. */
62
61
  type CssSize = CssLength | CssSizeKeyword;
63
- declare const uiColorNames: readonly ["accent", "accent-text", "border", "border-quiet", "brand-border-loud", "brand-border-normal", "brand-border-quiet", "brand-fill-loud", "brand-fill-normal", "brand-fill-quiet", "brand-on-fill", "brand-on-loud", "brand-on-normal", "brand-on-quiet", "danger", "danger-border-loud", "danger-border-normal", "danger-border-quiet", "danger-fill-loud", "danger-fill-normal", "danger-fill-quiet", "danger-on-fill", "danger-on-loud", "danger-on-normal", "danger-on-quiet", "danger-text", "neutral-border-loud", "neutral-border-normal", "neutral-border-quiet", "neutral-fill-loud", "neutral-fill-normal", "neutral-fill-quiet", "neutral-on-loud", "neutral-on-normal", "neutral-on-quiet", "pop", "pop-border-loud", "pop-border-normal", "pop-border-quiet", "pop-fill-loud", "pop-fill-normal", "pop-fill-quiet", "pop-on-fill", "pop-on-loud", "pop-on-normal", "pop-on-quiet", "pop-text", "success", "success-border-loud", "success-border-normal", "success-border-quiet", "success-fill-loud", "success-fill-normal", "success-fill-quiet", "success-on-fill", "success-on-loud", "success-on-normal", "success-on-quiet", "success-text", "surface", "surface-lowered", "surface-raised", "text", "text-link", "text-quiet", "warning", "warning-border-loud", "warning-border-normal", "warning-border-quiet", "warning-fill-loud", "warning-fill-normal", "warning-fill-quiet", "warning-on-fill", "warning-on-loud", "warning-on-normal", "warning-on-quiet", "warning-text"];
62
+ declare const uiColorNames: readonly ["brand-border-loud", "brand-border-normal", "brand-border-quiet", "brand-fill-loud", "brand-fill-normal", "brand-fill-quiet", "brand-on-fill", "brand-on-loud", "brand-on-normal", "brand-on-quiet", "danger-border-loud", "danger-border-normal", "danger-border-quiet", "danger-fill-loud", "danger-fill-normal", "danger-fill-quiet", "danger-on-fill", "danger-on-loud", "danger-on-normal", "danger-on-quiet", "neutral-border-loud", "neutral-border-normal", "neutral-border-quiet", "neutral-fill-loud", "neutral-fill-normal", "neutral-fill-quiet", "neutral-on-loud", "neutral-on-normal", "neutral-on-quiet", "pop-border-loud", "pop-border-normal", "pop-border-quiet", "pop-fill-loud", "pop-fill-normal", "pop-fill-quiet", "pop-on-fill", "pop-on-loud", "pop-on-normal", "pop-on-quiet", "success-border-loud", "success-border-normal", "success-border-quiet", "success-fill-loud", "success-fill-normal", "success-fill-quiet", "success-on-fill", "success-on-loud", "success-on-normal", "success-on-quiet", "surface", "surface-lowered", "surface-raised", "text", "text-link", "text-quiet", "warning-border-loud", "warning-border-normal", "warning-border-quiet", "warning-fill-loud", "warning-fill-normal", "warning-fill-quiet", "warning-on-fill", "warning-on-loud", "warning-on-normal", "warning-on-quiet"];
64
63
  /** Names of the public `--kui-color-*` semantic tokens. */
65
64
  type UiColorName = (typeof uiColorNames)[number];
66
- /**
67
- * The semantic tokens that paint a foreground: the `*-on-*` roles, the text
68
- * roles, and their `*-text` compatibility aliases. The bare `success`,
69
- * `warning`, `danger`, `pop`, and `accent` aliases are quiet fills, not
70
- * foregrounds.
71
- */
72
- type UiForegroundColorName = Extract<UiColorName, `${string}-on-${string}` | `${string}-text` | 'text' | 'text-quiet' | 'text-link'>;
65
+ /** The semantic tokens that paint a foreground: the `*-on-*` and text roles. */
66
+ type UiForegroundColorName = Extract<UiColorName, `${string}-on-${string}` | 'text' | 'text-quiet' | 'text-link'>;
73
67
  /** Kerf UI's complete spacing-token vocabulary. `s` and `xl` are exceptions. */
74
68
  type UiSpaceName = 'none' | '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl';
75
69
  /** Create a complete pixel length. */
@@ -124,6 +118,7 @@ export { type CssColor, type CssFlex, type CssFlexBasis, type CssFlexKeyword, ty
124
118
 
125
119
  ```ts
126
120
  import { SafeHtml } from 'kerfjs';
121
+ import { CssLength } from './css-values.js';
127
122
 
128
123
  type DisclosureDirection = 'up' | 'down' | 'left' | 'right';
129
124
  interface DisclosureArrowProps {
@@ -132,11 +127,13 @@ interface DisclosureArrowProps {
132
127
  closedDirection?: DisclosureDirection;
133
128
  /** Replacement icons should use right as their unrotated orientation. */
134
129
  icon?: SafeHtml;
130
+ /** Typed box size for the square visual. Default: `remify(18px)`. */
131
+ size?: CssLength;
135
132
  className?: string;
136
133
  /** Native named-slot assignment when composed inside a web component. */
137
134
  slot?: string;
138
135
  }
139
- declare function DisclosureArrow({ open, openDirection, closedDirection, icon, className, slot, }: DisclosureArrowProps): SafeHtml;
136
+ declare function DisclosureArrow({ open, openDirection, closedDirection, icon, size, className, slot, }: DisclosureArrowProps): SafeHtml;
140
137
 
141
138
  export { DisclosureArrow, type DisclosureArrowProps, type DisclosureDirection };
142
139
  ```
@@ -145,23 +142,32 @@ export { DisclosureArrow, type DisclosureArrowProps, type DisclosureDirection };
145
142
 
146
143
  ```ts
147
144
  import * as kerfjs from 'kerfjs';
148
- import { D as DividerSides } from './divider-sides-BzB6rphT.js';
149
145
  import { PaneSeparatorSide } from './pane.js';
150
146
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
147
+ import { S as Sides } from './sides-BPSWde0A.js';
151
148
 
152
149
  interface ToolbarProps {
153
150
  leading?: KerfUiContent;
154
151
  center?: KerfUiContent;
155
152
  trailing?: KerfUiContent;
156
153
  label?: string;
157
- /** Physical divider edges in canonical top/right/bottom/left order. Defaults to bottom. */
158
- dividerSides?: DividerSides;
154
+ /**
155
+ * Physical divider edges in canonical top/right/bottom/left order, drawn
156
+ * always. Defaults to none: a toolbar pinned over or under scrolling content
157
+ * gets its divider from the scroll state instead — a `Pane` draws the line
158
+ * between its chrome and content while content is scrolled away beneath it,
159
+ * and `wireScrollDividers` `targets` can name a toolbar as chrome, which
160
+ * then draws its facing side the same way.
161
+ */
162
+ dividerSides?: Sides;
159
163
  /** Horizontal treatment of the center zone. Defaults to centered content. */
160
164
  centerAlign?: 'center' | 'stretch';
161
165
  /**
162
166
  * Component-owned responsive layout; applications choose the policy rather
163
167
  * than restyling toolbar internals. Under every policy the trailing zone
164
- * wraps its groups instead of clipping an action.
168
+ * wraps its groups instead of clipping an action, and the center zone keeps
169
+ * its whole content width: when the zones do not fit one row, the leading
170
+ * title truncates with an ellipsis rather than the center overlapping it.
165
171
  * - `none` keeps one row; the leading identity truncates first.
166
172
  * - `stack` stacks the zones at `responsiveAt`, wrapping stacked control
167
173
  * groups onto further rows.
@@ -186,9 +192,15 @@ interface ToolbarProps {
186
192
  /** Native named-slot assignment when composed inside a web component. */
187
193
  slot?: string;
188
194
  }
195
+ /**
196
+ * A toolbar's configuration, apart from its content: the props a composite
197
+ * that renders a `Toolbar` for the app (a Workbench or CollapsiblePanel
198
+ * toolbar) forwards, so the app configures that toolbar instead of styling it.
199
+ */
200
+ type ToolbarConfig = Pick<ToolbarProps, 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
189
201
  declare function Toolbar({ leading, center, trailing, label, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
190
202
 
191
- export { DividerSides, Toolbar, type ToolbarProps };
203
+ export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
192
204
  ```
193
205
 
194
206
  ## `@kerfjs/ui/toolbar-text`
@@ -219,6 +231,12 @@ interface ToolbarTextBaseProps {
219
231
  * instead. Default true.
220
232
  */
221
233
  ellipsis?: boolean;
234
+ /**
235
+ * Grow to fill the free space of the flex row it sits in (a Toolbar zone),
236
+ * truncating at the space left by its siblings instead of taking only its
237
+ * text's width. Default false.
238
+ */
239
+ fill?: boolean;
222
240
  /** Native named-slot assignment when composed inside a web component. */
223
241
  slot?: string;
224
242
  }
@@ -231,7 +249,7 @@ type ToolbarTextWrappingProps = {
231
249
  maxLines?: never;
232
250
  };
233
251
  type ToolbarTextProps = ToolbarTextBaseProps & ToolbarTextWrappingProps;
234
- declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, slot, }: ToolbarTextProps): kerfjs.SafeHtml;
252
+ declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, fill, slot, }: ToolbarTextProps): kerfjs.SafeHtml;
235
253
 
236
254
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
237
255
  ```
@@ -316,6 +334,7 @@ export { ToolbarActionLink, type ToolbarActionLinkProps, ToolbarControlGroup, ty
316
334
 
317
335
  ```ts
318
336
  import * as kerfjs from 'kerfjs';
337
+ import { CssLength } from './css-values.js';
319
338
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
320
339
 
321
340
  /** Where a {@link FloatingToolbar} floats within its positioned container. */
@@ -330,6 +349,13 @@ interface FloatingToolbarProps {
330
349
  * Default: `'bottom-end'`.
331
350
  */
332
351
  position?: FloatingToolbarPosition;
352
+ /**
353
+ * Distance from the container edges named by `position`. Default:
354
+ * `space('m')` (16px, 8px past a top toolbar's own inset). Omit it inside a
355
+ * `Workbench`, `CollapsiblePanel`, or `ResizableRegion` restore corner: the
356
+ * corner owns the inset there and sets it to zero.
357
+ */
358
+ inset?: CssLength;
333
359
  className?: string;
334
360
  /** Native named-slot assignment when composed inside a web component. */
335
361
  slot?: string;
@@ -339,14 +365,17 @@ interface FloatingToolbarProps {
339
365
  * ancestor — a transparent, forced-dark cluster of controls (e.g. a drawer
340
366
  * restore button) that sits over the content but NOT over dialogs or overlays
341
367
  * (it is not in the top layer). It is inset from the container edges by
342
- * `--kui-floating-toolbar-inset` (default `--kui-space-m`, i.e. 8px more than a
343
- * top toolbar's own inset); override that token, on the toolbar or an
344
- * ancestor, to move it. Inside a `Workbench`, `CollapsiblePanel`, or
368
+ * `inset` (default `--kui-space-m`, i.e. 8px more than a top toolbar's own
369
+ * inset); pass a typed length to move it. Inside a `Workbench`, `CollapsiblePanel`, or
345
370
  * `ResizableRegion` restore corner the corner owns the inset, so the toolbar
346
- * floats from the corner's own position. The app owns the controls and their
347
- * behavior — wire them with `delegate()` as usual.
371
+ * floats from the corner's own position. While one of those layouts has a
372
+ * side overlay open over the toolbar's region (a Workbench rail overlay, a
373
+ * `wireSidebar` compact overlay, an overlay `CollapsiblePanel` or horizontal
374
+ * `ResizableRegion`), the toolbar is hidden — unfocusable and out of the
375
+ * accessibility tree — until the overlay closes. The app owns the controls
376
+ * and their behavior — wire them with `delegate()` as usual.
348
377
  */
349
- declare function FloatingToolbar({ children, label, position, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
378
+ declare function FloatingToolbar({ children, label, position, inset, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
350
379
 
351
380
  export { FloatingToolbar, type FloatingToolbarPosition, type FloatingToolbarProps };
352
381
  ```
@@ -431,6 +460,7 @@ export { PopupMenu, type PopupMenuDivider, type PopupMenuEntry, type PopupMenuHe
431
460
 
432
461
  ```ts
433
462
  import { SafeHtml } from 'kerfjs';
463
+ import { HeadingLevel } from './toolbar-text.js';
434
464
 
435
465
  type ListHeaderRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
436
466
  'data-component'?: never;
@@ -471,6 +501,8 @@ interface ListHeaderBaseProps {
471
501
  type ListHeaderModeProps = {
472
502
  /** Render the title as a controlled disclosure trigger. */
473
503
  toggle: true;
504
+ /** A toggle's label is its button text, not a heading. */
505
+ headingLevel?: never;
474
506
  action: string;
475
507
  expanded: boolean;
476
508
  actionIcon?: SafeHtml;
@@ -480,6 +512,11 @@ type ListHeaderModeProps = {
480
512
  } | {
481
513
  /** Render a separately named trailing action. */
482
514
  toggle?: false;
515
+ /**
516
+ * Native heading level (`h1`–`h6`) of the label. Default `2`. Match the
517
+ * document outline; the visual treatment does not change.
518
+ */
519
+ headingLevel?: HeadingLevel;
483
520
  action: string;
484
521
  actionLabel: string;
485
522
  actionIcon: SafeHtml;
@@ -489,6 +526,11 @@ type ListHeaderModeProps = {
489
526
  } | {
490
527
  /** Render a passive section heading. */
491
528
  toggle?: false;
529
+ /**
530
+ * Native heading level (`h1`–`h6`) of the label. Default `2`. Match the
531
+ * document outline; the visual treatment does not change.
532
+ */
533
+ headingLevel?: HeadingLevel;
492
534
  action?: never;
493
535
  actionLabel?: never;
494
536
  actionIcon?: never;
@@ -513,7 +555,7 @@ type ListHeaderIndicatorProps = {
513
555
  status?: SafeHtml;
514
556
  };
515
557
  type ListHeaderProps = ListHeaderBaseProps & ListHeaderIndicatorProps & ListHeaderModeProps;
516
- declare function ListHeader({ label, count, countLabel, badge, status, density, divider, inline, width, indicatorTone, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes, slot, }: ListHeaderProps): SafeHtml;
558
+ declare function ListHeader({ label, headingLevel, count, countLabel, badge, status, density, divider, inline, width, indicatorTone, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes, slot, }: ListHeaderProps): SafeHtml;
517
559
 
518
560
  export { ListHeader, type ListHeaderProps };
519
561
  ```
@@ -523,10 +565,10 @@ export { ListHeader, type ListHeaderProps };
523
565
  ```ts
524
566
  import * as kerfjs from 'kerfjs';
525
567
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
526
- import { D as DividerSides, S as Sides } from './divider-sides-BzB6rphT.js';
527
568
  import { H as HorizontalAlignment, L as ListVerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
528
569
  export { V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
529
570
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
571
+ import { S as Sides } from './sides-BPSWde0A.js';
530
572
 
531
573
  type ListRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
532
574
  'data-component'?: never;
@@ -558,7 +600,7 @@ interface ListProps {
558
600
  /** Own vertical scrolling and overscroll containment. */
559
601
  scrollable?: boolean;
560
602
  /** Physical divider edges in canonical top/right/bottom/left order. */
561
- dividerSides?: DividerSides;
603
+ dividerSides?: Sides;
562
604
  /** Physical sides that receive the standard 17px text inset. */
563
605
  textInsets?: Sides;
564
606
  /** Physical sides that receive the standard 8px control inset. Text insets win on overlap. */
@@ -569,10 +611,17 @@ interface ListProps {
569
611
  /** Native named-slot assignment when composed inside a web component. */
570
612
  slot?: string;
571
613
  }
614
+ /**
615
+ * A list's configuration, apart from its content and styling hooks: the props a
616
+ * composite that renders a `List` for the app (the Workbench's `mainHeader` /
617
+ * `mainFooter` chrome) forwards, so the app configures that list instead of
618
+ * styling it. An omitted or `undefined` field keeps the composite's default.
619
+ */
620
+ type ListConfig = Pick<ListProps, 'gap' | 'hAlign' | 'vAlign' | 'dividerSides' | 'textInsets' | 'controlInsets'>;
572
621
  /** A stretch-aligned vertical stack with optional gap, flex, fill, scroll, and dividers. */
573
622
  declare function List({ children, gap, flex, fill, hAlign, vAlign, scrollable, dividerSides, textInsets, controlInsets, className, rootAttributes, slot, }: ListProps): kerfjs.SafeHtml;
574
623
 
575
- export { CssFlex, CssFlexKeyword, CssLength, DividerSides, HorizontalAlignment, List, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
624
+ export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, List, type ListConfig, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
576
625
  ```
577
626
 
578
627
  ## `@kerfjs/ui/list-action-row`
@@ -702,8 +751,8 @@ export { ListItem, type ListItemProps };
702
751
 
703
752
  ```ts
704
753
  import * as kerfjs from 'kerfjs';
705
- import { S as Sides } from './divider-sides-BzB6rphT.js';
706
754
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
755
+ import { S as Sides } from './sides-BPSWde0A.js';
707
756
 
708
757
  interface ListInsetControlProps {
709
758
  /** Control(s) that own their own border and padding (e.g. an input, a `wa-*`). */
@@ -729,8 +778,8 @@ export { ListInsetControl, type ListInsetControlProps, Sides };
729
778
 
730
779
  ```ts
731
780
  import * as kerfjs from 'kerfjs';
732
- import { S as Sides } from './divider-sides-BzB6rphT.js';
733
781
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
782
+ import { S as Sides } from './sides-BPSWde0A.js';
734
783
 
735
784
  type ListInsetTextRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
736
785
  'data-component'?: never;
@@ -741,13 +790,6 @@ interface ListInsetTextProps {
741
790
  children: KerfUiContent | string;
742
791
  /** Physical inset sides in canonical top/right/bottom/left order. Defaults to all sides. */
743
792
  sides?: Sides;
744
- /**
745
- * @deprecated Pass `sides="rl"` instead. Keep only the horizontal geometry (inline margin, left/right border, and
746
- * left/right padding) and drop the vertical margin, border, and padding. Use it
747
- * when the text edge must still align with bordered items but the line should not
748
- * add its own vertical box space — tight text layout inside a content region.
749
- */
750
- horizontalOnly?: boolean;
751
793
  className?: string;
752
794
  /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
753
795
  rootAttributes?: ListInsetTextRootAttributes;
@@ -759,14 +801,65 @@ interface ListInsetTextProps {
759
801
  * transparent border, and 8px padding — so a plain string lines up with
760
802
  * bordered `.kui-content` items (its text edge lands at the same 17px inset).
761
803
  * Use it for text elements that have no margin, border, or padding of their own.
762
- * Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box
804
+ * Pass `sides="rl"` to keep the horizontal inset but drop the vertical box
763
805
  * space for tight text layout.
764
806
  */
765
- declare function ListInsetText({ children, sides, horizontalOnly, className, rootAttributes, slot, }: ListInsetTextProps): kerfjs.SafeHtml;
807
+ declare function ListInsetText({ children, sides, className, rootAttributes, slot, }: ListInsetTextProps): kerfjs.SafeHtml;
766
808
 
767
809
  export { ListInsetText, type ListInsetTextProps, Sides };
768
810
  ```
769
811
 
812
+ ## `@kerfjs/ui/content-item`
813
+
814
+ ```ts
815
+ import * as kerfjs from 'kerfjs';
816
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
817
+
818
+ /** Whether the item's always-reserved 1px border is transparent or visible. */
819
+ type ContentItemFrame = 'none' | 'framed';
820
+ /** Corner shape: the 12px rounded rectangle or the 22px pill. */
821
+ type ContentItemShape = 'rounded' | 'pill';
822
+ type ContentItemRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
823
+ 'data-component'?: never;
824
+ }>;
825
+ interface ContentItemProps {
826
+ /** Item content; a plain string is allowed for bare copy. */
827
+ children?: KerfUiContent | string;
828
+ /**
829
+ * `framed` paints the standard neutral border in the 1px the item always
830
+ * reserves, so framing never changes geometry. Frame only an item that
831
+ * marks a real distinction. Defaults to `none` (transparent border).
832
+ */
833
+ frame?: ContentItemFrame;
834
+ /** Corner shape. Defaults to `rounded`. */
835
+ shape?: ContentItemShape;
836
+ /**
837
+ * Names the item as a distinct region (`role="region"`). Omit it for an
838
+ * ordinary item, which stays a non-landmark grouping.
839
+ */
840
+ ariaLabel?: string;
841
+ /**
842
+ * Makes the item a programmatic focus target (`tabindex="-1"`, never a tab
843
+ * stop), for example the preferred initial focus of a NavStack view when
844
+ * combined with `data-nav-focus` in `rootAttributes`.
845
+ */
846
+ focusTarget?: boolean;
847
+ className?: string;
848
+ /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
849
+ rootAttributes?: ContentItemRootAttributes;
850
+ /** Native named-slot assignment when composed inside a web component. */
851
+ slot?: string;
852
+ }
853
+ /**
854
+ * One self-contained `.kui-content` child: an 8px inline margin, a real 1px
855
+ * border (transparent unless `framed`), 8px padding, and a rounded or pill
856
+ * radius. It owns that whole geometry, so wrappers must not add more.
857
+ */
858
+ declare function ContentItem({ children, frame, shape, ariaLabel, focusTarget, className, rootAttributes, slot, }: ContentItemProps): kerfjs.SafeHtml;
859
+
860
+ export { ContentItem, type ContentItemFrame, type ContentItemProps, type ContentItemShape };
861
+ ```
862
+
770
863
  ## `@kerfjs/ui/value-table`
771
864
 
772
865
  ```ts
@@ -938,11 +1031,89 @@ declare function wireTabBars(root: HTMLElement | Document, { onReorder, activati
938
1031
  export { TabActivation, type TabDropPosition, type TabReorder, type TabReorderSource, type WireTabBarsOptions, reorderTabs, wireTabBars };
939
1032
  ```
940
1033
 
1034
+ ## `@kerfjs/ui/wire-scroll-dividers`
1035
+
1036
+ ```ts
1037
+ /**
1038
+ * An app-owned scroll arrangement outside a `Pane`: the `id` of the element
1039
+ * that scrolls and the `id`s of the pinned chrome on each physical side of it.
1040
+ * Each named chrome element shows its divider on the side facing the scroller
1041
+ * while content is scrolled away beyond that side. Ids are resolved below the
1042
+ * wired root on every refresh, so a re-render that replaces an element keeps
1043
+ * the pairing.
1044
+ */
1045
+ interface ScrollDividerTarget {
1046
+ /** The `id` of the scrolling element. */
1047
+ scroller: string;
1048
+ /** Chrome above the scroller: shows its bottom divider once scrolled down. */
1049
+ top?: string;
1050
+ /**
1051
+ * Chrome right of the scroller: shows its left divider while content is
1052
+ * hidden beyond the scroller's right edge (never when nothing overflows).
1053
+ */
1054
+ right?: string;
1055
+ /**
1056
+ * Chrome below the scroller: shows its top divider while content is hidden
1057
+ * beyond the scroller's bottom edge (never when nothing overflows).
1058
+ */
1059
+ bottom?: string;
1060
+ /** Chrome left of the scroller: shows its right divider once scrolled right. */
1061
+ left?: string;
1062
+ }
1063
+ interface WireScrollDividersOptions {
1064
+ /**
1065
+ * App-owned scroll arrangements to pair beyond the ones found by structure
1066
+ * (every `Pane`'s header and footer around its content, every `NavStack`'s
1067
+ * and `TabScaffold`'s chrome around its active region, and every `TabBar`
1068
+ * strip).
1069
+ */
1070
+ targets?: readonly ScrollDividerTarget[];
1071
+ }
1072
+ /**
1073
+ * Wire scroll dividers below `root`: a divider between pinned chrome and the
1074
+ * content that scrolls beside it shows only while content is scrolled away
1075
+ * from that edge. Near edges (top, left) hide at the scroll start; far edges
1076
+ * (bottom, right) hide at the scroll end and whenever nothing overflows.
1077
+ *
1078
+ * The wiring only reports scroll state; each component draws its own divider
1079
+ * from it. It writes `data-scroll-overflow` (the edges with hidden content, in
1080
+ * canonical `t`/`r`/`b`/`l` order) on each scroller, and `data-scroll-divider`
1081
+ * (the sides to draw) on each paired chrome element:
1082
+ *
1083
+ * - every `Pane` with a header or footer: its header shows a bottom divider and
1084
+ * its footer a top divider (drawn by the Pane, per its `chromeDividers`);
1085
+ * - every `NavStack`'s top chrome and bottom toolbar around its active view,
1086
+ * and every `TabScaffold`'s bar under its active scene: the chrome shows a
1087
+ * bottom (top chrome) or top (bottom toolbar, bar) divider. The scroller is
1088
+ * whichever element actually scrolls there: the view or scene itself, or,
1089
+ * through a sole child with no chrome of its own on that edge, a `Pane`'s
1090
+ * content or a nested `NavStack` / `TabScaffold` region (a Pane's own header
1091
+ * or footer draws that boundary instead);
1092
+ * - every `TabBar` strip: the bar draws a divider on each side of the strip
1093
+ * whose tabs are scrolled out of view;
1094
+ * - each app-owned `targets` pairing: a `Toolbar` or `List` named as chrome
1095
+ * draws the divider on its facing side.
1096
+ *
1097
+ * Structure is re-read after every DOM change below root (a re-render that
1098
+ * drops the attributes gets them back before paint), scroll is tracked with
1099
+ * one capturing listener, and size changes of each scroller and its children
1100
+ * with a `ResizeObserver`. Returns a disposer that removes every attribute it
1101
+ * wrote. See `docs/23-app-layouts.md` §3.7.
1102
+ */
1103
+ declare function wireScrollDividers(root: HTMLElement | Document, { targets }?: WireScrollDividersOptions): () => void;
1104
+
1105
+ export { type ScrollDividerTarget, type WireScrollDividersOptions, wireScrollDividers };
1106
+ ```
1107
+
941
1108
  ## `@kerfjs/ui/nav-stack`
942
1109
 
943
1110
  ```ts
944
1111
  import * as kerfjs from 'kerfjs';
945
1112
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1113
+ import { ToolbarConfig } from './toolbar.js';
1114
+ import { ToolbarTextSize, HeadingLevel } from './toolbar-text.js';
1115
+ import './pane.js';
1116
+ import './sides-BPSWde0A.js';
946
1117
 
947
1118
  /**
948
1119
  * One entry in a {@link NavStack}. The app owns the stack as an array (usually a
@@ -954,23 +1125,62 @@ interface NavStackView {
954
1125
  content: KerfUiContent;
955
1126
  /** Title shown in the top toolbar for this view. */
956
1127
  title?: string;
1128
+ /** Leading groups for this view's top toolbar, after the back control and before the title. */
1129
+ leading?: KerfUiContent;
1130
+ /** Center content for this view's top toolbar (placed per `toolbarConfig.centerAlign`). */
1131
+ center?: KerfUiContent;
957
1132
  /** Trailing actions for this view's top toolbar. */
958
1133
  toolbar?: KerfUiContent;
959
1134
  /** Bottom toolbar for this view. Cross-fades with the top chrome on navigation. */
960
1135
  bottomToolbar?: KerfUiContent;
961
1136
  }
1137
+ /**
1138
+ * The top toolbar's configuration. Its `ToolbarConfig` forwards to the real
1139
+ * `Toolbar` the stack renders; by default that toolbar draws no divider and
1140
+ * claims the top and side safe-area edges the stack still touches.
1141
+ */
1142
+ interface NavStackToolbarConfig extends ToolbarConfig {
1143
+ /** Accessible name of the top toolbar (default: none). */
1144
+ label?: string;
1145
+ /** Size of the view title's `ToolbarText` (default `large`). */
1146
+ titleSize?: ToolbarTextSize;
1147
+ /** Expose the view title as a heading at this level (default: a plain span). */
1148
+ headingLevel?: HeadingLevel;
1149
+ }
962
1150
  interface NavStackProps {
963
1151
  id: string;
964
1152
  /** Accessible name for the stack region. */
965
1153
  label: string;
966
1154
  /** The stack, root first; the last entry is the active top view. */
967
1155
  views: NavStackView[];
968
- /** Accessible label for the back control (default "Back"). */
1156
+ /** Accessible label for the icon-only back control (default "Back"). */
969
1157
  backLabel?: string;
1158
+ /** The back control's icon (default a chevron-left `LucideIcon`). */
1159
+ backIcon?: KerfUiContent;
1160
+ /**
1161
+ * Visible text beside the back icon, such as the previous view's title
1162
+ * (default: icon only). When set, the text names the control and
1163
+ * `backLabel` is not used.
1164
+ */
1165
+ backText?: string;
1166
+ /** The top toolbar's configuration, forwarded to its `Toolbar`. */
1167
+ toolbarConfig?: NavStackToolbarConfig;
970
1168
  /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */
971
1169
  hideToolbar?: boolean;
972
1170
  /** Optional persistent bottom toolbar used when the active view does not provide one. */
973
1171
  bottomToolbar?: KerfUiContent;
1172
+ /**
1173
+ * The line under the top chrome and over the bottom toolbar, where they
1174
+ * meet the active view. `scroll` (default) shows the chrome's line only
1175
+ * while the view's content is scrolled beneath it, and the bottom
1176
+ * toolbar's only while more content lies below — never when the content
1177
+ * fits — once `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is
1178
+ * wired above the stack; unwired, neither shows. `always` shows both
1179
+ * without the wiring; `none` neither, even when wired. The line is drawn
1180
+ * inside the chrome, so no state moves the chrome or the content. A
1181
+ * `toolbarConfig.dividerSides` edge is the Toolbar's own and is unaffected.
1182
+ */
1183
+ chromeDividers?: 'scroll' | 'always' | 'none';
974
1184
  className?: string;
975
1185
  /** Native named-slot assignment when composed inside a web component. */
976
1186
  slot?: string;
@@ -978,12 +1188,14 @@ interface NavStackProps {
978
1188
  /**
979
1189
  * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last
980
1190
  * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and
981
- * cross-fades the chrome across a change. A single-pane layout is a `NavStack`
982
- * with one entry. See `docs/23-app-layouts.md` §3.1.
1191
+ * cross-fades the chrome across a change. Its top chrome is a real `Toolbar`: the
1192
+ * back control and title lead, the active view's `leading` / `center` / `toolbar`
1193
+ * content fills the zones, and `toolbarConfig` configures it. A single-pane
1194
+ * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.
983
1195
  */
984
- declare function NavStack({ id, label, views, backLabel, hideToolbar, bottomToolbar, className, slot, }: NavStackProps): kerfjs.SafeHtml;
1196
+ declare function NavStack({ id, label, views, backLabel, backIcon, backText, toolbarConfig, hideToolbar, bottomToolbar, chromeDividers, className, slot, }: NavStackProps): kerfjs.SafeHtml;
985
1197
 
986
- export { NavStack, type NavStackProps, type NavStackView };
1198
+ export { NavStack, type NavStackProps, type NavStackToolbarConfig, type NavStackView };
987
1199
  ```
988
1200
 
989
1201
  ## `@kerfjs/ui/wire-nav-stack`
@@ -1013,13 +1225,39 @@ export { type WireNavStackOptions, wireNavStack };
1013
1225
 
1014
1226
  ```ts
1015
1227
  import * as kerfjs from 'kerfjs';
1228
+ import { NavStackProps, NavStackView } from './nav-stack.js';
1229
+ import { ResizableRegionProps } from './resizable-region.js';
1016
1230
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1231
+ import './toolbar.js';
1232
+ import './pane.js';
1233
+ import './sides-BPSWde0A.js';
1234
+ import './toolbar-text.js';
1017
1235
 
1018
- interface SplitViewResizable {
1236
+ /**
1237
+ * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /
1238
+ * `max` limits, plus the region configuration that forwards unchanged
1239
+ * (`separator`, `handleIcon`, `contentOverflow`, and collapse:
1240
+ * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,
1241
+ * `restorePosition`). Omitted options keep the region's defaults.
1242
+ */
1243
+ interface SplitViewResizable extends Pick<ResizableRegionProps, 'separator' | 'handleIcon' | 'contentOverflow' | 'collapsed' | 'transitioning' | 'collapseMotion' | 'restoreControl' | 'restorePosition'> {
1019
1244
  size: number;
1020
1245
  min: number;
1021
1246
  max: number;
1022
1247
  }
1248
+ /** One compact view's top- and bottom-toolbar content (see `NavStackView`). */
1249
+ type SplitViewCompactViewToolbars = Pick<NavStackView, 'leading' | 'center' | 'toolbar' | 'bottomToolbar'>;
1250
+ /**
1251
+ * The compact `NavStack`'s configuration: its toolbar configuration, back
1252
+ * control, persistent bottom toolbar, and chrome dividers forward to the
1253
+ * stack, and `list` / `detail` give each view its own toolbar groups.
1254
+ */
1255
+ interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar' | 'chromeDividers'> {
1256
+ /** Toolbar content for the list (root) view. */
1257
+ list?: SplitViewCompactViewToolbars;
1258
+ /** Toolbar content for the pushed detail view. */
1259
+ detail?: SplitViewCompactViewToolbars;
1260
+ }
1023
1261
  interface SplitViewProps {
1024
1262
  id: string;
1025
1263
  label: string;
@@ -1041,6 +1279,8 @@ interface SplitViewProps {
1041
1279
  detailTitle?: string;
1042
1280
  /** Back label for the compact NavStack (default "Back"). */
1043
1281
  backLabel?: string;
1282
+ /** Compact NavStack configuration and per-view toolbars. */
1283
+ compactStack?: SplitViewCompactStack;
1044
1284
  /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */
1045
1285
  resizable?: SplitViewResizable;
1046
1286
  className?: string;
@@ -1054,9 +1294,9 @@ interface SplitViewProps {
1054
1294
  * resizable wiring with `wireResizableRegions` and the compact back with
1055
1295
  * `wireNavStack`.
1056
1296
  */
1057
- declare function SplitView({ id, label, list, detail, compact, detailActive, listTitle, detailTitle, backLabel, resizable, className, slot, }: SplitViewProps): kerfjs.SafeHtml;
1297
+ declare function SplitView({ id, label, list, detail, compact, detailActive, listTitle, detailTitle, backLabel, compactStack, resizable, className, slot, }: SplitViewProps): kerfjs.SafeHtml;
1058
1298
 
1059
- export { SplitView, type SplitViewProps, type SplitViewResizable };
1299
+ export { SplitView, type SplitViewCompactStack, type SplitViewCompactViewToolbars, type SplitViewProps, type SplitViewResizable };
1060
1300
  ```
1061
1301
 
1062
1302
  ## `@kerfjs/ui/pane`
@@ -1084,7 +1324,17 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
1084
1324
  'data-safe-area-block-end'?: never;
1085
1325
  'data-safe-area-inline-start'?: never;
1086
1326
  'data-safe-area-inline-end'?: never;
1327
+ 'data-chrome-placement'?: never;
1328
+ 'data-chrome-dividers'?: never;
1087
1329
  }>;
1330
+ /** How a Pane's header and footer relate to its scrolling content. */
1331
+ type PaneChromePlacement = 'fixed' | 'auto';
1332
+ /**
1333
+ * When a Pane draws the divider between its pinned header or footer and its
1334
+ * scrolling content: `scroll` while content is scrolled away beneath that
1335
+ * chrome, as `wireScrollDividers` reports; `always`; or `none`.
1336
+ */
1337
+ type PaneChromeDividers = 'scroll' | 'always' | 'none';
1088
1338
  interface PaneProps {
1089
1339
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
1090
1340
  header?: KerfUiContent;
@@ -1092,6 +1342,24 @@ interface PaneProps {
1092
1342
  children?: KerfUiContent;
1093
1343
  /** Optional fixed chrome below the scrolling content. */
1094
1344
  footer?: KerfUiContent;
1345
+ /**
1346
+ * Whether the header and footer stay pinned around the scrolling content.
1347
+ * `fixed` (default) always pins them. `auto` pins them while the pane is
1348
+ * tall enough, and below 480px of height (30rem, so it scales with the text
1349
+ * size) lets the whole pane scroll as one column, so tall chrome can never
1350
+ * squeeze the content to nothing.
1351
+ */
1352
+ chromePlacement?: PaneChromePlacement;
1353
+ /**
1354
+ * The divider under the header and over the footer, where they meet the
1355
+ * scrolling content. `scroll` (default) shows the header's divider only
1356
+ * while the content is scrolled down, and the footer's only while more
1357
+ * content lies below — never when the content fits — once
1358
+ * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above
1359
+ * the pane; unwired, neither shows. `always` shows both; `none` neither.
1360
+ * The line is drawn inside the chrome, so no state moves the content.
1361
+ */
1362
+ chromeDividers?: PaneChromeDividers;
1095
1363
  /** Root semantics. Defaults to `div`. */
1096
1364
  element?: PaneElement;
1097
1365
  /** Scrolling content semantics. Defaults to `div`. */
@@ -1120,29 +1388,39 @@ interface PaneProps {
1120
1388
  /** Native named-slot assignment when composed inside a web component. */
1121
1389
  slot?: string;
1122
1390
  }
1391
+ /**
1392
+ * A pane's configuration, apart from its content and styling hooks: the props a
1393
+ * composite that renders a `Pane` for the app (a Workbench panel or work area,
1394
+ * or a CollapsiblePanel) forwards, so the app configures that pane instead of
1395
+ * styling it. An omitted or `undefined` field keeps the composite's default.
1396
+ */
1397
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers'>;
1123
1398
  /**
1124
1399
  * An unpadded application column with optional fixed header/footer slots and one
1125
1400
  * scrolling vertical content owner. Separator lines are independently opt-in on
1126
1401
  * each logical edge, so the same component works as a sidebar, main area,
1127
1402
  * inspector, or dialog column.
1128
1403
  */
1129
- declare function Pane({ header, children, footer, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1404
+ declare function Pane({ header, children, footer, chromePlacement, chromeDividers, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1130
1405
 
1131
- export { Pane, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1406
+ export { Pane, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1132
1407
  ```
1133
1408
 
1134
1409
  ## `@kerfjs/ui/workbench`
1135
1410
 
1136
1411
  ```ts
1137
1412
  import { SafeHtml } from 'kerfjs';
1413
+ import { ListConfig } from './list.js';
1414
+ import { PaneConfig } from './pane.js';
1138
1415
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1139
1416
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1140
- import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BFQxFITu.js';
1141
- import { ToolbarProps } from './toolbar.js';
1417
+ import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BN4x0rth.js';
1418
+ import { ToolbarConfig } from './toolbar.js';
1419
+ import './css-values.js';
1420
+ import './flex-alignment-4ms8ZbV8.js';
1421
+ import './sides-BPSWde0A.js';
1142
1422
  import './lucide-icon.js';
1143
1423
  import 'lucide';
1144
- import './divider-sides-BzB6rphT.js';
1145
- import './pane.js';
1146
1424
 
1147
1425
  /** The standard toggle a Workbench renders for a panel (see {@link PanelToggle}). */
1148
1426
  type WorkbenchPanelToggle = PanelToggle;
@@ -1155,8 +1433,13 @@ type WorkbenchPanelToggle = PanelToggle;
1155
1433
  * `FloatingToolbar` in the work area's bottom-end corner.
1156
1434
  */
1157
1435
  type WorkbenchPanelToolbar = PanelToolbar;
1158
- /** The work area's top toolbar; collapsed rails add their groups to it. */
1159
- interface WorkbenchMainToolbar {
1436
+ /**
1437
+ * The work area's top toolbar; collapsed rails add their groups to it. Its
1438
+ * configuration forwards to its `Toolbar`. It draws no divider of its own by
1439
+ * default: the work area's `Pane` draws one under its header chrome, wherever
1440
+ * that chrome ends, while `main` is scrolled (`mainPane.chromeDividers`).
1441
+ */
1442
+ interface WorkbenchMainToolbar extends ToolbarConfig {
1160
1443
  label: string;
1161
1444
  /** The work area's title, usually an extra-large `ToolbarText`. */
1162
1445
  title?: KerfUiContent;
@@ -1165,26 +1448,27 @@ interface WorkbenchMainToolbar {
1165
1448
  center?: KerfUiContent;
1166
1449
  /** Groups at the trailing edge, before a collapsed right rail's groups. */
1167
1450
  trailing?: KerfUiContent;
1168
- /** The toolbar's narrow-width policy (see `Toolbar.responsive`). */
1169
- responsive?: ToolbarProps['responsive'];
1170
- responsiveAt?: ToolbarProps['responsiveAt'];
1171
1451
  }
1172
- /** The work area's bottom toolbar; a collapsed drawer adds its groups to it. */
1173
- interface WorkbenchMainBottomToolbar {
1452
+ /**
1453
+ * The work area's bottom toolbar; a collapsed drawer adds its groups to it.
1454
+ * Its configuration forwards to its `Toolbar`. It draws no divider of its own
1455
+ * by default: the work area's `Pane` draws one over its footer chrome while
1456
+ * more of `main` lies below (`mainPane.chromeDividers`).
1457
+ */
1458
+ interface WorkbenchMainBottomToolbar extends ToolbarConfig {
1174
1459
  label: string;
1175
1460
  leading?: KerfUiContent;
1461
+ center?: KerfUiContent;
1176
1462
  trailing?: KerfUiContent;
1177
1463
  }
1178
1464
  /**
1179
- * The work area: the app's `main` under `mainToolbar` (and above
1180
- * `mainBottomToolbar`), with each collapsed panel's groups added to the
1181
- * toolbar on its side. Without either toolbar, `main` renders as given.
1465
+ * Whether the work area's header or footer chrome stays pinned (`fixed`),
1466
+ * scrolls away with the content (`scroll`), or stays pinned while the work
1467
+ * area is tall enough and scrolls with the content when it is short (`auto`,
1468
+ * the Pane's `chromePlacement="auto"`; it applies to the pinned header and
1469
+ * footer together).
1182
1470
  */
1183
- /**
1184
- * Whether the work area's header or footer chrome stays pinned (`fixed`) or
1185
- * scrolls away with the content (`scroll`).
1186
- */
1187
- type WorkbenchChromePlacement = 'fixed' | 'scroll';
1471
+ type WorkbenchChromePlacement = 'fixed' | 'scroll' | 'auto';
1188
1472
 
1189
1473
  /**
1190
1474
  * The Workbench container breakpoint below which a panel presents as an
@@ -1217,6 +1501,14 @@ interface WorkbenchPanel {
1217
1501
  toolbar?: WorkbenchPanelToolbar;
1218
1502
  /** Optional bottom toolbar under a `toolbar` panel's content. */
1219
1503
  footer?: KerfUiContent;
1504
+ /**
1505
+ * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1506
+ * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
1507
+ * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1508
+ * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1509
+ * without a `toolbar`, where `content` renders as given.
1510
+ */
1511
+ pane?: PaneConfig;
1220
1512
  /** Whether the panel is currently collapsed (the app owns this). */
1221
1513
  collapsed?: boolean;
1222
1514
  /**
@@ -1294,13 +1586,34 @@ interface WorkbenchProps {
1294
1586
  */
1295
1587
  mainBottomToolbar?: WorkbenchMainBottomToolbar;
1296
1588
  /**
1297
- * Whether `mainToolbar` and `mainHeader` stay pinned (`fixed`, default) or
1589
+ * Whether `mainToolbar` and `mainHeader` stay pinned (`fixed`, default),
1298
1590
  * scroll away with `main` (`scroll`) — useful where large text would leave
1299
- * pinned chrome little room.
1591
+ * pinned chrome little room — or stay pinned while the work area is tall
1592
+ * enough and scroll with `main` when it is short (`auto`).
1300
1593
  */
1301
1594
  mainHeaderPlacement?: WorkbenchChromePlacement;
1302
1595
  /** The same for `mainFooter` and `mainBottomToolbar` (default `fixed`). */
1303
1596
  mainFooterPlacement?: WorkbenchChromePlacement;
1597
+ /**
1598
+ * Configuration for the work area's `Pane` (`contentElement`,
1599
+ * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`), which it has whenever it
1600
+ * has a toolbar, `mainHeader`, or `mainFooter`; without that chrome, `main`
1601
+ * renders as given and this is ignored. Omitted or `undefined` fields keep
1602
+ * the `Pane` defaults.
1603
+ */
1604
+ mainPane?: PaneConfig;
1605
+ /**
1606
+ * Configuration for the `List` that holds `mainHeader` (`gap`, `hAlign`,
1607
+ * `vAlign`, `dividerSides`, `textInsets`, `controlInsets`). Omitted or
1608
+ * `undefined` fields keep the defaults (no divider: the work area's
1609
+ * `Pane` draws the line under its header chrome).
1610
+ */
1611
+ mainHeaderList?: ListConfig;
1612
+ /**
1613
+ * The same for the `List` that holds `mainFooter` (no divider by default:
1614
+ * the work area's `Pane` draws the line over its footer chrome).
1615
+ */
1616
+ mainFooterList?: ListConfig;
1304
1617
  leftRail?: WorkbenchPanel;
1305
1618
  rightRail?: WorkbenchPanel;
1306
1619
  bottomDrawer?: WorkbenchPanel;
@@ -1337,7 +1650,7 @@ interface WorkbenchProps {
1337
1650
  * lives outside it and stays reachable). A panel may opt in to drag and keyboard resizing with
1338
1651
  * `resizable`, which `wireWorkbench` drives. See `docs/23-app-layouts.md` §3.3.
1339
1652
  */
1340
- declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1653
+ declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1341
1654
 
1342
1655
  export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
1343
1656
  ```
@@ -1460,12 +1773,15 @@ export { type WireWorkbenchOptions, type WireWorkbenchPanel, type WorkbenchPanel
1460
1773
 
1461
1774
  ```ts
1462
1775
  import { SafeHtml } from 'kerfjs';
1463
- import { P as PanelSide, a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BFQxFITu.js';
1464
- export { c as collapsiblePanelToggleIcon } from './panel-toolbar-BFQxFITu.js';
1776
+ import { PaneConfig } from './pane.js';
1777
+ import { P as PanelSide, a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BN4x0rth.js';
1778
+ export { c as collapsiblePanelToggleIcon } from './panel-toolbar-BN4x0rth.js';
1465
1779
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1466
1780
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1467
1781
  import './lucide-icon.js';
1468
1782
  import 'lucide';
1783
+ import './toolbar.js';
1784
+ import './sides-BPSWde0A.js';
1469
1785
 
1470
1786
  /** Which edge a {@link CollapsiblePanel} docks to. */
1471
1787
  type CollapsiblePanelSide = PanelSide;
@@ -1523,6 +1839,14 @@ interface CollapsiblePanelProps {
1523
1839
  toolbar?: CollapsiblePanelToolbar;
1524
1840
  /** Optional bottom toolbar under a `toolbar` panel's content. */
1525
1841
  footer?: KerfUiContent;
1842
+ /**
1843
+ * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1844
+ * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
1845
+ * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1846
+ * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1847
+ * without a `toolbar`, where `children` renders as given.
1848
+ */
1849
+ pane?: PaneConfig;
1526
1850
  separator?: ResizableRegionSeparator;
1527
1851
  collapseMotion?: ResizableRegionCollapseMotion;
1528
1852
  contentOverflow?: ResizableRegionContentOverflow;
@@ -1548,7 +1872,7 @@ interface CollapsiblePanelProps {
1548
1872
  * and persistence semantics, and with `CollapsiblePanelToggle` for the standard
1549
1873
  * affordance. See `ui/docs/collapsible-panel.md` and `docs/23-app-layouts.md`.
1550
1874
  */
1551
- declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, footer, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1875
+ declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, footer, pane, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1552
1876
  interface CollapsiblePanelRelocatedProps {
1553
1877
  /** The panel's `id`. */
1554
1878
  panelId: string;
@@ -1645,7 +1969,7 @@ export { type SidebarStorage, type WireSidebarOptions, type WireSidebarPanel, wi
1645
1969
  import { SafeHtml } from 'kerfjs';
1646
1970
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1647
1971
 
1648
- interface TabScaffoldTab<Id extends string = string> {
1972
+ interface TabScaffoldTabBase<Id extends string> {
1649
1973
  id: Id;
1650
1974
  label: string;
1651
1975
  /** Decorative icon shown above the label in the bottom bar. */
@@ -1653,6 +1977,40 @@ interface TabScaffoldTab<Id extends string = string> {
1653
1977
  /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
1654
1978
  content: KerfUiContent;
1655
1979
  }
1980
+ /** A tab with an optional count or short-status badge. */
1981
+ interface TabScaffoldTabCountBadge {
1982
+ /**
1983
+ * Optional count or short status shown as a solid danger `Badge` at the
1984
+ * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,
1985
+ * or non-finite numbers render no badge. The visual badge is `aria-hidden`;
1986
+ * its meaning reaches assistive technology through `badgeLabel`.
1987
+ *
1988
+ * Pass `true` instead for the text-free dot (new content without a count).
1989
+ */
1990
+ badge?: string | number;
1991
+ /**
1992
+ * Localized phrase folded into the tab's accessible name as
1993
+ * `"<label>, <badgeLabel>"` (for example `"3 unread"` → `"Inbox, 3 unread"`).
1994
+ * Defaults to the badge text itself. Ignored when no badge renders.
1995
+ */
1996
+ badgeLabel?: string;
1997
+ }
1998
+ /** A tab with the text-free dot badge (new content without a count). */
1999
+ interface TabScaffoldTabDotBadge {
2000
+ /**
2001
+ * `true` shows a solid danger dot `Badge` at the top-trailing corner of the
2002
+ * tab icon — the iOS tab-bar dot for new content without a count.
2003
+ */
2004
+ badge: true;
2005
+ /**
2006
+ * Required localized phrase folded into the tab's accessible name as
2007
+ * `"<label>, <badgeLabel>"` (for example `"New activity"` →
2008
+ * `"Feed, New activity"`). A dot has no text, so this is its only meaning.
2009
+ */
2010
+ badgeLabel: string;
2011
+ }
2012
+ /** One bottom-bar destination: its label, optional icon and badge, and content. */
2013
+ type TabScaffoldTab<Id extends string = string> = TabScaffoldTabBase<Id> & (TabScaffoldTabCountBadge | TabScaffoldTabDotBadge);
1656
2014
  interface TabScaffoldProps<Id extends string = string> {
1657
2015
  id: string;
1658
2016
  /** Accessible name for the tab bar. */
@@ -1660,6 +2018,16 @@ interface TabScaffoldProps<Id extends string = string> {
1660
2018
  tabs: readonly TabScaffoldTab<Id>[];
1661
2019
  /** The controlled active tab id (the app owns selection). */
1662
2020
  active: NoInfer<Id>;
2021
+ /**
2022
+ * The line over the tab bar, where it meets the active scene. `scroll`
2023
+ * (default) shows it only while more of the scene's content lies below —
2024
+ * never at the scroll end or when the content fits — once
2025
+ * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above
2026
+ * the scaffold; unwired, it does not show. `always` shows it without the
2027
+ * wiring; `none` never, even when wired. The line is the bar's own 1px top
2028
+ * border, so no state moves the bar or a tab.
2029
+ */
2030
+ chromeDividers?: 'scroll' | 'always' | 'none';
1663
2031
  className?: string;
1664
2032
  /** Native named-slot assignment when composed inside a web component. */
1665
2033
  slot?: string;
@@ -1672,7 +2040,7 @@ interface TabScaffoldProps<Id extends string = string> {
1672
2040
  * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
1673
2041
  * a bottom bar. See `docs/23-app-layouts.md` §3.4.
1674
2042
  */
1675
- declare function TabScaffold<Id extends string>({ id, label, tabs, active, className, slot, }: TabScaffoldProps<Id>): SafeHtml;
2043
+ declare function TabScaffold<Id extends string>({ id, label, tabs, active, chromeDividers, className, slot, }: TabScaffoldProps<Id>): SafeHtml;
1676
2044
 
1677
2045
  export { TabScaffold, type TabScaffoldProps, type TabScaffoldTab };
1678
2046
  ```
@@ -1838,9 +2206,20 @@ export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type Dev
1838
2206
  ```ts
1839
2207
  import * as kerfjs from 'kerfjs';
1840
2208
  import { SafeHtml } from 'kerfjs';
1841
- import { a as CatalogProps } from './types-D6vzj-VT.js';
1842
- export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-D6vzj-VT.js';
2209
+ import { a as CatalogProps } from './types-BuHELdXR.js';
2210
+ export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-BuHELdXR.js';
1843
2211
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2212
+ import './toolbar.js';
2213
+ import './pane.js';
2214
+ import './sides-BPSWde0A.js';
2215
+ import './workbench.js';
2216
+ import './list.js';
2217
+ import './css-values.js';
2218
+ import './flex-alignment-4ms8ZbV8.js';
2219
+ import './resizable-region.js';
2220
+ import './panel-toolbar-BN4x0rth.js';
2221
+ import './lucide-icon.js';
2222
+ import 'lucide';
1844
2223
 
1845
2224
  /**
1846
2225
  * Controlled, stateless component-catalog shell: a `Workbench` whose left rail
@@ -1849,7 +2228,7 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1849
2228
  * standard toggle moves into the entry toolbar while it is collapsed, and on
1850
2229
  * a small screen the sidebar overlays the stage like any Workbench rail.
1851
2230
  */
1852
- declare function Catalog({ id, brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, headerPlacement, footerPlacement, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2231
+ declare function Catalog({ id, brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
1853
2232
 
1854
2233
  /** How a specimen aligns its visible edge with its `ListHeader` label. */
1855
2234
  type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';
@@ -1920,9 +2299,20 @@ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleP
1920
2299
  ## `@kerfjs/ui/catalog-resources`
1921
2300
 
1922
2301
  ```ts
1923
- import { C as CatalogResource } from './types-D6vzj-VT.js';
2302
+ import { C as CatalogResource } from './types-BuHELdXR.js';
1924
2303
  import './semantic-content-BbzjvSu9.js';
1925
2304
  import 'kerfjs';
2305
+ import './toolbar.js';
2306
+ import './pane.js';
2307
+ import './sides-BPSWde0A.js';
2308
+ import './workbench.js';
2309
+ import './list.js';
2310
+ import './css-values.js';
2311
+ import './flex-alignment-4ms8ZbV8.js';
2312
+ import './resizable-region.js';
2313
+ import './panel-toolbar-BN4x0rth.js';
2314
+ import './lucide-icon.js';
2315
+ import 'lucide';
1926
2316
 
1927
2317
  /**
1928
2318
  * Standard resource labels for a Kerf catalog detail footer. Keep these labels
@@ -1990,6 +2380,17 @@ interface WireCatalogOptions {
1990
2380
  * open overlay closes it.
1991
2381
  */
1992
2382
  collapsed?: Signal<boolean>;
2383
+ /**
2384
+ * The app-owned sidebar width signal for a Catalog rendered with
2385
+ * `sidebar={{ resizable: true, size: sidebarSize.value }}`. Each committed
2386
+ * drag or keyboard resize is written to it.
2387
+ */
2388
+ sidebarSize?: Signal<number>;
2389
+ /**
2390
+ * With `sidebarSize`, load and save the width under this storage key so the
2391
+ * catalog remembers the user's sidebar width.
2392
+ */
2393
+ sidebarStorageKey?: string;
1993
2394
  /** The Catalog's `id`, when it is not the default `kui-catalog`. */
1994
2395
  id?: string;
1995
2396
  }
@@ -2024,9 +2425,11 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
2024
2425
  * item selection (and the related-entry popup menu), the sidebar collapse toggle, and
2025
2426
  * the theme toggle. The app owns the `active`/`collapsed`/`theme` signals and updates
2026
2427
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
2027
- * Returns a disposer.
2428
+ * It also wires the scroll dividers below root (`wireScrollDividers`), so the
2429
+ * catalog's panes and every example in it show their chrome dividers only
2430
+ * while scrolled. Returns a disposer.
2028
2431
  */
2029
- declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, id: catalogId, }: WireCatalogOptions): () => void;
2432
+ declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
2030
2433
 
2031
2434
  export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog, wireCatalogGeometryOverlay };
2032
2435
  ```
@@ -2075,6 +2478,7 @@ export { SegmentedControl, type SegmentedControlAppearance, type SegmentedContro
2075
2478
  import { SafeHtml } from 'kerfjs';
2076
2479
  import { CssForegroundColor } from './css-values.js';
2077
2480
  import { LucideNode } from './lucide-icon.js';
2481
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2078
2482
  import 'lucide';
2079
2483
 
2080
2484
  interface SelectChoice<Value extends string = string> {
@@ -2086,7 +2490,8 @@ interface SelectChoice<Value extends string = string> {
2086
2490
  * Foreground color for the optional icon: a semantic foreground token such
2087
2491
  * as `uiColor('success-on-quiet')`, or an application-owned
2088
2492
  * `foregroundColorVar('--app-icon-color')`. Fill tokens such as
2089
- * `uiColor('success')` are pale background tints and do not type-check.
2493
+ * `uiColor('success-fill-quiet')` are pale background tints and do not
2494
+ * type-check.
2090
2495
  */
2091
2496
  color?: CssForegroundColor;
2092
2497
  group?: string;
@@ -2110,7 +2515,6 @@ type SelectSelectedPresentation = 'label' | 'icon-only';
2110
2515
  type SelectFocusRingOwner = 'select' | 'group';
2111
2516
  interface SelectBaseProps<Value extends string = string> {
2112
2517
  name: string;
2113
- value: NoInfer<Value>;
2114
2518
  choices: readonly SelectChoice<Value>[];
2115
2519
  className?: string;
2116
2520
  /** Empty-value hint text shown in the closed control (the native select placeholder). */
@@ -2119,14 +2523,11 @@ interface SelectBaseProps<Value extends string = string> {
2119
2523
  hint?: string;
2120
2524
  disabled?: boolean;
2121
2525
  fitMenu?: boolean;
2122
- renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
2123
2526
  /** Render as an unanimated loading skeleton: the label above a static, empty control box. */
2124
2527
  placeholder?: boolean;
2125
2528
  /** Form (default), borderless toolbar, or intrinsic navigation chrome. */
2126
2529
  presentation?: SelectPresentation;
2127
2530
  size?: SelectSize;
2128
- /** Show only the selected choice icon while retaining the Select's accessible name. */
2129
- selectedPresentation?: SelectSelectedPresentation;
2130
2531
  /** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
2131
2532
  focusRingOwner?: SelectFocusRingOwner;
2132
2533
  /** Maximum closed-control label width in CSS pixels before ellipsis. */
@@ -2134,10 +2535,50 @@ interface SelectBaseProps<Value extends string = string> {
2134
2535
  /** Native named-slot assignment when composed inside a web component. */
2135
2536
  slot?: string;
2136
2537
  }
2137
- type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName;
2138
- declare function Select<Value extends string>({ name, value, label, ariaLabel, choices, className, placeholderText, hint, disabled, fitMenu, renderSelected, placeholder, presentation, size, selectedPresentation, focusRingOwner, labelMaxWidth, slot, }: SelectProps<Value>): SafeHtml;
2538
+ /** One chosen value (the default). */
2539
+ interface SelectSingleValueProps<Value extends string = string> {
2540
+ multiple?: false;
2541
+ value: NoInfer<Value>;
2542
+ renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
2543
+ /** Show only the selected choice icon while retaining the Select's accessible name. */
2544
+ selectedPresentation?: SelectSelectedPresentation;
2545
+ triggerIcon?: never;
2546
+ }
2547
+ /**
2548
+ * Any number of chosen values. The popup stays open while the person toggles
2549
+ * choices and closes on an outside click, Escape, or focus leaving; the closed
2550
+ * control summarizes the chosen labels in choice order.
2551
+ */
2552
+ interface SelectMultipleLabelProps<Value extends string = string> {
2553
+ multiple: true;
2554
+ value: readonly NoInfer<Value>[];
2555
+ renderSelected?: never;
2556
+ selectedPresentation?: 'label';
2557
+ triggerIcon?: never;
2558
+ }
2559
+ /**
2560
+ * A multiple Select drawn as an icon-only toolbar trigger, such as a
2561
+ * "Filter by label" funnel. No single choice is selected, so the trigger shows
2562
+ * a fixed `triggerIcon` naming the menu's purpose; while any choice is chosen
2563
+ * a count badge sits beside it, and the combobox's accessible name ends with
2564
+ * the chosen labels in choice order.
2565
+ */
2566
+ interface SelectMultipleIconProps<Value extends string = string> {
2567
+ multiple: true;
2568
+ value: readonly NoInfer<Value>[];
2569
+ renderSelected?: never;
2570
+ selectedPresentation: 'icon-only';
2571
+ /**
2572
+ * The trigger's fixed icon, typically a `LucideIcon` naming the menu's
2573
+ * purpose (a funnel for a filter), independent of the selection.
2574
+ */
2575
+ triggerIcon: KerfUiContent;
2576
+ }
2577
+ type SelectMultipleValueProps<Value extends string = string> = SelectMultipleLabelProps<Value> | SelectMultipleIconProps<Value>;
2578
+ type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName & (SelectSingleValueProps<Value> | SelectMultipleValueProps<Value>);
2579
+ declare function Select<Value extends string>(props: SelectProps<Value>): SafeHtml;
2139
2580
 
2140
- export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSize };
2581
+ export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectMultipleIconProps, type SelectMultipleLabelProps, type SelectMultipleValueProps, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSingleValueProps, type SelectSize };
2141
2582
  ```
2142
2583
 
2143
2584
  ## `@kerfjs/ui/state-banner`
@@ -2272,7 +2713,7 @@ export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
2272
2713
  ## `@kerfjs/ui/token-search-field`
2273
2714
 
2274
2715
  ```ts
2275
- import * as kerfjs from 'kerfjs';
2716
+ import { SafeHtml } from 'kerfjs';
2276
2717
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2277
2718
 
2278
2719
  interface TokenSearchToken {
@@ -2315,6 +2756,8 @@ interface TokenSearchFieldBaseProps {
2315
2756
  removeAction?: string;
2316
2757
  clearAction?: string;
2317
2758
  clearLabel?: string;
2759
+ /** Icon for the clear button. Default: the Lucide `x` glyph token chips also use. */
2760
+ clearIcon?: SafeHtml;
2318
2761
  className?: string;
2319
2762
  editorAttributes?: TokenSearchEditorAttributes;
2320
2763
  /** Native named-slot assignment when composed inside a web component. */
@@ -2338,7 +2781,7 @@ interface TokenSearchFieldValue {
2338
2781
  query: string;
2339
2782
  tokens: TokenSearchToken[];
2340
2783
  }
2341
- declare function TokenSearchField({ id, label, query, tokens, revision, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, slot, }: TokenSearchFieldProps): kerfjs.SafeHtml;
2784
+ declare function TokenSearchField({ id, label, query, tokens, revision, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, clearIcon, className, editorAttributes, slot, }: TokenSearchFieldProps): SafeHtml;
2342
2785
  /** Read editable text and ordered token offsets from a rendered TokenSearchField editor. */
2343
2786
  declare function readTokenSearchField(editor: HTMLElement, knownTokens?: readonly TokenSearchToken[]): TokenSearchFieldValue;
2344
2787
  /** Focus an editor and place its caret at a text offset, skipping atomic token chips. */
@@ -2548,10 +2991,17 @@ import { SafeHtml } from 'kerfjs';
2548
2991
  type BadgeTone = 'neutral' | 'brand' | 'pop' | 'success' | 'warning' | 'danger';
2549
2992
  type BadgeAppearance = 'quiet' | 'solid' | 'outline';
2550
2993
  type BadgeShape = 'pill' | 'rounded';
2994
+ /** Size of a text badge. A text-free dot is the separate `size: 'dot'` form. */
2551
2995
  type BadgeSize = 'compact' | 'default';
2552
- interface BadgeProps {
2553
- children: SafeHtml | string | number;
2996
+ interface BadgeCommonProps {
2554
2997
  tone?: BadgeTone;
2998
+ className?: string;
2999
+ /** Native named-slot assignment when composed inside a web component. */
3000
+ slot?: string;
3001
+ }
3002
+ /** A badge that shows a short status, count, or category as visible text. */
3003
+ interface BadgeTextProps extends BadgeCommonProps {
3004
+ children: SafeHtml | string | number;
2555
3005
  appearance?: BadgeAppearance;
2556
3006
  shape?: BadgeShape;
2557
3007
  size?: BadgeSize;
@@ -2559,14 +3009,35 @@ interface BadgeProps {
2559
3009
  label?: string;
2560
3010
  /** Hide a repeated visual badge from assistive technology. */
2561
3011
  ariaHidden?: boolean;
2562
- className?: string;
2563
- /** Native named-slot assignment when composed inside a web component. */
2564
- slot?: string;
2565
3012
  }
3013
+ /** A labeled dot, announced as an image with its own accessible name. */
3014
+ interface BadgeDotLabeled {
3015
+ /** Accessible name for the dot, for example `"New activity"`. */
3016
+ label: string;
3017
+ ariaHidden?: false;
3018
+ }
3019
+ /** A decorative dot whose meaning the owning component already announces. */
3020
+ interface BadgeDotDecorative {
3021
+ label?: never;
3022
+ ariaHidden: true;
3023
+ }
3024
+ /**
3025
+ * A text-free status dot (the iOS "new content" dot): a small solid circle in
3026
+ * the badge's tone. It has no visible text, so it must either carry its own
3027
+ * accessible `label` (exposed as an image) or be `ariaHidden` because the
3028
+ * surrounding component already folds its meaning into an accessible name.
3029
+ */
3030
+ type BadgeDotProps = BadgeCommonProps & {
3031
+ size: 'dot';
3032
+ children?: never;
3033
+ appearance?: never;
3034
+ shape?: never;
3035
+ } & (BadgeDotLabeled | BadgeDotDecorative);
3036
+ type BadgeProps = BadgeTextProps | BadgeDotProps;
2566
3037
  /** Compact, non-interactive metadata whose tone, emphasis, and shape are configured by props. */
2567
- declare function Badge({ children, tone, appearance, shape, size, label, ariaHidden, className, slot, }: BadgeProps): SafeHtml;
3038
+ declare function Badge(props: BadgeProps): SafeHtml;
2568
3039
 
2569
- export { Badge, type BadgeAppearance, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTone };
3040
+ export { Badge, type BadgeAppearance, type BadgeDotProps, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTextProps, type BadgeTone };
2570
3041
  ```
2571
3042
 
2572
3043
  ## `@kerfjs/ui/lucide-icon`
@@ -2668,9 +3139,9 @@ export { Text, type TextBorder, type TextContent, type TextFont, type TextProps,
2668
3139
  ```ts
2669
3140
  import * as kerfjs from 'kerfjs';
2670
3141
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
2671
- import { S as Sides } from './divider-sides-BzB6rphT.js';
2672
3142
  import { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
2673
3143
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3144
+ import { S as Sides } from './sides-BPSWde0A.js';
2674
3145
 
2675
3146
  type RowRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
2676
3147
  'data-component'?: never;