List.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. "use strict";
  2. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
  3. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  9. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  10. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  11. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  12. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  13. var _classnames = _interopRequireDefault(require("classnames"));
  14. var React = _interopRequireWildcard(require("react"));
  15. var _context = _interopRequireDefault(require("../context"));
  16. var _commonUtil = require("../utils/commonUtil");
  17. var _treeUtil = require("../utils/treeUtil");
  18. var _CacheContent = _interopRequireDefault(require("./CacheContent"));
  19. var _Column = _interopRequireWildcard(require("./Column"));
  20. var _useActive3 = _interopRequireDefault(require("./useActive"));
  21. var _useKeyboard = _interopRequireDefault(require("./useKeyboard"));
  22. /* eslint-disable default-case */
  23. var RawOptionList = /*#__PURE__*/React.forwardRef(function (props, ref) {
  24. var _optionColumns$, _ref3, _classNames;
  25. var prefixCls = props.prefixCls,
  26. multiple = props.multiple,
  27. searchValue = props.searchValue,
  28. toggleOpen = props.toggleOpen,
  29. notFoundContent = props.notFoundContent,
  30. direction = props.direction,
  31. open = props.open,
  32. disabled = props.disabled;
  33. var containerRef = React.useRef(null);
  34. var rtl = direction === 'rtl';
  35. var _React$useContext = React.useContext(_context.default),
  36. options = _React$useContext.options,
  37. values = _React$useContext.values,
  38. halfValues = _React$useContext.halfValues,
  39. fieldNames = _React$useContext.fieldNames,
  40. changeOnSelect = _React$useContext.changeOnSelect,
  41. onSelect = _React$useContext.onSelect,
  42. searchOptions = _React$useContext.searchOptions,
  43. dropdownPrefixCls = _React$useContext.dropdownPrefixCls,
  44. loadData = _React$useContext.loadData,
  45. expandTrigger = _React$useContext.expandTrigger;
  46. var mergedPrefixCls = dropdownPrefixCls || prefixCls;
  47. // ========================= loadData =========================
  48. var _React$useState = React.useState([]),
  49. _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
  50. loadingKeys = _React$useState2[0],
  51. setLoadingKeys = _React$useState2[1];
  52. var internalLoadData = function internalLoadData(valueCells) {
  53. // Do not load when search
  54. if (!loadData || searchValue) {
  55. return;
  56. }
  57. var optionList = (0, _treeUtil.toPathOptions)(valueCells, options, fieldNames);
  58. var rawOptions = optionList.map(function (_ref) {
  59. var option = _ref.option;
  60. return option;
  61. });
  62. var lastOption = rawOptions[rawOptions.length - 1];
  63. if (lastOption && !(0, _commonUtil.isLeaf)(lastOption, fieldNames)) {
  64. var pathKey = (0, _commonUtil.toPathKey)(valueCells);
  65. setLoadingKeys(function (keys) {
  66. return [].concat((0, _toConsumableArray2.default)(keys), [pathKey]);
  67. });
  68. loadData(rawOptions);
  69. }
  70. };
  71. // zombieJ: This is bad. We should make this same as `rc-tree` to use Promise instead.
  72. React.useEffect(function () {
  73. if (loadingKeys.length) {
  74. loadingKeys.forEach(function (loadingKey) {
  75. var valueStrCells = (0, _commonUtil.toPathValueStr)(loadingKey);
  76. var optionList = (0, _treeUtil.toPathOptions)(valueStrCells, options, fieldNames, true).map(function (_ref2) {
  77. var option = _ref2.option;
  78. return option;
  79. });
  80. var lastOption = optionList[optionList.length - 1];
  81. if (!lastOption || lastOption[fieldNames.children] || (0, _commonUtil.isLeaf)(lastOption, fieldNames)) {
  82. setLoadingKeys(function (keys) {
  83. return keys.filter(function (key) {
  84. return key !== loadingKey;
  85. });
  86. });
  87. }
  88. });
  89. }
  90. }, [options, loadingKeys, fieldNames]);
  91. // ========================== Values ==========================
  92. var checkedSet = React.useMemo(function () {
  93. return new Set((0, _commonUtil.toPathKeys)(values));
  94. }, [values]);
  95. var halfCheckedSet = React.useMemo(function () {
  96. return new Set((0, _commonUtil.toPathKeys)(halfValues));
  97. }, [halfValues]);
  98. // ====================== Accessibility =======================
  99. var _useActive = (0, _useActive3.default)(multiple, open),
  100. _useActive2 = (0, _slicedToArray2.default)(_useActive, 2),
  101. activeValueCells = _useActive2[0],
  102. setActiveValueCells = _useActive2[1];
  103. // =========================== Path ===========================
  104. var onPathOpen = function onPathOpen(nextValueCells) {
  105. setActiveValueCells(nextValueCells);
  106. // Trigger loadData
  107. internalLoadData(nextValueCells);
  108. };
  109. var isSelectable = function isSelectable(option) {
  110. if (disabled) {
  111. return false;
  112. }
  113. var optionDisabled = option.disabled;
  114. var isMergedLeaf = (0, _commonUtil.isLeaf)(option, fieldNames);
  115. return !optionDisabled && (isMergedLeaf || changeOnSelect || multiple);
  116. };
  117. var onPathSelect = function onPathSelect(valuePath, leaf) {
  118. var fromKeyboard = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  119. onSelect(valuePath);
  120. if (!multiple && (leaf || changeOnSelect && (expandTrigger === 'hover' || fromKeyboard))) {
  121. toggleOpen(false);
  122. }
  123. };
  124. // ========================== Option ==========================
  125. var mergedOptions = React.useMemo(function () {
  126. if (searchValue) {
  127. return searchOptions;
  128. }
  129. return options;
  130. }, [searchValue, searchOptions, options]);
  131. // ========================== Column ==========================
  132. var optionColumns = React.useMemo(function () {
  133. var optionList = [{
  134. options: mergedOptions
  135. }];
  136. var currentList = mergedOptions;
  137. var fullPathKeys = (0, _commonUtil.getFullPathKeys)(currentList, fieldNames);
  138. var _loop = function _loop() {
  139. var activeValueCell = activeValueCells[i];
  140. var currentOption = currentList.find(function (option, index) {
  141. return (fullPathKeys[index] ? (0, _commonUtil.toPathKey)(fullPathKeys[index]) : option[fieldNames.value]) === activeValueCell;
  142. });
  143. var subOptions = currentOption === null || currentOption === void 0 ? void 0 : currentOption[fieldNames.children];
  144. if (!(subOptions !== null && subOptions !== void 0 && subOptions.length)) {
  145. return 1; // break
  146. }
  147. currentList = subOptions;
  148. optionList.push({
  149. options: subOptions
  150. });
  151. };
  152. for (var i = 0; i < activeValueCells.length; i += 1) {
  153. if (_loop()) break;
  154. }
  155. return optionList;
  156. }, [mergedOptions, activeValueCells, fieldNames]);
  157. // ========================= Keyboard =========================
  158. var onKeyboardSelect = function onKeyboardSelect(selectValueCells, option) {
  159. if (isSelectable(option)) {
  160. onPathSelect(selectValueCells, (0, _commonUtil.isLeaf)(option, fieldNames), true);
  161. }
  162. };
  163. (0, _useKeyboard.default)(ref, mergedOptions, fieldNames, activeValueCells, onPathOpen, onKeyboardSelect, {
  164. direction: direction,
  165. searchValue: searchValue,
  166. toggleOpen: toggleOpen,
  167. open: open
  168. });
  169. // >>>>> Active Scroll
  170. React.useEffect(function () {
  171. if (searchValue) {
  172. return;
  173. }
  174. for (var i = 0; i < activeValueCells.length; i += 1) {
  175. var _containerRef$current;
  176. var cellPath = activeValueCells.slice(0, i + 1);
  177. var cellKeyPath = (0, _commonUtil.toPathKey)(cellPath);
  178. var ele = (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.querySelector("li[data-path-key=\"".concat(cellKeyPath.replace(/\\{0,2}"/g, '\\"'), "\"]") // matches unescaped double quotes
  179. );
  180. if (ele) {
  181. (0, _commonUtil.scrollIntoParentView)(ele);
  182. }
  183. }
  184. }, [activeValueCells, searchValue]);
  185. // ========================== Render ==========================
  186. // >>>>> Empty
  187. var isEmpty = !((_optionColumns$ = optionColumns[0]) !== null && _optionColumns$ !== void 0 && (_optionColumns$ = _optionColumns$.options) !== null && _optionColumns$ !== void 0 && _optionColumns$.length);
  188. var emptyList = [(_ref3 = {}, (0, _defineProperty2.default)(_ref3, fieldNames.value, '__EMPTY__'), (0, _defineProperty2.default)(_ref3, _Column.FIX_LABEL, notFoundContent), (0, _defineProperty2.default)(_ref3, "disabled", true), _ref3)];
  189. var columnProps = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
  190. multiple: !isEmpty && multiple,
  191. onSelect: onPathSelect,
  192. onActive: onPathOpen,
  193. onToggleOpen: toggleOpen,
  194. checkedSet: checkedSet,
  195. halfCheckedSet: halfCheckedSet,
  196. loadingKeys: loadingKeys,
  197. isSelectable: isSelectable
  198. });
  199. // >>>>> Columns
  200. var mergedOptionColumns = isEmpty ? [{
  201. options: emptyList
  202. }] : optionColumns;
  203. var columnNodes = mergedOptionColumns.map(function (col, index) {
  204. var prevValuePath = activeValueCells.slice(0, index);
  205. var activeValue = activeValueCells[index];
  206. return /*#__PURE__*/React.createElement(_Column.default, (0, _extends2.default)({
  207. key: index
  208. }, columnProps, {
  209. prefixCls: mergedPrefixCls,
  210. options: col.options,
  211. prevValuePath: prevValuePath,
  212. activeValue: activeValue
  213. }));
  214. });
  215. // >>>>> Render
  216. return /*#__PURE__*/React.createElement(_CacheContent.default, {
  217. open: open
  218. }, /*#__PURE__*/React.createElement("div", {
  219. className: (0, _classnames.default)("".concat(mergedPrefixCls, "-menus"), (_classNames = {}, (0, _defineProperty2.default)(_classNames, "".concat(mergedPrefixCls, "-menu-empty"), isEmpty), (0, _defineProperty2.default)(_classNames, "".concat(mergedPrefixCls, "-rtl"), rtl), _classNames)),
  220. ref: containerRef
  221. }, columnNodes));
  222. });
  223. if (process.env.NODE_ENV !== 'production') {
  224. RawOptionList.displayName = 'RawOptionList';
  225. }
  226. var _default = exports.default = RawOptionList;