UNPKG

@activecollab/components

Version:

ActiveCollab Components

589 lines (588 loc) • 24.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Autocomplete = void 0; exports.isOptionGroup = isOptionGroup; var _styledComponents = _interopRequireDefault(require("styled-components")); var _react = _interopRequireWildcard(require("react")); var _reactVirtual = require("@tanstack/react-virtual"); var _HandleKeyboard = require("./HandleKeyboard"); var _Styles = require("./Styles"); var _useHighlightText = _interopRequireDefault(require("../../hooks/useHighlightText")); var _Option = require("../Select/Option"); var _Styles2 = require("../Select/Option/Styles"); var _OptionGroup = require("../Select/OptionGroup"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function isOptionGroup(item) { return item.options !== undefined; } var Autocomplete = exports.Autocomplete = function Autocomplete(_ref) { var type = _ref.type, _ref$options = _ref.options, options = _ref$options === void 0 ? [] : _ref$options, inputEl = _ref.inputEl, _ref$selected = _ref.selected, selected = _ref$selected === void 0 ? [] : _ref$selected, emptyValue = _ref.emptyValue, noResultText = _ref.noResultText, _ref$renderOption = _ref.renderOption, renderOption = _ref$renderOption === void 0 ? function (option) { return option === null || option === void 0 ? void 0 : option.name; } : _ref$renderOption, defaultValue = _ref.defaultValue, _ref$sortDirection = _ref.sortDirection, sortDirection = _ref$sortDirection === void 0 ? "asc" : _ref$sortDirection, handleChange = _ref.handleChange, optionClassName = _ref.optionClassName, handleEmptyAction = _ref.handleEmptyAction, disabledInternalSort = _ref.disabledInternalSort, AutocompleteClassName = _ref.AutocompleteClassName, handleDefaultOptionChange = _ref.handleDefaultOptionChange, preselectDefaultValue = _ref.preselectDefaultValue, _ref$keepSameOptionsO = _ref.keepSameOptionsOrder, keepSameOptionsOrder = _ref$keepSameOptionsO === void 0 ? false : _ref$keepSameOptionsO, _ref$autoHeightMax = _ref.autoHeightMax, autoHeightMax = _ref$autoHeightMax === void 0 ? 340 : _ref$autoHeightMax, clearInputOnSelect = _ref.clearInputOnSelect, _ref$mixedOptions = _ref.mixedOptions, mixedOptions = _ref$mixedOptions === void 0 ? [] : _ref$mixedOptions, filterCriteria = _ref.filterCriteria, disableVirtualization = _ref.disableVirtualization; var listContainerRef = (0, _react.useRef)(null); var itemRef = (0, _react.useRef)(null); var selectedOptions = (0, _react.useMemo)(function () { if (Array.isArray(selected)) { return selected; } return [selected]; }, [selected]); var handleSort = (0, _react.useCallback)(function (opts) { var _opts$; if (keepSameOptionsOrder) { return opts; } var isGrouped = Array.isArray((_opts$ = opts[0]) === null || _opts$ === void 0 ? void 0 : _opts$.options); var sortOptions = function sortOptions(a, b) { var aSelected = selectedOptions.includes(a.id); var bSelected = selectedOptions.includes(b.id); var aMixed = mixedOptions.includes(a.id); var bMixed = mixedOptions.includes(b.id); if (aSelected && !bSelected) { return -1; } if (!aSelected && bSelected) { return 1; } if (aMixed && !bMixed) { return -1; } if (!aMixed && bMixed) { return 1; } return 0; }; if (isGrouped) { return opts.map(function (group) { var sortedGroupOptions = group.options.sort(sortOptions); return _objectSpread(_objectSpread({}, group), {}, { options: sortedGroupOptions }); }); } else { return opts.sort(sortOptions); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [mixedOptions, selectedOptions]); var sortList = (0, _react.useCallback)(function (options) { var _options$; if (disabledInternalSort) { return handleSort([...options]); } var isGrouped = Array.isArray((_options$ = options[0]) === null || _options$ === void 0 ? void 0 : _options$.options); if (isGrouped) { var sortedOptions = options.map(function (group) { var sortedGroupOptions = group.options.sort(function (a, b) { return sortDirection === "asc" ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name); }); return _objectSpread(_objectSpread({}, group), {}, { options: handleSort(sortedGroupOptions) }); }); return handleSort(sortedOptions); } else { var _sortedOptions = options.sort(function (a, b) { return sortDirection === "asc" ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name); }); return handleSort(_sortedOptions); } }, [sortDirection, disabledInternalSort, handleSort]); var _useState = (0, _react.useState)(function () { return sortList(options); }), _useState2 = _slicedToArray(_useState, 2), sortedList = _useState2[0], setSortedList = _useState2[1]; (0, _react.useEffect)(function () { setSortedList(sortList(options)); // eslint-disable-next-line react-hooks/exhaustive-deps }, [options]); var _useState3 = (0, _react.useState)({ item: undefined, by: undefined }), _useState4 = _slicedToArray(_useState3, 2), hover = _useState4[0], setHover = _useState4[1]; var _useState5 = (0, _react.useState)(""), _useState6 = _slicedToArray(_useState5, 2), filter = _useState6[0], setFilter = _useState6[1]; var handleEmpty = (0, _react.useCallback)(function (e) { if (e && e.button !== 0) { return; } if (handleEmptyAction) { var _inputEl$current; inputEl === null || inputEl === void 0 || (_inputEl$current = inputEl.current) === null || _inputEl$current === void 0 || _inputEl$current.focus(); setFilter(""); handleEmptyAction(filter); } }, [filter, handleEmptyAction, inputEl]); var onAddNewMouseEnter = (0, _react.useCallback)(function () { return setHover({ item: "addNew", by: "mouse" }); }, []); var showAddNew = (0, _react.useMemo)(function () { return !!(emptyValue && filter.trim() && options.every(function (option) { if (isOptionGroup(option)) { return option.options.every(function (v) { return v.name.toLowerCase() !== filter.trim().toLowerCase(); }); } return option.name.toLowerCase() !== filter.trim().toLowerCase(); })); }, [emptyValue, filter, options]); var filterOptions = (0, _react.useCallback)(function (options, filter) { var trimmedFilter = filter.trim(); var isGrouped = options[0] && isOptionGroup(options[0]); var matchesFilter = function matchesFilter(option) { var nameMatch = option.name.toLowerCase().includes(trimmedFilter.toLowerCase()); if (filterCriteria && trimmedFilter) { return nameMatch || filterCriteria(option, trimmedFilter); } return nameMatch; }; if (isGrouped) { var hovered = false; return options.reduce(function (acc, groupedOption) { var filteredOptions = groupedOption.options.filter(matchesFilter); if (filteredOptions.length > 0) { if (!hovered && filter) { setHover({ item: filteredOptions[0].id, by: "keyboard" }); } hovered = true; return [...acc, _objectSpread(_objectSpread({}, groupedOption), {}, { options: filteredOptions })]; } return [...acc]; }, []); } else { var filteredOptions = options.filter(matchesFilter); if (filter && filteredOptions.length > 0) { setHover({ item: filteredOptions[0].id, by: "keyboard" }); } if (filteredOptions.length === 0 && emptyValue) { setHover({ item: "addNew", by: "keyboard" }); } return filteredOptions; } }, [emptyValue, filterCriteria]); var list = (0, _react.useMemo)(function () { return filterOptions(sortedList, filter); }, [filter, filterOptions, sortedList]); var showDefaultOption = (0, _react.useMemo)(function () { return !!defaultValue && !filter; }, [defaultValue, filter]); var flatOptions = (0, _react.useMemo)(function () { var options = list.reduce(function (acc, option) { if (!isOptionGroup(option)) { return [...acc, option]; } return [...acc, ...option.options]; }, []); return filterOptions(options, filter); }, [filter, filterOptions, list]); var showNoResultCondition = (0, _react.useMemo)(function () { return noResultText && !showAddNew && list.length < 1 && (defaultValue && filter || !defaultValue); }, [noResultText, showAddNew, list.length, defaultValue, filter]); var virtualItems = (0, _react.useMemo)(function () { var items = []; if (showDefaultOption) { items.push({ type: "default", id: "default" }); } list.forEach(function (item, index) { if (isOptionGroup(item)) { items.push({ type: "group", id: item.id, item }); item.options.forEach(function (option) { items.push({ type: "option", id: option.id, item: option, index }); }); } else { items.push({ type: "option", id: item.id, item, index }); } }); if (showNoResultCondition) { items.push({ type: "noResult", id: "noResult" }); } if (showAddNew) { items.push({ type: "addNew", id: "addNew" }); } return items; }, [list, showDefaultOption, showNoResultCondition, showAddNew]); var shouldUseVirtualization = !disableVirtualization && virtualItems.length > 40; var rowVirtualizer = (0, _reactVirtual.useVirtualizer)({ count: virtualItems.length, getScrollElement: function getScrollElement() { return listContainerRef.current; }, estimateSize: function estimateSize() { return 28; }, overscan: 5, gap: 4 }); var handleInputChange = (0, _react.useCallback)(function (e) { if (e.target && !(e.key === "ArrowDown") && !(e.key === "ArrowUp") && !(e.key === "Enter")) { setFilter(e.target.value); } }, []); var handleHoverCallback = (0, _react.useCallback)(function (e) { setHover({ item: e, by: "mouse" }); }, []); var toggleSelected = (0, _react.useCallback)(function (id) { var result; if (id !== null) { if (type === "multiple") { if (selectedOptions.includes(id)) { result = selectedOptions.filter(function (_id) { return _id !== id; }); } else { result = [...selectedOptions, id]; } } else { result = id; } if (clearInputOnSelect && inputEl !== null && inputEl !== void 0 && inputEl.current) { inputEl.current.value = ""; inputEl.current.dispatchEvent(new Event("change", { bubbles: true })); } setFilter(""); } else { if (typeof handleDefaultOptionChange === "function") { handleDefaultOptionChange(); return; } } if (typeof handleChange === "function") { handleChange(result); } }, [clearInputOnSelect, handleChange, handleDefaultOptionChange, inputEl, selectedOptions, type]); var handleMouseEnter = (0, _react.useCallback)(function (e) { if (e === undefined || e === null) { return setHover({ item: null, by: "mouse" }); } setHover({ item: e, by: "mouse" }); }, []); var handleClick = (0, _react.useCallback)(function (e) { e.preventDefault(); toggleSelected(hover.item); }, [toggleSelected, hover]); var handleRenderOption = (0, _react.useCallback)(function (item, index) { if (isOptionGroup(item)) { return /*#__PURE__*/_react.default.createElement(_OptionGroup.OptionGroup, { checked: selectedOptions, name: item.name, tooltip: item.tooltip, key: item.id, setHover: handleHoverCallback, id: item.id, hover: hover.item, options: item.options, renderOptions: handleRenderOption, type: type, onChange: handleChange, filter: filter, mixedOptions: mixedOptions }); } return /*#__PURE__*/_react.default.createElement(_Option.Option, { name: item.name, ref: hover.item === item.id ? itemRef : null, key: index, tooltip: item.tooltip, onMouseEnter: handleMouseEnter, onClick: handleClick, id: item.id, hover: item.id === hover.item, className: optionClassName, renderOption: renderOption(_objectSpread(_objectSpread({}, item), {}, { name: (0, _useHighlightText.default)(item.name, filter) }), { id: "option_".concat(item.id), checked: selectedOptions && selectedOptions.includes(item.id), hover: hover.item === item.id, onChange: function onChange() { return null; } }) }); }, [handleClick, handleMouseEnter, hover.item, optionClassName, renderOption, filter, selectedOptions, handleHoverCallback, type, handleChange, mixedOptions]); var handleOnMouseLeave = (0, _react.useCallback)(function () { setHover({ item: undefined, by: "mouse" }); }, []); (0, _react.useEffect)(function () { if (hover.by === "keyboard" && hover.item !== undefined) { var index = virtualItems.findIndex(function (item) { return item.id === hover.item; }); if (index !== -1) { rowVirtualizer.scrollToIndex(index, { align: "center" }); } } }, [hover, rowVirtualizer, virtualItems]); var handleOnKeyDown = (0, _react.useCallback)(function (e) { if (e.key === "Enter") { e.preventDefault(); if (hover.item === undefined && filter === "") { return; } if (hover.item === "addNew") { handleEmpty(null); return; } if (hover.item === null && handleDefaultOptionChange) { handleDefaultOptionChange(); return; } if (typeof hover.item !== "undefined" || hover.item !== null) { toggleSelected(hover.item); setFilter(""); } return; } setHover({ item: (0, _HandleKeyboard.handleKeyboardMovement)(e, hover.item, flatOptions, showAddNew, showDefaultOption), by: "keyboard" }); }, [filter, flatOptions, toggleSelected, handleDefaultOptionChange, handleEmpty, hover, showAddNew, showDefaultOption]); (0, _react.useEffect)(function () { var _inputEl$current2; var listenerTarget = (_inputEl$current2 = inputEl === null || inputEl === void 0 ? void 0 : inputEl.current) !== null && _inputEl$current2 !== void 0 ? _inputEl$current2 : document; listenerTarget.addEventListener("input", handleInputChange); listenerTarget.addEventListener("keydown", handleOnKeyDown); return function () { listenerTarget.removeEventListener("input", handleInputChange); listenerTarget.removeEventListener("keydown", handleOnKeyDown); }; }, [handleInputChange, handleOnKeyDown, inputEl]); var isDefaultOptionSelected = (0, _react.useCallback)(function () { if (preselectDefaultValue) { return selectedOptions.length < 1 || selectedOptions[0] === ""; } else { return selectedOptions[0] === null || selectedOptions.length === flatOptions.length; } }, [flatOptions.length, preselectDefaultValue, selectedOptions]); var renderVirtualItem = (0, _react.useCallback)(function (virtualItem, index) { switch (virtualItem.type) { case "default": return /*#__PURE__*/_react.default.createElement(_Option.Option, { name: String(defaultValue), ref: hover.item === null ? itemRef : null, hover: hover.item === null, onMouseEnter: handleMouseEnter, onClick: function onClick(e) { e.preventDefault(); toggleSelected(null); }, renderOption: renderOption({ name: defaultValue, id: null }, { checked: isDefaultOptionSelected(), hover: hover.item === null, onChange: function onChange() { return null; } }) }); case "group": if (!virtualItem.item || !isOptionGroup(virtualItem.item)) return null; return /*#__PURE__*/_react.default.createElement(_OptionGroup.OptionGroup, { checked: selectedOptions, name: virtualItem.item.name, tooltip: virtualItem.item.tooltip, key: virtualItem.item.id, setHover: handleHoverCallback, id: virtualItem.item.id, hover: hover.item, options: virtualItem.item.options, renderOptions: handleRenderOption, type: type, onChange: handleChange, filter: filter, mixedOptions: mixedOptions }); case "option": if (!virtualItem.item || isOptionGroup(virtualItem.item)) return null; return /*#__PURE__*/_react.default.createElement(_Option.Option, { name: virtualItem.item.name, ref: hover.item === virtualItem.id ? itemRef : null, key: index, tooltip: virtualItem.item.tooltip, onMouseEnter: function onMouseEnter() { return handleMouseEnter(virtualItem.id); }, onClick: handleClick, id: virtualItem.id, hover: virtualItem.id === hover.item, className: optionClassName, renderOption: renderOption(_objectSpread(_objectSpread({}, virtualItem.item), {}, { name: (0, _useHighlightText.default)(virtualItem.item.name, filter) }), { id: "option_".concat(virtualItem.id), checked: selectedOptions && selectedOptions.includes(virtualItem.id), hover: hover.item === virtualItem.id, onChange: function onChange() { return null; } }) }); case "noResult": return /*#__PURE__*/_react.default.createElement(_StyledStyledOption, null, noResultText); case "addNew": return /*#__PURE__*/_react.default.createElement(_Styles.StyledAutocompleteNewItem, { ref: hover.item === "addNew" ? itemRef : null, key: "emptyValue", hover: hover.item === "addNew", onMouseDown: handleEmpty, onMouseEnter: onAddNewMouseEnter }, emptyValue); default: return null; } }, [defaultValue, hover.item, handleMouseEnter, renderOption, isDefaultOptionSelected, selectedOptions, handleHoverCallback, handleRenderOption, type, handleChange, filter, mixedOptions, handleClick, optionClassName, noResultText, handleEmpty, onAddNewMouseEnter, emptyValue, toggleSelected]); return /*#__PURE__*/_react.default.createElement(_Styles.StyledAutocompleteScrollShadow, { className: AutocompleteClassName, $isHidden: !defaultValue && !emptyValue && !noResultText && list.length < 1 }, function (_ref2) { var _onScroll = _ref2.onScroll; return /*#__PURE__*/_react.default.createElement(_Styles.StyledAutocompleteBody, { key: "body", onMouseLeave: handleOnMouseLeave }, /*#__PURE__*/_react.default.createElement("div", { ref: listContainerRef, style: { height: "".concat(Math.min(rowVirtualizer.getTotalSize() + 12, autoHeightMax), "px"), overflow: "auto" }, onScroll: function onScroll(e) { if (_onScroll) _onScroll(e); } }, /*#__PURE__*/_react.default.createElement("div", { style: { height: "".concat(rowVirtualizer.getTotalSize(), "px"), width: "100%", position: "relative" } }, shouldUseVirtualization ? rowVirtualizer.getVirtualItems().map(function (virtualRow) { var item = virtualItems[virtualRow.index]; return /*#__PURE__*/_react.default.createElement("div", { key: virtualRow.index, "data-index": virtualRow.index, style: { position: "absolute", top: 0, left: 0, width: "100%", transform: "translateY(".concat(virtualRow.start, "px)") } }, renderVirtualItem(item, virtualRow.index)); }) : virtualItems.map(function (item, index) { return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, { key: index }, renderVirtualItem(item, index)); })))); }); }; Autocomplete.displayName = "Autocomplete"; var _StyledStyledOption = (0, _styledComponents.default)(_Styles2.StyledOption).withConfig({ displayName: "Autocomplete___StyledStyledOption", componentId: "sc-9x4q7e-0" })(["cursor:auto"]); //# sourceMappingURL=Autocomplete.js.map