@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/actions/popup-menu/internal/reveal-in-menu.ts","../src/components/actions/popup-menu/internal/popup-menu-controller.ts"],"names":["root"],"mappings":"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","file":"chunk-EYDXFOSH.js","sourcesContent":["/**\n * Scroll `item`'s own menu panel by the least amount that brings the item\n * fully inside it, leaving the page and every other scroller alone. Pairs\n * with `focus({ preventScroll: true })`: a menu in the top layer is fixed, so\n * the browser's own focus scrolling would move the page beneath it.\n */\nexport function revealInMenu(item: HTMLElement, menu: HTMLElement): void {\n if (menu.scrollHeight <= menu.clientHeight) return;\n const box = item.getBoundingClientRect();\n const top = menu.getBoundingClientRect().top + menu.clientTop;\n const bottom = top + menu.clientHeight;\n if (box.top < top) menu.scrollTop -= top - box.top;\n else if (box.bottom > bottom) menu.scrollTop += box.bottom - bottom;\n}\n","import {\n followAnchor,\n PHONE_SUBMENU_QUERY,\n phoneSubmenuPosition,\n pointAnchor,\n type PopupAnchor,\n type PopupPlacement,\n positionPopup,\n} from '../../../../shared/popup/position-popup.js';\nimport {\n POPUP_MENU_CLOSE_EVENT,\n POPUP_MENU_OPEN_EVENT,\n POPUP_MENU_SELECT_EVENT,\n type PopupMenuOpenDetail,\n type PopupMenuSelectDetail,\n} from './popup-menu-events.js';\nimport { revealInMenu } from './reveal-in-menu.js';\n\nconst ROOT = '.kui-popup-menu';\nconst MENU = '.kui-popup-menu__menu';\nconst ITEM = '.kui-popup-menu__item';\nconst TRIGGER = '.kui-popup-menu__trigger';\nconst ROOT_OPENER =\n ':scope > .kui-popup-menu__trigger, :scope > .kui-popup-menu__context-anchor';\n\n/** A typeahead query resets after this long without a keystroke. */\nexport const TYPEAHEAD_RESET = 1000;\n\n/** A submenu the pointer has left closes after this grace period. */\nexport const SUBMENU_CLOSE_DELAY = 100;\n\n/**\n * A submenu lifts by its own inset plus border, so its first row lines up\n * with the item that opened it.\n */\nconst SUBMENU_CROSS_OFFSET = -5;\n\n/** How far ahead of the pointer, toward the submenu, the safe triangle starts. */\nconst SAFE_TRIANGLE_LEAD = 2;\n\n/** The submenu attribute marking a pointer opening, which gets the safe triangle. */\nexport const POINTER_OPENED = 'data-pointer-opened';\n\ntype Focus = 'first' | 'last' | 'none';\n\nconst installed = new WeakSet<Document>();\n\nconst isOpen = (menu: Element): boolean => {\n try {\n return menu.matches(':popover-open');\n } catch {\n return false;\n }\n};\n\nconst isDisabled = (item: Element): boolean =>\n item.getAttribute('aria-disabled') === 'true';\n\nconst rootMenuOf = (root: Element): HTMLElement | null =>\n root.querySelector<HTMLElement>(`:scope > ${MENU}`);\n\nconst rootOpenerOf = (root: Element): HTMLElement | null =>\n root.querySelector<HTMLElement>(ROOT_OPENER);\n\n/** A submenu item's own menu, the sibling after it in its host. */\nconst submenuOf = (item: Element): HTMLElement | null =>\n item.parentElement?.classList.contains('kui-popup-menu__submenu-host') &&\n item.nextElementSibling?.matches(MENU)\n ? (item.nextElementSibling as HTMLElement)\n : null;\n\n/** The control a menu opened from: the root trigger, or a submenu's item. */\nfunction openerOf(menu: Element): HTMLElement | null {\n if (menu.hasAttribute('data-submenu')) {\n const item = menu.previousElementSibling;\n return item instanceof HTMLElement && item.matches(ITEM) ? item : null;\n }\n const root = menu.parentElement;\n return root?.matches(ROOT) ? rootOpenerOf(root) : null;\n}\n\n/** The items of one menu level, in order; disabled items are skipped by default. */\nfunction levelItems(menu: Element, includeDisabled = false): HTMLElement[] {\n return Array.from(menu.querySelectorAll<HTMLElement>(ITEM)).filter(\n (item) =>\n item.closest(MENU) === menu && (includeDisabled || !isDisabled(item)),\n );\n}\n\n/** The open submenus a menu level shows directly. */\nfunction openSubmenus(menu: Element): HTMLElement[] {\n return levelItems(menu, true)\n .map(submenuOf)\n .filter((submenu): submenu is HTMLElement => !!submenu && isOpen(submenu));\n}\n\nconst isRtl = (element: Element): boolean =>\n element.ownerDocument.defaultView!.getComputedStyle(element).direction ===\n 'rtl';\n\n// Every rendered item holds its label span.\nconst labelOf = (item: Element): string =>\n item.querySelector('.kui-popup-menu__item-label')!.textContent!.trim();\n\nfunction focusItem(menu: HTMLElement, focus: Focus): void {\n if (focus === 'none') return;\n const items = levelItems(menu);\n const target = focus === 'last' ? items[items.length - 1] : items[0];\n // A menu with nothing to focus still takes focus, so its keys work.\n (target ?? menu).focus({ preventScroll: true });\n if (target) revealInMenu(target, menu);\n}\n\ninterface Typeahead {\n query: string;\n timer: number | undefined;\n}\n\n/**\n * Wire every PopupMenu in `doc`: opening from its trigger (and from the\n * open/close requests the component helpers send), placement in the top\n * layer, keyboard navigation and typeahead, hover-opened submenus with a\n * pointer safe triangle, the `kui-menu-select` choice event, focus return, and\n * cleanup when a menu closes for any reason. Idempotent per document.\n */\nexport function installPopupMenus(doc: Document = document): void {\n if (installed.has(doc)) return;\n installed.add(doc);\n const win = doc.defaultView!;\n const following = new WeakMap<HTMLElement, () => void>();\n const pendingClose = new WeakMap<HTMLElement, number>();\n const typeahead = new WeakMap<HTMLElement, Typeahead>();\n // Open root menus, for dismissal by a press outside them.\n const openRoots = new Set<HTMLElement>();\n // Menus closing without returning focus (a press outside moves it).\n const quiet = new WeakSet<HTMLElement>();\n // Each menu's toggle count, so a deferred focus return from an earlier\n // close never acts after the menu has opened or closed again.\n const toggles = new WeakMap<HTMLElement, number>();\n\n const follow = (\n menu: HTMLElement,\n anchor: PopupAnchor,\n place: () => Promise<void> | void,\n ) => {\n following.get(menu)?.();\n // A placement can cap the menu after a key has already moved focus\n // inside it (End pressed as it opens): keep that item in view.\n const reveal = () => {\n const active = doc.activeElement;\n if (active instanceof HTMLElement && active.closest(MENU) === menu)\n revealInMenu(active, menu);\n };\n const stop = followAnchor(anchor, menu, () => {\n if (!menu.isConnected || !isOpen(menu)) {\n stopFollowing(menu);\n return;\n }\n void Promise.resolve(place()).then(reveal);\n });\n following.set(menu, stop);\n };\n\n const stopFollowing = (menu: HTMLElement) => {\n following.get(menu)?.();\n following.delete(menu);\n };\n\n const placeSubmenu = (item: HTMLElement, submenu: HTMLElement) => {\n const parent = item.closest<HTMLElement>(MENU);\n if (parent && win.matchMedia(PHONE_SUBMENU_QUERY).matches) {\n submenu.style.removeProperty('max-height');\n submenu.style.removeProperty('max-width');\n const size = submenu.getBoundingClientRect();\n const placement = phoneSubmenuPosition(\n parent.getBoundingClientRect(),\n size,\n {\n width: doc.documentElement.clientWidth || win.innerWidth,\n height: doc.documentElement.clientHeight || win.innerHeight,\n },\n isRtl(submenu),\n );\n submenu.style.left = `${placement.left}px`;\n submenu.style.top = `${placement.top}px`;\n submenu.style.maxHeight = `${placement.maxHeight}px`;\n submenu.style.maxWidth = `${placement.maxWidth}px`;\n submenu.setAttribute('data-placement', placement.placement);\n return;\n }\n return positionPopup(item, submenu, {\n placement: isRtl(submenu) ? 'left-start' : 'right-start',\n crossOffset: SUBMENU_CROSS_OFFSET,\n });\n };\n\n const openRoot = (\n root: HTMLElement,\n {\n point,\n placement: pointPlacement,\n focus,\n }: PopupMenuOpenDetail & { focus: Focus },\n ) => {\n const opener = rootOpenerOf(root);\n const menu = rootMenuOf(root);\n if (!opener || !menu) return;\n if (opener instanceof HTMLButtonElement && opener.disabled) return;\n if (isOpen(menu)) closeMenu(menu, false);\n const context = root.getAttribute('data-trigger') === 'context';\n // A button-triggered menu opened at a pointer point (openPopupMenuAt)\n // opens at the point for that opening only, `bottom-start` unless the\n // call names a placement: its own placement describes where it sits\n // against its trigger. A context menu's anchor is always its point, so\n // its placement (top-start above the point, say) applies there, unless\n // the call names one for this opening.\n const pointOpened = point !== undefined && !context;\n const anchor: PopupAnchor = pointOpened\n ? pointAnchor(point.x, point.y)\n : opener;\n const placement = ((point !== undefined ? pointPlacement : undefined) ??\n (pointOpened\n ? 'bottom-start'\n : (root.getAttribute('data-placement') ??\n 'bottom-start'))) as PopupPlacement;\n try {\n menu.showPopover();\n } catch {\n return;\n }\n openRoots.add(menu);\n opener.setAttribute('aria-expanded', 'true');\n follow(menu, anchor, () => positionPopup(anchor, menu, { placement }));\n focusItem(menu, focus);\n };\n\n const openSubmenu = (\n item: HTMLElement,\n submenu: HTMLElement,\n focus: Focus,\n pointer: boolean,\n ) => {\n cancelClose(submenu);\n if (!isOpen(submenu)) {\n // One submenu per level: a sibling's (and its own submenus) close.\n for (const open of openSubmenus(item.closest(MENU)!))\n closeMenu(open, false);\n try {\n submenu.showPopover();\n } catch {\n return;\n }\n item.setAttribute('aria-expanded', 'true');\n submenu.toggleAttribute(POINTER_OPENED, pointer);\n follow(submenu, item, () => placeSubmenu(item, submenu));\n }\n focusItem(submenu, focus);\n };\n\n /**\n * Hide one menu (its open submenus follow, below), returning focus to its\n * opener if asked. A silent close leaves focus where the user is moving it.\n */\n const closeMenu = (\n menu: HTMLElement,\n restoreFocus: boolean,\n silent = false,\n ) => {\n if (!isOpen(menu)) return;\n const opener = openerOf(menu);\n const focusInside = menu.contains(doc.activeElement);\n if (silent) quiet.add(menu);\n try {\n menu.hidePopover();\n } catch {\n quiet.delete(menu);\n return;\n }\n if (restoreFocus && focusInside) opener?.focus({ preventScroll: true });\n };\n\n const closeRoot = (root: Element, restoreFocus: boolean) => {\n const menu = rootMenuOf(root);\n if (menu) closeMenu(menu, restoreFocus);\n };\n\n const cancelClose = (submenu: HTMLElement) => {\n const timer = pendingClose.get(submenu);\n if (timer !== undefined) win.clearTimeout(timer);\n pendingClose.delete(submenu);\n };\n\n /** Close a submenu the pointer left, unless it returns within the grace period. */\n const scheduleClose = (submenu: HTMLElement) => {\n if (pendingClose.has(submenu)) return;\n pendingClose.set(\n submenu,\n win.setTimeout(() => {\n pendingClose.delete(submenu);\n const opener = openerOf(submenu);\n if (submenu.matches(':hover') || opener?.matches(':hover')) return;\n closeMenu(submenu, false);\n }, SUBMENU_CLOSE_DELAY),\n );\n };\n\n // A checkbox choice reports the state it asks for; the application owns\n // the state and renders it, so the item itself is not toggled here.\n const choose = (root: HTMLElement, item: HTMLElement) => {\n const checked =\n item.getAttribute('role') === 'menuitemcheckbox'\n ? item.getAttribute('aria-checked') !== 'true'\n : undefined;\n const proceed = root.dispatchEvent(\n new CustomEvent<PopupMenuSelectDetail>(POPUP_MENU_SELECT_EVENT, {\n bubbles: true,\n cancelable: true,\n detail: {\n item,\n value: item.getAttribute('value') ?? undefined,\n checked,\n },\n }),\n );\n if (proceed) closeRoot(root, true);\n };\n\n const runTypeahead = (menu: HTMLElement, key: string): boolean => {\n const state = typeahead.get(menu) ?? { query: '', timer: undefined };\n typeahead.set(menu, state);\n win.clearTimeout(state.timer);\n state.timer = win.setTimeout(() => {\n state.query = '';\n }, TYPEAHEAD_RESET);\n state.query += key.toLowerCase();\n const match = levelItems(menu).find((item) =>\n labelOf(item).toLowerCase().startsWith(state.query.trim()),\n );\n if (!match) return false;\n match.focus({ preventScroll: true });\n revealInMenu(match, menu);\n return true;\n };\n\n // A press outside an open menu (and its trigger) closes it. Menus are\n // manual popovers so a context menu opened during a press (`contextmenu`\n // fires on press in some engines) is not light-dismissed on release.\n doc.addEventListener(\n 'pointerdown',\n (event) => {\n const path = event.composedPath();\n for (const menu of [...openRoots]) {\n if (!menu.isConnected || !isOpen(menu)) {\n openRoots.delete(menu);\n continue;\n }\n if (!path.includes(menu.parentElement!)) closeMenu(menu, false, true);\n }\n },\n true,\n );\n\n doc.addEventListener(\n 'click',\n (event) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const trigger = target.closest<HTMLElement>(TRIGGER);\n if (trigger?.parentElement?.matches(ROOT)) {\n const root = trigger.parentElement as HTMLElement;\n const menu = rootMenuOf(root);\n if (!menu) return;\n if (isOpen(menu)) closeMenu(menu, true);\n else openRoot(root, { focus: 'first' });\n return;\n }\n const item = target.closest<HTMLElement>(ITEM);\n const root = item?.closest<HTMLElement>(ROOT);\n if (!item || !root) return;\n // A disabled command does nothing, and its click never reaches the\n // application's delegated data-action.\n if (isDisabled(item)) {\n event.preventDefault();\n event.stopImmediatePropagation();\n return;\n }\n const submenu = submenuOf(item);\n if (submenu) {\n // A keyboard click (Enter or Space) moves into the submenu.\n openSubmenu(\n item,\n submenu,\n event.detail === 0 ? 'first' : 'none',\n event.detail !== 0,\n );\n return;\n }\n choose(root, item);\n },\n true,\n );\n\n doc.addEventListener(\n 'keydown',\n (event) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const trigger = target.closest<HTMLElement>(TRIGGER);\n if (trigger?.parentElement?.matches(ROOT)) {\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n event.preventDefault();\n openRoot(trigger.parentElement as HTMLElement, {\n focus: event.key === 'ArrowUp' ? 'last' : 'first',\n });\n return;\n }\n const menu = target.closest<HTMLElement>(MENU);\n const root = menu?.closest<HTMLElement>(ROOT);\n if (!menu || !root || !isOpen(menu)) return;\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n const items = levelItems(menu);\n const current =\n target.matches(ITEM) && target.closest(MENU) === menu\n ? (target as HTMLElement)\n : null;\n const index = current ? items.indexOf(current) : -1;\n const rtl = isRtl(menu);\n const forward = rtl ? 'ArrowLeft' : 'ArrowRight';\n const back = rtl ? 'ArrowRight' : 'ArrowLeft';\n const move = (next: HTMLElement | undefined) => {\n event.preventDefault();\n event.stopPropagation();\n if (!next) return;\n next.focus({ preventScroll: true });\n revealInMenu(next, menu);\n };\n const query = typeahead.get(menu)?.query ?? '';\n switch (event.key) {\n case 'ArrowDown':\n move(items[index >= 0 && index < items.length - 1 ? index + 1 : 0]);\n return;\n case 'ArrowUp':\n move(items[index > 0 ? index - 1 : items.length - 1]);\n return;\n case 'Home':\n move(items[0]);\n return;\n case 'End':\n move(items[items.length - 1]);\n return;\n case 'Escape':\n // The menu claims Escape, so an enclosing dialog stays open.\n event.preventDefault();\n event.stopPropagation();\n closeMenu(menu, true);\n return;\n case 'Tab':\n // Tab leaves the menu: close it and continue from the trigger.\n closeRoot(root, false);\n rootOpenerOf(root)?.focus({ preventScroll: true });\n return;\n case forward: {\n const submenu = current && submenuOf(current);\n if (submenu) {\n event.preventDefault();\n event.stopPropagation();\n openSubmenu(current, submenu, 'first', false);\n }\n return;\n }\n case back:\n if (menu.hasAttribute('data-submenu')) {\n event.preventDefault();\n event.stopPropagation();\n closeMenu(menu, true);\n }\n return;\n case ' ':\n // Space continues a typeahead query; otherwise it chooses.\n if (query) {\n event.preventDefault();\n runTypeahead(menu, ' ');\n }\n return;\n default:\n if (event.key.length === 1 && runTypeahead(menu, event.key)) {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n },\n true,\n );\n\n // Hovering an item with a submenu opens it; moving onto another item of\n // the same level closes it after a short grace period.\n doc.addEventListener(\n 'pointerover',\n (event) => {\n if ((event as PointerEvent).pointerType === 'touch') return;\n const target = event.target;\n if (!(target instanceof Element)) return;\n const menu = target.closest<HTMLElement>(MENU);\n if (!menu || !isOpen(menu)) return;\n // Over a submenu (or its safe triangle): keep it and its ancestors open.\n // A submenu always sits inside its parent menu.\n for (\n let level = menu;\n level.hasAttribute('data-submenu');\n level = level.parentElement!.closest<HTMLElement>(MENU)!\n )\n cancelClose(level);\n const item = target.closest<HTMLElement>(ITEM);\n if (!item || item.closest(MENU) !== menu) return;\n const submenu = submenuOf(item);\n for (const open of openSubmenus(menu))\n if (open !== submenu) scheduleClose(open);\n if (submenu && !isDisabled(item))\n openSubmenu(item, submenu, 'none', true);\n },\n true,\n );\n\n // The safe triangle: while a pointer-opened submenu shows, its ::before\n // spans from the pointer to the submenu's near edge, so a diagonal move\n // toward the submenu stays over it instead of crossing sibling items.\n doc.addEventListener(\n 'pointermove',\n (event) => {\n const { clientX, clientY } = event as PointerEvent;\n for (const submenu of doc.querySelectorAll<HTMLElement>(\n `${MENU}[${POINTER_OPENED}]`,\n )) {\n if (!isOpen(submenu)) continue;\n const box = submenu.getBoundingClientRect();\n const edge = isRtl(submenu) ? box.right : box.left;\n // The apex sits just ahead of the pointer, toward the submenu: some\n // engines hit-test a polygon's edge as inside, so an apex under the\n // pointer would take the hover from the item beneath it.\n const x = isRtl(submenu)\n ? Math.max(clientX - SAFE_TRIANGLE_LEAD, edge)\n : Math.min(clientX + SAFE_TRIANGLE_LEAD, edge);\n const y = Math.max(box.top, Math.min(clientY, box.bottom));\n submenu.style.setProperty('--_kui-popup-menu-safe-x', `${x}px`);\n submenu.style.setProperty('--_kui-popup-menu-safe-y', `${y}px`);\n submenu.style.setProperty('--_kui-popup-menu-safe-edge', `${edge}px`);\n submenu.style.setProperty('--_kui-popup-menu-safe-top', `${box.top}px`);\n submenu.style.setProperty(\n '--_kui-popup-menu-safe-bottom',\n `${box.bottom}px`,\n );\n }\n },\n { capture: true, passive: true },\n );\n\n // Every close, however it happens (a choice, Escape, a press outside,\n // another menu opening), stops placement and resets the opener's state;\n // focus inside a closing menu returns to its opener unless focus has\n // already gone somewhere else.\n doc.addEventListener(\n 'beforetoggle',\n (event) => {\n const menu = event.target;\n if (!(menu instanceof HTMLElement) || !menu.matches(MENU)) return;\n const toggle = (toggles.get(menu) ?? 0) + 1;\n toggles.set(menu, toggle);\n if ((event as ToggleEvent).newState !== 'closed') return;\n stopFollowing(menu);\n cancelClose(menu);\n openRoots.delete(menu);\n menu.removeAttribute(POINTER_OPENED);\n const opener = openerOf(menu);\n opener?.setAttribute('aria-expanded', 'false');\n // Menus are manual popovers, so a closing menu hides the submenus it\n // shows itself; their focus is this menu's to return.\n for (const nested of menu.querySelectorAll<HTMLElement>(MENU))\n if (isOpen(nested)) {\n quiet.add(nested);\n nested.hidePopover();\n }\n const silent = quiet.has(menu);\n quiet.delete(menu);\n if (silent || !menu.contains(doc.activeElement)) return;\n win.queueMicrotask(() => {\n const active = doc.activeElement;\n // Toggled again in the meantime, or focus has moved on: leave it.\n if (toggles.get(menu) !== toggle) return;\n if (!active || active === doc.body || menu.contains(active))\n opener?.focus({ preventScroll: true });\n });\n },\n true,\n );\n\n doc.addEventListener(\n POPUP_MENU_OPEN_EVENT,\n (event) => {\n const root = event.target;\n if (!(root instanceof HTMLElement) || !root.matches(ROOT)) return;\n const { point, placement } = (event as CustomEvent<PopupMenuOpenDetail>)\n .detail;\n openRoot(root, { point, placement, focus: 'first' });\n },\n true,\n );\n\n doc.addEventListener(\n POPUP_MENU_CLOSE_EVENT,\n (event) => {\n const root = event.target;\n if (root instanceof HTMLElement && root.matches(ROOT))\n closeRoot(root, true);\n },\n true,\n );\n}\n"]}
@@ -26,6 +26,7 @@ function DialogSurface({
26
26
  id,
27
27
  label,
28
28
  labelledBy,
29
+ describedBy,
29
30
  heading,
30
31
  headerActions,
31
32
  footer,
@@ -69,6 +70,7 @@ function DialogSurface({
69
70
  class: `kui-dialog-surface ${className}`.trim(),
70
71
  "aria-label": label,
71
72
  "aria-labelledby": labelledBy,
73
+ "aria-describedby": describedBy,
72
74
  tabindex: -1,
73
75
  "data-light-dismiss": lightDismiss ? "" : void 0,
74
76
  "data-component": "dialog-surface",
@@ -197,4 +199,4 @@ function PopupSurface({
197
199
 
198
200
  export { DialogSurface, PopoverDialogSurface, PopupSurface };
199
201
 
200
- //# sourceMappingURL=chunk-TAHR457X.js.map
202
+ //# sourceMappingURL=chunk-G4DRH4A5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/surfaces/surface-scaffold/surface-scaffold.tsx"],"names":[],"mappings":"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","file":"chunk-G4DRH4A5.js","sourcesContent":["import { X } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport type { CssLength } from '../../../shared/styles/css-values.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\n\nexport {\n closeDialog,\n type DialogCloseSource,\n type DialogRequestCloseDetail,\n openDialog,\n} from './internal/dialog-surface-controller.js';\n\nexport type DialogSurfaceSize = 'small' | 'medium' | 'large';\n/**\n * How the dialog is presented: `modal` (default) centered on the screen,\n * `side-sheet` against the inline end, `fullscreen`, or `bottom-sheet`\n * attached to the bottom edge (square bottom corners, safe-area and\n * virtual-keyboard clearance, optionally user-resizable).\n */\nexport type DialogSurfacePresentation =\n 'modal' | 'side-sheet' | 'fullscreen' | 'bottom-sheet';\n/**\n * How a bottom sheet appears or leaves: `slide` (default) moves the panel in\n * from, or out to, the bottom edge; `standard` keeps the dialog's\n * scale-and-fade. Both honor `prefers-reduced-motion`.\n */\nexport type DialogSurfaceSheetMotion = 'slide' | 'standard';\nexport type SurfaceInset = 'none' | 'compact' | 'comfortable';\nexport type DialogSurfaceMaxHeight = CssLength | 'viewport';\n/** A definite modal height: a length or the full viewport, minus both gutters. */\nexport type DialogSurfaceHeight = CssLength | 'viewport';\n/**\n * How the dialog body lays out its children: `flow` (default) scrolls ordinary\n * content in the body; `fill` gives one child the body's whole height and\n * lets it own scrolling (a SplitView, a Pane, an editor); `fill-last` stacks\n * the leading children at their natural height and gives the last child the\n * remaining height to own its scrolling (a heading and notices above a\n * scrolling transcript).\n */\nexport type DialogSurfaceBodyLayout = 'flow' | 'fill' | 'fill-last';\n/**\n * Where the dialog footer sits: `docked` (default) below the body, or\n * `floating` over the body's block end, inset from the panel's inline and\n * block-end edges on a transparent background (a chat composer).\n */\nexport type DialogSurfaceFooterPresentation = 'docked' | 'floating';\n/**\n * Where the dialog header sits: `docked` (default) above the body, or\n * `floating` over the body's block-start edge on the translucent chrome\n * material, so content scrolls visibly beneath the title bar.\n */\nexport type DialogSurfaceHeaderPresentation = 'docked' | 'floating';\n\n/**\n * Application `data-*` identity on the DialogSurface root, such as\n * `data-key`; the surface's own configuration attributes stay protected.\n */\nexport type DialogSurfaceRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\nconst DIALOG_SURFACE_PROTECTED = new Set([\n 'data-component',\n 'data-size',\n 'data-presentation',\n 'data-preferred-width',\n 'data-body-inset',\n 'data-footer-inset',\n 'data-viewport-gutter',\n 'data-max-height',\n 'data-height',\n 'data-body-layout',\n 'data-footer-presentation',\n 'data-header-presentation',\n 'data-min-height',\n 'data-resizable',\n 'data-enter-motion',\n 'data-exit-motion',\n 'data-light-dismiss',\n]);\n\n/**\n * The dialog's accessible name: its `label` text (also the default title), or\n * the id of an element that names it, such as a `heading` ToolbarText.\n */\nexport type DialogSurfaceName =\n { label: string; labelledBy?: never } | { label?: never; labelledBy: string };\n\nexport type DialogSurfaceProps = DialogSurfaceName & DialogSurfaceOptions;\n\nexport interface DialogSurfaceOptions {\n /** The dialog's id, for `openDialog(document.getElementById(id))`. */\n id?: string;\n /**\n * Id of the element whose text is the dialog's accessible description,\n * such as the `heading` ToolbarText's `descriptionId` or app-owned summary\n * copy in the body; rendered as `aria-describedby` on the `<dialog>`.\n */\n describedBy?: string;\n /** The body content. */\n children: KerfUiContent;\n /**\n * Header title content in place of the `label` text, such as an xl\n * `ToolbarText` with a description. The dialog keeps its `label` (or\n * `labelledBy`) name.\n */\n heading?: KerfUiContent;\n /** Controls before the close button in the header. */\n headerActions?: KerfUiContent;\n /** The footer, below the body (or floating over it); usually its buttons. */\n footer?: KerfUiContent;\n /**\n * Render no header: no title and no close button. The content then owns its\n * heading and a way to close (an element with `data-dialog-close`).\n */\n withoutHeader?: boolean;\n /** Close on a press on the backdrop; otherwise the panel pulses. */\n lightDismiss?: boolean;\n /** The close button's accessible name (default `Close`). */\n closeLabel?: string;\n size?: DialogSurfaceSize;\n presentation?: DialogSurfacePresentation;\n /** Modal preferred width. Takes precedence over size, within the viewport cap. */\n preferredWidth?: CssLength;\n bodyInset?: SurfaceInset;\n footerInset?: SurfaceInset;\n /** Modal edge clearance. Omit to retain Web Awesome's default viewport cap. */\n viewportGutter?: CssLength;\n /**\n * Modal height cap, bounded by the dynamic viewport minus both gutters. On a\n * bottom sheet, the cap (and the resize ceiling), bounded by the dynamic\n * viewport minus the top safe area and one gutter.\n */\n maxHeight?: DialogSurfaceMaxHeight;\n /**\n * Modal definite height, bounded the same way, so a filling child has a\n * height to fill. Takes precedence over `maxHeight`. On a bottom sheet, the\n * height it opens at (the visible height above the safe area or keyboard).\n */\n height?: DialogSurfaceHeight;\n /**\n * A resizable bottom sheet's resize floor (default 160px), the visible\n * height above the safe area or keyboard.\n */\n minHeight?: CssLength;\n /**\n * Let the person resize a bottom sheet by its top grabber (drag, or the\n * arrow, Page Up/Down, Home and End keys) between `minHeight` and the\n * sheet's cap. Needs the `/register` entry; each opening starts at `height`\n * (or the content height). Ignored by other presentations.\n */\n resizable?: boolean;\n /** How a bottom sheet appears (default `slide` up from the bottom edge). */\n enterMotion?: DialogSurfaceSheetMotion;\n /** How a bottom sheet is dismissed (default `slide` down off the bottom edge). */\n exitMotion?: DialogSurfaceSheetMotion;\n /**\n * Body layout (default `flow`); `fill` lets one child own the body and\n * `fill-last` stacks fixed rows above one filling last child.\n */\n bodyLayout?: DialogSurfaceBodyLayout;\n /**\n * Header placement (default `docked`); `floating` lays the dialog's header\n * (its title and close control) over the body's block-start edge on the\n * translucent chrome material (`--kui-chrome-material-raised`, opaque under\n * `prefers-reduced-transparency`, increased contrast, forced colors, or\n * without `backdrop-filter`). The `/register` entry measures the header;\n * the body reserves that height before its own inset, so its first content\n * rests below the title bar. A `fill`/`fill-last` child that is the body's\n * only child and opts into block-start `scrollClearance` (a `List` or\n * `Pane`) takes the clearance inside its own scroll area instead, published\n * as `--kui-scroll-clearance-block-start`, so its content scrolls visibly\n * beneath the header. Unmeasured (without the register), the header stays\n * docked. Keep header text in the normal text color: quiet text can fall\n * below AA over the content passing beneath it.\n */\n headerPresentation?: DialogSurfaceHeaderPresentation;\n /**\n * Footer placement (default `docked`); `floating` lays the footer over the\n * body's block end. The body reserves the footer's measured height so its\n * last content is never hidden beneath it. A `fill`/`fill-last` child that\n * opts into block-end `scrollClearance` (a `List` or `Pane`) takes that\n * clearance inside its own scroll area instead, published as\n * `--kui-scroll-clearance-block-end`, so its content scrolls visibly beneath\n * the transparent footer.\n */\n footerPresentation?: DialogSurfaceFooterPresentation;\n /**\n * A floating footer's clearance from the panel's inline and block-end edges\n * (default the 16px container inset). Choose a phone value such as\n * `remify(8)` from `deviceClass()`; the scaffold adds no breakpoint.\n */\n footerOffset?: CssLength;\n /**\n * Safe `data-*` identity on the root. Give sibling dialogs distinct\n * `data-key`s so a re-render morphs each surface into itself instead of\n * reusing one dialog's element for another (structurally identical roots\n * are otherwise matched by position).\n */\n rootAttributes?: DialogSurfaceRootAttributes;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A modal dialog: a native `<dialog>` with Kerf's header, body, and footer\n * chrome, sized and presented by its props. Render it closed, then open it\n * with `openDialog()` and close it with `closeDialog()`, the close button, an\n * element with `data-dialog-close`, Escape, or (with `lightDismiss`) a press\n * on the backdrop. Import `@kerfjs/ui/surface-scaffold/register` for the\n * floating header and footer measurement, the bottom sheet's keyboard\n * clearance and grabber, and re-render resilience while open.\n */\nexport function DialogSurface({\n id,\n label,\n labelledBy,\n describedBy,\n heading,\n headerActions,\n footer,\n withoutHeader = false,\n lightDismiss = false,\n closeLabel = 'Close',\n children,\n size = 'medium',\n presentation = 'modal',\n preferredWidth,\n bodyInset = 'compact',\n footerInset = 'comfortable',\n viewportGutter,\n maxHeight,\n height,\n minHeight,\n resizable = false,\n enterMotion = 'slide',\n exitMotion = 'slide',\n bodyLayout = 'flow',\n headerPresentation = 'docked',\n footerPresentation = 'docked',\n footerOffset,\n rootAttributes = {},\n className = '',\n slot,\n}: DialogSurfaceProps) {\n const style = [\n preferredWidth === undefined\n ? ''\n : `--_kui-dialog-surface-preferred-width:${preferredWidth}`,\n viewportGutter === undefined\n ? ''\n : `--_kui-dialog-surface-gutter:${viewportGutter}`,\n maxHeight === undefined || maxHeight === 'viewport'\n ? ''\n : `--_kui-dialog-surface-max-height:${maxHeight}`,\n height === undefined || height === 'viewport'\n ? ''\n : `--_kui-dialog-surface-height:${height}`,\n footerOffset === undefined\n ? ''\n : `--_kui-dialog-surface-footer-offset:${footerOffset}`,\n minHeight === undefined\n ? ''\n : `--_kui-dialog-surface-min-height:${minHeight}`,\n ]\n .filter(Boolean)\n .join(';');\n return (\n <dialog\n {...filterDataAttributes(rootAttributes, DIALOG_SURFACE_PROTECTED)}\n id={id}\n class={`kui-dialog-surface ${className}`.trim()}\n aria-label={label}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n tabindex={-1}\n data-light-dismiss={lightDismiss ? '' : undefined}\n data-component=\"dialog-surface\"\n data-size={size}\n data-presentation={presentation}\n data-preferred-width={preferredWidth === undefined ? undefined : ''}\n data-body-inset={bodyInset}\n data-footer-inset={footerInset}\n data-viewport-gutter={viewportGutter === undefined ? undefined : ''}\n data-max-height={maxHeight === undefined ? undefined : ''}\n data-height={height === undefined ? undefined : ''}\n data-body-layout={bodyLayout === 'flow' ? undefined : bodyLayout}\n data-header-presentation={\n headerPresentation === 'floating' ? 'floating' : undefined\n }\n data-footer-presentation={\n footerPresentation === 'floating' ? 'floating' : undefined\n }\n data-min-height={minHeight === undefined ? undefined : ''}\n data-resizable={resizable ? '' : undefined}\n data-enter-motion={enterMotion === 'slide' ? undefined : enterMotion}\n data-exit-motion={exitMotion === 'slide' ? undefined : exitMotion}\n style={style || undefined}\n slot={slot}\n >\n {withoutHeader ? null : (\n <header class=\"kui-dialog-surface__header\">\n {heading === undefined ? (\n <h2 class=\"kui-dialog-surface__title\">{label}</h2>\n ) : (\n <div class=\"kui-dialog-surface__title\">{heading}</div>\n )}\n <div class=\"kui-dialog-surface__header-actions\">\n {headerActions}\n <button\n type=\"button\"\n class=\"kui-dialog-surface__close\"\n aria-label={closeLabel}\n data-dialog-close=\"\"\n >\n <LucideIcon icon={X} name=\"x\" size=\"l\" />\n </button>\n </div>\n </header>\n )}\n {presentation === 'bottom-sheet' && resizable ? (\n <div\n class=\"kui-dialog-surface__sheet-handle\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n aria-label=\"Resize sheet\"\n tabindex={0}\n />\n ) : null}\n <div class=\"kui-dialog-surface__body\">{children}</div>\n {footer === undefined ? null : (\n <footer class=\"kui-dialog-surface__footer\">{footer}</footer>\n )}\n {/* Where kerfjs/overlay hosts a popover or tooltip opened inside the\n modal dialog, so it stays interactive above the inert page. */}\n <div data-kerf-overlay-host data-morph-skip style=\"display:contents\" />\n </dialog>\n );\n}\n\n/** Where a PopoverDialogSurface appears: the top layer, or in flow. */\nexport type PopoverDialogSurfacePresentation = 'overlay' | 'embedded';\n\n/** Application `data-*` metadata on the surface root. */\nexport type PopoverDialogSurfaceDataAttributes = Readonly<\n Record<`data-${string}`, string>\n>;\n\ntype PopoverDialogSurfaceName =\n { label: string; labelledBy?: never } | { label?: never; labelledBy: string };\n\nexport type PopoverDialogSurfaceProps = PopoverDialogSurfaceName & {\n /** The root id: what an opening control's `popovertarget` names. */\n id?: string;\n /**\n * Id of the element whose text is the dialog's accessible description,\n * such as a title `ToolbarText`'s `descriptionId`; rendered as\n * `aria-describedby` on the `role=\"dialog\"` root.\n */\n describedBy?: string;\n children: KerfUiContent;\n /**\n * `overlay` (default) is a native `popover=\"auto\"` in the top layer:\n * non-modal, light dismiss (Escape or a press outside), nothing inert.\n * `embedded` renders the same surface in flow for a catalog or inline use.\n */\n presentation?: PopoverDialogSurfacePresentation;\n /** Preferred width preset: 400px, 560px (default), or 800px. */\n size?: DialogSurfaceSize;\n /** Preferred width; takes precedence over `size`, within the viewport cap. */\n preferredWidth?: CssLength;\n /** Definite height, bounded by the dynamic viewport minus both gutters. */\n height?: DialogSurfaceHeight;\n /** Height cap, bounded the same way, for a surface that sizes to content. */\n maxHeight?: DialogSurfaceMaxHeight;\n /** Edge clearance on each side of the viewport (default 16px). */\n viewportGutter?: CssLength;\n /**\n * Body layout (default `flow`); `fill` lets one child own the surface and\n * `fill-last` stacks fixed rows above one filling last child.\n */\n bodyLayout?: DialogSurfaceBodyLayout;\n rootAttributes?: PopoverDialogSurfaceDataAttributes;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n};\n\nconst POPOVER_DIALOG_PROTECTED = new Set([\n 'data-component',\n 'data-presentation',\n 'data-size',\n 'data-height',\n 'data-max-height',\n 'data-body-layout',\n]);\n\n/**\n * A non-modal dialog surface on the native Popover API: Kerf's dialog chrome,\n * viewport-bounded size, and single-child fill without application CSS.\n * Open it with a `popovertarget` control or `showPopover()`; it light\n * dismisses and leaves the page interactive. Use `DialogSurface` when the\n * task must block the page.\n */\nexport function PopoverDialogSurface({\n id,\n children,\n label,\n labelledBy,\n describedBy,\n presentation = 'overlay',\n size = 'medium',\n preferredWidth,\n height,\n maxHeight,\n viewportGutter,\n bodyLayout = 'flow',\n rootAttributes = {},\n className = '',\n slot,\n}: PopoverDialogSurfaceProps) {\n const style = [\n preferredWidth === undefined\n ? ''\n : `--_kui-popover-dialog-surface-preferred-width:${preferredWidth}`,\n viewportGutter === undefined\n ? ''\n : `--_kui-popover-dialog-surface-gutter:${viewportGutter}`,\n height === undefined || height === 'viewport'\n ? ''\n : `--_kui-popover-dialog-surface-height:${height}`,\n maxHeight === undefined || maxHeight === 'viewport'\n ? ''\n : `--_kui-popover-dialog-surface-max-height:${maxHeight}`,\n ]\n .filter(Boolean)\n .join(';');\n return (\n <section\n {...filterDataAttributes(rootAttributes, POPOVER_DIALOG_PROTECTED)}\n id={id}\n class={`kui-popover-dialog-surface ${className}`.trim()}\n data-component=\"popover-dialog-surface\"\n data-presentation={presentation}\n data-size={size}\n data-height={height === undefined ? undefined : ''}\n data-max-height={maxHeight === undefined ? undefined : ''}\n data-body-layout={bodyLayout === 'flow' ? undefined : bodyLayout}\n popover={presentation === 'overlay' ? 'auto' : undefined}\n role=\"dialog\"\n aria-label={label}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n style={style || undefined}\n slot={slot}\n >\n {children}\n </section>\n );\n}\n\nexport type PopupSurfaceInset = 'standard' | 'compact' | 'list-zero';\n\nexport interface PopupSurfaceProps {\n children: KerfUiContent;\n inset?: PopupSurfaceInset;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** Configure recurring Web Awesome dropdown-menu geometry without consumer ::part() CSS. */\nexport function PopupSurface({\n children,\n inset = 'standard',\n className = '',\n slot,\n}: PopupSurfaceProps) {\n return (\n <span\n class={`kui-popup-surface ${className}`.trim()}\n data-component=\"popup-surface\"\n data-inset={inset}\n slot={slot}\n >\n {children}\n </span>\n );\n}\n"]}
@@ -32,8 +32,13 @@ async function positionPopup(anchor, popup, {
32
32
  return vertical ? { x: ox + cross, y: oy + sign * gap } : { x: ox + sign * gap, y: oy + cross };
33
33
  }
34
34
  },
35
+ // When neither side fits, best fit takes the side with more room and
36
+ // the size cap below scrolls the popup inside it.
35
37
  flip({ fallbackStrategy: "bestFit", padding, boundary }),
36
- shift({ padding, crossAxis: true, boundary }),
38
+ // Shift only along the anchor's edge, never across the anchor: a
39
+ // popup shifted over its trigger would hide it, and a second press
40
+ // meant to close the popup would land on a row instead.
41
+ shift({ padding, boundary }),
37
42
  size({
38
43
  padding,
39
44
  boundary,
@@ -82,4 +87,4 @@ function phoneSubmenuPosition(parent, submenu, viewport, rtl) {
82
87
 
83
88
  export { PHONE_SUBMENU_QUERY, followAnchor, phoneSubmenuPosition, pointAnchor, positionPopup };
84
89
 
85
- //# sourceMappingURL=chunk-PE2KPZDW.js.map
90
+ //# sourceMappingURL=chunk-HDXUHLTQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/popup/position-popup.ts"],"names":[],"mappings":"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","file":"chunk-HDXUHLTQ.js","sourcesContent":["import {\n autoUpdate,\n computePosition,\n flip,\n type Placement,\n shift,\n size,\n type VirtualElement,\n} from '@floating-ui/dom';\n\n/**\n * Placement for Kerf-owned popups (a PopupMenu's menu and submenus, a\n * Select's listbox): a top-layer element positioned `fixed` against an\n * anchor, flipped to the other side when its preferred side is short (to\n * the side with more room when neither fits), shifted along the anchor's\n * edge to stay clear of the viewport edge, and capped to the block size its\n * side has room for, so a tall popup scrolls instead of covering its anchor.\n * No gap, best-fit flip, 10px shift and size padding.\n */\n\n/** Where a popup opens: below or above its anchor, at the start, center, or end. */\nexport type PopupPlacement =\n 'bottom-start' | 'bottom' | 'bottom-end' | 'top-start' | 'top' | 'top-end';\n\n/**\n * The custom property a placed popup's CSS reads to cap its width at the room\n * its side has; the popup also keeps any width limit of its own.\n */\nexport const POPUP_AVAILABLE_WIDTH = '--_kui-popup-available-width';\n\n/** A popup stays this far from the viewport edge when shifted or capped. */\nexport const POPUP_VIEWPORT_PADDING = 10;\n\n/** An element, or a viewport rectangle such as a context menu's pointer point. */\nexport type PopupAnchor = Element | VirtualElement;\n\n/** A zero-size anchor at a viewport point. */\nexport function pointAnchor(x: number, y: number): VirtualElement {\n return { getBoundingClientRect: () => new DOMRect(x, y, 0, 0) };\n}\n\nexport interface PositionPopupOptions {\n placement: Placement;\n /** Main-axis distance from the anchor. */\n gap?: number;\n /** Cross-axis offset (a submenu lifts so its first row meets its item). */\n crossOffset?: number;\n /** Viewport padding the flip, shift, and height cap keep. */\n padding?: number;\n}\n\n/**\n * Position `popup` against `anchor` once. Records the placement used as\n * `data-placement`, so the popup's motion grows from its anchor side.\n */\nexport async function positionPopup(\n anchor: PopupAnchor,\n popup: HTMLElement,\n {\n placement,\n gap = 0,\n crossOffset = 0,\n padding = POPUP_VIEWPORT_PADDING,\n }: PositionPopupOptions,\n): Promise<void> {\n // The popup is in the top layer, which no ancestor clips: only the\n // viewport bounds it, not the scroll containers it is rendered inside.\n const boundary = popup.ownerDocument.documentElement;\n // Measure the natural size: a cap from an earlier, shorter side would\n // otherwise steer the flip.\n popup.style.removeProperty('max-height');\n popup.style.removeProperty(POPUP_AVAILABLE_WIDTH);\n const {\n x,\n y,\n placement: used,\n } = await computePosition(anchor, popup, {\n strategy: 'fixed',\n placement,\n middleware: [\n {\n name: 'offset',\n fn: ({ x: ox, y: oy, placement: current }) => {\n const vertical =\n current.startsWith('top') || current.startsWith('bottom');\n const sign =\n current.startsWith('top') || current.startsWith('left') ? -1 : 1;\n // An end alignment (after a flip) shifts the other way, so the\n // popup's last row meets the anchor as its first row would.\n const cross = current.endsWith('-end') ? -crossOffset : crossOffset;\n return vertical\n ? { x: ox + cross, y: oy + sign * gap }\n : { x: ox + sign * gap, y: oy + cross };\n },\n },\n // When neither side fits, best fit takes the side with more room and\n // the size cap below scrolls the popup inside it.\n flip({ fallbackStrategy: 'bestFit', padding, boundary }),\n // Shift only along the anchor's edge, never across the anchor: a\n // popup shifted over its trigger would hide it, and a second press\n // meant to close the popup would land on a row instead.\n shift({ padding, boundary }),\n size({\n padding,\n boundary,\n apply({ availableHeight, availableWidth }) {\n popup.style.maxHeight = `${Math.max(0, availableHeight)}px`;\n // The popup's own CSS caps its width by this and its own limit.\n popup.style.setProperty(\n POPUP_AVAILABLE_WIDTH,\n `${Math.max(0, availableWidth)}px`,\n );\n },\n }),\n ],\n });\n popup.style.left = `${x}px`;\n popup.style.top = `${y}px`;\n popup.setAttribute('data-placement', used);\n}\n\n/**\n * Keep a shown popup positioned while its anchor or any scroll ancestor\n * moves, the viewport resizes, or either element changes size. Returns the\n * function that stops following.\n */\nexport function followAnchor(\n anchor: PopupAnchor,\n popup: HTMLElement,\n place: () => void,\n): () => void {\n return autoUpdate(anchor, popup, place);\n}\n\n/** Phone-width viewports place a submenu above or below its parent menu. */\nexport const PHONE_SUBMENU_QUERY = '(max-width: 480px)';\n\nconst PHONE_INSET = 8;\nconst PHONE_GAP = 4;\n\nexport interface Box {\n readonly left: number;\n readonly top: number;\n readonly right: number;\n readonly bottom: number;\n}\n\n/**\n * Place a phone-width submenu beside its parent menu in the block axis, so\n * its rows never cover the parent's: below the parent menu when it fits (or\n * when below has more room), otherwise above.\n */\nexport function phoneSubmenuPosition(\n parent: Box,\n submenu: { width: number; height: number },\n viewport: { width: number; height: number },\n rtl: boolean,\n) {\n const width = Math.min(submenu.width, viewport.width - 2 * PHONE_INSET);\n const height = submenu.height;\n const below = Math.max(\n 0,\n viewport.height - parent.bottom - PHONE_GAP - PHONE_INSET,\n );\n const above = Math.max(0, parent.top - PHONE_GAP - PHONE_INSET);\n const useBelow = height <= below || (height > above && below >= above);\n const availableHeight = useBelow ? below : above;\n const left = rtl ? parent.right - width : parent.left;\n return {\n left: Math.max(\n PHONE_INSET,\n Math.min(left, viewport.width - PHONE_INSET - width),\n ),\n top: useBelow\n ? parent.bottom + PHONE_GAP\n : parent.top - PHONE_GAP - Math.min(height, availableHeight),\n maxHeight: availableHeight,\n maxWidth: viewport.width - 2 * PHONE_INSET,\n placement: useBelow ? ('bottom-start' as const) : ('top-start' as const),\n };\n}\n"]}
@@ -0,0 +1,73 @@
1
+ import { Checkbox } from './chunk-C26Q6P4Q.js';
2
+ import { filterDataAttributes } from './chunk-KH4KEMSP.js';
3
+ import { jsxs, jsx } from 'kerfjs/jsx-runtime';
4
+
5
+ var CHECKBOX_GROUP_PROTECTED = /* @__PURE__ */ new Set([
6
+ "data-component",
7
+ "data-size",
8
+ "data-orientation",
9
+ "data-invalid"
10
+ ]);
11
+ function CheckboxGroup({
12
+ label,
13
+ ariaLabel,
14
+ labelledBy,
15
+ name,
16
+ choices,
17
+ value = [],
18
+ hint,
19
+ error,
20
+ size = "default",
21
+ orientation = "vertical",
22
+ disabled = false,
23
+ action,
24
+ form,
25
+ id,
26
+ className = "",
27
+ rootAttributes = {},
28
+ slot
29
+ }) {
30
+ const description = [hint, error].filter(Boolean).join(" ") || void 0;
31
+ const checked = new Set(value);
32
+ return /* @__PURE__ */ jsxs(
33
+ "fieldset",
34
+ {
35
+ ...filterDataAttributes(rootAttributes, CHECKBOX_GROUP_PROTECTED),
36
+ class: `kui-checkbox-group ${className}`.trim(),
37
+ "data-component": "checkbox-group",
38
+ "data-size": size,
39
+ "data-orientation": orientation,
40
+ "data-invalid": error ? "" : void 0,
41
+ id,
42
+ "aria-label": ariaLabel,
43
+ "aria-labelledby": labelledBy,
44
+ "aria-description": description,
45
+ "aria-invalid": error ? "true" : void 0,
46
+ disabled,
47
+ slot,
48
+ children: [
49
+ label === void 0 ? null : /* @__PURE__ */ jsx("legend", { class: "kui-checkbox-group__label", children: label }),
50
+ /* @__PURE__ */ jsx("div", { class: "kui-checkbox-group__choices", children: choices.map((choice) => /* @__PURE__ */ jsx(
51
+ Checkbox,
52
+ {
53
+ label: choice.label,
54
+ name,
55
+ value: choice.value,
56
+ checked: checked.has(choice.value),
57
+ hint: choice.hint,
58
+ size,
59
+ disabled: choice.disabled,
60
+ action,
61
+ form
62
+ }
63
+ )) }),
64
+ hint === void 0 ? null : /* @__PURE__ */ jsx("span", { class: "kui-checkbox-group__hint", "aria-hidden": "true", children: hint }),
65
+ error === void 0 ? null : /* @__PURE__ */ jsx("span", { class: "kui-checkbox-group__error", "aria-hidden": "true", children: error })
66
+ ]
67
+ }
68
+ );
69
+ }
70
+
71
+ export { CheckboxGroup };
72
+
73
+ //# sourceMappingURL=chunk-HU5IHXCI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/forms/checkbox-group/checkbox-group.tsx"],"names":[],"mappings":";;;;AASA,IAAM,wBAAA,uBAA+B,GAAA,CAAI;AAAA,EACvC,gBAAA;AAAA,EACA,WAAA;AAAA,EACA,kBAAA;AAAA,EACA;AACF,CAAC,CAAA;AA8DM,SAAS,aAAA,CAAoC;AAAA,EAClD,KAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAQ,EAAC;AAAA,EACT,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA,GAAO,SAAA;AAAA,EACP,WAAA,GAAc,UAAA;AAAA,EACd,QAAA,GAAW,KAAA;AAAA,EACX,MAAA;AAAA,EACA,IAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,iBAAiB,EAAC;AAAA,EAClB;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,EAAM,KAAK,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,IAAK,MAAA;AAC/D,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAY,KAAK,CAAA;AACrC,EAAA,uBACE,IAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACE,GAAG,oBAAA,CAAqB,cAAA,EAAgB,wBAAwB,CAAA;AAAA,MACjE,KAAA,EAAO,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC9C,gBAAA,EAAe,gBAAA;AAAA,MACf,WAAA,EAAW,IAAA;AAAA,MACX,kBAAA,EAAkB,WAAA;AAAA,MAClB,cAAA,EAAc,QAAQ,EAAA,GAAK,MAAA;AAAA,MAC3B,EAAA;AAAA,MACA,YAAA,EAAY,SAAA;AAAA,MACZ,iBAAA,EAAiB,UAAA;AAAA,MACjB,kBAAA,EAAkB,WAAA;AAAA,MAClB,cAAA,EAAc,QAAQ,MAAA,GAAS,MAAA;AAAA,MAC/B,QAAA;AAAA,MACA,IAAA;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,KAAA,KAAU,SAAY,IAAA,mBACrB,GAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,6BAA6B,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,4BAElD,KAAA,EAAA,EAAI,KAAA,EAAM,+BACR,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,qBACZ,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,IAAA;AAAA,YACA,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA;AAAA,YACjC,MAAM,MAAA,CAAO,IAAA;AAAA,YACb,IAAA;AAAA,YACA,UAAU,MAAA,CAAO,QAAA;AAAA,YACjB,MAAA;AAAA,YACA;AAAA;AAAA,SAEH,CAAA,EACH,CAAA;AAAA,QACC,IAAA,KAAS,SAAY,IAAA,mBACpB,GAAA,CAAC,UAAK,KAAA,EAAM,0BAAA,EAA2B,aAAA,EAAY,MAAA,EAChD,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,QAED,KAAA,KAAU,SAAY,IAAA,mBACrB,GAAA,CAAC,UAAK,KAAA,EAAM,2BAAA,EAA4B,aAAA,EAAY,MAAA,EACjD,QAAA,EAAA,KAAA,EACH;AAAA;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-HU5IHXCI.js","sourcesContent":["import { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport { Checkbox } from '../checkbox/checkbox.js';\n\n/** `default` is a 20px box beside 16px text; `compact` 18px and 14px. */\nexport type CheckboxGroupSize = 'default' | 'compact';\n\n/** `vertical` stacks the choices; `horizontal` lines them up and wraps. */\nexport type CheckboxGroupOrientation = 'vertical' | 'horizontal';\n\nconst CHECKBOX_GROUP_PROTECTED = new Set([\n 'data-component',\n 'data-size',\n 'data-orientation',\n 'data-invalid',\n]);\n\n/** Application `data-*` metadata; the CheckboxGroup's own markers stay protected. */\nexport type CheckboxGroupRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\nexport interface CheckboxGroupChoice<Value extends string = string> {\n value: Value;\n /** Visible label; it is also the checkbox's accessible name. */\n label: string;\n /** Supporting text under this choice's label, also its description. */\n hint?: string;\n disabled?: boolean;\n}\n\n/**\n * A group is named by a visible `label` (its legend), by `ariaLabel`, or by\n * `labelledBy`, the id of a visible heading elsewhere that names it.\n */\nexport type CheckboxGroupName =\n | { label: string; ariaLabel?: never; labelledBy?: never }\n | { label?: never; ariaLabel: string; labelledBy?: never }\n | { label?: never; ariaLabel?: never; labelledBy: string };\n\nexport interface CheckboxGroupOptions<Value extends string = string> {\n /** Native input `name`: the form field every checked value submits under. */\n name: string;\n choices: readonly CheckboxGroupChoice<Value>[];\n /** The checked values. Omit for none. */\n value?: readonly NoInfer<Value>[];\n /** Supporting text below the choices, also the group's description. */\n hint?: string;\n /** A validation message: shown in the danger color and marking it invalid. */\n error?: string;\n size?: CheckboxGroupSize;\n orientation?: CheckboxGroupOrientation;\n /** Disable the whole group. */\n disabled?: boolean;\n /** Delegated `data-action` on every checkbox; listen for `change`. */\n action?: string;\n /** Associate the checkboxes with a form outside their ancestor chain. */\n form?: string;\n /** The fieldset's id. */\n id?: string;\n className?: string;\n /** Safe `data-*` metadata (a `data-key`). */\n rootAttributes?: CheckboxGroupRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nexport type CheckboxGroupProps<Value extends string = string> =\n CheckboxGroupName & CheckboxGroupOptions<Value>;\n\n/**\n * Any number of related options among a few visible choices: a native\n * fieldset of `Checkbox`es with the group label above and hint and error text\n * below, laid out like a `RadioGroup` so stacked checkboxes and radios share\n * one control column and one 28px pitch. Every checked value submits under\n * `name`.\n */\nexport function CheckboxGroup<Value extends string>({\n label,\n ariaLabel,\n labelledBy,\n name,\n choices,\n value = [],\n hint,\n error,\n size = 'default',\n orientation = 'vertical',\n disabled = false,\n action,\n form,\n id,\n className = '',\n rootAttributes = {},\n slot,\n}: CheckboxGroupProps<Value>) {\n const description = [hint, error].filter(Boolean).join(' ') || undefined;\n const checked = new Set<string>(value);\n return (\n <fieldset\n {...filterDataAttributes(rootAttributes, CHECKBOX_GROUP_PROTECTED)}\n class={`kui-checkbox-group ${className}`.trim()}\n data-component=\"checkbox-group\"\n data-size={size}\n data-orientation={orientation}\n data-invalid={error ? '' : undefined}\n id={id}\n aria-label={ariaLabel}\n aria-labelledby={labelledBy}\n aria-description={description}\n aria-invalid={error ? 'true' : undefined}\n disabled={disabled}\n slot={slot}\n >\n {label === undefined ? null : (\n <legend class=\"kui-checkbox-group__label\">{label}</legend>\n )}\n <div class=\"kui-checkbox-group__choices\">\n {choices.map((choice) => (\n <Checkbox\n label={choice.label}\n name={name}\n value={choice.value}\n checked={checked.has(choice.value)}\n hint={choice.hint}\n size={size}\n disabled={choice.disabled}\n action={action}\n form={form}\n />\n ))}\n </div>\n {hint === undefined ? null : (\n <span class=\"kui-checkbox-group__hint\" aria-hidden=\"true\">\n {hint}\n </span>\n )}\n {error === undefined ? null : (\n <span class=\"kui-checkbox-group__error\" aria-hidden=\"true\">\n {error}\n </span>\n )}\n </fieldset>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { PopupMenu } from './chunk-7W3GKMN4.js';
1
+ import { PopupMenu } from './chunk-OQP3PFKQ.js';
2
2
  import { listIconTilePresentation, withWordBreaks, nativeDraggable } from './chunk-ZNROKDSZ.js';
3
3
  import { Skeleton } from './chunk-CVD5IZGB.js';
4
4
  import { LoadingSpinner } from './chunk-WVS6CUCT.js';
@@ -173,4 +173,4 @@ function ListActionRow({
173
173
 
174
174
  export { ListActionRow };
175
175
 
176
- //# sourceMappingURL=chunk-DF2YKGIX.js.map
176
+ //# sourceMappingURL=chunk-JCCN3U6X.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/collections/list-action-row/list-action-row.tsx"],"names":[],"mappings":"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","file":"chunk-DF2YKGIX.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport {\n type ListIconTile,\n listIconTilePresentation,\n} from '../../../shared/content/list-icon-tile.js';\nimport { nativeDraggable } from '../../../shared/dom/draggable.js';\nimport {\n filterControlAttributes,\n filterDataAttributes,\n} from '../../../shared/dom/extension-attributes.js';\nimport { em, remify } from '../../../shared/styles/css-values.js';\nimport { withWordBreaks } from '../../../shared/text/word-breaks.js';\nimport {\n PopupMenu,\n type PopupMenuEntry,\n type PopupMenuPlacement,\n} from '../../actions/popup-menu/popup-menu.js';\nimport { LoadingSpinner } from '../../feedback/loading-spinner/loading-spinner.js';\nimport { Skeleton } from '../../feedback/skeleton/skeleton.js';\n\nexport type {\n ListIconTile,\n ListIconTileColor,\n ListIconTileTone,\n} from '../../../shared/content/list-icon-tile.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-has-icon',\n 'data-icon-tile',\n 'data-icon-tile-tone',\n 'data-multiline',\n 'data-density',\n 'data-divider',\n 'data-busy',\n 'data-trailing-visibility',\n 'data-state',\n 'data-selected',\n 'data-pressed',\n 'data-dragging',\n 'data-drop-position',\n]);\nconst PROTECTED_TRAILING_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-kui-disabled',\n]);\n\ntype ListActionRowRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-has-icon'?: never;\n 'data-icon-tile'?: never;\n 'data-icon-tile-tone'?: never;\n 'data-multiline'?: never;\n 'data-density'?: never;\n 'data-divider'?: never;\n 'data-busy'?: never;\n 'data-trailing-visibility'?: never;\n 'data-state'?: never;\n 'data-selected'?: never;\n 'data-pressed'?: never;\n 'data-dragging'?: never;\n 'data-drop-position'?: never;\n }\n>;\n\ntype ListActionRowTrailingAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-kui-disabled'?: never;\n popoverTarget?: string;\n popoverTargetAction?: 'toggle' | 'show' | 'hide';\n 'aria-controls'?: string;\n 'aria-haspopup'?: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | 'true';\n }\n>;\n\n/** A trailing overflow `PopupMenu` rendered as the row's sibling trailing control. */\nexport interface ListActionRowTrailingMenu {\n /** Accessible name of the icon-only menu trigger, such as `Actions for report.json`. */\n label: string;\n /** Decorative trigger icon, typically a `MoreHorizontal` `LucideIcon`. */\n icon: SafeHtml;\n /** The menu's commands, headings, and dividers; items dispatch their own `data-action`s. */\n items: readonly PopupMenuEntry[];\n /** Where the menu opens relative to its trigger. Defaults to `bottom-end`. */\n placement?: PopupMenuPlacement;\n disabled?: boolean;\n}\n\ninterface ListActionRowTrailingButtonProps {\n trailingAction: string;\n trailingActionLabel: string;\n /** Decorative dormant content for the trailing button. Must not contain interactive descendants. */\n trailingActionIcon: SafeHtml;\n trailingActionDisabled?: boolean;\n trailingActionTitle?: string;\n trailingActionAttributes?: ListActionRowTrailingAttributes;\n trailingMenu?: never;\n}\n\ninterface ListActionRowTrailingMenuProps {\n /** A trailing overflow menu in place of the trailing button. Import `@kerfjs/ui/popup-menu/register` once. */\n trailingMenu: ListActionRowTrailingMenu;\n trailingAction?: never;\n trailingActionLabel?: never;\n trailingActionIcon?: never;\n trailingActionDisabled?: never;\n trailingActionTitle?: never;\n trailingActionAttributes?: never;\n}\n\ninterface ListActionRowCommonProps {\n /** Visible dormant content for the primary button. Must not contain interactive descendants. */\n label: string | SafeHtml;\n description?: string | SafeHtml;\n status?: string | SafeHtml;\n busy?: boolean;\n /** Row height: `standard` is 44px; `compact` is 36px (42px with `iconTile`), the height of a compact `ListItem`. */\n density?: 'standard' | 'compact';\n divider?: 'none' | 'before' | 'after' | 'both';\n /** Decorative dormant content for the primary button. Must not contain interactive descendants. */\n icon?: SafeHtml;\n /** Present `icon` in a filled 32px rounded tile with an 18px glyph: a quiet tone preset, or `{ color, foreground? }` for an application color. */\n iconTile?: ListIconTile;\n action: string;\n itemId?: string;\n selected?: boolean;\n pressed?: boolean;\n accessibleLabel?: string;\n title?: string;\n multiline?: boolean;\n state?: string;\n disabled?: boolean;\n tabIndex?: number;\n /** Render as an unanimated loading skeleton, disabling both actions: label, description, icon, and status text become skeletons; the `busy` indicator stays live. */\n placeholder?: boolean;\n /** Native HTML drag source (`draggable=\"true\"` on the row root); a placeholder is never draggable. Pair with `wireListReorder` for pointer and keyboard reordering. */\n draggable?: boolean;\n /** Dim this row as one of the rows being dragged. */\n dragging?: boolean;\n /** Draw the insertion line at this row's leading (`before`) or trailing (`after`) block edge. */\n dropPosition?: 'before' | 'after';\n trailingActionVisibility?: 'always' | 'interaction';\n className?: string;\n rootAttributes?: ListActionRowRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** Exactly one trailing control: a native button (`trailingAction*`) or an overflow menu (`trailingMenu`). */\nexport type ListActionRowProps = ListActionRowCommonProps &\n (ListActionRowTrailingButtonProps | ListActionRowTrailingMenuProps);\n\nexport function ListActionRow({\n label,\n description,\n status,\n busy = false,\n density = 'standard',\n divider = 'none',\n icon,\n iconTile,\n action,\n itemId,\n selected = false,\n pressed,\n accessibleLabel,\n title,\n multiline = false,\n state,\n disabled = false,\n tabIndex,\n placeholder = false,\n draggable,\n dragging = false,\n dropPosition,\n trailingAction,\n trailingActionLabel,\n trailingActionIcon,\n trailingActionDisabled = false,\n trailingActionTitle,\n trailingActionVisibility = 'always',\n trailingMenu,\n className = '',\n rootAttributes = {},\n trailingActionAttributes = {},\n slot,\n}: ListActionRowProps) {\n const extensionRootAttributes = filterDataAttributes(\n rootAttributes,\n PROTECTED_ROOT_DATA_ATTRIBUTES,\n );\n const extensionTrailingAttributes = filterControlAttributes(\n trailingActionAttributes,\n PROTECTED_TRAILING_DATA_ATTRIBUTES,\n );\n const tile = icon\n ? listIconTilePresentation(iconTile, 'list-action-row')\n : null;\n const iconSize = tile?.tile ? 32 : 18;\n\n return (\n <div\n {...extensionRootAttributes}\n class={`kui-list-action-row ${className}`.trim()}\n data-component=\"list-action-row\"\n data-item-id={itemId}\n data-has-icon={String(Boolean(icon))}\n data-icon-tile={tile?.tile}\n data-icon-tile-tone={tile?.tone}\n data-multiline={multiline ? 'true' : undefined}\n data-density={density}\n data-divider={divider}\n data-busy={busy ? 'true' : undefined}\n data-trailing-visibility={trailingActionVisibility}\n data-state={state}\n data-selected={String(selected)}\n data-pressed={pressed === undefined ? undefined : String(pressed)}\n data-placeholder={placeholder ? 'true' : undefined}\n draggable={nativeDraggable(draggable, placeholder)}\n data-dragging={dragging ? 'true' : undefined}\n data-drop-position={dropPosition}\n aria-busy={placeholder || busy ? 'true' : undefined}\n slot={slot}\n >\n <button\n type=\"button\"\n class=\"kui-list-action-row__primary\"\n title={placeholder ? undefined : title}\n disabled={disabled || placeholder}\n tabindex={placeholder ? -1 : tabIndex}\n data-kui-disabled={disabled ? 'true' : undefined}\n data-action={placeholder ? undefined : action}\n data-item-id={itemId}\n aria-label={accessibleLabel}\n aria-current={selected ? 'page' : undefined}\n aria-pressed={pressed === undefined ? undefined : String(pressed)}\n >\n {icon && (\n <span\n class=\"kui-list-action-row__icon\"\n style={placeholder ? undefined : tile?.style}\n >\n {placeholder ? (\n <Skeleton\n block\n width={remify(iconSize)}\n height={remify(iconSize)}\n />\n ) : (\n icon\n )}\n </span>\n )}\n <span class=\"kui-list-action-row__label\">\n <span class=\"kui-list-action-row__primary-label\">\n {placeholder ? (\n <Skeleton width={em(9)} />\n ) : multiline ? (\n withWordBreaks(label)\n ) : (\n label\n )}\n </span>\n {description && (\n <span class=\"kui-list-action-row__description\">\n {placeholder ? <Skeleton width={em(11)} /> : description}\n </span>\n )}\n {(busy || status) && (\n <span class=\"kui-list-action-row__status\">\n {/* The busy spinner is component-owned chrome drawn from a\n known prop, so a placeholder keeps it live; only the status\n text is a value and becomes a skeleton. */}\n {busy && <LoadingSpinner />}\n {status && (placeholder ? <Skeleton width={em(6)} /> : status)}\n </span>\n )}\n </span>\n </button>\n {trailingMenu ? (\n <PopupMenu\n label={trailingMenu.label}\n icon={trailingMenu.icon}\n items={trailingMenu.items}\n placement={trailingMenu.placement ?? 'bottom-end'}\n caret={false}\n disabled={Boolean(trailingMenu.disabled) || placeholder}\n />\n ) : (\n <button\n {...extensionTrailingAttributes}\n type=\"button\"\n class=\"kui-list-action-row__trailing-action\"\n data-action={placeholder ? undefined : trailingAction}\n data-item-id={itemId}\n aria-label={trailingActionLabel}\n title={trailingActionTitle ?? trailingActionLabel}\n disabled={trailingActionDisabled || placeholder || undefined}\n data-kui-disabled={trailingActionDisabled ? 'true' : undefined}\n >\n {trailingActionIcon}\n </button>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/collections/list-action-row/list-action-row.tsx"],"names":[],"mappings":";;;;;;;;AA2BA,IAAM,8BAAA,uBAAqC,GAAA,CAAI;AAAA,EAC7C,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,qBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,0BAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAC,CAAA;AACD,IAAM,kCAAA,uBAAyC,GAAA,CAAI;AAAA,EACjD,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAC,CAAA;AAiHM,SAAS,aAAA,CAAc;AAAA,EAC5B,KAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,OAAA,GAAU,UAAA;AAAA,EACV,OAAA,GAAU,MAAA;AAAA,EACV,IAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,OAAA;AAAA,EACA,eAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EACZ,KAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,QAAA;AAAA,EACA,WAAA,GAAc,KAAA;AAAA,EACd,SAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,YAAA;AAAA,EACA,cAAA;AAAA,EACA,mBAAA;AAAA,EACA,kBAAA;AAAA,EACA,sBAAA,GAAyB,KAAA;AAAA,EACzB,mBAAA;AAAA,EACA,wBAAA,GAA2B,QAAA;AAAA,EAC3B,YAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,iBAAiB,EAAC;AAAA,EAClB,2BAA2B,EAAC;AAAA,EAC5B;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,uBAAA,GAA0B,oBAAA;AAAA,IAC9B,cAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,2BAAA,GAA8B,uBAAA;AAAA,IAClC,wBAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,IAAA,GAAO,IAAA,GACT,wBAAA,CAAyB,QAAA,EAAU,iBAAiB,CAAA,GACpD,IAAA;AACJ,EAAA,MAAM,QAAA,GAAW,IAAA,EAAM,IAAA,GAAO,EAAA,GAAK,EAAA;AAEnC,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,uBAAA;AAAA,MACJ,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC/C,gBAAA,EAAe,iBAAA;AAAA,MACf,cAAA,EAAc,MAAA;AAAA,MACd,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA;AAAA,MACnC,kBAAgB,IAAA,EAAM,IAAA;AAAA,MACtB,uBAAqB,IAAA,EAAM,IAAA;AAAA,MAC3B,gBAAA,EAAgB,YAAY,MAAA,GAAS,MAAA;AAAA,MACrC,cAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAc,OAAA;AAAA,MACd,WAAA,EAAW,OAAO,MAAA,GAAS,MAAA;AAAA,MAC3B,0BAAA,EAA0B,wBAAA;AAAA,MAC1B,YAAA,EAAY,KAAA;AAAA,MACZ,eAAA,EAAe,OAAO,QAAQ,CAAA;AAAA,MAC9B,cAAA,EAAc,OAAA,KAAY,MAAA,GAAY,MAAA,GAAY,OAAO,OAAO,CAAA;AAAA,MAChE,kBAAA,EAAkB,cAAc,MAAA,GAAS,MAAA;AAAA,MACzC,SAAA,EAAW,eAAA,CAAgB,SAAA,EAAW,WAAW,CAAA;AAAA,MACjD,eAAA,EAAe,WAAW,MAAA,GAAS,MAAA;AAAA,MACnC,oBAAA,EAAoB,YAAA;AAAA,MACpB,WAAA,EAAW,WAAA,IAAe,IAAA,GAAO,MAAA,GAAS,MAAA;AAAA,MAC1C,IAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,IAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,8BAAA;AAAA,YACN,KAAA,EAAO,cAAc,MAAA,GAAY,KAAA;AAAA,YACjC,UAAU,QAAA,IAAY,WAAA;AAAA,YACtB,QAAA,EAAU,cAAc,EAAA,GAAK,QAAA;AAAA,YAC7B,mBAAA,EAAmB,WAAW,MAAA,GAAS,MAAA;AAAA,YACvC,aAAA,EAAa,cAAc,MAAA,GAAY,MAAA;AAAA,YACvC,cAAA,EAAc,MAAA;AAAA,YACd,YAAA,EAAY,eAAA;AAAA,YACZ,cAAA,EAAc,WAAW,MAAA,GAAS,MAAA;AAAA,YAClC,cAAA,EAAc,OAAA,KAAY,MAAA,GAAY,MAAA,GAAY,OAAO,OAAO,CAAA;AAAA,YAE/D,QAAA,EAAA;AAAA,cAAA,IAAA,oBACC,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,KAAA,EAAM,2BAAA;AAAA,kBACN,KAAA,EAAO,WAAA,GAAc,MAAA,GAAY,IAAA,EAAM,KAAA;AAAA,kBAEtC,QAAA,EAAA,WAAA,mBACC,GAAA;AAAA,oBAAC,QAAA;AAAA,oBAAA;AAAA,sBACC,KAAA,EAAK,IAAA;AAAA,sBACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,sBACtB,MAAA,EAAQ,OAAO,QAAQ;AAAA;AAAA,mBACzB,GAEA;AAAA;AAAA,eAEJ;AAAA,8BAEF,IAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,4BAAA,EACV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,oCAAA,EACT,QAAA,EAAA,WAAA,uBACE,QAAA,EAAA,EAAS,KAAA,EAAO,EAAA,CAAG,CAAC,GAAG,CAAA,GACtB,SAAA,GACF,cAAA,CAAe,KAAK,IAEpB,KAAA,EAEJ,CAAA;AAAA,gBACC,WAAA,oBACC,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,kCAAA,EACT,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAO,EAAA,CAAG,EAAE,CAAA,EAAG,IAAK,WAAA,EAC/C,CAAA;AAAA,gBAAA,CAEA,IAAA,IAAQ,MAAA,qBACR,IAAA,CAAC,MAAA,EAAA,EAAK,OAAM,6BAAA,EAIT,QAAA,EAAA;AAAA,kBAAA,IAAA,wBAAS,cAAA,EAAA,EAAe,CAAA;AAAA,kBACxB,MAAA,KAAW,8BAAc,GAAA,CAAC,QAAA,EAAA,EAAS,OAAO,EAAA,CAAG,CAAC,GAAG,CAAA,GAAK,MAAA;AAAA,iBAAA,EACzD;AAAA,eAAA,EAEJ;AAAA;AAAA;AAAA,SACF;AAAA,QACC,YAAA,mBACC,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,OAAO,YAAA,CAAa,KAAA;AAAA,YACpB,MAAM,YAAA,CAAa,IAAA;AAAA,YACnB,OAAO,YAAA,CAAa,KAAA;AAAA,YACpB,SAAA,EAAW,aAAa,SAAA,IAAa,YAAA;AAAA,YACrC,KAAA,EAAO,KAAA;AAAA,YACP,QAAA,EAAU,OAAA,CAAQ,YAAA,CAAa,QAAQ,CAAA,IAAK;AAAA;AAAA,SAC9C,mBAEA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACE,GAAG,2BAAA;AAAA,YACJ,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,sCAAA;AAAA,YACN,aAAA,EAAa,cAAc,MAAA,GAAY,cAAA;AAAA,YACvC,cAAA,EAAc,MAAA;AAAA,YACd,YAAA,EAAY,mBAAA;AAAA,YACZ,OAAO,mBAAA,IAAuB,mBAAA;AAAA,YAC9B,QAAA,EAAU,0BAA0B,WAAA,IAAe,MAAA;AAAA,YACnD,mBAAA,EAAmB,yBAAyB,MAAA,GAAS,MAAA;AAAA,YAEpD,QAAA,EAAA;AAAA;AAAA;AACH;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-JCCN3U6X.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport {\n type ListIconTile,\n listIconTilePresentation,\n} from '../../../shared/content/list-icon-tile.js';\nimport { nativeDraggable } from '../../../shared/dom/draggable.js';\nimport {\n filterControlAttributes,\n filterDataAttributes,\n} from '../../../shared/dom/extension-attributes.js';\nimport { em, remify } from '../../../shared/styles/css-values.js';\nimport { withWordBreaks } from '../../../shared/text/word-breaks.js';\nimport {\n PopupMenu,\n type PopupMenuEntry,\n type PopupMenuPlacement,\n} from '../../actions/popup-menu/popup-menu.js';\nimport { LoadingSpinner } from '../../feedback/loading-spinner/loading-spinner.js';\nimport { Skeleton } from '../../feedback/skeleton/skeleton.js';\n\nexport type {\n ListIconTile,\n ListIconTileColor,\n ListIconTileTone,\n} from '../../../shared/content/list-icon-tile.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-has-icon',\n 'data-icon-tile',\n 'data-icon-tile-tone',\n 'data-multiline',\n 'data-density',\n 'data-divider',\n 'data-busy',\n 'data-trailing-visibility',\n 'data-state',\n 'data-selected',\n 'data-pressed',\n 'data-dragging',\n 'data-drop-position',\n]);\nconst PROTECTED_TRAILING_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-kui-disabled',\n]);\n\ntype ListActionRowRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-has-icon'?: never;\n 'data-icon-tile'?: never;\n 'data-icon-tile-tone'?: never;\n 'data-multiline'?: never;\n 'data-density'?: never;\n 'data-divider'?: never;\n 'data-busy'?: never;\n 'data-trailing-visibility'?: never;\n 'data-state'?: never;\n 'data-selected'?: never;\n 'data-pressed'?: never;\n 'data-dragging'?: never;\n 'data-drop-position'?: never;\n }\n>;\n\ntype ListActionRowTrailingAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-kui-disabled'?: never;\n popoverTarget?: string;\n popoverTargetAction?: 'toggle' | 'show' | 'hide';\n 'aria-controls'?: string;\n 'aria-haspopup'?: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | 'true';\n }\n>;\n\n/** A trailing overflow `PopupMenu` rendered as the row's sibling trailing control. */\nexport interface ListActionRowTrailingMenu {\n /** Accessible name of the icon-only menu trigger, such as `Actions for report.json`. */\n label: string;\n /** Decorative trigger icon, typically a `MoreHorizontal` `LucideIcon`. */\n icon: SafeHtml;\n /** The menu's commands, headings, and dividers; items dispatch their own `data-action`s. */\n items: readonly PopupMenuEntry[];\n /** Where the menu opens relative to its trigger. Defaults to `bottom-end`. */\n placement?: PopupMenuPlacement;\n disabled?: boolean;\n}\n\ninterface ListActionRowTrailingButtonProps {\n trailingAction: string;\n trailingActionLabel: string;\n /** Decorative dormant content for the trailing button. Must not contain interactive descendants. */\n trailingActionIcon: SafeHtml;\n trailingActionDisabled?: boolean;\n trailingActionTitle?: string;\n trailingActionAttributes?: ListActionRowTrailingAttributes;\n trailingMenu?: never;\n}\n\ninterface ListActionRowTrailingMenuProps {\n /** A trailing overflow menu in place of the trailing button. Import `@kerfjs/ui/popup-menu/register` once. */\n trailingMenu: ListActionRowTrailingMenu;\n trailingAction?: never;\n trailingActionLabel?: never;\n trailingActionIcon?: never;\n trailingActionDisabled?: never;\n trailingActionTitle?: never;\n trailingActionAttributes?: never;\n}\n\ninterface ListActionRowCommonProps {\n /** Visible dormant content for the primary button. Must not contain interactive descendants. */\n label: string | SafeHtml;\n description?: string | SafeHtml;\n status?: string | SafeHtml;\n busy?: boolean;\n /** Row height: `standard` is 44px; `compact` is 36px (42px with `iconTile`), the height of a compact `ListItem`. */\n density?: 'standard' | 'compact';\n divider?: 'none' | 'before' | 'after' | 'both';\n /** Decorative dormant content for the primary button. Must not contain interactive descendants. */\n icon?: SafeHtml;\n /** Present `icon` in a filled 32px rounded tile with an 18px glyph: a quiet tone preset, or `{ color, foreground? }` for an application color. */\n iconTile?: ListIconTile;\n action: string;\n itemId?: string;\n selected?: boolean;\n pressed?: boolean;\n accessibleLabel?: string;\n title?: string;\n multiline?: boolean;\n state?: string;\n disabled?: boolean;\n tabIndex?: number;\n /** Render as an unanimated loading skeleton, disabling both actions: label, description, icon, and status text become skeletons; the `busy` indicator stays live. */\n placeholder?: boolean;\n /** Native HTML drag source (`draggable=\"true\"` on the row root); a placeholder is never draggable. Pair with `wireListReorder` for pointer and keyboard reordering. */\n draggable?: boolean;\n /** Dim this row as one of the rows being dragged. */\n dragging?: boolean;\n /** Draw the insertion line at this row's leading (`before`) or trailing (`after`) block edge. */\n dropPosition?: 'before' | 'after';\n trailingActionVisibility?: 'always' | 'interaction';\n className?: string;\n rootAttributes?: ListActionRowRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** Exactly one trailing control: a native button (`trailingAction*`) or an overflow menu (`trailingMenu`). */\nexport type ListActionRowProps = ListActionRowCommonProps &\n (ListActionRowTrailingButtonProps | ListActionRowTrailingMenuProps);\n\nexport function ListActionRow({\n label,\n description,\n status,\n busy = false,\n density = 'standard',\n divider = 'none',\n icon,\n iconTile,\n action,\n itemId,\n selected = false,\n pressed,\n accessibleLabel,\n title,\n multiline = false,\n state,\n disabled = false,\n tabIndex,\n placeholder = false,\n draggable,\n dragging = false,\n dropPosition,\n trailingAction,\n trailingActionLabel,\n trailingActionIcon,\n trailingActionDisabled = false,\n trailingActionTitle,\n trailingActionVisibility = 'always',\n trailingMenu,\n className = '',\n rootAttributes = {},\n trailingActionAttributes = {},\n slot,\n}: ListActionRowProps) {\n const extensionRootAttributes = filterDataAttributes(\n rootAttributes,\n PROTECTED_ROOT_DATA_ATTRIBUTES,\n );\n const extensionTrailingAttributes = filterControlAttributes(\n trailingActionAttributes,\n PROTECTED_TRAILING_DATA_ATTRIBUTES,\n );\n const tile = icon\n ? listIconTilePresentation(iconTile, 'list-action-row')\n : null;\n const iconSize = tile?.tile ? 32 : 18;\n\n return (\n <div\n {...extensionRootAttributes}\n class={`kui-list-action-row ${className}`.trim()}\n data-component=\"list-action-row\"\n data-item-id={itemId}\n data-has-icon={String(Boolean(icon))}\n data-icon-tile={tile?.tile}\n data-icon-tile-tone={tile?.tone}\n data-multiline={multiline ? 'true' : undefined}\n data-density={density}\n data-divider={divider}\n data-busy={busy ? 'true' : undefined}\n data-trailing-visibility={trailingActionVisibility}\n data-state={state}\n data-selected={String(selected)}\n data-pressed={pressed === undefined ? undefined : String(pressed)}\n data-placeholder={placeholder ? 'true' : undefined}\n draggable={nativeDraggable(draggable, placeholder)}\n data-dragging={dragging ? 'true' : undefined}\n data-drop-position={dropPosition}\n aria-busy={placeholder || busy ? 'true' : undefined}\n slot={slot}\n >\n <button\n type=\"button\"\n class=\"kui-list-action-row__primary\"\n title={placeholder ? undefined : title}\n disabled={disabled || placeholder}\n tabindex={placeholder ? -1 : tabIndex}\n data-kui-disabled={disabled ? 'true' : undefined}\n data-action={placeholder ? undefined : action}\n data-item-id={itemId}\n aria-label={accessibleLabel}\n aria-current={selected ? 'page' : undefined}\n aria-pressed={pressed === undefined ? undefined : String(pressed)}\n >\n {icon && (\n <span\n class=\"kui-list-action-row__icon\"\n style={placeholder ? undefined : tile?.style}\n >\n {placeholder ? (\n <Skeleton\n block\n width={remify(iconSize)}\n height={remify(iconSize)}\n />\n ) : (\n icon\n )}\n </span>\n )}\n <span class=\"kui-list-action-row__label\">\n <span class=\"kui-list-action-row__primary-label\">\n {placeholder ? (\n <Skeleton width={em(9)} />\n ) : multiline ? (\n withWordBreaks(label)\n ) : (\n label\n )}\n </span>\n {description && (\n <span class=\"kui-list-action-row__description\">\n {placeholder ? <Skeleton width={em(11)} /> : description}\n </span>\n )}\n {(busy || status) && (\n <span class=\"kui-list-action-row__status\">\n {/* The busy spinner is component-owned chrome drawn from a\n known prop, so a placeholder keeps it live; only the status\n text is a value and becomes a skeleton. */}\n {busy && <LoadingSpinner />}\n {status && (placeholder ? <Skeleton width={em(6)} /> : status)}\n </span>\n )}\n </span>\n </button>\n {trailingMenu ? (\n <PopupMenu\n label={trailingMenu.label}\n icon={trailingMenu.icon}\n items={trailingMenu.items}\n placement={trailingMenu.placement ?? 'bottom-end'}\n caret={false}\n disabled={Boolean(trailingMenu.disabled) || placeholder}\n />\n ) : (\n <button\n {...extensionTrailingAttributes}\n type=\"button\"\n class=\"kui-list-action-row__trailing-action\"\n data-action={placeholder ? undefined : trailingAction}\n data-item-id={itemId}\n aria-label={trailingActionLabel}\n title={trailingActionTitle ?? trailingActionLabel}\n disabled={trailingActionDisabled || placeholder || undefined}\n data-kui-disabled={trailingActionDisabled ? 'true' : undefined}\n >\n {trailingActionIcon}\n </button>\n )}\n </div>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { followAnchor, positionPopup } from './chunk-PE2KPZDW.js';
1
+ import { followAnchor, positionPopup } from './chunk-HDXUHLTQ.js';
2
2
 
3
3
  // src/components/forms/combobox/wiring/wire-comboboxes.ts
4
4
  var INPUT = ".kui-combobox__input";
@@ -166,4 +166,4 @@ function wireComboboxes(root, { onCommit, commitKeys = [","] }) {
166
166
 
167
167
  export { wireComboboxes };
168
168
 
169
- //# sourceMappingURL=chunk-GCAK23PU.js.map
169
+ //# sourceMappingURL=chunk-MVKHSAKE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/forms/combobox/wiring/wire-comboboxes.ts"],"names":[],"mappings":"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","file":"chunk-GCAK23PU.js","sourcesContent":["import {\n followAnchor,\n positionPopup,\n} from '../../../../shared/popup/position-popup.js';\n\ntype Root = HTMLElement | Document;\n\nconst INPUT = '.kui-combobox__input';\n\n/** A committed combobox value. */\nexport interface ComboboxCommit {\n id: string;\n value: string;\n /** True when the value matched no suggestion (the person created it). */\n created: boolean;\n /** The field's input; clear or keep its text after applying the commit. */\n input: HTMLInputElement;\n}\n\nexport interface WireComboboxesOptions {\n onCommit: (commit: ComboboxCommit) => void;\n /** Characters that commit the typed text besides Enter. Default `[',']`. */\n commitKeys?: readonly string[];\n}\n\ninterface Parts {\n field: HTMLElement;\n input: HTMLInputElement;\n listbox: HTMLElement;\n create: HTMLElement | null;\n}\n\n// `Combobox` renders the input inside its field with its listbox, and every\n// suggestion option with `data-value`, so the lookups below cannot miss.\nfunction partsOf(input: HTMLInputElement): Parts {\n const field = input.closest<HTMLElement>('[data-component=\"combobox\"]')!;\n const listbox = field.querySelector<HTMLElement>('[role=\"listbox\"]')!;\n return {\n field,\n input,\n listbox,\n create: listbox.querySelector<HTMLElement>('[data-create]'),\n };\n}\n\nconst visibleOptions = (parts: Parts) =>\n [...parts.listbox.querySelectorAll<HTMLElement>('[role=\"option\"]')].filter(\n (option) => !option.hidden,\n );\n\nconst matches = (option: HTMLElement, text: string) =>\n option.textContent!.toLowerCase().includes(text) ||\n option.dataset.value!.toLowerCase().includes(text);\n\nfunction setActive(parts: Parts, option: HTMLElement | null) {\n for (const item of parts.listbox.querySelectorAll('[role=\"option\"]'))\n item.setAttribute('aria-selected', String(item === option));\n if (option) {\n parts.input.setAttribute('aria-activedescendant', option.id);\n option.scrollIntoView?.({ block: 'nearest' });\n } else parts.input.removeAttribute('aria-activedescendant');\n}\n\nfunction activeOption(parts: Parts): HTMLElement | null {\n const id = parts.input.getAttribute('aria-activedescendant');\n return id\n ? parts.listbox.querySelector<HTMLElement>(`#${CSS.escape(id)}`)\n : null;\n}\n\n// The listbox is a manual popover in the top layer, so no clipping or\n// scrolling ancestor (an AnchoredSurface, a dialog, a scrolling List) cuts\n// it off; it follows the field while shown.\nconst following = new WeakMap<HTMLElement, () => void>();\n\nfunction show(parts: Parts) {\n const { listbox } = parts;\n listbox.hidden = false;\n if (!listbox.matches(':popover-open')) listbox.showPopover();\n if (following.has(listbox)) return;\n const control = parts.input.parentElement!;\n const place = async () => {\n if (!listbox.isConnected || listbox.hidden) return;\n listbox.style.width = `${control.getBoundingClientRect().width}px`;\n await positionPopup(control, listbox, {\n placement: 'bottom-start',\n gap: 4,\n });\n // Placement caps the height to the room its side has; keep the list's\n // own cap too.\n listbox.style.maxHeight = `min(${listbox.style.maxHeight}, var(--_kui-combobox-max-height))`;\n };\n following.set(\n listbox,\n followAnchor(control, listbox, () => void place()),\n );\n}\n\nfunction hide(parts: Parts) {\n const { listbox } = parts;\n listbox.hidden = true;\n if (listbox.matches(':popover-open')) listbox.hidePopover();\n following.get(listbox)?.();\n following.delete(listbox);\n}\n\nfunction close(parts: Parts) {\n hide(parts);\n parts.input.setAttribute('aria-expanded', 'false');\n setActive(parts, null);\n}\n\n/** Filter the suggestions to the typed text and show the create option. */\nfunction update(parts: Parts) {\n const typed = parts.input.value.trim();\n const text = typed.toLowerCase();\n let exact = false;\n for (const option of parts.listbox.querySelectorAll<HTMLElement>(\n '[role=\"option\"]:not([data-create])',\n )) {\n option.hidden = text !== '' && !matches(option, text);\n if (option.dataset.value!.toLowerCase() === text) exact = true;\n }\n if (parts.create) {\n parts.create.hidden = typed === '' || exact;\n parts.create.dataset.value = typed;\n // A create option exists only when the field has a create label.\n parts.create.textContent = parts.field.dataset.createLabel!.replaceAll(\n '{value}',\n typed,\n );\n }\n const options = visibleOptions(parts);\n if (options.length === 0) hide(parts);\n else show(parts);\n parts.input.setAttribute('aria-expanded', String(options.length > 0));\n if (!options.includes(activeOption(parts)!)) setActive(parts, null);\n}\n\n/**\n * Wire every `Combobox` below root: typing filters the suggestions (and offers\n * to create the typed text), ArrowDown/ArrowUp move the active option, Enter or\n * a commit key (comma by default) commits the active option or the typed text,\n * a click commits an option, and Escape or leaving the field closes the list.\n * Typed text that matches no suggestion commits only when the field offers\n * creation; otherwise Enter commits the first matching suggestion. Dispose with the owning application.\n */\nexport function wireComboboxes(\n root: Root,\n { onCommit, commitKeys = [','] }: WireComboboxesOptions,\n): () => void {\n const commit = (parts: Parts, active: HTMLElement | null) => {\n // Without a create option, Enter on partial text takes the first match.\n const option =\n active ?? (parts.create ? null : (visibleOptions(parts)[0] ?? null));\n const typed = parts.input.value.trim();\n // Callers commit only with an option or non-empty typed text.\n const value = option ? option.dataset.value! : typed;\n const suggestion = [\n ...parts.listbox.querySelectorAll<HTMLElement>(\n '[role=\"option\"]:not([data-create])',\n ),\n ].find((item) => item.dataset.value!.toLowerCase() === value.toLowerCase());\n const created = !suggestion;\n if (created && !parts.create) return;\n close(parts);\n onCommit({\n id: parts.field.dataset.comboboxId!,\n value: suggestion?.dataset.value ?? value,\n created,\n input: parts.input,\n });\n };\n const inputOf = (event: Event) =>\n event.target instanceof HTMLInputElement && event.target.matches(INPUT)\n ? event.target\n : null;\n const onInput = (event: Event) => {\n const input = inputOf(event);\n const parts = input && partsOf(input);\n if (parts) update(parts);\n };\n const onFocus = onInput;\n const onKeyDown = (event: Event) => {\n const keyboard = event as KeyboardEvent;\n const input = inputOf(keyboard);\n const parts = input && partsOf(input);\n if (!parts || keyboard.isComposing) return;\n const options = visibleOptions(parts);\n const current = activeOption(parts);\n const index = current ? options.indexOf(current) : -1;\n if (keyboard.key === 'ArrowDown' || keyboard.key === 'ArrowUp') {\n keyboard.preventDefault();\n if (parts.listbox.hidden) update(parts);\n const open = visibleOptions(parts);\n if (open.length === 0) return;\n const step = keyboard.key === 'ArrowDown' ? 1 : -1;\n const next =\n index < 0\n ? step > 0\n ? 0\n : open.length - 1\n : (index + step + open.length) % open.length;\n setActive(parts, open[next]!);\n } else if (keyboard.key === 'Enter' || commitKeys.includes(keyboard.key)) {\n if (!parts.input.value.trim() && !current) return;\n keyboard.preventDefault();\n commit(parts, current);\n } else if (keyboard.key === 'Escape' && !parts.listbox.hidden) {\n keyboard.preventDefault();\n close(parts);\n }\n };\n const onPointerDown = (event: Event) => {\n const option =\n event.target instanceof Element\n ? event.target.closest<HTMLElement>('.kui-combobox__option')\n : null;\n const input = option\n ?.closest('[data-component=\"combobox\"]')\n ?.querySelector<HTMLInputElement>(INPUT);\n const parts = input && partsOf(input);\n if (!option || !parts) return;\n // Keep focus in the field; commit on the press itself.\n event.preventDefault();\n commit(parts, option);\n };\n const onFocusOut = (event: Event) => {\n const input = inputOf(event);\n const parts = input && partsOf(input);\n if (parts) close(parts);\n };\n root.addEventListener('input', onInput);\n root.addEventListener('focusin', onFocus);\n root.addEventListener('keydown', onKeyDown);\n root.addEventListener('pointerdown', onPointerDown);\n root.addEventListener('focusout', onFocusOut);\n return () => {\n root.removeEventListener('input', onInput);\n root.removeEventListener('focusin', onFocus);\n root.removeEventListener('keydown', onKeyDown);\n root.removeEventListener('pointerdown', onPointerDown);\n root.removeEventListener('focusout', onFocusOut);\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/components/forms/combobox/wiring/wire-comboboxes.ts"],"names":[],"mappings":"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","file":"chunk-MVKHSAKE.js","sourcesContent":["import {\n followAnchor,\n positionPopup,\n} from '../../../../shared/popup/position-popup.js';\n\ntype Root = HTMLElement | Document;\n\nconst INPUT = '.kui-combobox__input';\n\n/** A committed combobox value. */\nexport interface ComboboxCommit {\n id: string;\n value: string;\n /** True when the value matched no suggestion (the person created it). */\n created: boolean;\n /** The field's input; clear or keep its text after applying the commit. */\n input: HTMLInputElement;\n}\n\nexport interface WireComboboxesOptions {\n onCommit: (commit: ComboboxCommit) => void;\n /** Characters that commit the typed text besides Enter. Default `[',']`. */\n commitKeys?: readonly string[];\n}\n\ninterface Parts {\n field: HTMLElement;\n input: HTMLInputElement;\n listbox: HTMLElement;\n create: HTMLElement | null;\n}\n\n// `Combobox` renders the input inside its field with its listbox, and every\n// suggestion option with `data-value`, so the lookups below cannot miss.\nfunction partsOf(input: HTMLInputElement): Parts {\n const field = input.closest<HTMLElement>('[data-component=\"combobox\"]')!;\n const listbox = field.querySelector<HTMLElement>('[role=\"listbox\"]')!;\n return {\n field,\n input,\n listbox,\n create: listbox.querySelector<HTMLElement>('[data-create]'),\n };\n}\n\nconst visibleOptions = (parts: Parts) =>\n [...parts.listbox.querySelectorAll<HTMLElement>('[role=\"option\"]')].filter(\n (option) => !option.hidden,\n );\n\nconst matches = (option: HTMLElement, text: string) =>\n option.textContent!.toLowerCase().includes(text) ||\n option.dataset.value!.toLowerCase().includes(text);\n\nfunction setActive(parts: Parts, option: HTMLElement | null) {\n for (const item of parts.listbox.querySelectorAll('[role=\"option\"]'))\n item.setAttribute('aria-selected', String(item === option));\n if (option) {\n parts.input.setAttribute('aria-activedescendant', option.id);\n option.scrollIntoView?.({ block: 'nearest' });\n } else parts.input.removeAttribute('aria-activedescendant');\n}\n\nfunction activeOption(parts: Parts): HTMLElement | null {\n const id = parts.input.getAttribute('aria-activedescendant');\n return id\n ? parts.listbox.querySelector<HTMLElement>(`#${CSS.escape(id)}`)\n : null;\n}\n\n// The listbox is a manual popover in the top layer, so no clipping or\n// scrolling ancestor (an AnchoredSurface, a dialog, a scrolling List) cuts\n// it off; it follows the field while shown.\nconst following = new WeakMap<HTMLElement, () => void>();\n\nfunction show(parts: Parts) {\n const { listbox } = parts;\n listbox.hidden = false;\n if (!listbox.matches(':popover-open')) listbox.showPopover();\n if (following.has(listbox)) return;\n const control = parts.input.parentElement!;\n const place = async () => {\n if (!listbox.isConnected || listbox.hidden) return;\n listbox.style.width = `${control.getBoundingClientRect().width}px`;\n await positionPopup(control, listbox, {\n placement: 'bottom-start',\n gap: 4,\n });\n // Placement caps the height to the room its side has; keep the list's\n // own cap too.\n listbox.style.maxHeight = `min(${listbox.style.maxHeight}, var(--_kui-combobox-max-height))`;\n };\n following.set(\n listbox,\n followAnchor(control, listbox, () => void place()),\n );\n}\n\nfunction hide(parts: Parts) {\n const { listbox } = parts;\n listbox.hidden = true;\n if (listbox.matches(':popover-open')) listbox.hidePopover();\n following.get(listbox)?.();\n following.delete(listbox);\n}\n\nfunction close(parts: Parts) {\n hide(parts);\n parts.input.setAttribute('aria-expanded', 'false');\n setActive(parts, null);\n}\n\n/** Filter the suggestions to the typed text and show the create option. */\nfunction update(parts: Parts) {\n const typed = parts.input.value.trim();\n const text = typed.toLowerCase();\n let exact = false;\n for (const option of parts.listbox.querySelectorAll<HTMLElement>(\n '[role=\"option\"]:not([data-create])',\n )) {\n option.hidden = text !== '' && !matches(option, text);\n if (option.dataset.value!.toLowerCase() === text) exact = true;\n }\n if (parts.create) {\n parts.create.hidden = typed === '' || exact;\n parts.create.dataset.value = typed;\n // A create option exists only when the field has a create label.\n parts.create.textContent = parts.field.dataset.createLabel!.replaceAll(\n '{value}',\n typed,\n );\n }\n const options = visibleOptions(parts);\n if (options.length === 0) hide(parts);\n else show(parts);\n parts.input.setAttribute('aria-expanded', String(options.length > 0));\n if (!options.includes(activeOption(parts)!)) setActive(parts, null);\n}\n\n/**\n * Wire every `Combobox` below root: typing filters the suggestions (and offers\n * to create the typed text), ArrowDown/ArrowUp move the active option, Enter or\n * a commit key (comma by default) commits the active option or the typed text,\n * a click commits an option, and Escape or leaving the field closes the list.\n * Typed text that matches no suggestion commits only when the field offers\n * creation; otherwise Enter commits the first matching suggestion. Dispose with the owning application.\n */\nexport function wireComboboxes(\n root: Root,\n { onCommit, commitKeys = [','] }: WireComboboxesOptions,\n): () => void {\n const commit = (parts: Parts, active: HTMLElement | null) => {\n // Without a create option, Enter on partial text takes the first match.\n const option =\n active ?? (parts.create ? null : (visibleOptions(parts)[0] ?? null));\n const typed = parts.input.value.trim();\n // Callers commit only with an option or non-empty typed text.\n const value = option ? option.dataset.value! : typed;\n const suggestion = [\n ...parts.listbox.querySelectorAll<HTMLElement>(\n '[role=\"option\"]:not([data-create])',\n ),\n ].find((item) => item.dataset.value!.toLowerCase() === value.toLowerCase());\n const created = !suggestion;\n if (created && !parts.create) return;\n close(parts);\n onCommit({\n id: parts.field.dataset.comboboxId!,\n value: suggestion?.dataset.value ?? value,\n created,\n input: parts.input,\n });\n };\n const inputOf = (event: Event) =>\n event.target instanceof HTMLInputElement && event.target.matches(INPUT)\n ? event.target\n : null;\n const onInput = (event: Event) => {\n const input = inputOf(event);\n const parts = input && partsOf(input);\n if (parts) update(parts);\n };\n const onFocus = onInput;\n const onKeyDown = (event: Event) => {\n const keyboard = event as KeyboardEvent;\n const input = inputOf(keyboard);\n const parts = input && partsOf(input);\n if (!parts || keyboard.isComposing) return;\n const options = visibleOptions(parts);\n const current = activeOption(parts);\n const index = current ? options.indexOf(current) : -1;\n if (keyboard.key === 'ArrowDown' || keyboard.key === 'ArrowUp') {\n keyboard.preventDefault();\n if (parts.listbox.hidden) update(parts);\n const open = visibleOptions(parts);\n if (open.length === 0) return;\n const step = keyboard.key === 'ArrowDown' ? 1 : -1;\n const next =\n index < 0\n ? step > 0\n ? 0\n : open.length - 1\n : (index + step + open.length) % open.length;\n setActive(parts, open[next]!);\n } else if (keyboard.key === 'Enter' || commitKeys.includes(keyboard.key)) {\n if (!parts.input.value.trim() && !current) return;\n keyboard.preventDefault();\n commit(parts, current);\n } else if (keyboard.key === 'Escape' && !parts.listbox.hidden) {\n keyboard.preventDefault();\n close(parts);\n }\n };\n const onPointerDown = (event: Event) => {\n const option =\n event.target instanceof Element\n ? event.target.closest<HTMLElement>('.kui-combobox__option')\n : null;\n const input = option\n ?.closest('[data-component=\"combobox\"]')\n ?.querySelector<HTMLInputElement>(INPUT);\n const parts = input && partsOf(input);\n if (!option || !parts) return;\n // Keep focus in the field; commit on the press itself.\n event.preventDefault();\n commit(parts, option);\n };\n const onFocusOut = (event: Event) => {\n const input = inputOf(event);\n const parts = input && partsOf(input);\n if (parts) close(parts);\n };\n root.addEventListener('input', onInput);\n root.addEventListener('focusin', onFocus);\n root.addEventListener('keydown', onKeyDown);\n root.addEventListener('pointerdown', onPointerDown);\n root.addEventListener('focusout', onFocusOut);\n return () => {\n root.removeEventListener('input', onInput);\n root.removeEventListener('focusin', onFocus);\n root.removeEventListener('keydown', onKeyDown);\n root.removeEventListener('pointerdown', onPointerDown);\n root.removeEventListener('focusout', onFocusOut);\n };\n}\n"]}
@@ -1,13 +1,13 @@
1
1
  import { WORKBENCH_MAIN_MIN_SIZE, WORKBENCH_MAIN_MIN_HEIGHT, workbenchRegionId, WORKBENCH_RESIZE_DEFAULTS } from './chunk-S4ZGTDSG.js';
2
- import { FloatingToolbar } from './chunk-S3ECMF23.js';
3
- import { NavStack } from './chunk-ZXZAECHZ.js';
2
+ import { NavStack } from './chunk-Z4DS77U2.js';
4
3
  import { clampRegionSize, ResizeGrip } from './chunk-Y6KT7ZTR.js';
5
- import { panelToggleGroup, groupSizeFor, composedPanelBody, relocatedPanelGroups } from './chunk-FG6U7KQQ.js';
4
+ import { FloatingToolbar } from './chunk-S3ECMF23.js';
5
+ import { panelToggleGroup, groupSizeFor, composedPanelBody, relocatedPanelGroups } from './chunk-DNWWF6UN.js';
6
6
  import { paneConfigProps } from './chunk-CTQUDCY5.js';
7
+ import { Toolbar } from './chunk-CMLPFIC5.js';
7
8
  import { Pane } from './chunk-HQZG3OFL.js';
8
9
  import { ensureSunkenTexture } from './chunk-IKS72C6P.js';
9
10
  import { List } from './chunk-OY2MXIBB.js';
10
- import { Toolbar } from './chunk-CMLPFIC5.js';
11
11
  import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
12
12
 
13
13
  var SIDES = {
@@ -524,4 +524,4 @@ function Workbench({
524
524
 
525
525
  export { Workbench };
526
526
 
527
- //# sourceMappingURL=chunk-DDSCVEO5.js.map
527
+ //# sourceMappingURL=chunk-NLMEDZRM.js.map