"use strict"; function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var React = _interopRequireWildcard(require("react")); var _KeyCode = _interopRequireDefault(require("rc-util/lib/KeyCode")); var _useMemo = _interopRequireDefault(require("rc-util/lib/hooks/useMemo")); var _classnames = _interopRequireDefault(require("classnames")); var _rcVirtualList = _interopRequireDefault(require("rc-virtual-list")); var _TransBtn = _interopRequireDefault(require("./TransBtn")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } 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(n); 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(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } /** * Using virtual list of option display. * Will fallback to dom if use customize render. */ var OptionList = function OptionList(_ref, ref) { var prefixCls = _ref.prefixCls, id = _ref.id, flattenOptions = _ref.flattenOptions, childrenAsData = _ref.childrenAsData, values = _ref.values, searchValue = _ref.searchValue, multiple = _ref.multiple, defaultActiveFirstOption = _ref.defaultActiveFirstOption, height = _ref.height, itemHeight = _ref.itemHeight, notFoundContent = _ref.notFoundContent, open = _ref.open, menuItemSelectedIcon = _ref.menuItemSelectedIcon, virtual = _ref.virtual, onSelect = _ref.onSelect, onToggleOpen = _ref.onToggleOpen, onActiveValue = _ref.onActiveValue, onScroll = _ref.onScroll; var itemPrefixCls = "".concat(prefixCls, "-item"); var memoFlattenOptions = (0, _useMemo.default)(function () { return flattenOptions; }, [open, flattenOptions], function (prev, next) { return next[0] && prev[1] !== next[1]; }); // =========================== List =========================== var listRef = React.useRef(null); var onListMouseDown = function onListMouseDown(event) { event.preventDefault(); }; var scrollIntoView = function scrollIntoView(index) { if (listRef.current) { listRef.current.scrollTo({ index: index }); } }; // ========================== Active ========================== var getEnabledActiveIndex = function getEnabledActiveIndex(index) { var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var len = memoFlattenOptions.length; for (var i = 0; i < len; i += 1) { var current = (index + i * offset + len) % len; var _memoFlattenOptions$c = memoFlattenOptions[current], group = _memoFlattenOptions$c.group, data = _memoFlattenOptions$c.data; if (!group && !data.disabled) { return current; } } return -1; }; var _React$useState = React.useState(function () { return getEnabledActiveIndex(0); }), _React$useState2 = _slicedToArray(_React$useState, 2), activeIndex = _React$useState2[0], setActiveIndex = _React$useState2[1]; var setActive = function setActive(index) { setActiveIndex(index); // Trigger active event var flattenItem = memoFlattenOptions[index]; if (!flattenItem) { onActiveValue(null, -1); return; } onActiveValue(flattenItem.data.value, index); }; // Auto active first item when list length or searchValue changed React.useEffect(function () { setActive(defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1); }, [memoFlattenOptions.length, searchValue]); // Auto scroll to item position in single mode React.useEffect(function () { /** * React will skip `onChange` when component update. * `setActive` function will call root accessibility state update which makes re-render. * So we need to delay to let Input component trigger onChange first. */ var timeoutId = setTimeout(function () { if (!multiple && open && values.size === 1) { var value = Array.from(values)[0]; var index = memoFlattenOptions.findIndex(function (_ref2) { var data = _ref2.data; return data.value === value; }); setActive(index); scrollIntoView(index); } }); return function () { return clearTimeout(timeoutId); }; }, [open]); // ========================== Values ========================== var onSelectValue = function onSelectValue(value) { if (value !== undefined) { onSelect(value, { selected: !values.has(value) }); } // Single mode should always close by select if (!multiple) { onToggleOpen(false); } }; // ========================= Keyboard ========================= React.useImperativeHandle(ref, function () { return { onKeyDown: function onKeyDown(event) { var which = event.which; switch (which) { // >>> Arrow keys case _KeyCode.default.UP: case _KeyCode.default.DOWN: { var offset = 0; if (which === _KeyCode.default.UP) { offset = -1; } else if (which === _KeyCode.default.DOWN) { offset = 1; } if (offset !== 0) { var nextActiveIndex = getEnabledActiveIndex(activeIndex + offset, offset); scrollIntoView(nextActiveIndex); setActive(nextActiveIndex); } break; } // >>> Select case _KeyCode.default.ENTER: { // value var item = memoFlattenOptions[activeIndex]; if (item && !item.data.disabled) { onSelectValue(item.data.value); } else { onSelectValue(undefined); } if (open) { event.preventDefault(); } break; } // >>> Close case _KeyCode.default.ESC: { onToggleOpen(false); } } }, onKeyUp: function onKeyUp() {}, scrollTo: function scrollTo(index) { scrollIntoView(index); } }; }); // ========================== Render ========================== if (memoFlattenOptions.length === 0) { return React.createElement("div", { role: "listbox", id: "".concat(id, "_list"), className: "".concat(itemPrefixCls, "-empty"), onMouseDown: onListMouseDown }, notFoundContent); } function renderItem(index) { var item = memoFlattenOptions[index]; var value = item && item.data.value; return item ? React.createElement("div", { key: index, role: "option", id: "".concat(id, "_list_").concat(index), "aria-selected": values.has(value) }, value) : null; } return React.createElement(React.Fragment, null, React.createElement("div", { role: "listbox", id: "".concat(id, "_list"), style: { height: 0, overflow: 'hidden' } }, renderItem(activeIndex - 1), renderItem(activeIndex), renderItem(activeIndex + 1)), React.createElement(_rcVirtualList.default, { itemKey: "key", ref: listRef, data: memoFlattenOptions, height: height, itemHeight: itemHeight, fullHeight: false, onMouseDown: onListMouseDown, onScroll: onScroll, virtual: virtual }, function (_ref3, itemIndex) { var _classNames; var group = _ref3.group, groupOption = _ref3.groupOption, data = _ref3.data; var label = data.label, key = data.key; // Group if (group) { return React.createElement("div", { className: (0, _classnames.default)(itemPrefixCls, "".concat(itemPrefixCls, "-group")) }, label !== undefined ? label : key); } var disabled = data.disabled, value = data.value, title = data.title, children = data.children, style = data.style, className = data.className, otherProps = _objectWithoutProperties(data, ["disabled", "value", "title", "children", "style", "className"]); // Option var selected = values.has(value); var optionPrefixCls = "".concat(itemPrefixCls, "-option"); var optionClassName = (0, _classnames.default)(itemPrefixCls, optionPrefixCls, className, (_classNames = {}, _defineProperty(_classNames, "".concat(optionPrefixCls, "-grouped"), groupOption), _defineProperty(_classNames, "".concat(optionPrefixCls, "-active"), activeIndex === itemIndex && !disabled), _defineProperty(_classNames, "".concat(optionPrefixCls, "-disabled"), disabled), _defineProperty(_classNames, "".concat(optionPrefixCls, "-selected"), selected), _classNames)); var mergedLabel = childrenAsData ? children : label; var iconVisible = !menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected; return React.createElement("div", Object.assign({}, otherProps, { "aria-selected": selected, className: optionClassName, title: title, onMouseMove: function onMouseMove() { if (activeIndex === itemIndex || disabled) { return; } setActive(itemIndex); }, onClick: function onClick() { if (!disabled) { onSelectValue(value); } }, style: style }), React.createElement("div", { className: "".concat(optionPrefixCls, "-content") }, mergedLabel || value), React.isValidElement(menuItemSelectedIcon) || selected, iconVisible && React.createElement(_TransBtn.default, { className: "".concat(itemPrefixCls, "-option-state"), customizeIcon: menuItemSelectedIcon, customizeIconProps: { isSelected: selected } }, selected ? '✓' : null)); })); }; var RefOptionList = React.forwardRef(OptionList); RefOptionList.displayName = 'OptionList'; var _default = RefOptionList; exports.default = _default;