@kerfjs/ui 5.0.0-beta.106 → 5.0.0-beta.108

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 (283) hide show
  1. package/README.md +2 -1
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/application-ui-profile.defaults.json +6 -1
  4. package/ai/component-catalog.json +184 -39
  5. package/ai/component-composition-rules.json +20 -2
  6. package/ai/component-composition.d.ts +11 -0
  7. package/ai/component-composition.json +126 -21
  8. package/ai/component-composition.schema.json +32 -0
  9. package/ai/components/README.md +3 -2
  10. package/ai/components/button.md +9 -6
  11. package/ai/components/checkbox-group.md +89 -0
  12. package/ai/components/checkbox.md +3 -2
  13. package/ai/components/chip.md +1 -0
  14. package/ai/components/color-picker.md +10 -7
  15. package/ai/components/disclosure.md +6 -1
  16. package/ai/components/foundation.md +1 -1
  17. package/ai/components/list-detail-dialog.md +1 -1
  18. package/ai/components/list.md +1 -1
  19. package/ai/components/message-composer.md +2 -1
  20. package/ai/components/radio-group.md +4 -3
  21. package/ai/components/segmented-control.md +1 -0
  22. package/ai/components/split-button.md +5 -2
  23. package/ai/components/surface-scaffold.md +3 -1
  24. package/ai/components/switch.md +1 -1
  25. package/ai/components/text-field.md +3 -1
  26. package/ai/components/text.md +2 -0
  27. package/ai/components/toolbar-control-group.md +1 -0
  28. package/ai/components/toolbar.md +1 -1
  29. package/ai/components/wa-checkbox-group.md +5 -5
  30. package/ai/components/workbench-dialog.md +1 -1
  31. package/ai/public-api-signatures-v1.md +258 -35
  32. package/ai/skill.md +82 -65
  33. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  34. package/dist/browser/checkbox-group.js +5 -0
  35. package/dist/button.d.ts +18 -5
  36. package/dist/button.js +1 -1
  37. package/dist/catalog.js +11 -10
  38. package/dist/catalog.js.map +1 -1
  39. package/dist/checkbox-group.d.ts +70 -0
  40. package/dist/checkbox-group.js +7 -0
  41. package/dist/checkbox-group.js.map +1 -0
  42. package/dist/chip.d.ts +20 -2
  43. package/dist/chip.js +2 -1
  44. package/dist/{chunk-SQ2Q3OQI.js → chunk-2LM3PYHA.js} +2 -2
  45. package/dist/{chunk-SQ2Q3OQI.js.map → chunk-2LM3PYHA.js.map} +1 -1
  46. package/dist/{chunk-HYORKKYP.js → chunk-3VZ6SFD4.js} +1 -1
  47. package/dist/chunk-3VZ6SFD4.js.map +1 -0
  48. package/dist/{chunk-EKBMUXFV.js → chunk-3Z7N2NAZ.js} +141 -54
  49. package/dist/chunk-3Z7N2NAZ.js.map +1 -0
  50. package/dist/{chunk-23PPPNH6.js → chunk-4OV272LF.js} +2 -2
  51. package/dist/{chunk-23PPPNH6.js.map → chunk-4OV272LF.js.map} +1 -1
  52. package/dist/{chunk-2PXZBFEC.js → chunk-5J6Z4BWY.js} +1 -1
  53. package/dist/{chunk-2PXZBFEC.js.map → chunk-5J6Z4BWY.js.map} +1 -1
  54. package/dist/{chunk-TAHR457X.js → chunk-6CDILXF4.js} +5 -1
  55. package/dist/chunk-6CDILXF4.js.map +1 -0
  56. package/dist/{chunk-DDSCVEO5.js → chunk-CPSGUGAY.js} +6 -6
  57. package/dist/{chunk-DDSCVEO5.js.map → chunk-CPSGUGAY.js.map} +1 -1
  58. package/dist/{chunk-C3RLKKFQ.js → chunk-EYDXFOSH.js} +13 -8
  59. package/dist/chunk-EYDXFOSH.js.map +1 -0
  60. package/dist/{chunk-PE2KPZDW.js → chunk-HDXUHLTQ.js} +7 -2
  61. package/dist/chunk-HDXUHLTQ.js.map +1 -0
  62. package/dist/chunk-HU5IHXCI.js +73 -0
  63. package/dist/chunk-HU5IHXCI.js.map +1 -0
  64. package/dist/{chunk-DF2YKGIX.js → chunk-JCCN3U6X.js} +2 -2
  65. package/dist/{chunk-DF2YKGIX.js.map → chunk-JCCN3U6X.js.map} +1 -1
  66. package/dist/{chunk-UTCAOOXU.js → chunk-KPINJHIC.js} +8 -2
  67. package/dist/chunk-KPINJHIC.js.map +1 -0
  68. package/dist/{chunk-N7MBGONH.js → chunk-LMHN2TJL.js} +22 -2
  69. package/dist/chunk-LMHN2TJL.js.map +1 -0
  70. package/dist/{chunk-NS2TBYM4.js → chunk-LZUUUHNH.js} +7 -3
  71. package/dist/chunk-LZUUUHNH.js.map +1 -0
  72. package/dist/{chunk-GCAK23PU.js → chunk-MVKHSAKE.js} +2 -2
  73. package/dist/{chunk-GCAK23PU.js.map → chunk-MVKHSAKE.js.map} +1 -1
  74. package/dist/{chunk-OY2MXIBB.js → chunk-NB6POCFH.js} +3 -1
  75. package/dist/chunk-NB6POCFH.js.map +1 -0
  76. package/dist/{chunk-ECFCAKWE.js → chunk-NR6O74ST.js} +5 -1
  77. package/dist/chunk-NR6O74ST.js.map +1 -0
  78. package/dist/{chunk-7W3GKMN4.js → chunk-OQP3PFKQ.js} +7 -4
  79. package/dist/chunk-OQP3PFKQ.js.map +1 -0
  80. package/dist/{chunk-FKKJHGN5.js → chunk-P7EJ4CAD.js} +2 -2
  81. package/dist/{chunk-FKKJHGN5.js.map → chunk-P7EJ4CAD.js.map} +1 -1
  82. package/dist/{chunk-ZXZAECHZ.js → chunk-SOFPUW3O.js} +4 -4
  83. package/dist/{chunk-ZXZAECHZ.js.map → chunk-SOFPUW3O.js.map} +1 -1
  84. package/dist/{chunk-WJKHLOP5.js → chunk-TI2GV36S.js} +8 -2
  85. package/dist/chunk-TI2GV36S.js.map +1 -0
  86. package/dist/{chunk-QLA25V2K.js → chunk-WPNIKZMJ.js} +15 -1
  87. package/dist/chunk-WPNIKZMJ.js.map +1 -0
  88. package/dist/{chunk-FG6U7KQQ.js → chunk-WSEJ2FDE.js} +4 -4
  89. package/dist/{chunk-FG6U7KQQ.js.map → chunk-WSEJ2FDE.js.map} +1 -1
  90. package/dist/{chunk-ACUKTVS3.js → chunk-XWNXGFX3.js} +52 -42
  91. package/dist/chunk-XWNXGFX3.js.map +1 -0
  92. package/dist/{chunk-WU57BYYM.js → chunk-YVZCKXR3.js} +8 -2
  93. package/dist/chunk-YVZCKXR3.js.map +1 -0
  94. package/dist/{chunk-CMLPFIC5.js → chunk-ZN7KUMPY.js} +3 -1
  95. package/dist/chunk-ZN7KUMPY.js.map +1 -0
  96. package/dist/collapsible-panel.js +2 -2
  97. package/dist/color-picker.d.ts +30 -5
  98. package/dist/color-picker.js +1 -1
  99. package/dist/disclosure.d.ts +13 -4
  100. package/dist/disclosure.js.map +1 -1
  101. package/dist/help-tags-register.js +1 -1
  102. package/dist/index.d.ts +2 -1
  103. package/dist/index.js +24 -23
  104. package/dist/list-action-row.js +1 -1
  105. package/dist/list-detail-dialog.d.ts +7 -1
  106. package/dist/list-detail-dialog.js +7 -5
  107. package/dist/list-detail-dialog.js.map +1 -1
  108. package/dist/list-header.d.ts +8 -1
  109. package/dist/list-header.js +1 -1
  110. package/dist/list.d.ts +7 -1
  111. package/dist/list.js +1 -1
  112. package/dist/message-composer.js +1 -1
  113. package/dist/nav-stack.js +1 -1
  114. package/dist/popup-menu-register.js +2 -2
  115. package/dist/popup-menu.d.ts +15 -5
  116. package/dist/popup-menu.js +1 -1
  117. package/dist/segmented-control.d.ts +3 -1
  118. package/dist/segmented-control.js +1 -1
  119. package/dist/select-register.js +3 -3
  120. package/dist/split-button.d.ts +14 -2
  121. package/dist/split-button.js +1 -1
  122. package/dist/split-view.js +1 -1
  123. package/dist/styles/anchored-surface.css +3 -0
  124. package/dist/styles/button.css +57 -2
  125. package/dist/styles/catalog/components/catalog-example.css +55 -18
  126. package/dist/styles/checkbox-group.css +63 -0
  127. package/dist/styles/checkbox.css +7 -6
  128. package/dist/styles/color-picker.css +69 -34
  129. package/dist/styles/components/actions/button/button.css +57 -2
  130. package/dist/styles/components/actions/split-button/split-button.css +51 -5
  131. package/dist/styles/components/actions/toolbar/toolbar.css +9 -0
  132. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +29 -1
  133. package/dist/styles/components/collections/framed-list/framed-list.css +6 -0
  134. package/dist/styles/components/collections/list/list.css +6 -0
  135. package/dist/styles/components/collections/list-header/list-header.css +7 -0
  136. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +3 -0
  137. package/dist/styles/components/forms/checkbox/checkbox.css +7 -6
  138. package/dist/styles/components/forms/checkbox-group/checkbox-group.css +63 -0
  139. package/dist/styles/components/forms/color-picker/color-picker.css +69 -34
  140. package/dist/styles/components/forms/radio-group/radio-group.css +7 -5
  141. package/dist/styles/components/forms/select/select.css +6 -2
  142. package/dist/styles/components/forms/switch/switch.css +3 -3
  143. package/dist/styles/components/layout/pane/pane.css +24 -0
  144. package/dist/styles/components/layout/workbench/workbench.css +4 -0
  145. package/dist/styles/components/navigation/nav-stack/nav-stack.css +77 -1
  146. package/dist/styles/components/navigation/tab-bar/tab-bar.css +6 -0
  147. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +17 -0
  148. package/dist/styles/components/surfaces/content-item/content-item.css +30 -0
  149. package/dist/styles/components/surfaces/disclosure/disclosure.css +38 -0
  150. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +3 -0
  151. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +8 -0
  152. package/dist/styles/components/typography/text/text.css +10 -0
  153. package/dist/styles/content-item.css +30 -0
  154. package/dist/styles/disclosure.css +38 -0
  155. package/dist/styles/foundation.css +78 -13
  156. package/dist/styles/framed-list.css +6 -0
  157. package/dist/styles/list-header.css +7 -0
  158. package/dist/styles/list.css +6 -0
  159. package/dist/styles/nav-stack.css +77 -1
  160. package/dist/styles/pane.css +24 -0
  161. package/dist/styles/radio-group.css +7 -5
  162. package/dist/styles/select.css +6 -2
  163. package/dist/styles/split-button.css +51 -5
  164. package/dist/styles/styles.css +1 -0
  165. package/dist/styles/sunken-panel.css +3 -0
  166. package/dist/styles/surface-scaffold.css +8 -0
  167. package/dist/styles/switch.css +3 -3
  168. package/dist/styles/tab-bar.css +6 -0
  169. package/dist/styles/tab-navigator.css +17 -0
  170. package/dist/styles/text.css +10 -0
  171. package/dist/styles/toolbar-control-group.css +29 -1
  172. package/dist/styles/toolbar.css +9 -0
  173. package/dist/styles/webawesome.css +56 -12
  174. package/dist/styles/workbench.css +4 -0
  175. package/dist/surface-scaffold.d.ts +15 -1
  176. package/dist/surface-scaffold.js +1 -1
  177. package/dist/text-field.d.ts +7 -1
  178. package/dist/text-field.js +1 -1
  179. package/dist/toolbar-control-group.d.ts +8 -2
  180. package/dist/toolbar-control-group.js +1 -1
  181. package/dist/toolbar.d.ts +6 -1
  182. package/dist/toolbar.js +1 -1
  183. package/dist/wire-catalog.js +1 -1
  184. package/dist/wire-color-fields.js +2 -2
  185. package/dist/wire-color-pickers.d.ts +4 -3
  186. package/dist/wire-color-pickers.js +1 -1
  187. package/dist/wire-comboboxes.js +1 -1
  188. package/dist/wire-workbench.js +1 -1
  189. package/dist/workbench-dialog.d.ts +11 -2
  190. package/dist/workbench-dialog.js +6 -3
  191. package/dist/workbench-dialog.js.map +1 -1
  192. package/dist/workbench.js +1 -1
  193. package/docs/accessibility.md +58 -3
  194. package/docs/anchored-surface.md +6 -1
  195. package/docs/catalog.md +26 -1
  196. package/docs/color-picker.md +39 -8
  197. package/docs/component-contract.md +47 -3
  198. package/docs/component-selection.md +58 -21
  199. package/docs/design/templates/button/full-width-dark.svg +1 -0
  200. package/docs/design/templates/button/full-width.svg +1 -0
  201. package/docs/design/templates/button/tones-dark.svg +1 -1
  202. package/docs/design/templates/button/tones.svg +1 -1
  203. package/docs/design/templates/button-dark.svg +1 -1
  204. package/docs/design/templates/button.svg +1 -1
  205. package/docs/design/templates/checkbox/error-dark.svg +1 -1
  206. package/docs/design/templates/checkbox/error.svg +1 -1
  207. package/docs/design/templates/checkbox/states-dark.svg +1 -1
  208. package/docs/design/templates/checkbox/states.svg +1 -1
  209. package/docs/design/templates/checkbox-dark.svg +1 -1
  210. package/docs/design/templates/checkbox-group/horizontal-dark.svg +1 -0
  211. package/docs/design/templates/checkbox-group/horizontal.svg +1 -0
  212. package/docs/design/templates/checkbox-group/vertical-dark.svg +1 -0
  213. package/docs/design/templates/checkbox-group/vertical.svg +1 -0
  214. package/docs/design/templates/checkbox-group-dark.svg +1 -0
  215. package/docs/design/templates/checkbox-group.svg +1 -0
  216. package/docs/design/templates/checkbox.svg +1 -1
  217. package/docs/design/templates/color-picker/gray-dark.svg +1 -1
  218. package/docs/design/templates/color-picker/gray.svg +1 -1
  219. package/docs/design/templates/color-picker/hsb-dark.svg +1 -0
  220. package/docs/design/templates/color-picker/hsb.svg +1 -0
  221. package/docs/design/templates/color-picker/rgb-dark.svg +1 -1
  222. package/docs/design/templates/color-picker/rgb.svg +1 -1
  223. package/docs/design/templates/color-picker-dark.svg +1 -1
  224. package/docs/design/templates/color-picker.svg +1 -1
  225. package/docs/design/templates/disclosure/embedded-dark.svg +1 -0
  226. package/docs/design/templates/disclosure/embedded.svg +1 -0
  227. package/docs/design/templates/disclosure-dark.svg +1 -1
  228. package/docs/design/templates/disclosure.svg +1 -1
  229. package/docs/design/templates/radio-group/horizontal-dark.svg +1 -1
  230. package/docs/design/templates/radio-group/horizontal.svg +1 -1
  231. package/docs/design/templates/radio-group/vertical-dark.svg +1 -1
  232. package/docs/design/templates/radio-group/vertical.svg +1 -1
  233. package/docs/design/templates/radio-group-dark.svg +1 -1
  234. package/docs/design/templates/radio-group.svg +1 -1
  235. package/docs/design/templates/split-button/full-width-dark.svg +1 -0
  236. package/docs/design/templates/split-button/full-width.svg +1 -0
  237. package/docs/design/templates/split-button/pill-dark.svg +1 -0
  238. package/docs/design/templates/split-button/pill.svg +1 -0
  239. package/docs/design/templates/split-button/states-dark.svg +1 -0
  240. package/docs/design/templates/split-button/states.svg +1 -0
  241. package/docs/design/templates/split-button/tones-dark.svg +1 -0
  242. package/docs/design/templates/split-button/tones.svg +1 -0
  243. package/docs/design/templates/split-button-dark.svg +1 -0
  244. package/docs/design/templates/split-button.svg +1 -0
  245. package/docs/design/templates/switch/states-dark.svg +1 -1
  246. package/docs/design/templates/switch/states.svg +1 -1
  247. package/docs/design/templates/switch-dark.svg +1 -1
  248. package/docs/design/templates/switch.svg +1 -1
  249. package/docs/design/templates/text-field/number-dark.svg +1 -0
  250. package/docs/design/templates/text-field/number.svg +1 -0
  251. package/docs/design/templates/text-field-dark.svg +1 -1
  252. package/docs/design/templates/text-field.svg +1 -1
  253. package/docs/design/templates.md +10 -3
  254. package/docs/disclosure.md +34 -0
  255. package/docs/layout.md +16 -5
  256. package/docs/list-detail-dialog.md +4 -0
  257. package/docs/nav-stack.md +6 -2
  258. package/docs/surface-scaffold.md +6 -2
  259. package/docs/ui-doctor.md +16 -4
  260. package/docs/webawesome-migration.md +3 -1
  261. package/docs/webawesome-theme.md +56 -18
  262. package/docs/workbench-dialog.md +4 -1
  263. package/docs/workbench.md +7 -1
  264. package/docs/writing.md +3 -3
  265. package/doctor/copy-capitalization-checks.mjs +10 -7
  266. package/llms.txt +65 -23
  267. package/package.json +7 -1
  268. package/dist/chunk-7W3GKMN4.js.map +0 -1
  269. package/dist/chunk-ACUKTVS3.js.map +0 -1
  270. package/dist/chunk-C3RLKKFQ.js.map +0 -1
  271. package/dist/chunk-CMLPFIC5.js.map +0 -1
  272. package/dist/chunk-ECFCAKWE.js.map +0 -1
  273. package/dist/chunk-EKBMUXFV.js.map +0 -1
  274. package/dist/chunk-HYORKKYP.js.map +0 -1
  275. package/dist/chunk-N7MBGONH.js.map +0 -1
  276. package/dist/chunk-NS2TBYM4.js.map +0 -1
  277. package/dist/chunk-OY2MXIBB.js.map +0 -1
  278. package/dist/chunk-PE2KPZDW.js.map +0 -1
  279. package/dist/chunk-QLA25V2K.js.map +0 -1
  280. package/dist/chunk-TAHR457X.js.map +0 -1
  281. package/dist/chunk-UTCAOOXU.js.map +0 -1
  282. package/dist/chunk-WJKHLOP5.js.map +0 -1
  283. package/dist/chunk-WU57BYYM.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.106` and `kerfjs@5.0.0-beta.106`. 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.108` and `kerfjs@5.0.0-beta.108`. 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
 
@@ -172,6 +172,11 @@ type ToolbarPosition = 'header' | 'footer';
172
172
  /** Control-band density: `default` (60px with 44px groups) or `compact`. */
173
173
  type ToolbarDensity = 'default' | 'compact';
174
174
  interface ToolbarProps {
175
+ /**
176
+ * The toolbar's id, so app code can address it: name it as a scrolling
177
+ * List's chrome in `wireScrollDividers({ targets })`, or find it in tests.
178
+ */
179
+ id?: string;
175
180
  leading?: KerfUiContent;
176
181
  center?: KerfUiContent;
177
182
  trailing?: KerfUiContent;
@@ -236,7 +241,7 @@ interface ToolbarProps {
236
241
  * toolbar) forwards, so the app configures that toolbar instead of styling it.
237
242
  */
238
243
  type ToolbarConfig = Pick<ToolbarProps, 'density' | 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
239
- declare function Toolbar({ leading, center, trailing, label, position, density, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
244
+ declare function Toolbar({ id, leading, center, trailing, label, position, density, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
240
245
 
241
246
  export { Sides, Toolbar, type ToolbarConfig, type ToolbarDensity, type ToolbarPosition, type ToolbarProps };
242
247
  ```
@@ -347,7 +352,7 @@ type ToolbarControlGroupSelectedTone = 'brand' | 'neutral' | 'pop';
347
352
  type ToolbarControlGroupOverflow = 'visible' | 'scroll' | 'wrap';
348
353
  type ToolbarControlGroupExpandedOverflow = 'clip' | 'visible';
349
354
  type ToolbarControlGroupMenuInset = 'standard' | 'compact' | 'list-zero';
350
- type ToolbarControlGroupVisibility = 'always' | 'compact-only' | 'hide-collapsed-tiny' | 'yield-to-expanded-sibling';
355
+ type ToolbarControlGroupVisibility = 'always' | 'compact-only' | 'hide-collapsed-tiny' | 'yield-to-expanded-sibling' | 'yield-to-priority-row';
351
356
  type ToolbarControlGroupSizing = 'content' | 'grow' | 'fill';
352
357
  type ToolbarControlGroupPlacement = 'start' | 'end';
353
358
  interface ToolbarActionLinkProps {
@@ -410,7 +415,13 @@ interface ToolbarControlGroupProps {
410
415
  overflow?: ToolbarControlGroupOverflow;
411
416
  /** Let app-owned anchored surfaces extend outside an expanded search group. Collapsed searches retain their clipping. */
412
417
  expandedOverflow?: ToolbarControlGroupExpandedOverflow;
413
- /** Responsive visibility owned by the enclosing Toolbar container. */
418
+ /**
419
+ * Responsive visibility owned by the enclosing Toolbar container.
420
+ * `yield-to-priority-row` hides this trailing group exactly while its
421
+ * Toolbar's `responsive="trailing-priority"` row is active (an expanded
422
+ * trailing sibling at the Toolbar's `responsiveAt` width), so the app never
423
+ * restates that breakpoint with `hideBelow`.
424
+ */
414
425
  visibility?: ToolbarControlGroupVisibility;
415
426
  /** Hide below this Toolbar content width; requires wireToolbarVisibility. */
416
427
  hideBelow?: CssLength;
@@ -602,7 +613,11 @@ type PopupMenuProps = PopupMenuTrigger & {
602
613
  /** Trigger icon, typically a `LucideIcon`, before any visible text. */
603
614
  icon?: KerfUiContent;
604
615
  items: readonly PopupMenuEntry[];
605
- /** Where the menu opens relative to its trigger. Defaults to `bottom-start`. */
616
+ /**
617
+ * Where the menu opens relative to its trigger, or to its anchor point for
618
+ * a `context` menu (`top-start` opens above the point). Defaults to
619
+ * `bottom-start`.
620
+ */
606
621
  placement?: PopupMenuPlacement;
607
622
  /** Show the disclosure caret after the trigger content. Defaults to true. */
608
623
  caret?: boolean;
@@ -616,13 +631,19 @@ type PopupMenuProps = PopupMenuTrigger & {
616
631
  type PopupMenuElement = HTMLElement;
617
632
  /**
618
633
  * Open a PopupMenu at viewport pointer coordinates. A `context` menu rendered
619
- * without `anchor` moves its invisible anchor there (a menu rendered with
620
- * `anchor` opens with `openPopupMenu` instead). A button-triggered menu (such
634
+ * without `anchor` moves its invisible anchor there and opens at its
635
+ * `placement` (a menu rendered with `anchor` opens with `openPopupMenu`
636
+ * instead). A button-triggered menu (such
621
637
  * as a `ListActionRow` trailing menu) opens `bottom-start` from the point,
622
638
  * like a context menu, for this opening only; its next opening returns to its
623
- * trigger and placement. Needs the `/register` entry.
639
+ * trigger and placement. `options.placement` sets the placement at the point
640
+ * for this opening instead (`top-start` sits above it, say), for either kind
641
+ * of menu; flipping, shifting, and the height cap still apply. Needs the
642
+ * `/register` entry.
624
643
  */
625
- declare function openPopupMenuAt(menu: PopupMenuElement, x: number, y: number): void;
644
+ declare function openPopupMenuAt(menu: PopupMenuElement, x: number, y: number, options?: {
645
+ placement?: PopupMenuPlacement;
646
+ }): void;
626
647
  /**
627
648
  * Open a PopupMenu from its trigger, or a context PopupMenu at the `anchor`
628
649
  * it was rendered with (or the point a previous `openPopupMenuAt` set).
@@ -664,6 +685,7 @@ type ListHeaderRootAttributes = Readonly<Record<`data-${string}`, string | undef
664
685
  'data-divider'?: never;
665
686
  'data-inline'?: never;
666
687
  'data-width'?: never;
688
+ 'data-wrap'?: never;
667
689
  'data-indicator-tone'?: never;
668
690
  'data-toggle'?: never;
669
691
  }>;
@@ -685,6 +707,12 @@ interface ListHeaderBaseProps {
685
707
  inline?: boolean;
686
708
  /** Fill the available row or shrink-wrap while retaining normal header geometry. */
687
709
  width?: 'fill' | 'content';
710
+ /**
711
+ * Wrap a long label onto further lines instead of truncating it to one
712
+ * ellipsized line. Default false. Use it where the whole label must stay
713
+ * readable in a narrow column, such as a specimen or form-section heading.
714
+ */
715
+ wrap?: boolean;
688
716
  indicatorTone?: 'neutral' | 'accent' | 'pop' | 'danger';
689
717
  /** Render as an unanimated loading skeleton: keep the label and action affordance, disable interaction. */
690
718
  placeholder?: boolean;
@@ -745,7 +773,7 @@ type ListHeaderIndicatorProps = {
745
773
  status?: SafeHtml | undefined;
746
774
  };
747
775
  type ListHeaderProps = ListHeaderBaseProps & ListHeaderIndicatorProps & ListHeaderModeProps;
748
- declare function ListHeader({ label, size, headingLevel, count, countLabel, badge, status, density, divider, inline, width, indicatorTone, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes, slot, }: ListHeaderProps): SafeHtml;
776
+ declare function ListHeader({ label, size, headingLevel, count, countLabel, badge, status, density, divider, inline, width, wrap, indicatorTone, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes, slot, }: ListHeaderProps): SafeHtml;
749
777
 
750
778
  export { ListHeader, type ListHeaderProps };
751
779
  ```
@@ -876,6 +904,12 @@ interface ListProps {
876
904
  /** Physical sides that receive the standard 8px control inset. Text insets win on overlap. */
877
905
  controlInsets?: Sides;
878
906
  className?: string;
907
+ /**
908
+ * The list's id, so app code can address it: name it as a
909
+ * `wireScrollDividers` scroller (with a `Toolbar` above it as its chrome),
910
+ * or find it in tests.
911
+ */
912
+ id?: string;
879
913
  /**
880
914
  * Safe `data-*`, `aria-*`, and structural `role` metadata (a named drop
881
915
  * `region`, `aria-busy`); List-owned structural attributes remain
@@ -893,7 +927,7 @@ interface ListProps {
893
927
  */
894
928
  type ListConfig = Pick<ListProps, 'gap' | 'hAlign' | 'vAlign' | 'dividerSides' | 'textInsets' | 'controlInsets'>;
895
929
  /** A stretch-aligned vertical stack with optional gap, flex, fill, scroll, and dividers. */
896
- declare function List({ children, selectionMode, ariaLabel, gap, flex, fill, hAlign, vAlign, scrollable, scrollClearance, frame, maxHeight, minHeight, surface, inset, contentWidth, contentAlign, dividerSides, textInsets, controlInsets, className, rootAttributes, slot, }: ListProps): kerfjs.SafeHtml;
930
+ declare function List({ children, selectionMode, ariaLabel, gap, flex, fill, hAlign, vAlign, scrollable, scrollClearance, frame, maxHeight, minHeight, surface, inset, contentWidth, contentAlign, dividerSides, textInsets, controlInsets, className, id, rootAttributes, slot, }: ListProps): kerfjs.SafeHtml;
897
931
 
898
932
  export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, List, type ListConfig, type ListContentWidth, type ListInset, type ListProps, type ListSurface, ListVerticalAlignment, ScrollClearance, Sides, UiGap };
899
933
  ```
@@ -3430,10 +3464,12 @@ interface SegmentedControlProps<Value extends string = string> {
3430
3464
  className?: string;
3431
3465
  /** Render as a loading placeholder: every choice keeps its live label or icon, none is selected, and every segment is disabled. */
3432
3466
  placeholder?: boolean;
3467
+ /** Disable the whole control: every segment is disabled and dimmed, the selection stays visible, and the group reports `aria-disabled`. A choice's own `disabled` still disables just that segment. */
3468
+ disabled?: boolean;
3433
3469
  /** Native named-slot assignment when composed inside a web component. */
3434
3470
  slot?: string;
3435
3471
  }
3436
- declare function SegmentedControl<Value extends string>({ id, label, value, choices, action, appearance, shape, size, layout, className, placeholder, slot, }: SegmentedControlProps<Value>): kerfjs.SafeHtml;
3472
+ declare function SegmentedControl<Value extends string>({ id, label, value, choices, action, appearance, shape, size, layout, className, placeholder, disabled, slot, }: SegmentedControlProps<Value>): kerfjs.SafeHtml;
3437
3473
 
3438
3474
  export { SegmentedControl, type SegmentedControlAppearance, type SegmentedControlChoice, type SegmentedControlLayout, type SegmentedControlProps, type SegmentedControlShape, type SegmentedControlSize };
3439
3475
  ```
@@ -4307,6 +4343,19 @@ import './css-values.js';
4307
4343
  * and derives its fill, border, and focus ring from `currentColor`.
4308
4344
  */
4309
4345
  type ChipTone = SemanticTone | 'inherit';
4346
+ /** Safe `data-*` identity on a Chip root; Chip-owned attributes are protected. */
4347
+ type ChipRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
4348
+ 'data-component'?: never;
4349
+ 'data-tone'?: never;
4350
+ 'data-appearance'?: never;
4351
+ 'data-shape'?: never;
4352
+ 'data-size'?: never;
4353
+ 'data-disabled'?: never;
4354
+ 'data-truncate'?: never;
4355
+ 'data-item-id'?: never;
4356
+ 'data-link'?: never;
4357
+ 'data-action'?: never;
4358
+ }>;
4310
4359
  interface ChipCommonProps {
4311
4360
  /** Decorative leading icon, normally an unsized LucideIcon. */
4312
4361
  icon?: SafeHtml;
@@ -4317,6 +4366,11 @@ interface ChipCommonProps {
4317
4366
  disabled?: boolean;
4318
4367
  /** Record identifier available to an application delegated action handler. */
4319
4368
  itemId?: string;
4369
+ /**
4370
+ * Safe `data-*` identity on the chip root (a plain, link, or action chip),
4371
+ * for tests and delegated handlers; use `itemId` for the record id.
4372
+ */
4373
+ rootAttributes?: ChipRootAttributes;
4320
4374
  className?: string;
4321
4375
  /** Native named-slot assignment when composed inside a web component. */
4322
4376
  slot?: string;
@@ -4392,9 +4446,9 @@ type ChipProps = ChipCommonProps & ChipLabelProps & (({
4392
4446
  * `href` is set, or a native button when `action` is set. The application
4393
4447
  * owns removal, the link destination, and the action handler.
4394
4448
  */
4395
- declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, href, download, external, removeAction, removeLabel, action, actionLabel, }: ChipProps): SafeHtml;
4449
+ declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, rootAttributes, className, slot, href, download, external, removeAction, removeLabel, action, actionLabel, }: ChipProps): SafeHtml;
4396
4450
 
4397
- export { Chip, type ChipProps, type ChipTone };
4451
+ export { Chip, type ChipProps, type ChipRootAttributes, type ChipTone };
4398
4452
  ```
4399
4453
 
4400
4454
  ## `@kerfjs/ui/lucide-icon`
@@ -4678,6 +4732,20 @@ type DialogSurfaceProps = DialogSurfaceName & DialogSurfaceOptions;
4678
4732
  interface DialogSurfaceOptions {
4679
4733
  /** The dialog's id, for `openDialog(document.getElementById(id))`. */
4680
4734
  id?: string;
4735
+ /**
4736
+ * Id of the element whose text is the dialog's accessible description,
4737
+ * such as the `heading` ToolbarText's `descriptionId` or app-owned summary
4738
+ * copy in the body; rendered as `aria-describedby` on the `<dialog>`.
4739
+ */
4740
+ describedBy?: string;
4741
+ /**
4742
+ * An alert dialog: a confirmation that interrupts the person to report
4743
+ * something urgent or ask before a destructive action ("Delete this
4744
+ * topic?"). Renders `role="alertdialog"` on the `<dialog>`; set
4745
+ * `describedBy` to the element holding the message, and leave
4746
+ * `lightDismiss` off so the person answers it.
4747
+ */
4748
+ alert?: boolean;
4681
4749
  /** The body content. */
4682
4750
  children: KerfUiContent;
4683
4751
  /**
@@ -4792,7 +4860,7 @@ interface DialogSurfaceOptions {
4792
4860
  * floating header and footer measurement, the bottom sheet's keyboard
4793
4861
  * clearance and grabber, and re-render resilience while open.
4794
4862
  */
4795
- declare function DialogSurface({ id, label, labelledBy, heading, headerActions, footer, withoutHeader, lightDismiss, closeLabel, children, size, presentation, preferredWidth, bodyInset, footerInset, viewportGutter, maxHeight, height, minHeight, resizable, enterMotion, exitMotion, bodyLayout, headerPresentation, footerPresentation, footerOffset, rootAttributes, className, slot, }: DialogSurfaceProps): kerfjs.SafeHtml;
4863
+ declare function DialogSurface({ id, label, labelledBy, describedBy, alert, heading, headerActions, footer, withoutHeader, lightDismiss, closeLabel, children, size, presentation, preferredWidth, bodyInset, footerInset, viewportGutter, maxHeight, height, minHeight, resizable, enterMotion, exitMotion, bodyLayout, headerPresentation, footerPresentation, footerOffset, rootAttributes, className, slot, }: DialogSurfaceProps): kerfjs.SafeHtml;
4796
4864
  /** Where a PopoverDialogSurface appears: the top layer, or in flow. */
4797
4865
  type PopoverDialogSurfacePresentation = 'overlay' | 'embedded';
4798
4866
  /** Application `data-*` metadata on the surface root. */
@@ -4937,6 +5005,12 @@ interface ListDetailDialogProps {
4937
5005
  id: string;
4938
5006
  /** The dialog's accessible name. */
4939
5007
  label: string;
5008
+ /**
5009
+ * Id of the element whose text is the dialog's accessible description,
5010
+ * such as app-owned summary copy. The detail's `description` describes the
5011
+ * selection, not the dialog, so it is not wired automatically.
5012
+ */
5013
+ describedBy?: string;
4940
5014
  list: ListDetailDialogList;
4941
5015
  detail: ListDetailDialogDetail;
4942
5016
  /**
@@ -4979,7 +5053,7 @@ interface ListDetailDialogProps {
4979
5053
  * stack's back control dispatches `nav-back`). Built from `DialogSurface`,
4980
5054
  * `SplitView`, and `Pane`.
4981
5055
  */
4982
- declare function ListDetailDialog({ id, label, list, detail, compact, detailActive, backLabel, closeLabel, lightDismiss, size, preferredWidth, height, maxHeight, viewportGutter, rootAttributes, className, slot, }: ListDetailDialogProps): kerfjs.SafeHtml;
5056
+ declare function ListDetailDialog({ id, label, describedBy, list, detail, compact, detailActive, backLabel, closeLabel, lightDismiss, size, preferredWidth, height, maxHeight, viewportGutter, rootAttributes, className, slot, }: ListDetailDialogProps): kerfjs.SafeHtml;
4983
5057
 
4984
5058
  export { ListDetailDialog, type ListDetailDialogDetail, type ListDetailDialogList, type ListDetailDialogProps, type ListDetailDialogRootAttributes };
4985
5059
  ```
@@ -5023,8 +5097,17 @@ interface WorkbenchDialogProps {
5023
5097
  label: string;
5024
5098
  /** The dialog's primary title: an xl heading in the work area's toolbar. */
5025
5099
  title: string;
5026
- /** A short supporting line under the title. */
5100
+ /**
5101
+ * A short supporting line under the title. It is the dialog's accessible
5102
+ * description (`aria-describedby` to its `<id>-description`) unless
5103
+ * `describedBy` names other content.
5104
+ */
5027
5105
  description?: string;
5106
+ /**
5107
+ * Id of the element whose text is the dialog's accessible description, in
5108
+ * place of `description`, such as app-owned summary copy in `main`.
5109
+ */
5110
+ describedBy?: string;
5028
5111
  /** Groups after the title in the work area's toolbar. */
5029
5112
  leading?: KerfUiContent;
5030
5113
  /** Header controls before the close control, such as a `ToolbarControlGroup`. */
@@ -5081,7 +5164,7 @@ interface WorkbenchDialogProps {
5081
5164
  * Escape or a press outside it before the dialog sees the Escape. Built from
5082
5165
  * `DialogSurface` and `Workbench`.
5083
5166
  */
5084
- declare function WorkbenchDialog({ id, label, title, description, leading, actions, main, mainFooter, mainBottomToolbar, leftRail, rightRail, bottomDrawer, compact, closeLabel, lightDismiss, size, preferredWidth, height, maxHeight, viewportGutter, mainMinSize, rootAttributes, className, slot, }: WorkbenchDialogProps): kerfjs.SafeHtml;
5167
+ declare function WorkbenchDialog({ id, label, title, description, describedBy, leading, actions, main, mainFooter, mainBottomToolbar, leftRail, rightRail, bottomDrawer, compact, closeLabel, lightDismiss, size, preferredWidth, height, maxHeight, viewportGutter, mainMinSize, rootAttributes, className, slot, }: WorkbenchDialogProps): kerfjs.SafeHtml;
5085
5168
 
5086
5169
  export { WorkbenchDialog, type WorkbenchDialogProps, type WorkbenchDialogRootAttributes };
5087
5170
  ```
@@ -5603,10 +5686,12 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
5603
5686
 
5604
5687
  /**
5605
5688
  * The Disclosure's surface: `plain` (default) on the surrounding surface,
5606
- * `framed` with the standard neutral border, or `sunken` on the lowered,
5607
- * textured work surface with a border.
5689
+ * `framed` with the standard neutral border, `sunken` on the lowered,
5690
+ * textured work surface with a border, or `embedded` inside owner chrome such
5691
+ * as a `ContentItem`: no margin, border, or padding of its own and a compact
5692
+ * summary row, so the arrow sits on the owner's content inset.
5608
5693
  */
5609
- type DisclosureAppearance = 'plain' | 'framed' | 'sunken';
5694
+ type DisclosureAppearance = 'plain' | 'framed' | 'sunken' | 'embedded';
5610
5695
  /**
5611
5696
  * Application `data-*` identity on the `<details>` root, such as `data-key`;
5612
5697
  * the Disclosure's own configuration attributes stay protected.
@@ -5631,6 +5716,11 @@ interface DisclosureProps {
5631
5716
  * where opening one closes the others (the native `<details name>`).
5632
5717
  */
5633
5718
  name?: string;
5719
+ /**
5720
+ * Surface treatment; defaults to `plain`. Use `embedded` only inside chrome
5721
+ * that already owns the content-item inset, such as a `ContentItem`, and
5722
+ * give it content that draws no inset of its own (`Text flush`).
5723
+ */
5634
5724
  appearance?: DisclosureAppearance;
5635
5725
  /**
5636
5726
  * A `data-action` value on the `<details>` root, for a delegated listener of
@@ -5648,7 +5738,9 @@ interface DisclosureProps {
5648
5738
  * Content a person shows and hides under a summary row: a native `<details>`
5649
5739
  * with a `<summary>` that carries a `DisclosureArrow` and the title, on the
5650
5740
  * shared content-item geometry (8px inline margin, a 1px border, 8px
5651
- * padding, the rounded radius). Keyboard and screen-reader behavior is the
5741
+ * padding, the rounded radius). `appearance="embedded"` drops that geometry
5742
+ * for a Disclosure inside owner chrome (a `ContentItem`) that already insets
5743
+ * it. Keyboard and screen-reader behavior is the
5652
5744
  * platform's: the summary is a button that Enter and Space toggle, and it
5653
5745
  * reports its expanded state. Disclosures sharing a `name` form an accordion.
5654
5746
  */
@@ -5805,22 +5897,47 @@ interface ColorPickerProps {
5805
5897
  /** Native named-slot assignment when composed inside a web component. */
5806
5898
  slot?: string;
5807
5899
  }
5808
- /** The labels, accessible names, and maximum of each channel field per mode. */
5900
+ /**
5901
+ * The labels, accessible names, maximum, and spoken unit of each channel per
5902
+ * mode; the mode's sliders and fields both follow it.
5903
+ */
5809
5904
  declare const COLOR_PICKER_CHANNELS: Record<ColorPickerMode, readonly {
5810
5905
  short: string;
5811
5906
  name: string;
5812
5907
  max: number;
5908
+ unit: '' | '%' | '°';
5813
5909
  }[]>;
5814
5910
  /** The rounded channel values a mode shows for an HSV color. */
5815
5911
  declare function colorPickerChannels(mode: ColorPickerMode, hsv: Hsva): number[];
5912
+ /** One channel slider's attributes; see {@link colorPickerSlider}. */
5913
+ interface ColorPickerSliderState {
5914
+ max: number;
5915
+ value: string;
5916
+ label: string;
5917
+ valueText: string;
5918
+ style: string;
5919
+ }
5920
+ /**
5921
+ * The attributes of one channel slider for a mode's exact channel values:
5922
+ * its range, value, accessible name and spoken value, and an inline style
5923
+ * with the track gradient of the colors that channel produces while the
5924
+ * others hold (the full rainbow for the HSL and HSB hue) and the color under
5925
+ * the thumb.
5926
+ * `undefined` for a slot the mode does not use.
5927
+ */
5928
+ declare function colorPickerSlider(mode: ColorPickerMode, index: number, values: readonly number[]): ColorPickerSliderState | undefined;
5816
5929
  /** The area's spoken value. */
5817
5930
  declare function colorPickerAreaText(hsv: Hsva): string;
5818
5931
  /** The CSS custom properties that place the thumbs and paint the tracks. */
5819
5932
  declare function colorPickerStyle(hsv: Hsva): string;
5820
5933
  /**
5821
- * A full color picker panel: a saturation and brightness area, a hue slider,
5822
- * an optional opacity slider on a checkerboard, a color-model menu (RGB, HSL,
5823
- * HSB, Grayscale) with its channel fields, a hex field (8 digits below full
5934
+ * A full color picker panel: a saturation and brightness area; a slider for
5935
+ * each channel of the color model (red, green, and blue; hue, saturation, and
5936
+ * lightness or brightness; or one gray level), each track painting the colors
5937
+ * that channel produces while the others hold (the hue track the full
5938
+ * rainbow); an optional opacity slider on
5939
+ * a checkerboard; a color-model menu (RGB, HSL, HSB, Grayscale) with its
5940
+ * channel fields, a hex field (8 digits below full
5824
5941
  * opacity) and an opacity field, an optional screen sampler (EyeDropper), and
5825
5942
  * optional preset and sample swatches. The controlled `value` renders it;
5826
5943
  * wire `wireColorPickers` from `@kerfjs/ui/wire-color-pickers` to make it
@@ -5830,7 +5947,7 @@ declare function colorPickerStyle(hsv: Hsva): string;
5830
5947
  */
5831
5948
  declare function ColorPicker({ id, label, value, mode, alpha, name, form, eyedropper, presets, samples, addSampleAction, disabled, className, rootAttributes, slot, }: ColorPickerProps): kerfjs.SafeHtml;
5832
5949
 
5833
- export { COLOR_PICKER_CHANNELS, COLOR_PICKER_SWATCH_ACTION, ColorPicker, type ColorPickerMode, type ColorPickerProps, type ColorPickerRootAttributes, type ColorPickerSamples, colorPickerAreaText, colorPickerChannels, colorPickerStyle };
5950
+ export { COLOR_PICKER_CHANNELS, COLOR_PICKER_SWATCH_ACTION, ColorPicker, type ColorPickerMode, type ColorPickerProps, type ColorPickerRootAttributes, type ColorPickerSamples, type ColorPickerSliderState, colorPickerAreaText, colorPickerChannels, colorPickerSlider, colorPickerStyle };
5834
5951
  ```
5835
5952
 
5836
5953
  ## `@kerfjs/ui/color-field`
@@ -6054,6 +6171,12 @@ interface TextFieldOptions {
6054
6171
  showCount?: boolean;
6055
6172
  /** Single-line value kind (default `text`). */
6056
6173
  type?: TextFieldType;
6174
+ /** Native lower bound for `type="number"` (number or numeric string). */
6175
+ min?: number | string;
6176
+ /** Native upper bound for `type="number"` (number or numeric string). */
6177
+ max?: number | string;
6178
+ /** Native number increment (number, numeric string, or `"any"`). */
6179
+ step?: number | string;
6057
6180
  /** A multi-line field: a `<textarea>`. */
6058
6181
  multiline?: boolean;
6059
6182
  /** A multi-line field's height in lines (default 3). */
@@ -6082,7 +6205,7 @@ interface TextFieldOptions {
6082
6205
  * The whole field is one `<label>`, so clicking anywhere on it focuses the
6083
6206
  * input; the input is named by `label` (or `ariaLabel`) directly.
6084
6207
  */
6085
- declare function TextField({ label, ariaLabel, value, name, placeholder, hint, error, size, icon, clearable, clearLabel, maxLength, showCount, type, multiline, rows, maxRows, disabled, readOnly, required, autocomplete, id, className, rootAttributes, slot, }: TextFieldProps): kerfjs.SafeHtml;
6208
+ declare function TextField({ label, ariaLabel, value, name, placeholder, hint, error, size, icon, clearable, clearLabel, maxLength, showCount, type, min, max, step, multiline, rows, maxRows, disabled, readOnly, required, autocomplete, id, className, rootAttributes, slot, }: TextFieldProps): kerfjs.SafeHtml;
6086
6209
 
6087
6210
  export { TextField, type TextFieldName, type TextFieldOptions, type TextFieldProps, type TextFieldRootAttributes, type TextFieldSize, type TextFieldType };
6088
6211
  ```
@@ -6137,6 +6260,81 @@ declare function Checkbox({ label, checked, indeterminate, name, value, hint, er
6137
6260
  export { Checkbox, type CheckboxProps, type CheckboxRootAttributes, type CheckboxSize };
6138
6261
  ```
6139
6262
 
6263
+ ## `@kerfjs/ui/checkbox-group`
6264
+
6265
+ ```ts
6266
+ import * as kerfjs from 'kerfjs';
6267
+
6268
+ /** `default` is a 20px box beside 16px text; `compact` 18px and 14px. */
6269
+ type CheckboxGroupSize = 'default' | 'compact';
6270
+ /** `vertical` stacks the choices; `horizontal` lines them up and wraps. */
6271
+ type CheckboxGroupOrientation = 'vertical' | 'horizontal';
6272
+ /** Application `data-*` metadata; the CheckboxGroup's own markers stay protected. */
6273
+ type CheckboxGroupRootAttributes = Readonly<Record<`data-${string}`, string | undefined>>;
6274
+ interface CheckboxGroupChoice<Value extends string = string> {
6275
+ value: Value;
6276
+ /** Visible label; it is also the checkbox's accessible name. */
6277
+ label: string;
6278
+ /** Supporting text under this choice's label, also its description. */
6279
+ hint?: string;
6280
+ disabled?: boolean;
6281
+ }
6282
+ /**
6283
+ * A group is named by a visible `label` (its legend), by `ariaLabel`, or by
6284
+ * `labelledBy`, the id of a visible heading elsewhere that names it.
6285
+ */
6286
+ type CheckboxGroupName = {
6287
+ label: string;
6288
+ ariaLabel?: never;
6289
+ labelledBy?: never;
6290
+ } | {
6291
+ label?: never;
6292
+ ariaLabel: string;
6293
+ labelledBy?: never;
6294
+ } | {
6295
+ label?: never;
6296
+ ariaLabel?: never;
6297
+ labelledBy: string;
6298
+ };
6299
+ interface CheckboxGroupOptions<Value extends string = string> {
6300
+ /** Native input `name`: the form field every checked value submits under. */
6301
+ name: string;
6302
+ choices: readonly CheckboxGroupChoice<Value>[];
6303
+ /** The checked values. Omit for none. */
6304
+ value?: readonly NoInfer<Value>[];
6305
+ /** Supporting text below the choices, also the group's description. */
6306
+ hint?: string;
6307
+ /** A validation message: shown in the danger color and marking it invalid. */
6308
+ error?: string;
6309
+ size?: CheckboxGroupSize;
6310
+ orientation?: CheckboxGroupOrientation;
6311
+ /** Disable the whole group. */
6312
+ disabled?: boolean;
6313
+ /** Delegated `data-action` on every checkbox; listen for `change`. */
6314
+ action?: string;
6315
+ /** Associate the checkboxes with a form outside their ancestor chain. */
6316
+ form?: string;
6317
+ /** The fieldset's id. */
6318
+ id?: string;
6319
+ className?: string;
6320
+ /** Safe `data-*` metadata (a `data-key`). */
6321
+ rootAttributes?: CheckboxGroupRootAttributes;
6322
+ /** Native named-slot assignment when composed inside a web component. */
6323
+ slot?: string;
6324
+ }
6325
+ type CheckboxGroupProps<Value extends string = string> = CheckboxGroupName & CheckboxGroupOptions<Value>;
6326
+ /**
6327
+ * Any number of related options among a few visible choices: a native
6328
+ * fieldset of `Checkbox`es with the group label above and hint and error text
6329
+ * below, laid out like a `RadioGroup` so stacked checkboxes and radios share
6330
+ * one control column and one 28px pitch. Every checked value submits under
6331
+ * `name`.
6332
+ */
6333
+ declare function CheckboxGroup<Value extends string>({ label, ariaLabel, labelledBy, name, choices, value, hint, error, size, orientation, disabled, action, form, id, className, rootAttributes, slot, }: CheckboxGroupProps<Value>): kerfjs.SafeHtml;
6334
+
6335
+ export { CheckboxGroup, type CheckboxGroupChoice, type CheckboxGroupName, type CheckboxGroupOptions, type CheckboxGroupOrientation, type CheckboxGroupProps, type CheckboxGroupRootAttributes, type CheckboxGroupSize };
6336
+ ```
6337
+
6140
6338
  ## `@kerfjs/ui/radio-group`
6141
6339
 
6142
6340
  ```ts
@@ -6409,8 +6607,8 @@ import { BadgeTone } from './badge.js';
6409
6607
  import './css-values.js';
6410
6608
  import './semantic-tone-CdW013KF.js';
6411
6609
 
6412
- /** The color family: `neutral` (default), `brand` for the main action, `danger` for a destructive one. */
6413
- type ButtonTone = 'neutral' | 'brand' | 'danger';
6610
+ /** The color family: `neutral` (default), `brand` for the main action, `success` for a positive one, `danger` for a destructive one. */
6611
+ type ButtonTone = 'neutral' | 'brand' | 'success' | 'danger';
6414
6612
  /**
6415
6613
  * How loudly it asks: `primary` (default) fills the button, `secondary`
6416
6614
  * outlines it, and `plain` shows only its text until hovered.
@@ -6450,6 +6648,12 @@ interface ButtonOptions {
6450
6648
  size?: ButtonSize;
6451
6649
  /** Corner shape (default `rounded`). */
6452
6650
  shape?: ButtonShape;
6651
+ /**
6652
+ * Span the full width of the parent instead of sizing to the label, as on
6653
+ * `SplitButton`. The label stays centered and ellipsizes when it no longer
6654
+ * fits.
6655
+ */
6656
+ fill?: boolean;
6453
6657
  /**
6454
6658
  * Make it a toggle: `aria-pressed` reports the state, and a pressed look is
6455
6659
  * drawn on top of the tone and emphasis. The application owns the state and
@@ -6475,6 +6679,12 @@ interface ButtonOptions {
6475
6679
  target?: '_self' | '_blank' | '_parent' | '_top';
6476
6680
  /** Delegated `data-action` the application handles. */
6477
6681
  action?: string;
6682
+ /**
6683
+ * Keep the button's focus ring inside its box when an ancestor clips
6684
+ * overflow. The inset ring is two-tone, a surface-colored line inside the
6685
+ * ring color, so it stays visible on a loud fill of the ring's own hue.
6686
+ */
6687
+ focusRingInset?: boolean;
6478
6688
  /**
6479
6689
  * A count, short text, or `true` for a text-free dot over the button's
6480
6690
  * top-trailing corner, such as how many items a filter hides. It stays out
@@ -6501,14 +6711,15 @@ interface ButtonOptions {
6501
6711
  }
6502
6712
  /**
6503
6713
  * A standalone action button: a native `<button>` (or a link with `href`)
6504
- * in one of three tones and three emphases, at the 44px control height or
6714
+ * in one of four tones and three emphases, at the 44px control height or
6505
6715
  * compact, with a label or as an icon-only square, rounded or pill-shaped,
6506
- * and optionally a `pressed` toggle. Inside a
6716
+ * sized to its label or filling its parent's width, and optionally a
6717
+ * `pressed` toggle. Inside a
6507
6718
  * `ToolbarControlGroup`, use a plain `<button>`, which the group styles; use
6508
6719
  * Button for a dialog footer, a form, or a standalone action beside other
6509
6720
  * content.
6510
6721
  */
6511
- declare function Button({ children, tone, emphasis, size, shape, pressed, icon, loading, disabled, type, name, value, form, href, target, action, badge, badgeLabel, badgeTone, ariaLabel, title, id, className, rootAttributes, slot, }: ButtonProps): kerfjs.SafeHtml;
6722
+ declare function Button({ children, tone, emphasis, size, shape, fill, pressed, icon, loading, disabled, type, name, value, form, href, target, action, focusRingInset, badge, badgeLabel, badgeTone, ariaLabel, title, id, className, rootAttributes, slot, }: ButtonProps): kerfjs.SafeHtml;
6512
6723
 
6513
6724
  export { Button, type ButtonContent, type ButtonEmphasis, type ButtonLabel, type ButtonOptions, type ButtonProps, type ButtonRootAttributes, type ButtonShape, type ButtonSize, type ButtonTone, type ButtonType };
6514
6725
  ```
@@ -6520,11 +6731,15 @@ import { SafeHtml } from 'kerfjs';
6520
6731
 
6521
6732
  /** The loud fill the whole split button paints. */
6522
6733
  type SplitButtonTone = 'brand' | 'neutral' | 'success' | 'warning' | 'danger';
6734
+ /** Corner shape: the shared `rounded` control radius (default) or a full `pill`, as on `Button`. */
6735
+ type SplitButtonShape = 'rounded' | 'pill';
6523
6736
  type SplitButtonRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
6524
6737
  'data-component'?: never;
6525
6738
  'data-tone'?: never;
6526
6739
  'data-fill'?: never;
6527
6740
  'data-busy'?: never;
6741
+ 'data-shape'?: never;
6742
+ 'data-focus-ring-inset'?: never;
6528
6743
  }>;
6529
6744
  interface SplitButtonProps {
6530
6745
  /** Visible primary label. */
@@ -6549,6 +6764,14 @@ interface SplitButtonProps {
6549
6764
  tone?: SplitButtonTone;
6550
6765
  /** Span the full width of the parent instead of sizing to the label. */
6551
6766
  fill?: boolean;
6767
+ /** Corner shape (default `rounded`); `pill` fully rounds both outer ends. */
6768
+ shape?: SplitButtonShape;
6769
+ /**
6770
+ * Keep each half's focus ring inside its box when an ancestor clips
6771
+ * overflow. The inset ring is two-tone, a surface-colored line inside the
6772
+ * ring color, so it stays visible on every loud fill.
6773
+ */
6774
+ focusRingInset?: boolean;
6552
6775
  /** Show work in progress: a spinner replaces the icon and the primary is `aria-busy`. */
6553
6776
  busy?: boolean;
6554
6777
  /** Disable the primary half. */
@@ -6570,9 +6793,9 @@ interface SplitButtonProps {
6570
6793
  * technology directly; the application opens its own menu from the options
6571
6794
  * action and owns the running state.
6572
6795
  */
6573
- declare function SplitButton({ label, action, icon, accessibleLabel, optionsLabel, optionsAction, optionsExpanded, optionsPopup, optionsControls, tone, fill, busy, disabled, optionsDisabled, title, className, rootAttributes, slot, }: SplitButtonProps): SafeHtml;
6796
+ declare function SplitButton({ label, action, icon, accessibleLabel, optionsLabel, optionsAction, optionsExpanded, optionsPopup, optionsControls, tone, fill, shape, focusRingInset, busy, disabled, optionsDisabled, title, className, rootAttributes, slot, }: SplitButtonProps): SafeHtml;
6574
6797
 
6575
- export { SplitButton, type SplitButtonProps, type SplitButtonTone };
6798
+ export { SplitButton, type SplitButtonProps, type SplitButtonShape, type SplitButtonTone };
6576
6799
  ```
6577
6800
 
6578
6801
  ## `@kerfjs/ui/file-picker`