@kerfjs/ui 5.0.0-beta.105 → 5.0.0-beta.107

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 (227) 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 +160 -27
  5. package/ai/component-composition-rules.json +20 -2
  6. package/ai/component-composition.d.ts +11 -0
  7. package/ai/component-composition.json +118 -19
  8. package/ai/component-composition.schema.json +32 -0
  9. package/ai/components/README.md +3 -2
  10. package/ai/components/button.md +4 -1
  11. package/ai/components/checkbox-group.md +89 -0
  12. package/ai/components/checkbox.md +3 -2
  13. package/ai/components/color-picker.md +10 -7
  14. package/ai/components/disclosure.md +6 -1
  15. package/ai/components/foundation.md +1 -1
  16. package/ai/components/list-detail-dialog.md +1 -1
  17. package/ai/components/message-composer.md +2 -1
  18. package/ai/components/radio-group.md +4 -3
  19. package/ai/components/split-button.md +5 -2
  20. package/ai/components/surface-scaffold.md +2 -1
  21. package/ai/components/switch.md +1 -1
  22. package/ai/components/text.md +2 -0
  23. package/ai/components/wa-checkbox-group.md +5 -5
  24. package/ai/components/workbench-dialog.md +1 -1
  25. package/ai/public-api-signatures-v1.md +198 -26
  26. package/ai/skill.md +73 -62
  27. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  28. package/dist/browser/checkbox-group.js +5 -0
  29. package/dist/button.d.ts +15 -2
  30. package/dist/button.js +1 -1
  31. package/dist/catalog.js +9 -8
  32. package/dist/catalog.js.map +1 -1
  33. package/dist/checkbox-group.d.ts +70 -0
  34. package/dist/checkbox-group.js +7 -0
  35. package/dist/checkbox-group.js.map +1 -0
  36. package/dist/{chunk-SQ2Q3OQI.js → chunk-2LM3PYHA.js} +2 -2
  37. package/dist/{chunk-SQ2Q3OQI.js.map → chunk-2LM3PYHA.js.map} +1 -1
  38. package/dist/{chunk-HYORKKYP.js → chunk-3VZ6SFD4.js} +1 -1
  39. package/dist/chunk-3VZ6SFD4.js.map +1 -0
  40. package/dist/{chunk-EKBMUXFV.js → chunk-3Z7N2NAZ.js} +141 -54
  41. package/dist/chunk-3Z7N2NAZ.js.map +1 -0
  42. package/dist/{chunk-FKKJHGN5.js → chunk-AZ3WT77F.js} +2 -2
  43. package/dist/{chunk-FKKJHGN5.js.map → chunk-AZ3WT77F.js.map} +1 -1
  44. package/dist/{chunk-FG6U7KQQ.js → chunk-DNWWF6UN.js} +2 -2
  45. package/dist/{chunk-FG6U7KQQ.js.map → chunk-DNWWF6UN.js.map} +1 -1
  46. package/dist/{chunk-C3RLKKFQ.js → chunk-EYDXFOSH.js} +13 -8
  47. package/dist/chunk-EYDXFOSH.js.map +1 -0
  48. package/dist/{chunk-TAHR457X.js → chunk-G4DRH4A5.js} +3 -1
  49. package/dist/chunk-G4DRH4A5.js.map +1 -0
  50. package/dist/{chunk-PE2KPZDW.js → chunk-HDXUHLTQ.js} +7 -2
  51. package/dist/chunk-HDXUHLTQ.js.map +1 -0
  52. package/dist/chunk-HU5IHXCI.js +73 -0
  53. package/dist/chunk-HU5IHXCI.js.map +1 -0
  54. package/dist/{chunk-DF2YKGIX.js → chunk-JCCN3U6X.js} +2 -2
  55. package/dist/{chunk-DF2YKGIX.js.map → chunk-JCCN3U6X.js.map} +1 -1
  56. package/dist/{chunk-GCAK23PU.js → chunk-MVKHSAKE.js} +2 -2
  57. package/dist/{chunk-GCAK23PU.js.map → chunk-MVKHSAKE.js.map} +1 -1
  58. package/dist/{chunk-DDSCVEO5.js → chunk-NLMEDZRM.js} +5 -5
  59. package/dist/{chunk-DDSCVEO5.js.map → chunk-NLMEDZRM.js.map} +1 -1
  60. package/dist/{chunk-ECFCAKWE.js → chunk-NR6O74ST.js} +5 -1
  61. package/dist/chunk-NR6O74ST.js.map +1 -0
  62. package/dist/{chunk-7W3GKMN4.js → chunk-OQP3PFKQ.js} +7 -4
  63. package/dist/chunk-OQP3PFKQ.js.map +1 -0
  64. package/dist/{chunk-WJKHLOP5.js → chunk-TI2GV36S.js} +8 -2
  65. package/dist/chunk-TI2GV36S.js.map +1 -0
  66. package/dist/{chunk-UTCAOOXU.js → chunk-TXRKCGT3.js} +8 -2
  67. package/dist/chunk-TXRKCGT3.js.map +1 -0
  68. package/dist/{chunk-ACUKTVS3.js → chunk-XWNXGFX3.js} +52 -42
  69. package/dist/chunk-XWNXGFX3.js.map +1 -0
  70. package/dist/{chunk-ZXZAECHZ.js → chunk-Z4DS77U2.js} +2 -2
  71. package/dist/{chunk-ZXZAECHZ.js.map → chunk-Z4DS77U2.js.map} +1 -1
  72. package/dist/collapsible-panel.js +2 -2
  73. package/dist/color-picker.d.ts +30 -5
  74. package/dist/color-picker.js +1 -1
  75. package/dist/disclosure.d.ts +13 -4
  76. package/dist/disclosure.js +1 -1
  77. package/dist/disclosure.js.map +1 -1
  78. package/dist/help-tags-register.js +1 -1
  79. package/dist/index.d.ts +2 -1
  80. package/dist/index.js +20 -19
  81. package/dist/list-action-row.js +1 -1
  82. package/dist/list-detail-dialog.d.ts +7 -1
  83. package/dist/list-detail-dialog.js +6 -4
  84. package/dist/list-detail-dialog.js.map +1 -1
  85. package/dist/list-header.d.ts +8 -1
  86. package/dist/list-header.js +1 -1
  87. package/dist/nav-stack.js +1 -1
  88. package/dist/popup-menu-register.js +2 -2
  89. package/dist/popup-menu.d.ts +15 -5
  90. package/dist/popup-menu.js +1 -1
  91. package/dist/select-register.js +3 -3
  92. package/dist/split-button.d.ts +14 -2
  93. package/dist/split-button.js +1 -1
  94. package/dist/split-view.js +1 -1
  95. package/dist/styles/anchored-surface.css +3 -0
  96. package/dist/styles/button.css +29 -0
  97. package/dist/styles/catalog/components/catalog-example.css +55 -18
  98. package/dist/styles/checkbox-group.css +63 -0
  99. package/dist/styles/checkbox.css +7 -6
  100. package/dist/styles/color-picker.css +69 -34
  101. package/dist/styles/components/actions/button/button.css +29 -0
  102. package/dist/styles/components/actions/split-button/split-button.css +51 -5
  103. package/dist/styles/components/collections/framed-list/framed-list.css +4 -0
  104. package/dist/styles/components/collections/list/list.css +6 -0
  105. package/dist/styles/components/collections/list-header/list-header.css +7 -0
  106. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +3 -0
  107. package/dist/styles/components/forms/checkbox/checkbox.css +7 -6
  108. package/dist/styles/components/forms/checkbox-group/checkbox-group.css +63 -0
  109. package/dist/styles/components/forms/color-picker/color-picker.css +69 -34
  110. package/dist/styles/components/forms/radio-group/radio-group.css +7 -5
  111. package/dist/styles/components/forms/select/select.css +6 -2
  112. package/dist/styles/components/forms/switch/switch.css +3 -3
  113. package/dist/styles/components/layout/pane/pane.css +9 -0
  114. package/dist/styles/components/layout/workbench/workbench.css +4 -0
  115. package/dist/styles/components/navigation/nav-stack/nav-stack.css +64 -1
  116. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +1 -0
  117. package/dist/styles/components/surfaces/content-item/content-item.css +30 -0
  118. package/dist/styles/components/surfaces/disclosure/disclosure.css +38 -0
  119. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +3 -0
  120. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +6 -0
  121. package/dist/styles/components/typography/text/text.css +10 -0
  122. package/dist/styles/content-item.css +30 -0
  123. package/dist/styles/disclosure.css +38 -0
  124. package/dist/styles/foundation.css +21 -0
  125. package/dist/styles/framed-list.css +4 -0
  126. package/dist/styles/list-header.css +7 -0
  127. package/dist/styles/list.css +6 -0
  128. package/dist/styles/nav-stack.css +64 -1
  129. package/dist/styles/pane.css +9 -0
  130. package/dist/styles/radio-group.css +7 -5
  131. package/dist/styles/select.css +6 -2
  132. package/dist/styles/split-button.css +51 -5
  133. package/dist/styles/styles.css +1 -0
  134. package/dist/styles/sunken-panel.css +3 -0
  135. package/dist/styles/surface-scaffold.css +6 -0
  136. package/dist/styles/switch.css +3 -3
  137. package/dist/styles/tab-navigator.css +1 -0
  138. package/dist/styles/text.css +10 -0
  139. package/dist/styles/webawesome.css +45 -9
  140. package/dist/styles/workbench.css +4 -0
  141. package/dist/surface-scaffold.d.ts +7 -1
  142. package/dist/surface-scaffold.js +1 -1
  143. package/dist/wire-color-fields.js +2 -2
  144. package/dist/wire-color-pickers.d.ts +4 -3
  145. package/dist/wire-color-pickers.js +1 -1
  146. package/dist/wire-comboboxes.js +1 -1
  147. package/dist/workbench-dialog.d.ts +11 -2
  148. package/dist/workbench-dialog.js +5 -2
  149. package/dist/workbench-dialog.js.map +1 -1
  150. package/dist/workbench.js +1 -1
  151. package/docs/accessibility.md +40 -1
  152. package/docs/anchored-surface.md +6 -1
  153. package/docs/catalog.md +26 -1
  154. package/docs/color-picker.md +39 -8
  155. package/docs/component-contract.md +33 -2
  156. package/docs/component-selection.md +20 -9
  157. package/docs/design/templates/button/full-width-dark.svg +1 -0
  158. package/docs/design/templates/button/full-width.svg +1 -0
  159. package/docs/design/templates/button-dark.svg +1 -1
  160. package/docs/design/templates/button.svg +1 -1
  161. package/docs/design/templates/checkbox/error-dark.svg +1 -1
  162. package/docs/design/templates/checkbox/error.svg +1 -1
  163. package/docs/design/templates/checkbox/states-dark.svg +1 -1
  164. package/docs/design/templates/checkbox/states.svg +1 -1
  165. package/docs/design/templates/checkbox-dark.svg +1 -1
  166. package/docs/design/templates/checkbox-group/horizontal-dark.svg +1 -0
  167. package/docs/design/templates/checkbox-group/horizontal.svg +1 -0
  168. package/docs/design/templates/checkbox-group/vertical-dark.svg +1 -0
  169. package/docs/design/templates/checkbox-group/vertical.svg +1 -0
  170. package/docs/design/templates/checkbox-group-dark.svg +1 -0
  171. package/docs/design/templates/checkbox-group.svg +1 -0
  172. package/docs/design/templates/checkbox.svg +1 -1
  173. package/docs/design/templates/color-picker/gray-dark.svg +1 -1
  174. package/docs/design/templates/color-picker/gray.svg +1 -1
  175. package/docs/design/templates/color-picker/hsb-dark.svg +1 -0
  176. package/docs/design/templates/color-picker/hsb.svg +1 -0
  177. package/docs/design/templates/color-picker/rgb-dark.svg +1 -1
  178. package/docs/design/templates/color-picker/rgb.svg +1 -1
  179. package/docs/design/templates/color-picker-dark.svg +1 -1
  180. package/docs/design/templates/color-picker.svg +1 -1
  181. package/docs/design/templates/disclosure/embedded-dark.svg +1 -0
  182. package/docs/design/templates/disclosure/embedded.svg +1 -0
  183. package/docs/design/templates/disclosure-dark.svg +1 -1
  184. package/docs/design/templates/disclosure.svg +1 -1
  185. package/docs/design/templates/radio-group/horizontal-dark.svg +1 -1
  186. package/docs/design/templates/radio-group/horizontal.svg +1 -1
  187. package/docs/design/templates/radio-group/vertical-dark.svg +1 -1
  188. package/docs/design/templates/radio-group/vertical.svg +1 -1
  189. package/docs/design/templates/radio-group-dark.svg +1 -1
  190. package/docs/design/templates/radio-group.svg +1 -1
  191. package/docs/design/templates/split-button/full-width-dark.svg +1 -0
  192. package/docs/design/templates/split-button/full-width.svg +1 -0
  193. package/docs/design/templates/split-button/pill-dark.svg +1 -0
  194. package/docs/design/templates/split-button/pill.svg +1 -0
  195. package/docs/design/templates/split-button/states-dark.svg +1 -0
  196. package/docs/design/templates/split-button/states.svg +1 -0
  197. package/docs/design/templates/split-button/tones-dark.svg +1 -0
  198. package/docs/design/templates/split-button/tones.svg +1 -0
  199. package/docs/design/templates/split-button-dark.svg +1 -0
  200. package/docs/design/templates/split-button.svg +1 -0
  201. package/docs/design/templates/switch/states-dark.svg +1 -1
  202. package/docs/design/templates/switch/states.svg +1 -1
  203. package/docs/design/templates/switch-dark.svg +1 -1
  204. package/docs/design/templates/switch.svg +1 -1
  205. package/docs/design/templates.md +10 -3
  206. package/docs/disclosure.md +34 -0
  207. package/docs/list-detail-dialog.md +4 -0
  208. package/docs/nav-stack.md +6 -2
  209. package/docs/surface-scaffold.md +6 -2
  210. package/docs/ui-doctor.md +16 -4
  211. package/docs/webawesome-migration.md +1 -1
  212. package/docs/webawesome-theme.md +48 -16
  213. package/docs/workbench-dialog.md +4 -1
  214. package/docs/writing.md +3 -3
  215. package/doctor/copy-capitalization-checks.mjs +10 -7
  216. package/llms.txt +50 -20
  217. package/package.json +7 -1
  218. package/dist/chunk-7W3GKMN4.js.map +0 -1
  219. package/dist/chunk-ACUKTVS3.js.map +0 -1
  220. package/dist/chunk-C3RLKKFQ.js.map +0 -1
  221. package/dist/chunk-ECFCAKWE.js.map +0 -1
  222. package/dist/chunk-EKBMUXFV.js.map +0 -1
  223. package/dist/chunk-HYORKKYP.js.map +0 -1
  224. package/dist/chunk-PE2KPZDW.js.map +0 -1
  225. package/dist/chunk-TAHR457X.js.map +0 -1
  226. package/dist/chunk-UTCAOOXU.js.map +0 -1
  227. package/dist/chunk-WJKHLOP5.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,25 +1,25 @@
1
1
  export { reorderTabs, wireTabBars } from './chunk-T74YB76U.js';
2
2
  export { wireTextFields } from './chunk-KC6WUSNS.js';
3
3
  export { wireToolbarVisibility } from './chunk-2GOCOLQL.js';
4
+ export { reorderListItems, wireListReorder } from './chunk-MJ5RU6XT.js';
4
5
  export { wireMessageComposers } from './chunk-HTERKONR.js';
5
6
  export { wireOverlaySheets } from './chunk-4RECPEHI.js';
6
7
  export { wireResizableRegions } from './chunk-GS2QD3N7.js';
7
8
  export { wireSearchFields } from './chunk-UMNHJSIO.js';
8
- export { wireComboboxes } from './chunk-GCAK23PU.js';
9
+ export { readChoiceChips, wireChoiceChips } from './chunk-K57NINLH.js';
10
+ export { wireComboboxes } from './chunk-MVKHSAKE.js';
9
11
  export { wireCornerStatus } from './chunk-ZKKO4MHC.js';
10
12
  export { fileMatchesAccept, wireFilePickers } from './chunk-KK3S5OTW.js';
11
13
  export { wireListFocusScroll } from './chunk-QDSZTQXL.js';
12
- export { reorderListItems, wireListReorder } from './chunk-MJ5RU6XT.js';
13
14
  export { ValueTable, ValueTableRow } from './chunk-DZJ4GBSP.js';
14
15
 
15
16
  export { wireScrollDividers } from './chunk-OZ6X76G5.js';
16
17
  export { wireCheckboxes } from './chunk-CNM6ZWP2.js';
17
- export { readChoiceChips, wireChoiceChips } from './chunk-K57NINLH.js';
18
18
  export { TabBarItem } from './chunk-ZCDRLN3B.js';
19
19
  export { TabBar } from './chunk-RFLW4FPL.js';
20
20
  export { TextField } from './chunk-WU57BYYM.js';
21
21
  export { Spacer } from './chunk-YMUIQRWK.js';
22
- export { SplitButton } from './chunk-WJKHLOP5.js';
22
+ export { SplitButton } from './chunk-TI2GV36S.js';
23
23
  export { StateBanner } from './chunk-2FW7D4IG.js';
24
24
  export { SummaryRow } from './chunk-4UB5Z3ZZ.js';
25
25
  export { SunkenPanel } from './chunk-D5RGM3XA.js';
@@ -28,58 +28,59 @@ export { SegmentedControl } from './chunk-NS2TBYM4.js';
28
28
  export { Select } from './chunk-ZX2QQJXD.js';
29
29
 
30
30
  export { applySelection, isApplePlatform, selectionGesture } from './chunk-GXSX6Q6O.js';
31
- export { RadioGroup } from './chunk-OHPYT2BH.js';
32
31
  export { MessageComposer } from './chunk-23PPPNH6.js';
32
+ export { RadioGroup } from './chunk-OHPYT2BH.js';
33
+ export { DialogSurface, PopoverDialogSurface, PopupSurface } from './chunk-G4DRH4A5.js';
34
+ export { closeDialog, openDialog } from './chunk-ATGAJVZ6.js';
35
+
36
+ export { EmptyState } from './chunk-B53PS2LE.js';
33
37
  export { FileDropZone, FilePickerTrigger } from './chunk-KDQZ3E5C.js';
34
38
  export { FramedList, FramedListRow } from './chunk-S2XULQEK.js';
35
39
  export { Grid } from './chunk-KCS6NJ3O.js';
36
40
 
37
- export { ListActionRow } from './chunk-DF2YKGIX.js';
38
- export { DialogSurface, PopoverDialogSurface, PopupSurface } from './chunk-TAHR457X.js';
39
- export { closeDialog, openDialog } from './chunk-ATGAJVZ6.js';
40
-
41
+ export { ListActionRow } from './chunk-JCCN3U6X.js';
42
+ export { ContentItem } from './chunk-5USKCWGL.js';
41
43
  export { ContentSwap } from './chunk-EIET4QLK.js';
42
44
  export { CornerStatus } from './chunk-G3J7JDP6.js';
43
45
  export { EdgeActivityIndicator } from './chunk-QH5KOFNS.js';
44
- export { EmptyState } from './chunk-B53PS2LE.js';
46
+ export { Chip } from './chunk-N7MBGONH.js';
45
47
  export { ChoiceChips } from './chunk-ITUQC4FW.js';
46
48
  export { ColumnTrack } from './chunk-QYMJHS4K.js';
47
49
  export { Combobox } from './chunk-BKUMG2KB.js';
48
- export { ContentItem } from './chunk-5USKCWGL.js';
49
50
  export { openAnchoredSurface, openAnchoredSurfaceAt } from './chunk-3WYREXW4.js';
50
51
  export { BackdropImage } from './chunk-SCDWURBO.js';
51
- export { Button } from './chunk-UTCAOOXU.js';
52
+ export { Button } from './chunk-TXRKCGT3.js';
52
53
  export { Switch } from './chunk-LTBVP6VN.js';
53
54
  export { Row } from './chunk-AMIHGFLP.js';
54
55
  export { SearchField, placeSearchFieldCaret, readSearchField } from './chunk-VEME3D7K.js';
55
- export { ListHeader } from './chunk-ECFCAKWE.js';
56
+ export { ResizableRegion, clampRegionSize, resizeRegionFromPointer } from './chunk-Y6KT7ZTR.js';
57
+ export { ToolbarText } from './chunk-EKHDLBRP.js';
58
+ export { ListHeader } from './chunk-NR6O74ST.js';
59
+ export { FieldLabel, Text } from './chunk-7K6U6FCN.js';
56
60
  export { ListInsetControl } from './chunk-AN5IWMTM.js';
57
61
  export { ListInsetText } from './chunk-S4Y3YTAI.js';
58
62
  export { ListItem, ListItemLink } from './chunk-3GLYIIFR.js';
59
- export { FieldLabel, Text } from './chunk-7K6U6FCN.js';
60
63
  export { FloatingToolbar } from './chunk-S3ECMF23.js';
61
- export { PopupMenu, closePopupMenu, openPopupMenu, openPopupMenuAt } from './chunk-7W3GKMN4.js';
64
+ export { PopupMenu, closePopupMenu, openPopupMenu, openPopupMenuAt } from './chunk-OQP3PFKQ.js';
62
65
 
63
66
 
64
67
 
65
- export { ToolbarText } from './chunk-EKHDLBRP.js';
66
- export { ResizableRegion, clampRegionSize, resizeRegionFromPointer } from './chunk-Y6KT7ZTR.js';
67
68
  export { Skeleton } from './chunk-CVD5IZGB.js';
68
69
  export { DisclosureArrow } from './chunk-TKNVL53O.js';
69
70
  export { ToolbarActionLink, ToolbarControlGroup } from './chunk-2PXZBFEC.js';
71
+ export { Toolbar } from './chunk-CMLPFIC5.js';
70
72
  export { Pane } from './chunk-HQZG3OFL.js';
71
73
 
72
74
  export { ensureSunkenTexture } from './chunk-IKS72C6P.js';
73
75
  export { List } from './chunk-OY2MXIBB.js';
74
76
 
75
- export { Toolbar } from './chunk-CMLPFIC5.js';
76
77
 
77
78
  export { LoadingSpinner } from './chunk-WVS6CUCT.js';
78
79
  export { Badge } from './chunk-RMWNO6BA.js';
80
+ export { CheckboxGroup } from './chunk-HU5IHXCI.js';
79
81
  export { Checkbox } from './chunk-C26Q6P4Q.js';
80
82
  export { LucideIcon } from './chunk-HJXVVFBT.js';
81
83
  export { calc, colorVar, em, fillColor, flex, foregroundColor, foregroundColorVar, lengthVar, pct, plus, px, rem, space, uiColor } from './chunk-IQSRHXZR.js';
82
84
 
83
- export { Chip } from './chunk-N7MBGONH.js';
84
85
 
85
86
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- export { ListActionRow } from './chunk-DF2YKGIX.js';
1
+ export { ListActionRow } from './chunk-JCCN3U6X.js';
2
2
 
3
3
 
4
4
 
@@ -70,6 +70,12 @@ interface ListDetailDialogProps {
70
70
  id: string;
71
71
  /** The dialog's accessible name. */
72
72
  label: string;
73
+ /**
74
+ * Id of the element whose text is the dialog's accessible description,
75
+ * such as app-owned summary copy. The detail's `description` describes the
76
+ * selection, not the dialog, so it is not wired automatically.
77
+ */
78
+ describedBy?: string;
73
79
  list: ListDetailDialogList;
74
80
  detail: ListDetailDialogDetail;
75
81
  /**
@@ -112,6 +118,6 @@ interface ListDetailDialogProps {
112
118
  * stack's back control dispatches `nav-back`). Built from `DialogSurface`,
113
119
  * `SplitView`, and `Pane`.
114
120
  */
115
- declare function ListDetailDialog({ id, label, list, detail, compact, detailActive, backLabel, closeLabel, lightDismiss, size, preferredWidth, height, maxHeight, viewportGutter, rootAttributes, className, slot, }: ListDetailDialogProps): kerfjs.SafeHtml;
121
+ declare function ListDetailDialog({ id, label, describedBy, list, detail, compact, detailActive, backLabel, closeLabel, lightDismiss, size, preferredWidth, height, maxHeight, viewportGutter, rootAttributes, className, slot, }: ListDetailDialogProps): kerfjs.SafeHtml;
116
122
 
117
123
  export { ListDetailDialog, type ListDetailDialogDetail, type ListDetailDialogList, type ListDetailDialogProps, type ListDetailDialogRootAttributes };
@@ -1,19 +1,19 @@
1
- import { SplitView } from './chunk-FKKJHGN5.js';
2
- import { DialogSurface } from './chunk-TAHR457X.js';
1
+ import { SplitView } from './chunk-AZ3WT77F.js';
2
+ import { DialogSurface } from './chunk-G4DRH4A5.js';
3
3
  export { closeDialog, openDialog } from './chunk-ATGAJVZ6.js';
4
4
 
5
5
 
6
- import { ToolbarText } from './chunk-EKHDLBRP.js';
7
6
 
7
+ import { ToolbarText } from './chunk-EKHDLBRP.js';
8
8
 
9
9
 
10
10
  import { ToolbarControlGroup } from './chunk-2PXZBFEC.js';
11
+ import { Toolbar } from './chunk-CMLPFIC5.js';
11
12
  import { Pane } from './chunk-HQZG3OFL.js';
12
13
 
13
14
 
14
15
 
15
16
 
16
- import { Toolbar } from './chunk-CMLPFIC5.js';
17
17
 
18
18
 
19
19
  import { LucideIcon } from './chunk-HJXVVFBT.js';
@@ -29,6 +29,7 @@ function closeGroup(closeLabel) {
29
29
  function ListDetailDialog({
30
30
  id,
31
31
  label,
32
+ describedBy,
32
33
  list,
33
34
  detail,
34
35
  compact = false,
@@ -138,6 +139,7 @@ function ListDetailDialog({
138
139
  {
139
140
  id,
140
141
  label,
142
+ describedBy,
141
143
  withoutHeader: true,
142
144
  lightDismiss,
143
145
  closeLabel,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/surfaces/list-detail-dialog/list-detail-dialog.tsx"],"names":[],"mappings":"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","file":"list-detail-dialog.js","sourcesContent":["import { X } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport type { CssLength } from '../../../shared/styles/css-values.js';\nimport { remify } from '../../../shared/styles/css-values.js';\nimport { Toolbar } from '../../actions/toolbar/toolbar.js';\nimport { ToolbarControlGroup } from '../../actions/toolbar-control-group/toolbar-control-group.js';\nimport { ToolbarText } from '../../actions/toolbar-text/toolbar-text.js';\nimport { Pane } from '../../layout/pane/pane.js';\nimport {\n SplitView,\n type SplitViewListWidth,\n} from '../../layout/split-view/split-view.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\nimport {\n DialogSurface,\n type DialogSurfaceHeight,\n type DialogSurfaceMaxHeight,\n type DialogSurfaceRootAttributes,\n type DialogSurfaceSize,\n} from '../surface-scaffold/surface-scaffold.js';\n\n// Open and close it like any DialogSurface, from the same import.\nexport {\n closeDialog,\n type DialogCloseSource,\n type DialogRequestCloseDetail,\n openDialog,\n} from '../surface-scaffold/surface-scaffold.js';\n\n/** The list column: a secondary title, its own controls, and the list. */\nexport interface ListDetailDialogList {\n /**\n * The column's title, at the default toolbar size so it reads as pane\n * identity beside the detail's primary title. On compact devices it titles\n * the root view.\n */\n title: string;\n /** Controls after the title in the column's header, such as a `ToolbarControlGroup`. */\n toolbar?: KerfUiContent;\n /** The list, usually a `List` of selectable `ListItem`s. */\n content: KerfUiContent;\n /** Content pinned below the list, such as an add control. */\n footer?: KerfUiContent;\n /**\n * The column's width on roomy devices (default 280px, at most 40% of the\n * dialog's width).\n */\n width?: SplitViewListWidth;\n}\n\n/** The detail column: the dialog's primary title, actions, and close control. */\nexport interface ListDetailDialogDetail {\n /**\n * The dialog's primary title: an xl heading at the top of the detail\n * column on roomy devices, and the pushed view's title on compact devices.\n */\n title: string;\n /** A short supporting line under the roomy title. */\n description?: string;\n /**\n * Header controls before the close control, such as a\n * `ToolbarControlGroup`. Primary record actions usually go in `footer`.\n */\n actions?: KerfUiContent;\n /** The selected item's detail. */\n content: KerfUiContent;\n /** Content pinned below the detail, usually its buttons. */\n footer?: KerfUiContent;\n}\n\n/**\n * Application `data-*` identity on the dialog root, such as `data-key`; the\n * dialog's own configuration attributes stay protected.\n */\nexport type ListDetailDialogRootAttributes = DialogSurfaceRootAttributes;\n\nexport interface ListDetailDialogProps {\n /**\n * The dialog's id, for `openDialog(document.getElementById(id))`. Also\n * prefixes the ids of the split and the detail title.\n */\n id: string;\n /** The dialog's accessible name. */\n label: string;\n list: ListDetailDialogList;\n detail: ListDetailDialogDetail;\n /**\n * One pane at a time: derive from `deviceClass().value.compact`. The dialog\n * fills the screen and drills from the list into the detail as a\n * `NavStack`; every view keeps the close control.\n */\n compact?: boolean;\n /** On compact devices, whether the detail is pushed over the list. */\n detailActive?: boolean;\n /** The compact back control's accessible name (default `Back`). */\n backLabel?: string;\n /** The close control's accessible name (default `Close`). */\n closeLabel?: string;\n /** Close on a press on the backdrop; otherwise the panel pulses. */\n lightDismiss?: boolean;\n /** Roomy preferred width preset (default `large`). */\n size?: DialogSurfaceSize;\n /** Roomy preferred width; takes precedence over `size`. */\n preferredWidth?: CssLength;\n /** Roomy definite height (default 560px), bounded by the viewport. */\n height?: DialogSurfaceHeight;\n /** Roomy height cap in place of a definite height. */\n maxHeight?: DialogSurfaceMaxHeight;\n /** Roomy edge clearance from the viewport. */\n viewportGutter?: CssLength;\n rootAttributes?: ListDetailDialogRootAttributes;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nconst DEFAULT_LIST_WIDTH: SplitViewListWidth = { size: 280, maxFraction: 0.4 };\n\nfunction closeGroup(closeLabel: string) {\n return (\n <ToolbarControlGroup appearance=\"borderless\" single>\n <button type=\"button\" aria-label={closeLabel} data-dialog-close=\"\">\n <LucideIcon icon={X} name=\"x\" />\n </button>\n </ToolbarControlGroup>\n );\n}\n\n/**\n * A list-detail dialog: a modal whose list column and detail column each run\n * its full height. The list column carries a secondary title and its own\n * controls; the detail column carries the dialog's primary title, its\n * actions, and the close control, so the divider between them runs from top\n * to bottom. On compact devices it fills the screen and becomes a `NavStack`\n * that drills from the list into the detail. Open it with `openDialog()`;\n * the app owns the selection and, on compact devices, `detailActive` (the\n * stack's back control dispatches `nav-back`). Built from `DialogSurface`,\n * `SplitView`, and `Pane`.\n */\nexport function ListDetailDialog({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n backLabel = 'Back',\n closeLabel = 'Close',\n lightDismiss = false,\n size = 'large',\n preferredWidth,\n height,\n maxHeight,\n viewportGutter,\n rootAttributes,\n className = '',\n slot,\n}: ListDetailDialogProps) {\n const close = closeGroup(closeLabel);\n const split = compact ? (\n <SplitView\n id={`${id}-split`}\n label={label}\n compact\n detailActive={detailActive}\n listTitle={list.title}\n detailTitle={detail.title}\n backLabel={backLabel}\n compactStack={{\n list: {\n toolbar: {\n trailing: (\n <>\n {list.toolbar}\n {close}\n </>\n ),\n },\n footer: list.footer,\n },\n detail: {\n toolbar: {\n trailing: (\n <>\n {detail.actions}\n {close}\n </>\n ),\n },\n footer: detail.footer,\n },\n }}\n list={list.content}\n detail={detail.content}\n />\n ) : (\n <SplitView\n id={`${id}-split`}\n label={label}\n listTitle={list.title}\n detailTitle={detail.title}\n listWidth={list.width ?? DEFAULT_LIST_WIDTH}\n list={\n <Pane\n label={list.title}\n header={\n <Toolbar\n label={list.title}\n leading={<ToolbarText text={list.title} />}\n trailing={list.toolbar}\n />\n }\n footer={list.footer}\n >\n {list.content}\n </Pane>\n }\n detail={\n <Pane\n label={detail.title}\n header={\n <Toolbar\n label={detail.title}\n leading={\n <ToolbarText\n text={detail.title}\n description={detail.description}\n size=\"xlarge\"\n id={`${id}-title`}\n headingLevel={2}\n />\n }\n trailing={\n <>\n {detail.actions}\n {close}\n </>\n }\n />\n }\n footer={detail.footer}\n >\n {detail.content}\n </Pane>\n }\n />\n );\n return (\n <DialogSurface\n id={id}\n label={label}\n withoutHeader\n lightDismiss={lightDismiss}\n closeLabel={closeLabel}\n size={size}\n presentation={compact ? 'fullscreen' : 'modal'}\n preferredWidth={preferredWidth}\n height={\n compact\n ? undefined\n : maxHeight === undefined\n ? (height ?? remify(560))\n : height\n }\n maxHeight={compact ? undefined : maxHeight}\n viewportGutter={compact ? undefined : viewportGutter}\n bodyInset=\"none\"\n bodyLayout=\"fill\"\n rootAttributes={{\n ...rootAttributes,\n 'data-dialog-layout': 'list-detail',\n }}\n className={className}\n slot={slot}\n >\n {split}\n </DialogSurface>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/surfaces/list-detail-dialog/list-detail-dialog.tsx"],"names":[],"mappings":"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","file":"list-detail-dialog.js","sourcesContent":["import { X } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport type { CssLength } from '../../../shared/styles/css-values.js';\nimport { remify } from '../../../shared/styles/css-values.js';\nimport { Toolbar } from '../../actions/toolbar/toolbar.js';\nimport { ToolbarControlGroup } from '../../actions/toolbar-control-group/toolbar-control-group.js';\nimport { ToolbarText } from '../../actions/toolbar-text/toolbar-text.js';\nimport { Pane } from '../../layout/pane/pane.js';\nimport {\n SplitView,\n type SplitViewListWidth,\n} from '../../layout/split-view/split-view.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\nimport {\n DialogSurface,\n type DialogSurfaceHeight,\n type DialogSurfaceMaxHeight,\n type DialogSurfaceRootAttributes,\n type DialogSurfaceSize,\n} from '../surface-scaffold/surface-scaffold.js';\n\n// Open and close it like any DialogSurface, from the same import.\nexport {\n closeDialog,\n type DialogCloseSource,\n type DialogRequestCloseDetail,\n openDialog,\n} from '../surface-scaffold/surface-scaffold.js';\n\n/** The list column: a secondary title, its own controls, and the list. */\nexport interface ListDetailDialogList {\n /**\n * The column's title, at the default toolbar size so it reads as pane\n * identity beside the detail's primary title. On compact devices it titles\n * the root view.\n */\n title: string;\n /** Controls after the title in the column's header, such as a `ToolbarControlGroup`. */\n toolbar?: KerfUiContent;\n /** The list, usually a `List` of selectable `ListItem`s. */\n content: KerfUiContent;\n /** Content pinned below the list, such as an add control. */\n footer?: KerfUiContent;\n /**\n * The column's width on roomy devices (default 280px, at most 40% of the\n * dialog's width).\n */\n width?: SplitViewListWidth;\n}\n\n/** The detail column: the dialog's primary title, actions, and close control. */\nexport interface ListDetailDialogDetail {\n /**\n * The dialog's primary title: an xl heading at the top of the detail\n * column on roomy devices, and the pushed view's title on compact devices.\n */\n title: string;\n /** A short supporting line under the roomy title. */\n description?: string;\n /**\n * Header controls before the close control, such as a\n * `ToolbarControlGroup`. Primary record actions usually go in `footer`.\n */\n actions?: KerfUiContent;\n /** The selected item's detail. */\n content: KerfUiContent;\n /** Content pinned below the detail, usually its buttons. */\n footer?: KerfUiContent;\n}\n\n/**\n * Application `data-*` identity on the dialog root, such as `data-key`; the\n * dialog's own configuration attributes stay protected.\n */\nexport type ListDetailDialogRootAttributes = DialogSurfaceRootAttributes;\n\nexport interface ListDetailDialogProps {\n /**\n * The dialog's id, for `openDialog(document.getElementById(id))`. Also\n * prefixes the ids of the split and the detail title.\n */\n id: string;\n /** The dialog's accessible name. */\n label: string;\n /**\n * Id of the element whose text is the dialog's accessible description,\n * such as app-owned summary copy. The detail's `description` describes the\n * selection, not the dialog, so it is not wired automatically.\n */\n describedBy?: string;\n list: ListDetailDialogList;\n detail: ListDetailDialogDetail;\n /**\n * One pane at a time: derive from `deviceClass().value.compact`. The dialog\n * fills the screen and drills from the list into the detail as a\n * `NavStack`; every view keeps the close control.\n */\n compact?: boolean;\n /** On compact devices, whether the detail is pushed over the list. */\n detailActive?: boolean;\n /** The compact back control's accessible name (default `Back`). */\n backLabel?: string;\n /** The close control's accessible name (default `Close`). */\n closeLabel?: string;\n /** Close on a press on the backdrop; otherwise the panel pulses. */\n lightDismiss?: boolean;\n /** Roomy preferred width preset (default `large`). */\n size?: DialogSurfaceSize;\n /** Roomy preferred width; takes precedence over `size`. */\n preferredWidth?: CssLength;\n /** Roomy definite height (default 560px), bounded by the viewport. */\n height?: DialogSurfaceHeight;\n /** Roomy height cap in place of a definite height. */\n maxHeight?: DialogSurfaceMaxHeight;\n /** Roomy edge clearance from the viewport. */\n viewportGutter?: CssLength;\n rootAttributes?: ListDetailDialogRootAttributes;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nconst DEFAULT_LIST_WIDTH: SplitViewListWidth = { size: 280, maxFraction: 0.4 };\n\nfunction closeGroup(closeLabel: string) {\n return (\n <ToolbarControlGroup appearance=\"borderless\" single>\n <button type=\"button\" aria-label={closeLabel} data-dialog-close=\"\">\n <LucideIcon icon={X} name=\"x\" />\n </button>\n </ToolbarControlGroup>\n );\n}\n\n/**\n * A list-detail dialog: a modal whose list column and detail column each run\n * its full height. The list column carries a secondary title and its own\n * controls; the detail column carries the dialog's primary title, its\n * actions, and the close control, so the divider between them runs from top\n * to bottom. On compact devices it fills the screen and becomes a `NavStack`\n * that drills from the list into the detail. Open it with `openDialog()`;\n * the app owns the selection and, on compact devices, `detailActive` (the\n * stack's back control dispatches `nav-back`). Built from `DialogSurface`,\n * `SplitView`, and `Pane`.\n */\nexport function ListDetailDialog({\n id,\n label,\n describedBy,\n list,\n detail,\n compact = false,\n detailActive = false,\n backLabel = 'Back',\n closeLabel = 'Close',\n lightDismiss = false,\n size = 'large',\n preferredWidth,\n height,\n maxHeight,\n viewportGutter,\n rootAttributes,\n className = '',\n slot,\n}: ListDetailDialogProps) {\n const close = closeGroup(closeLabel);\n const split = compact ? (\n <SplitView\n id={`${id}-split`}\n label={label}\n compact\n detailActive={detailActive}\n listTitle={list.title}\n detailTitle={detail.title}\n backLabel={backLabel}\n compactStack={{\n list: {\n toolbar: {\n trailing: (\n <>\n {list.toolbar}\n {close}\n </>\n ),\n },\n footer: list.footer,\n },\n detail: {\n toolbar: {\n trailing: (\n <>\n {detail.actions}\n {close}\n </>\n ),\n },\n footer: detail.footer,\n },\n }}\n list={list.content}\n detail={detail.content}\n />\n ) : (\n <SplitView\n id={`${id}-split`}\n label={label}\n listTitle={list.title}\n detailTitle={detail.title}\n listWidth={list.width ?? DEFAULT_LIST_WIDTH}\n list={\n <Pane\n label={list.title}\n header={\n <Toolbar\n label={list.title}\n leading={<ToolbarText text={list.title} />}\n trailing={list.toolbar}\n />\n }\n footer={list.footer}\n >\n {list.content}\n </Pane>\n }\n detail={\n <Pane\n label={detail.title}\n header={\n <Toolbar\n label={detail.title}\n leading={\n <ToolbarText\n text={detail.title}\n description={detail.description}\n size=\"xlarge\"\n id={`${id}-title`}\n headingLevel={2}\n />\n }\n trailing={\n <>\n {detail.actions}\n {close}\n </>\n }\n />\n }\n footer={detail.footer}\n >\n {detail.content}\n </Pane>\n }\n />\n );\n return (\n <DialogSurface\n id={id}\n label={label}\n describedBy={describedBy}\n withoutHeader\n lightDismiss={lightDismiss}\n closeLabel={closeLabel}\n size={size}\n presentation={compact ? 'fullscreen' : 'modal'}\n preferredWidth={preferredWidth}\n height={\n compact\n ? undefined\n : maxHeight === undefined\n ? (height ?? remify(560))\n : height\n }\n maxHeight={compact ? undefined : maxHeight}\n viewportGutter={compact ? undefined : viewportGutter}\n bodyInset=\"none\"\n bodyLayout=\"fill\"\n rootAttributes={{\n ...rootAttributes,\n 'data-dialog-layout': 'list-detail',\n }}\n className={className}\n slot={slot}\n >\n {split}\n </DialogSurface>\n );\n}\n"]}
@@ -12,6 +12,7 @@ type ListHeaderRootAttributes = Readonly<Record<`data-${string}`, string | undef
12
12
  'data-divider'?: never;
13
13
  'data-inline'?: never;
14
14
  'data-width'?: never;
15
+ 'data-wrap'?: never;
15
16
  'data-indicator-tone'?: never;
16
17
  'data-toggle'?: never;
17
18
  }>;
@@ -33,6 +34,12 @@ interface ListHeaderBaseProps {
33
34
  inline?: boolean;
34
35
  /** Fill the available row or shrink-wrap while retaining normal header geometry. */
35
36
  width?: 'fill' | 'content';
37
+ /**
38
+ * Wrap a long label onto further lines instead of truncating it to one
39
+ * ellipsized line. Default false. Use it where the whole label must stay
40
+ * readable in a narrow column, such as a specimen or form-section heading.
41
+ */
42
+ wrap?: boolean;
36
43
  indicatorTone?: 'neutral' | 'accent' | 'pop' | 'danger';
37
44
  /** Render as an unanimated loading skeleton: keep the label and action affordance, disable interaction. */
38
45
  placeholder?: boolean;
@@ -93,6 +100,6 @@ type ListHeaderIndicatorProps = {
93
100
  status?: SafeHtml | undefined;
94
101
  };
95
102
  type ListHeaderProps = ListHeaderBaseProps & ListHeaderIndicatorProps & ListHeaderModeProps;
96
- 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;
103
+ 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;
97
104
 
98
105
  export { ListHeader, type ListHeaderProps };
@@ -1,4 +1,4 @@
1
- export { ListHeader } from './chunk-ECFCAKWE.js';
1
+ export { ListHeader } from './chunk-NR6O74ST.js';
2
2
 
3
3
 
4
4
 
package/dist/nav-stack.js CHANGED
@@ -1,4 +1,4 @@
1
- export { NavStack } from './chunk-ZXZAECHZ.js';
1
+ export { NavStack } from './chunk-Z4DS77U2.js';
2
2
 
3
3
 
4
4
 
@@ -1,5 +1,5 @@
1
- import { installPopupMenus } from './chunk-C3RLKKFQ.js';
2
- import { installHelpTags } from './chunk-SQ2Q3OQI.js';
1
+ import { installPopupMenus } from './chunk-EYDXFOSH.js';
2
+ import { installHelpTags } from './chunk-2LM3PYHA.js';
3
3
 
4
4
 
5
5
 
@@ -98,7 +98,11 @@ type PopupMenuProps = PopupMenuTrigger & {
98
98
  /** Trigger icon, typically a `LucideIcon`, before any visible text. */
99
99
  icon?: KerfUiContent;
100
100
  items: readonly PopupMenuEntry[];
101
- /** Where the menu opens relative to its trigger. Defaults to `bottom-start`. */
101
+ /**
102
+ * Where the menu opens relative to its trigger, or to its anchor point for
103
+ * a `context` menu (`top-start` opens above the point). Defaults to
104
+ * `bottom-start`.
105
+ */
102
106
  placement?: PopupMenuPlacement;
103
107
  /** Show the disclosure caret after the trigger content. Defaults to true. */
104
108
  caret?: boolean;
@@ -112,13 +116,19 @@ type PopupMenuProps = PopupMenuTrigger & {
112
116
  type PopupMenuElement = HTMLElement;
113
117
  /**
114
118
  * Open a PopupMenu at viewport pointer coordinates. A `context` menu rendered
115
- * without `anchor` moves its invisible anchor there (a menu rendered with
116
- * `anchor` opens with `openPopupMenu` instead). A button-triggered menu (such
119
+ * without `anchor` moves its invisible anchor there and opens at its
120
+ * `placement` (a menu rendered with `anchor` opens with `openPopupMenu`
121
+ * instead). A button-triggered menu (such
117
122
  * as a `ListActionRow` trailing menu) opens `bottom-start` from the point,
118
123
  * like a context menu, for this opening only; its next opening returns to its
119
- * trigger and placement. Needs the `/register` entry.
124
+ * trigger and placement. `options.placement` sets the placement at the point
125
+ * for this opening instead (`top-start` sits above it, say), for either kind
126
+ * of menu; flipping, shifting, and the height cap still apply. Needs the
127
+ * `/register` entry.
120
128
  */
121
- declare function openPopupMenuAt(menu: PopupMenuElement, x: number, y: number): void;
129
+ declare function openPopupMenuAt(menu: PopupMenuElement, x: number, y: number, options?: {
130
+ placement?: PopupMenuPlacement;
131
+ }): void;
122
132
  /**
123
133
  * Open a PopupMenu from its trigger, or a context PopupMenu at the `anchor`
124
134
  * it was rendered with (or the point a previous `openPopupMenuAt` set).
@@ -1,4 +1,4 @@
1
- export { PopupMenu, closePopupMenu, openPopupMenu, openPopupMenuAt } from './chunk-7W3GKMN4.js';
1
+ export { PopupMenu, closePopupMenu, openPopupMenu, openPopupMenuAt } from './chunk-OQP3PFKQ.js';
2
2
 
3
3
 
4
4
 
@@ -1,7 +1,7 @@
1
- import { installPopupMenus } from './chunk-C3RLKKFQ.js';
2
- import { installHelpTags } from './chunk-SQ2Q3OQI.js';
1
+ import { installPopupMenus } from './chunk-EYDXFOSH.js';
2
+ import { installHelpTags } from './chunk-2LM3PYHA.js';
3
3
  import { summarizeSelection } from './chunk-TUID42UE.js';
4
- import { followAnchor, positionPopup } from './chunk-PE2KPZDW.js';
4
+ import { followAnchor, positionPopup } from './chunk-HDXUHLTQ.js';
5
5
 
6
6
 
7
7
  // src/components/forms/select/internal/select-element.ts
@@ -2,11 +2,15 @@ import { SafeHtml } from 'kerfjs';
2
2
 
3
3
  /** The loud fill the whole split button paints. */
4
4
  type SplitButtonTone = 'brand' | 'neutral' | 'success' | 'warning' | 'danger';
5
+ /** Corner shape: the shared `rounded` control radius (default) or a full `pill`, as on `Button`. */
6
+ type SplitButtonShape = 'rounded' | 'pill';
5
7
  type SplitButtonRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
6
8
  'data-component'?: never;
7
9
  'data-tone'?: never;
8
10
  'data-fill'?: never;
9
11
  'data-busy'?: never;
12
+ 'data-shape'?: never;
13
+ 'data-focus-ring-inset'?: never;
10
14
  }>;
11
15
  interface SplitButtonProps {
12
16
  /** Visible primary label. */
@@ -31,6 +35,14 @@ interface SplitButtonProps {
31
35
  tone?: SplitButtonTone;
32
36
  /** Span the full width of the parent instead of sizing to the label. */
33
37
  fill?: boolean;
38
+ /** Corner shape (default `rounded`); `pill` fully rounds both outer ends. */
39
+ shape?: SplitButtonShape;
40
+ /**
41
+ * Keep each half's focus ring inside its box when an ancestor clips
42
+ * overflow. The inset ring is two-tone, a surface-colored line inside the
43
+ * ring color, so it stays visible on every loud fill.
44
+ */
45
+ focusRingInset?: boolean;
34
46
  /** Show work in progress: a spinner replaces the icon and the primary is `aria-busy`. */
35
47
  busy?: boolean;
36
48
  /** Disable the primary half. */
@@ -52,6 +64,6 @@ interface SplitButtonProps {
52
64
  * technology directly; the application opens its own menu from the options
53
65
  * action and owns the running state.
54
66
  */
55
- declare function SplitButton({ label, action, icon, accessibleLabel, optionsLabel, optionsAction, optionsExpanded, optionsPopup, optionsControls, tone, fill, busy, disabled, optionsDisabled, title, className, rootAttributes, slot, }: SplitButtonProps): SafeHtml;
67
+ 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;
56
68
 
57
- export { SplitButton, type SplitButtonProps, type SplitButtonTone };
69
+ export { SplitButton, type SplitButtonProps, type SplitButtonShape, type SplitButtonTone };
@@ -1,4 +1,4 @@
1
- export { SplitButton } from './chunk-WJKHLOP5.js';
1
+ export { SplitButton } from './chunk-TI2GV36S.js';
2
2
 
3
3
 
4
4
 
@@ -1,4 +1,4 @@
1
- export { SplitView } from './chunk-FKKJHGN5.js';
1
+ export { SplitView } from './chunk-AZ3WT77F.js';
2
2
 
3
3
 
4
4
 
@@ -20,6 +20,9 @@
20
20
  border: 1px solid var(--kui-color-neutral-border-normal);
21
21
  border-radius: var(--kui-anchored-surface-radius, var(--kui-radius-m));
22
22
  color: var(--kui-color-text, inherit);
23
+ --kui-color-surface-current: var(--kui-color-surface-raised);
24
+ --kui-color-surface-current-region: transparent;
25
+ --kui-color-surface-current-tint: transparent;
23
26
  background: var(--kui-color-surface-raised);
24
27
  box-shadow: var(--kui-shadow-l);
25
28
  font: inherit;
@@ -75,6 +75,18 @@
75
75
  flex-shrink: 0;
76
76
  padding: 0;
77
77
  }
78
+ /* fill: the button spans its parent's available inline width, as a filled
79
+ SplitButton does. The label stays centered and ellipsizes once it no longer
80
+ fits; an icon-only button that fills spans too. */
81
+ .kui-button[data-fill="true"] {
82
+ display: flex;
83
+ width: 100%;
84
+ min-width: 0;
85
+ }
86
+ .kui-button[data-fill="true"] > .kui-button__label {
87
+ overflow: hidden;
88
+ text-overflow: ellipsis;
89
+ }
78
90
  /* A pill: fully round ends (a circle when icon-only). */
79
91
  .kui-button[data-shape="pill"] {
80
92
  border-radius: var(--kui-layout-pill-radius, calc(1px + 1.3125rem));
@@ -197,6 +209,23 @@
197
209
  outline: var(--kui-focus-ring);
198
210
  outline-offset: 1px;
199
211
  }
212
+ /* focusRingInset: inside an ancestor that clips overflow, the ring moves
213
+ inside the box. On a loud fill the ring can share the fill's hue (brand),
214
+ so a surface-colored line runs inside it: the ring then meets the surface
215
+ on both edges, as the outside ring does, whatever the fill. The line is an
216
+ inset shadow from the padding edge (inside the 1px border) to 3px past the
217
+ ring, wide enough to stay solid at a fractional position; a pressed
218
+ toggle's inset ring lies under the focus ring meanwhile. The line paints
219
+ the surface the button sits on: the surface context's opaque color with
220
+ its translucent tint (a sunken or quiet fill) layered over it
221
+ (foundation.css), so it reads as a cut through the fill, not a halo. */
222
+ .kui-button[data-focus-ring-inset="true"]:focus-visible {
223
+ outline-offset: -3px;
224
+ box-shadow:
225
+ inset 0 0 0 5px var(--kui-color-surface-current-tint, transparent),
226
+ inset 0 0 0 5px var(--kui-color-surface-current-region, transparent),
227
+ inset 0 0 0 5px var(--kui-color-surface-current, var(--kui-color-surface));
228
+ }
200
229
  .kui-button:is(:disabled, [aria-disabled="true"]) {
201
230
  cursor: not-allowed;
202
231
  opacity: 0.5;
@@ -182,32 +182,69 @@
182
182
  }
183
183
  }
184
184
 
185
- /* Bare specimens use a small inset to align with the surrounding examples. */
186
- .kui-catalog-example[data-align="glyph"]
187
- > :not([data-catalog-example-label]):not([data-catalog-example-note]):not(
188
- :popover-open,
189
- :modal
190
- ) {
185
+ /* An aligned example insets its specimens so their visible edge lines up with
186
+ the label: 16px for a bare glyph, 8px for a control, and 8px for a text
187
+ trigger (whose own 8px inset plus 1px border then puts its text on the
188
+ label's). The inset is a grid column rather than a margin on each specimen:
189
+ the label and note span the full width while every specimen sits in the
190
+ inset column, so a percentage width — a full-width field, a fill-width
191
+ Select, a full-width or control-sized frame — resolves against that column
192
+ and ends on the example's inline-end edge instead of running past it by the
193
+ inset. Specimens keep their own width caps, and top-layer popovers and modal
194
+ dialogs ignore grid placement. */
195
+ .kui-catalog-example:is(
196
+ [data-align="glyph"],
197
+ [data-align="inline-control"],
198
+ [data-align="text-trigger"]
199
+ ) {
200
+ display: grid;
201
+ grid-template-columns: var(--kui-catalog-example-align) minmax(0, 1fr);
202
+ align-content: start;
203
+ align-items: start;
204
+ justify-items: start;
205
+ column-gap: 0;
206
+ }
207
+
208
+ .kui-catalog-example[data-align="glyph"] {
191
209
  --kui-catalog-example-align: 1rem;
192
- margin-inline-start: var(--kui-catalog-example-align);
193
210
  }
194
211
 
195
- .kui-catalog-example[data-align="inline-control"]
196
- > :not([data-catalog-example-label]):not([data-catalog-example-note]):not(
197
- :popover-open,
198
- :modal
199
- ) {
212
+ .kui-catalog-example:is(
213
+ [data-align="inline-control"],
214
+ [data-align="text-trigger"]
215
+ ) {
200
216
  --kui-catalog-example-align: 0.5rem;
201
- margin-inline-start: var(--kui-catalog-example-align);
202
217
  }
203
218
 
204
- /* A trigger's text lines up with the example label's: the trigger's own
205
- inset (8px plus its 1px border) follows this 8px offset. */
206
- .kui-catalog-example[data-align="text-trigger"]
219
+ .kui-catalog-example:is(
220
+ [data-align="glyph"],
221
+ [data-align="inline-control"],
222
+ [data-align="text-trigger"]
223
+ )
224
+ > * {
225
+ grid-column: 2;
226
+ }
227
+
228
+ /* The column is the whole inset: a specimen's own start margin (a ListItem's
229
+ 8px list inset) does not stack on it. Top-layer surfaces keep their
230
+ centering margins. */
231
+ .kui-catalog-example:is(
232
+ [data-align="glyph"],
233
+ [data-align="inline-control"],
234
+ [data-align="text-trigger"]
235
+ )
207
236
  > :not([data-catalog-example-label]):not([data-catalog-example-note]):not(
208
237
  :popover-open,
209
238
  :modal
210
239
  ) {
211
- --kui-catalog-example-align: 0.5rem;
212
- margin-inline-start: var(--kui-catalog-example-align);
240
+ margin-inline-start: 0;
241
+ }
242
+
243
+ .kui-catalog-example:is(
244
+ [data-align="glyph"],
245
+ [data-align="inline-control"],
246
+ [data-align="text-trigger"]
247
+ )
248
+ > :is([data-catalog-example-label], [data-catalog-example-note]) {
249
+ grid-column: 1 / -1;
213
250
  }
@@ -0,0 +1,63 @@
1
+ /* CheckboxGroup: the group label, the choices (each a Kerf Checkbox, which
2
+ draws its own box, label, and hint), and hint and error text below. It is
3
+ laid out exactly like a RadioGroup: each box sits on the group's
4
+ inline-start edge and stacked choices sit 8px apart, the 28px pitch
5
+ checkboxes and radios share. */
6
+ .kui-checkbox-group {
7
+ display: flex;
8
+ min-width: 0;
9
+ flex-direction: column;
10
+ margin: 0;
11
+ padding: 0;
12
+ border: none;
13
+ font-size: var(--kui-font-m, 1rem);
14
+ font-weight: 400;
15
+ line-height: 1.2;
16
+ }
17
+ .kui-checkbox-group[data-size="compact"] {
18
+ font-size: var(--kui-font-s, 0.875rem);
19
+ }
20
+ /* The label matches every Kerf form control's label (RadioGroup's too). */
21
+ .kui-checkbox-group__label {
22
+ display: block;
23
+ float: none;
24
+ margin-block-end: 0.375rem;
25
+ padding: 0;
26
+ padding-inline: calc(1px + var(--kui-layout-item-padding, 0.5rem));
27
+ color: var(--kui-color-neutral-on-quiet);
28
+ font-size: var(--kui-font-xs);
29
+ font-weight: 650;
30
+ letter-spacing: 0.04em;
31
+ line-height: 1.2;
32
+ text-transform: uppercase;
33
+ }
34
+ .kui-checkbox-group__choices {
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: var(--kui-space-xs);
38
+ }
39
+ .kui-checkbox-group[data-orientation="horizontal"]
40
+ .kui-checkbox-group__choices {
41
+ flex-direction: row;
42
+ flex-wrap: wrap;
43
+ column-gap: 1.5rem;
44
+ }
45
+ .kui-checkbox-group__hint,
46
+ .kui-checkbox-group__error {
47
+ display: block;
48
+ margin-block-start: 0.4375rem;
49
+ padding-inline: calc(1px + var(--kui-layout-item-padding, 0.5rem));
50
+ color: var(--kui-color-text-quiet);
51
+ font-size: var(--kui-font-s, 0.875rem);
52
+ line-height: 1.6;
53
+ }
54
+ .kui-checkbox-group[data-size="compact"]
55
+ :is(.kui-checkbox-group__hint, .kui-checkbox-group__error) {
56
+ font-size: var(--kui-font-xs, 0.75rem);
57
+ }
58
+ .kui-checkbox-group__error {
59
+ color: var(--kui-color-danger-on-quiet);
60
+ }
61
+ .kui-checkbox-group__hint + .kui-checkbox-group__error {
62
+ margin-block-start: 0;
63
+ }
@@ -1,6 +1,7 @@
1
- /* Checkbox: a drawn box beside its label, with hint and error text on the
2
- label's column. The native input sits invisibly over the box, so pointer,
3
- keyboard, touch exploration, and forms all reach the real control. */
1
+ /* Checkbox: a drawn box beside its label, with hint and error text directly
2
+ under the label on its column, as a grouped choice hint sits. The native
3
+ input sits invisibly over the box, so pointer, keyboard, touch
4
+ exploration, and forms all reach the real control. */
4
5
  .kui-checkbox {
5
6
  --_kui-checkbox-box: 1.25rem;
6
7
  --_kui-checkbox-gap: 0.5rem;
@@ -91,7 +92,6 @@
91
92
  .kui-checkbox__hint,
92
93
  .kui-checkbox__error {
93
94
  display: block;
94
- margin-block-start: 0.4375rem;
95
95
  padding-inline-start: calc(
96
96
  var(--_kui-checkbox-box) + var(--_kui-checkbox-gap)
97
97
  );
@@ -106,8 +106,9 @@
106
106
  .kui-checkbox__error {
107
107
  color: var(--kui-color-danger-on-quiet);
108
108
  }
109
- .kui-checkbox__hint + .kui-checkbox__error {
110
- margin-block-start: 0;
109
+ /* Inside a CheckboxGroup an invalid group marks every box. */
110
+ .kui-checkbox-group[data-invalid] .kui-checkbox__box {
111
+ border-color: var(--kui-color-danger-border-loud);
111
112
  }
112
113
  @media (forced-colors: active) {
113
114
  .kui-checkbox__box {