index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. "use strict";
  2. "use client";
  3. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
  4. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  5. Object.defineProperty(exports, "__esModule", {
  6. value: true
  7. });
  8. exports.default = void 0;
  9. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  10. var _react = _interopRequireWildcard(require("react"));
  11. var _classnames = _interopRequireDefault(require("classnames"));
  12. var _useMultipleSelect = _interopRequireDefault(require("../_util/hooks/useMultipleSelect"));
  13. var _statusUtils = require("../_util/statusUtils");
  14. var _transKeys = require("../_util/transKeys");
  15. var _warning = require("../_util/warning");
  16. var _configProvider = require("../config-provider");
  17. var _defaultRenderEmpty = _interopRequireDefault(require("../config-provider/defaultRenderEmpty"));
  18. var _context = require("../form/context");
  19. var _locale = require("../locale");
  20. var _en_US = _interopRequireDefault(require("../locale/en_US"));
  21. var _useData = _interopRequireDefault(require("./hooks/useData"));
  22. var _useSelection = _interopRequireDefault(require("./hooks/useSelection"));
  23. var _list = _interopRequireDefault(require("./list"));
  24. var _operation = _interopRequireDefault(require("./operation"));
  25. var _search = _interopRequireDefault(require("./search"));
  26. var _style = _interopRequireDefault(require("./style"));
  27. const Transfer = props => {
  28. const {
  29. dataSource,
  30. targetKeys = [],
  31. selectedKeys,
  32. selectAllLabels = [],
  33. operations = [],
  34. style = {},
  35. listStyle = {},
  36. locale = {},
  37. titles,
  38. disabled,
  39. showSearch = false,
  40. operationStyle,
  41. showSelectAll,
  42. oneWay,
  43. pagination,
  44. status: customStatus,
  45. prefixCls: customizePrefixCls,
  46. className,
  47. rootClassName,
  48. selectionsIcon,
  49. filterOption,
  50. render,
  51. footer,
  52. children,
  53. rowKey,
  54. onScroll,
  55. onChange,
  56. onSearch,
  57. onSelectChange
  58. } = props;
  59. const {
  60. getPrefixCls,
  61. renderEmpty,
  62. direction: dir,
  63. transfer
  64. } = (0, _react.useContext)(_configProvider.ConfigContext);
  65. const prefixCls = getPrefixCls('transfer', customizePrefixCls);
  66. const [wrapCSSVar, hashId, cssVarCls] = (0, _style.default)(prefixCls);
  67. // Fill record with `key`
  68. const [mergedDataSource, leftDataSource, rightDataSource] = (0, _useData.default)(dataSource, rowKey, targetKeys);
  69. // Get direction selected keys
  70. const [
  71. // Keys
  72. sourceSelectedKeys, targetSelectedKeys,
  73. // Setters
  74. setSourceSelectedKeys, setTargetSelectedKeys] = (0, _useSelection.default)(leftDataSource, rightDataSource, selectedKeys);
  75. const [leftMultipleSelect, updateLeftPrevSelectedIndex] = (0, _useMultipleSelect.default)(item => item.key);
  76. const [rightMultipleSelect, updateRightPrevSelectedIndex] = (0, _useMultipleSelect.default)(item => item.key);
  77. if (process.env.NODE_ENV !== 'production') {
  78. const warning = (0, _warning.devUseWarning)('Transfer');
  79. process.env.NODE_ENV !== "production" ? warning(!pagination || !children, 'usage', '`pagination` not support customize render list.') : void 0;
  80. }
  81. const setStateKeys = (0, _react.useCallback)((direction, keys) => {
  82. if (direction === 'left') {
  83. const nextKeys = typeof keys === 'function' ? keys(sourceSelectedKeys || []) : keys;
  84. setSourceSelectedKeys(nextKeys);
  85. } else {
  86. const nextKeys = typeof keys === 'function' ? keys(targetSelectedKeys || []) : keys;
  87. setTargetSelectedKeys(nextKeys);
  88. }
  89. }, [sourceSelectedKeys, targetSelectedKeys]);
  90. const setPrevSelectedIndex = (direction, value) => {
  91. const isLeftDirection = direction === 'left';
  92. const updatePrevSelectedIndex = isLeftDirection ? updateLeftPrevSelectedIndex : updateRightPrevSelectedIndex;
  93. updatePrevSelectedIndex(value);
  94. };
  95. const handleSelectChange = (0, _react.useCallback)((direction, holder) => {
  96. if (direction === 'left') {
  97. onSelectChange === null || onSelectChange === void 0 ? void 0 : onSelectChange(holder, targetSelectedKeys);
  98. } else {
  99. onSelectChange === null || onSelectChange === void 0 ? void 0 : onSelectChange(sourceSelectedKeys, holder);
  100. }
  101. }, [sourceSelectedKeys, targetSelectedKeys]);
  102. const getTitles = transferLocale => {
  103. var _a;
  104. return (_a = titles !== null && titles !== void 0 ? titles : transferLocale.titles) !== null && _a !== void 0 ? _a : [];
  105. };
  106. const handleLeftScroll = e => {
  107. onScroll === null || onScroll === void 0 ? void 0 : onScroll('left', e);
  108. };
  109. const handleRightScroll = e => {
  110. onScroll === null || onScroll === void 0 ? void 0 : onScroll('right', e);
  111. };
  112. const moveTo = direction => {
  113. const moveKeys = direction === 'right' ? sourceSelectedKeys : targetSelectedKeys;
  114. const dataSourceDisabledKeysMap = (0, _transKeys.groupDisabledKeysMap)(mergedDataSource);
  115. // filter the disabled options
  116. const newMoveKeys = moveKeys.filter(key => !dataSourceDisabledKeysMap.has(key));
  117. const newMoveKeysMap = (0, _transKeys.groupKeysMap)(newMoveKeys);
  118. // move items to target box
  119. const newTargetKeys = direction === 'right' ? newMoveKeys.concat(targetKeys) : targetKeys.filter(targetKey => !newMoveKeysMap.has(targetKey));
  120. // empty checked keys
  121. const oppositeDirection = direction === 'right' ? 'left' : 'right';
  122. setStateKeys(oppositeDirection, []);
  123. handleSelectChange(oppositeDirection, []);
  124. onChange === null || onChange === void 0 ? void 0 : onChange(newTargetKeys, direction, newMoveKeys);
  125. };
  126. const moveToLeft = () => {
  127. moveTo('left');
  128. setPrevSelectedIndex('left', null);
  129. };
  130. const moveToRight = () => {
  131. moveTo('right');
  132. setPrevSelectedIndex('right', null);
  133. };
  134. const onItemSelectAll = (direction, keys, checkAll) => {
  135. setStateKeys(direction, prevKeys => {
  136. let mergedCheckedKeys = [];
  137. if (checkAll === 'replace') {
  138. mergedCheckedKeys = keys;
  139. } else if (checkAll) {
  140. // Merge current keys with origin key
  141. mergedCheckedKeys = Array.from(new Set([].concat((0, _toConsumableArray2.default)(prevKeys), (0, _toConsumableArray2.default)(keys))));
  142. } else {
  143. const selectedKeysMap = (0, _transKeys.groupKeysMap)(keys);
  144. // Remove current keys from origin keys
  145. mergedCheckedKeys = prevKeys.filter(key => !selectedKeysMap.has(key));
  146. }
  147. handleSelectChange(direction, mergedCheckedKeys);
  148. return mergedCheckedKeys;
  149. });
  150. setPrevSelectedIndex(direction, null);
  151. };
  152. const onLeftItemSelectAll = (keys, checkAll) => {
  153. onItemSelectAll('left', keys, checkAll);
  154. };
  155. const onRightItemSelectAll = (keys, checkAll) => {
  156. onItemSelectAll('right', keys, checkAll);
  157. };
  158. const leftFilter = e => onSearch === null || onSearch === void 0 ? void 0 : onSearch('left', e.target.value);
  159. const rightFilter = e => onSearch === null || onSearch === void 0 ? void 0 : onSearch('right', e.target.value);
  160. const handleLeftClear = () => onSearch === null || onSearch === void 0 ? void 0 : onSearch('left', '');
  161. const handleRightClear = () => onSearch === null || onSearch === void 0 ? void 0 : onSearch('right', '');
  162. const handleSingleSelect = (direction, holder, selectedKey, checked, currentSelectedIndex) => {
  163. const isSelected = holder.has(selectedKey);
  164. if (isSelected) {
  165. holder.delete(selectedKey);
  166. setPrevSelectedIndex(direction, null);
  167. }
  168. if (checked) {
  169. holder.add(selectedKey);
  170. setPrevSelectedIndex(direction, currentSelectedIndex);
  171. }
  172. };
  173. const handleMultipleSelect = (direction, data, holder, currentSelectedIndex) => {
  174. const isLeftDirection = direction === 'left';
  175. const multipleSelect = isLeftDirection ? leftMultipleSelect : rightMultipleSelect;
  176. multipleSelect(currentSelectedIndex, data, holder);
  177. };
  178. const onItemSelect = (direction, selectedKey, checked, multiple) => {
  179. const isLeftDirection = direction === 'left';
  180. const holder = (0, _toConsumableArray2.default)(isLeftDirection ? sourceSelectedKeys : targetSelectedKeys);
  181. const holderSet = new Set(holder);
  182. const data = (0, _toConsumableArray2.default)(isLeftDirection ? leftDataSource : rightDataSource).filter(item => !(item === null || item === void 0 ? void 0 : item.disabled));
  183. const currentSelectedIndex = data.findIndex(item => item.key === selectedKey);
  184. // multiple select by hold down the shift key
  185. if (multiple && holder.length > 0) {
  186. handleMultipleSelect(direction, data, holderSet, currentSelectedIndex);
  187. } else {
  188. handleSingleSelect(direction, holderSet, selectedKey, checked, currentSelectedIndex);
  189. }
  190. const holderArr = Array.from(holderSet);
  191. handleSelectChange(direction, holderArr);
  192. if (!props.selectedKeys) {
  193. setStateKeys(direction, holderArr);
  194. }
  195. };
  196. const onLeftItemSelect = (selectedKey, checked, e) => {
  197. onItemSelect('left', selectedKey, checked, e === null || e === void 0 ? void 0 : e.shiftKey);
  198. };
  199. const onRightItemSelect = (selectedKey, checked, e) => {
  200. onItemSelect('right', selectedKey, checked, e === null || e === void 0 ? void 0 : e.shiftKey);
  201. };
  202. const onRightItemRemove = keys => {
  203. setStateKeys('right', []);
  204. onChange === null || onChange === void 0 ? void 0 : onChange(targetKeys.filter(key => !keys.includes(key)), 'left', (0, _toConsumableArray2.default)(keys));
  205. };
  206. const handleListStyle = direction => {
  207. if (typeof listStyle === 'function') {
  208. return listStyle({
  209. direction
  210. });
  211. }
  212. return listStyle || {};
  213. };
  214. const formItemContext = (0, _react.useContext)(_context.FormItemInputContext);
  215. const {
  216. hasFeedback,
  217. status
  218. } = formItemContext;
  219. const getLocale = transferLocale => Object.assign(Object.assign(Object.assign({}, transferLocale), {
  220. notFoundContent: (renderEmpty === null || renderEmpty === void 0 ? void 0 : renderEmpty('Transfer')) || /*#__PURE__*/_react.default.createElement(_defaultRenderEmpty.default, {
  221. componentName: "Transfer"
  222. })
  223. }), locale);
  224. const mergedStatus = (0, _statusUtils.getMergedStatus)(status, customStatus);
  225. const mergedPagination = !children && pagination;
  226. const leftActive = rightDataSource.filter(d => targetSelectedKeys.includes(d.key) && !d.disabled).length > 0;
  227. const rightActive = leftDataSource.filter(d => sourceSelectedKeys.includes(d.key) && !d.disabled).length > 0;
  228. const cls = (0, _classnames.default)(prefixCls, {
  229. [`${prefixCls}-disabled`]: disabled,
  230. [`${prefixCls}-customize-list`]: !!children,
  231. [`${prefixCls}-rtl`]: dir === 'rtl'
  232. }, (0, _statusUtils.getStatusClassNames)(prefixCls, mergedStatus, hasFeedback), transfer === null || transfer === void 0 ? void 0 : transfer.className, className, rootClassName, hashId, cssVarCls);
  233. const [contextLocale] = (0, _locale.useLocale)('Transfer', _en_US.default.Transfer);
  234. const listLocale = getLocale(contextLocale);
  235. const [leftTitle, rightTitle] = getTitles(listLocale);
  236. const mergedSelectionsIcon = selectionsIcon !== null && selectionsIcon !== void 0 ? selectionsIcon : transfer === null || transfer === void 0 ? void 0 : transfer.selectionsIcon;
  237. return wrapCSSVar(/*#__PURE__*/_react.default.createElement("div", {
  238. className: cls,
  239. style: Object.assign(Object.assign({}, transfer === null || transfer === void 0 ? void 0 : transfer.style), style)
  240. }, /*#__PURE__*/_react.default.createElement(_list.default, Object.assign({
  241. prefixCls: `${prefixCls}-list`,
  242. titleText: leftTitle,
  243. dataSource: leftDataSource,
  244. filterOption: filterOption,
  245. style: handleListStyle('left'),
  246. checkedKeys: sourceSelectedKeys,
  247. handleFilter: leftFilter,
  248. handleClear: handleLeftClear,
  249. onItemSelect: onLeftItemSelect,
  250. onItemSelectAll: onLeftItemSelectAll,
  251. render: render,
  252. showSearch: showSearch,
  253. renderList: children,
  254. footer: footer,
  255. onScroll: handleLeftScroll,
  256. disabled: disabled,
  257. direction: dir === 'rtl' ? 'right' : 'left',
  258. showSelectAll: showSelectAll,
  259. selectAllLabel: selectAllLabels[0],
  260. pagination: mergedPagination,
  261. selectionsIcon: mergedSelectionsIcon
  262. }, listLocale)), /*#__PURE__*/_react.default.createElement(_operation.default, {
  263. className: `${prefixCls}-operation`,
  264. rightActive: rightActive,
  265. rightArrowText: operations[0],
  266. moveToRight: moveToRight,
  267. leftActive: leftActive,
  268. leftArrowText: operations[1],
  269. moveToLeft: moveToLeft,
  270. style: operationStyle,
  271. disabled: disabled,
  272. direction: dir,
  273. oneWay: oneWay
  274. }), /*#__PURE__*/_react.default.createElement(_list.default, Object.assign({
  275. prefixCls: `${prefixCls}-list`,
  276. titleText: rightTitle,
  277. dataSource: rightDataSource,
  278. filterOption: filterOption,
  279. style: handleListStyle('right'),
  280. checkedKeys: targetSelectedKeys,
  281. handleFilter: rightFilter,
  282. handleClear: handleRightClear,
  283. onItemSelect: onRightItemSelect,
  284. onItemSelectAll: onRightItemSelectAll,
  285. onItemRemove: onRightItemRemove,
  286. render: render,
  287. showSearch: showSearch,
  288. renderList: children,
  289. footer: footer,
  290. onScroll: handleRightScroll,
  291. disabled: disabled,
  292. direction: dir === 'rtl' ? 'left' : 'right',
  293. showSelectAll: showSelectAll,
  294. selectAllLabel: selectAllLabels[1],
  295. showRemove: oneWay,
  296. pagination: mergedPagination,
  297. selectionsIcon: mergedSelectionsIcon
  298. }, listLocale))));
  299. };
  300. if (process.env.NODE_ENV !== 'production') {
  301. Transfer.displayName = 'Transfer';
  302. }
  303. Transfer.List = _list.default;
  304. Transfer.Search = _search.default;
  305. Transfer.Operation = _operation.default;
  306. var _default = exports.default = Transfer;