list.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. "use strict";
  2. "use client";
  3. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  4. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
  5. Object.defineProperty(exports, "__esModule", {
  6. value: true
  7. });
  8. exports.default = void 0;
  9. var _react = _interopRequireWildcard(require("react"));
  10. var _DownOutlined = _interopRequireDefault(require("@ant-design/icons/DownOutlined"));
  11. var _classnames = _interopRequireDefault(require("classnames"));
  12. var _omit = _interopRequireDefault(require("rc-util/lib/omit"));
  13. var _transKeys = require("../_util/transKeys");
  14. var _checkbox = _interopRequireDefault(require("../checkbox"));
  15. var _dropdown = _interopRequireDefault(require("../dropdown"));
  16. var _ListBody = _interopRequireWildcard(require("./ListBody"));
  17. var _search = _interopRequireDefault(require("./search"));
  18. const defaultRender = () => null;
  19. function isRenderResultPlainObject(result) {
  20. return !!(result && ! /*#__PURE__*/_react.default.isValidElement(result) && Object.prototype.toString.call(result) === '[object Object]');
  21. }
  22. function getEnabledItemKeys(items) {
  23. return items.filter(data => !data.disabled).map(data => data.key);
  24. }
  25. const isValidIcon = icon => icon !== undefined;
  26. const getShowSearchOption = showSearch => {
  27. if (showSearch && typeof showSearch === 'object') {
  28. return Object.assign(Object.assign({}, showSearch), {
  29. defaultValue: showSearch.defaultValue || ''
  30. });
  31. }
  32. return {
  33. defaultValue: '',
  34. placeholder: ''
  35. };
  36. };
  37. const TransferList = props => {
  38. const {
  39. prefixCls,
  40. dataSource = [],
  41. titleText = '',
  42. checkedKeys,
  43. disabled,
  44. showSearch = false,
  45. style,
  46. searchPlaceholder,
  47. notFoundContent,
  48. selectAll,
  49. deselectAll,
  50. selectCurrent,
  51. selectInvert,
  52. removeAll,
  53. removeCurrent,
  54. showSelectAll = true,
  55. showRemove,
  56. pagination,
  57. direction,
  58. itemsUnit,
  59. itemUnit,
  60. selectAllLabel,
  61. selectionsIcon,
  62. footer,
  63. renderList,
  64. onItemSelectAll,
  65. onItemRemove,
  66. handleFilter,
  67. handleClear,
  68. filterOption,
  69. render = defaultRender
  70. } = props;
  71. const searchOptions = getShowSearchOption(showSearch);
  72. const [filterValue, setFilterValue] = (0, _react.useState)(searchOptions.defaultValue);
  73. const listBodyRef = (0, _react.useRef)({});
  74. const internalHandleFilter = e => {
  75. setFilterValue(e.target.value);
  76. handleFilter(e);
  77. };
  78. const internalHandleClear = () => {
  79. setFilterValue('');
  80. handleClear();
  81. };
  82. const matchFilter = (text, item) => {
  83. if (filterOption) {
  84. return filterOption(filterValue, item, direction);
  85. }
  86. return text.includes(filterValue);
  87. };
  88. const renderListBody = listProps => {
  89. let bodyContent = renderList ? renderList(Object.assign(Object.assign({}, listProps), {
  90. onItemSelect: (key, check) => listProps.onItemSelect(key, check)
  91. })) : null;
  92. const customize = !!bodyContent;
  93. if (!customize) {
  94. // @ts-ignore
  95. bodyContent = /*#__PURE__*/_react.default.createElement(_ListBody.default, Object.assign({
  96. ref: listBodyRef
  97. }, listProps));
  98. }
  99. return {
  100. customize,
  101. bodyContent
  102. };
  103. };
  104. const renderItem = item => {
  105. const renderResult = render(item);
  106. const isRenderResultPlain = isRenderResultPlainObject(renderResult);
  107. return {
  108. item,
  109. renderedEl: isRenderResultPlain ? renderResult.label : renderResult,
  110. renderedText: isRenderResultPlain ? renderResult.value : renderResult
  111. };
  112. };
  113. const notFoundContentEle = (0, _react.useMemo)(() => Array.isArray(notFoundContent) ? notFoundContent[direction === 'left' ? 0 : 1] : notFoundContent, [notFoundContent, direction]);
  114. const [filteredItems, filteredRenderItems] = (0, _react.useMemo)(() => {
  115. const filterItems = [];
  116. const filterRenderItems = [];
  117. dataSource.forEach(item => {
  118. const renderedItem = renderItem(item);
  119. if (filterValue && !matchFilter(renderedItem.renderedText, item)) {
  120. return;
  121. }
  122. filterItems.push(item);
  123. filterRenderItems.push(renderedItem);
  124. });
  125. return [filterItems, filterRenderItems];
  126. }, [dataSource, filterValue]);
  127. const checkedActiveItems = (0, _react.useMemo)(() => {
  128. return filteredItems.filter(item => checkedKeys.includes(item.key) && !item.disabled);
  129. }, [checkedKeys, filteredItems]);
  130. const checkStatus = (0, _react.useMemo)(() => {
  131. if (checkedActiveItems.length === 0) {
  132. return 'none';
  133. }
  134. const checkedKeysMap = (0, _transKeys.groupKeysMap)(checkedKeys);
  135. if (filteredItems.every(item => checkedKeysMap.has(item.key) || !!item.disabled)) {
  136. return 'all';
  137. }
  138. return 'part';
  139. }, [checkedKeys, checkedActiveItems]);
  140. const listBody = (0, _react.useMemo)(() => {
  141. const search = showSearch ? (/*#__PURE__*/_react.default.createElement("div", {
  142. className: `${prefixCls}-body-search-wrapper`
  143. }, /*#__PURE__*/_react.default.createElement(_search.default, {
  144. prefixCls: `${prefixCls}-search`,
  145. onChange: internalHandleFilter,
  146. handleClear: internalHandleClear,
  147. placeholder: searchOptions.placeholder || searchPlaceholder,
  148. value: filterValue,
  149. disabled: disabled
  150. }))) : null;
  151. const {
  152. customize,
  153. bodyContent
  154. } = renderListBody(Object.assign(Object.assign({}, (0, _omit.default)(props, _ListBody.OmitProps)), {
  155. filteredItems,
  156. filteredRenderItems,
  157. selectedKeys: checkedKeys
  158. }));
  159. let bodyNode;
  160. // We should wrap customize list body in a classNamed div to use flex layout.
  161. if (customize) {
  162. bodyNode = /*#__PURE__*/_react.default.createElement("div", {
  163. className: `${prefixCls}-body-customize-wrapper`
  164. }, bodyContent);
  165. } else {
  166. bodyNode = filteredItems.length ? bodyContent : (/*#__PURE__*/_react.default.createElement("div", {
  167. className: `${prefixCls}-body-not-found`
  168. }, notFoundContentEle));
  169. }
  170. return /*#__PURE__*/_react.default.createElement("div", {
  171. className: (0, _classnames.default)(`${prefixCls}-body`, {
  172. [`${prefixCls}-body-with-search`]: showSearch
  173. })
  174. }, search, bodyNode);
  175. }, [showSearch, prefixCls, searchPlaceholder, filterValue, disabled, checkedKeys, filteredItems, filteredRenderItems, notFoundContentEle]);
  176. const checkBox = /*#__PURE__*/_react.default.createElement(_checkbox.default, {
  177. disabled: dataSource.filter(d => !d.disabled).length === 0 || disabled,
  178. checked: checkStatus === 'all',
  179. indeterminate: checkStatus === 'part',
  180. className: `${prefixCls}-checkbox`,
  181. onChange: () => {
  182. // Only select enabled items
  183. onItemSelectAll === null || onItemSelectAll === void 0 ? void 0 : onItemSelectAll(filteredItems.filter(item => !item.disabled).map(({
  184. key
  185. }) => key), checkStatus !== 'all');
  186. }
  187. });
  188. const getSelectAllLabel = (selectedCount, totalCount) => {
  189. if (selectAllLabel) {
  190. return typeof selectAllLabel === 'function' ? selectAllLabel({
  191. selectedCount,
  192. totalCount
  193. }) : selectAllLabel;
  194. }
  195. const unit = totalCount > 1 ? itemsUnit : itemUnit;
  196. return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (selectedCount > 0 ? `${selectedCount}/` : '') + totalCount, " ", unit);
  197. };
  198. // Custom Layout
  199. const footerDom = footer && (footer.length < 2 ? footer(props) : footer(props, {
  200. direction
  201. }));
  202. const listCls = (0, _classnames.default)(prefixCls, {
  203. [`${prefixCls}-with-pagination`]: !!pagination,
  204. [`${prefixCls}-with-footer`]: !!footerDom
  205. });
  206. // ====================== Get filtered, checked item list ======================
  207. const listFooter = footerDom ? /*#__PURE__*/_react.default.createElement("div", {
  208. className: `${prefixCls}-footer`
  209. }, footerDom) : null;
  210. const checkAllCheckbox = !showRemove && !pagination && checkBox;
  211. let items;
  212. if (showRemove) {
  213. items = [/* Remove Current Page */
  214. pagination ? {
  215. key: 'removeCurrent',
  216. label: removeCurrent,
  217. onClick() {
  218. var _a;
  219. const pageKeys = getEnabledItemKeys((((_a = listBodyRef.current) === null || _a === void 0 ? void 0 : _a.items) || []).map(entity => entity.item));
  220. onItemRemove === null || onItemRemove === void 0 ? void 0 : onItemRemove(pageKeys);
  221. }
  222. } : null, /* Remove All */
  223. {
  224. key: 'removeAll',
  225. label: removeAll,
  226. onClick() {
  227. onItemRemove === null || onItemRemove === void 0 ? void 0 : onItemRemove(getEnabledItemKeys(filteredItems));
  228. }
  229. }].filter(Boolean);
  230. } else {
  231. items = [{
  232. key: 'selectAll',
  233. label: checkStatus === 'all' ? deselectAll : selectAll,
  234. onClick() {
  235. const keys = getEnabledItemKeys(filteredItems);
  236. onItemSelectAll === null || onItemSelectAll === void 0 ? void 0 : onItemSelectAll(keys, keys.length !== checkedKeys.length);
  237. }
  238. }, pagination ? {
  239. key: 'selectCurrent',
  240. label: selectCurrent,
  241. onClick() {
  242. var _a;
  243. const pageItems = ((_a = listBodyRef.current) === null || _a === void 0 ? void 0 : _a.items) || [];
  244. onItemSelectAll === null || onItemSelectAll === void 0 ? void 0 : onItemSelectAll(getEnabledItemKeys(pageItems.map(entity => entity.item)), true);
  245. }
  246. } : null, {
  247. key: 'selectInvert',
  248. label: selectInvert,
  249. onClick() {
  250. var _a;
  251. const availablePageItemKeys = getEnabledItemKeys((((_a = listBodyRef.current) === null || _a === void 0 ? void 0 : _a.items) || []).map(entity => entity.item));
  252. const checkedKeySet = new Set(checkedKeys);
  253. const newCheckedKeysSet = new Set(checkedKeySet);
  254. availablePageItemKeys.forEach(key => {
  255. if (checkedKeySet.has(key)) {
  256. newCheckedKeysSet.delete(key);
  257. } else {
  258. newCheckedKeysSet.add(key);
  259. }
  260. });
  261. onItemSelectAll === null || onItemSelectAll === void 0 ? void 0 : onItemSelectAll(Array.from(newCheckedKeysSet), 'replace');
  262. }
  263. }];
  264. }
  265. const dropdown = /*#__PURE__*/_react.default.createElement(_dropdown.default, {
  266. className: `${prefixCls}-header-dropdown`,
  267. menu: {
  268. items
  269. },
  270. disabled: disabled
  271. }, isValidIcon(selectionsIcon) ? selectionsIcon : /*#__PURE__*/_react.default.createElement(_DownOutlined.default, null));
  272. return /*#__PURE__*/_react.default.createElement("div", {
  273. className: listCls,
  274. style: style
  275. }, /*#__PURE__*/_react.default.createElement("div", {
  276. className: `${prefixCls}-header`
  277. }, showSelectAll ? (/*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, checkAllCheckbox, dropdown)) : null, /*#__PURE__*/_react.default.createElement("span", {
  278. className: `${prefixCls}-header-selected`
  279. }, getSelectAllLabel(checkedActiveItems.length, filteredItems.length)), /*#__PURE__*/_react.default.createElement("span", {
  280. className: `${prefixCls}-header-title`
  281. }, titleText)), listBody, listFooter);
  282. };
  283. if (process.env.NODE_ENV !== 'production') {
  284. TransferList.displayName = 'TransferList';
  285. }
  286. var _default = exports.default = TransferList;