@grafana/ui
Version:
Grafana Components Library
1 lines • 10.3 kB
Source Map (JSON)
{"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/ThemeContext';\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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"}