list.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  2. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  3. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  4. import { createTextVNode as _createTextVNode, Fragment as _Fragment, createVNode as _createVNode } from "vue";
  5. import classNames from '../_util/classNames';
  6. import PropTypes from '../_util/vue-types';
  7. import { isValidElement, splitAttrs, filterEmpty } from '../_util/props-util';
  8. import DownOutlined from "@ant-design/icons-vue/es/icons/DownOutlined";
  9. import Checkbox from '../checkbox';
  10. import Menu from '../menu';
  11. import Dropdown from '../dropdown';
  12. import Search from './search';
  13. import ListBody from './ListBody';
  14. import { watchEffect, computed, defineComponent, ref } from 'vue';
  15. var defaultRender = function defaultRender() {
  16. return null;
  17. };
  18. function isRenderResultPlainObject(result) {
  19. return result && !isValidElement(result) && Object.prototype.toString.call(result) === '[object Object]';
  20. }
  21. function getEnabledItemKeys(items) {
  22. return items.filter(function (data) {
  23. return !data.disabled;
  24. }).map(function (data) {
  25. return data.key;
  26. });
  27. }
  28. export var transferListProps = {
  29. prefixCls: String,
  30. dataSource: {
  31. type: Array,
  32. default: []
  33. },
  34. filter: String,
  35. filterOption: Function,
  36. checkedKeys: PropTypes.arrayOf(PropTypes.string),
  37. handleFilter: Function,
  38. handleClear: Function,
  39. renderItem: Function,
  40. showSearch: {
  41. type: Boolean,
  42. default: false
  43. },
  44. searchPlaceholder: String,
  45. notFoundContent: PropTypes.any,
  46. itemUnit: String,
  47. itemsUnit: String,
  48. renderList: PropTypes.any,
  49. disabled: {
  50. type: Boolean,
  51. default: undefined
  52. },
  53. direction: String,
  54. showSelectAll: {
  55. type: Boolean,
  56. default: undefined
  57. },
  58. remove: String,
  59. selectAll: String,
  60. selectCurrent: String,
  61. selectInvert: String,
  62. removeAll: String,
  63. removeCurrent: String,
  64. selectAllLabel: PropTypes.any,
  65. showRemove: {
  66. type: Boolean,
  67. default: undefined
  68. },
  69. pagination: PropTypes.any,
  70. onItemSelect: Function,
  71. onItemSelectAll: Function,
  72. onItemRemove: Function,
  73. onScroll: Function
  74. };
  75. export default defineComponent({
  76. compatConfig: {
  77. MODE: 3
  78. },
  79. name: 'TransferList',
  80. inheritAttrs: false,
  81. props: transferListProps,
  82. // emits: ['scroll', 'itemSelectAll', 'itemRemove', 'itemSelect'],
  83. slots: ['footer', 'titleText'],
  84. setup: function setup(props, _ref) {
  85. var attrs = _ref.attrs,
  86. slots = _ref.slots;
  87. var filterValue = ref('');
  88. var transferNode = ref();
  89. var defaultListBodyRef = ref();
  90. var renderListBody = function renderListBody(renderList, props) {
  91. var bodyContent = renderList ? renderList(props) : null;
  92. var customize = !!bodyContent && filterEmpty(bodyContent).length > 0;
  93. if (!customize) {
  94. bodyContent = _createVNode(ListBody, _objectSpread(_objectSpread({}, props), {}, {
  95. "ref": defaultListBodyRef
  96. }), null);
  97. }
  98. return {
  99. customize: customize,
  100. bodyContent: bodyContent
  101. };
  102. };
  103. var renderItemHtml = function renderItemHtml(item) {
  104. var _props$renderItem = props.renderItem,
  105. renderItem = _props$renderItem === void 0 ? defaultRender : _props$renderItem;
  106. var renderResult = renderItem(item);
  107. var isRenderResultPlain = isRenderResultPlainObject(renderResult);
  108. return {
  109. renderedText: isRenderResultPlain ? renderResult.value : renderResult,
  110. renderedEl: isRenderResultPlain ? renderResult.label : renderResult,
  111. item: item
  112. };
  113. };
  114. var filteredItems = ref([]);
  115. var filteredRenderItems = ref([]);
  116. watchEffect(function () {
  117. var fItems = [];
  118. var fRenderItems = [];
  119. props.dataSource.forEach(function (item) {
  120. var renderedItem = renderItemHtml(item);
  121. var renderedText = renderedItem.renderedText;
  122. // Filter skip
  123. if (filterValue.value && filterValue.value.trim() && !matchFilter(renderedText, item)) {
  124. return null;
  125. }
  126. fItems.push(item);
  127. fRenderItems.push(renderedItem);
  128. });
  129. filteredItems.value = fItems;
  130. filteredRenderItems.value = fRenderItems;
  131. });
  132. var checkStatus = computed(function () {
  133. var checkedKeys = props.checkedKeys;
  134. if (checkedKeys.length === 0) {
  135. return 'none';
  136. }
  137. if (filteredItems.value.every(function (item) {
  138. return checkedKeys.indexOf(item.key) >= 0 || !!item.disabled;
  139. })) {
  140. return 'all';
  141. }
  142. return 'part';
  143. });
  144. var enabledItemKeys = computed(function () {
  145. return getEnabledItemKeys(filteredItems.value);
  146. });
  147. var getNewSelectKeys = function getNewSelectKeys(keys, unCheckedKeys) {
  148. return Array.from(new Set([].concat(_toConsumableArray(keys), _toConsumableArray(props.checkedKeys)))).filter(function (key) {
  149. return unCheckedKeys.indexOf(key) === -1;
  150. });
  151. };
  152. var getCheckBox = function getCheckBox(_ref2) {
  153. var disabled = _ref2.disabled,
  154. prefixCls = _ref2.prefixCls;
  155. var checkedAll = checkStatus.value === 'all';
  156. var checkAllCheckbox = _createVNode(Checkbox, {
  157. "disabled": disabled,
  158. "checked": checkedAll,
  159. "indeterminate": checkStatus.value === 'part',
  160. "class": "".concat(prefixCls, "-checkbox"),
  161. "onChange": function onChange() {
  162. // Only select enabled items
  163. var keys = enabledItemKeys.value;
  164. props.onItemSelectAll(getNewSelectKeys(!checkedAll ? keys : [], checkedAll ? props.checkedKeys : []));
  165. }
  166. }, null);
  167. return checkAllCheckbox;
  168. };
  169. var handleFilter = function handleFilter(e) {
  170. var _props$handleFilter;
  171. var filter = e.target.value;
  172. filterValue.value = filter;
  173. (_props$handleFilter = props.handleFilter) === null || _props$handleFilter === void 0 ? void 0 : _props$handleFilter.call(props, e);
  174. };
  175. var handleClear = function handleClear(e) {
  176. var _props$handleClear;
  177. filterValue.value = '';
  178. (_props$handleClear = props.handleClear) === null || _props$handleClear === void 0 ? void 0 : _props$handleClear.call(props, e);
  179. };
  180. var matchFilter = function matchFilter(text, item) {
  181. var filterOption = props.filterOption;
  182. if (filterOption) {
  183. return filterOption(filterValue.value, item);
  184. }
  185. return text.indexOf(filterValue.value) >= 0;
  186. };
  187. var getSelectAllLabel = function getSelectAllLabel(selectedCount, totalCount) {
  188. var itemsUnit = props.itemsUnit,
  189. itemUnit = props.itemUnit,
  190. selectAllLabel = props.selectAllLabel;
  191. if (selectAllLabel) {
  192. return typeof selectAllLabel === 'function' ? selectAllLabel({
  193. selectedCount: selectedCount,
  194. totalCount: totalCount
  195. }) : selectAllLabel;
  196. }
  197. var unit = totalCount > 1 ? itemsUnit : itemUnit;
  198. return _createVNode(_Fragment, null, [(selectedCount > 0 ? "".concat(selectedCount, "/") : '') + totalCount, _createTextVNode(" "), unit]);
  199. };
  200. var getListBody = function getListBody(prefixCls, searchPlaceholder, checkedKeys, renderList, showSearch, disabled) {
  201. var search = showSearch ? _createVNode("div", {
  202. "class": "".concat(prefixCls, "-body-search-wrapper")
  203. }, [_createVNode(Search, {
  204. "prefixCls": "".concat(prefixCls, "-search"),
  205. "onChange": handleFilter,
  206. "handleClear": handleClear,
  207. "placeholder": searchPlaceholder,
  208. "value": filterValue.value,
  209. "disabled": disabled
  210. }, null)]) : null;
  211. var bodyNode;
  212. var _splitAttrs = splitAttrs(attrs),
  213. onEvents = _splitAttrs.onEvents;
  214. var _renderListBody = renderListBody(renderList, _objectSpread(_objectSpread({}, props), {}, {
  215. filteredItems: filteredItems.value,
  216. filteredRenderItems: filteredRenderItems.value,
  217. selectedKeys: checkedKeys
  218. }, onEvents)),
  219. bodyContent = _renderListBody.bodyContent,
  220. customize = _renderListBody.customize;
  221. // We should wrap customize list body in a classNamed div to use flex layout.
  222. if (customize) {
  223. bodyNode = _createVNode("div", {
  224. "class": "".concat(prefixCls, "-body-customize-wrapper")
  225. }, [bodyContent]);
  226. } else {
  227. bodyNode = filteredItems.value.length ? bodyContent : _createVNode("div", {
  228. "class": "".concat(prefixCls, "-body-not-found")
  229. }, [props.notFoundContent]);
  230. }
  231. return _createVNode("div", {
  232. "class": showSearch ? "".concat(prefixCls, "-body ").concat(prefixCls, "-body-with-search") : "".concat(prefixCls, "-body"),
  233. "ref": transferNode
  234. }, [search, bodyNode]);
  235. };
  236. return function () {
  237. var _slots$footer, _classNames, _slots$titleText;
  238. var prefixCls = props.prefixCls,
  239. checkedKeys = props.checkedKeys,
  240. disabled = props.disabled,
  241. showSearch = props.showSearch,
  242. searchPlaceholder = props.searchPlaceholder,
  243. selectAll = props.selectAll,
  244. selectCurrent = props.selectCurrent,
  245. selectInvert = props.selectInvert,
  246. removeAll = props.removeAll,
  247. removeCurrent = props.removeCurrent,
  248. renderList = props.renderList,
  249. onItemSelectAll = props.onItemSelectAll,
  250. onItemRemove = props.onItemRemove,
  251. _props$showSelectAll = props.showSelectAll,
  252. showSelectAll = _props$showSelectAll === void 0 ? true : _props$showSelectAll,
  253. showRemove = props.showRemove,
  254. pagination = props.pagination;
  255. // Custom Layout
  256. var footerDom = (_slots$footer = slots.footer) === null || _slots$footer === void 0 ? void 0 : _slots$footer.call(slots, _objectSpread({}, props));
  257. var listCls = classNames(prefixCls, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-with-pagination"), !!pagination), _defineProperty(_classNames, "".concat(prefixCls, "-with-footer"), !!footerDom), _classNames));
  258. // ================================= List Body =================================
  259. var listBody = getListBody(prefixCls, searchPlaceholder, checkedKeys, renderList, showSearch, disabled);
  260. var listFooter = footerDom ? _createVNode("div", {
  261. "class": "".concat(prefixCls, "-footer")
  262. }, [footerDom]) : null;
  263. var checkAllCheckbox = !showRemove && !pagination && getCheckBox({
  264. disabled: disabled,
  265. prefixCls: prefixCls
  266. });
  267. var menu = null;
  268. if (showRemove) {
  269. menu = _createVNode(Menu, null, {
  270. default: function _default() {
  271. return [pagination && _createVNode(Menu.Item, {
  272. "key": "removeCurrent",
  273. "onClick": function onClick() {
  274. var pageKeys = getEnabledItemKeys((defaultListBodyRef.value.items || []).map(function (entity) {
  275. return entity.item;
  276. }));
  277. onItemRemove === null || onItemRemove === void 0 ? void 0 : onItemRemove(pageKeys);
  278. }
  279. }, {
  280. default: function _default() {
  281. return [removeCurrent];
  282. }
  283. }), _createVNode(Menu.Item, {
  284. "key": "removeAll",
  285. "onClick": function onClick() {
  286. onItemRemove === null || onItemRemove === void 0 ? void 0 : onItemRemove(enabledItemKeys.value);
  287. }
  288. }, {
  289. default: function _default() {
  290. return [removeAll];
  291. }
  292. })];
  293. }
  294. });
  295. } else {
  296. menu = _createVNode(Menu, null, {
  297. default: function _default() {
  298. return [_createVNode(Menu.Item, {
  299. "key": "selectAll",
  300. "onClick": function onClick() {
  301. var keys = enabledItemKeys.value;
  302. onItemSelectAll(getNewSelectKeys(keys, []));
  303. }
  304. }, {
  305. default: function _default() {
  306. return [selectAll];
  307. }
  308. }), pagination && _createVNode(Menu.Item, {
  309. "onClick": function onClick() {
  310. var pageKeys = getEnabledItemKeys((defaultListBodyRef.value.items || []).map(function (entity) {
  311. return entity.item;
  312. }));
  313. onItemSelectAll(getNewSelectKeys(pageKeys, []));
  314. }
  315. }, {
  316. default: function _default() {
  317. return [selectCurrent];
  318. }
  319. }), _createVNode(Menu.Item, {
  320. "key": "selectInvert",
  321. "onClick": function onClick() {
  322. var availableKeys;
  323. if (pagination) {
  324. availableKeys = getEnabledItemKeys((defaultListBodyRef.value.items || []).map(function (entity) {
  325. return entity.item;
  326. }));
  327. } else {
  328. availableKeys = enabledItemKeys.value;
  329. }
  330. var checkedKeySet = new Set(checkedKeys);
  331. var newCheckedKeys = [];
  332. var newUnCheckedKeys = [];
  333. availableKeys.forEach(function (key) {
  334. if (checkedKeySet.has(key)) {
  335. newUnCheckedKeys.push(key);
  336. } else {
  337. newCheckedKeys.push(key);
  338. }
  339. });
  340. onItemSelectAll(getNewSelectKeys(newCheckedKeys, newUnCheckedKeys));
  341. }
  342. }, {
  343. default: function _default() {
  344. return [selectInvert];
  345. }
  346. })];
  347. }
  348. });
  349. }
  350. var dropdown = _createVNode(Dropdown, {
  351. "class": "".concat(prefixCls, "-header-dropdown"),
  352. "overlay": menu,
  353. "disabled": disabled
  354. }, {
  355. default: function _default() {
  356. return [_createVNode(DownOutlined, null, null)];
  357. }
  358. });
  359. return _createVNode("div", {
  360. "class": listCls,
  361. "style": attrs.style
  362. }, [_createVNode("div", {
  363. "class": "".concat(prefixCls, "-header")
  364. }, [showSelectAll ? _createVNode(_Fragment, null, [checkAllCheckbox, dropdown]) : null, _createVNode("span", {
  365. "class": "".concat(prefixCls, "-header-selected")
  366. }, [_createVNode("span", null, [getSelectAllLabel(checkedKeys.length, filteredItems.value.length)]), _createVNode("span", {
  367. "class": "".concat(prefixCls, "-header-title")
  368. }, [(_slots$titleText = slots.titleText) === null || _slots$titleText === void 0 ? void 0 : _slots$titleText.call(slots)])])]), listBody, listFooter]);
  369. };
  370. }
  371. });