@kerfjs/ui 5.0.0-beta.56 → 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 (282) hide show
  1. package/README.md +63 -32
  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/component-catalog.json +208 -32
  7. package/ai/component-catalog.schema.json +2 -0
  8. package/ai/component-class-owners.cjs +83 -0
  9. package/ai/component-composition-extension.d.ts +7 -0
  10. package/ai/component-composition-extension.schema.json +7 -0
  11. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +2 -1
  12. package/ai/{component-catalog-v2.d.ts → component-composition.d.ts} +9 -5
  13. package/ai/{component-catalog-v2.json → component-composition.json} +155 -24
  14. package/ai/{component-catalog-v2.schema.json → component-composition.schema.json} +21 -5
  15. package/ai/components/README.md +170 -0
  16. package/ai/components/application-tabs.md +65 -0
  17. package/ai/components/badge.md +72 -0
  18. package/ai/components/collapsible-panel.md +102 -0
  19. package/ai/components/content-item.md +90 -0
  20. package/ai/components/disclosure-arrow.md +77 -0
  21. package/ai/components/document-baseline.md +75 -0
  22. package/ai/components/empty-state.md +80 -0
  23. package/ai/components/feedback.md +71 -0
  24. package/ai/components/floating-toolbar.md +80 -0
  25. package/ai/components/foundation.md +65 -0
  26. package/ai/components/grid.md +93 -0
  27. package/ai/components/headers.md +63 -0
  28. package/ai/components/layout.md +75 -0
  29. package/ai/components/list-action-row.md +91 -0
  30. package/ai/components/list-header.md +89 -0
  31. package/ai/components/list-inset-control.md +74 -0
  32. package/ai/components/list-inset-text.md +72 -0
  33. package/ai/components/list-item.md +88 -0
  34. package/ai/components/list.md +103 -0
  35. package/ai/components/loading-spinner.md +72 -0
  36. package/ai/components/lucide-icon.md +66 -0
  37. package/ai/components/nav-stack.md +103 -0
  38. package/ai/components/pane.md +100 -0
  39. package/ai/components/popup-menu.md +82 -0
  40. package/ai/components/recipe-app-shell.md +57 -0
  41. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  42. package/ai/components/recipe-compact-toolbar.md +57 -0
  43. package/ai/components/recipe-composer-form.md +57 -0
  44. package/ai/components/recipe-list-detail-dialog.md +57 -0
  45. package/ai/components/recipe-list-workspace-states.md +57 -0
  46. package/ai/components/recipe-loading-inspector.md +57 -0
  47. package/ai/components/recipe-navigation-sidebar.md +57 -0
  48. package/ai/components/recipe-navigation-stack.md +57 -0
  49. package/ai/components/recipe-workspace-header.md +57 -0
  50. package/ai/components/resize.md +101 -0
  51. package/ai/components/row.md +96 -0
  52. package/ai/components/segmented-control.md +82 -0
  53. package/ai/components/select.md +107 -0
  54. package/ai/components/skeleton.md +84 -0
  55. package/ai/components/spacer.md +86 -0
  56. package/ai/components/split-view.md +102 -0
  57. package/ai/components/state-banner.md +92 -0
  58. package/ai/components/sunken-panel.md +79 -0
  59. package/ai/components/surface-scaffold.md +78 -0
  60. package/ai/components/tab-bar.md +112 -0
  61. package/ai/components/tab-scaffold.md +94 -0
  62. package/ai/components/tabs.md +90 -0
  63. package/ai/components/text.md +82 -0
  64. package/ai/components/token-search-field.md +101 -0
  65. package/ai/components/toolbar-control-group.md +100 -0
  66. package/ai/components/toolbar-text.md +76 -0
  67. package/ai/components/toolbar.md +95 -0
  68. package/ai/components/value-table.md +72 -0
  69. package/ai/components/wa-accordion-item.md +55 -0
  70. package/ai/components/wa-accordion.md +65 -0
  71. package/ai/components/wa-animated-image.md +55 -0
  72. package/ai/components/wa-animation.md +55 -0
  73. package/ai/components/wa-avatar.md +55 -0
  74. package/ai/components/wa-badge.md +55 -0
  75. package/ai/components/wa-breadcrumb-item.md +53 -0
  76. package/ai/components/wa-breadcrumb.md +55 -0
  77. package/ai/components/wa-button-group.md +59 -0
  78. package/ai/components/wa-button.md +55 -0
  79. package/ai/components/wa-callout.md +58 -0
  80. package/ai/components/wa-card.md +59 -0
  81. package/ai/components/wa-carousel-item.md +53 -0
  82. package/ai/components/wa-carousel.md +55 -0
  83. package/ai/components/wa-checkbox-group.md +55 -0
  84. package/ai/components/wa-checkbox.md +55 -0
  85. package/ai/components/wa-color-picker.md +55 -0
  86. package/ai/components/wa-comparison.md +55 -0
  87. package/ai/components/wa-copy-button.md +55 -0
  88. package/ai/components/wa-details.md +61 -0
  89. package/ai/components/wa-dialog.md +59 -0
  90. package/ai/components/wa-divider.md +53 -0
  91. package/ai/components/wa-drawer.md +55 -0
  92. package/ai/components/wa-dropdown-item.md +60 -0
  93. package/ai/components/wa-dropdown.md +60 -0
  94. package/ai/components/wa-format-bytes.md +53 -0
  95. package/ai/components/wa-format-date.md +53 -0
  96. package/ai/components/wa-format-number.md +53 -0
  97. package/ai/components/wa-icon.md +58 -0
  98. package/ai/components/wa-include.md +53 -0
  99. package/ai/components/wa-input.md +59 -0
  100. package/ai/components/wa-intersection-observer.md +53 -0
  101. package/ai/components/wa-known-date.md +53 -0
  102. package/ai/components/wa-markdown.md +53 -0
  103. package/ai/components/wa-mutation-observer.md +53 -0
  104. package/ai/components/wa-number-input.md +55 -0
  105. package/ai/components/wa-option.md +59 -0
  106. package/ai/components/wa-otp-input.md +53 -0
  107. package/ai/components/wa-page.md +53 -0
  108. package/ai/components/wa-pagination.md +55 -0
  109. package/ai/components/wa-popover.md +55 -0
  110. package/ai/components/wa-popup.md +53 -0
  111. package/ai/components/wa-progress-bar.md +53 -0
  112. package/ai/components/wa-progress-ring.md +53 -0
  113. package/ai/components/wa-qr-code.md +53 -0
  114. package/ai/components/wa-radio-group.md +59 -0
  115. package/ai/components/wa-radio.md +55 -0
  116. package/ai/components/wa-random-content.md +53 -0
  117. package/ai/components/wa-rating.md +55 -0
  118. package/ai/components/wa-relative-time.md +53 -0
  119. package/ai/components/wa-resize-observer.md +53 -0
  120. package/ai/components/wa-scroller.md +53 -0
  121. package/ai/components/wa-select.md +63 -0
  122. package/ai/components/wa-skeleton.md +53 -0
  123. package/ai/components/wa-slider.md +55 -0
  124. package/ai/components/wa-spinner.md +58 -0
  125. package/ai/components/wa-split-panel.md +58 -0
  126. package/ai/components/wa-switch.md +53 -0
  127. package/ai/components/wa-tab-group.md +69 -0
  128. package/ai/components/wa-tab-panel.md +60 -0
  129. package/ai/components/wa-tab.md +59 -0
  130. package/ai/components/wa-tag.md +59 -0
  131. package/ai/components/wa-textarea.md +53 -0
  132. package/ai/components/wa-time-input.md +55 -0
  133. package/ai/components/wa-toast-item.md +60 -0
  134. package/ai/components/wa-toast.md +60 -0
  135. package/ai/components/wa-tooltip.md +55 -0
  136. package/ai/components/wa-tree-item.md +55 -0
  137. package/ai/components/wa-tree.md +55 -0
  138. package/ai/components/wa-zoomable-frame.md +55 -0
  139. package/ai/components/workbench.md +114 -0
  140. package/ai/public-api-signatures-v1.md +161 -32
  141. package/ai/skill.md +100 -48
  142. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  143. package/analyzer/component-ownership.d.mts +56 -0
  144. package/analyzer/component-ownership.mjs +184 -0
  145. package/analyzer/index.d.mts +3 -0
  146. package/analyzer/index.mjs +274 -20
  147. package/analyzer/selectors.d.mts +21 -0
  148. package/analyzer/selectors.mjs +212 -0
  149. package/dist/browser/catalog.js +25 -0
  150. package/dist/browser/collapsible-panel.js +7 -0
  151. package/dist/browser/nav-stack.js +8 -0
  152. package/dist/browser/split-view.js +10 -0
  153. package/dist/browser/tab-scaffold.js +4 -0
  154. package/dist/browser/workbench.js +10 -0
  155. package/dist/catalog-resources.d.ts +2 -2
  156. package/dist/catalog.d.ts +3 -3
  157. package/dist/catalog.js +7 -6
  158. package/dist/catalog.js.map +1 -1
  159. package/dist/{chunk-PK4N5QTO.js → chunk-553ASUK6.js} +2 -3
  160. package/dist/chunk-553ASUK6.js.map +1 -0
  161. package/dist/{chunk-G33XC2NB.js → chunk-6YFHCLHG.js} +2 -2
  162. package/dist/chunk-6YFHCLHG.js.map +1 -0
  163. package/dist/{chunk-T4UZTNZ4.js → chunk-EVYKTVBQ.js} +2 -11
  164. package/dist/chunk-EVYKTVBQ.js.map +1 -0
  165. package/dist/{chunk-AK67F6QN.js → chunk-EZVNC4J6.js} +4 -1
  166. package/dist/chunk-EZVNC4J6.js.map +1 -0
  167. package/dist/{chunk-MA6Z6EIM.js → chunk-F4QMLOXJ.js} +3 -2
  168. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  169. package/dist/{chunk-QQOTQTDD.js → chunk-G2RKFVRB.js} +13 -10
  170. package/dist/chunk-G2RKFVRB.js.map +1 -0
  171. package/dist/chunk-JCV4GXWB.js +249 -0
  172. package/dist/chunk-JCV4GXWB.js.map +1 -0
  173. package/dist/chunk-K47P7QZC.js +17 -0
  174. package/dist/chunk-K47P7QZC.js.map +1 -0
  175. package/dist/{chunk-MOBRFZH3.js → chunk-OUK6QRDR.js} +2 -12
  176. package/dist/chunk-OUK6QRDR.js.map +1 -0
  177. package/dist/{chunk-O3EXIBEZ.js → chunk-PWXNJS2B.js} +7 -6
  178. package/dist/chunk-PWXNJS2B.js.map +1 -0
  179. package/dist/{chunk-VNPQDCQZ.js → chunk-QOWG4ZCL.js} +3 -2
  180. package/dist/chunk-QOWG4ZCL.js.map +1 -0
  181. package/dist/{chunk-V65EOWNF.js → chunk-XCO6YCYM.js} +5 -4
  182. package/dist/chunk-XCO6YCYM.js.map +1 -0
  183. package/dist/{chunk-K6UNVKDK.js → chunk-XDKAYSVD.js} +3 -1
  184. package/dist/chunk-XDKAYSVD.js.map +1 -0
  185. package/dist/collapsible-panel.d.ts +3 -3
  186. package/dist/collapsible-panel.js +2 -2
  187. package/dist/collapsible-panel.js.map +1 -1
  188. package/dist/index.d.ts +2 -1
  189. package/dist/index.js +10 -8
  190. package/dist/list-action-row.js +2 -1
  191. package/dist/list-header.js +1 -1
  192. package/dist/list-item.js +2 -1
  193. package/dist/nav-stack.d.ts +13 -1
  194. package/dist/nav-stack.js +1 -1
  195. package/dist/pane.d.ts +20 -3
  196. package/dist/pane.js +1 -1
  197. package/dist/{panel-toolbar-C8sF-YZC.d.ts → panel-toolbar-BN4x0rth.d.ts} +3 -2
  198. package/dist/select.js +1 -1
  199. package/dist/split-view.d.ts +3 -3
  200. package/dist/split-view.js +3 -2
  201. package/dist/split-view.js.map +1 -1
  202. package/dist/state-banner.js +1 -1
  203. package/dist/styles/app-tab.css +31 -0
  204. package/dist/styles/badge.css +19 -11
  205. package/dist/styles/collapsible-panel.css +13 -9
  206. package/dist/styles/floating-toolbar.css +25 -6
  207. package/dist/styles/list-header.css +0 -12
  208. package/dist/styles/list.css +4 -4
  209. package/dist/styles/nav-stack.css +46 -19
  210. package/dist/styles/pane.css +50 -0
  211. package/dist/styles/popup-menu.css +151 -0
  212. package/dist/styles/resizable-region.css +22 -10
  213. package/dist/styles/select.css +28 -14
  214. package/dist/styles/skeleton.css +30 -3
  215. package/dist/styles/split-view.css +10 -7
  216. package/dist/styles/state-banner.css +0 -19
  217. package/dist/styles/surface-scaffold.css +8 -3
  218. package/dist/styles/tab-bar.css +79 -28
  219. package/dist/styles/tab-scaffold.css +25 -1
  220. package/dist/styles/text.css +16 -0
  221. package/dist/styles/toolbar-control-group.css +121 -66
  222. package/dist/styles/toolbar-text.css +21 -0
  223. package/dist/styles/toolbar.css +8 -32
  224. package/dist/styles/workbench.css +18 -18
  225. package/dist/tab-scaffold.d.ts +11 -1
  226. package/dist/tab-scaffold.js +2 -0
  227. package/dist/tab-scaffold.js.map +1 -1
  228. package/dist/toolbar-text.d.ts +7 -1
  229. package/dist/toolbar-text.js +1 -1
  230. package/dist/toolbar.d.ts +8 -1
  231. package/dist/toolbar.js +1 -1
  232. package/dist/{types-DXAGogOS.d.ts → types-BuHELdXR.d.ts} +1 -1
  233. package/dist/wire-catalog.d.ts +3 -1
  234. package/dist/wire-catalog.js +2 -0
  235. package/dist/wire-catalog.js.map +1 -1
  236. package/dist/wire-scroll-dividers.d.ts +69 -0
  237. package/dist/wire-scroll-dividers.js +3 -0
  238. package/dist/wire-scroll-dividers.js.map +1 -0
  239. package/dist/workbench.d.ts +13 -12
  240. package/dist/workbench.js +1 -1
  241. package/docs/app-layouts.md +9 -1
  242. package/docs/catalog.md +10 -5
  243. package/docs/collapsible-panel.md +10 -6
  244. package/docs/component-contract.md +147 -21
  245. package/docs/component-selection.md +18 -6
  246. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  247. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  248. package/docs/design/templates/tab-bar-dark.svg +1 -1
  249. package/docs/design/templates/tab-bar.svg +1 -1
  250. package/docs/design-philosophy.md +30 -3
  251. package/docs/examples/application-ui-profile.json +4 -4
  252. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +3 -3
  253. package/docs/layout.md +82 -3
  254. package/docs/nav-stack.md +33 -3
  255. package/docs/split-view.md +10 -5
  256. package/docs/tab-scaffold.md +23 -1
  257. package/docs/type-contracts.md +4 -3
  258. package/docs/ui-analyzer.md +99 -5
  259. package/docs/ui-doctor.md +10 -0
  260. package/docs/workbench.md +19 -9
  261. package/doctor/index.mjs +6 -1
  262. package/llms.txt +85 -20
  263. package/package.json +17 -5
  264. package/ux-demo/recipes/collapsible-sidebar.tsx +0 -1
  265. package/ux-demo/recipes/composer-form.tsx +0 -1
  266. package/ux-demo/recipes/list-detail-dialog.tsx +0 -2
  267. package/ux-demo/recipes/list-workspace-states.tsx +0 -1
  268. package/ux-demo/recipes/loading-inspector.tsx +0 -1
  269. package/ux-demo/recipes/workspace-header.tsx +0 -1
  270. package/ai/component-catalog-extension-v2.d.ts +0 -7
  271. package/ai/component-catalog-extension-v2.schema.json +0 -7
  272. package/dist/chunk-AK67F6QN.js.map +0 -1
  273. package/dist/chunk-G33XC2NB.js.map +0 -1
  274. package/dist/chunk-K6UNVKDK.js.map +0 -1
  275. package/dist/chunk-MA6Z6EIM.js.map +0 -1
  276. package/dist/chunk-MOBRFZH3.js.map +0 -1
  277. package/dist/chunk-O3EXIBEZ.js.map +0 -1
  278. package/dist/chunk-PK4N5QTO.js.map +0 -1
  279. package/dist/chunk-QQOTQTDD.js.map +0 -1
  280. package/dist/chunk-T4UZTNZ4.js.map +0 -1
  281. package/dist/chunk-V65EOWNF.js.map +0 -1
  282. package/dist/chunk-VNPQDCQZ.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.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.
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
 
@@ -151,7 +151,14 @@ interface ToolbarProps {
151
151
  center?: KerfUiContent;
152
152
  trailing?: KerfUiContent;
153
153
  label?: string;
154
- /** Physical divider edges in canonical top/right/bottom/left order. Defaults to bottom. */
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
+ */
155
162
  dividerSides?: Sides;
156
163
  /** Horizontal treatment of the center zone. Defaults to centered content. */
157
164
  centerAlign?: 'center' | 'stretch';
@@ -224,6 +231,12 @@ interface ToolbarTextBaseProps {
224
231
  * instead. Default true.
225
232
  */
226
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;
227
240
  /** Native named-slot assignment when composed inside a web component. */
228
241
  slot?: string;
229
242
  }
@@ -236,7 +249,7 @@ type ToolbarTextWrappingProps = {
236
249
  maxLines?: never;
237
250
  };
238
251
  type ToolbarTextProps = ToolbarTextBaseProps & ToolbarTextWrappingProps;
239
- 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;
240
253
 
241
254
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
242
255
  ```
@@ -1018,6 +1031,80 @@ declare function wireTabBars(root: HTMLElement | Document, { onReorder, activati
1018
1031
  export { TabActivation, type TabDropPosition, type TabReorder, type TabReorderSource, type WireTabBarsOptions, reorderTabs, wireTabBars };
1019
1032
  ```
1020
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
+
1021
1108
  ## `@kerfjs/ui/nav-stack`
1022
1109
 
1023
1110
  ```ts
@@ -1082,6 +1169,18 @@ interface NavStackProps {
1082
1169
  hideToolbar?: boolean;
1083
1170
  /** Optional persistent bottom toolbar used when the active view does not provide one. */
1084
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';
1085
1184
  className?: string;
1086
1185
  /** Native named-slot assignment when composed inside a web component. */
1087
1186
  slot?: string;
@@ -1094,7 +1193,7 @@ interface NavStackProps {
1094
1193
  * content fills the zones, and `toolbarConfig` configures it. A single-pane
1095
1194
  * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.
1096
1195
  */
1097
- declare function NavStack({ id, label, views, backLabel, backIcon, backText, toolbarConfig, 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;
1098
1197
 
1099
1198
  export { NavStack, type NavStackProps, type NavStackToolbarConfig, type NavStackView };
1100
1199
  ```
@@ -1150,10 +1249,10 @@ interface SplitViewResizable extends Pick<ResizableRegionProps, 'separator' | 'h
1150
1249
  type SplitViewCompactViewToolbars = Pick<NavStackView, 'leading' | 'center' | 'toolbar' | 'bottomToolbar'>;
1151
1250
  /**
1152
1251
  * 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.
1252
+ * control, persistent bottom toolbar, and chrome dividers forward to the
1253
+ * stack, and `list` / `detail` give each view its own toolbar groups.
1155
1254
  */
1156
- interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar'> {
1255
+ interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar' | 'chromeDividers'> {
1157
1256
  /** Toolbar content for the list (root) view. */
1158
1257
  list?: SplitViewCompactViewToolbars;
1159
1258
  /** Toolbar content for the pushed detail view. */
@@ -1226,9 +1325,16 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
1226
1325
  'data-safe-area-inline-start'?: never;
1227
1326
  'data-safe-area-inline-end'?: never;
1228
1327
  'data-chrome-placement'?: never;
1328
+ 'data-chrome-dividers'?: never;
1229
1329
  }>;
1230
1330
  /** How a Pane's header and footer relate to its scrolling content. */
1231
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';
1232
1338
  interface PaneProps {
1233
1339
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
1234
1340
  header?: KerfUiContent;
@@ -1244,6 +1350,16 @@ interface PaneProps {
1244
1350
  * squeeze the content to nothing.
1245
1351
  */
1246
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;
1247
1363
  /** Root semantics. Defaults to `div`. */
1248
1364
  element?: PaneElement;
1249
1365
  /** Scrolling content semantics. Defaults to `div`. */
@@ -1278,16 +1394,16 @@ interface PaneProps {
1278
1394
  * or a CollapsiblePanel) forwards, so the app configures that pane instead of
1279
1395
  * styling it. An omitted or `undefined` field keeps the composite's default.
1280
1396
  */
1281
- type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges'>;
1397
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers'>;
1282
1398
  /**
1283
1399
  * An unpadded application column with optional fixed header/footer slots and one
1284
1400
  * scrolling vertical content owner. Separator lines are independently opt-in on
1285
1401
  * each logical edge, so the same component works as a sidebar, main area,
1286
1402
  * inspector, or dialog column.
1287
1403
  */
1288
- declare function Pane({ header, children, footer, chromePlacement, 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;
1289
1405
 
1290
- export { Pane, type PaneChromePlacement, type PaneConfig, 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 };
1291
1407
  ```
1292
1408
 
1293
1409
  ## `@kerfjs/ui/workbench`
@@ -1298,7 +1414,7 @@ import { ListConfig } from './list.js';
1298
1414
  import { PaneConfig } from './pane.js';
1299
1415
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1300
1416
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1301
- import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-C8sF-YZC.js';
1417
+ import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BN4x0rth.js';
1302
1418
  import { ToolbarConfig } from './toolbar.js';
1303
1419
  import './css-values.js';
1304
1420
  import './flex-alignment-4ms8ZbV8.js';
@@ -1319,9 +1435,9 @@ type WorkbenchPanelToggle = PanelToggle;
1319
1435
  type WorkbenchPanelToolbar = PanelToolbar;
1320
1436
  /**
1321
1437
  * 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).
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`).
1325
1441
  */
1326
1442
  interface WorkbenchMainToolbar extends ToolbarConfig {
1327
1443
  label: string;
@@ -1335,9 +1451,9 @@ interface WorkbenchMainToolbar extends ToolbarConfig {
1335
1451
  }
1336
1452
  /**
1337
1453
  * 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.
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`).
1341
1457
  */
1342
1458
  interface WorkbenchMainBottomToolbar extends ToolbarConfig {
1343
1459
  label: string;
@@ -1387,7 +1503,7 @@ interface WorkbenchPanel {
1387
1503
  footer?: KerfUiContent;
1388
1504
  /**
1389
1505
  * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1390
- * `contentLabel`, `separators`, `safeAreaEdges`) — for example
1506
+ * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
1391
1507
  * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1392
1508
  * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1393
1509
  * without a `toolbar`, where `content` renders as given.
@@ -1480,7 +1596,7 @@ interface WorkbenchProps {
1480
1596
  mainFooterPlacement?: WorkbenchChromePlacement;
1481
1597
  /**
1482
1598
  * Configuration for the work area's `Pane` (`contentElement`,
1483
- * `contentLabel`, `separators`, `safeAreaEdges`), which it has whenever it
1599
+ * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`), which it has whenever it
1484
1600
  * has a toolbar, `mainHeader`, or `mainFooter`; without that chrome, `main`
1485
1601
  * renders as given and this is ignored. Omitted or `undefined` fields keep
1486
1602
  * the `Pane` defaults.
@@ -1489,12 +1605,13 @@ interface WorkbenchProps {
1489
1605
  /**
1490
1606
  * Configuration for the `List` that holds `mainHeader` (`gap`, `hAlign`,
1491
1607
  * `vAlign`, `dividerSides`, `textInsets`, `controlInsets`). Omitted or
1492
- * `undefined` fields keep the defaults, including its bottom divider.
1608
+ * `undefined` fields keep the defaults (no divider: the work area's
1609
+ * `Pane` draws the line under its header chrome).
1493
1610
  */
1494
1611
  mainHeaderList?: ListConfig;
1495
1612
  /**
1496
- * The same for the `List` that holds `mainFooter`; by default it draws a
1497
- * top divider, or none when a `mainBottomToolbar` follows it.
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).
1498
1615
  */
1499
1616
  mainFooterList?: ListConfig;
1500
1617
  leftRail?: WorkbenchPanel;
@@ -1657,8 +1774,8 @@ export { type WireWorkbenchOptions, type WireWorkbenchPanel, type WorkbenchPanel
1657
1774
  ```ts
1658
1775
  import { SafeHtml } from 'kerfjs';
1659
1776
  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';
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';
1662
1779
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1663
1780
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1664
1781
  import './lucide-icon.js';
@@ -1724,7 +1841,7 @@ interface CollapsiblePanelProps {
1724
1841
  footer?: KerfUiContent;
1725
1842
  /**
1726
1843
  * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1727
- * `contentLabel`, `separators`, `safeAreaEdges`) — for example
1844
+ * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
1728
1845
  * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1729
1846
  * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1730
1847
  * without a `toolbar`, where `children` renders as given.
@@ -1901,6 +2018,16 @@ interface TabScaffoldProps<Id extends string = string> {
1901
2018
  tabs: readonly TabScaffoldTab<Id>[];
1902
2019
  /** The controlled active tab id (the app owns selection). */
1903
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';
1904
2031
  className?: string;
1905
2032
  /** Native named-slot assignment when composed inside a web component. */
1906
2033
  slot?: string;
@@ -1913,7 +2040,7 @@ interface TabScaffoldProps<Id extends string = string> {
1913
2040
  * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
1914
2041
  * a bottom bar. See `docs/23-app-layouts.md` §3.4.
1915
2042
  */
1916
- 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;
1917
2044
 
1918
2045
  export { TabScaffold, type TabScaffoldProps, type TabScaffoldTab };
1919
2046
  ```
@@ -2079,8 +2206,8 @@ export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type Dev
2079
2206
  ```ts
2080
2207
  import * as kerfjs from 'kerfjs';
2081
2208
  import { SafeHtml } from 'kerfjs';
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';
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';
2084
2211
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2085
2212
  import './toolbar.js';
2086
2213
  import './pane.js';
@@ -2090,7 +2217,7 @@ import './list.js';
2090
2217
  import './css-values.js';
2091
2218
  import './flex-alignment-4ms8ZbV8.js';
2092
2219
  import './resizable-region.js';
2093
- import './panel-toolbar-C8sF-YZC.js';
2220
+ import './panel-toolbar-BN4x0rth.js';
2094
2221
  import './lucide-icon.js';
2095
2222
  import 'lucide';
2096
2223
 
@@ -2172,7 +2299,7 @@ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleP
2172
2299
  ## `@kerfjs/ui/catalog-resources`
2173
2300
 
2174
2301
  ```ts
2175
- import { C as CatalogResource } from './types-DXAGogOS.js';
2302
+ import { C as CatalogResource } from './types-BuHELdXR.js';
2176
2303
  import './semantic-content-BbzjvSu9.js';
2177
2304
  import 'kerfjs';
2178
2305
  import './toolbar.js';
@@ -2183,7 +2310,7 @@ import './list.js';
2183
2310
  import './css-values.js';
2184
2311
  import './flex-alignment-4ms8ZbV8.js';
2185
2312
  import './resizable-region.js';
2186
- import './panel-toolbar-C8sF-YZC.js';
2313
+ import './panel-toolbar-BN4x0rth.js';
2187
2314
  import './lucide-icon.js';
2188
2315
  import 'lucide';
2189
2316
 
@@ -2298,7 +2425,9 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
2298
2425
  * item selection (and the related-entry popup menu), the sidebar collapse toggle, and
2299
2426
  * the theme toggle. The app owns the `active`/`collapsed`/`theme` signals and updates
2300
2427
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
2301
- * 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.
2302
2431
  */
2303
2432
  declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
2304
2433