UNPKG

@activecollab/components

Version:

ActiveCollab Components

192 lines • 8.16 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; const _excluded = ["type", "mode", "target", "options", "selected", "mixed", "position", "onChange", "placeholder", "emptyAction", "disableSearch", "forceCloseMenu", "selectClassName", "keepSameOptionsOrder", "onSelectOpen", "onSelectClose", "renderOption", "handleDefaultOptionChange", "preselectDefaultValue", "startAdornment", "endAdornment", "focusInput", "disableVirtualization"]; import React, { useCallback, useState, useMemo, useEffect, useRef } from "react"; import classNames from "classnames"; import { OptionContent } from "./OptionContent/OptionContent"; import { StyledSelectForm, StyledSelectInput, StyledCheckbox, StyledRadioButton, StyledStartAdornment, StyledEndAdornment } from "./Styles"; import useForkRef from "../../utils/useForkRef"; import { Autocomplete, isOptionGroup } from "../Autocomplete"; import { Menu } from "../Menu/Menu"; export const Select = _ref => { let { type = "single", mode, target, options, selected = [], mixed = [], position = "bottom-start", onChange = () => null, placeholder, emptyAction = () => null, disableSearch = false, forceCloseMenu, selectClassName, keepSameOptionsOrder = false, onSelectOpen, onSelectClose, renderOption, handleDefaultOptionChange, preselectDefaultValue = type === "single", startAdornment, endAdornment, focusInput = false, disableVirtualization } = _ref, prop = _objectWithoutPropertiesLoose(_ref, _excluded); if (disableSearch && (startAdornment || endAdornment)) { console.warn("Adornments are not visible when search bar is hidden"); } const childNode = useRef(); const elementRef = useRef(null); const handleRef = useForkRef(childNode, elementRef); const Tag = !target ? "div" : Menu; const formRef = useRef(null); const [open, setOpen] = useState(false); const selectedOptions = useMemo(() => selected instanceof Array ? selected : [selected], [selected]); const selectOptions = useMemo(() => { if (!options) { return []; } return options; }, [options]); const allOptionValues = useMemo(() => { return selectOptions.reduce((acc, option) => { if (!isOptionGroup(option)) { return [...acc, option.id]; } const allGroupOptions = option.options.map(option => option.id); return [...acc, ...allGroupOptions]; }, []); }, [selectOptions]); const mixedOptions = useRef(type === "multiple" && mixed.length ? mixed : []); const removeFromMixedOptions = useCallback(idsToRemove => { mixedOptions.current = mixedOptions.current.filter(mixedOption => !idsToRemove.includes(mixedOption)); }, []); const isAllOptionsChecked = useMemo(() => allOptionValues.every(option => selectedOptions.includes(option)), [allOptionValues, selectedOptions]); const someOptionsChecked = useMemo(() => allOptionValues.some(option => selectedOptions.includes(option)), [allOptionValues, selectedOptions]); useEffect(() => { if (open && target || !target && focusInput) { var _childNode$current; childNode == null || (_childNode$current = childNode.current) == null || _childNode$current.focus(); } }, [focusInput, open, target]); const handleChange = useCallback(selectedValue => { if (forceCloseMenu) { if (typeof onSelectClose === "function") onSelectClose(); setOpen(false); } if (selectedValue !== undefined && selectedValue !== selected && !(selectedValue instanceof Array && selectedValue.includes(undefined))) { onChange(selectedValue); type === "multiple" && mixedOptions.current.length && removeFromMixedOptions(selectedValue); } }, [forceCloseMenu, selected, onSelectClose, onChange, type, removeFromMixedOptions]); const onClose = useCallback(() => { setOpen(false); if (onSelectClose) { onSelectClose(); } }, [onSelectClose]); const onOpen = useCallback(() => { setOpen(true); if (onSelectOpen) { onSelectOpen(); } }, [onSelectOpen]); const props = useMemo(() => { if (target) { return { menuClassName: classNames("c-select", selectClassName), onClose, onOpen, target, mode, open, position, onPopperOpen: () => { var _elementRef$current; return elementRef == null || (_elementRef$current = elementRef.current) == null ? void 0 : _elementRef$current.focus(); } }; } return { className: classNames("c-select", selectClassName) }; }, [target, selectClassName, onClose, onOpen, mode, open, position]); const handleEmptyAction = useCallback(value => { var _formRef$current; emptyAction(value); if (forceCloseMenu) { setOpen(false); } (_formRef$current = formRef.current) == null || _formRef$current.reset(); }, [emptyAction, forceCloseMenu]); const handleDefaultOptionChangeCallback = useCallback(() => { if (type === "multiple") { if (selectedOptions.length === allOptionValues.length) { if (typeof handleDefaultOptionChange === "function") { handleDefaultOptionChange(); } else { onChange([]); } } else { if (typeof handleDefaultOptionChange === "function") { handleDefaultOptionChange(); } else { onChange(allOptionValues); } } } else { if (typeof handleDefaultOptionChange === "function") { handleDefaultOptionChange(); } else { onChange(""); } } if (forceCloseMenu) { setOpen(false); } }, [onChange, type, forceCloseMenu, selectedOptions.length, allOptionValues, handleDefaultOptionChange]); const handleRenderOption = useCallback((option, props) => { if (typeof renderOption === "function") { return renderOption(option, props); } return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(OptionContent, { imageUrl: option.image, color: option.color, textColor: option.textColor, name: option.name, additionalInfo: option.additionalInfo }), option.id === null ? type === "multiple" ? /*#__PURE__*/React.createElement(StyledCheckbox, _extends({ checked: isAllOptionsChecked, mixed: someOptionsChecked && !isAllOptionsChecked }, props)) : /*#__PURE__*/React.createElement(StyledRadioButton, _extends({ checked: selectedOptions.length < 1 || !selectedOptions[0] }, props)) : type === "multiple" ? /*#__PURE__*/React.createElement(StyledCheckbox, _extends({ mixed: mixedOptions.current.includes(option.id) }, props)) : /*#__PURE__*/React.createElement(StyledRadioButton, props)); }, [isAllOptionsChecked, renderOption, type, someOptionsChecked, selectedOptions]); return /*#__PURE__*/React.createElement(Tag, props, /*#__PURE__*/React.createElement("div", null, !disableSearch ? /*#__PURE__*/React.createElement(StyledSelectForm, { ref: formRef }, startAdornment ? /*#__PURE__*/React.createElement(StyledStartAdornment, null, startAdornment) : null, /*#__PURE__*/React.createElement(StyledSelectInput, { ref: handleRef, placeholder: placeholder }), endAdornment ? /*#__PURE__*/React.createElement(StyledEndAdornment, null, endAdornment) : null) : null, /*#__PURE__*/React.createElement(Autocomplete, _extends({}, prop, { clearInputOnSelect: true, inputEl: disableSearch ? undefined : childNode, handleEmptyAction: handleEmptyAction, selected: selected, handleChange: handleChange, renderOption: handleRenderOption, options: options, mixedOptions: mixedOptions.current, handleDefaultOptionChange: handleDefaultOptionChangeCallback, type: type, preselectDefaultValue: preselectDefaultValue, keepSameOptionsOrder: keepSameOptionsOrder, disableVirtualization: disableVirtualization })))); }; Select.displayName = "Select"; //# sourceMappingURL=Select.js.map