@kerfjs/ui 5.0.0-beta.61 → 5.0.0-beta.63

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 (191) hide show
  1. package/README.md +4 -0
  2. package/ai/component-catalog-extension.schema.json +13 -0
  3. package/ai/component-catalog.json +20 -7
  4. package/ai/component-composition.json +17 -3
  5. package/ai/components/list-item.md +1 -1
  6. package/ai/components/pane.md +3 -2
  7. package/ai/components/select.md +1 -0
  8. package/ai/components/toolbar-text.md +2 -1
  9. package/ai/components/workbench.md +3 -2
  10. package/ai/public-api-signatures-v1.md +162 -48
  11. package/ai/skill.md +11 -5
  12. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  13. package/analyzer/index.mjs +3 -2
  14. package/catalog-projection-cli.mjs +96 -0
  15. package/catalog-projection.d.mts +55 -0
  16. package/catalog-projection.mjs +62 -0
  17. package/dist/browser/catalog.js +1 -1
  18. package/dist/browser/collapsible-panel.js +2 -0
  19. package/dist/browser/nav-stack.js +1 -0
  20. package/dist/browser/split-view.js +1 -0
  21. package/dist/browser/toolbar-control-group.js +1 -0
  22. package/dist/browser/workbench.js +1 -0
  23. package/dist/catalog-resources.d.ts +1 -1
  24. package/dist/catalog.d.ts +1 -1
  25. package/dist/catalog.js +11 -10
  26. package/dist/catalog.js.map +1 -1
  27. package/dist/chip.d.ts +9 -3
  28. package/dist/chip.js +1 -1
  29. package/dist/{chunk-EZVNC4J6.js → chunk-3BYFWTP3.js} +7 -3
  30. package/dist/chunk-3BYFWTP3.js.map +1 -0
  31. package/dist/{chunk-5Q3N6EV7.js → chunk-5IJ6UGNZ.js} +3 -3
  32. package/dist/{chunk-5Q3N6EV7.js.map → chunk-5IJ6UGNZ.js.map} +1 -1
  33. package/dist/chunk-7AKGPBCC.js +76 -0
  34. package/dist/chunk-7AKGPBCC.js.map +1 -0
  35. package/dist/{chunk-KROD7KZK.js → chunk-AUVG54KC.js} +2 -2
  36. package/dist/{chunk-KROD7KZK.js.map → chunk-AUVG54KC.js.map} +1 -1
  37. package/dist/{chunk-AUKT3KMG.js → chunk-CQHN45XR.js} +17 -2
  38. package/dist/chunk-CQHN45XR.js.map +1 -0
  39. package/dist/{chunk-SWVW56CV.js → chunk-EN4LDR5Y.js} +2 -2
  40. package/dist/{chunk-SWVW56CV.js.map → chunk-EN4LDR5Y.js.map} +1 -1
  41. package/dist/{chunk-TEYARRAK.js → chunk-F7OCOBTG.js} +5 -2
  42. package/dist/chunk-F7OCOBTG.js.map +1 -0
  43. package/dist/{chunk-5PESG2VP.js → chunk-HXCMWANP.js} +6 -5
  44. package/dist/chunk-HXCMWANP.js.map +1 -0
  45. package/dist/{chunk-NYL63PSD.js → chunk-IA4D5XNT.js} +61 -10
  46. package/dist/chunk-IA4D5XNT.js.map +1 -0
  47. package/dist/{chunk-F4QMLOXJ.js → chunk-IAOAZUOO.js} +2 -2
  48. package/dist/{chunk-F4QMLOXJ.js.map → chunk-IAOAZUOO.js.map} +1 -1
  49. package/dist/{chunk-Y74NWGQW.js → chunk-KFYANKJI.js} +66 -22
  50. package/dist/chunk-KFYANKJI.js.map +1 -0
  51. package/dist/chunk-MOSIE4Z2.js +51 -0
  52. package/dist/chunk-MOSIE4Z2.js.map +1 -0
  53. package/dist/{chunk-7JUBXOIV.js → chunk-NXWE5S57.js} +25 -6
  54. package/dist/chunk-NXWE5S57.js.map +1 -0
  55. package/dist/{chunk-NNMLEDMD.js → chunk-OBAFAH5B.js} +36 -8
  56. package/dist/chunk-OBAFAH5B.js.map +1 -0
  57. package/dist/{chunk-A3CKOW2R.js → chunk-R75GGNWY.js} +123 -20
  58. package/dist/chunk-R75GGNWY.js.map +1 -0
  59. package/dist/chunk-RGS4WX2M.js +44 -0
  60. package/dist/chunk-RGS4WX2M.js.map +1 -0
  61. package/dist/{chunk-N3GKMPDW.js → chunk-RKTTF3L4.js} +3 -1
  62. package/dist/chunk-RKTTF3L4.js.map +1 -0
  63. package/dist/{chunk-RRB26JRJ.js → chunk-RTJNJTG3.js} +2 -2
  64. package/dist/{chunk-RRB26JRJ.js.map → chunk-RTJNJTG3.js.map} +1 -1
  65. package/dist/{chunk-EAC4CDY7.js → chunk-SMZGAPCU.js} +15 -2
  66. package/dist/chunk-SMZGAPCU.js.map +1 -0
  67. package/dist/{chunk-C4OYOKWX.js → chunk-UA6JW52D.js} +36 -2
  68. package/dist/chunk-UA6JW52D.js.map +1 -0
  69. package/dist/{chunk-3SXMEK3B.js → chunk-V3DX3K65.js} +1 -1
  70. package/dist/chunk-V3DX3K65.js.map +1 -0
  71. package/dist/{chunk-6ZXOQEAN.js → chunk-WF75U3V4.js} +7 -1
  72. package/dist/chunk-WF75U3V4.js.map +1 -0
  73. package/dist/{chunk-VCBTX62E.js → chunk-ZRWXFDDS.js} +2 -2
  74. package/dist/chunk-ZRWXFDDS.js.map +1 -0
  75. package/dist/collapsible-panel.d.ts +18 -7
  76. package/dist/collapsible-panel.js +19 -3
  77. package/dist/collapsible-panel.js.map +1 -1
  78. package/dist/content-item.d.ts +36 -5
  79. package/dist/content-item.js +1 -1
  80. package/dist/disclosure-arrow.js +2 -1
  81. package/dist/index.d.ts +3 -3
  82. package/dist/index.js +22 -22
  83. package/dist/list-action-row.js +1 -1
  84. package/dist/list-header.js +1 -1
  85. package/dist/list-item.js +1 -1
  86. package/dist/lucide-icon.d.ts +5 -2
  87. package/dist/lucide-icon.js +2 -1
  88. package/dist/nav-stack.d.ts +3 -1
  89. package/dist/nav-stack.js +2 -1
  90. package/dist/pane.d.ts +10 -4
  91. package/dist/pane.js +1 -1
  92. package/dist/{panel-toolbar-DqwtBxQL.d.ts → panel-toolbar-DDKh4uKd.d.ts} +11 -2
  93. package/dist/popup-menu-register.js +38 -1
  94. package/dist/popup-menu-register.js.map +1 -1
  95. package/dist/popup-menu.d.ts +2 -2
  96. package/dist/popup-menu.js +1 -1
  97. package/dist/select.d.ts +2 -0
  98. package/dist/select.js +1 -1
  99. package/dist/split-view.d.ts +1 -1
  100. package/dist/split-view.js +2 -1
  101. package/dist/split-view.js.map +1 -1
  102. package/dist/styles/app-tab.css +84 -0
  103. package/dist/styles/chip.css +14 -0
  104. package/dist/styles/content-item.css +36 -0
  105. package/dist/styles/list-action-row.css +4 -3
  106. package/dist/styles/list-header.css +4 -3
  107. package/dist/styles/list-item.css +21 -11
  108. package/dist/styles/lucide-icon.css +5 -0
  109. package/dist/styles/nav-stack.css +13 -0
  110. package/dist/styles/pane.css +36 -2
  111. package/dist/styles/popup-menu.css +15 -10
  112. package/dist/styles/resizable-region.css +9 -0
  113. package/dist/styles/select.css +26 -0
  114. package/dist/styles/split-view.css +6 -0
  115. package/dist/styles/sunken-panel.css +7 -0
  116. package/dist/styles/tab-bar.css +3 -0
  117. package/dist/styles/tab-scaffold.css +13 -0
  118. package/dist/styles/text.css +29 -0
  119. package/dist/styles/token-search-field.css +29 -6
  120. package/dist/styles/toolbar-control-group.css +35 -0
  121. package/dist/styles/toolbar-text.css +15 -6
  122. package/dist/styles/toolbar.css +7 -0
  123. package/dist/styles/workbench.css +260 -90
  124. package/dist/sunken-panel.d.ts +6 -1
  125. package/dist/sunken-panel.js +1 -1
  126. package/dist/tab-bar.d.ts +6 -2
  127. package/dist/tab-bar.js +1 -1
  128. package/dist/tab-scaffold.d.ts +3 -0
  129. package/dist/tab-scaffold.js +1 -0
  130. package/dist/tab-scaffold.js.map +1 -1
  131. package/dist/text.d.ts +14 -3
  132. package/dist/text.js +1 -1
  133. package/dist/token-search-field.js +2 -1
  134. package/dist/toolbar-control-group.d.ts +5 -1
  135. package/dist/toolbar-control-group.js +2 -1
  136. package/dist/toolbar-text.d.ts +1 -1
  137. package/dist/toolbar-text.js +1 -1
  138. package/dist/toolbar.d.ts +7 -4
  139. package/dist/toolbar.js +1 -1
  140. package/dist/wire-catalog.js +1 -1
  141. package/dist/wire-content-items.d.ts +9 -0
  142. package/dist/wire-content-items.js +62 -0
  143. package/dist/wire-content-items.js.map +1 -0
  144. package/dist/wire-tab-bars.js +1 -1
  145. package/dist/wire-token-search-fields.js +2 -1
  146. package/dist/wire-workbench.d.ts +7 -0
  147. package/dist/wire-workbench.js +1 -1
  148. package/dist/workbench.d.ts +24 -8
  149. package/dist/workbench.js +2 -1
  150. package/docs/accessibility.md +21 -5
  151. package/docs/catalog.md +36 -0
  152. package/docs/collapsible-panel.md +12 -4
  153. package/docs/component-contract.md +10 -4
  154. package/docs/component-selection.md +65 -15
  155. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
  156. package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
  157. package/docs/design/templates/toolbar-dark.svg +1 -1
  158. package/docs/design/templates/toolbar.svg +1 -1
  159. package/docs/examples/component-catalog-extension.json +6 -0
  160. package/docs/layout.md +61 -3
  161. package/docs/nav-stack.md +5 -0
  162. package/docs/split-view.md +5 -0
  163. package/docs/sunken-panel.md +30 -1
  164. package/docs/tab-scaffold.md +5 -0
  165. package/docs/ui-analyzer.md +4 -0
  166. package/docs/webawesome-theme.md +36 -6
  167. package/docs/workbench.md +60 -14
  168. package/llms.txt +12 -4
  169. package/package.json +16 -2
  170. package/scripts/component-catalog-extension-validation.mjs +28 -0
  171. package/dist/chunk-3SXMEK3B.js.map +0 -1
  172. package/dist/chunk-4R777DUZ.js +0 -34
  173. package/dist/chunk-4R777DUZ.js.map +0 -1
  174. package/dist/chunk-5PESG2VP.js.map +0 -1
  175. package/dist/chunk-6ZXOQEAN.js.map +0 -1
  176. package/dist/chunk-7JUBXOIV.js.map +0 -1
  177. package/dist/chunk-A3CKOW2R.js.map +0 -1
  178. package/dist/chunk-AUKT3KMG.js.map +0 -1
  179. package/dist/chunk-C4OYOKWX.js.map +0 -1
  180. package/dist/chunk-EAC4CDY7.js.map +0 -1
  181. package/dist/chunk-EZVNC4J6.js.map +0 -1
  182. package/dist/chunk-MA73TA6D.js +0 -42
  183. package/dist/chunk-MA73TA6D.js.map +0 -1
  184. package/dist/chunk-MERWRTBG.js +0 -45
  185. package/dist/chunk-MERWRTBG.js.map +0 -1
  186. package/dist/chunk-N3GKMPDW.js.map +0 -1
  187. package/dist/chunk-NNMLEDMD.js.map +0 -1
  188. package/dist/chunk-NYL63PSD.js.map +0 -1
  189. package/dist/chunk-TEYARRAK.js.map +0 -1
  190. package/dist/chunk-VCBTX62E.js.map +0 -1
  191. package/dist/chunk-Y74NWGQW.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.61` and `kerfjs@5.0.0-beta.61`. 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.63` and `kerfjs@5.0.0-beta.63`. 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
 
@@ -146,11 +146,14 @@ import { PaneSeparatorSide } from './pane.js';
146
146
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
147
147
  import { S as Sides } from './sides-BPSWde0A.js';
148
148
 
149
+ type ToolbarPosition = 'header' | 'footer';
149
150
  interface ToolbarProps {
150
151
  leading?: KerfUiContent;
151
152
  center?: KerfUiContent;
152
153
  trailing?: KerfUiContent;
153
154
  label?: string;
155
+ /** Use footer semantics for a bottom toolbar; defaults to header. */
156
+ position?: ToolbarPosition;
154
157
  /**
155
158
  * Physical divider edges in canonical top/right/bottom/left order, drawn
156
159
  * always. Defaults to none: a toolbar pinned over or under scrolling content
@@ -160,8 +163,8 @@ interface ToolbarProps {
160
163
  * then draws its facing side the same way.
161
164
  */
162
165
  dividerSides?: Sides;
163
- /** Horizontal treatment of the center zone. Defaults to centered content. */
164
- centerAlign?: 'center' | 'stretch';
166
+ /** `balanced` gives both side zones equal tracks, centering the middle zone on the toolbar even if only one side has controls. */
167
+ centerAlign?: 'center' | 'stretch' | 'balanced';
165
168
  /**
166
169
  * Component-owned responsive layout; applications choose the policy rather
167
170
  * than restyling toolbar internals. Under every policy the trailing zone
@@ -200,9 +203,9 @@ interface ToolbarProps {
200
203
  * toolbar) forwards, so the app configures that toolbar instead of styling it.
201
204
  */
202
205
  type ToolbarConfig = Pick<ToolbarProps, 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
203
- declare function Toolbar({ leading, center, trailing, label, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
206
+ declare function Toolbar({ leading, center, trailing, label, position, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
204
207
 
205
- export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
208
+ export { Sides, Toolbar, type ToolbarConfig, type ToolbarPosition, type ToolbarProps };
206
209
  ```
207
210
 
208
211
  ## `@kerfjs/ui/toolbar-text`
@@ -210,7 +213,7 @@ export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
210
213
  ```ts
211
214
  import * as kerfjs from 'kerfjs';
212
215
 
213
- type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small' | 'xsmall';
216
+ type ToolbarTextSize = 'xlarge' | 'xlarge-fixed' | 'large' | 'default' | 'small' | 'xsmall';
214
217
  /** ARIA heading level for a title exposed as a heading landmark. */
215
218
  type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
216
219
  interface ToolbarTextBaseProps {
@@ -321,6 +324,10 @@ interface ToolbarControlGroupProps {
321
324
  relocateOnCollapse?: boolean;
322
325
  /** Add contrast behind photo-backed avatar content. */
323
326
  scrim?: boolean;
327
+ /** Block the group's controls and show a spinner without changing its dimensions. */
328
+ busy?: boolean;
329
+ /** Announced status while busy; defaults to “Working”. */
330
+ busyLabel?: string;
324
331
  /**
325
332
  * Avatar image URL. A single-control group paints it on the group; a
326
333
  * multi-control group paints it only on the pressed selection highlight.
@@ -329,7 +336,7 @@ interface ToolbarControlGroupProps {
329
336
  /** Native named-slot assignment when composed inside a web component. */
330
337
  slot?: string;
331
338
  }
332
- declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, size, density, content, focusRing, selectedChrome, selectedTone, nestedDropdown, menuInset, overflow, visibility, relocateOnCollapse, scrim, avatarImage, slot, }: ToolbarControlGroupProps): kerfjs.SafeHtml;
339
+ declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, size, density, content, focusRing, selectedChrome, selectedTone, nestedDropdown, menuInset, overflow, visibility, relocateOnCollapse, scrim, busy, busyLabel, avatarImage, slot, }: ToolbarControlGroupProps): kerfjs.SafeHtml;
333
340
 
334
341
  export { ToolbarActionLink, type ToolbarActionLinkProps, ToolbarControlGroup, type ToolbarControlGroupAppearance, type ToolbarControlGroupButtonAppearance, type ToolbarControlGroupContent, type ToolbarControlGroupDensity, type ToolbarControlGroupFocusRing, type ToolbarControlGroupMenuInset, type ToolbarControlGroupOverflow, type ToolbarControlGroupProps, type ToolbarControlGroupSelectedChrome, type ToolbarControlGroupSelectedTone, type ToolbarControlGroupShape, type ToolbarControlGroupSize, type ToolbarControlGroupTone, type ToolbarControlGroupVisibility };
335
342
  ```
@@ -413,9 +420,9 @@ interface PopupMenuItem {
413
420
  value?: string;
414
421
  /** Leading icon, typically a `LucideIcon`; it is placed in the item's icon slot. */
415
422
  icon?: SafeHtml;
416
- /** A checked menu choice, including nested choices. */
423
+ /** A checkbox choice, including nested choices; omit for a plain command. */
417
424
  checked?: boolean;
418
- /** Trailing safe content, such as a selected-choice tick. */
425
+ /** Trailing safe content, such as secondary status. */
419
426
  details?: SafeHtml;
420
427
  /** Destructive command styling. */
421
428
  tone?: 'default' | 'danger';
@@ -870,10 +877,22 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
870
877
  type ContentItemFrame = 'none' | 'framed';
871
878
  /** Corner shape: the 12px rounded rectangle or the 22px pill. */
872
879
  type ContentItemShape = 'rounded' | 'pill';
880
+ /** `single` uses option selection; `toggle` uses a pressed button. */
881
+ type ContentItemSelectionMode = 'none' | 'single' | 'toggle';
873
882
  type ContentItemRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
874
883
  'data-component'?: never;
875
884
  }>;
876
- interface ContentItemProps {
885
+ type ContentItemInteractiveRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
886
+ 'data-component'?: never;
887
+ 'data-action'?: never;
888
+ 'data-item-id'?: never;
889
+ 'data-interactive'?: never;
890
+ 'data-selected'?: never;
891
+ 'data-disabled'?: never;
892
+ 'data-selection-mode'?: never;
893
+ 'data-kui-pressed'?: never;
894
+ }>;
895
+ interface ContentItemBaseProps {
877
896
  /** Item content; a plain string is allowed for bare copy. */
878
897
  children?: KerfUiContent | string;
879
898
  /**
@@ -896,19 +915,38 @@ interface ContentItemProps {
896
915
  */
897
916
  focusTarget?: boolean;
898
917
  className?: string;
899
- /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
900
- rootAttributes?: ContentItemRootAttributes;
901
918
  /** Native named-slot assignment when composed inside a web component. */
902
919
  slot?: string;
903
920
  }
921
+ type ContentItemProps = ContentItemBaseProps & ({
922
+ interactive?: false;
923
+ action?: never;
924
+ itemId?: never;
925
+ selectionMode?: never;
926
+ selected?: never;
927
+ disabled?: never;
928
+ /** Existing static `data-*` metadata remains available. */
929
+ rootAttributes?: ContentItemRootAttributes;
930
+ } | {
931
+ /** Enable a keyboard reachable card; wire `wireContentItems` once on its containing root. */
932
+ interactive: true;
933
+ /** Delegated action dispatched by pointer, Enter, or Space. */
934
+ action: string;
935
+ itemId?: string;
936
+ selectionMode?: ContentItemSelectionMode;
937
+ selected?: boolean;
938
+ disabled?: boolean;
939
+ /** Safe app metadata; interaction attributes are component-owned. */
940
+ rootAttributes?: ContentItemInteractiveRootAttributes;
941
+ });
904
942
  /**
905
943
  * One self-contained `.kui-content` child: an 8px inline margin, a real 1px
906
944
  * border (transparent unless `framed`), 8px padding, and a rounded or pill
907
945
  * radius. It owns that whole geometry, so wrappers must not add more.
908
946
  */
909
- declare function ContentItem({ children, frame, shape, ariaLabel, focusTarget, className, rootAttributes, slot, }: ContentItemProps): kerfjs.SafeHtml;
947
+ declare function ContentItem({ children, frame, shape, ariaLabel, focusTarget, interactive, action, itemId, selectionMode, selected, disabled, className, rootAttributes, slot, }: ContentItemProps): kerfjs.SafeHtml;
910
948
 
911
- export { ContentItem, type ContentItemFrame, type ContentItemProps, type ContentItemShape };
949
+ export { ContentItem, type ContentItemFrame, type ContentItemProps, type ContentItemSelectionMode, type ContentItemShape };
912
950
  ```
913
951
 
914
952
  ## `@kerfjs/ui/value-table`
@@ -1024,6 +1062,8 @@ type TabActivation = 'automatic' | 'manual';
1024
1062
  type TabBarAllocation = 'intrinsic' | 'fill';
1025
1063
  type TabBarPresentation = 'rail' | 'segmented' | 'inspector';
1026
1064
  type TabBarTrailingPlacement = 'separate' | 'adjacent';
1065
+ /** Tablist width where segmented AppTabs switch to icon-only. */
1066
+ type TabBarIconOnlyAt = 'wide' | 'narrow' | 'compact';
1027
1067
  interface TabBarProps {
1028
1068
  id: string;
1029
1069
  label: string;
@@ -1047,15 +1087,17 @@ interface TabBarProps {
1047
1087
  allocation?: TabBarAllocation;
1048
1088
  /** Named strip chrome for application rails, segmented tabs, or inspectors. */
1049
1089
  presentation?: TabBarPresentation;
1090
+ /** Switch segmented AppTabs to icon-only at tablist widths of 832, 704, or 448px. Each tab needs a leading icon. */
1091
+ iconOnlyAt?: TabBarIconOnlyAt;
1050
1092
  /** Keep a trailing action beside the final tab or at the far edge of the bar. */
1051
1093
  trailingPlacement?: TabBarTrailingPlacement;
1052
1094
  /** Native named-slot assignment when composed inside a web component. */
1053
1095
  slot?: string;
1054
1096
  }
1055
1097
  /** Render a controlled tab strip. The application owns selection, order, and persistence. */
1056
- declare function TabBar({ id, label, children, leading, trailing, end, className, activation, allocation, presentation, trailingPlacement, slot, }: TabBarProps): kerfjs.SafeHtml;
1098
+ declare function TabBar({ id, label, children, leading, trailing, end, className, activation, allocation, presentation, iconOnlyAt, trailingPlacement, slot, }: TabBarProps): kerfjs.SafeHtml;
1057
1099
 
1058
- export { type TabActivation, TabBar, type TabBarAllocation, type TabBarPresentation, type TabBarProps, type TabBarTrailingPlacement };
1100
+ export { type TabActivation, TabBar, type TabBarAllocation, type TabBarIconOnlyAt, type TabBarPresentation, type TabBarProps, type TabBarTrailingPlacement };
1059
1101
  ```
1060
1102
 
1061
1103
  ## `@kerfjs/ui/wire-tab-bars`
@@ -1175,10 +1217,10 @@ export { type ScrollDividerTarget, type WireScrollDividersOptions, wireScrollDiv
1175
1217
 
1176
1218
  ```ts
1177
1219
  import * as kerfjs from 'kerfjs';
1220
+ import { PaneAppearance } from './pane.js';
1178
1221
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1179
1222
  import { ToolbarConfig } from './toolbar.js';
1180
1223
  import { ToolbarTextSize, HeadingLevel } from './toolbar-text.js';
1181
- import './pane.js';
1182
1224
  import './sides-BPSWde0A.js';
1183
1225
 
1184
1226
  /**
@@ -1189,6 +1231,8 @@ interface NavStackView {
1189
1231
  /** Stable identity for keyed reconcile and transition direction. */
1190
1232
  key: string;
1191
1233
  content: KerfUiContent;
1234
+ /** Background of this view's scrolling work surface. */
1235
+ appearance?: PaneAppearance;
1192
1236
  /** Title shown in the top toolbar for this view. */
1193
1237
  title?: string;
1194
1238
  /** Leading groups for this view's top toolbar, after the back control and before the title. */
@@ -1294,8 +1338,8 @@ import * as kerfjs from 'kerfjs';
1294
1338
  import { NavStackProps, NavStackView } from './nav-stack.js';
1295
1339
  import { ResizableRegionProps } from './resizable-region.js';
1296
1340
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1297
- import './toolbar.js';
1298
1341
  import './pane.js';
1342
+ import './toolbar.js';
1299
1343
  import './sides-BPSWde0A.js';
1300
1344
  import './toolbar-text.js';
1301
1345
  import './css-values.js';
@@ -1393,6 +1437,7 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
1393
1437
  'data-safe-area-inline-end'?: never;
1394
1438
  'data-chrome-placement'?: never;
1395
1439
  'data-chrome-dividers'?: never;
1440
+ 'data-appearance'?: never;
1396
1441
  }>;
1397
1442
  /** How a Pane's header and footer relate to its scrolling content. */
1398
1443
  type PaneChromePlacement = 'fixed' | 'auto';
@@ -1402,6 +1447,8 @@ type PaneChromePlacement = 'fixed' | 'auto';
1402
1447
  * chrome, as `wireScrollDividers` reports; `always`; or `none`.
1403
1448
  */
1404
1449
  type PaneChromeDividers = 'scroll' | 'always' | 'none';
1450
+ /** Background treatment of the Pane's scrolling work surface. */
1451
+ type PaneAppearance = 'default' | 'sunken';
1405
1452
  interface PaneProps {
1406
1453
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
1407
1454
  header?: KerfUiContent;
@@ -1419,7 +1466,8 @@ interface PaneProps {
1419
1466
  chromePlacement?: PaneChromePlacement;
1420
1467
  /**
1421
1468
  * The divider under the header and over the footer, where they meet the
1422
- * scrolling content. `scroll` (default) shows the header's divider only
1469
+ * scrolling content. Omitted defaults to `scroll` for a plain pane and
1470
+ * `always` for `appearance="sunken"`. `scroll` shows the header's divider only
1423
1471
  * while the content is scrolled down, and the footer's only while more
1424
1472
  * content lies below — never when the content fits — once
1425
1473
  * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above
@@ -1427,6 +1475,8 @@ interface PaneProps {
1427
1475
  * The line is drawn inside the chrome, so no state moves the content.
1428
1476
  */
1429
1477
  chromeDividers?: PaneChromeDividers;
1478
+ /** Paint the scrolling work surface with the shared lowered-surface color. */
1479
+ appearance?: PaneAppearance;
1430
1480
  /** Root semantics. Defaults to `div`. */
1431
1481
  element?: PaneElement;
1432
1482
  /** Scrolling content semantics. Defaults to `div`. */
@@ -1461,16 +1511,16 @@ interface PaneProps {
1461
1511
  * or a CollapsiblePanel) forwards, so the app configures that pane instead of
1462
1512
  * styling it. An omitted or `undefined` field keeps the composite's default.
1463
1513
  */
1464
- type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers'>;
1514
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers' | 'appearance'>;
1465
1515
  /**
1466
1516
  * An unpadded application column with optional fixed header/footer slots and one
1467
1517
  * scrolling vertical content owner. Separator lines are independently opt-in on
1468
1518
  * each logical edge, so the same component works as a sidebar, main area,
1469
1519
  * inspector, or dialog column.
1470
1520
  */
1471
- declare function Pane({ header, children, footer, chromePlacement, chromeDividers, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1521
+ declare function Pane({ header, children, footer, chromePlacement, chromeDividers, appearance, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1472
1522
 
1473
- export { Pane, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1523
+ export { Pane, type PaneAppearance, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1474
1524
  ```
1475
1525
 
1476
1526
  ## `@kerfjs/ui/workbench`
@@ -1481,7 +1531,7 @@ import { ListConfig } from './list.js';
1481
1531
  import { PaneConfig } from './pane.js';
1482
1532
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1483
1533
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1484
- import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-DqwtBxQL.js';
1534
+ import { a as PanelToolbar, b as PanelChromePlacement, c as PanelBottomToolbar, d as PanelToggle } from './panel-toolbar-DDKh4uKd.js';
1485
1535
  import { ToolbarConfig } from './toolbar.js';
1486
1536
  import './css-values.js';
1487
1537
  import './flex-alignment-4ms8ZbV8.js';
@@ -1500,6 +1550,7 @@ type WorkbenchPanelToggle = PanelToggle;
1500
1550
  * `FloatingToolbar` in the work area's bottom-end corner.
1501
1551
  */
1502
1552
  type WorkbenchPanelToolbar = PanelToolbar;
1553
+ type WorkbenchPanelBottomToolbar = PanelBottomToolbar;
1503
1554
  /**
1504
1555
  * The work area's top toolbar; collapsed rails add their groups to it. Its
1505
1556
  * configuration forwards to its `Toolbar`. It draws no divider of its own by
@@ -1535,7 +1586,7 @@ interface WorkbenchMainBottomToolbar extends ToolbarConfig {
1535
1586
  * the Pane's `chromePlacement="auto"`; it applies to the pinned header and
1536
1587
  * footer together).
1537
1588
  */
1538
- type WorkbenchChromePlacement = 'fixed' | 'scroll' | 'auto';
1589
+ type WorkbenchChromePlacement = PanelChromePlacement;
1539
1590
 
1540
1591
  /**
1541
1592
  * The Workbench container breakpoint below which a panel presents as an
@@ -1543,7 +1594,7 @@ type WorkbenchChromePlacement = 'fixed' | 'scroll' | 'auto';
1543
1594
  * breakpoints as `ResizableRegion`'s `responsiveFillAt` — or `never` to keep
1544
1595
  * it inline at every width.
1545
1596
  */
1546
- type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow' | 'never';
1597
+ type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow' | 'never' | number;
1547
1598
  /**
1548
1599
  * How wide a rail's overlay is in a compact (448px or less) Workbench: `inset`
1549
1600
  * fills the Workbench less a dismiss margin on the side away from the rail's
@@ -1566,8 +1617,20 @@ interface WorkbenchPanel {
1566
1617
  * collapsed. With it, `content` renders in a `Pane` below the toolbar.
1567
1618
  */
1568
1619
  toolbar?: WorkbenchPanelToolbar;
1569
- /** Optional bottom toolbar under a `toolbar` panel's content. */
1620
+ /** Fixed content below a toolbar panel's top toolbar, above its scroll region. */
1621
+ header?: KerfUiContent;
1622
+ /** List layout for `header`; omitted fields keep List defaults. */
1623
+ headerList?: ListConfig;
1624
+ /** Placement of the top toolbar and header together; default `fixed`. */
1625
+ headerPlacement?: WorkbenchChromePlacement;
1626
+ /** Fixed content above a toolbar panel's bottom toolbar. */
1570
1627
  footer?: KerfUiContent;
1628
+ /** List layout for `footer`; omitted fields keep List defaults. */
1629
+ footerList?: ListConfig;
1630
+ /** Fixed toolbar below `footer`, using footer semantics. */
1631
+ bottomToolbar?: WorkbenchPanelBottomToolbar;
1632
+ /** Placement of the footer and bottom toolbar together; default `fixed`. */
1633
+ footerPlacement?: WorkbenchChromePlacement;
1571
1634
  /**
1572
1635
  * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1573
1636
  * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
@@ -1599,8 +1662,9 @@ interface WorkbenchPanel {
1599
1662
  presentation?: ResizableRegionPresentation;
1600
1663
  /**
1601
1664
  * Present the panel as an overlay, without a separator, below a Workbench
1602
- * container breakpoint, and inline above it — the CSS decides, so the app
1603
- * needs no device-class check. A rail overlays from its side at full
1665
+ * container breakpoint, and inline above it. `compact` and `narrow` use
1666
+ * CSS container queries; a positive number is a pixel threshold measured
1667
+ * by `wireWorkbench` and requires a `collapsed` signal. A rail overlays from its side at full
1604
1668
  * height, over the work area and an open drawer; the bottom drawer
1605
1669
  * overlays the bottom of the work-area column. Rails default to `narrow`
1606
1670
  * (pass `never` to keep one inline); the drawer defaults to inline.
@@ -1700,6 +1764,8 @@ interface WorkbenchProps {
1700
1764
  * shorter. Workbenches without a drawer ignore it.
1701
1765
  */
1702
1766
  mainMinHeight?: number;
1767
+ /** Dim the work area below any open overlay and absorb outside presses; off by default. */
1768
+ overlayBackdrop?: boolean;
1703
1769
  className?: string;
1704
1770
  /** Native named-slot assignment when composed inside a web component. */
1705
1771
  slot?: string;
@@ -1717,9 +1783,9 @@ interface WorkbenchProps {
1717
1783
  * lives outside it and stays reachable). A panel may opt in to drag and keyboard resizing with
1718
1784
  * `resizable`, which `wireWorkbench` drives. See `docs/23-app-layouts.md` §3.3.
1719
1785
  */
1720
- declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1786
+ declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, overlayBackdrop, className, slot, }: WorkbenchProps): SafeHtml;
1721
1787
 
1722
- export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
1788
+ export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelBottomToolbar, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
1723
1789
  ```
1724
1790
 
1725
1791
  ## `@kerfjs/ui/wire-workbench`
@@ -1759,6 +1825,13 @@ interface WireWorkbenchPanel {
1759
1825
  * keeps Tab inside it, and it closes on Escape or a press outside it.
1760
1826
  */
1761
1827
  collapsed?: Signal<boolean>;
1828
+ /**
1829
+ * Treat presses in a portal surface launched by this panel (for example a
1830
+ * body-level menu or dialog) as inside it. The predicate receives each Node
1831
+ * in the press's composed path; return true for the portal root. Ordinary
1832
+ * presses outside the panel and its allowed surfaces still dismiss it.
1833
+ */
1834
+ keepOpenOn?: (target: Node) => boolean;
1762
1835
  }
1763
1836
  /** A resize the user made, after `wireWorkbench` wrote it to the size signal. */
1764
1837
  interface WorkbenchResize {
@@ -1840,16 +1913,18 @@ export { type WireWorkbenchOptions, type WireWorkbenchPanel, type WorkbenchPanel
1840
1913
 
1841
1914
  ```ts
1842
1915
  import { SafeHtml } from 'kerfjs';
1916
+ import { ListConfig } from './list.js';
1843
1917
  import { PaneConfig } from './pane.js';
1844
- import { P as PanelSide, a as PanelToolbar, b as PanelToggle } from './panel-toolbar-DqwtBxQL.js';
1845
- export { c as collapsiblePanelToggleIcon } from './panel-toolbar-DqwtBxQL.js';
1918
+ import { P as PanelSide, a as PanelToolbar, b as PanelChromePlacement, c as PanelBottomToolbar, d as PanelToggle } from './panel-toolbar-DDKh4uKd.js';
1919
+ export { e as collapsiblePanelToggleIcon } from './panel-toolbar-DDKh4uKd.js';
1846
1920
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1847
1921
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1922
+ import './css-values.js';
1923
+ import './flex-alignment-4ms8ZbV8.js';
1924
+ import './sides-BPSWde0A.js';
1848
1925
  import './lucide-icon.js';
1849
1926
  import 'lucide';
1850
1927
  import './toolbar.js';
1851
- import './sides-BPSWde0A.js';
1852
- import './css-values.js';
1853
1928
 
1854
1929
  /** Which edge a {@link CollapsiblePanel} docks to. */
1855
1930
  type CollapsiblePanelSide = PanelSide;
@@ -1862,6 +1937,8 @@ type CollapsiblePanelToolbarToggle = PanelToggle;
1862
1937
  * {@link CollapsiblePanelRelocated} while it is collapsed.
1863
1938
  */
1864
1939
  type CollapsiblePanelToolbar = PanelToolbar;
1940
+ type CollapsiblePanelBottomToolbar = PanelBottomToolbar;
1941
+ type CollapsiblePanelChromePlacement = PanelChromePlacement;
1865
1942
  interface CollapsiblePanelToggleProps {
1866
1943
  /** The panel this toggle controls. */
1867
1944
  side: CollapsiblePanelSide;
@@ -1905,8 +1982,15 @@ interface CollapsiblePanelProps {
1905
1982
  * marked groups and toggle stay reachable while the panel is collapsed.
1906
1983
  */
1907
1984
  toolbar?: CollapsiblePanelToolbar;
1908
- /** Optional bottom toolbar under a `toolbar` panel's content. */
1985
+ /** Fixed content below a toolbar panel's top toolbar. */
1986
+ header?: KerfUiContent;
1987
+ headerList?: ListConfig;
1988
+ headerPlacement?: CollapsiblePanelChromePlacement;
1989
+ /** Fixed content above a toolbar panel's bottom toolbar. */
1909
1990
  footer?: KerfUiContent;
1991
+ footerList?: ListConfig;
1992
+ bottomToolbar?: CollapsiblePanelBottomToolbar;
1993
+ footerPlacement?: CollapsiblePanelChromePlacement;
1910
1994
  /**
1911
1995
  * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1912
1996
  * `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
@@ -1940,7 +2024,7 @@ interface CollapsiblePanelProps {
1940
2024
  * and persistence semantics, and with `CollapsiblePanelToggle` for the standard
1941
2025
  * affordance. See `ui/docs/collapsible-panel.md` and `docs/23-app-layouts.md`.
1942
2026
  */
1943
- declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, footer, pane, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
2027
+ declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, header, headerList, headerPlacement, footer, footerList, bottomToolbar, footerPlacement, pane, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1944
2028
  interface CollapsiblePanelRelocatedProps {
1945
2029
  /** The panel's `id`. */
1946
2030
  panelId: string;
@@ -1960,7 +2044,7 @@ interface CollapsiblePanelRelocatedProps {
1960
2044
  */
1961
2045
  declare function CollapsiblePanelRelocated({ panelId, side, collapsed, toolbar, }: CollapsiblePanelRelocatedProps): SafeHtml;
1962
2046
 
1963
- export { CollapsiblePanel, type CollapsiblePanelProps, CollapsiblePanelRelocated, type CollapsiblePanelRelocatedProps, type CollapsiblePanelSide, CollapsiblePanelToggle, type CollapsiblePanelToggleProps, type CollapsiblePanelToolbar, type CollapsiblePanelToolbarToggle };
2047
+ export { CollapsiblePanel, type CollapsiblePanelBottomToolbar, type CollapsiblePanelChromePlacement, type CollapsiblePanelProps, CollapsiblePanelRelocated, type CollapsiblePanelRelocatedProps, type CollapsiblePanelSide, CollapsiblePanelToggle, type CollapsiblePanelToggleProps, type CollapsiblePanelToolbar, type CollapsiblePanelToolbarToggle };
1964
2048
  ```
1965
2049
 
1966
2050
  ## `@kerfjs/ui/wire-sidebar`
@@ -2035,6 +2119,7 @@ export { type SidebarStorage, type WireSidebarOptions, type WireSidebarPanel, wi
2035
2119
 
2036
2120
  ```ts
2037
2121
  import { SafeHtml } from 'kerfjs';
2122
+ import { PaneAppearance } from './pane.js';
2038
2123
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2039
2124
 
2040
2125
  interface TabScaffoldTabBase<Id extends string> {
@@ -2044,6 +2129,8 @@ interface TabScaffoldTabBase<Id extends string> {
2044
2129
  icon?: SafeHtml;
2045
2130
  /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
2046
2131
  content: KerfUiContent;
2132
+ /** Background of this scene's scrolling work surface. */
2133
+ appearance?: PaneAppearance;
2047
2134
  }
2048
2135
  /** A tab with an optional count or short-status badge. */
2049
2136
  interface TabScaffoldTabCountBadge {
@@ -2290,7 +2377,7 @@ import './list.js';
2290
2377
  import './css-values.js';
2291
2378
  import './flex-alignment-4ms8ZbV8.js';
2292
2379
  import './resizable-region.js';
2293
- import './panel-toolbar-DqwtBxQL.js';
2380
+ import './panel-toolbar-DDKh4uKd.js';
2294
2381
  import './lucide-icon.js';
2295
2382
  import 'lucide';
2296
2383
 
@@ -2383,7 +2470,7 @@ import './list.js';
2383
2470
  import './css-values.js';
2384
2471
  import './flex-alignment-4ms8ZbV8.js';
2385
2472
  import './resizable-region.js';
2386
- import './panel-toolbar-DqwtBxQL.js';
2473
+ import './panel-toolbar-DDKh4uKd.js';
2387
2474
  import './lucide-icon.js';
2388
2475
  import 'lucide';
2389
2476
 
@@ -2608,6 +2695,8 @@ interface SelectBaseProps<Value extends string = string> {
2608
2695
  size?: SelectSize;
2609
2696
  /** Closed trigger width; omit to keep the presentation's default. */
2610
2697
  triggerWidth?: SelectTriggerWidth;
2698
+ /** Show the disclosure caret (default); omit it for a compact icon-only trigger. */
2699
+ caret?: boolean;
2611
2700
  /** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
2612
2701
  focusRingOwner?: SelectFocusRingOwner;
2613
2702
  /** Maximum closed-control label width in CSS pixels before ellipsis. */
@@ -2783,6 +2872,7 @@ export { Skeleton, type SkeletonProps };
2783
2872
 
2784
2873
  ```ts
2785
2874
  import * as kerfjs from 'kerfjs';
2875
+ import { CssFlexKeyword, CssFlex } from './css-values.js';
2786
2876
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2787
2877
 
2788
2878
  type SunkenPanelShape = 'rounded' | 'square';
@@ -2792,6 +2882,10 @@ interface SunkenPanelProps {
2792
2882
  ariaLabel?: string;
2793
2883
  /** Corner shape: a rounded rectangle (default) or square corners. */
2794
2884
  shape?: SunkenPanelShape;
2885
+ /** Grow or shrink within a flex parent, using Grid's typed flex contract. */
2886
+ flex?: boolean | CssFlexKeyword | CssFlex;
2887
+ /** Fill a parent with a definite height; use flex inside a flex layout. */
2888
+ fill?: boolean;
2795
2889
  className?: string;
2796
2890
  /** Native named-slot assignment when composed inside a web component. */
2797
2891
  slot?: string;
@@ -2801,7 +2895,7 @@ interface SunkenPanelProps {
2801
2895
  * stack. The panel owns its background and padding; children own their own
2802
2896
  * borders and internal geometry.
2803
2897
  */
2804
- declare function SunkenPanel({ children, ariaLabel, shape, className, slot, }: SunkenPanelProps): kerfjs.SafeHtml;
2898
+ declare function SunkenPanel({ children, ariaLabel, shape, flex, fill, className, slot, }: SunkenPanelProps): kerfjs.SafeHtml;
2805
2899
 
2806
2900
  export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
2807
2901
  ```
@@ -3075,8 +3169,8 @@ import { SafeHtml } from 'kerfjs';
3075
3169
  import { BadgeTone, BadgeAppearance, BadgeShape, BadgeSize } from './badge.js';
3076
3170
 
3077
3171
  interface ChipCommonProps {
3078
- /** Visible, non-interactive chip content. */
3079
- children: SafeHtml | string | number;
3172
+ /** Decorative leading icon, normally an unsized LucideIcon. */
3173
+ icon?: SafeHtml;
3080
3174
  tone?: BadgeTone;
3081
3175
  appearance?: BadgeAppearance;
3082
3176
  shape?: BadgeShape;
@@ -3090,6 +3184,12 @@ interface ChipCommonProps {
3090
3184
  }
3091
3185
  /** A removable chip needs both a delegated action and a specific accessible name. */
3092
3186
  type ChipProps = ChipCommonProps & ({
3187
+ children: SafeHtml | string | number;
3188
+ truncate?: false;
3189
+ } | {
3190
+ children: string;
3191
+ truncate: true;
3192
+ }) & ({
3093
3193
  removeAction: string;
3094
3194
  removeLabel: string;
3095
3195
  } | {
@@ -3097,7 +3197,7 @@ type ChipProps = ChipCommonProps & ({
3097
3197
  removeLabel?: never;
3098
3198
  });
3099
3199
  /** A short label with an optional native remove button. The application owns removal. */
3100
- declare function Chip({ children, tone, appearance, shape, size, disabled, itemId, className, slot, ...remove }: ChipProps): SafeHtml;
3200
+ declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, ...remove }: ChipProps): SafeHtml;
3101
3201
 
3102
3202
  export { Chip, type ChipProps };
3103
3203
  ```
@@ -3109,18 +3209,21 @@ import * as kerfjs from 'kerfjs';
3109
3209
  import { IconNode } from 'lucide';
3110
3210
 
3111
3211
  type LucideNode = IconNode;
3212
+ type LucideIconSize = 'xs' | 's' | 'm' | 'l' | 'xl' | number;
3112
3213
  interface LucideIconProps {
3113
3214
  icon: LucideNode;
3114
3215
  name: string;
3115
3216
  className?: string;
3116
3217
  label?: string;
3218
+ /** Named icon scale or positive pixel size, converted to rem. Omit for 1em. */
3219
+ size?: LucideIconSize;
3117
3220
  /** Native named-slot assignment when composed inside a web component. */
3118
3221
  slot?: string;
3119
3222
  }
3120
3223
  /** Render a Lucide-compatible icon node without copying icon SVG strings. */
3121
- declare function LucideIcon({ icon, name, className, label, slot, }: LucideIconProps): kerfjs.SafeHtml;
3224
+ declare function LucideIcon({ icon, name, className, label, size, slot, }: LucideIconProps): kerfjs.SafeHtml;
3122
3225
 
3123
- export { LucideIcon, type LucideIconProps, type LucideNode };
3226
+ export { LucideIcon, type LucideIconProps, type LucideIconSize, type LucideNode };
3124
3227
  ```
3125
3228
 
3126
3229
  ## `@kerfjs/ui/surface-scaffold`
@@ -3171,8 +3274,9 @@ type TextSize = 'compact' | 'default' | 'large' | 'xlarge';
3171
3274
  type TextFont = 'default' | 'monospace';
3172
3275
  type TextBorder = 'transparent' | 'none';
3173
3276
  type TextLineHeight = 'default' | 'tight';
3277
+ type TextWrap = 'normal' | 'anywhere' | 'nowrap' | 'truncate';
3174
3278
  type TextContent = KerfUiContent | string | number | readonly TextContent[];
3175
- type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
3279
+ type TextCommonProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
3176
3280
  /** Native heading, paragraph, or inline span element to render. Defaults to `p`. */
3177
3281
  variant?: TextVariant;
3178
3282
  /** Semantic foreground treatment. Defaults to the inherited foreground. */
@@ -3191,14 +3295,24 @@ type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
3191
3295
  class?: string;
3192
3296
  className?: string;
3193
3297
  };
3298
+ type TextProps = TextCommonProps & ({
3299
+ /** Wrap normally or break long unbroken strings. Defaults to normal. */
3300
+ wrap?: 'normal' | 'anywhere';
3301
+ /** Cap wrapped text to this positive number of lines. */
3302
+ maxLines?: number;
3303
+ } | {
3304
+ /** Keep one line, with or without an ellipsis. */
3305
+ wrap: 'nowrap' | 'truncate';
3306
+ maxLines?: never;
3307
+ });
3194
3308
  /**
3195
3309
  * Semantic heading, paragraph, or inline text. Block variants use the standard
3196
3310
  * content-item padding; `span` adds no box geometry.
3197
3311
  * All ordinary native heading/paragraph attributes pass through to the element.
3198
3312
  */
3199
- declare function Text({ variant: Variant, tone, size, font, border, flush, lineHeight, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
3313
+ declare function Text({ variant: Variant, tone, size, font, border, flush, lineHeight, wrap, maxLines, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
3200
3314
 
3201
- export { Text, type TextBorder, type TextContent, type TextFont, type TextLineHeight, type TextProps, type TextSize, type TextTone, type TextVariant };
3315
+ export { Text, type TextBorder, type TextContent, type TextFont, type TextLineHeight, type TextProps, type TextSize, type TextTone, type TextVariant, type TextWrap };
3202
3316
  ```
3203
3317
 
3204
3318
  ## `@kerfjs/ui/row`