@persona/design-system 0.10.12 → 0.10.14

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 (157) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/{CheckboxGroupField-XSVAmESI.d.mts → CheckboxGroupField-tBvP22Bo.d.mts} +2 -2
  3. package/dist/CheckboxGroupField.d.mts +1 -1
  4. package/dist/{Combobox-BNjYEAmv.mjs → Combobox-DmFQ5cAy.mjs} +63 -51
  5. package/dist/Combobox-DmFQ5cAy.mjs.map +1 -0
  6. package/dist/{Combobox-DbcSss15.d.mts → Combobox-RX4DfO5L.d.mts} +3 -3
  7. package/dist/Combobox.d.mts +2 -2
  8. package/dist/{ComboboxBase-CrFweFGi.d.mts → ComboboxBase-VIGR58Uc.d.mts} +2 -2
  9. package/dist/ComboboxBase.d.mts +1 -1
  10. package/dist/{ComboboxMultiSelect-Cp5GBGQj.d.mts → ComboboxMultiSelect-D5TWGGKZ.d.mts} +2 -2
  11. package/dist/ComboboxMultiSelect.d.mts +1 -1
  12. package/dist/{ComboboxSingleSelect-u7fK3Yvy.d.mts → ComboboxSingleSelect-D9It8t6W.d.mts} +3 -3
  13. package/dist/ComboboxSingleSelect.d.mts +1 -1
  14. package/dist/{CompactBar-BLZZWtIE.d.mts → CompactBar-tNtY2EhN.d.mts} +2 -2
  15. package/dist/CompactBar.d.mts +1 -1
  16. package/dist/{ControlBar-B3Jn8G0k.d.mts → ControlBar-CDb6b1_6.d.mts} +5 -3
  17. package/dist/ControlBar.d.mts +1 -1
  18. package/dist/{DataTable-C1mdfmQa.d.mts → DataTable-0nhT5_Fe.d.mts} +31 -7
  19. package/dist/{DataTable-DdSY9mzT.mjs → DataTable-6t5ryaEq.mjs} +146 -77
  20. package/dist/DataTable-6t5ryaEq.mjs.map +1 -0
  21. package/dist/DataTable.d.mts +1 -1
  22. package/dist/{DatePicker-DiilpYQg.mjs → DatePicker-CHVYVKB-.mjs} +2 -2
  23. package/dist/{DatePicker-DiilpYQg.mjs.map → DatePicker-CHVYVKB-.mjs.map} +1 -1
  24. package/dist/DropdownButton.d.mts +1 -1
  25. package/dist/{DropdownMenu-CQR0U-zM.d.mts → DropdownMenu-Db6N6ZNB.d.mts} +2 -2
  26. package/dist/DropdownMenu.d.mts +1 -1
  27. package/dist/{FloatingActionBar-BUgSKimy.d.mts → FloatingActionBar-CfgjHs81.d.mts} +5 -1
  28. package/dist/FloatingActionBar.d.mts +1 -1
  29. package/dist/{FormField-yYJFkJ6R.mjs → FormField-BfVrDOY0.mjs} +4 -4
  30. package/dist/{FormField-yYJFkJ6R.mjs.map → FormField-BfVrDOY0.mjs.map} +1 -1
  31. package/dist/{HoverCopyableField-X2XfKTTh.mjs → HoverCopyableField-CJ_p3llp.mjs} +2 -2
  32. package/dist/{HoverCopyableField-X2XfKTTh.mjs.map → HoverCopyableField-CJ_p3llp.mjs.map} +1 -1
  33. package/dist/IndexTableLayout.d.mts +3 -3
  34. package/dist/InlineCombobox.d.mts +1 -1
  35. package/dist/InlineInput.d.mts +1 -1
  36. package/dist/{Link-B29ZMN6m.mjs → Link-Df3zJrj2.mjs} +1 -1
  37. package/dist/{Link-B29ZMN6m.mjs.map → Link-Df3zJrj2.mjs.map} +1 -1
  38. package/dist/{ListBox-4rTgr3IJ.mjs → ListBox-BRgjgUSp.mjs} +2 -2
  39. package/dist/{ListBox-4rTgr3IJ.mjs.map → ListBox-BRgjgUSp.mjs.map} +1 -1
  40. package/dist/{ListBox-ZDaitaXR.d.mts → ListBox-l47zUDj4.d.mts} +2 -2
  41. package/dist/ListBox.d.mts +1 -1
  42. package/dist/{ListBoxField-CGvVWKyL.d.mts → ListBoxField-Di_6uD3S.d.mts} +4 -4
  43. package/dist/ListBoxField.d.mts +1 -1
  44. package/dist/{LogicRow-Bzp5o1sL.d.mts → LogicRow-7f17CKrW.d.mts} +2 -2
  45. package/dist/LogicRow.d.mts +1 -1
  46. package/dist/MaskedInput.d.mts +1 -1
  47. package/dist/{Menu-DviYNrFd.d.mts → Menu-DvzoR8e7.d.mts} +2 -2
  48. package/dist/Menu.d.mts +1 -1
  49. package/dist/{Modal-CiPFqr0L.mjs → Modal-C_vSgqgl.mjs} +20 -16
  50. package/dist/Modal-C_vSgqgl.mjs.map +1 -0
  51. package/dist/{Modal-CujB7DuB.d.mts → Modal-IVXc4p8Y.d.mts} +7 -2
  52. package/dist/Modal.d.mts +1 -1
  53. package/dist/{Pii-jSYND7Cn.mjs → Pii-BYPkrBuT.mjs} +1 -1
  54. package/dist/{Pii-jSYND7Cn.mjs.map → Pii-BYPkrBuT.mjs.map} +1 -1
  55. package/dist/{Popover-CVX-dfYb.mjs → Popover-DP9DXReH.mjs} +1 -1
  56. package/dist/{Popover-CVX-dfYb.mjs.map → Popover-DP9DXReH.mjs.map} +1 -1
  57. package/dist/{Select-DsVeAyZy.d.mts → Select-boZ6XP8k.d.mts} +2 -2
  58. package/dist/Select.d.mts +1 -1
  59. package/dist/SmartTextInputField.d.mts +2 -2
  60. package/dist/SmartTextInputListbox.d.mts +8 -3
  61. package/dist/{TableBox-D9NA-s9l.mjs → TableBox-RxpwflEb.mjs} +3 -3
  62. package/dist/{TableBox-D9NA-s9l.mjs.map → TableBox-RxpwflEb.mjs.map} +1 -1
  63. package/dist/TableBox.d.mts +1 -1
  64. package/dist/{TableBoxCell-CQOL30et.d.mts → TableBoxCell-B6Z23mby.d.mts} +4 -4
  65. package/dist/TableBoxCell.d.mts +1 -1
  66. package/dist/{TableBoxField-z0GIFeQw.d.mts → TableBoxField-6qAOW8t9.d.mts} +5 -5
  67. package/dist/TableBoxField.d.mts +1 -1
  68. package/dist/{TableBoxRow-tb9-KMr9.d.mts → TableBoxRow-CpgNWdLS.d.mts} +2 -2
  69. package/dist/TableBoxRow.d.mts +1 -1
  70. package/dist/{TableBoxRowActions-BZwulsFP.d.mts → TableBoxRowActions-BDx5naRj.d.mts} +2 -2
  71. package/dist/TableBoxRowActions.d.mts +1 -1
  72. package/dist/{TableControls-DE6eHq8h.d.mts → TableControls-BGKL7_zF.d.mts} +4 -4
  73. package/dist/{TableControls-BXykbUBf.mjs → TableControls-BwZl4TjJ.mjs} +31 -12
  74. package/dist/TableControls-BwZl4TjJ.mjs.map +1 -0
  75. package/dist/TableControls.d.mts +1 -1
  76. package/dist/{TableControlsContext-C2_2EuMh.d.mts → TableControlsContext-DhABbtVY.d.mts} +2 -2
  77. package/dist/TableControlsContext.d.mts +1 -1
  78. package/dist/{TableViewConfigurationDropdown-DE9HFXYY.d.mts → TableViewConfigurationDropdown-D76ApJ_-.d.mts} +2 -2
  79. package/dist/TableViewConfigurationDropdown.d.mts +1 -1
  80. package/dist/WizardModal.d.mts +1 -1
  81. package/dist/{clientFilterUtils-2TBUC31K.d.mts → clientFilterUtils-WH_Dqtv4.d.mts} +2 -2
  82. package/dist/clientFilterUtils.d.mts +1 -1
  83. package/dist/components/Combobox/index.d.mts +4 -4
  84. package/dist/components/Combobox/index.mjs +1 -1
  85. package/dist/components/DataTable/TableControls/index.d.mts +7 -7
  86. package/dist/components/DataTable/TableControls/index.mjs +1 -1
  87. package/dist/components/DataTable/index.d.mts +6 -6
  88. package/dist/components/DataTable/index.mjs +1 -1
  89. package/dist/components/DataTable/types.d.mts +1 -1
  90. package/dist/components/DatePicker/index.mjs +1 -1
  91. package/dist/components/DropdownMenu/index.d.mts +1 -1
  92. package/dist/components/FormField/index.d.mts +4 -4
  93. package/dist/components/FormField/index.mjs +1 -1
  94. package/dist/components/HoverCopyableField/index.mjs +1 -1
  95. package/dist/components/Link/index.mjs +1 -1
  96. package/dist/components/ListBox/index.d.mts +3 -3
  97. package/dist/components/ListBox/index.mjs +1 -1
  98. package/dist/components/Menu/index.d.mts +1 -1
  99. package/dist/components/Modal/index.d.mts +1 -1
  100. package/dist/components/Modal/index.mjs +1 -1
  101. package/dist/components/Pii/index.mjs +1 -1
  102. package/dist/components/Popover/index.mjs +1 -1
  103. package/dist/components/RichTextEditor/index.mjs +2 -2
  104. package/dist/components/Select/index.d.mts +1 -1
  105. package/dist/components/SmartTextInput/index.mjs +128 -59
  106. package/dist/components/SmartTextInput/index.mjs.map +1 -1
  107. package/dist/components/TableBox/index.d.mts +1 -1
  108. package/dist/components/TableBox/index.mjs +1 -1
  109. package/dist/components/VersionHistory/index.mjs +1 -1
  110. package/dist/fieldPickerOptions.d.mts +1 -1
  111. package/dist/{filters-DW7pqWv3.d.mts → filters-BXtKuft3.d.mts} +2 -2
  112. package/dist/filters.d.mts +1 -1
  113. package/dist/{helpers-BTD2kXLs.d.mts → helpers-gpO42h8t.d.mts} +5 -3
  114. package/dist/helpers.d.mts +1 -1
  115. package/dist/{index-B4tE0RxY.d.mts → index-bkzLg85W.d.mts} +3 -3
  116. package/dist/{inputFields-DnBb3NhK.d.mts → inputFields-B7parF2l.d.mts} +4 -4
  117. package/dist/inputFields.d.mts +1 -1
  118. package/dist/lib/PDSProvider.d.mts +2 -1
  119. package/dist/lib/PDSProvider.mjs +8 -3
  120. package/dist/lib/PDSProvider.mjs.map +1 -1
  121. package/dist/lib/colorMode.d.mts +18 -7
  122. package/dist/lib/colorMode.mjs +47 -13
  123. package/dist/lib/colorMode.mjs.map +1 -1
  124. package/dist/lib/schemaOptions.mjs +1 -1
  125. package/dist/lib/schemaOptions.mjs.map +1 -1
  126. package/dist/patterns/IndexTableLayout/index.mjs +1 -1
  127. package/dist/patterns/WizardModal/index.mjs +1 -1
  128. package/dist/{types-NO2GRlM-.d.mts → types-BvaXqjUm.d.mts} +2 -2
  129. package/dist/{types-Dws2XDz2.d.mts → types-CuH-sUJ2.d.mts} +6 -4
  130. package/dist/types5.d.mts +1 -1
  131. package/dist/useColumnConfiguration.d.mts +2 -2
  132. package/dist/useComboboxFooterAction.d.mts +1 -1
  133. package/dist/{useTableColumns-tITjHasE.d.mts → useTableColumns-I7StvoRs.d.mts} +17 -2
  134. package/dist/useTableColumns.d.mts +1 -1
  135. package/dist/useTruncation.d.mts +1 -1
  136. package/dist/utils4.d.mts +1 -1
  137. package/dist/withDisabledReason.d.mts +19 -0
  138. package/llms.txt +4 -3
  139. package/package.json +4 -12
  140. package/skills/ui-authoring/COMPONENTS.md +0 -1
  141. package/skills/ui-authoring/PATTERNS.md +0 -64
  142. package/skills/ui-authoring/TOKENS.md +14 -25
  143. package/dist/ChartFrame.d.mts +0 -61
  144. package/dist/ChartLegend.d.mts +0 -60
  145. package/dist/ChartPopover.d.mts +0 -155
  146. package/dist/Combobox-BNjYEAmv.mjs.map +0 -1
  147. package/dist/DataTable-DdSY9mzT.mjs.map +0 -1
  148. package/dist/Modal-CiPFqr0L.mjs.map +0 -1
  149. package/dist/TableControls-BXykbUBf.mjs.map +0 -1
  150. package/dist/chartColors.d.mts +0 -92
  151. package/dist/chartFrameLayout.d.mts +0 -46
  152. package/dist/components/Chart/index.d.mts +0 -9
  153. package/dist/components/Chart/index.mjs +0 -680
  154. package/dist/components/Chart/index.mjs.map +0 -1
  155. package/dist/useChartColors.d.mts +0 -30
  156. package/dist/useChartSeriesVisibility.d.mts +0 -22
  157. package/dist/useChartStyles.d.mts +0 -108
@@ -1 +0,0 @@
1
- {"version":3,"file":"Combobox-BNjYEAmv.mjs","names":["Input","EXTERNAL_TRIGGER_DROPDOWN_MIN_WIDTH","StyledMenuItem","selectedOption","MenuItemIconContainer"],"sources":["../src/components/Combobox/ComboboxBase.tsx","../src/components/Combobox/useComboboxFooterAction.ts","../src/components/Combobox/useTruncation.ts","../src/components/Combobox/ComboboxMultiSelect.tsx","../src/components/Combobox/ComboboxSingleSelect.tsx","../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import type { Virtualizer } from '@tanstack/react-virtual';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport {\n type CSSProperties,\n Fragment,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport styled, { css, type DefaultTheme, type StyledComponent } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\n\nimport Button from '#src/components/Button';\nimport Input from '#src/components/Input';\nimport { FloatingCard, MenuHeading, MenuList } from '#src/components/Menu';\nimport Spinner from '#src/components/Spinner/Spinner';\nimport type { StickerProps } from '#src/components/Sticker/Sticker';\nimport { Paragraph } from '#src/components/Text';\nimport { isDisabled, isHovered, isNotDisabled } from '#src/lib/pseudoClass';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { Z_INDICES } from '#src/lib/zindex';\nimport { focusStyle } from '#src/mixins/focus';\nimport type { InputSizes } from '#src/mixins/input';\nimport { semanticScrollbar } from '#src/mixins/scrollbar';\n\n/**\n * In the future, we may extend this to include other style properties\n * like fontWeight, fontStyle, etc. if needed.\n */\ntype LabelStyle = Pick<CSSProperties, 'fontFamily'>;\n\n// Re-export ComboboxOption type that both components need\nexport interface ComboboxOption<T = string> {\n label: string;\n /**\n * Description of the option that will be displayed below the label. Will not be rendered when labelStickerVariant is provided.\n */\n description?: string;\n /**\n * Extra text Fuse indexes when filtering. Never rendered in the UI — use\n * `description` for a visible sublabel.\n */\n keywords?: string;\n value: T;\n /**\n * Sticker variant to render the label within.\n */\n labelStickerVariant?: StickerProps['variant'];\n /**\n * Optional style properties to apply to the option label currently limited to fontFamily.\n * This should only be used as a one-off for font dropdowns and most comboboxes should use the default fontFamily.\n */\n PLEASE_DO_NOT_USE_labelFontStyle?: LabelStyle;\n}\n\n// Group type — either an inline section header (the default) or a\n// nested submenu the user navigates into (`nested: true`).\nexport interface ComboboxOptionGroup<T = string> {\n readonly label: string;\n readonly prefixIcon?: ReactNode;\n readonly options: ComboboxOptionsOrGroups<T>;\n /**\n * Sublabel beneath the group label. Only honored for `nested` groups — an\n * inline group renders as a bare `MenuHeading` with no room for it.\n */\n readonly description?: string;\n /**\n * When `true`, the group renders as a single navigation row with a\n * trailing chevron. Clicking it descends into a submenu whose\n * contents are this group's `options`; the group itself never\n * commits a value via `onChange`. The `label` becomes the\n * breadcrumb crumb shown alongside any leaf inside in search mode.\n *\n * When omitted (or `false`), the group renders inline as a section\n * header above its options — the legacy `MenuHeading` behavior.\n *\n * Today only single-select Combobox honors the nested-navigation\n * UX. Multi-select degrades gracefully: it strips the `nested`\n * flag from every group at the top of the component (treating the\n * tree as inline section headers + leaves), so every leaf stays\n * reachable with checkboxes — just without the chevron / Back-row\n * navigation. Nested-nav for multi-select can be added once we\n * have customer demand without changing this API.\n */\n readonly nested?: boolean;\n}\n\n// Type guard using structural typing (like react-select's GroupBase)\nexport function isOptionGroup<T>(\n item: ComboboxOption<T> | ComboboxOptionGroup<T>,\n): item is ComboboxOptionGroup<T> {\n return 'options' in item && Array.isArray((item as ComboboxOptionGroup<T>).options);\n}\n\n/** True when a group renders as a navigation row rather than a section header. */\nexport function isNestedGroup<T>(\n item: ComboboxOption<T> | ComboboxOptionGroup<T>,\n): item is ComboboxOptionGroup<T> & { nested: true } {\n return isOptionGroup(item) && item.nested === true;\n}\n\n/**\n * Moves disabled options after the enabled ones, keeping each run in its original order. A section\n * header (inline group) is a boundary, so an option never leaves its section. Nested-group rows\n * count as enabled. Recurses into every group.\n */\nexport function sortDisabledOptionsLast<T>(\n items: ComboboxOptionsOrGroups<T>,\n isDisabled: (option: ComboboxOption<T>) => boolean,\n): ComboboxOptionsOrGroups<T> {\n const sorted: (ComboboxOption<T> | ComboboxOptionGroup<T>)[] = [];\n let enabled: (ComboboxOption<T> | ComboboxOptionGroup<T>)[] = [];\n let disabled: ComboboxOption<T>[] = [];\n const flush = () => {\n sorted.push(...enabled, ...disabled);\n enabled = [];\n disabled = [];\n };\n for (const item of items) {\n if (isOptionGroup(item)) {\n const group = { ...item, options: sortDisabledOptionsLast(item.options, isDisabled) };\n if (item.nested) {\n enabled.push(group);\n } else {\n flush();\n sorted.push(group);\n }\n } else if (isDisabled(item)) {\n disabled.push(item);\n } else {\n enabled.push(item);\n }\n }\n flush();\n return sorted;\n}\n\n// Union type for options prop — supports flat options, inline groups\n// (section headers), nested groups (submenu entries), or any mix.\nexport type ComboboxOptionsOrGroups<T = string> = readonly (\n | ComboboxOption<T>\n | ComboboxOptionGroup<T>\n)[];\n\n/**\n * Flatten the visible leaves at the current navigation level. Inline\n * (non-nested) groups are walked through transparently — their leaves\n * surface at this level. Nested groups are skipped along with their\n * contents — those leaves live behind a navigation step in single-\n * select. Multi-select doesn't reach this code with nested groups\n * intact (it inlines them at the component boundary), so the skip\n * here is the single-select-only contract.\n */\nexport function flattenOptions<T>(items: ComboboxOptionsOrGroups<T>): ComboboxOption<T>[] {\n const out: ComboboxOption<T>[] = [];\n for (const item of items) {\n if (isOptionGroup(item)) {\n if (!item.nested) {\n out.push(...flattenOptions(item.options));\n }\n } else {\n out.push(item);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Nested-navigation helpers\n//\n// A single-select Combobox can act as a cascading menu by tagging\n// groups with `nested: true`: those groups render as navigation rows\n// (chevron) that descend into a submenu showing the group's `options`.\n// The functions below resolve the items visible at a given navigation\n// path and flatten the tree to its leaves for search-mode fallback.\n// ---------------------------------------------------------------------------\n\n/**\n * Recurse through the entire option tree looking for any nested\n * group. Used to gate nested-mode behavior so trees that don't opt\n * in (the overwhelmingly common case) skip the extra book-keeping\n * entirely. Single-select uses this to switch between its nested-nav\n * render path and the legacy renderer; multi-select uses it to\n * short-circuit its `nested → inline` transform when there's nothing\n * to convert.\n */\nexport function containsNestedGroup<T>(\n items: readonly (ComboboxOption<T> | ComboboxOptionGroup<T>)[],\n): boolean {\n for (const item of items) {\n if (isOptionGroup(item)) {\n if (item.nested) {\n return true;\n }\n if (containsNestedGroup(item.options)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Find a nested-group child of `items` whose `label` matches `label`.\n * Walks transparently through inline (non-nested) groups at the same\n * level — they don't add a navigation step, so a nested submenu\n * declared inside an inline section header is still \"at this level\"\n * for descent purposes. Returns `null` if no match.\n */\nfunction findNestedGroupByLabel<T>(\n items: ComboboxOptionsOrGroups<T>,\n label: string,\n): ComboboxOptionGroup<T> | null {\n for (const item of items) {\n if (!isOptionGroup(item)) {\n continue;\n }\n if (item.nested) {\n if (item.label === label) {\n return item;\n }\n } else {\n const found = findNestedGroupByLabel(item.options, label);\n if (found) {\n return found;\n }\n }\n }\n return null;\n}\n\n/**\n * Walk the option tree by following `path` step-by-step. Each entry\n * in `path` is the `label` of a nested group at that level; we\n * descend into its `options` at each step. Returns the items visible\n * at the resolved level (a mix of leaves, inline groups, and further\n * nested groups).\n *\n * - Empty `path` returns the original top-level items unchanged.\n * - If a step no longer resolves to a nested group, returns an empty list.\n */\nexport function getOptionsAtPath<T>(\n options: ComboboxOptionsOrGroups<T>,\n path: readonly string[],\n): ComboboxOptionsOrGroups<T> {\n let scope = options;\n for (const label of path) {\n const found = findNestedGroupByLabel(scope, label);\n if (!found) {\n return [];\n }\n scope = found.options;\n }\n return scope;\n}\n\n/**\n * One leaf hit returned by `flattenLeafOptions`. Carries the leaf's\n * `option` alongside the labels of every nested-group ancestor\n * (top-down). Used as the search-results data shape so each hit can\n * render with a breadcrumb (e.g. \"Business Account\" for a custom\n * field that lives under that parent record type's submenu).\n */\nexport interface LeafOptionEntry<T = string> {\n option: ComboboxOption<T>;\n breadcrumb: readonly string[];\n}\n\n/**\n * Recursively walk the tree and return every leaf option, each paired\n * with the labels of its nested-group ancestors. Used by single-select\n * Combobox to populate the search-results view: the search query\n * bypasses the active navigation path and matches against every leaf\n * in the tree, with the breadcrumb surfacing parent context in each\n * hit.\n *\n * Inline (non-nested) groups are walked through transparently — their\n * `label` isn't a breadcrumb crumb because they don't correspond to a\n * navigation step. Only nested groups contribute a crumb.\n */\nexport function flattenLeafOptions<T>(\n options: ComboboxOptionsOrGroups<T>,\n breadcrumb: readonly string[] = [],\n): LeafOptionEntry<T>[] {\n const result: LeafOptionEntry<T>[] = [];\n for (const item of options) {\n if (isOptionGroup(item)) {\n const nextBreadcrumb = item.nested ? [...breadcrumb, item.label] : breadcrumb;\n result.push(...flattenLeafOptions(item.options, nextBreadcrumb));\n } else {\n result.push({ option: item, breadcrumb });\n }\n }\n return result;\n}\n\n/**\n * Discriminated tagged item for single-select's downshift items list\n * in nested-navigation mode. Leaves are selectable and commit via\n * `onChange`; groups are navigable and descend into a submenu instead.\n */\nexport type NavigableItem<T> =\n | { readonly kind: 'leaf'; readonly option: ComboboxOption<T> }\n | { readonly kind: 'group'; readonly group: ComboboxOptionGroup<T> };\n\n/**\n * Build the flat list of navigable items at the current navigation\n * level, in document order. Inline (non-nested) groups are walked\n * through transparently; their leaves and any nested subgroups\n * contribute at this level. Nested groups become a `kind: 'group'`\n * entry that the renderer turns into a navigation row.\n */\nexport function getNavigableItemsAtLevel<T>(items: ComboboxOptionsOrGroups<T>): NavigableItem<T>[] {\n const out: NavigableItem<T>[] = [];\n for (const item of items) {\n if (isOptionGroup(item)) {\n if (item.nested) {\n out.push({ kind: 'group', group: item });\n } else {\n out.push(...getNavigableItemsAtLevel(item.options));\n }\n } else {\n out.push({ kind: 'leaf', option: item });\n }\n }\n return out;\n}\n\nfunction filterComboboxOptions<T>(options: ComboboxOptionsOrGroups<T>, inputValue: string) {\n const flatOptions = flattenOptions(options);\n const fuseOptions: IFuseOptions<ComboboxOption<T>> = {\n shouldSort: false,\n threshold: 0.0,\n ignoreLocation: true,\n minMatchCharLength: 1,\n keys: ['label', 'description', 'keywords'],\n };\n const fuse = new Fuse<ComboboxOption<T>>(flatOptions, fuseOptions);\n return inputValue === ''\n ? flatOptions\n : Array.from(new Set(fuse.search(inputValue).map(({ item }) => item)).values());\n}\n\n/** All server-specific behavior lives here; client event/filtering behavior passes through. */\nexport function useComboboxServerMode<T>(\n props: ComboboxBaseProps<T> | ComboboxServerBaseProps<T>,\n values: readonly T[],\n clientOptions: ComboboxOptionsOrGroups<T> = props.options,\n selectAll = false,\n) {\n const server = props.filterMode === 'server';\n const options = useMemo(\n () => (server ? flattenLeafOptions(props.options).map(({ option }) => option) : clientOptions),\n [server, props.options, clientOptions],\n );\n const selectedItems = useMemo(() => {\n if (!server) {\n // Match master: chips/removal order follow options, including duplicate values.\n return flattenLeafOptions(options)\n .map(({ option }) => option)\n .filter((option) => values.includes(option.value));\n }\n const byValue = new Map<T, ComboboxOption<T>>();\n if (props.filterMode === 'server') {\n props.selectedOptions?.forEach((option) => byValue.set(option.value, option));\n }\n flattenLeafOptions(options).forEach(({ option }) => byValue.set(option.value, option));\n return values.flatMap((value) => {\n const option = byValue.get(value) ?? (server ? { value, label: String(value) } : undefined);\n return option ? [option] : [];\n });\n }, [options, server, props.filterMode, props.selectedOptions, values]);\n const itemToKey = useCallback((item: ComboboxOption<T> | null) => item?.value, []);\n const filterOptions = useCallback(\n (source: ComboboxOptionsOrGroups<T>, inputValue: string) =>\n server ? flattenOptions(source) : filterComboboxOptions(source, inputValue),\n [server],\n );\n const scrollRef = useRef<HTMLDivElement>(null);\n const scrollState = useRef<{ open: boolean; rowHeight: number; callback?: () => void }>({\n open: false,\n rowHeight: 32,\n });\n scrollState.current.rowHeight = props.size === 'sm' ? 24 : 32;\n scrollState.current.callback = props.filterMode === 'server' ? props.onScrollEnd : undefined;\n const checkScrollEnd = useCallback((shortOnly = false) => {\n const list = scrollRef.current;\n if (!scrollState.current.open || !list || list.clientHeight <= 0) {\n return;\n }\n if (\n shortOnly\n ? list.scrollHeight <= list.clientHeight\n : list.scrollHeight - list.scrollTop - list.clientHeight <= scrollState.current.rowHeight\n ) {\n scrollState.current.callback?.();\n }\n }, []);\n const onMenuOpenChange = useCallback(\n (open: boolean) => {\n if (scrollState.current.open === open) {\n return;\n }\n scrollState.current.open = open;\n if (open) {\n checkScrollEnd(true);\n }\n },\n [checkScrollEnd],\n );\n // Callback/loading/query changes never re-check: failed short pages need user action.\n useEffect(() => checkScrollEnd(true), [checkScrollEnd, options.length]);\n const getQueryInputProps = (\n inputProps: React.InputHTMLAttributes<HTMLInputElement>,\n isOpen = true,\n onQueryEdit?: () => void,\n ) => {\n if (props.filterMode !== 'server') {\n return inputProps;\n }\n return {\n ...inputProps,\n value: isOpen ? props.query : inputProps.value,\n // Closed labels are display-only. Replace them before native insertion/deletion,\n // rather than guessing inserted text from the resulting label/query string.\n onKeyDown: (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (\n !isOpen &&\n !event.nativeEvent.isComposing &&\n ((event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey) ||\n event.key === 'Backspace' ||\n event.key === 'Delete' ||\n // IME, Android virtual keyboards, and dead keys start composition with these keys.\n event.key === 'Process' ||\n event.key === 'Unidentified' ||\n event.key === 'Dead')\n ) {\n event.currentTarget.select();\n }\n inputProps.onKeyDown?.(event);\n },\n onPaste: (event: React.ClipboardEvent<HTMLInputElement>) => {\n if (!isOpen) {\n event.currentTarget.select();\n }\n inputProps.onPaste?.(event);\n },\n // Keep Downshift InputChange (open/highlight/value clearing), but query reports\n // still come only from this native edit path, never selection/display callbacks.\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => {\n const nextInput = event.currentTarget.value;\n inputProps.onChange?.(event);\n onQueryEdit?.();\n props.onQueryChange(nextInput);\n },\n };\n };\n return {\n options,\n selectedItems,\n scrollRef,\n onMenuOpenChange,\n onScroll: server ? () => checkScrollEnd() : undefined,\n loadingMore:\n props.filterMode === 'server' && props.isLoadingMore ? (\n <LoadingMoreRow>\n <Spinner size='sm' srText='Loading more options' />\n </LoadingMoreRow>\n ) : null,\n itemToKey,\n filterOptions,\n getQueryInputProps,\n query: props.filterMode === 'server' ? props.query : undefined,\n onInputChange: server ? undefined : props.onInputChange,\n selectAll: !server && selectAll,\n preserveOptionOrder: server,\n };\n}\n\n// A row in the virtualized list — either a group label or an option\ntype VirtualRow<T> =\n | { kind: 'group-header'; label: string }\n | { kind: 'option'; option: ComboboxOption<T>; index: number };\n\nexport function buildVirtualRows<T>(\n options: ComboboxOptionsOrGroups<T>,\n filteredOptions: ComboboxOption<T>[],\n indexRealToIndexVirtual: Map<number, number>,\n): VirtualRow<T>[] {\n const rows: VirtualRow<T>[] = [];\n // idx counts only option rows — matches navigableItems indices (no group headers)\n let idx = 0;\n\n for (const item of options) {\n if (isOptionGroup(item)) {\n // Nested groups belong to the single-select nested-nav render\n // path. Multi-select (the only `buildVirtualRows` caller)\n // inlines its nested groups at the component boundary, so any\n // group reaching here with `nested: true` is unexpected — skip\n // defensively rather than render a header without a row.\n if (item.nested) {\n continue;\n }\n const groupLeaves = flattenOptions(item.options);\n const visibleLeaves = groupLeaves.filter((opt) =>\n filteredOptions.some((f) => f.value === opt.value),\n );\n if (visibleLeaves.length > 0) {\n rows.push({ kind: 'group-header', label: item.label });\n for (const opt of visibleLeaves) {\n indexRealToIndexVirtual.set(idx, rows.length);\n rows.push({ kind: 'option', option: opt, index: idx++ });\n }\n }\n } else {\n if (filteredOptions.some((f) => f.value === item.value)) {\n indexRealToIndexVirtual.set(idx, rows.length);\n rows.push({ kind: 'option', option: item, index: idx++ });\n }\n }\n }\n\n return rows;\n}\n\ninterface RenderOptionsWithGroupsParams<T> {\n options: ComboboxOptionsOrGroups<T>;\n filteredOptions: ComboboxOption<T>[];\n virtualizer?: Virtualizer<HTMLDivElement, Element>;\n virtualRows?: VirtualRow<T>[];\n renderOption: (option: ComboboxOption<T>, flatIndex: number) => React.ReactNode;\n}\n\n/**\n * Renders options with support for groups, handling filtering and proper indexing\n *\n * @param params - Object containing options, filteredOptions, and renderOption\n * @param params.options - The original options array (can include groups)\n * @param params.filteredOptions - The flat filtered options to display\n * @param params.virtualizer - Optional virtualizer for large lists\n * @param params.virtualRows - Pre-built flat rows list (required when virtualizer is provided)\n * @param params.renderOption - Callback to render each individual option with its flat index\n * @returns React nodes with properly grouped and filtered options\n */\nexport function renderOptionsWithGroups<T>({\n options,\n filteredOptions,\n renderOption,\n virtualizer,\n virtualRows,\n}: RenderOptionsWithGroupsParams<T>): React.ReactNode {\n if (virtualizer && virtualRows) {\n const rows = virtualRows;\n const vItems = virtualizer.getVirtualItems();\n return (\n <div\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n width: '100%',\n position: 'relative',\n }}\n >\n {vItems.map((vItem) => {\n const row = rows[vItem.index];\n if (!row) {\n return null;\n }\n\n return (\n <div\n key={String(vItem.key)}\n data-index={vItem.index}\n ref={virtualizer.measureElement}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${vItem.start}px)`,\n }}\n >\n {row.kind === 'group-header' ? (\n <MenuHeading as='div'>{row.label}</MenuHeading>\n ) : (\n renderOption(row.option, row.index)\n )}\n </div>\n );\n })}\n </div>\n );\n }\n\n let flatIndex = -1;\n\n return options.map((item, groupIndex) => {\n if (isOptionGroup(item)) {\n // Nested groups belong to the single-select nested-nav code\n // path, which renders them via its own local helper. Multi-\n // select inlines nested groups at the component boundary\n // before calling this renderer, so a group reaching here with\n // `nested: true` is single-select's responsibility — skip it.\n if (item.nested) {\n return null;\n }\n const groupLeaves = flattenOptions(item.options);\n const visibleLeaves = groupLeaves.filter((opt) =>\n filteredOptions.some((filtered) => filtered.value === opt.value),\n );\n\n if (visibleLeaves.length === 0) {\n return null;\n }\n\n return (\n <Fragment key={`group-${groupIndex}`}>\n <MenuHeading>{item.label}</MenuHeading>\n {visibleLeaves.map((option) => {\n flatIndex++;\n return renderOption(option, flatIndex);\n })}\n </Fragment>\n );\n } else {\n // This is a flat option\n if (!filteredOptions.some((filtered) => filtered.value === item.value)) {\n return null;\n }\n\n flatIndex++;\n return renderOption(item, flatIndex);\n }\n });\n}\n\n// Footer action button rendered at the bottom of the dropdown. The type is\n// intentionally generic (not Combobox-prefixed); alias it on import if the\n// name collides with a local one.\nexport interface FooterAction {\n /** Text shown on the footer button. */\n label: string;\n /**\n * Invoked when the footer button is clicked. The Combobox is agnostic to\n * what it does (e.g. load more options); it just calls this on click.\n */\n onClick: () => void;\n}\n\n// Base interface with common props\ninterface ComboboxCommonProps {\n /**\n * Size of the combobox input\n */\n size?: InputSizes;\n\n /**\n * If true, the options are currently being loaded\n */\n isOptionsLoading?: boolean;\n\n /**\n * Callback when input value changes (for filtering)\n * In single this is the main input, in multi this is the search input\n * In both cases this corresponds to the input the user can type into to filter the options.\n * Client mode only; server mode uses the controlled query / onQueryChange pair.\n */\n onInputChange?: (value: string) => void;\n\n /**\n * Callback when dropdown open state changes\n */\n onOpenChange?: (isOpen: boolean) => void;\n\n /**\n * Custom empty state message when no options match filter\n */\n emptyStateMessage?: string;\n\n /**\n * Whether the combobox is disabled\n */\n disabled?: boolean;\n\n /**\n * ID of the label for the combobox input\n */\n labelId?: string;\n\n /**\n * Aria label for accessibility when no visible label is provided\n */\n 'aria-label'?: string;\n\n /**\n * Placeholder text when no option is selected\n */\n placeholder?: string;\n\n /**\n * Whether the combobox has a warning state\n */\n hasWarning?: boolean;\n\n /**\n * Whether the combobox has an error state\n */\n hasError?: boolean;\n\n /** Marks the combobox as required (sets aria-required). */\n required?: boolean;\n\n /**\n * ID for the combobox input\n */\n id?: string;\n\n /**\n * Whether to render the dropdown in a portal (breaks out of overflow containers)\n */\n portal?: boolean;\n\n /**\n * Reference to the container element for portal rendering.\n * When provided, the dropdown will use this element's dimensions for positioning.\n */\n portalContainerRef?: React.RefObject<HTMLElement>;\n\n /**\n * Optional external trigger (e.g. an \"Add\" button or icon-only menu opener).\n * When provided, the Combobox clones it with downshift's toggle props and\n * renders it in place of the default input + caret; the search input moves\n * inside the dropdown.\n */\n trigger?: React.ReactElement;\n\n /**\n * Render the searchable option list inline without a trigger or floating\n * dropdown. Use when another component already owns the containing popover.\n *\n * When `true`, the in-panel search uses bordered `Input` chrome and the\n * embedder owns all surrounding spacing; when `false`, the floating-dropdown\n * borderless search strip is preserved.\n */\n embedded?: boolean;\n\n /**\n * **THIS IS A BAD PATTERN AND ONLY EXISTS AS A BANDAID. AVOID USING THIS PROP IF POSSIBLE.**\n * Optional action button rendered at the bottom of the dropdown, below the\n * option list. Common use is \"Load more\" pagination, but the label/handler\n * are up to the consumer. Works identically in single- and multi-select.\n */\n footerAction?: FooterAction;\n}\n\n/** Client search keeps the existing grouped/nested options and local input behavior. */\nexport interface ComboboxBaseProps<T = string> extends ComboboxCommonProps {\n filterMode?: 'client';\n options: ComboboxOptionsOrGroups<T>;\n query?: never;\n onQueryChange?: never;\n selectedOptions?: never;\n}\n\n/** Flat, already-filtered server results with consumer-owned query and selected labels. */\nexport interface ComboboxServerBaseProps<T = string> extends ComboboxCommonProps {\n filterMode: 'server';\n /** Flat results only. Nested/grouped navigation is a client-mode feature. */\n options: readonly ComboboxOption<T>[];\n /** The consumer-owned search text; separate from the selected label displayed when closed. */\n query: string;\n /** Called only by native query edits, never by Downshift selection/display events. */\n onQueryChange: (query: string) => void;\n /**\n * Required metadata for all selected values, including those absent from current results.\n * Current results win for duplicate values. Metadata never adds menu rows. String(value)\n * is only a runtime safety fallback if a selected option is accidentally omitted.\n */\n selectedOptions: readonly ComboboxOption<T>[];\n /**\n * Reports scrolling within about one row of the end, and short lists on open/count\n * changes. Calls may repeat: the caller must ignore duplicate, loading or exhausted\n * requests (useServerOptions().loadMore does). PDS has no request lock or hasMore prop.\n */\n onScrollEnd?: () => void;\n /** Adds a loading row after existing options; does not gate onScrollEnd reports. */\n isLoadingMore?: boolean;\n}\n\n// Shared constants\nexport const MAX_DROPDOWN_HEIGHT = '300px';\n\n// Shared styled components\nexport const Container = styled.div`\n display: flex;\n position: relative;\n width: 100%;\n`;\n\nexport const InputContainer = styled.div`\n position: relative;\n width: 100%;\n`;\n\n// Interface for ComboboxInput props\ninterface ComboboxInputProps {\n $isOpen?: boolean;\n hasError?: boolean;\n hasWarning?: boolean;\n $selectedItemStyle?: LabelStyle;\n}\n\nexport const ComboboxInput = styled(Input)<ComboboxInputProps>`\n padding-right: ${({ size }) =>\n size === 'sm' ? Spacing[5] : Spacing[6]}; /* Space for caret icon */\n\n ${({ $isOpen }) =>\n $isOpen &&\n css`\n ${focusStyle}\n `}\n\n /* Apply custom font family from selected item when dropdown is closed */\n ${({ $selectedItemStyle, $isOpen }) =>\n !$isOpen &&\n $selectedItemStyle?.fontFamily &&\n css`\n && {\n font-family: ${$selectedItemStyle.fontFamily};\n }\n `}\n`;\n\nexport const CaretButton = styled(Button).attrs({ width: 'icon' })`\n background-color: transparent;\n border: none;\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n\n &:hover:not(:disabled),\n &:active:not(:disabled) {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n background-color: transparent;\n border: none;\n }\n\n &:disabled {\n color: ${({ theme }) => semanticColor(theme, 'FgDisabled', Color.BorderIconDisabled)};\n background-color: transparent;\n border: none;\n }\n\n position: absolute;\n right: 0;\n top: 0;\n`;\n\ninterface DropdownContainerProps {\n $isOpen?: boolean;\n $portal?: boolean;\n $embedded?: boolean;\n $top?: number;\n $left?: number;\n $width?: number;\n /** Minimum dropdown width (decouples from a narrow trigger). */\n $minWidth?: string;\n}\n\nexport const DropdownContainer: StyledComponent<\n typeof FloatingCard,\n DefaultTheme,\n DropdownContainerProps\n> = styled(FloatingCard)<DropdownContainerProps>`\n ${({ $portal, $embedded, $top, $left, $width }) =>\n $embedded\n ? css`\n position: static;\n width: 100%;\n min-width: 0;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n background: transparent;\n margin: 0;\n `\n : $portal\n ? css`\n position: fixed;\n top: ${$top != null ? `${$top}px` : '0'};\n left: ${$left != null ? `${$left}px` : '0'};\n width: ${$width != null ? `${$width}px` : 'auto'};\n `\n : css`\n position: absolute;\n top: calc(100% + ${Spacing[2]});\n left: 0;\n right: 0;\n width: 100%;\n `}\n\n ${({ $minWidth }) =>\n $minWidth &&\n css`\n min-width: ${$minWidth};\n `}\n\n display: flex;\n flex-direction: column;\n ${({ $embedded }) =>\n $embedded &&\n css`\n gap: ${Spacing[2]};\n `}\n overflow: ${({ $embedded }) =>\n $embedded\n ? 'visible'\n : 'hidden'}; /* Prevent floating menu overflow while preserving embedded focus rings */\n box-sizing: border-box;\n z-index: ${Z_INDICES.modalDropdown}; /* Ensure portal dropdown appears above other content */\n\n ${({ $embedded, theme }) =>\n !$embedded &&\n css`\n background-color: ${semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n `}\n\n ${({ $isOpen }) =>\n !$isOpen &&\n css`\n display: none;\n `}\n`;\n\nexport const ScrollableMenuList = styled(MenuList)`\n max-height: ${MAX_DROPDOWN_HEIGHT};\n overflow-y: auto;\n overflow-x: hidden; /* Prevent horizontal scrolling */\n width: 100%; /* Ensure full width is used */\n box-sizing: border-box;\n ${semanticScrollbar}\n`;\n\n// In-dropdown search chrome, shared by any Combobox-family component that\n// renders a search row inside the dropdown panel.\nexport const SearchInputContainer = styled.div<{ $embedded?: boolean }>`\n flex-shrink: 0;\n ${({ $embedded }) =>\n $embedded\n ? css`\n padding: 0;\n `\n : css`\n padding: ${Spacing[1]} ${Spacing[2]};\n border-bottom: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDivider', theme.color.border.primary)};\n `}\n`;\n\nexport const SearchInput = styled(Input)<{ $embedded?: boolean }>`\n &&,\n &&${isHovered}${isNotDisabled},\n &&${isDisabled} {\n background: transparent;\n }\n\n ${({ $embedded }) =>\n !$embedded &&\n css`\n /* Borderless strip inside floating menus. */\n border: none;\n padding-top: ${Spacing[1]};\n padding-bottom: ${Spacing[1]};\n\n &:focus {\n outline: none !important;\n }\n `}\n`;\n\nexport const EmptyState = styled(Paragraph).attrs<{ size: InputSizes }>(({ size }) => ({\n size,\n}))`\n padding: 0 ${({ size }) => (size === 'sm' ? Spacing[1] : Spacing[2])};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.tertiary)};\n ${({ theme }) => theme.text.paragraph.md};\n`;\n\nexport const LoadingContainer = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 136px;\n padding: ${Spacing[3]};\n`;\n\nconst LoadingMoreRow = styled(LoadingContainer)`\n min-height: 0;\n padding: ${Spacing[2]};\n`;\n\nconst FooterActionContainer = styled.div`\n flex-shrink: 0;\n padding-top: ${Spacing[1]};\n`;\n\n/**\n * Action button rendered at the bottom of the dropdown, below the option list.\n * Kept out of downshift's `items` list and out of the Tab order, mirroring the\n * `BackRow` affordance: `onMouseDown` preventDefault beats downshift's\n * blur-on-mousedown so the dropdown stays open on click. Keyboard users reach it\n * by arrowing past the last option (the parent drives `isHighlighted` and points\n * the input's `aria-activedescendant` at this button via `id`).\n */\nexport function FooterActionRow({\n action,\n size,\n id,\n isHighlighted = false,\n}: {\n action: FooterAction;\n size: InputSizes;\n id?: string;\n isHighlighted?: boolean;\n}) {\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (isHighlighted) {\n buttonRef.current?.scrollIntoView({ block: 'nearest' });\n }\n }, [isHighlighted]);\n\n return (\n <FooterActionContainer>\n <Button\n ref={buttonRef}\n id={id}\n type='button'\n variant='basic'\n width='full'\n size={size}\n tabIndex={-1}\n active={isHighlighted}\n onMouseDown={(e) => {\n e.preventDefault();\n action.onClick();\n }}\n onClick={(e) => {\n // AT activation (VoiceOver) fires click with detail 0 and no mousedown\n if (e.detail === 0) {\n action.onClick();\n }\n }}\n >\n {action.label}\n </Button>\n </FooterActionContainer>\n );\n}\n\nexport const OptionLabel = styled.div<{ $labelStyle?: LabelStyle }>`\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0; /* Allow flex item to shrink below content size */\n\n /* Apply custom font family if provided */\n ${({ $labelStyle }) =>\n $labelStyle?.fontFamily &&\n css`\n font-family: ${$labelStyle.fontFamily};\n `}\n`;\n\nexport const Description = styled.p`\n ${Typography.TextSmall};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.TextSecondary)};\n margin: 0;\n\n /* Multi-line truncation with 3-line limit */\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n\n /* Fallback for browsers that don't support -webkit-line-clamp */\n max-height: calc(${Typography.TextSmall.lineHeight} * 3); /* line-height * 3 lines */\n`;\n\n// Hook to calculate dropdown position for portal rendering\nexport function useDropdownPosition(\n portalContainerRef: React.RefObject<HTMLElement>,\n isOpen: boolean,\n portal?: boolean,\n) {\n const [position, setPosition] = useState({ top: 0, left: 0, width: 0 });\n\n useEffect(() => {\n if (!portal || !isOpen || !portalContainerRef.current) {\n return;\n }\n\n const updatePosition = () => {\n const rect = portalContainerRef.current!.getBoundingClientRect();\n const spacing = parseInt(Spacing[2]);\n setPosition({\n top: rect.bottom + spacing,\n left: rect.left,\n width: rect.width,\n });\n };\n\n updatePosition();\n\n // Update position on scroll and resize\n window.addEventListener('scroll', updatePosition, true);\n window.addEventListener('resize', updatePosition);\n\n return () => {\n window.removeEventListener('scroll', updatePosition, true);\n window.removeEventListener('resize', updatePosition);\n };\n }, [portalContainerRef, isOpen, portal]);\n\n return position;\n}\n\n// Wrapper component for portal rendering\nexport interface DropdownPortalWrapperProps {\n children: React.ReactNode;\n portal?: boolean;\n}\n\nexport function DropdownPortalWrapper({ children, portal }: DropdownPortalWrapperProps) {\n const portalRoot = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (portal) {\n portalRoot.current = document.body;\n }\n }, [portal]);\n\n if (portal && portalRoot.current) {\n return createPortal(\n // data-react-aria-top-layer='true': FocusScope contain allows focus here\n // (presence selector). ariaHideOutside's MutationObserver only exempts\n // newly added nodes when the dataset value is the string 'true'.\n <div id='combobox-dropdown-portal-wrapper' data-react-aria-top-layer='true'>\n {children}\n </div>,\n portalRoot.current,\n );\n }\n\n return <>{children}</>;\n}\n","import { type KeyboardEvent as ReactKeyboardEvent, useCallback, useEffect, useState } from 'react';\n\nimport type { FooterAction } from './ComboboxBase';\n\ninterface UseComboboxFooterActionParams {\n footerAction?: FooterAction;\n isOptionsLoading?: boolean;\n itemCount: number;\n firstNavigableIndex?: number;\n lastNavigableIndex?: number;\n isMenuOpen: boolean;\n inputValue: string;\n /** Downshift's current option highlight (`-1` when no option is highlighted). */\n highlightedIndex: number;\n setHighlightedIndex: (index: number) => void;\n /** The combobox input id, used to build the footer button's id. */\n inputId?: string;\n}\n\ninterface UseComboboxFooterActionResult {\n isFooterHighlighted: boolean;\n footerActionId: string;\n showFooterAction: boolean;\n /** Returns `true` when the event was consumed and the caller should stop. */\n handleFooterKeyDown: (event: ReactKeyboardEvent<HTMLInputElement>) => boolean;\n clearFooterHighlight: () => void;\n}\n\n/**\n * Shared keyboard-navigation logic for the Combobox `footerAction` button, used\n * by both the single- and multi-select variants. The footer is a real\n * `<button>` outside downshift's item list, so it needs a parallel highlight\n * flag (`isFooterHighlighted`) reached by arrowing past the last option or up\n * from the first option, rather than a downshift `highlightedIndex`. DOM focus\n * stays on the input; the footer is never a Tab stop (mirrors the `BackRow`\n * affordance).\n */\nexport function useComboboxFooterAction({\n footerAction,\n isOptionsLoading,\n itemCount,\n firstNavigableIndex = 0,\n lastNavigableIndex = itemCount - 1,\n isMenuOpen,\n inputValue,\n highlightedIndex,\n setHighlightedIndex,\n inputId,\n}: UseComboboxFooterActionParams): UseComboboxFooterActionResult {\n const [isFooterHighlighted, setIsFooterHighlighted] = useState(false);\n const footerActionId = `${inputId}-footer-action`;\n const showFooterAction = Boolean(footerAction) && !isOptionsLoading && itemCount > 0;\n\n // Drop the footer highlight whenever it can no longer be the active target:\n // the menu closed, the query changed, the footer stopped being shown (e.g.\n // options started loading after a load-more), or an option became highlighted\n // (e.g. mouse hover). The two never appear active at once.\n useEffect(() => {\n if (!isMenuOpen) {\n setIsFooterHighlighted(false);\n }\n }, [isMenuOpen]);\n useEffect(() => {\n setIsFooterHighlighted(false);\n }, [inputValue]);\n useEffect(() => {\n if (!showFooterAction) {\n setIsFooterHighlighted(false);\n }\n }, [showFooterAction]);\n useEffect(() => {\n if (highlightedIndex >= 0) {\n setIsFooterHighlighted(false);\n }\n }, [highlightedIndex]);\n\n const clearFooterHighlight = useCallback(() => setIsFooterHighlighted(false), []);\n\n const handleFooterKeyDown = useCallback(\n (event: ReactKeyboardEvent<HTMLInputElement>): boolean => {\n if (!showFooterAction) {\n return false;\n }\n // downshift v9 stops its built-in Arrow/Enter handling when a consumer\n // handler sets `preventDownshiftDefault` (its `callAllEventHandlers`\n // escape hatch). Harmless no-op on the multi-select plain search input.\n const nativeEvent = event.nativeEvent as KeyboardEvent & {\n preventDownshiftDefault?: boolean;\n };\n const consume = () => {\n event.preventDefault();\n nativeEvent.preventDownshiftDefault = true;\n };\n\n if (firstNavigableIndex < 0 && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {\n consume();\n setIsFooterHighlighted(true);\n setHighlightedIndex(-1);\n return true;\n }\n if (\n !isFooterHighlighted &&\n event.key === 'ArrowDown' &&\n highlightedIndex === lastNavigableIndex\n ) {\n consume();\n setIsFooterHighlighted(true);\n setHighlightedIndex(-1);\n return true;\n }\n if (\n !isFooterHighlighted &&\n event.key === 'ArrowUp' &&\n highlightedIndex === firstNavigableIndex\n ) {\n consume();\n setIsFooterHighlighted(true);\n setHighlightedIndex(-1);\n return true;\n }\n if (isFooterHighlighted) {\n if (event.key === 'ArrowUp') {\n consume();\n setIsFooterHighlighted(false);\n setHighlightedIndex(lastNavigableIndex);\n return true;\n }\n if (event.key === 'ArrowDown') {\n consume();\n setIsFooterHighlighted(false);\n setHighlightedIndex(firstNavigableIndex);\n return true;\n }\n if (event.key === 'Enter') {\n consume();\n footerAction?.onClick();\n return true;\n }\n }\n return false;\n },\n [\n showFooterAction,\n isFooterHighlighted,\n highlightedIndex,\n firstNavigableIndex,\n lastNavigableIndex,\n footerAction,\n setHighlightedIndex,\n ],\n );\n\n return {\n isFooterHighlighted,\n footerActionId,\n showFooterAction,\n handleFooterKeyDown,\n clearFooterHighlight,\n };\n}\n","import { type MutableRefObject, type RefObject, useEffect, useState } from 'react';\n\nimport type { ComboboxOption } from '#src/components/Combobox';\n\n/**\n * Custom hook for calculating truncation when multi-select items are restricted to a single line using actual DOM measurements\n * Ensures at least one item is always visible\n */\nexport function useTruncation<T>(\n selectedItems: ComboboxOption<T>[],\n stickerRefs: MutableRefObject<(HTMLElement | null)[]>,\n truncatorRef: RefObject<HTMLElement>,\n containerRef: RefObject<HTMLDivElement>,\n truncate: boolean,\n) {\n const [visibleCount, setVisibleCount] = useState<number>(selectedItems.length);\n\n useEffect(() => {\n if (!truncate || selectedItems.length === 0 || !containerRef.current) {\n setVisibleCount(selectedItems.length);\n return;\n }\n\n const calculateVisibleCount = () => {\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n // Check if all refs are populated\n const allRefsReady =\n selectedItems.every((_, i) => stickerRefs.current[i] != null) &&\n truncatorRef.current != null;\n if (!allRefsReady) {\n return;\n }\n\n // Get actual content width by subtracting padding\n const computedStyle = window.getComputedStyle(container);\n const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;\n const paddingRight = parseFloat(computedStyle.paddingRight) || 0;\n const availableWidth = container.offsetWidth - paddingLeft - paddingRight;\n\n const gap = 4; // Spacing[1] = 4px\n const truncatorWidth = truncatorRef.current!.offsetWidth;\n\n // Simple algorithm: Start with 1 item, keep adding while they fit\n let count = 1;\n let totalWidth = stickerRefs.current[0]!.offsetWidth;\n\n // Try to add more items\n for (let i = 1; i < selectedItems.length; i++) {\n const itemWidth = stickerRefs.current[i]!.offsetWidth;\n const wouldBeLastItem = i === selectedItems.length - 1;\n\n // Calculate required width if we add this item\n const widthWithItem = totalWidth + gap + itemWidth;\n const widthWithTruncator = wouldBeLastItem ? 0 : gap + truncatorWidth;\n const requiredWidth = widthWithItem + widthWithTruncator;\n\n if (requiredWidth <= availableWidth) {\n totalWidth = widthWithItem;\n count++;\n } else {\n // Can't fit this item, stop\n break;\n }\n }\n\n // Update state only if changed\n setVisibleCount((prev) => (prev === count ? prev : count));\n };\n\n // Recalculate on resize\n const resizeObserver = new ResizeObserver(calculateVisibleCount);\n resizeObserver.observe(containerRef.current);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [selectedItems, stickerRefs, truncatorRef, containerRef, truncate]);\n\n return visibleCount;\n}\n","import { useVirtualizer } from '@tanstack/react-virtual';\nimport { useCombobox, useMultipleSelection } from 'downshift';\nimport {\n cloneElement,\n forwardRef,\n isValidElement,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\nimport { CaretDownIcon, CircleXInverseIcon, SearchIcon } from '@persona/icons';\n\nimport Checkbox from '#src/components/Checkbox';\nimport {\n CaretButton,\n type ComboboxBaseProps,\n type ComboboxServerBaseProps,\n ComboboxInput,\n type ComboboxOption,\n type ComboboxOptionsOrGroups,\n containsNestedGroup,\n Container,\n Description,\n DropdownContainer,\n DropdownPortalWrapper,\n EmptyState,\n flattenOptions,\n FooterActionRow,\n InputContainer,\n isOptionGroup,\n LoadingContainer,\n MAX_DROPDOWN_HEIGHT,\n OptionLabel,\n renderOptionsWithGroups,\n ScrollableMenuList,\n SearchInput,\n SearchInputContainer,\n useDropdownPosition,\n useComboboxServerMode,\n buildVirtualRows,\n} from '#src/components/Combobox/ComboboxBase';\nimport { useComboboxFooterAction } from '#src/components/Combobox/useComboboxFooterAction';\nimport { useTruncation } from '#src/components/Combobox/useTruncation';\nimport useFormField from '#src/components/FormControl/useFormField';\nimport { InputGroup } from '#src/components/Input';\nimport { MenuItem } from '#src/components/Menu';\nimport Spinner from '#src/components/Spinner/Spinner';\nimport Stack from '#src/components/Stack';\nimport Sticker from '#src/components/Sticker';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { useOutsideClick } from '#src/lib/useOutsideClick';\nimport type { InputSizes } from '#src/mixins/input';\n\n// Constants\nconst SELECT_ALL_VALUE = '__SELECT_ALL__';\nconst EXTERNAL_TRIGGER_DROPDOWN_MIN_WIDTH = '240px';\n\n/**\n * Recursively drop the `nested: true` flag from every group in the\n * tree, converting nested-navigation groups into inline section-\n * header groups. Multi-select doesn't implement the nested-nav UX\n * (chevron rows, Back row, descent), so this graceful-degradation\n * transform keeps every leaf reachable as a checkable option under\n * its parent's section header — instead of having `flattenOptions` /\n * `renderOptionsWithGroups` silently drop them along with their\n * descendants. Single-select Combobox is unaffected; it owns its own\n * nested-nav render path.\n *\n * For a multi-level tree (`{nested, options: [{nested, options}]}`),\n * the inner inline group is walked through by `flattenOptions` so\n * its leaves surface under the outer header — the inner label is\n * lost, but all leaves stay reachable. Acceptable for the\n * graceful-degradation goal; nested-nav can be added later without\n * changing this API.\n */\nfunction inlineNestedGroups<T>(items: ComboboxOptionsOrGroups<T>): ComboboxOptionsOrGroups<T> {\n return items.map((item) => {\n if (!isOptionGroup(item)) {\n return item;\n }\n return {\n label: item.label,\n options: inlineNestedGroups(item.options),\n };\n });\n}\n\n// Multi-select specific props\ninterface ComboboxMultiSelectionProps<T> {\n /**\n * Multi-select mode\n */\n multiple: true;\n\n /**\n * Selected values\n */\n values?: T[];\n\n /**\n * Callback when selection changes\n */\n onValuesChange?: (values: T[]) => void;\n\n /**\n * Placeholder for search input in dropdown\n */\n searchPlaceholder?: string;\n\n /**\n * If true, the combobox will truncate the selected items to a single line with overflow indicator.\n */\n truncate?: boolean;\n\n /**\n * Client mode only: show an option to select/deselect the current filtered list.\n * Ignored in server mode, where PDS cannot know the complete result set. Consumers\n * can provide an explicit selection action through footerAction.\n */\n selectAll?: boolean;\n\n /**\n * When `true`, options keep their given order instead of floating\n * currently-selected options to the top. Toggling a value no longer\n * reorders the list under the pointer — important for surfaces like filter\n * value pickers, where the just-clicked row visibly jumping to another\n * position reads as \"the wrong item toggled\". Defaults to `false`\n * (selected-first).\n */\n stableOptionOrder?: boolean;\n\n // Explicitly exclude single-select props to prevent usage\n value?: never;\n onChange?: never;\n virtualize?: boolean;\n}\n\nexport interface ComboboxMultiSelectProps<T = string>\n extends ComboboxBaseProps<T>, ComboboxMultiSelectionProps<T> {}\nexport interface ComboboxServerMultiSelectProps<T = string>\n extends ComboboxServerBaseProps<T>, ComboboxMultiSelectionProps<T> {}\n\n// Multi-select specific extensions of base components\nconst MultiSelectComboboxInput = styled(ComboboxInput)`\n position: absolute;\n inset: 0;\n height: auto;\n caret-color: transparent; /* Hide cursor in multi-select mode because we use stickers and focus into the search input */\n`;\n\n// Multi-select specific ScrollableMenuList that accounts for search bar\nconst MultiSelectScrollableMenuList = styled(ScrollableMenuList)<{ $embedded?: boolean }>`\n max-height: calc(${MAX_DROPDOWN_HEIGHT} - 60px); /* Subtract approximate search bar height */\n overflow-x: hidden; /* Prevent horizontal scrolling */\n width: 100%; /* Ensure full width is used */\n box-sizing: border-box;\n ${({ $embedded }) =>\n $embedded &&\n css`\n padding: 0;\n `}\n`;\n\nconst SelectedItemsContainer = styled.div<{ $size: InputSizes; $truncate?: boolean }>`\n position: relative; /* Establish positioning context */\n box-sizing: border-box;\n min-height: ${({ $size }) => ($size === 'sm' ? Spacing[5] : Spacing[6])};\n max-height: ${({ $truncate, $size }) =>\n $truncate ? ($size === 'sm' ? Spacing[5] : Spacing[6]) : 'none'};\n padding-left: ${Spacing[2]};\n padding-right: ${({ $size }) =>\n $size === 'sm' ? Spacing[5] : Spacing[6]}; /* Leave space for caret button. */\n padding-top: ${({ $size }) => ($size === 'sm' ? Spacing[1] : Spacing[2])};\n padding-bottom: ${({ $size }) => ($size === 'sm' ? Spacing[1] : Spacing[2])};\n display: flex;\n flex-wrap: ${({ $truncate }) => ($truncate ? 'nowrap' : 'wrap')};\n gap: ${Spacing[1]};\n align-items: flex-start;\n align-content: flex-start;\n pointer-events: none; /* Allow clicks to pass through to underlying input */\n overflow: hidden; /* Required for truncation when truncate mode is enabled */\n\n /* Re-enable pointer events on stickers' dismiss buttons */\n button {\n pointer-events: auto;\n }\n`;\n\nconst TruncatedItemsWrapper = styled.div`\n display: flex;\n flex-wrap: nowrap;\n gap: ${Spacing[1]};\n overflow: hidden;\n flex: 1;\n min-width: 0; /* Allow shrinking below content size */\n pointer-events: none;\n`;\n\nconst TruncatedSticker = styled(Sticker)<{ $isOnlyItem: boolean }>`\n /* Allow first sticker to truncate its text only when it's the only item */\n flex-shrink: ${({ $isOnlyItem }) => ($isOnlyItem ? 1 : 0)};\n min-width: 0;\n max-width: 100%;\n /* If the sticker is an inline element it was causing the parent to gain an extra pixel of height */\n vertical-align: top;\n`;\n\nconst TruncatorSticker = styled(Sticker)`\n /* Truncator should never shrink */\n flex-shrink: 0;\n /* If the sticker is an inline element it was causing the parent to gain an extra pixel of height */\n vertical-align: top;\n`;\n\nconst HiddenMeasurementContainer = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n visibility: hidden;\n display: flex;\n flex-wrap: nowrap;\n gap: ${Spacing[1]};\n pointer-events: none;\n overflow: hidden;\n max-width: 100%;\n`;\n\nconst StyledMenuItem = styled(MenuItem)<{ $size?: InputSizes }>`\n /* These heights should add up to 24 and 32 respectively and the content is 20 already */\n padding: ${({ $size }) => ($size === 'sm' ? `2px ${Spacing[2]}` : `6px ${Spacing[2]}`)};\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: ${Spacing[1]};\n min-width: 0; /* Allow content to shrink below natural size */\n width: 100%; /* Ensure full width of dropdown */\n box-sizing: border-box;\n\n /* Force all children to respect the container width */\n > * {\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n }\n`;\n\nconst CheckboxLabel = styled.span<{ id?: string; $size?: InputSizes }>`\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n ${({ $size }) => ($size === 'sm' ? Typography.TextSmall : Typography.TextMedium)};\n display: flex;\n flex-direction: column;\n gap: ${Spacing[1]};\n min-width: 0; /* Allow content to shrink below natural size */\n\n /** Nudge text for visual alignment */\n position: relative;\n bottom: -1px;\n`;\n\nfunction ComboboxMultiSelectComponent<T = string>(\n componentProps: ComboboxMultiSelectProps<T> | ComboboxServerMultiSelectProps<T>,\n ref: React.Ref<HTMLInputElement>,\n) {\n const {\n size = 'md',\n options: rawOptions,\n isOptionsLoading,\n filterMode: _filterMode,\n selectedOptions: _selectedOptions,\n query: _query,\n onQueryChange: _onQueryChange,\n onScrollEnd: _onScrollEnd,\n isLoadingMore: _isLoadingMore,\n values = [],\n onValuesChange,\n searchPlaceholder = 'Search...',\n onInputChange: _onInputChange,\n placeholder = 'Select an option...',\n emptyStateMessage = 'No options found',\n disabled = false,\n hasWarning,\n hasError,\n required,\n id,\n labelId,\n 'aria-label': ariaLabel,\n onOpenChange,\n truncate = false,\n selectAll: requestedSelectAll = false,\n stableOptionOrder = false,\n portal = false,\n portalContainerRef: externalPortalContainerRef,\n trigger,\n embedded = false,\n virtualize = false,\n footerAction,\n ...props\n } = { onScrollEnd: undefined, isLoadingMore: undefined, ...componentProps };\n // Normalize `nested: true` groups into inline section-header\n // groups before the rest of the component sees them, so the legacy\n // flatten / render / virtualization code paths work uniformly. The\n // common case (no nested groups anywhere) short-circuits via\n // `containsNestedGroup` and returns the prop value as-is, keeping\n // referential identity stable for downstream memoization.\n const clientOptions = useMemo(\n () => (containsNestedGroup(rawOptions) ? inlineNestedGroups(rawOptions) : rawOptions),\n [rawOptions],\n );\n\n const mode = useComboboxServerMode(componentProps, values, clientOptions, requestedSelectAll);\n const { options, selectedItems, selectAll } = mode;\n const field = useFormField({ hasWarning, hasError, disabled, inputId: id });\n const [inputValue, setInputValue] = useState('');\n const [embeddedOpen, setEmbeddedOpen] = useState(false);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const comboboxInputRef = useRef<HTMLInputElement>(null);\n const caretButtonRef = useRef<HTMLButtonElement>(null);\n const comboboxContainerRef = useRef<HTMLDivElement>(null);\n const scrollableListRef = mode.scrollRef;\n const selectedItemsContainerRef = useRef<HTMLDivElement>(null);\n const measurementStickerRefs = useRef<(HTMLElement | null)[]>([]);\n const measurementTruncatorRef = useRef<HTMLElement>(null);\n\n useEffect(() => {\n setEmbeddedOpen(embedded);\n }, [embedded]);\n\n // Use external portalContainerRef if provided, otherwise use internal ref for portal positioning\n const portalContainerRef = externalPortalContainerRef || comboboxContainerRef;\n\n const preserveOptionOrder = stableOptionOrder || mode.preserveOptionOrder;\n\n // Initialize measurement refs array\n useEffect(() => {\n measurementStickerRefs.current = measurementStickerRefs.current.slice(0, selectedItems.length);\n }, [selectedItems.length]);\n\n const visibleCount = useTruncation(\n selectedItems,\n measurementStickerRefs,\n measurementTruncatorRef,\n selectedItemsContainerRef,\n truncate,\n );\n\n // Expose methods to parent component\n useImperativeHandle(\n ref,\n () => ({\n ...comboboxInputRef.current!,\n focusSearchInput: () => {\n if (searchInputRef.current) {\n searchInputRef.current.focus();\n }\n },\n }),\n [],\n );\n\n // Filter options based on input value\n const filteredOptions = useMemo(\n () => mode.filterOptions(options, inputValue),\n [mode.filterOptions, options, inputValue],\n );\n\n // When options are not grouped, we float selected items to the top of the menu.\n // When grouped, we float selected items to the top within each group.\n const isGrouped = useMemo(() => options.some(isOptionGroup), [options]);\n\n // When grouped and there are selected values, reorder each group's options so selected come first\n const optionsWithSelectedFirstInGroups = useMemo(() => {\n if (!isGrouped || values.length === 0 || preserveOptionOrder) {\n return options;\n }\n return options.map((item) => {\n if (isOptionGroup(item)) {\n // `options` has already been normalized to inline groups at\n // the component boundary (`inlineNestedGroups` above), so\n // flattening the group's contents here surfaces every leaf\n // under it — even ones that came from a nested-marked\n // subtree in the original prop. Sort selected-first within\n // the resulting flat list.\n const groupLeaves = flattenOptions(item.options);\n return {\n ...item,\n options: groupLeaves.toSorted((a, b) => {\n const aSelected = values.includes(a.value);\n const bSelected = values.includes(b.value);\n if (aSelected === bSelected) {\n return 0;\n }\n return aSelected ? -1 : 1;\n }),\n };\n }\n return item;\n });\n }, [options, isGrouped, values, preserveOptionOrder]);\n\n // Create navigable items array that includes select all option for keyboard navigation.\n // When flat (not grouped): selected items first. When grouped: selected first within each group.\n const navigableItems = useMemo(() => {\n const items: ComboboxOption<T>[] = [];\n\n if (isGrouped && values.length > 0) {\n // Build flat list in render order: each group's options with selected first, only including filtered\n if (selectAll && filteredOptions.length > 0) {\n items.push({\n value: SELECT_ALL_VALUE as T,\n label: 'Select all',\n } satisfies ComboboxOption<T>);\n }\n for (const item of optionsWithSelectedFirstInGroups) {\n if (isOptionGroup(item)) {\n // `optionsWithSelectedFirstInGroups` flattens each group's\n // contents to leaves above; the inner iteration is safe to\n // treat as `ComboboxOption<T>[]` here.\n for (const opt of flattenOptions(item.options)) {\n if (filteredOptions.some((f) => f.value === opt.value)) {\n items.push(opt);\n }\n }\n } else {\n if (filteredOptions.some((f) => f.value === item.value)) {\n items.push(item);\n }\n }\n }\n return items;\n }\n\n const orderedFiltered =\n !isGrouped && values.length > 0 && !preserveOptionOrder\n ? filteredOptions.toSorted((a, b) => {\n const aSelected = values.includes(a.value);\n const bSelected = values.includes(b.value);\n if (aSelected === bSelected) {\n return 0;\n }\n return aSelected ? -1 : 1;\n })\n : filteredOptions;\n\n // Add select all option if enabled and there are filtered options\n if (selectAll && orderedFiltered.length > 0) {\n items.push({\n value: SELECT_ALL_VALUE as T,\n label: 'Select all',\n } satisfies ComboboxOption<T>);\n }\n\n // Add regular filtered options (selected first when ungrouped)\n items.push(...orderedFiltered);\n\n return items;\n }, [\n selectAll,\n filteredOptions,\n isGrouped,\n values,\n optionsWithSelectedFirstInGroups,\n preserveOptionOrder,\n ]);\n\n const optionsToRender = useMemo(() => {\n if (!isGrouped && values.length > 0) {\n return navigableItems;\n }\n\n const hasSelectAll =\n selectAll && filteredOptions.length > 0 && navigableItems[0]?.value === SELECT_ALL_VALUE;\n\n const baseOptions = isGrouped && values.length > 0 ? optionsWithSelectedFirstInGroups : options;\n\n return hasSelectAll ? [navigableItems[0], ...baseOptions] : baseOptions;\n }, [\n isGrouped,\n values,\n navigableItems,\n selectAll,\n filteredOptions,\n optionsWithSelectedFirstInGroups,\n options,\n ]);\n\n const navigableToVirtualRowRef = useRef(new Map<number, number>());\n\n const virtualRows = useMemo(() => {\n if (!virtualize) {\n return [];\n }\n const map = new Map<number, number>();\n const rows = buildVirtualRows(optionsToRender, navigableItems, map);\n navigableToVirtualRowRef.current = map;\n return rows;\n }, [optionsToRender, navigableItems, virtualize]);\n\n const virtualizer = useVirtualizer({\n count: virtualRows.length,\n getScrollElement: () => scrollableListRef.current,\n estimateSize: () => (size === 'sm' ? 24 : 32),\n overscan: 5,\n });\n\n const itemToString = useCallback((item: ComboboxOption<T> | null) => {\n return item ? item.label : '';\n }, []);\n\n const getOptionId = useCallback(\n (index: number) => `${field.inputId}-option-${index}`,\n [field.inputId],\n );\n\n // Multi-select hooks - pass selectedItems to initialize downshift state\n const {\n addSelectedItem,\n getSelectedItemProps,\n getDropdownProps,\n removeSelectedItem,\n reset,\n setSelectedItems,\n } = useMultipleSelection({\n selectedItems, // Pass selectedItems to initialize/control downshift state\n itemToKey: mode.itemToKey,\n onStateChange: ({ selectedItems: newSelectedItems, type }) => {\n switch (type) {\n case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownBackspace:\n case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete:\n case useMultipleSelection.stateChangeTypes.DropdownKeyDownBackspace:\n case useMultipleSelection.stateChangeTypes.FunctionRemoveSelectedItem:\n case useMultipleSelection.stateChangeTypes.FunctionAddSelectedItem:\n case useMultipleSelection.stateChangeTypes.FunctionSetSelectedItems:\n if (onValuesChange && newSelectedItems) {\n const newValues = newSelectedItems.map((item) => item.value);\n onValuesChange?.(newValues);\n }\n break;\n case useMultipleSelection.stateChangeTypes.FunctionReset:\n if (onValuesChange) {\n onValuesChange([]);\n }\n break;\n default:\n break;\n }\n },\n });\n\n // Calculate selected state for filtered items (for select all checkbox state)\n const selectedState = useMemo(() => {\n const counts = filteredOptions.reduce(\n (acc, option) => {\n if (values.includes(option.value)) {\n acc.selected++;\n } else {\n acc.notSelected++;\n }\n return acc;\n },\n { selected: 0, notSelected: 0 },\n );\n return {\n allSelected: counts.selected === filteredOptions.length,\n allNotSelected: counts.notSelected === filteredOptions.length,\n indeterminate: counts.selected > 0 && counts.selected < filteredOptions.length,\n };\n }, [values, filteredOptions]);\n\n const handleSelectAllToggle = useCallback(() => {\n if (selectedState.allSelected || selectedState.indeterminate) {\n // Deselect all visible filtered items - keep only items not in filtered results\n const visibleValues = filteredOptions.map((option) => option.value);\n const remainingItems = selectedItems.filter((item) => !visibleValues.includes(item.value));\n setSelectedItems(remainingItems);\n } else {\n // Select all: combine existing + new filtered items\n const newItems = filteredOptions.filter((option) => !values.includes(option.value));\n setSelectedItems([...selectedItems, ...newItems]);\n }\n }, [\n selectedState.allSelected,\n selectedState.indeterminate,\n filteredOptions,\n selectedItems,\n values,\n setSelectedItems,\n ]);\n\n // Multi-select combobox hooks\n const {\n isOpen,\n getToggleButtonProps,\n getMenuProps,\n getInputProps,\n getItemProps,\n highlightedIndex,\n setHighlightedIndex,\n closeMenu,\n openMenu,\n } = useCombobox({\n items: navigableItems,\n itemToString,\n itemToKey: mode.itemToKey,\n getItemId: getOptionId,\n isOpen: embedded ? embeddedOpen : undefined,\n selectedItem: null,\n initialHighlightedIndex: 0,\n defaultHighlightedIndex: 0,\n onIsOpenChange({ isOpen: newIsOpen }) {\n // Clear search input when dropdown opens, but only if it has content\n // This prevents unnecessary recalculation when inputValue is already empty\n if (newIsOpen && inputValue !== '') {\n setInputValue('');\n }\n },\n onHighlightedIndexChange: ({ highlightedIndex, type }) => {\n if (\n virtualize &&\n type !== useCombobox.stateChangeTypes.MenuMouseLeave &&\n highlightedIndex >= 0\n ) {\n const rowIndex = navigableToVirtualRowRef.current.get(highlightedIndex);\n if (rowIndex != null) {\n virtualizer.scrollToIndex(rowIndex, { align: 'auto' });\n }\n }\n },\n onStateChange({ type, selectedItem: newSelectedItem, inputValue: newInputValue }) {\n switch (type) {\n case useCombobox.stateChangeTypes.InputChange:\n setInputValue(newInputValue || '');\n mode.onInputChange?.(newInputValue || '');\n break;\n case useCombobox.stateChangeTypes.InputKeyDownEnter:\n case useCombobox.stateChangeTypes.ItemClick:\n // A toggle changes selections, not the search query.\n // Handle select all option\n if (newSelectedItem && newSelectedItem.value === SELECT_ALL_VALUE) {\n handleSelectAllToggle();\n break;\n }\n\n // Handle regular multi-select logic\n if (newSelectedItem) {\n const isSelected = values.includes(newSelectedItem.value);\n if (isSelected) {\n removeSelectedItem(newSelectedItem);\n } else {\n addSelectedItem(newSelectedItem);\n }\n }\n break;\n default:\n break;\n }\n },\n stateReducer(state, actionAndChanges) {\n const { type, changes } = actionAndChanges;\n\n switch (type) {\n case useCombobox.stateChangeTypes.ItemClick:\n case useCombobox.stateChangeTypes.InputKeyDownEnter:\n // Keep menu open after selection and let Downshift manage highlighting\n return {\n ...changes,\n isOpen: true,\n inputValue: '', // Always keep input empty in multi-select mode\n highlightedIndex: state.highlightedIndex, // Not doing this resets the highlighted index to 0\n };\n case useCombobox.stateChangeTypes.InputBlur:\n // Prevent closing when focus moves to search input. Read `state.isOpen`,\n // not the outer `isOpen` const (temporal dead zone during this hook's own init).\n if (state.isOpen) {\n return {\n ...changes,\n isOpen: true, // Keep open, let search input onBlur handle external focus\n };\n }\n return changes;\n case useCombobox.stateChangeTypes.MenuMouseLeave:\n // Downshift clears the highlight (-1) when the pointer leaves the\n // menu, which the highlight-reset effect below then snaps back to\n // the first option. Keep the last highlighted option instead.\n return {\n ...changes,\n highlightedIndex: state.highlightedIndex,\n };\n case useCombobox.stateChangeTypes.InputClick:\n case useCombobox.stateChangeTypes.ToggleButtonClick:\n return changes;\n default:\n return changes;\n }\n },\n });\n\n const renderOption = useCallback(\n (option: ComboboxOption<T>, currentIndex: number) => {\n const isHighlighted = highlightedIndex === currentIndex;\n const isSelected = values.includes(option.value);\n\n // Handle select all option\n if (option.value === SELECT_ALL_VALUE) {\n return (\n <StyledMenuItem\n key='select-all'\n {...getItemProps({\n item: option,\n index: currentIndex,\n })}\n focused={isHighlighted}\n selected={false}\n aria-labelledby={`combobox-option-label-${currentIndex}`}\n $size={size}\n tabIndex={-1}\n >\n <Stack direction='horizontal' align='center' spacing={Spacing[2]}>\n <Checkbox\n checked={selectedState.allSelected}\n indeterminate={selectedState.indeterminate}\n tabIndex={-1}\n />\n <CheckboxLabel id={`combobox-option-label-${currentIndex}`} $size={size}>\n <OptionLabel>{option.label}</OptionLabel>\n </CheckboxLabel>\n </Stack>\n </StyledMenuItem>\n );\n }\n\n // Handle regular options\n return (\n <StyledMenuItem\n key={`${option.value}-${currentIndex}`}\n {...getItemProps({\n item: option,\n index: currentIndex,\n 'aria-selected': isSelected,\n })}\n focused={isHighlighted}\n selected={false} // Don't use selected styling for multi-select items\n aria-labelledby={`combobox-option-label-${currentIndex}`}\n $size={size}\n tabIndex={-1}\n >\n <Stack direction='horizontal' align='center' spacing={Spacing[2]}>\n <Checkbox checked={isSelected} tabIndex={-1} />\n <CheckboxLabel id={`combobox-option-label-${currentIndex}`} $size={size}>\n {option.labelStickerVariant ? (\n <Sticker variant={option.labelStickerVariant}>{option.label}</Sticker>\n ) : (\n <>\n <OptionLabel\n title={option.label}\n $labelStyle={option.PLEASE_DO_NOT_USE_labelFontStyle}\n >\n {option.label}\n </OptionLabel>\n {option.description && (\n <Description title={option.description}>{option.description}</Description>\n )}\n </>\n )}\n </CheckboxLabel>\n </Stack>\n </StyledMenuItem>\n );\n },\n [highlightedIndex, values, getItemProps, size, selectedState],\n );\n\n // Downshift owns the open state; embedded mode opens after mount so its\n // initial-focus effect cannot scroll the host page.\n const isMenuOpen = isOpen;\n\n const {\n isFooterHighlighted,\n footerActionId,\n showFooterAction,\n handleFooterKeyDown,\n clearFooterHighlight,\n } = useComboboxFooterAction({\n footerAction,\n isOptionsLoading,\n itemCount: navigableItems.length,\n isMenuOpen,\n inputValue: mode.query ?? inputValue,\n highlightedIndex,\n setHighlightedIndex,\n inputId: field.inputId,\n });\n\n // Handle Enter key to open menu when closed\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter' && !isMenuOpen) {\n openMenu();\n }\n },\n [isMenuOpen, openMenu],\n );\n\n // Calculate dropdown position for portal rendering\n const dropdownPosition = useDropdownPosition(\n portalContainerRef,\n isMenuOpen,\n embedded ? false : portal,\n );\n\n // Call onOpenChange when dropdown state changes\n useEffect(() => {\n mode.onMenuOpenChange(isMenuOpen);\n onOpenChange?.(isMenuOpen);\n }, [isMenuOpen, onOpenChange, mode.onMenuOpenChange]);\n\n // Reset highlighted index when filtering changes options. `MenuMouseLeave` is\n // neutralised in `stateReducer` so leaving the menu doesn't trigger this.\n // Skipped while the footer is highlighted so entering it (`highlightedIndex ===\n // -1`) isn't bounced straight back onto the first option.\n useEffect(() => {\n if (isMenuOpen && navigableItems.length > 0 && !isFooterHighlighted) {\n if (highlightedIndex === -1 || highlightedIndex >= navigableItems.length) {\n setHighlightedIndex(0);\n }\n }\n }, [navigableItems, isMenuOpen, highlightedIndex, isFooterHighlighted, setHighlightedIndex]);\n\n // Generate unique ID for SearchInput component\n const searchInputId = `${field.inputId}-search`;\n\n // Simple focus management for multi-select search input\n useLayoutEffect(() => {\n if (embedded && isMenuOpen && searchInputRef.current) {\n searchInputRef.current.focus({ preventScroll: true });\n }\n }, [embedded, isMenuOpen]);\n useEffect(() => {\n if (!embedded && isMenuOpen && searchInputRef.current) {\n // Focus search input when dropdown opens - downshift handles the rest\n searchInputRef.current.focus();\n }\n }, [embedded, isMenuOpen]);\n\n const handleSearchInputKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Footer action keyboard nav (arrow past the last option to reach it,\n // Enter to activate) is handled by the shared hook.\n if (handleFooterKeyDown(e)) {\n return;\n }\n\n // Handle arrow keys to navigate through options\n if (e.key === 'ArrowDown' && navigableItems.length > 0) {\n e.preventDefault();\n const nextIndex =\n highlightedIndex === -1 ? 0 : (highlightedIndex + 1) % navigableItems.length;\n setHighlightedIndex(nextIndex);\n }\n\n if (e.key === 'ArrowUp' && navigableItems.length > 0) {\n e.preventDefault();\n const prevIndex =\n highlightedIndex === -1\n ? navigableItems.length - 1\n : (highlightedIndex - 1 + navigableItems.length) % navigableItems.length;\n setHighlightedIndex(prevIndex);\n }\n\n if (e.key === 'Enter' && highlightedIndex >= 0 && navigableItems[highlightedIndex]) {\n e.preventDefault();\n const selectedItem = navigableItems[highlightedIndex];\n\n // Handle select all option\n if (selectedItem.value === SELECT_ALL_VALUE) {\n handleSelectAllToggle();\n return;\n }\n\n // Handle regular options\n const isSelected = values.includes(selectedItem.value);\n if (isSelected) {\n removeSelectedItem(selectedItem);\n } else {\n addSelectedItem(selectedItem);\n }\n }\n\n if (e.key === 'Escape') {\n clearFooterHighlight();\n closeMenu();\n // Restore focus to main input\n if (comboboxInputRef.current) {\n comboboxInputRef.current.focus();\n }\n }\n if (e.key === 'Tab') {\n if (isFooterHighlighted) {\n clearFooterHighlight();\n closeMenu();\n // Don't prevent default - let Tab continue to next element\n } else if (highlightedIndex >= 0 && navigableItems[highlightedIndex]) {\n closeMenu();\n // Don't prevent default - let Tab continue to next element\n }\n }\n },\n [\n navigableItems,\n highlightedIndex,\n setHighlightedIndex,\n handleFooterKeyDown,\n isFooterHighlighted,\n clearFooterHighlight,\n values,\n addSelectedItem,\n removeSelectedItem,\n closeMenu,\n comboboxInputRef,\n handleSelectAllToggle,\n ],\n );\n\n const handleOutsideClick = useCallback(\n (e: MouseEvent) => {\n if (\n !embedded &&\n isMenuOpen &&\n !(e.target as HTMLElement)?.closest('#combobox-dropdown-portal-wrapper')\n ) {\n closeMenu();\n }\n },\n [embedded, isMenuOpen, closeMenu],\n );\n\n useOutsideClick({\n ref: comboboxContainerRef,\n onOutsideClick: handleOutsideClick,\n });\n\n const externalTrigger = (() => {\n if (embedded || trigger == null || !isValidElement(trigger)) {\n return null;\n }\n const triggerProps = trigger.props as Record<string, unknown> & { disabled?: unknown };\n return cloneElement(\n trigger,\n getToggleButtonProps({\n ...triggerProps,\n disabled: field.disabled || Boolean(triggerProps.disabled),\n }) as Record<string, unknown>,\n );\n })();\n\n const handleSearchInputBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n if (!isMenuOpen) {\n return;\n }\n\n const relatedTarget = e.relatedTarget as HTMLElement | null;\n const staysInCombobox =\n relatedTarget != null &&\n (Boolean(comboboxContainerRef.current?.contains(relatedTarget)) ||\n Boolean(relatedTarget.closest('#combobox-dropdown-portal-wrapper')));\n\n if (!staysInCombobox) {\n if (!embedded) {\n closeMenu();\n }\n }\n },\n [embedded, isMenuOpen, closeMenu],\n );\n\n const searchInputAriaLabel = embedded ? 'Search options' : (ariaLabel ?? searchPlaceholder);\n\n // Embedded mode never renders the collapsed field input, leaving the\n // in-dropdown search input as the only element Downshift can bind its input\n // and dropdown refs to. Other modes bind them to the collapsed input instead\n // — binding both would leave Downshift tracking whichever rendered last.\n // The label goes through the getter so Downshift omits its own\n // `aria-labelledby`, which would otherwise point at a label this component\n // never renders.\n const searchInputDownshiftProps = embedded\n ? getInputProps(\n getDropdownProps({\n ref: searchInputRef,\n id: searchInputId,\n 'aria-label': searchInputAriaLabel,\n }),\n )\n : { ref: searchInputRef, id: searchInputId };\n\n return (\n <Container {...props} ref={comboboxContainerRef}>\n {embedded ? null : externalTrigger != null ? (\n externalTrigger\n ) : (\n <InputContainer>\n <MultiSelectComboboxInput\n {...getInputProps(\n getDropdownProps({\n ...props,\n ref: comboboxInputRef,\n id: field.inputId,\n placeholder: selectedItems.length === 0 ? placeholder : '',\n disabled: field.disabled,\n 'aria-label': ariaLabel,\n 'aria-labelledby': labelId,\n 'aria-describedby':\n [field.helperTextId, field.hasWarning ? field.warningTextId : null]\n .filter(Boolean)\n .join(' ') || undefined,\n 'aria-errormessage': field.hasError ? field.errorTextId : undefined,\n 'aria-invalid': field.hasError,\n 'aria-required': required || undefined,\n preventKeyAction: isMenuOpen,\n onKeyDown: handleKeyDown,\n }),\n )}\n size={size}\n $isOpen={isMenuOpen}\n hasWarning={field.hasWarning}\n hasError={field.hasError}\n value='' // Always empty in multi-select mode\n />\n {/* Hidden measurement container - always renders all items for accurate measurements */}\n {truncate && selectedItems.length > 0 && (\n <HiddenMeasurementContainer aria-hidden='true'>\n {selectedItems.map((item, index) => {\n const selectedOption = item;\n const stickerVariant = selectedOption?.labelStickerVariant || 'grey';\n return (\n <div\n key={`measurement-${item.value}-${index}`}\n ref={(el: HTMLDivElement | null) =>\n (measurementStickerRefs.current[index] = el)\n }\n >\n <Sticker variant={stickerVariant} disabled={field.disabled}>\n {item.label}\n </Sticker>\n </div>\n );\n })}\n <div ref={measurementTruncatorRef as React.RefObject<HTMLDivElement>}>\n <TruncatorSticker variant='grey' disabled={field.disabled}>\n &#43;{selectedItems.length - visibleCount}\n </TruncatorSticker>\n </div>\n </HiddenMeasurementContainer>\n )}\n {/* Show selected items as stickers */}\n <SelectedItemsContainer $size={size} $truncate={truncate} ref={selectedItemsContainerRef}>\n {truncate ? (\n <TruncatedItemsWrapper>\n {selectedItems.slice(0, visibleCount).map((item, index) => {\n const { ref: _ref, ...stickerProps } = getSelectedItemProps({\n selectedItem: item,\n index,\n });\n const selectedOption = item;\n const stickerVariant = selectedOption?.labelStickerVariant || 'grey';\n\n return (\n <TruncatedSticker\n key={`selected-${item.value}-${index}`}\n {...stickerProps}\n variant={stickerVariant}\n disabled={field.disabled}\n $isOnlyItem={visibleCount === 1}\n >\n {item.label}\n </TruncatedSticker>\n );\n })}\n {visibleCount < selectedItems.length && (\n <TruncatorSticker variant='grey' disabled={field.disabled}>\n &#43;{selectedItems.length - visibleCount}\n </TruncatorSticker>\n )}\n </TruncatedItemsWrapper>\n ) : (\n selectedItems.map((item, index) => {\n const { ref, ...stickerProps } = getSelectedItemProps({\n selectedItem: item,\n index,\n });\n const selectedOption = item;\n const stickerVariant = selectedOption?.labelStickerVariant || 'grey';\n return (\n <Sticker\n key={`selected-${item.value}-${index}`}\n {...stickerProps}\n variant={stickerVariant}\n onDismiss={(e) => {\n // Without this, clicking dismiss doesn't work due to event bubbling\n e.stopPropagation();\n removeSelectedItem(item);\n }}\n dismissButtonProps={{\n tabIndex: -1,\n }}\n disabled={field.disabled}\n tabIndex={-1}\n >\n {item.label}\n </Sticker>\n );\n })\n )}\n </SelectedItemsContainer>\n\n {selectedItems.length > 0 ? (\n <CaretButton\n id={`${field.inputId}__clear-all`}\n onClick={reset}\n size={size}\n disabled={field.disabled}\n aria-label='Clear all selected items'\n >\n <CircleXInverseIcon />\n </CaretButton>\n ) : (\n <CaretButton\n {...getToggleButtonProps({\n ref: caretButtonRef,\n })}\n size={size}\n disabled={field.disabled}\n aria-label={`${isMenuOpen ? 'Close' : 'Open'} options menu`}\n aria-haspopup='listbox'\n >\n <CaretDownIcon />\n </CaretButton>\n )}\n </InputContainer>\n )}\n\n <DropdownPortalWrapper portal={embedded ? false : portal}>\n <DropdownContainer\n $isOpen={isMenuOpen}\n $portal={embedded ? false : portal}\n $embedded={embedded}\n $top={dropdownPosition.top}\n $left={dropdownPosition.left}\n $width={dropdownPosition.width}\n $minWidth={externalTrigger ? EXTERNAL_TRIGGER_DROPDOWN_MIN_WIDTH : undefined}\n {...getMenuProps()}\n aria-multiselectable='true'\n >\n {/* Fixed search input */}\n {(embedded || isMenuOpen) && (\n <SearchInputContainer $embedded={embedded}>\n <InputGroup leftIcon={embedded ? undefined : <SearchIcon />} size={size}>\n <SearchInput\n {...mode.getQueryInputProps(\n {\n ...searchInputDownshiftProps,\n value: inputValue,\n onChange: (event) => {\n setInputValue(event.target.value);\n mode.onInputChange?.(event.target.value);\n },\n },\n true,\n () => setHighlightedIndex(0),\n )}\n // Declared after the spread so they replace Downshift's\n // equivalents rather than composing with them: multi-select\n // owns the input value and hand-rolls arrow/Enter navigation,\n // and letting Downshift also handle those keys would move the\n // highlight twice per keypress.\n $embedded={embedded}\n placeholder={searchPlaceholder}\n onKeyDown={handleSearchInputKeyDown}\n onBlur={handleSearchInputBlur}\n disabled={field.disabled}\n aria-label={searchInputAriaLabel}\n aria-activedescendant={\n isFooterHighlighted\n ? footerActionId\n : highlightedIndex >= 0\n ? getOptionId(highlightedIndex)\n : undefined\n }\n size={size}\n />\n </InputGroup>\n </SearchInputContainer>\n )}\n <MultiSelectScrollableMenuList\n $embedded={embedded}\n tabIndex={-1}\n ref={scrollableListRef}\n onScroll={mode.onScroll}\n >\n {isMenuOpen && (\n <>\n {isOptionsLoading ? (\n <LoadingContainer>\n <Spinner size='md' />\n </LoadingContainer>\n ) : navigableItems.length > 0 ? (\n renderOptionsWithGroups({\n options: optionsToRender,\n filteredOptions: navigableItems,\n renderOption,\n virtualizer: virtualize ? virtualizer : undefined,\n virtualRows: virtualize ? virtualRows : undefined,\n })\n ) : (\n <EmptyState role='status' aria-live='polite' size={size}>\n {emptyStateMessage}\n </EmptyState>\n )}\n {mode.loadingMore}\n {showFooterAction && footerAction && (\n <FooterActionRow\n action={footerAction}\n size={size}\n id={footerActionId}\n isHighlighted={isFooterHighlighted}\n />\n )}\n </>\n )}\n </MultiSelectScrollableMenuList>\n </DropdownContainer>\n </DropdownPortalWrapper>\n </Container>\n );\n}\n\nexport const ComboboxMultiSelect = forwardRef(ComboboxMultiSelectComponent) as <T = string>(\n props: (ComboboxMultiSelectProps<T> | ComboboxServerMultiSelectProps<T>) & {\n ref?: React.Ref<HTMLInputElement>;\n },\n) => React.ReactElement;\n\nexport default ComboboxMultiSelect;\n","import { useCombobox } from 'downshift';\nimport Fuse from 'fuse.js';\nimport {\n cloneElement,\n forwardRef,\n Fragment,\n isValidElement,\n type ReactElement,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\nimport { ArrowLeftIcon, CaretDownIcon, ChevronRightIcon, SearchIcon } from '@persona/icons';\n\nimport {\n CaretButton,\n type ComboboxBaseProps,\n type ComboboxServerBaseProps,\n ComboboxInput,\n type ComboboxOption,\n type ComboboxOptionGroup,\n containsNestedGroup,\n Container,\n Description,\n DropdownContainer,\n DropdownPortalWrapper,\n EmptyState,\n flattenLeafOptions,\n FooterActionRow,\n getNavigableItemsAtLevel,\n getOptionsAtPath,\n useComboboxServerMode,\n InputContainer,\n isOptionGroup,\n LoadingContainer,\n type NavigableItem,\n OptionLabel,\n renderOptionsWithGroups,\n ScrollableMenuList,\n SearchInput,\n SearchInputContainer,\n sortDisabledOptionsLast,\n useDropdownPosition,\n} from '#src/components/Combobox/ComboboxBase';\nimport { useComboboxFooterAction } from '#src/components/Combobox/useComboboxFooterAction';\nimport useFormField from '#src/components/FormControl/useFormField';\nimport { InputGroup } from '#src/components/Input';\nimport {\n IconContainer as MenuItemIconContainer,\n MenuHeading,\n MenuItem,\n} from '#src/components/Menu';\nimport Spinner from '#src/components/Spinner/Spinner';\nimport Sticker from '#src/components/Sticker';\nimport { Tooltip } from '#src/components/Tooltip';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { Z_INDICES } from '#src/lib/zindex';\nimport type { InputSizes } from '#src/mixins/input';\n\ninterface ComboboxSingleSelectionProps<T> {\n /**\n * Single-select mode\n */\n multiple?: false;\n\n /**\n * Selected value\n */\n value?: T | null;\n\n /**\n * Callback when selection changes\n */\n onChange?: (value: T | null) => void;\n optionDisabledReason?: (option: ComboboxOption<T>) => string | undefined;\n\n // Explicitly exclude multi-select props to prevent usage\n values?: never;\n onValuesChange?: never;\n searchPlaceholder?: never;\n truncate?: never;\n selectAll?: never;\n stableOptionOrder?: never;\n}\n\nexport interface ComboboxSingleSelectProps<T = string>\n extends ComboboxBaseProps<T>, ComboboxSingleSelectionProps<T> {}\nexport interface ComboboxServerSingleSelectProps<T = string>\n extends ComboboxServerBaseProps<T>, ComboboxSingleSelectionProps<T> {}\n\nexport const StyledMenuItem = styled(MenuItem)<{ size?: InputSizes }>`\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: ${Spacing[1]};\n min-width: 0; /* Allow content to shrink below natural size */\n width: 100%; /* Ensure full width of dropdown */\n box-sizing: border-box;\n\n /* Force all children to respect the container width */\n > * {\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n }\n\n /* MenuItem drops pointer events when disabled; keep them so the reason tooltip opens on hover.\n \\`stateReducer\\` refuses a click on a disabled option, so it still can't be picked. */\n &[aria-disabled='true'] {\n pointer-events: auto;\n }\n`;\n\n/** Room the reason tooltip needs beside its row: its 250px max width, 8px offset and 8px margin. */\nconst REASON_TOOLTIP_SPACE = 266;\n\n/**\n * A disabled option's reason, shown on hover. It opens to the right of the row, or above it when\n * the row reaches too close to the right edge of the screen (an embedded or narrow menu).\n */\nfunction DisabledReasonTooltip({ reason, children }: { reason: string; children: ReactElement }) {\n const [side, setSide] = useState<'right' | 'top'>('right');\n return (\n <Tooltip\n trigger={children}\n triggerProps={{\n onPointerEnter: (event) => {\n const { right } = event.currentTarget.getBoundingClientRect();\n setSide(window.innerWidth - right >= REASON_TOOLTIP_SPACE ? 'right' : 'top');\n },\n }}\n side={side}\n align={side === 'top' ? 'start' : 'center'}\n collisionPadding={8}\n hideWhenDetached\n size='sm'\n zIndex={Z_INDICES.modalDropdownTooltip}\n interactive={false}\n >\n {reason}\n </Tooltip>\n );\n}\n\nconst ParentMenuItem = styled(MenuItem)<{ size?: InputSizes }>`\n ${MenuItemIconContainer} {\n margin-right: 0;\n }\n\n > ${MenuItemIconContainer}:first-child:not(:last-child) {\n margin-right: ${Spacing[2]};\n }\n`;\n\nconst ParentChevron = styled.span`\n display: inline-flex;\n align-items: center;\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.BorderIconSecondary)};\n`;\n\n// Minimum dropdown width when an external `trigger` is supplied —\n// keeps the dropdown readable even when the trigger is icon-sized.\nconst EXTERNAL_TRIGGER_DROPDOWN_MIN_WIDTH = '240px';\n\nconst SingleSelectScrollableMenuList = styled(ScrollableMenuList)<{ $embedded?: boolean }>`\n ${({ $embedded }) =>\n $embedded &&\n css`\n padding: 0;\n `}\n`;\n\n// Back-navigation affordance shown at the top of the dropdown whenever\n// the user has descended into a submenu. Click ascends one level; the\n// ← keyboard arrow does the same. The Back row is intentionally NOT\n// part of downshift's `items` list so it doesn't interfere with the\n// option highlight/keyboard nav across the level's real options.\nconst BackRow = styled.button<{ $size?: InputSizes }>`\n display: flex;\n align-items: center;\n gap: ${({ $size }) => ($size === 'sm' ? Spacing[1] : Spacing[2])};\n width: 100%;\n padding: ${({ $size }) => ($size === 'sm' ? `${Spacing[1]} ${Spacing[2]}` : Spacing[2])};\n background: transparent;\n border: 0;\n cursor: pointer;\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n ${({ $size }) => ($size === 'sm' ? Typography.TextSmall : Typography.TextMedium)};\n\n svg {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n }\n`;\n\nconst StickerDisplay = styled(Sticker)`\n position: absolute;\n left: ${Spacing[2]};\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n z-index: 1;\n`;\n\nconst StickerComboboxInput = styled(ComboboxInput)`\n /* Hide text when sticker is shown */\n color: transparent;\n caret-color: transparent;\n`;\n\nfunction ComboboxSingleSelectComponent<T = string>(\n componentProps: ComboboxSingleSelectProps<T> | ComboboxServerSingleSelectProps<T>,\n ref: React.Ref<HTMLInputElement>,\n) {\n const {\n size = 'md',\n options: optionsProp,\n isOptionsLoading,\n filterMode: _filterMode,\n selectedOptions: _selectedOptions,\n query: _query,\n onQueryChange: _onQueryChange,\n onScrollEnd: _onScrollEnd,\n isLoadingMore: _isLoadingMore,\n value,\n onChange,\n optionDisabledReason,\n onInputChange: _onInputChange,\n placeholder = 'Select an option...',\n emptyStateMessage = 'No options found',\n disabled = false,\n hasWarning,\n hasError,\n required,\n id,\n labelId,\n 'aria-label': ariaLabel,\n onOpenChange,\n portal = false,\n portalContainerRef: externalPortalContainerRef,\n trigger,\n embedded = false,\n footerAction,\n ...props\n } = { onScrollEnd: undefined, isLoadingMore: undefined, ...componentProps };\n // Disabled options list after the enabled ones, keeping their order and their section.\n const clientOptions = useMemo(\n () =>\n optionDisabledReason == null\n ? optionsProp\n : sortDisabledOptionsLast(optionsProp, (option) => optionDisabledReason(option) != null),\n [optionsProp, optionDisabledReason],\n );\n\n const selectedValues = useMemo(() => (value == null ? [] : [value]), [value]);\n const mode = useComboboxServerMode(componentProps, selectedValues, clientOptions);\n const options = mode.options;\n const field = useFormField({ hasWarning, hasError, disabled, inputId: id });\n const [inputValue, setInputValue] = useState('');\n // Keep track of dropdown state to avoid filtering options when updating value while dropdown is open\n const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n // Path of nested-group labels the user has descended into. Empty\n // when the dropdown is at the root. Reset on close so the next\n // open always lands at the top of the tree.\n const [navigationPath, setNavigationPath] = useState<string[]>([]);\n const comboboxInputRef = useRef<HTMLInputElement>(null);\n const internalContainerRef = useRef<HTMLDivElement>(null);\n // Label committed by the user this interaction, held until the controlled\n // `value` prop catches up. Without it, the closed-state sync effect below\n // repaints the previous selection's label for a frame on every commit.\n const committedLabelRef = useRef<string | null>(null);\n const lastValueRef = useRef(value);\n\n useEffect(() => {\n setIsDropdownOpen(embedded);\n }, [embedded]);\n\n if (lastValueRef.current !== value) {\n lastValueRef.current = value;\n committedLabelRef.current = null; // parent acknowledged (or overrode) — the prop wins\n }\n\n // Use external portalContainerRef if provided, otherwise use internal ref for portal positioning\n const portalContainerRef = externalPortalContainerRef || internalContainerRef;\n\n // Expose methods to parent component\n useImperativeHandle(\n ref,\n () => ({\n ...comboboxInputRef.current!,\n }),\n [],\n );\n\n // Active query — drives the search vs. nested mode switch. A non-empty\n // query flattens the tree and shows all leaves matching the query;\n // an empty query shows the level the navigation path resolves to.\n const trimmedQuery = inputValue.trim();\n const isSearching = trimmedQuery !== '';\n\n // The items visible at the current navigation depth: either the\n // original `options` at the root, or the contents of the nested\n // group `navigationPath` resolves to. Returns `[]` if the path is\n // stale (e.g. the group was removed from `options` mid-drill-down).\n const nestedOptions = useMemo(\n () => getOptionsAtPath(options, navigationPath),\n [options, navigationPath],\n );\n // True when at least one nested group exists anywhere in the tree.\n // Nested-navigation behavior (Back row, chevron, search-flattens-tree)\n // only activates for trees that actually use the new feature; legacy\n // flat or grouped option lists keep their original render unchanged.\n const hasNestedGroups = useMemo(() => containsNestedGroup(options), [options]);\n\n // Navigable items at the current nav level: leaves and nested groups\n // interleaved, in document order. Inline section-header groups are\n // walked through transparently (their leaves surface at this level).\n // This is the downshift `items` list in browse mode, and the order\n // matches what `renderNestedLevel` paints below.\n const navigableItems = useMemo(() => getNavigableItemsAtLevel(nestedOptions), [nestedOptions]);\n\n // Search-mode hits: every leaf in the tree (groups are unselectable).\n // Built only when the tree is nested; legacy flat/grouped lists keep\n // their original search render.\n const searchableLeaves = useMemo(() => {\n if (!isSearching || !hasNestedGroups) {\n return [] as ComboboxOption<T>[];\n }\n return flattenLeafOptions(options).map(({ option }) => option);\n }, [options, isSearching, hasNestedGroups]);\n\n // Separate Fuse index for nested-mode search that ALSO matches against\n // each leaf's ancestor labels — so typing a parent's label (e.g.\n // \"Business Account\") returns all of that parent's children. The\n // ancestor list is a search-only field carried alongside the option\n // (not on the option itself), so the leaf's rendered `description`\n // stays exactly what the consumer supplied.\n const searchableLeafFuse = useMemo(() => {\n if (!isSearching || !hasNestedGroups) {\n return null;\n }\n const entries = flattenLeafOptions(options).map(({ option, breadcrumb }) => ({\n option,\n label: String(option.label),\n description: option.description,\n keywords: option.keywords,\n ancestors: breadcrumb.join(' '),\n }));\n return new Fuse(entries, {\n shouldSort: false,\n threshold: 0,\n ignoreLocation: true,\n minMatchCharLength: 1,\n keys: ['label', 'description', 'keywords', 'ancestors'],\n });\n }, [options, isSearching, hasNestedGroups]);\n\n // The source the visible dropdown renders from. Nested-browse uses\n // whatever the navigation path resolves to. Search mode falls back to\n // the original `options` for flat/grouped lists (group headers stay\n // visible) and uses the flat-leaves overlay for nested trees.\n const renderSource = isSearching ? (hasNestedGroups ? searchableLeaves : options) : nestedOptions;\n\n // Filter the render source's LEAVES by the query. Nested+searching\n // uses the ancestor-aware Fuse so parent-label matches still surface\n // children; every other case (browse mode, flat/grouped search) goes\n // through the shared client filter supplied by the mode hook.\n const standardFilteredOptions = useMemo(\n () => mode.filterOptions(renderSource, inputValue),\n [mode.filterOptions, renderSource, inputValue],\n );\n const filteredOptions = useMemo(() => {\n if (!isSearching || !hasNestedGroups || searchableLeafFuse == null) {\n return standardFilteredOptions;\n }\n if (inputValue === '') {\n return searchableLeaves;\n }\n return Array.from(\n new Set(searchableLeafFuse.search(inputValue).map(({ item }) => item.option)).values(),\n );\n }, [\n isSearching,\n hasNestedGroups,\n searchableLeafFuse,\n inputValue,\n searchableLeaves,\n standardFilteredOptions,\n ]);\n\n // Downshift `items` list. In search mode every item is a leaf\n // (groups never appear in search results). In browse mode the list\n // is `navigableItems` — leaves + nested groups, in render order —\n // so the highlightedIndex tracks both selectable and navigable rows.\n const downshiftItems = useMemo<NavigableItem<T>[]>(() => {\n if (isSearching) {\n return filteredOptions.map((option) => ({ kind: 'leaf', option }) as const);\n }\n // Browse-mode filter: navigable items whose leaf option is still\n // in `filteredOptions` (nested groups always pass through — they\n // aren't filtered by query because we'd flip to search mode).\n const filteredValues = new Set(filteredOptions.map((option) => option.value));\n return navigableItems.filter(\n (item) => item.kind === 'group' || filteredValues.has(item.option.value),\n );\n }, [isSearching, filteredOptions, navigableItems]);\n const downshiftNodes = useMemo(\n () => new Set(downshiftItems.map((item) => (item.kind === 'group' ? item.group : item.option))),\n [downshiftItems],\n );\n\n // Lookup table for resolving the selected option's label when the\n // dropdown is closed. Walks the full tree so values stored deep in a\n // submenu still render their label in the input.\n const selectedOption = mode.selectedItems[0] ?? null;\n\n // Downshift's `selectedItem` is a NavigableItem in nested mode. The\n // selected leaf is wrapped here so `itemToString` and the input's\n // displayed value resolve to the right label.\n //\n // Memoize on the committed value + label, NOT the `selectedOption` object\n // identity. Consumers that rebuild `options` on `onInputChange` produce a\n // fresh option object on every keystroke; keying off identity would make\n // Downshift treat the controlled `selectedItem` as changed and reset the\n // search input back to the selected label, clobbering an in-progress query.\n // The wrapper only needs to change when the committed selection does, and\n // Downshift only reads its label via `itemToString`.\n const selectedNavigableItem = useMemo<NavigableItem<T> | null>(\n () => (selectedOption ? { kind: 'leaf', option: selectedOption } : null),\n [selectedOption?.value, selectedOption?.label],\n );\n\n const itemToString = useCallback((item: NavigableItem<T> | null) => {\n if (!item) {\n return '';\n }\n return item.kind === 'leaf' ? item.option.label : item.group.label;\n }, []);\n\n const handleAscend = useCallback(() => {\n setNavigationPath((prev) => (prev.length > 0 ? prev.slice(0, -1) : prev));\n setInputValue('');\n }, []);\n\n const isItemDisabled = useCallback(\n (item: NavigableItem<T> | undefined) =>\n item?.kind === 'leaf' && optionDisabledReason?.(item.option) != null,\n [optionDisabledReason],\n );\n\n // Single-select combobox hooks\n const {\n isOpen,\n getToggleButtonProps,\n getMenuProps,\n getInputProps,\n getItemProps,\n highlightedIndex,\n setHighlightedIndex,\n openMenu,\n } = useCombobox<NavigableItem<T>>({\n items: downshiftItems,\n itemToString,\n itemToKey: (item) => (item?.kind === 'leaf' ? mode.itemToKey(item.option) : item?.group.label),\n // Disabled options stay reachable with the arrow keys (as the APG listbox pattern allows), so a\n // screen reader announces their reason; `stateReducer` refuses to select them.\n isOpen: embedded ? isDropdownOpen : undefined,\n selectedItem: isDropdownOpen ? null : selectedNavigableItem,\n inputValue: isDropdownOpen ? (mode.query ?? inputValue) : inputValue,\n onInputValueChange({ inputValue: newInputValue, type }) {\n // Downshift resets the text to match the controlled `selectedItem`, which\n // is null while the menu is open. Keep what the user typed to open it.\n if (\n type === useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem &&\n isDropdownOpen &&\n !embedded\n ) {\n return;\n }\n // Only the user emptying the input (typing, or Escape on a closed menu)\n // clears the value, not text Downshift resets or re-reports on its own.\n // Clearing an open server query must not clear the selection. Deleting a closed\n // selected label (or Escape on the closed field) retains the existing clear behavior.\n const isUserEdit =\n (type === useCombobox.stateChangeTypes.InputChange &&\n (mode.query === undefined || !isDropdownOpen)) ||\n type === useCombobox.stateChangeTypes.InputKeyDownEscape;\n if (newInputValue === '' && isUserEdit && !embedded && trigger == null) {\n onChange?.(null);\n }\n setInputValue(newInputValue || '');\n mode.onInputChange?.(newInputValue || '');\n },\n onIsOpenChange({ isOpen: newIsOpen }) {\n // Embedded menus stay controlled open; client input behavior remains unchanged.\n if (embedded) {\n return;\n }\n setIsDropdownOpen(newIsOpen);\n if (newIsOpen) {\n if (selectedOption || committedLabelRef.current != null) {\n setInputValue('');\n }\n } else {\n setInputValue(committedLabelRef.current ?? selectedOption?.label ?? '');\n }\n },\n // Groups navigate in their mouse/keyboard handlers, not through Downshift's\n // selection transition. Only leaves commit a consumer value here.\n onSelectedItemChange: ({ selectedItem: newSelectedItem }) => {\n if (newSelectedItem == null || newSelectedItem.kind !== 'leaf') {\n return;\n }\n const leaf = newSelectedItem.option;\n if (optionDisabledReason?.(leaf) != null) {\n return;\n }\n committedLabelRef.current = leaf.label;\n onChange?.(leaf.value);\n setInputValue(leaf.label);\n },\n stateReducer(state, actionAndChanges) {\n const { changes, type } = actionAndChanges;\n\n switch (type) {\n case useCombobox.stateChangeTypes.InputBlur:\n // Close menu on blur but don't select highlighted item\n return {\n ...changes,\n selectedItem: state.selectedItem, // Keep current selection unchanged\n };\n case useCombobox.stateChangeTypes.MenuMouseLeave:\n // Downshift clears the highlight (-1) when the pointer leaves the\n // menu, which our highlight effect then snaps back to the first\n // option. Keep the last highlighted option instead.\n return {\n ...changes,\n highlightedIndex: state.highlightedIndex,\n };\n case useCombobox.stateChangeTypes.ItemClick:\n case useCombobox.stateChangeTypes.InputKeyDownEnter: {\n // Keep this reducer pure: React 18 may replay it when a quick click\n // overlaps a hover update. Group handlers own navigation; this guard\n // only preserves selection/open state if Downshift reports a group.\n const candidate = changes.selectedItem;\n if (candidate?.kind === 'leaf' && optionDisabledReason?.(candidate.option) != null) {\n return state;\n }\n if (candidate && candidate.kind === 'group') {\n return {\n ...changes,\n selectedItem: state.selectedItem, // preserve null in nested mode\n isOpen: true, // descent never closes the dropdown\n };\n }\n return changes;\n }\n default:\n return changes;\n }\n },\n });\n\n const handleDescend = useCallback(\n (groupLabel: string) => {\n setNavigationPath((prev) => [...prev, groupLabel]);\n setInputValue('');\n // A parent index can also be valid in the children. Let the highlight\n // effect choose the new level's first enabled item, not that stale index.\n setHighlightedIndex(-1);\n },\n [setHighlightedIndex],\n );\n\n // Reset navigation path whenever the dropdown closes so the next open\n // always starts at the root. Without this the user re-opens the\n // dropdown deep in a submenu they were previously browsing, which\n // surprises both the keyboard-search and mouse-driven re-entry flows.\n useEffect(() => {\n if (!isOpen && !embedded && navigationPath.length > 0) {\n setNavigationPath([]);\n }\n }, [embedded, isOpen, navigationPath.length]);\n\n const renderLeaf = useCallback(\n (option: ComboboxOption<T>, currentIndex: number) => {\n const isHighlighted = highlightedIndex === currentIndex;\n const isSelected = selectedOption?.value === option.value;\n const disabledReason = optionDisabledReason?.(option);\n const descriptionId = `${field.inputId}-disabled-option-${currentIndex}`;\n const itemProps = getItemProps({\n item: { kind: 'leaf', option } as NavigableItem<T>,\n index: currentIndex,\n // Override aria-selected to be true if the option is selected downshift has an open issue related to this https://github.com/downshift-js/downshift/issues/935\n 'aria-selected': isSelected,\n 'aria-disabled': disabledReason != null ? true : undefined,\n });\n\n const labelContent = option.labelStickerVariant ? (\n <Sticker variant={option.labelStickerVariant}>{option.label}</Sticker>\n ) : (\n <>\n <OptionLabel title={option.label} $labelStyle={option.PLEASE_DO_NOT_USE_labelFontStyle}>\n {option.label}\n </OptionLabel>\n {option.description && (\n <Description title={option.description}>{option.description}</Description>\n )}\n </>\n );\n\n const key = `leaf-${String(option.value)}-${currentIndex}`;\n const item = (\n <StyledMenuItem\n key={key}\n {...itemProps}\n disabled={disabledReason != null}\n aria-describedby={disabledReason != null ? descriptionId : undefined}\n focused={isHighlighted}\n selected={isSelected}\n size={size}\n tabIndex={-1}\n >\n {labelContent}\n {/* `hidden` keeps the reason out of the option's name; `aria-describedby` still reads it. */}\n {disabledReason != null && (\n <span id={descriptionId} hidden>\n {disabledReason}\n </span>\n )}\n </StyledMenuItem>\n );\n return disabledReason == null ? (\n item\n ) : (\n <DisabledReasonTooltip key={key} reason={disabledReason}>\n {item}\n </DisabledReasonTooltip>\n );\n },\n [highlightedIndex, selectedOption, getItemProps, size, optionDisabledReason, field.inputId],\n );\n\n // Nested-group rows render with a trailing chevron in the MenuItem's\n // built-in `suffixIcon` slot — the DS layout owns the right-alignment\n // + spacing so we don't have to fight the `flex-direction: column` +\n // `> * { width: 100% }` rules baked into `StyledMenuItem`.\n // `stretchLabel` makes the label take the available row width so the\n // chevron sits flush against the right edge. `aria-haspopup` tells AT\n // that activating this row opens a submenu instead of committing a\n // value. Keep Downshift's registration, hover, mouse-down and ARIA props,\n // but replace its selection click with one event-driven navigation action.\n const renderNestedGroupRow = useCallback(\n (group: ComboboxOptionGroup<T>, currentIndex: number) => {\n const isHighlighted = highlightedIndex === currentIndex;\n const itemProps = getItemProps({\n item: { kind: 'group', group } as NavigableItem<T>,\n index: currentIndex,\n });\n return (\n <ParentMenuItem\n key={`group-${group.label}-${currentIndex}`}\n {...itemProps}\n onClick={() => handleDescend(group.label)}\n aria-haspopup='menu'\n focused={isHighlighted}\n prefixIcon={group.prefixIcon}\n size={size}\n tabIndex={-1}\n stretchLabel\n suffixIcon={\n <ParentChevron aria-hidden='true'>\n <ChevronRightIcon />\n </ParentChevron>\n }\n >\n <OptionLabel title={group.label}>{group.label}</OptionLabel>\n {group.description && (\n <Description title={group.description}>{group.description}</Description>\n )}\n </ParentMenuItem>\n );\n },\n [highlightedIndex, getItemProps, size, handleDescend],\n );\n\n // Browse-mode renderer for nested-nav trees. Walks the items at the\n // current navigation level, interleaving leaves (via `renderLeaf`),\n // nested-group nav rows (via `renderNestedGroupRow`), and inline\n // section headers (`MenuHeading`). `navIndex` advances in lockstep\n // with `downshiftItems` so highlightedIndex maps cleanly to what\n // gets painted.\n const renderNestedLevel = useCallback(\n (items: typeof nestedOptions) => {\n let navIndex = -1;\n const walk = (\n node: ComboboxOption<T> | ComboboxOptionGroup<T>,\n key: string,\n ): React.ReactNode => {\n if (isOptionGroup(node)) {\n if (node.nested) {\n // Only render if the node is in the filtered downshift\n // items list (browse mode keeps groups; search mode never\n // reaches this code path).\n if (!downshiftNodes.has(node)) {\n return null;\n }\n navIndex++;\n return <Fragment key={key}>{renderNestedGroupRow(node, navIndex)}</Fragment>;\n }\n // Inline section header: render header + walk children. Skip\n // entirely if no children would render (keeps the header from\n // floating above nothing).\n const childNodes: React.ReactNode[] = [];\n for (let i = 0; i < node.options.length; i++) {\n const rendered = walk(node.options[i]!, `${key}-${i}`);\n if (rendered != null) {\n childNodes.push(rendered);\n }\n }\n if (childNodes.length === 0) {\n return null;\n }\n return (\n <Fragment key={key}>\n <MenuHeading>{node.label}</MenuHeading>\n {childNodes}\n </Fragment>\n );\n }\n if (!downshiftNodes.has(node)) {\n return null;\n }\n navIndex++;\n return renderLeaf(node, navIndex);\n };\n return items.map((item, idx) => walk(item, `item-${idx}`));\n },\n [downshiftNodes, renderLeaf, renderNestedGroupRow],\n );\n\n // Adapter wrapping `renderLeaf` for the legacy `renderOptionsWithGroups`\n // signature — the shared multi/single search-mode renderer expects\n // `(ComboboxOption<T>, flatIndex) => ReactNode`.\n const renderOption = useCallback(\n (option: ComboboxOption<T>, currentIndex: number) => renderLeaf(option, currentIndex),\n [renderLeaf],\n );\n\n // Downshift owns the open state; embedded mode opens after mount so its\n // initial-focus effect cannot scroll the host page.\n const isMenuOpen = isOpen;\n useLayoutEffect(() => {\n if (embedded && isMenuOpen && comboboxInputRef.current) {\n comboboxInputRef.current.focus({ preventScroll: true });\n }\n }, [embedded, isMenuOpen]);\n const dropdownPosition = useDropdownPosition(\n portalContainerRef,\n isMenuOpen,\n embedded ? false : portal,\n );\n\n // The menu opens on the first enabled option; the arrow keys reach every row after that.\n const firstEnabledIndex = useMemo(\n () => downshiftItems.findIndex((item) => !isItemDisabled(item)),\n [downshiftItems, isItemDisabled],\n );\n\n const { isFooterHighlighted, footerActionId, showFooterAction, handleFooterKeyDown } =\n useComboboxFooterAction({\n footerAction,\n isOptionsLoading,\n itemCount: downshiftItems.length,\n firstNavigableIndex: downshiftItems.length > 0 ? 0 : -1,\n isMenuOpen,\n inputValue: mode.query ?? inputValue,\n highlightedIndex,\n setHighlightedIndex,\n inputId: field.inputId,\n });\n\n // Keyboard:\n // - Enter on a closed input opens the menu (existing behavior)\n // - ArrowDown past the last option highlights the footer action; Enter\n // activates it; ArrowUp returns to the list (handled by the footer hook,\n // works in search mode too)\n // - Right arrow on a highlighted parent option descends\n // - Left arrow at the start of the input (i.e. not text-navigating\n // within the query) ascends one level, when not at the root\n //\n // Nested arrow-nav (Right/Left) is nested-mode-only — search mode bypasses it\n // so the arrow keys retain their normal text-caret semantics in the query.\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter' && !isMenuOpen) {\n openMenu();\n return;\n }\n if (!isMenuOpen) {\n return;\n }\n if (handleFooterKeyDown(event)) {\n return;\n }\n if (isSearching) {\n return;\n }\n if (event.key === 'Enter' || event.key === 'ArrowRight') {\n const highlighted = downshiftItems[highlightedIndex];\n if (highlighted?.kind === 'group') {\n event.preventDefault();\n if (event.key === 'Enter') {\n event.stopPropagation();\n }\n // The same escape hatch used by the footer: do not also dispatch a\n // Downshift selection action for this navigation-only key event.\n const nativeEvent = event.nativeEvent as KeyboardEvent & {\n preventDownshiftDefault?: boolean;\n };\n nativeEvent.preventDownshiftDefault = true;\n handleDescend(highlighted.group.label);\n }\n return;\n }\n if (event.key === 'ArrowLeft' && navigationPath.length > 0) {\n const input = event.currentTarget;\n const caretAtStart = (input.selectionStart ?? 0) === 0 && (input.selectionEnd ?? 0) === 0;\n if (caretAtStart) {\n event.preventDefault();\n handleAscend();\n }\n }\n },\n [\n isMenuOpen,\n isSearching,\n handleFooterKeyDown,\n downshiftItems,\n highlightedIndex,\n navigationPath.length,\n openMenu,\n handleDescend,\n handleAscend,\n ],\n );\n\n // Call onOpenChange when dropdown state changes\n useEffect(() => {\n mode.onMenuOpenChange(isMenuOpen);\n onOpenChange?.(isMenuOpen);\n }, [isMenuOpen, onOpenChange, mode.onMenuOpenChange]);\n\n // Keep inputValue in sync with selected option when dropdown is closed\n useEffect(() => {\n if (!embedded && !isMenuOpen) {\n setInputValue(committedLabelRef.current ?? selectedOption?.label ?? '');\n }\n }, [embedded, selectedOption, isMenuOpen]);\n\n // Highlight the first enabled option when nothing is highlighted, and when a new query or submenu\n // would otherwise leave the highlight on a disabled one. Otherwise the arrow keys may rest on a\n // disabled option.\n const levelKey = JSON.stringify([navigationPath, mode.query ?? inputValue]);\n const levelKeyRef = useRef(levelKey);\n useEffect(() => {\n const levelChanged = levelKeyRef.current !== levelKey;\n levelKeyRef.current = levelKey;\n if (!isMenuOpen || isFooterHighlighted || firstEnabledIndex === -1) {\n return;\n }\n const highlighted = downshiftItems[highlightedIndex];\n if (highlighted == null || (levelChanged && isItemDisabled(highlighted))) {\n setHighlightedIndex(firstEnabledIndex);\n }\n }, [\n downshiftItems,\n isMenuOpen,\n highlightedIndex,\n isFooterHighlighted,\n setHighlightedIndex,\n firstEnabledIndex,\n isItemDisabled,\n levelKey,\n ]);\n\n const displayValue = isMenuOpen\n ? inputValue\n : (committedLabelRef.current ?? selectedOption?.label ?? '');\n const hasSticker = !isMenuOpen && selectedOption?.labelStickerVariant;\n const InputComponent = hasSticker ? StickerComboboxInput : ComboboxInput;\n\n // Show the Back row only in nested mode at a non-root level. In\n // search mode the tree is flattened and breadcrumbs surface as\n // option `description`s, so a Back row would just be noise.\n const showBackRow = isMenuOpen && navigationPath.length > 0 && !isSearching;\n\n // External trigger mode: clone the consumer-supplied trigger with\n // downshift's toggle props so click / aria-expanded / aria-controls\n // wire up. The trigger's own props are passed through\n // `getToggleButtonProps` so downshift composes (rather than clobbers)\n // existing handlers like `onClick`. Falls back to the default\n // input + caret if a non-element was passed.\n const externalTrigger = (() => {\n if (embedded || trigger == null || !isValidElement(trigger)) {\n return null;\n }\n const triggerProps = trigger.props as Record<string, unknown> & { disabled?: unknown };\n return cloneElement(\n trigger,\n getToggleButtonProps({\n ...triggerProps,\n disabled: field.disabled || Boolean(triggerProps.disabled),\n }) as Record<string, unknown>,\n );\n })();\n\n // Pre-computed downshift-wrapped props for the in-dropdown search\n // input rendered in external-trigger mode (only used when\n // `externalTrigger` is non-null; cheap to compute either way).\n const searchInputProps = getInputProps({\n ref: comboboxInputRef,\n id: field.inputId,\n placeholder: 'Search…',\n disabled: field.disabled,\n 'aria-label': embedded ? 'Search options' : (ariaLabel ?? 'Search options'),\n 'aria-labelledby': embedded ? undefined : labelId,\n 'aria-describedby':\n [field.helperTextId, field.hasWarning ? field.warningTextId : null]\n .filter(Boolean)\n .join(' ') || undefined,\n 'aria-errormessage': field.hasError ? field.errorTextId : undefined,\n 'aria-invalid': field.hasError,\n 'aria-required': required || undefined,\n onKeyDown: handleKeyDown,\n });\n // When the footer is keyboard-highlighted, point the input's active\n // descendant at the footer button so screen readers announce it (downshift's\n // value stands otherwise).\n if (isFooterHighlighted) {\n searchInputProps['aria-activedescendant'] = footerActionId;\n }\n\n const mainInputProps = getInputProps({\n ...props,\n ref: comboboxInputRef,\n id: field.inputId,\n placeholder,\n disabled: field.disabled,\n 'aria-label': ariaLabel,\n 'aria-labelledby': labelId,\n 'aria-describedby':\n [field.helperTextId, field.hasWarning ? field.warningTextId : null]\n .filter(Boolean)\n .join(' ') || undefined,\n 'aria-errormessage': field.hasError ? field.errorTextId : undefined,\n 'aria-invalid': field.hasError,\n 'aria-required': required || undefined,\n onKeyDown: handleKeyDown,\n });\n if (isFooterHighlighted) {\n mainInputProps['aria-activedescendant'] = footerActionId;\n }\n\n return (\n <Container {...props} ref={internalContainerRef}>\n {embedded ? null : externalTrigger != null ? (\n externalTrigger\n ) : (\n <InputContainer>\n {hasSticker && (\n <StickerDisplay variant={selectedOption.labelStickerVariant}>\n {selectedOption.label}\n </StickerDisplay>\n )}\n <InputComponent\n {...mode.getQueryInputProps({ ...mainInputProps, value: displayValue }, isMenuOpen)}\n size={size}\n $isOpen={isMenuOpen}\n hasWarning={field.hasWarning}\n hasError={field.hasError}\n $selectedItemStyle={selectedOption?.PLEASE_DO_NOT_USE_labelFontStyle}\n />\n\n <CaretButton\n {...getToggleButtonProps()}\n size={size}\n disabled={field.disabled}\n aria-label={`${isMenuOpen ? 'Close' : 'Open'} options menu`}\n aria-haspopup='listbox'\n >\n <CaretDownIcon />\n </CaretButton>\n </InputContainer>\n )}\n\n <DropdownPortalWrapper portal={embedded ? false : portal}>\n <DropdownContainer\n $isOpen={isMenuOpen}\n $portal={embedded ? false : portal}\n $embedded={embedded}\n $top={dropdownPosition.top}\n $left={dropdownPosition.left}\n $width={dropdownPosition.width}\n $minWidth={externalTrigger ? EXTERNAL_TRIGGER_DROPDOWN_MIN_WIDTH : undefined}\n {...getMenuProps()}\n >\n {(externalTrigger || embedded) && (\n // Search input moves into the dropdown when an external\n // trigger owns the closed state. Mounted unconditionally\n // so downshift's input ref stays stable across open/close\n // (the surrounding `DropdownContainer` handles visibility).\n <SearchInputContainer $embedded={embedded}>\n <InputGroup leftIcon={embedded ? undefined : <SearchIcon />} size={size}>\n <SearchInput\n $embedded={embedded}\n {...mode.getQueryInputProps({ ...searchInputProps, value: inputValue })}\n size={size}\n hasWarning={field.hasWarning}\n hasError={field.hasError}\n autoComplete='off'\n />\n </InputGroup>\n </SearchInputContainer>\n )}\n <SingleSelectScrollableMenuList\n $embedded={embedded}\n tabIndex={-1}\n ref={mode.scrollRef}\n onScroll={mode.onScroll}\n >\n {isMenuOpen && (\n <>\n {showBackRow && (\n <BackRow\n type='button'\n // Removed from the Tab order: a Tab landing here\n // would blur the input and downshift would close\n // the menu before any handler could ascend. The\n // documented keyboard path is ArrowLeft from the\n // input (caret at position 0). The button stays\n // discoverable to assistive tech (screen-reader\n // cursors can still focus + activate it).\n tabIndex={-1}\n onMouseDown={(event) => {\n // Beat downshift's blur-on-mousedown by handling\n // the ascend here and preventing the input from\n // losing focus (which would close the dropdown).\n event.preventDefault();\n handleAscend();\n }}\n onClick={(event) => {\n // Assistive-tech activation (e.g. VoiceOver\n // VO+Space) dispatches `click` with `detail === 0`\n // without firing `mousedown` — handle it here so\n // a screen-reader user who activates the Back\n // affordance actually ascends. Mouse clicks\n // (`detail >= 1`) were already handled by\n // `onMouseDown`; skip them to avoid double-ascending.\n if (event.detail === 0) {\n handleAscend();\n }\n }}\n aria-label='Back to previous menu'\n $size={size}\n >\n <ArrowLeftIcon aria-hidden='true' size={size === 'sm' ? 12 : 16} />\n <span>Back</span>\n </BackRow>\n )}\n {isOptionsLoading ? (\n <LoadingContainer>\n <Spinner size='md' />\n </LoadingContainer>\n ) : downshiftItems.length > 0 ? (\n hasNestedGroups && !isSearching ? (\n // Browse-mode for nested-nav trees: render leaves +\n // nested-group nav rows + inline section headers in\n // document order; downshift's highlightedIndex maps\n // to this list via `downshiftItems`.\n renderNestedLevel(nestedOptions)\n ) : (\n // Legacy / flat / grouped search: the shared\n // renderer handles section headers and leaves.\n // `renderSource` is the flat-leaves overlay in\n // search mode and the original `options` (legacy\n // tree) otherwise.\n renderOptionsWithGroups({\n options: renderSource,\n filteredOptions,\n renderOption,\n })\n )\n ) : (\n <EmptyState role='status' aria-live='polite' size={size}>\n {emptyStateMessage}\n </EmptyState>\n )}\n {mode.loadingMore}\n {showFooterAction && footerAction && (\n <FooterActionRow\n action={footerAction}\n size={size}\n id={footerActionId}\n isHighlighted={isFooterHighlighted}\n />\n )}\n </>\n )}\n </SingleSelectScrollableMenuList>\n </DropdownContainer>\n </DropdownPortalWrapper>\n </Container>\n );\n}\n\nexport const ComboboxSingleSelect = forwardRef(ComboboxSingleSelectComponent) as <T = string>(\n props: (ComboboxSingleSelectProps<T> | ComboboxServerSingleSelectProps<T>) & {\n ref?: React.Ref<HTMLInputElement>;\n },\n) => React.ReactElement;\n\nexport default ComboboxSingleSelect;\n","import { forwardRef } from 'react';\n\nimport { CaretButton } from './ComboboxBase';\nimport ComboboxMultiSelect, {\n type ComboboxMultiSelectProps,\n type ComboboxServerMultiSelectProps,\n} from './ComboboxMultiSelect';\nimport ComboboxSingleSelect, {\n type ComboboxSingleSelectProps,\n type ComboboxServerSingleSelectProps,\n} from './ComboboxSingleSelect';\n\n// Existing client-mode props retain their original multiple discriminator.\nexport type ComboboxProps<T = string> = ComboboxSingleSelectProps<T> | ComboboxMultiSelectProps<T>;\nexport type ComboboxServerProps<T = string> =\n | ComboboxServerSingleSelectProps<T>\n | ComboboxServerMultiSelectProps<T>;\n\nfunction ComboboxComponent<T = string>(\n props: ComboboxProps<T> | ComboboxServerProps<T>,\n ref: React.Ref<HTMLInputElement>,\n) {\n if (props.multiple) {\n return <ComboboxMultiSelect<T> ref={ref} {...props} />;\n } else {\n return <ComboboxSingleSelect<T> ref={ref} {...props} />;\n }\n}\n\nexport const Combobox = forwardRef(ComboboxComponent) as <T = string>(\n props: (ComboboxProps<T> | ComboboxServerProps<T>) & { ref?: React.Ref<HTMLInputElement> },\n) => React.ReactElement;\n\nexport { CaretButton };\n\nexport default Combobox;\n"],"mappings":"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"}