@kerfjs/ui 5.0.0-beta.54 → 5.0.0-beta.56

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 (274) hide show
  1. package/README.md +14 -11
  2. package/ai/compile-time-contracts-v1.json +2 -2
  3. package/ai/component-catalog-v2.json +206 -39
  4. package/ai/component-catalog.json +306 -58
  5. package/ai/public-api-signatures-v1.md +671 -92
  6. package/ai/skill.md +43 -38
  7. package/ai/webawesome-jsx-signatures-v1.md +8 -2
  8. package/dist/app-tab.js +1 -1
  9. package/dist/badge.d.ts +35 -7
  10. package/dist/badge.js +1 -1
  11. package/dist/browser/content-item.js +3 -0
  12. package/dist/browser/popup-menu.js +3 -0
  13. package/dist/browser/select.js +1 -0
  14. package/dist/catalog-resources.d.ts +12 -1
  15. package/dist/catalog.d.ts +21 -4
  16. package/dist/catalog.js +260 -308
  17. package/dist/catalog.js.map +1 -1
  18. package/dist/{chunk-7IUSV4XG.js → chunk-24PHKUR3.js} +2 -2
  19. package/dist/chunk-24PHKUR3.js.map +1 -0
  20. package/dist/{chunk-WZ2GLEY4.js → chunk-2G2ZJQYK.js} +2 -14
  21. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  22. package/dist/{chunk-D7GWXIAS.js → chunk-5I7QGQVT.js} +1 -1
  23. package/dist/chunk-5I7QGQVT.js.map +1 -0
  24. package/dist/{chunk-HJKRCKDR.js → chunk-63ZWBGE3.js} +6 -3
  25. package/dist/chunk-63ZWBGE3.js.map +1 -0
  26. package/dist/{chunk-44IG7PFV.js → chunk-6CINWX2E.js} +3 -3
  27. package/dist/{chunk-44IG7PFV.js.map → chunk-6CINWX2E.js.map} +1 -1
  28. package/dist/{chunk-C2FAYFDE.js → chunk-AGXQQFKZ.js} +2 -2
  29. package/dist/{chunk-C2FAYFDE.js.map → chunk-AGXQQFKZ.js.map} +1 -1
  30. package/dist/{chunk-ATHXW6RP.js → chunk-AHEG27M7.js} +2 -2
  31. package/dist/{chunk-ATHXW6RP.js.map → chunk-AHEG27M7.js.map} +1 -1
  32. package/dist/{chunk-7GUQYHKA.js → chunk-AK67F6QN.js} +4 -1
  33. package/dist/chunk-AK67F6QN.js.map +1 -0
  34. package/dist/chunk-BFPBS5Y4.js +250 -0
  35. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  36. package/dist/chunk-DG6G5EPF.js +35 -0
  37. package/dist/chunk-DG6G5EPF.js.map +1 -0
  38. package/dist/{chunk-MTM43SJO.js → chunk-G33XC2NB.js} +1 -1
  39. package/dist/chunk-G33XC2NB.js.map +1 -0
  40. package/dist/{chunk-TZ5IHWB2.js → chunk-K6UNVKDK.js} +3 -3
  41. package/dist/{chunk-TZ5IHWB2.js.map → chunk-K6UNVKDK.js.map} +1 -1
  42. package/dist/chunk-KH6VUGHU.js +399 -0
  43. package/dist/chunk-KH6VUGHU.js.map +1 -0
  44. package/dist/{chunk-HMQ2ZDGG.js → chunk-KROD7KZK.js} +3 -2
  45. package/dist/chunk-KROD7KZK.js.map +1 -0
  46. package/dist/{chunk-5NDQABWK.js → chunk-M7QV3IHH.js} +3 -1
  47. package/dist/chunk-M7QV3IHH.js.map +1 -0
  48. package/dist/{chunk-RNZAKSME.js → chunk-MA6Z6EIM.js} +3 -3
  49. package/dist/{chunk-RNZAKSME.js.map → chunk-MA6Z6EIM.js.map} +1 -1
  50. package/dist/chunk-MA73TA6D.js +42 -0
  51. package/dist/chunk-MA73TA6D.js.map +1 -0
  52. package/dist/{chunk-ZMBU522F.js → chunk-MEY33VWB.js} +2 -2
  53. package/dist/{chunk-ZMBU522F.js.map → chunk-MEY33VWB.js.map} +1 -1
  54. package/dist/{chunk-T22EM4ET.js → chunk-MOBRFZH3.js} +81 -31
  55. package/dist/chunk-MOBRFZH3.js.map +1 -0
  56. package/dist/chunk-MP2GDBQZ.js +50 -0
  57. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  58. package/dist/{chunk-3NBL3OUQ.js → chunk-NAPE7WUS.js} +2 -2
  59. package/dist/chunk-NAPE7WUS.js.map +1 -0
  60. package/dist/{chunk-CMUIXJZM.js → chunk-NBYTIVHS.js} +2 -2
  61. package/dist/{chunk-CMUIXJZM.js.map → chunk-NBYTIVHS.js.map} +1 -1
  62. package/dist/chunk-O3EXIBEZ.js +114 -0
  63. package/dist/chunk-O3EXIBEZ.js.map +1 -0
  64. package/dist/{chunk-KPNTVB7A.js → chunk-PK4N5QTO.js} +8 -7
  65. package/dist/chunk-PK4N5QTO.js.map +1 -0
  66. package/dist/chunk-QQOTQTDD.js +415 -0
  67. package/dist/chunk-QQOTQTDD.js.map +1 -0
  68. package/dist/{chunk-BJJKFVWW.js → chunk-T4UZTNZ4.js} +5 -5
  69. package/dist/chunk-T4UZTNZ4.js.map +1 -0
  70. package/dist/chunk-V65EOWNF.js +83 -0
  71. package/dist/chunk-V65EOWNF.js.map +1 -0
  72. package/dist/{chunk-GUIHMIT2.js → chunk-VNPQDCQZ.js} +3 -3
  73. package/dist/{chunk-GUIHMIT2.js.map → chunk-VNPQDCQZ.js.map} +1 -1
  74. package/dist/{chunk-5I22LMCV.js → chunk-VZOFZPSO.js} +2 -2
  75. package/dist/chunk-VZOFZPSO.js.map +1 -0
  76. package/dist/chunk-WLG6SSNT.js +94 -0
  77. package/dist/chunk-WLG6SSNT.js.map +1 -0
  78. package/dist/{chunk-NE5JAOQS.js → chunk-WOUF7YXM.js} +3 -3
  79. package/dist/{chunk-NE5JAOQS.js.map → chunk-WOUF7YXM.js.map} +1 -1
  80. package/dist/collapsible-panel.d.ts +51 -13
  81. package/dist/collapsible-panel.js +38 -10
  82. package/dist/collapsible-panel.js.map +1 -1
  83. package/dist/content-item.d.ts +46 -0
  84. package/dist/content-item.js +4 -0
  85. package/dist/content-item.js.map +1 -0
  86. package/dist/css-values.d.ts +5 -11
  87. package/dist/css-values.js +1 -1
  88. package/dist/disclosure-arrow.d.ts +4 -1
  89. package/dist/disclosure-arrow.js +1 -1
  90. package/dist/floating-toolbar.d.ts +17 -6
  91. package/dist/floating-toolbar.js +1 -1
  92. package/dist/grid.js +1 -1
  93. package/dist/help-tags-register.d.ts +13 -0
  94. package/dist/help-tags-register.js +9 -0
  95. package/dist/help-tags-register.js.map +1 -0
  96. package/dist/index.d.ts +7 -5
  97. package/dist/index.js +31 -29
  98. package/dist/list-action-row.js +1 -1
  99. package/dist/list-header.d.ts +14 -1
  100. package/dist/list-header.js +1 -1
  101. package/dist/list-inset-control.d.ts +1 -1
  102. package/dist/list-inset-control.js +1 -1
  103. package/dist/list-inset-text.d.ts +9 -10
  104. package/dist/list-inset-text.js +2 -1
  105. package/dist/list-item.js +1 -1
  106. package/dist/list.d.ts +10 -3
  107. package/dist/list.js +1 -1
  108. package/dist/nav-stack.d.ts +38 -5
  109. package/dist/nav-stack.js +4 -1
  110. package/dist/pane.d.ts +20 -2
  111. package/dist/pane.js +1 -1
  112. package/dist/panel-toolbar-C8sF-YZC.d.ts +63 -0
  113. package/dist/popup-menu-register.d.ts +9 -0
  114. package/dist/popup-menu-register.js +31 -0
  115. package/dist/popup-menu-register.js.map +1 -0
  116. package/dist/popup-menu.d.ts +71 -0
  117. package/dist/popup-menu.js +3 -0
  118. package/dist/popup-menu.js.map +1 -0
  119. package/dist/row.d.ts +1 -1
  120. package/dist/row.js +1 -1
  121. package/dist/select-register.js +70 -3
  122. package/dist/select-register.js.map +1 -1
  123. package/dist/select.d.ts +46 -8
  124. package/dist/select.js +2 -1
  125. package/dist/{divider-sides-BzB6rphT.d.ts → sides-BPSWde0A.d.ts} +1 -3
  126. package/dist/skeleton.js +1 -1
  127. package/dist/spacer.js +1 -1
  128. package/dist/split-view.d.ts +31 -3
  129. package/dist/split-view.js +33 -5
  130. package/dist/split-view.js.map +1 -1
  131. package/dist/state-banner.js +1 -1
  132. package/dist/styles/badge.css +13 -0
  133. package/dist/styles/catalog/components/catalog-example.css +1 -17
  134. package/dist/styles/catalog/components/catalog-stage.css +9 -14
  135. package/dist/styles/catalog/components/catalog.css +8 -18
  136. package/dist/styles/catalog.css +0 -5
  137. package/dist/styles/collapsible-panel.css +192 -39
  138. package/dist/styles/content-item.css +30 -0
  139. package/dist/styles/floating-toolbar.css +5 -0
  140. package/dist/styles/foundation.css +28 -19
  141. package/dist/styles/layout.css +1 -21
  142. package/dist/styles/list-action-row.css +13 -1
  143. package/dist/styles/list-inset-text.css +1 -2
  144. package/dist/styles/list-item.css +14 -1
  145. package/dist/styles/list.css +1 -1
  146. package/dist/styles/nav-stack.css +29 -64
  147. package/dist/styles/pane.css +33 -1
  148. package/dist/styles/popup-menu.css +90 -0
  149. package/dist/styles/resizable-region.css +53 -10
  150. package/dist/styles/select.css +39 -12
  151. package/dist/styles/split-view.css +21 -25
  152. package/dist/styles/state-banner.css +13 -4
  153. package/dist/styles/styles.css +1 -0
  154. package/dist/styles/tab-bar.css +31 -3
  155. package/dist/styles/tab-scaffold.css +36 -14
  156. package/dist/styles/text.css +1 -1
  157. package/dist/styles/token-search-field.css +4 -4
  158. package/dist/styles/toolbar-control-group.css +44 -12
  159. package/dist/styles/toolbar.css +57 -7
  160. package/dist/styles/value-table.css +19 -2
  161. package/dist/styles/webawesome.css +3 -1
  162. package/dist/styles/workbench.css +165 -31
  163. package/dist/tab-scaffold.d.ts +35 -1
  164. package/dist/tab-scaffold.js +50 -16
  165. package/dist/tab-scaffold.js.map +1 -1
  166. package/dist/text.js +1 -1
  167. package/dist/token-search-field.d.ts +13 -2
  168. package/dist/token-search-field.js +1 -1
  169. package/dist/toolbar-text.js +1 -1
  170. package/dist/toolbar.d.ts +12 -4
  171. package/dist/toolbar.js +1 -1
  172. package/dist/{types-CEsieBZi.d.ts → types-DXAGogOS.d.ts} +48 -0
  173. package/dist/value-table.js +1 -1
  174. package/dist/webawesome.d.ts +7 -1
  175. package/dist/wire-catalog.d.ts +24 -1
  176. package/dist/wire-catalog.js +26 -3
  177. package/dist/wire-catalog.js.map +1 -1
  178. package/dist/wire-sidebar.js +6 -3
  179. package/dist/wire-sidebar.js.map +1 -1
  180. package/dist/wire-token-search-fields.js +1 -1
  181. package/dist/wire-workbench.js +1 -350
  182. package/dist/wire-workbench.js.map +1 -1
  183. package/dist/workbench.d.ts +144 -6
  184. package/dist/workbench.js +11 -208
  185. package/dist/workbench.js.map +1 -1
  186. package/docs/accessibility.md +126 -6
  187. package/docs/app-layouts.md +9 -7
  188. package/docs/catalog.md +41 -9
  189. package/docs/collapsible-panel.md +79 -5
  190. package/docs/component-contract.md +38 -12
  191. package/docs/component-selection.md +64 -55
  192. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  193. package/docs/design/templates/empty-state/with-action.svg +1 -1
  194. package/docs/design/templates/empty-state-dark.svg +1 -1
  195. package/docs/design/templates/empty-state.svg +1 -1
  196. package/docs/design/templates/list/compact-dark.svg +1 -1
  197. package/docs/design/templates/list/compact.svg +1 -1
  198. package/docs/design/templates/list/stack-dark.svg +1 -1
  199. package/docs/design/templates/list/stack.svg +1 -1
  200. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  201. package/docs/design/templates/list-action-row/default.svg +1 -1
  202. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  203. package/docs/design/templates/list-action-row/selected.svg +1 -1
  204. package/docs/design/templates/list-action-row-dark.svg +1 -1
  205. package/docs/design/templates/list-action-row.svg +1 -1
  206. package/docs/design/templates/list-dark.svg +1 -1
  207. package/docs/design/templates/list-item/default-dark.svg +1 -1
  208. package/docs/design/templates/list-item/default.svg +1 -1
  209. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  210. package/docs/design/templates/list-item/selected.svg +1 -1
  211. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  212. package/docs/design/templates/list-item/trailing.svg +1 -1
  213. package/docs/design/templates/list-item-dark.svg +1 -1
  214. package/docs/design/templates/list-item.svg +1 -1
  215. package/docs/design/templates/list.svg +1 -1
  216. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  217. package/docs/design/templates/state-banner/danger.svg +1 -1
  218. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  219. package/docs/design/templates/state-banner/info.svg +1 -1
  220. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  221. package/docs/design/templates/state-banner/success.svg +1 -1
  222. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  223. package/docs/design/templates/state-banner/warning.svg +1 -1
  224. package/docs/design/templates/state-banner-dark.svg +1 -1
  225. package/docs/design/templates/state-banner.svg +1 -1
  226. package/docs/design/templates/value-table/details-dark.svg +1 -1
  227. package/docs/design/templates/value-table/details.svg +1 -1
  228. package/docs/design/templates/value-table-dark.svg +1 -1
  229. package/docs/design/templates/value-table.svg +1 -1
  230. package/docs/design-philosophy.md +1 -1
  231. package/docs/examples/command-palette-adapter.tsx +3 -2
  232. package/docs/layout.md +74 -29
  233. package/docs/nav-stack.md +45 -1
  234. package/docs/recipes.md +48 -40
  235. package/docs/split-view.md +46 -2
  236. package/docs/surface-scaffold.md +1 -1
  237. package/docs/tab-scaffold.md +50 -1
  238. package/docs/type-contracts.md +17 -17
  239. package/docs/ux-demo.md +8 -4
  240. package/docs/webawesome-theme.md +1 -2
  241. package/docs/workbench.md +131 -10
  242. package/llms.txt +38 -9
  243. package/package.json +24 -2
  244. package/ux-demo/recipes/app-shell.tsx +141 -223
  245. package/ux-demo/recipes/collapsible-sidebar.tsx +47 -77
  246. package/ux-demo/recipes/list-detail-dialog.tsx +150 -54
  247. package/ux-demo/recipes/mount-recipe.ts +0 -5
  248. package/ux-demo/recipes/navigation-sidebar.tsx +3 -2
  249. package/ux-demo/recipes/navigation-stack.tsx +3 -2
  250. package/ux-demo/recipes/types.ts +0 -1
  251. package/dist/chunk-3NBL3OUQ.js.map +0 -1
  252. package/dist/chunk-5I22LMCV.js.map +0 -1
  253. package/dist/chunk-5NDQABWK.js.map +0 -1
  254. package/dist/chunk-7GUQYHKA.js.map +0 -1
  255. package/dist/chunk-7IUSV4XG.js.map +0 -1
  256. package/dist/chunk-BJJKFVWW.js.map +0 -1
  257. package/dist/chunk-D7GWXIAS.js.map +0 -1
  258. package/dist/chunk-DQA5FMOX.js +0 -85
  259. package/dist/chunk-DQA5FMOX.js.map +0 -1
  260. package/dist/chunk-HJKRCKDR.js.map +0 -1
  261. package/dist/chunk-HMQ2ZDGG.js.map +0 -1
  262. package/dist/chunk-KPNTVB7A.js.map +0 -1
  263. package/dist/chunk-MTM43SJO.js.map +0 -1
  264. package/dist/chunk-T22EM4ET.js.map +0 -1
  265. package/dist/chunk-WZ2GLEY4.js.map +0 -1
  266. package/dist/chunk-XD7DWYXG.js +0 -34
  267. package/dist/chunk-XD7DWYXG.js.map +0 -1
  268. package/dist/chunk-ZK5EGVFP.js +0 -27
  269. package/dist/chunk-ZK5EGVFP.js.map +0 -1
  270. package/dist/styles/catalog/components/catalog-detail.css +0 -35
  271. package/dist/styles/catalog/components/catalog-resource-footer.css +0 -37
  272. package/dist/styles/catalog/components/catalog-secondary-sections.css +0 -38
  273. package/dist/styles/catalog/components/catalog-section-list.css +0 -22
  274. package/dist/styles/catalog/components/catalog-sidebar.css +0 -82
@@ -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.54` and `kerfjs@5.0.0-beta.54`. 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.56` and `kerfjs@5.0.0-beta.56`. 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,9 +142,9 @@ 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;
@@ -155,13 +152,15 @@ interface ToolbarProps {
155
152
  trailing?: KerfUiContent;
156
153
  label?: string;
157
154
  /** Physical divider edges in canonical top/right/bottom/left order. Defaults to bottom. */
158
- dividerSides?: DividerSides;
155
+ dividerSides?: Sides;
159
156
  /** Horizontal treatment of the center zone. Defaults to centered content. */
160
157
  centerAlign?: 'center' | 'stretch';
161
158
  /**
162
159
  * Component-owned responsive layout; applications choose the policy rather
163
160
  * than restyling toolbar internals. Under every policy the trailing zone
164
- * wraps its groups instead of clipping an action.
161
+ * wraps its groups instead of clipping an action, and the center zone keeps
162
+ * its whole content width: when the zones do not fit one row, the leading
163
+ * title truncates with an ellipsis rather than the center overlapping it.
165
164
  * - `none` keeps one row; the leading identity truncates first.
166
165
  * - `stack` stacks the zones at `responsiveAt`, wrapping stacked control
167
166
  * groups onto further rows.
@@ -186,9 +185,15 @@ interface ToolbarProps {
186
185
  /** Native named-slot assignment when composed inside a web component. */
187
186
  slot?: string;
188
187
  }
188
+ /**
189
+ * A toolbar's configuration, apart from its content: the props a composite
190
+ * that renders a `Toolbar` for the app (a Workbench or CollapsiblePanel
191
+ * toolbar) forwards, so the app configures that toolbar instead of styling it.
192
+ */
193
+ type ToolbarConfig = Pick<ToolbarProps, 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
189
194
  declare function Toolbar({ leading, center, trailing, label, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
190
195
 
191
- export { DividerSides, Toolbar, type ToolbarProps };
196
+ export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
192
197
  ```
193
198
 
194
199
  ## `@kerfjs/ui/toolbar-text`
@@ -316,6 +321,7 @@ export { ToolbarActionLink, type ToolbarActionLinkProps, ToolbarControlGroup, ty
316
321
 
317
322
  ```ts
318
323
  import * as kerfjs from 'kerfjs';
324
+ import { CssLength } from './css-values.js';
319
325
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
320
326
 
321
327
  /** Where a {@link FloatingToolbar} floats within its positioned container. */
@@ -330,6 +336,13 @@ interface FloatingToolbarProps {
330
336
  * Default: `'bottom-end'`.
331
337
  */
332
338
  position?: FloatingToolbarPosition;
339
+ /**
340
+ * Distance from the container edges named by `position`. Default:
341
+ * `space('m')` (16px, 8px past a top toolbar's own inset). Omit it inside a
342
+ * `Workbench`, `CollapsiblePanel`, or `ResizableRegion` restore corner: the
343
+ * corner owns the inset there and sets it to zero.
344
+ */
345
+ inset?: CssLength;
333
346
  className?: string;
334
347
  /** Native named-slot assignment when composed inside a web component. */
335
348
  slot?: string;
@@ -339,22 +352,102 @@ interface FloatingToolbarProps {
339
352
  * ancestor — a transparent, forced-dark cluster of controls (e.g. a drawer
340
353
  * restore button) that sits over the content but NOT over dialogs or overlays
341
354
  * (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
355
+ * `inset` (default `--kui-space-m`, i.e. 8px more than a top toolbar's own
356
+ * inset); pass a typed length to move it. Inside a `Workbench`, `CollapsiblePanel`, or
345
357
  * `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.
358
+ * floats from the corner's own position. While one of those layouts has a
359
+ * side overlay open over the toolbar's region (a Workbench rail overlay, a
360
+ * `wireSidebar` compact overlay, an overlay `CollapsiblePanel` or horizontal
361
+ * `ResizableRegion`), the toolbar is hidden — unfocusable and out of the
362
+ * accessibility tree — until the overlay closes. The app owns the controls
363
+ * and their behavior — wire them with `delegate()` as usual.
348
364
  */
349
- declare function FloatingToolbar({ children, label, position, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
365
+ declare function FloatingToolbar({ children, label, position, inset, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
350
366
 
351
367
  export { FloatingToolbar, type FloatingToolbarPosition, type FloatingToolbarProps };
352
368
  ```
353
369
 
370
+ ## `@kerfjs/ui/popup-menu`
371
+
372
+ ```ts
373
+ import { SafeHtml } from 'kerfjs';
374
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
375
+
376
+ type PopupMenuPlacement = 'bottom-start' | 'bottom' | 'bottom-end' | 'top-start' | 'top' | 'top-end';
377
+ type PopupMenuDataAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
378
+ 'data-action'?: never;
379
+ 'data-component'?: never;
380
+ 'data-key'?: never;
381
+ 'data-morph-skip-children'?: never;
382
+ }>;
383
+ /** One command in the menu. */
384
+ interface PopupMenuItem {
385
+ kind?: 'item';
386
+ label: string;
387
+ /** Delegated `data-action` the app handles when the item is chosen. */
388
+ action?: string;
389
+ /** Native `wa-dropdown-item` value, reported by its `wa-select` event. */
390
+ value?: string;
391
+ /** Leading icon, typically a `LucideIcon`; it is placed in the item's icon slot. */
392
+ icon?: SafeHtml;
393
+ disabled?: boolean;
394
+ /** Application `data-*` metadata such as a record id. */
395
+ attributes?: PopupMenuDataAttributes;
396
+ }
397
+ /** A labeled group heading; items that follow it belong to the group. */
398
+ interface PopupMenuHeading {
399
+ kind: 'heading';
400
+ label: string;
401
+ }
402
+ /** A separator between groups of items. */
403
+ interface PopupMenuDivider {
404
+ kind: 'divider';
405
+ }
406
+ type PopupMenuEntry = PopupMenuItem | PopupMenuHeading | PopupMenuDivider;
407
+ type PopupMenuTriggerName = {
408
+ /** Visible trigger text, which is also its accessible name. */
409
+ text: string;
410
+ label?: never;
411
+ } | {
412
+ text?: never;
413
+ /**
414
+ * Accessible name of an icon-only trigger, rendered as visually hidden
415
+ * slotted text (a Web Awesome button takes its name from its content).
416
+ */
417
+ label: string;
418
+ };
419
+ type PopupMenuProps = PopupMenuTriggerName & {
420
+ /** Trigger icon, typically a `LucideIcon`, before any visible text. */
421
+ icon?: KerfUiContent;
422
+ items: readonly PopupMenuEntry[];
423
+ /** Where the menu opens relative to its trigger. Defaults to `bottom-start`. */
424
+ placement?: PopupMenuPlacement;
425
+ /** Show the disclosure caret after the trigger content. Defaults to true. */
426
+ caret?: boolean;
427
+ disabled?: boolean;
428
+ /** Application `data-*` metadata on the menu root. */
429
+ rootAttributes?: PopupMenuDataAttributes;
430
+ /** Native named-slot assignment when composed inside a web component. */
431
+ slot?: string;
432
+ };
433
+ /**
434
+ * An action menu: a trigger button that opens a list of commands. Renders the
435
+ * `wa-dropdown` root directly, so a `single` `ToolbarControlGroup` (with
436
+ * `nestedDropdown`) or a `PopupSurface` sizes and insets it as usual. Items
437
+ * dispatch through delegated `data-action`s; the app owns the commands and any
438
+ * open-state reaction. Import `@kerfjs/ui/popup-menu/register` once to register
439
+ * the Web Awesome elements.
440
+ */
441
+ declare function PopupMenu({ text, label, icon, items, placement, caret, disabled, rootAttributes, slot, }: PopupMenuProps): SafeHtml;
442
+
443
+ export { PopupMenu, type PopupMenuDivider, type PopupMenuEntry, type PopupMenuHeading, type PopupMenuItem, type PopupMenuPlacement, type PopupMenuProps };
444
+ ```
445
+
354
446
  ## `@kerfjs/ui/list-header`
355
447
 
356
448
  ```ts
357
449
  import { SafeHtml } from 'kerfjs';
450
+ import { HeadingLevel } from './toolbar-text.js';
358
451
 
359
452
  type ListHeaderRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
360
453
  'data-component'?: never;
@@ -395,6 +488,8 @@ interface ListHeaderBaseProps {
395
488
  type ListHeaderModeProps = {
396
489
  /** Render the title as a controlled disclosure trigger. */
397
490
  toggle: true;
491
+ /** A toggle's label is its button text, not a heading. */
492
+ headingLevel?: never;
398
493
  action: string;
399
494
  expanded: boolean;
400
495
  actionIcon?: SafeHtml;
@@ -404,6 +499,11 @@ type ListHeaderModeProps = {
404
499
  } | {
405
500
  /** Render a separately named trailing action. */
406
501
  toggle?: false;
502
+ /**
503
+ * Native heading level (`h1`–`h6`) of the label. Default `2`. Match the
504
+ * document outline; the visual treatment does not change.
505
+ */
506
+ headingLevel?: HeadingLevel;
407
507
  action: string;
408
508
  actionLabel: string;
409
509
  actionIcon: SafeHtml;
@@ -413,6 +513,11 @@ type ListHeaderModeProps = {
413
513
  } | {
414
514
  /** Render a passive section heading. */
415
515
  toggle?: false;
516
+ /**
517
+ * Native heading level (`h1`–`h6`) of the label. Default `2`. Match the
518
+ * document outline; the visual treatment does not change.
519
+ */
520
+ headingLevel?: HeadingLevel;
416
521
  action?: never;
417
522
  actionLabel?: never;
418
523
  actionIcon?: never;
@@ -437,7 +542,7 @@ type ListHeaderIndicatorProps = {
437
542
  status?: SafeHtml;
438
543
  };
439
544
  type ListHeaderProps = ListHeaderBaseProps & ListHeaderIndicatorProps & ListHeaderModeProps;
440
- 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;
545
+ 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;
441
546
 
442
547
  export { ListHeader, type ListHeaderProps };
443
548
  ```
@@ -447,10 +552,10 @@ export { ListHeader, type ListHeaderProps };
447
552
  ```ts
448
553
  import * as kerfjs from 'kerfjs';
449
554
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
450
- import { D as DividerSides, S as Sides } from './divider-sides-BzB6rphT.js';
451
555
  import { H as HorizontalAlignment, L as ListVerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
452
556
  export { V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
453
557
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
558
+ import { S as Sides } from './sides-BPSWde0A.js';
454
559
 
455
560
  type ListRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
456
561
  'data-component'?: never;
@@ -482,7 +587,7 @@ interface ListProps {
482
587
  /** Own vertical scrolling and overscroll containment. */
483
588
  scrollable?: boolean;
484
589
  /** Physical divider edges in canonical top/right/bottom/left order. */
485
- dividerSides?: DividerSides;
590
+ dividerSides?: Sides;
486
591
  /** Physical sides that receive the standard 17px text inset. */
487
592
  textInsets?: Sides;
488
593
  /** Physical sides that receive the standard 8px control inset. Text insets win on overlap. */
@@ -493,10 +598,17 @@ interface ListProps {
493
598
  /** Native named-slot assignment when composed inside a web component. */
494
599
  slot?: string;
495
600
  }
601
+ /**
602
+ * A list's configuration, apart from its content and styling hooks: the props a
603
+ * composite that renders a `List` for the app (the Workbench's `mainHeader` /
604
+ * `mainFooter` chrome) forwards, so the app configures that list instead of
605
+ * styling it. An omitted or `undefined` field keeps the composite's default.
606
+ */
607
+ type ListConfig = Pick<ListProps, 'gap' | 'hAlign' | 'vAlign' | 'dividerSides' | 'textInsets' | 'controlInsets'>;
496
608
  /** A stretch-aligned vertical stack with optional gap, flex, fill, scroll, and dividers. */
497
609
  declare function List({ children, gap, flex, fill, hAlign, vAlign, scrollable, dividerSides, textInsets, controlInsets, className, rootAttributes, slot, }: ListProps): kerfjs.SafeHtml;
498
610
 
499
- export { CssFlex, CssFlexKeyword, CssLength, DividerSides, HorizontalAlignment, List, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
611
+ export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, List, type ListConfig, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
500
612
  ```
501
613
 
502
614
  ## `@kerfjs/ui/list-action-row`
@@ -626,8 +738,8 @@ export { ListItem, type ListItemProps };
626
738
 
627
739
  ```ts
628
740
  import * as kerfjs from 'kerfjs';
629
- import { S as Sides } from './divider-sides-BzB6rphT.js';
630
741
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
742
+ import { S as Sides } from './sides-BPSWde0A.js';
631
743
 
632
744
  interface ListInsetControlProps {
633
745
  /** Control(s) that own their own border and padding (e.g. an input, a `wa-*`). */
@@ -653,22 +765,21 @@ export { ListInsetControl, type ListInsetControlProps, Sides };
653
765
 
654
766
  ```ts
655
767
  import * as kerfjs from 'kerfjs';
656
- import { S as Sides } from './divider-sides-BzB6rphT.js';
657
768
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
769
+ import { S as Sides } from './sides-BPSWde0A.js';
658
770
 
771
+ type ListInsetTextRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
772
+ 'data-component'?: never;
773
+ 'data-sides'?: never;
774
+ }>;
659
775
  interface ListInsetTextProps {
660
776
  /** Text (or inline content) that carries no margin, border, or padding of its own. */
661
777
  children: KerfUiContent | string;
662
778
  /** Physical inset sides in canonical top/right/bottom/left order. Defaults to all sides. */
663
779
  sides?: Sides;
664
- /**
665
- * @deprecated Pass `sides="rl"` instead. Keep only the horizontal geometry (inline margin, left/right border, and
666
- * left/right padding) and drop the vertical margin, border, and padding. Use it
667
- * when the text edge must still align with bordered items but the line should not
668
- * add its own vertical box space — tight text layout inside a content region.
669
- */
670
- horizontalOnly?: boolean;
671
780
  className?: string;
781
+ /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
782
+ rootAttributes?: ListInsetTextRootAttributes;
672
783
  /** Native named-slot assignment when composed inside a web component. */
673
784
  slot?: string;
674
785
  }
@@ -677,14 +788,65 @@ interface ListInsetTextProps {
677
788
  * transparent border, and 8px padding — so a plain string lines up with
678
789
  * bordered `.kui-content` items (its text edge lands at the same 17px inset).
679
790
  * Use it for text elements that have no margin, border, or padding of their own.
680
- * Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box
791
+ * Pass `sides="rl"` to keep the horizontal inset but drop the vertical box
681
792
  * space for tight text layout.
682
793
  */
683
- declare function ListInsetText({ children, sides, horizontalOnly, className, slot, }: ListInsetTextProps): kerfjs.SafeHtml;
794
+ declare function ListInsetText({ children, sides, className, rootAttributes, slot, }: ListInsetTextProps): kerfjs.SafeHtml;
684
795
 
685
796
  export { ListInsetText, type ListInsetTextProps, Sides };
686
797
  ```
687
798
 
799
+ ## `@kerfjs/ui/content-item`
800
+
801
+ ```ts
802
+ import * as kerfjs from 'kerfjs';
803
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
804
+
805
+ /** Whether the item's always-reserved 1px border is transparent or visible. */
806
+ type ContentItemFrame = 'none' | 'framed';
807
+ /** Corner shape: the 12px rounded rectangle or the 22px pill. */
808
+ type ContentItemShape = 'rounded' | 'pill';
809
+ type ContentItemRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
810
+ 'data-component'?: never;
811
+ }>;
812
+ interface ContentItemProps {
813
+ /** Item content; a plain string is allowed for bare copy. */
814
+ children?: KerfUiContent | string;
815
+ /**
816
+ * `framed` paints the standard neutral border in the 1px the item always
817
+ * reserves, so framing never changes geometry. Frame only an item that
818
+ * marks a real distinction. Defaults to `none` (transparent border).
819
+ */
820
+ frame?: ContentItemFrame;
821
+ /** Corner shape. Defaults to `rounded`. */
822
+ shape?: ContentItemShape;
823
+ /**
824
+ * Names the item as a distinct region (`role="region"`). Omit it for an
825
+ * ordinary item, which stays a non-landmark grouping.
826
+ */
827
+ ariaLabel?: string;
828
+ /**
829
+ * Makes the item a programmatic focus target (`tabindex="-1"`, never a tab
830
+ * stop), for example the preferred initial focus of a NavStack view when
831
+ * combined with `data-nav-focus` in `rootAttributes`.
832
+ */
833
+ focusTarget?: boolean;
834
+ className?: string;
835
+ /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
836
+ rootAttributes?: ContentItemRootAttributes;
837
+ /** Native named-slot assignment when composed inside a web component. */
838
+ slot?: string;
839
+ }
840
+ /**
841
+ * One self-contained `.kui-content` child: an 8px inline margin, a real 1px
842
+ * border (transparent unless `framed`), 8px padding, and a rounded or pill
843
+ * radius. It owns that whole geometry, so wrappers must not add more.
844
+ */
845
+ declare function ContentItem({ children, frame, shape, ariaLabel, focusTarget, className, rootAttributes, slot, }: ContentItemProps): kerfjs.SafeHtml;
846
+
847
+ export { ContentItem, type ContentItemFrame, type ContentItemProps, type ContentItemShape };
848
+ ```
849
+
688
850
  ## `@kerfjs/ui/value-table`
689
851
 
690
852
  ```ts
@@ -861,6 +1023,10 @@ export { TabActivation, type TabDropPosition, type TabReorder, type TabReorderSo
861
1023
  ```ts
862
1024
  import * as kerfjs from 'kerfjs';
863
1025
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1026
+ import { ToolbarConfig } from './toolbar.js';
1027
+ import { ToolbarTextSize, HeadingLevel } from './toolbar-text.js';
1028
+ import './pane.js';
1029
+ import './sides-BPSWde0A.js';
864
1030
 
865
1031
  /**
866
1032
  * One entry in a {@link NavStack}. The app owns the stack as an array (usually a
@@ -872,19 +1038,46 @@ interface NavStackView {
872
1038
  content: KerfUiContent;
873
1039
  /** Title shown in the top toolbar for this view. */
874
1040
  title?: string;
1041
+ /** Leading groups for this view's top toolbar, after the back control and before the title. */
1042
+ leading?: KerfUiContent;
1043
+ /** Center content for this view's top toolbar (placed per `toolbarConfig.centerAlign`). */
1044
+ center?: KerfUiContent;
875
1045
  /** Trailing actions for this view's top toolbar. */
876
1046
  toolbar?: KerfUiContent;
877
1047
  /** Bottom toolbar for this view. Cross-fades with the top chrome on navigation. */
878
1048
  bottomToolbar?: KerfUiContent;
879
1049
  }
1050
+ /**
1051
+ * The top toolbar's configuration. Its `ToolbarConfig` forwards to the real
1052
+ * `Toolbar` the stack renders; by default that toolbar draws no divider and
1053
+ * claims the top and side safe-area edges the stack still touches.
1054
+ */
1055
+ interface NavStackToolbarConfig extends ToolbarConfig {
1056
+ /** Accessible name of the top toolbar (default: none). */
1057
+ label?: string;
1058
+ /** Size of the view title's `ToolbarText` (default `large`). */
1059
+ titleSize?: ToolbarTextSize;
1060
+ /** Expose the view title as a heading at this level (default: a plain span). */
1061
+ headingLevel?: HeadingLevel;
1062
+ }
880
1063
  interface NavStackProps {
881
1064
  id: string;
882
1065
  /** Accessible name for the stack region. */
883
1066
  label: string;
884
1067
  /** The stack, root first; the last entry is the active top view. */
885
1068
  views: NavStackView[];
886
- /** Accessible label for the back control (default "Back"). */
1069
+ /** Accessible label for the icon-only back control (default "Back"). */
887
1070
  backLabel?: string;
1071
+ /** The back control's icon (default a chevron-left `LucideIcon`). */
1072
+ backIcon?: KerfUiContent;
1073
+ /**
1074
+ * Visible text beside the back icon, such as the previous view's title
1075
+ * (default: icon only). When set, the text names the control and
1076
+ * `backLabel` is not used.
1077
+ */
1078
+ backText?: string;
1079
+ /** The top toolbar's configuration, forwarded to its `Toolbar`. */
1080
+ toolbarConfig?: NavStackToolbarConfig;
888
1081
  /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */
889
1082
  hideToolbar?: boolean;
890
1083
  /** Optional persistent bottom toolbar used when the active view does not provide one. */
@@ -896,12 +1089,14 @@ interface NavStackProps {
896
1089
  /**
897
1090
  * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last
898
1091
  * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and
899
- * cross-fades the chrome across a change. A single-pane layout is a `NavStack`
900
- * with one entry. See `docs/23-app-layouts.md` §3.1.
1092
+ * cross-fades the chrome across a change. Its top chrome is a real `Toolbar`: the
1093
+ * back control and title lead, the active view's `leading` / `center` / `toolbar`
1094
+ * content fills the zones, and `toolbarConfig` configures it. A single-pane
1095
+ * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.
901
1096
  */
902
- declare function NavStack({ id, label, views, backLabel, hideToolbar, bottomToolbar, className, slot, }: NavStackProps): kerfjs.SafeHtml;
1097
+ declare function NavStack({ id, label, views, backLabel, backIcon, backText, toolbarConfig, hideToolbar, bottomToolbar, className, slot, }: NavStackProps): kerfjs.SafeHtml;
903
1098
 
904
- export { NavStack, type NavStackProps, type NavStackView };
1099
+ export { NavStack, type NavStackProps, type NavStackToolbarConfig, type NavStackView };
905
1100
  ```
906
1101
 
907
1102
  ## `@kerfjs/ui/wire-nav-stack`
@@ -931,13 +1126,39 @@ export { type WireNavStackOptions, wireNavStack };
931
1126
 
932
1127
  ```ts
933
1128
  import * as kerfjs from 'kerfjs';
1129
+ import { NavStackProps, NavStackView } from './nav-stack.js';
1130
+ import { ResizableRegionProps } from './resizable-region.js';
934
1131
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1132
+ import './toolbar.js';
1133
+ import './pane.js';
1134
+ import './sides-BPSWde0A.js';
1135
+ import './toolbar-text.js';
935
1136
 
936
- interface SplitViewResizable {
1137
+ /**
1138
+ * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /
1139
+ * `max` limits, plus the region configuration that forwards unchanged
1140
+ * (`separator`, `handleIcon`, `contentOverflow`, and collapse:
1141
+ * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,
1142
+ * `restorePosition`). Omitted options keep the region's defaults.
1143
+ */
1144
+ interface SplitViewResizable extends Pick<ResizableRegionProps, 'separator' | 'handleIcon' | 'contentOverflow' | 'collapsed' | 'transitioning' | 'collapseMotion' | 'restoreControl' | 'restorePosition'> {
937
1145
  size: number;
938
1146
  min: number;
939
1147
  max: number;
940
1148
  }
1149
+ /** One compact view's top- and bottom-toolbar content (see `NavStackView`). */
1150
+ type SplitViewCompactViewToolbars = Pick<NavStackView, 'leading' | 'center' | 'toolbar' | 'bottomToolbar'>;
1151
+ /**
1152
+ * The compact `NavStack`'s configuration: its toolbar configuration, back
1153
+ * control, and persistent bottom toolbar forward to the stack, and `list` /
1154
+ * `detail` give each view its own toolbar groups.
1155
+ */
1156
+ interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar'> {
1157
+ /** Toolbar content for the list (root) view. */
1158
+ list?: SplitViewCompactViewToolbars;
1159
+ /** Toolbar content for the pushed detail view. */
1160
+ detail?: SplitViewCompactViewToolbars;
1161
+ }
941
1162
  interface SplitViewProps {
942
1163
  id: string;
943
1164
  label: string;
@@ -959,6 +1180,8 @@ interface SplitViewProps {
959
1180
  detailTitle?: string;
960
1181
  /** Back label for the compact NavStack (default "Back"). */
961
1182
  backLabel?: string;
1183
+ /** Compact NavStack configuration and per-view toolbars. */
1184
+ compactStack?: SplitViewCompactStack;
962
1185
  /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */
963
1186
  resizable?: SplitViewResizable;
964
1187
  className?: string;
@@ -972,9 +1195,9 @@ interface SplitViewProps {
972
1195
  * resizable wiring with `wireResizableRegions` and the compact back with
973
1196
  * `wireNavStack`.
974
1197
  */
975
- declare function SplitView({ id, label, list, detail, compact, detailActive, listTitle, detailTitle, backLabel, resizable, className, slot, }: SplitViewProps): kerfjs.SafeHtml;
1198
+ declare function SplitView({ id, label, list, detail, compact, detailActive, listTitle, detailTitle, backLabel, compactStack, resizable, className, slot, }: SplitViewProps): kerfjs.SafeHtml;
976
1199
 
977
- export { SplitView, type SplitViewProps, type SplitViewResizable };
1200
+ export { SplitView, type SplitViewCompactStack, type SplitViewCompactViewToolbars, type SplitViewProps, type SplitViewResizable };
978
1201
  ```
979
1202
 
980
1203
  ## `@kerfjs/ui/pane`
@@ -1002,7 +1225,10 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
1002
1225
  'data-safe-area-block-end'?: never;
1003
1226
  'data-safe-area-inline-start'?: never;
1004
1227
  'data-safe-area-inline-end'?: never;
1228
+ 'data-chrome-placement'?: never;
1005
1229
  }>;
1230
+ /** How a Pane's header and footer relate to its scrolling content. */
1231
+ type PaneChromePlacement = 'fixed' | 'auto';
1006
1232
  interface PaneProps {
1007
1233
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
1008
1234
  header?: KerfUiContent;
@@ -1010,6 +1236,14 @@ interface PaneProps {
1010
1236
  children?: KerfUiContent;
1011
1237
  /** Optional fixed chrome below the scrolling content. */
1012
1238
  footer?: KerfUiContent;
1239
+ /**
1240
+ * Whether the header and footer stay pinned around the scrolling content.
1241
+ * `fixed` (default) always pins them. `auto` pins them while the pane is
1242
+ * tall enough, and below 480px of height (30rem, so it scales with the text
1243
+ * size) lets the whole pane scroll as one column, so tall chrome can never
1244
+ * squeeze the content to nothing.
1245
+ */
1246
+ chromePlacement?: PaneChromePlacement;
1013
1247
  /** Root semantics. Defaults to `div`. */
1014
1248
  element?: PaneElement;
1015
1249
  /** Scrolling content semantics. Defaults to `div`. */
@@ -1038,30 +1272,101 @@ interface PaneProps {
1038
1272
  /** Native named-slot assignment when composed inside a web component. */
1039
1273
  slot?: string;
1040
1274
  }
1275
+ /**
1276
+ * A pane's configuration, apart from its content and styling hooks: the props a
1277
+ * composite that renders a `Pane` for the app (a Workbench panel or work area,
1278
+ * or a CollapsiblePanel) forwards, so the app configures that pane instead of
1279
+ * styling it. An omitted or `undefined` field keeps the composite's default.
1280
+ */
1281
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges'>;
1041
1282
  /**
1042
1283
  * An unpadded application column with optional fixed header/footer slots and one
1043
1284
  * scrolling vertical content owner. Separator lines are independently opt-in on
1044
1285
  * each logical edge, so the same component works as a sidebar, main area,
1045
1286
  * inspector, or dialog column.
1046
1287
  */
1047
- declare function Pane({ header, children, footer, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1288
+ declare function Pane({ header, children, footer, chromePlacement, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1048
1289
 
1049
- export { Pane, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1290
+ export { Pane, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1050
1291
  ```
1051
1292
 
1052
1293
  ## `@kerfjs/ui/workbench`
1053
1294
 
1054
1295
  ```ts
1055
1296
  import { SafeHtml } from 'kerfjs';
1297
+ import { ListConfig } from './list.js';
1298
+ import { PaneConfig } from './pane.js';
1056
1299
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1057
1300
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1301
+ import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-C8sF-YZC.js';
1302
+ import { ToolbarConfig } from './toolbar.js';
1303
+ import './css-values.js';
1304
+ import './flex-alignment-4ms8ZbV8.js';
1305
+ import './sides-BPSWde0A.js';
1306
+ import './lucide-icon.js';
1307
+ import 'lucide';
1308
+
1309
+ /** The standard toggle a Workbench renders for a panel (see {@link PanelToggle}). */
1310
+ type WorkbenchPanelToggle = PanelToggle;
1311
+ /**
1312
+ * A Workbench panel's top toolbar, composed by the Workbench so its groups can
1313
+ * follow the panel's open state (see {@link PanelToolbar} for the roles).
1314
+ * A collapsed rail's `constant` groups and toggle go to the leading edge of
1315
+ * `mainToolbar` (left rail) or its trailing edge (right rail); a collapsed
1316
+ * drawer's go to the trailing edge of `mainBottomToolbar`, else to a
1317
+ * `FloatingToolbar` in the work area's bottom-end corner.
1318
+ */
1319
+ type WorkbenchPanelToolbar = PanelToolbar;
1320
+ /**
1321
+ * The work area's top toolbar; collapsed rails add their groups to it. Its
1322
+ * configuration forwards to its `Toolbar`. By default it draws the divider
1323
+ * under the work area's header chrome: its own bottom edge, or none when a
1324
+ * `mainHeader` follows (which then carries the divider).
1325
+ */
1326
+ interface WorkbenchMainToolbar extends ToolbarConfig {
1327
+ label: string;
1328
+ /** The work area's title, usually an extra-large `ToolbarText`. */
1329
+ title?: KerfUiContent;
1330
+ /** Groups after the title. */
1331
+ leading?: KerfUiContent;
1332
+ center?: KerfUiContent;
1333
+ /** Groups at the trailing edge, before a collapsed right rail's groups. */
1334
+ trailing?: KerfUiContent;
1335
+ }
1336
+ /**
1337
+ * The work area's bottom toolbar; a collapsed drawer adds its groups to it.
1338
+ * Its configuration forwards to its `Toolbar`. By default it draws the divider
1339
+ * over the work area's footer chrome: its own top edge, or none when a
1340
+ * `mainFooter` precedes it.
1341
+ */
1342
+ interface WorkbenchMainBottomToolbar extends ToolbarConfig {
1343
+ label: string;
1344
+ leading?: KerfUiContent;
1345
+ center?: KerfUiContent;
1346
+ trailing?: KerfUiContent;
1347
+ }
1348
+ /**
1349
+ * Whether the work area's header or footer chrome stays pinned (`fixed`),
1350
+ * scrolls away with the content (`scroll`), or stays pinned while the work
1351
+ * area is tall enough and scrolls with the content when it is short (`auto`,
1352
+ * the Pane's `chromePlacement="auto"`; it applies to the pinned header and
1353
+ * footer together).
1354
+ */
1355
+ type WorkbenchChromePlacement = 'fixed' | 'scroll' | 'auto';
1058
1356
 
1059
1357
  /**
1060
1358
  * The Workbench container breakpoint below which a panel presents as an
1061
1359
  * overlay: `narrow` (704px or less) or `compact` (448px or less) — the same
1062
- * breakpoints as `ResizableRegion`'s `responsiveFillAt`.
1360
+ * breakpoints as `ResizableRegion`'s `responsiveFillAt` — or `never` to keep
1361
+ * it inline at every width.
1063
1362
  */
1064
- type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow';
1363
+ type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow' | 'never';
1364
+ /**
1365
+ * How wide a rail's overlay is in a compact (448px or less) Workbench: `inset`
1366
+ * fills the Workbench less a dismiss margin on the side away from the rail's
1367
+ * edge, so a press beside it closes it; `full` fills the Workbench.
1368
+ */
1369
+ type WorkbenchCompactOverlay = 'inset' | 'full';
1065
1370
  /** Drag-resize limits for a resizable Workbench panel, in px. */
1066
1371
  interface WorkbenchPanelResizable {
1067
1372
  /** Smallest size (default 180 for a rail, 120 for the drawer). */
@@ -1072,6 +1377,22 @@ interface WorkbenchPanelResizable {
1072
1377
  /** A collapsible Workbench panel — a side rail or the bottom drawer. */
1073
1378
  interface WorkbenchPanel {
1074
1379
  content: KerfUiContent;
1380
+ /**
1381
+ * The panel's top toolbar, composed by the Workbench: its `constant` groups
1382
+ * and standard `toggle` move to the work area's toolbar while the panel is
1383
+ * collapsed. With it, `content` renders in a `Pane` below the toolbar.
1384
+ */
1385
+ toolbar?: WorkbenchPanelToolbar;
1386
+ /** Optional bottom toolbar under a `toolbar` panel's content. */
1387
+ footer?: KerfUiContent;
1388
+ /**
1389
+ * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1390
+ * `contentLabel`, `separators`, `safeAreaEdges`) — for example
1391
+ * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1392
+ * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1393
+ * without a `toolbar`, where `content` renders as given.
1394
+ */
1395
+ pane?: PaneConfig;
1075
1396
  /** Whether the panel is currently collapsed (the app owns this). */
1076
1397
  collapsed?: boolean;
1077
1398
  /**
@@ -1097,13 +1418,22 @@ interface WorkbenchPanel {
1097
1418
  * Present the panel as an overlay, without a separator, below a Workbench
1098
1419
  * container breakpoint, and inline above it — the CSS decides, so the app
1099
1420
  * needs no device-class check. A rail overlays from its side at full
1100
- * height; the bottom drawer overlays the bottom of the work-area column.
1421
+ * height, over the work area and an open drawer; the bottom drawer
1422
+ * overlays the bottom of the work-area column. Rails default to `narrow`
1423
+ * (pass `never` to keep one inline); the drawer defaults to inline.
1101
1424
  */
1102
1425
  responsiveOverlayAt?: WorkbenchResponsiveOverlayAt;
1426
+ /**
1427
+ * A rail's overlay width in a compact Workbench (default `inset`: the
1428
+ * Workbench less `--kui-workbench-overlay-dismiss-margin`, 44px). Ignored
1429
+ * by the drawer.
1430
+ */
1431
+ compactOverlay?: WorkbenchCompactOverlay;
1103
1432
  /**
1104
1433
  * Control shown while collapsed, in a safe-area-aware corner of the
1105
1434
  * Workbench (not the viewport); the bottom drawer's sits in the work-area
1106
- * column.
1435
+ * column. Prefer `toolbar.toggle`, which the Workbench relocates into the
1436
+ * work area's toolbar (or this corner when that toolbar is absent).
1107
1437
  */
1108
1438
  restoreControl?: SafeHtml;
1109
1439
  restorePosition?: ResizableRegionRestorePosition;
@@ -1118,6 +1448,55 @@ interface WorkbenchProps {
1118
1448
  label: string;
1119
1449
  /** The central work area. */
1120
1450
  main: KerfUiContent;
1451
+ /**
1452
+ * The work area's top toolbar. A collapsed left rail's `constant` groups
1453
+ * and toggle lead it; a collapsed right rail's trail it. With it, `main`
1454
+ * renders in a `Pane` below the toolbar.
1455
+ */
1456
+ mainToolbar?: WorkbenchMainToolbar;
1457
+ /**
1458
+ * Fixed content under `mainToolbar` — supporting copy such as a
1459
+ * description — divided from the scrolling `main` below it.
1460
+ */
1461
+ mainHeader?: KerfUiContent;
1462
+ /**
1463
+ * Fixed content over `mainBottomToolbar` — a status line or a resource
1464
+ * toolbar — divided from the scrolling `main` above it.
1465
+ */
1466
+ mainFooter?: KerfUiContent;
1467
+ /**
1468
+ * The work area's bottom toolbar. A collapsed drawer's `constant` groups and
1469
+ * toggle trail it; without it they float in the work area's corner.
1470
+ */
1471
+ mainBottomToolbar?: WorkbenchMainBottomToolbar;
1472
+ /**
1473
+ * Whether `mainToolbar` and `mainHeader` stay pinned (`fixed`, default),
1474
+ * scroll away with `main` (`scroll`) — useful where large text would leave
1475
+ * pinned chrome little room — or stay pinned while the work area is tall
1476
+ * enough and scroll with `main` when it is short (`auto`).
1477
+ */
1478
+ mainHeaderPlacement?: WorkbenchChromePlacement;
1479
+ /** The same for `mainFooter` and `mainBottomToolbar` (default `fixed`). */
1480
+ mainFooterPlacement?: WorkbenchChromePlacement;
1481
+ /**
1482
+ * Configuration for the work area's `Pane` (`contentElement`,
1483
+ * `contentLabel`, `separators`, `safeAreaEdges`), which it has whenever it
1484
+ * has a toolbar, `mainHeader`, or `mainFooter`; without that chrome, `main`
1485
+ * renders as given and this is ignored. Omitted or `undefined` fields keep
1486
+ * the `Pane` defaults.
1487
+ */
1488
+ mainPane?: PaneConfig;
1489
+ /**
1490
+ * Configuration for the `List` that holds `mainHeader` (`gap`, `hAlign`,
1491
+ * `vAlign`, `dividerSides`, `textInsets`, `controlInsets`). Omitted or
1492
+ * `undefined` fields keep the defaults, including its bottom divider.
1493
+ */
1494
+ mainHeaderList?: ListConfig;
1495
+ /**
1496
+ * The same for the `List` that holds `mainFooter`; by default it draws a
1497
+ * top divider, or none when a `mainBottomToolbar` follows it.
1498
+ */
1499
+ mainFooterList?: ListConfig;
1121
1500
  leftRail?: WorkbenchPanel;
1122
1501
  rightRail?: WorkbenchPanel;
1123
1502
  bottomDrawer?: WorkbenchPanel;
@@ -1154,9 +1533,9 @@ interface WorkbenchProps {
1154
1533
  * lives outside it and stays reachable). A panel may opt in to drag and keyboard resizing with
1155
1534
  * `resizable`, which `wireWorkbench` drives. See `docs/23-app-layouts.md` §3.3.
1156
1535
  */
1157
- declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1536
+ declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1158
1537
 
1159
- export { Workbench, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
1538
+ export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
1160
1539
  ```
1161
1540
 
1162
1541
  ## `@kerfjs/ui/wire-workbench`
@@ -1277,24 +1656,27 @@ export { type WireWorkbenchOptions, type WireWorkbenchPanel, type WorkbenchPanel
1277
1656
 
1278
1657
  ```ts
1279
1658
  import { SafeHtml } from 'kerfjs';
1280
- import { LucideIcon } from './lucide-icon.js';
1659
+ import { PaneConfig } from './pane.js';
1660
+ import { P as PanelSide, a as PanelToolbar, b as PanelToggle } from './panel-toolbar-C8sF-YZC.js';
1661
+ export { c as collapsiblePanelToggleIcon } from './panel-toolbar-C8sF-YZC.js';
1281
1662
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1282
1663
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1664
+ import './lucide-icon.js';
1283
1665
  import 'lucide';
1666
+ import './toolbar.js';
1667
+ import './sides-BPSWde0A.js';
1284
1668
 
1285
1669
  /** Which edge a {@link CollapsiblePanel} docks to. */
1286
- type CollapsiblePanelSide = 'left' | 'right' | 'bottom';
1670
+ type CollapsiblePanelSide = PanelSide;
1671
+ /** The standard toggle a panel toolbar renders (see {@link CollapsiblePanelToolbar}). */
1672
+ type CollapsiblePanelToolbarToggle = PanelToggle;
1287
1673
  /**
1288
- * The standard collapse/expand icon for a panel `side` and `collapsed` state,
1289
- * so every app's sidebars and drawers use one recognizable convention:
1290
- * `PanelLeft*` for a left rail, `PanelRight*` for a right rail, `PanelBottom*`
1291
- * for a bottom drawer — the `Close` glyph while open, the `Open` glyph while
1292
- * collapsed. Exposed so an app can render its own toggle affordance.
1674
+ * A panel's composed top toolbar. `title` and `panelOnly` groups lead it and
1675
+ * are available only while the panel is open; `constant` groups and the
1676
+ * standard `toggle` trail it while open and move to the app's work-area
1677
+ * toolbar — through {@link CollapsiblePanelRelocated} — while it is collapsed.
1293
1678
  */
1294
- declare function collapsiblePanelToggleIcon(side: CollapsiblePanelSide, collapsed: boolean): {
1295
- icon: Parameters<typeof LucideIcon>[0]['icon'];
1296
- name: string;
1297
- };
1679
+ type CollapsiblePanelToolbar = PanelToolbar;
1298
1680
  interface CollapsiblePanelToggleProps {
1299
1681
  /** The panel this toggle controls. */
1300
1682
  side: CollapsiblePanelSide;
@@ -1331,6 +1713,23 @@ interface CollapsiblePanelProps {
1331
1713
  label?: string;
1332
1714
  /** Panel content. */
1333
1715
  children?: KerfUiContent;
1716
+ /**
1717
+ * The panel's top toolbar, composed so its groups follow the panel's open
1718
+ * state. With it, `children` renders in a `Pane` below the toolbar; render
1719
+ * {@link CollapsiblePanelRelocated} in the app's work-area toolbar so the
1720
+ * `constant` groups and toggle stay reachable while the panel is collapsed.
1721
+ */
1722
+ toolbar?: CollapsiblePanelToolbar;
1723
+ /** Optional bottom toolbar under a `toolbar` panel's content. */
1724
+ footer?: KerfUiContent;
1725
+ /**
1726
+ * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1727
+ * `contentLabel`, `separators`, `safeAreaEdges`) — for example
1728
+ * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1729
+ * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1730
+ * without a `toolbar`, where `children` renders as given.
1731
+ */
1732
+ pane?: PaneConfig;
1334
1733
  separator?: ResizableRegionSeparator;
1335
1734
  collapseMotion?: ResizableRegionCollapseMotion;
1336
1735
  contentOverflow?: ResizableRegionContentOverflow;
@@ -1356,9 +1755,27 @@ interface CollapsiblePanelProps {
1356
1755
  * and persistence semantics, and with `CollapsiblePanelToggle` for the standard
1357
1756
  * affordance. See `ui/docs/collapsible-panel.md` and `docs/23-app-layouts.md`.
1358
1757
  */
1359
- declare function CollapsiblePanel({ id, side, collapsed, size, label, children, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1758
+ declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, footer, pane, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1759
+ interface CollapsiblePanelRelocatedProps {
1760
+ /** The panel's `id`. */
1761
+ panelId: string;
1762
+ side: CollapsiblePanelSide;
1763
+ /** The panel's current collapsed state. */
1764
+ collapsed: boolean;
1765
+ /** The same `toolbar` the panel receives. */
1766
+ toolbar: CollapsiblePanelToolbar;
1767
+ }
1768
+ /**
1769
+ * A collapsed {@link CollapsiblePanel}'s `constant` groups and standard
1770
+ * toggle, for the app's work-area toolbar — nothing while the panel is open.
1771
+ * Put it first in the leading zone for a left rail, last in the trailing zone
1772
+ * for a right rail, and last in a bottom toolbar (or a `FloatingToolbar`
1773
+ * `restoreControl`) for a bottom drawer. `wireSidebar` hands focus to it when
1774
+ * the panel closes from its own toggle.
1775
+ */
1776
+ declare function CollapsiblePanelRelocated({ panelId, side, collapsed, toolbar, }: CollapsiblePanelRelocatedProps): SafeHtml;
1360
1777
 
1361
- export { CollapsiblePanel, type CollapsiblePanelProps, type CollapsiblePanelSide, CollapsiblePanelToggle, type CollapsiblePanelToggleProps, collapsiblePanelToggleIcon };
1778
+ export { CollapsiblePanel, type CollapsiblePanelProps, CollapsiblePanelRelocated, type CollapsiblePanelRelocatedProps, type CollapsiblePanelSide, CollapsiblePanelToggle, type CollapsiblePanelToggleProps, type CollapsiblePanelToolbar, type CollapsiblePanelToolbarToggle };
1362
1779
  ```
1363
1780
 
1364
1781
  ## `@kerfjs/ui/wire-sidebar`
@@ -1435,7 +1852,7 @@ export { type SidebarStorage, type WireSidebarOptions, type WireSidebarPanel, wi
1435
1852
  import { SafeHtml } from 'kerfjs';
1436
1853
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1437
1854
 
1438
- interface TabScaffoldTab<Id extends string = string> {
1855
+ interface TabScaffoldTabBase<Id extends string> {
1439
1856
  id: Id;
1440
1857
  label: string;
1441
1858
  /** Decorative icon shown above the label in the bottom bar. */
@@ -1443,6 +1860,40 @@ interface TabScaffoldTab<Id extends string = string> {
1443
1860
  /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
1444
1861
  content: KerfUiContent;
1445
1862
  }
1863
+ /** A tab with an optional count or short-status badge. */
1864
+ interface TabScaffoldTabCountBadge {
1865
+ /**
1866
+ * Optional count or short status shown as a solid danger `Badge` at the
1867
+ * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,
1868
+ * or non-finite numbers render no badge. The visual badge is `aria-hidden`;
1869
+ * its meaning reaches assistive technology through `badgeLabel`.
1870
+ *
1871
+ * Pass `true` instead for the text-free dot (new content without a count).
1872
+ */
1873
+ badge?: string | number;
1874
+ /**
1875
+ * Localized phrase folded into the tab's accessible name as
1876
+ * `"<label>, <badgeLabel>"` (for example `"3 unread"` → `"Inbox, 3 unread"`).
1877
+ * Defaults to the badge text itself. Ignored when no badge renders.
1878
+ */
1879
+ badgeLabel?: string;
1880
+ }
1881
+ /** A tab with the text-free dot badge (new content without a count). */
1882
+ interface TabScaffoldTabDotBadge {
1883
+ /**
1884
+ * `true` shows a solid danger dot `Badge` at the top-trailing corner of the
1885
+ * tab icon — the iOS tab-bar dot for new content without a count.
1886
+ */
1887
+ badge: true;
1888
+ /**
1889
+ * Required localized phrase folded into the tab's accessible name as
1890
+ * `"<label>, <badgeLabel>"` (for example `"New activity"` →
1891
+ * `"Feed, New activity"`). A dot has no text, so this is its only meaning.
1892
+ */
1893
+ badgeLabel: string;
1894
+ }
1895
+ /** One bottom-bar destination: its label, optional icon and badge, and content. */
1896
+ type TabScaffoldTab<Id extends string = string> = TabScaffoldTabBase<Id> & (TabScaffoldTabCountBadge | TabScaffoldTabDotBadge);
1446
1897
  interface TabScaffoldProps<Id extends string = string> {
1447
1898
  id: string;
1448
1899
  /** Accessible name for the tab bar. */
@@ -1628,12 +2079,29 @@ export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type Dev
1628
2079
  ```ts
1629
2080
  import * as kerfjs from 'kerfjs';
1630
2081
  import { SafeHtml } from 'kerfjs';
1631
- import { a as CatalogProps } from './types-CEsieBZi.js';
1632
- export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-CEsieBZi.js';
2082
+ import { a as CatalogProps } from './types-DXAGogOS.js';
2083
+ export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-DXAGogOS.js';
1633
2084
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2085
+ import './toolbar.js';
2086
+ import './pane.js';
2087
+ import './sides-BPSWde0A.js';
2088
+ import './workbench.js';
2089
+ import './list.js';
2090
+ import './css-values.js';
2091
+ import './flex-alignment-4ms8ZbV8.js';
2092
+ import './resizable-region.js';
2093
+ import './panel-toolbar-C8sF-YZC.js';
2094
+ import './lucide-icon.js';
2095
+ import 'lucide';
1634
2096
 
1635
- /** Controlled, stateless component-catalog shell. */
1636
- declare function Catalog({ brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2097
+ /**
2098
+ * Controlled, stateless component-catalog shell: a `Workbench` whose left rail
2099
+ * is the catalog navigation and whose work area is the active entry — its
2100
+ * toolbar, description, preview stage, and resource footer. The sidebar's
2101
+ * standard toggle moves into the entry toolbar while it is collapsed, and on
2102
+ * a small screen the sidebar overlays the stage like any Workbench rail.
2103
+ */
2104
+ 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;
1637
2105
 
1638
2106
  /** How a specimen aligns its visible edge with its `ListHeader` label. */
1639
2107
  type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';
@@ -1704,9 +2172,20 @@ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleP
1704
2172
  ## `@kerfjs/ui/catalog-resources`
1705
2173
 
1706
2174
  ```ts
1707
- import { C as CatalogResource } from './types-CEsieBZi.js';
2175
+ import { C as CatalogResource } from './types-DXAGogOS.js';
1708
2176
  import './semantic-content-BbzjvSu9.js';
1709
2177
  import 'kerfjs';
2178
+ import './toolbar.js';
2179
+ import './pane.js';
2180
+ import './sides-BPSWde0A.js';
2181
+ import './workbench.js';
2182
+ import './list.js';
2183
+ import './css-values.js';
2184
+ import './flex-alignment-4ms8ZbV8.js';
2185
+ import './resizable-region.js';
2186
+ import './panel-toolbar-C8sF-YZC.js';
2187
+ import './lucide-icon.js';
2188
+ import 'lucide';
1710
2189
 
1711
2190
  /**
1712
2191
  * Standard resource labels for a Kerf catalog detail footer. Keep these labels
@@ -1744,6 +2223,8 @@ export { type CatalogGuidanceKind, type CatalogResourceKind, type CatalogResourc
1744
2223
  ## `@kerfjs/ui/wire-catalog`
1745
2224
 
1746
2225
  ```ts
2226
+ import { Signal } from 'kerfjs';
2227
+
1747
2228
  interface WireCatalogOptions {
1748
2229
  /** Invoked with the entry id when a sidebar item or a related-entry option is chosen. */
1749
2230
  onSelect: (id: string) => void;
@@ -1764,6 +2245,27 @@ interface WireCatalogOptions {
1764
2245
  toggleSidebarAction?: string;
1765
2246
  toggleThemeAction?: string;
1766
2247
  toggleSecondaryAction?: string;
2248
+ /**
2249
+ * The sidebar's app-owned collapsed flag. With it, the catalog's Workbench
2250
+ * sidebar is wired like any Workbench rail: it becomes a transient overlay
2251
+ * on a small screen (collapsed as the breakpoint applies, closed on Escape
2252
+ * or a press outside, focus handed back), and choosing an entry from the
2253
+ * open overlay closes it.
2254
+ */
2255
+ collapsed?: Signal<boolean>;
2256
+ /**
2257
+ * The app-owned sidebar width signal for a Catalog rendered with
2258
+ * `sidebar={{ resizable: true, size: sidebarSize.value }}`. Each committed
2259
+ * drag or keyboard resize is written to it.
2260
+ */
2261
+ sidebarSize?: Signal<number>;
2262
+ /**
2263
+ * With `sidebarSize`, load and save the width under this storage key so the
2264
+ * catalog remembers the user's sidebar width.
2265
+ */
2266
+ sidebarStorageKey?: string;
2267
+ /** The Catalog's `id`, when it is not the default `kui-catalog`. */
2268
+ id?: string;
1767
2269
  }
1768
2270
  interface CatalogRevealOptions {
1769
2271
  /** Scroll alignment within the sidebar. Default `'nearest'`. */
@@ -1798,7 +2300,7 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
1798
2300
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
1799
2301
  * Returns a disposer.
1800
2302
  */
1801
- declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, }: WireCatalogOptions): () => void;
2303
+ declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
1802
2304
 
1803
2305
  export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog, wireCatalogGeometryOverlay };
1804
2306
  ```
@@ -1847,6 +2349,7 @@ export { SegmentedControl, type SegmentedControlAppearance, type SegmentedContro
1847
2349
  import { SafeHtml } from 'kerfjs';
1848
2350
  import { CssForegroundColor } from './css-values.js';
1849
2351
  import { LucideNode } from './lucide-icon.js';
2352
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1850
2353
  import 'lucide';
1851
2354
 
1852
2355
  interface SelectChoice<Value extends string = string> {
@@ -1858,7 +2361,8 @@ interface SelectChoice<Value extends string = string> {
1858
2361
  * Foreground color for the optional icon: a semantic foreground token such
1859
2362
  * as `uiColor('success-on-quiet')`, or an application-owned
1860
2363
  * `foregroundColorVar('--app-icon-color')`. Fill tokens such as
1861
- * `uiColor('success')` are pale background tints and do not type-check.
2364
+ * `uiColor('success-fill-quiet')` are pale background tints and do not
2365
+ * type-check.
1862
2366
  */
1863
2367
  color?: CssForegroundColor;
1864
2368
  group?: string;
@@ -1882,7 +2386,6 @@ type SelectSelectedPresentation = 'label' | 'icon-only';
1882
2386
  type SelectFocusRingOwner = 'select' | 'group';
1883
2387
  interface SelectBaseProps<Value extends string = string> {
1884
2388
  name: string;
1885
- value: NoInfer<Value>;
1886
2389
  choices: readonly SelectChoice<Value>[];
1887
2390
  className?: string;
1888
2391
  /** Empty-value hint text shown in the closed control (the native select placeholder). */
@@ -1891,14 +2394,11 @@ interface SelectBaseProps<Value extends string = string> {
1891
2394
  hint?: string;
1892
2395
  disabled?: boolean;
1893
2396
  fitMenu?: boolean;
1894
- renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
1895
2397
  /** Render as an unanimated loading skeleton: the label above a static, empty control box. */
1896
2398
  placeholder?: boolean;
1897
2399
  /** Form (default), borderless toolbar, or intrinsic navigation chrome. */
1898
2400
  presentation?: SelectPresentation;
1899
2401
  size?: SelectSize;
1900
- /** Show only the selected choice icon while retaining the Select's accessible name. */
1901
- selectedPresentation?: SelectSelectedPresentation;
1902
2402
  /** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
1903
2403
  focusRingOwner?: SelectFocusRingOwner;
1904
2404
  /** Maximum closed-control label width in CSS pixels before ellipsis. */
@@ -1906,10 +2406,50 @@ interface SelectBaseProps<Value extends string = string> {
1906
2406
  /** Native named-slot assignment when composed inside a web component. */
1907
2407
  slot?: string;
1908
2408
  }
1909
- type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName;
1910
- 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;
2409
+ /** One chosen value (the default). */
2410
+ interface SelectSingleValueProps<Value extends string = string> {
2411
+ multiple?: false;
2412
+ value: NoInfer<Value>;
2413
+ renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
2414
+ /** Show only the selected choice icon while retaining the Select's accessible name. */
2415
+ selectedPresentation?: SelectSelectedPresentation;
2416
+ triggerIcon?: never;
2417
+ }
2418
+ /**
2419
+ * Any number of chosen values. The popup stays open while the person toggles
2420
+ * choices and closes on an outside click, Escape, or focus leaving; the closed
2421
+ * control summarizes the chosen labels in choice order.
2422
+ */
2423
+ interface SelectMultipleLabelProps<Value extends string = string> {
2424
+ multiple: true;
2425
+ value: readonly NoInfer<Value>[];
2426
+ renderSelected?: never;
2427
+ selectedPresentation?: 'label';
2428
+ triggerIcon?: never;
2429
+ }
2430
+ /**
2431
+ * A multiple Select drawn as an icon-only toolbar trigger, such as a
2432
+ * "Filter by label" funnel. No single choice is selected, so the trigger shows
2433
+ * a fixed `triggerIcon` naming the menu's purpose; while any choice is chosen
2434
+ * a count badge sits beside it, and the combobox's accessible name ends with
2435
+ * the chosen labels in choice order.
2436
+ */
2437
+ interface SelectMultipleIconProps<Value extends string = string> {
2438
+ multiple: true;
2439
+ value: readonly NoInfer<Value>[];
2440
+ renderSelected?: never;
2441
+ selectedPresentation: 'icon-only';
2442
+ /**
2443
+ * The trigger's fixed icon, typically a `LucideIcon` naming the menu's
2444
+ * purpose (a funnel for a filter), independent of the selection.
2445
+ */
2446
+ triggerIcon: KerfUiContent;
2447
+ }
2448
+ type SelectMultipleValueProps<Value extends string = string> = SelectMultipleLabelProps<Value> | SelectMultipleIconProps<Value>;
2449
+ type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName & (SelectSingleValueProps<Value> | SelectMultipleValueProps<Value>);
2450
+ declare function Select<Value extends string>(props: SelectProps<Value>): SafeHtml;
1911
2451
 
1912
- export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSize };
2452
+ export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectMultipleIconProps, type SelectMultipleLabelProps, type SelectMultipleValueProps, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSingleValueProps, type SelectSize };
1913
2453
  ```
1914
2454
 
1915
2455
  ## `@kerfjs/ui/state-banner`
@@ -2044,7 +2584,7 @@ export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
2044
2584
  ## `@kerfjs/ui/token-search-field`
2045
2585
 
2046
2586
  ```ts
2047
- import * as kerfjs from 'kerfjs';
2587
+ import { SafeHtml } from 'kerfjs';
2048
2588
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2049
2589
 
2050
2590
  interface TokenSearchToken {
@@ -2066,6 +2606,15 @@ interface TokenSearchFieldBaseProps {
2066
2606
  label: string;
2067
2607
  query?: string;
2068
2608
  tokens?: readonly TokenSearchToken[];
2609
+ /**
2610
+ * Editor identity for a programmatic text replacement. The editor's text is
2611
+ * DOM-owned between token changes, so a new `query` with the same tokens
2612
+ * does not re-render it (that would reset the caret on every keystroke).
2613
+ * Change `revision` when the app replaces the text itself — reseeding a
2614
+ * persistent dialog's field on reopen, applying a saved search — and the
2615
+ * editor is rebuilt from `query` and `tokens`.
2616
+ */
2617
+ revision?: string | number;
2069
2618
  placeholder?: string;
2070
2619
  tokenPlaceholder?: string;
2071
2620
  disabled?: boolean;
@@ -2078,6 +2627,8 @@ interface TokenSearchFieldBaseProps {
2078
2627
  removeAction?: string;
2079
2628
  clearAction?: string;
2080
2629
  clearLabel?: string;
2630
+ /** Icon for the clear button. Default: the Lucide `x` glyph token chips also use. */
2631
+ clearIcon?: SafeHtml;
2081
2632
  className?: string;
2082
2633
  editorAttributes?: TokenSearchEditorAttributes;
2083
2634
  /** Native named-slot assignment when composed inside a web component. */
@@ -2101,7 +2652,7 @@ interface TokenSearchFieldValue {
2101
2652
  query: string;
2102
2653
  tokens: TokenSearchToken[];
2103
2654
  }
2104
- declare function TokenSearchField({ id, label, query, tokens, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, slot, }: TokenSearchFieldProps): kerfjs.SafeHtml;
2655
+ 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;
2105
2656
  /** Read editable text and ordered token offsets from a rendered TokenSearchField editor. */
2106
2657
  declare function readTokenSearchField(editor: HTMLElement, knownTokens?: readonly TokenSearchToken[]): TokenSearchFieldValue;
2107
2658
  /** Focus an editor and place its caret at a text offset, skipping atomic token chips. */
@@ -2311,10 +2862,17 @@ import { SafeHtml } from 'kerfjs';
2311
2862
  type BadgeTone = 'neutral' | 'brand' | 'pop' | 'success' | 'warning' | 'danger';
2312
2863
  type BadgeAppearance = 'quiet' | 'solid' | 'outline';
2313
2864
  type BadgeShape = 'pill' | 'rounded';
2865
+ /** Size of a text badge. A text-free dot is the separate `size: 'dot'` form. */
2314
2866
  type BadgeSize = 'compact' | 'default';
2315
- interface BadgeProps {
2316
- children: SafeHtml | string | number;
2867
+ interface BadgeCommonProps {
2317
2868
  tone?: BadgeTone;
2869
+ className?: string;
2870
+ /** Native named-slot assignment when composed inside a web component. */
2871
+ slot?: string;
2872
+ }
2873
+ /** A badge that shows a short status, count, or category as visible text. */
2874
+ interface BadgeTextProps extends BadgeCommonProps {
2875
+ children: SafeHtml | string | number;
2318
2876
  appearance?: BadgeAppearance;
2319
2877
  shape?: BadgeShape;
2320
2878
  size?: BadgeSize;
@@ -2322,14 +2880,35 @@ interface BadgeProps {
2322
2880
  label?: string;
2323
2881
  /** Hide a repeated visual badge from assistive technology. */
2324
2882
  ariaHidden?: boolean;
2325
- className?: string;
2326
- /** Native named-slot assignment when composed inside a web component. */
2327
- slot?: string;
2328
2883
  }
2884
+ /** A labeled dot, announced as an image with its own accessible name. */
2885
+ interface BadgeDotLabeled {
2886
+ /** Accessible name for the dot, for example `"New activity"`. */
2887
+ label: string;
2888
+ ariaHidden?: false;
2889
+ }
2890
+ /** A decorative dot whose meaning the owning component already announces. */
2891
+ interface BadgeDotDecorative {
2892
+ label?: never;
2893
+ ariaHidden: true;
2894
+ }
2895
+ /**
2896
+ * A text-free status dot (the iOS "new content" dot): a small solid circle in
2897
+ * the badge's tone. It has no visible text, so it must either carry its own
2898
+ * accessible `label` (exposed as an image) or be `ariaHidden` because the
2899
+ * surrounding component already folds its meaning into an accessible name.
2900
+ */
2901
+ type BadgeDotProps = BadgeCommonProps & {
2902
+ size: 'dot';
2903
+ children?: never;
2904
+ appearance?: never;
2905
+ shape?: never;
2906
+ } & (BadgeDotLabeled | BadgeDotDecorative);
2907
+ type BadgeProps = BadgeTextProps | BadgeDotProps;
2329
2908
  /** Compact, non-interactive metadata whose tone, emphasis, and shape are configured by props. */
2330
- declare function Badge({ children, tone, appearance, shape, size, label, ariaHidden, className, slot, }: BadgeProps): SafeHtml;
2909
+ declare function Badge(props: BadgeProps): SafeHtml;
2331
2910
 
2332
- export { Badge, type BadgeAppearance, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTone };
2911
+ export { Badge, type BadgeAppearance, type BadgeDotProps, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTextProps, type BadgeTone };
2333
2912
  ```
2334
2913
 
2335
2914
  ## `@kerfjs/ui/lucide-icon`
@@ -2431,9 +3010,9 @@ export { Text, type TextBorder, type TextContent, type TextFont, type TextProps,
2431
3010
  ```ts
2432
3011
  import * as kerfjs from 'kerfjs';
2433
3012
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
2434
- import { S as Sides } from './divider-sides-BzB6rphT.js';
2435
3013
  import { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
2436
3014
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3015
+ import { S as Sides } from './sides-BPSWde0A.js';
2437
3016
 
2438
3017
  type RowRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
2439
3018
  'data-component'?: never;