{"version":3,"file":"ComboboxList.mjs","sources":["../../../../src/components/Combobox/ComboboxList.tsx"],"sourcesContent":["import { cx } from '@emotion/css';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport type { UseComboboxPropGetters } from 'downshift';\nimport { useCallback } from 'react';\n\nimport { useStyles2 } from '../../themes';\nimport { Checkbox } from '../Forms/Checkbox';\nimport { ScrollContainer } from '../ScrollContainer/ScrollContainer';\n\nimport { AsyncError, NotFoundError } from './MessageRows';\nimport { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles';\nimport { ALL_OPTION_VALUE, ComboboxOption } from './types';\nimport { isNewGroup } from './utils';\n\nexport const VIRTUAL_OVERSCAN_ITEMS = 4;\n\ninterface ComboboxListProps<T extends string | number> {\n  options: Array<ComboboxOption<T>>;\n  highlightedIndex: number | null;\n  selectedItems?: Array<ComboboxOption<T>>;\n  scrollRef: React.RefObject<HTMLDivElement>;\n  getItemProps: UseComboboxPropGetters<ComboboxOption<T>>['getItemProps'];\n  enableAllOption?: boolean;\n  isMultiSelect?: boolean;\n  error?: boolean;\n}\n\nexport const ComboboxList = <T extends string | number>({\n  options,\n  highlightedIndex,\n  selectedItems = [],\n  scrollRef,\n  getItemProps,\n  enableAllOption,\n  isMultiSelect = false,\n  error = false,\n}: ComboboxListProps<T>) => {\n  const styles = useStyles2(getComboboxStyles);\n\n  const estimateSize = useCallback(\n    (index: number) => {\n      const firstGroupItem = isNewGroup(options[index], index > 0 ? options[index - 1] : undefined);\n      const hasDescription = 'description' in options[index];\n      const hasGroup = 'group' in options[index];\n\n      let itemHeight = MENU_OPTION_HEIGHT;\n      if (hasDescription) {\n        itemHeight = MENU_OPTION_HEIGHT_DESCRIPTION;\n      }\n      if (firstGroupItem && hasGroup) {\n        itemHeight += MENU_OPTION_HEIGHT;\n      }\n      return itemHeight;\n    },\n    [options]\n  );\n\n  const rowVirtualizer = useVirtualizer({\n    count: options.length,\n    getScrollElement: () => scrollRef.current,\n    estimateSize,\n    overscan: VIRTUAL_OVERSCAN_ITEMS,\n  });\n\n  const isOptionSelected = useCallback(\n    (item: ComboboxOption<T>) => selectedItems.some((opt) => opt.value === item.value),\n    [selectedItems]\n  );\n\n  const allItemsSelected = enableAllOption && selectedItems.length === options.length - 1;\n\n  return (\n    <ScrollContainer showScrollIndicators maxHeight=\"inherit\" ref={scrollRef} padding={0.5}>\n      <div style={{ height: rowVirtualizer.getTotalSize() }} className={styles.menuUlContainer}>\n        {rowVirtualizer.getVirtualItems().map((virtualRow, index, allVirtualRows) => {\n          const item = options[virtualRow.index];\n          const startingNewGroup = isNewGroup(item, options[virtualRow.index - 1]);\n\n          // Find the item that renders the group header. It can be this same item if this is rendering it.\n          const groupHeaderIndex = allVirtualRows.find((row) => {\n            const rowItem = options[row.index];\n            return rowItem.group === item.group;\n          });\n          const groupHeaderItem = groupHeaderIndex && options[groupHeaderIndex.index];\n\n          const itemId = `combobox-option-${item.value}`;\n          // If we're rendering the group header, this is the ID for it. Otherwise its used on\n          // the option for aria-describedby.\n          const groupHeaderId = groupHeaderItem ? `combobox-option-group-${groupHeaderItem.value}` : undefined;\n\n          return (\n            // Wrapping div should have no styling other than virtual list positioning.\n            // It's children (header and option) should appear as flat list items.\n            <div\n              key={item.value}\n              className={styles.listItem}\n              style={{\n                height: virtualRow.size,\n                transform: `translateY(${virtualRow.start}px)`,\n              }}\n            >\n              {/* Group header */}\n              {startingNewGroup && (\n                <div\n                  role=\"presentation\"\n                  data-testid=\"combobox-option-group\"\n                  id={groupHeaderId}\n                  className={cx(\n                    styles.optionGroupHeader,\n                    item.group && styles.optionGroupLabel,\n                    virtualRow.index === 0 && styles.optionFirstGroupHeader\n                  )}\n                >\n                  {item.group}\n                </div>\n              )}\n\n              {/* Option */}\n              <div\n                className={cx(\n                  styles.option,\n                  !isMultiSelect && isOptionSelected(item) && styles.optionSelected,\n                  highlightedIndex === virtualRow.index && styles.optionFocused\n                )}\n                {...getItemProps({\n                  item: item,\n                  index: virtualRow.index,\n                  id: itemId,\n                  'aria-describedby': groupHeaderId,\n                })}\n              >\n                {isMultiSelect && (\n                  <div className={styles.optionAccessory}>\n                    <Checkbox\n                      key={itemId}\n                      value={allItemsSelected || isOptionSelected(item)}\n                      indeterminate={item.value === ALL_OPTION_VALUE && selectedItems.length > 0 && !allItemsSelected}\n                      aria-labelledby={itemId}\n                      onClick={(e) => {\n                        e.stopPropagation();\n                      }}\n                    />\n                  </div>\n                )}\n\n                <div className={styles.optionBody}>\n                  <div className={styles.optionLabel}>{item.label ?? item.value}</div>\n\n                  {item.description && <div className={styles.optionDescription}>{item.description}</div>}\n                </div>\n              </div>\n            </div>\n          );\n        })}\n      </div>\n\n      <div aria-live=\"polite\">\n        {error && <AsyncError />}\n        {options.length === 0 && !error && <NotFoundError />}\n      </div>\n    </ScrollContainer>\n  );\n};\n"],"names":[],"mappings":"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"}