@activecollab/components
Version:
ActiveCollab Components
192 lines • 8.16 kB
JavaScript
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