UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

129 lines (125 loc) 4.97 kB
import React__default, { useCallback, useMemo } from 'react'; import { useProvidedStateOrCreate } from '../hooks/useProvidedStateOrCreate.js'; import { useProvidedRefOrCreate } from '../hooks/useProvidedRefOrCreate.js'; import { AnchoredOverlay } from '../AnchoredOverlay/AnchoredOverlay.js'; import { FilteredActionList } from '../FilteredActionList/FilteredActionList.js'; import { DropdownButton } from '../deprecated/DropdownMenu/DropdownButton.js'; function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function isMultiSelectVariant(selected) { return Array.isArray(selected); } const focusZoneSettings = { // Let FilteredActionList handle focus zone disabled: true }; function SelectPanel({ open, onOpenChange, renderAnchor = props => /*#__PURE__*/React__default.createElement(DropdownButton, props), anchorRef: externalAnchorRef, placeholder, selected, onSelectedChange, filterValue: externalFilterValue, onFilterChange: externalOnFilterChange, items, textInputProps, overlayProps, sx, ...listProps }) { const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, ''); const onFilterChange = useCallback((value, e) => { externalOnFilterChange(value, e); setInternalFilterValue(value); }, [externalOnFilterChange, setInternalFilterValue]); const anchorRef = useProvidedRefOrCreate(externalAnchorRef); const onOpen = useCallback(gesture => onOpenChange(true, gesture), [onOpenChange]); const onClose = useCallback(gesture => { onOpenChange(false, gesture); }, [onOpenChange]); const renderMenuAnchor = useMemo(() => { if (renderAnchor === null) { return null; } const selectedItems = Array.isArray(selected) ? selected : [...(selected ? [selected] : [])]; return props => { return renderAnchor({ ...props, children: selectedItems.length ? selectedItems.map(item => item.text).join(', ') : placeholder }); }; }, [placeholder, renderAnchor, selected]); const itemsToRender = useMemo(() => { return items.map(item => { const isItemSelected = isMultiSelectVariant(selected) ? selected.includes(item) : selected === item; return { ...item, role: 'option', selected: 'selected' in item && item.selected === undefined ? undefined : isItemSelected, onAction: (itemFromAction, event) => { var _item$onAction; (_item$onAction = item.onAction) === null || _item$onAction === void 0 ? void 0 : _item$onAction.call(item, itemFromAction, event); if (event.defaultPrevented) { return; } if (isMultiSelectVariant(selected)) { const otherSelectedItems = selected.filter(selectedItem => selectedItem !== item); const newSelectedItems = selected.includes(item) ? otherSelectedItems : [...otherSelectedItems, item]; const multiSelectOnChange = onSelectedChange; multiSelectOnChange(newSelectedItems); return; } // single select const singleSelectOnChange = onSelectedChange; singleSelectOnChange(item === selected ? undefined : item); onClose('selection'); } }; }); }, [onClose, onSelectedChange, items, selected]); const inputRef = React__default.useRef(null); const focusTrapSettings = { initialFocusRef: inputRef }; const extendedTextInputProps = useMemo(() => { return { sx: { m: 2 }, contrast: true, ...textInputProps }; }, [textInputProps]); return /*#__PURE__*/React__default.createElement(AnchoredOverlay, { renderAnchor: renderMenuAnchor, anchorRef: anchorRef, open: open, onOpen: onOpen, onClose: onClose, overlayProps: overlayProps, focusTrapSettings: focusTrapSettings, focusZoneSettings: focusZoneSettings }, /*#__PURE__*/React__default.createElement(FilteredActionList, _extends({ filterValue: filterValue, onFilterChange: onFilterChange }, listProps, { role: "listbox", "aria-multiselectable": isMultiSelectVariant(selected) ? 'true' : 'false', selectionVariant: isMultiSelectVariant(selected) ? 'multiple' : 'single', items: itemsToRender, textInputProps: extendedTextInputProps, inputRef: inputRef // inheriting height and maxHeight ensures that the FilteredActionList is never taller // than the Overlay (which would break scrolling the items) , sx: { ...sx, height: 'inherit', maxHeight: 'inherit' } }))); } SelectPanel.displayName = "SelectPanel"; SelectPanel.displayName = 'SelectPanel'; export { SelectPanel };