Table.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.tableProps = exports.default = void 0;
  7. var _vue = require("vue");
  8. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  9. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  10. var _vcTable = _interopRequireDefault(require("../vc-table"));
  11. var _Table = require("../vc-table/Table");
  12. var _spin = _interopRequireDefault(require("../spin"));
  13. var _pagination = _interopRequireDefault(require("../pagination"));
  14. var _usePagination = _interopRequireWildcard(require("./hooks/usePagination"));
  15. var _useLazyKVMap = _interopRequireDefault(require("./hooks/useLazyKVMap"));
  16. var _useSelection = _interopRequireDefault(require("./hooks/useSelection"));
  17. var _useSorter = _interopRequireWildcard(require("./hooks/useSorter"));
  18. var _useFilter = _interopRequireWildcard(require("./hooks/useFilter"));
  19. var _useTitleColumns = _interopRequireDefault(require("./hooks/useTitleColumns"));
  20. var _ExpandIcon = _interopRequireDefault(require("./ExpandIcon"));
  21. var _scrollTo = _interopRequireDefault(require("../_util/scrollTo"));
  22. var _en_US = _interopRequireDefault(require("../locale/en_US"));
  23. var _devWarning = _interopRequireDefault(require("../vc-util/devWarning"));
  24. var _useBreakpoint = _interopRequireDefault(require("../_util/hooks/useBreakpoint"));
  25. var _useConfigInject = _interopRequireDefault(require("../config-provider/hooks/useConfigInject"));
  26. var _LocaleReceiver = require("../locale-provider/LocaleReceiver");
  27. var _classNames = _interopRequireDefault(require("../_util/classNames"));
  28. var _omit = _interopRequireDefault(require("../_util/omit"));
  29. var _propsUtil = require("../_util/props-util");
  30. var _context = require("./context");
  31. var _useColumns = _interopRequireDefault(require("./hooks/useColumns"));
  32. var _util = require("./util");
  33. var _type = require("../_util/type");
  34. var _style = _interopRequireDefault(require("./style"));
  35. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
  36. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  37. // CSSINJS
  38. const EMPTY_LIST = [];
  39. const tableProps = () => {
  40. return {
  41. prefixCls: (0, _type.stringType)(),
  42. columns: (0, _type.arrayType)(),
  43. rowKey: (0, _type.someType)([String, Function]),
  44. tableLayout: (0, _type.stringType)(),
  45. rowClassName: (0, _type.someType)([String, Function]),
  46. title: (0, _type.functionType)(),
  47. footer: (0, _type.functionType)(),
  48. id: (0, _type.stringType)(),
  49. showHeader: (0, _type.booleanType)(),
  50. components: (0, _type.objectType)(),
  51. customRow: (0, _type.functionType)(),
  52. customHeaderRow: (0, _type.functionType)(),
  53. direction: (0, _type.stringType)(),
  54. expandFixed: (0, _type.someType)([Boolean, String]),
  55. expandColumnWidth: Number,
  56. expandedRowKeys: (0, _type.arrayType)(),
  57. defaultExpandedRowKeys: (0, _type.arrayType)(),
  58. expandedRowRender: (0, _type.functionType)(),
  59. expandRowByClick: (0, _type.booleanType)(),
  60. expandIcon: (0, _type.functionType)(),
  61. onExpand: (0, _type.functionType)(),
  62. onExpandedRowsChange: (0, _type.functionType)(),
  63. 'onUpdate:expandedRowKeys': (0, _type.functionType)(),
  64. defaultExpandAllRows: (0, _type.booleanType)(),
  65. indentSize: Number,
  66. /** @deprecated Please use `EXPAND_COLUMN` in `columns` directly */
  67. expandIconColumnIndex: Number,
  68. showExpandColumn: (0, _type.booleanType)(),
  69. expandedRowClassName: (0, _type.functionType)(),
  70. childrenColumnName: (0, _type.stringType)(),
  71. rowExpandable: (0, _type.functionType)(),
  72. sticky: (0, _type.someType)([Boolean, Object]),
  73. dropdownPrefixCls: String,
  74. dataSource: (0, _type.arrayType)(),
  75. pagination: (0, _type.someType)([Boolean, Object]),
  76. loading: (0, _type.someType)([Boolean, Object]),
  77. size: (0, _type.stringType)(),
  78. bordered: (0, _type.booleanType)(),
  79. locale: (0, _type.objectType)(),
  80. onChange: (0, _type.functionType)(),
  81. onResizeColumn: (0, _type.functionType)(),
  82. rowSelection: (0, _type.objectType)(),
  83. getPopupContainer: (0, _type.functionType)(),
  84. scroll: (0, _type.objectType)(),
  85. sortDirections: (0, _type.arrayType)(),
  86. showSorterTooltip: (0, _type.someType)([Boolean, Object], true),
  87. transformCellText: (0, _type.functionType)()
  88. };
  89. };
  90. exports.tableProps = tableProps;
  91. const InternalTable = (0, _vue.defineComponent)({
  92. name: 'InternalTable',
  93. inheritAttrs: false,
  94. props: (0, _propsUtil.initDefaultProps)((0, _extends2.default)((0, _extends2.default)({}, tableProps()), {
  95. contextSlots: (0, _type.objectType)()
  96. }), {
  97. rowKey: 'key'
  98. }),
  99. setup(props, _ref) {
  100. let {
  101. attrs,
  102. slots,
  103. expose,
  104. emit
  105. } = _ref;
  106. (0, _devWarning.default)(!(typeof props.rowKey === 'function' && props.rowKey.length > 1), 'Table', '`index` parameter of `rowKey` function is deprecated. There is no guarantee that it will work as expected.');
  107. (0, _context.useProvideSlots)((0, _vue.computed)(() => props.contextSlots));
  108. (0, _context.useProvideTableContext)({
  109. onResizeColumn: (w, col) => {
  110. emit('resizeColumn', w, col);
  111. }
  112. });
  113. const screens = (0, _useBreakpoint.default)();
  114. const mergedColumns = (0, _vue.computed)(() => {
  115. const matched = new Set(Object.keys(screens.value).filter(m => screens.value[m]));
  116. return props.columns.filter(c => !c.responsive || c.responsive.some(r => matched.has(r)));
  117. });
  118. const {
  119. size: mergedSize,
  120. renderEmpty,
  121. direction,
  122. prefixCls,
  123. configProvider
  124. } = (0, _useConfigInject.default)('table', props);
  125. // Style
  126. const [wrapSSR, hashId] = (0, _style.default)(prefixCls);
  127. const transformCellText = (0, _vue.computed)(() => {
  128. var _a;
  129. return props.transformCellText || ((_a = configProvider.transformCellText) === null || _a === void 0 ? void 0 : _a.value);
  130. });
  131. const [tableLocale] = (0, _LocaleReceiver.useLocaleReceiver)('Table', _en_US.default.Table, (0, _vue.toRef)(props, 'locale'));
  132. const rawData = (0, _vue.computed)(() => props.dataSource || EMPTY_LIST);
  133. const dropdownPrefixCls = (0, _vue.computed)(() => configProvider.getPrefixCls('dropdown', props.dropdownPrefixCls));
  134. const childrenColumnName = (0, _vue.computed)(() => props.childrenColumnName || 'children');
  135. const expandType = (0, _vue.computed)(() => {
  136. if (rawData.value.some(item => item === null || item === void 0 ? void 0 : item[childrenColumnName.value])) {
  137. return 'nest';
  138. }
  139. if (props.expandedRowRender) {
  140. return 'row';
  141. }
  142. return null;
  143. });
  144. const internalRefs = (0, _vue.reactive)({
  145. body: null
  146. });
  147. const updateInternalRefs = refs => {
  148. (0, _extends2.default)(internalRefs, refs);
  149. };
  150. // ============================ RowKey ============================
  151. const getRowKey = (0, _vue.computed)(() => {
  152. if (typeof props.rowKey === 'function') {
  153. return props.rowKey;
  154. }
  155. return record => record === null || record === void 0 ? void 0 : record[props.rowKey];
  156. });
  157. const [getRecordByKey] = (0, _useLazyKVMap.default)(rawData, childrenColumnName, getRowKey);
  158. // ============================ Events =============================
  159. const changeEventInfo = {};
  160. const triggerOnChange = function (info, action) {
  161. let reset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  162. const {
  163. pagination,
  164. scroll,
  165. onChange
  166. } = props;
  167. const changeInfo = (0, _extends2.default)((0, _extends2.default)({}, changeEventInfo), info);
  168. if (reset) {
  169. changeEventInfo.resetPagination();
  170. // Reset event param
  171. if (changeInfo.pagination.current) {
  172. changeInfo.pagination.current = 1;
  173. }
  174. // Trigger pagination events
  175. if (pagination && pagination.onChange) {
  176. pagination.onChange(1, changeInfo.pagination.pageSize);
  177. }
  178. }
  179. if (scroll && scroll.scrollToFirstRowOnChange !== false && internalRefs.body) {
  180. (0, _scrollTo.default)(0, {
  181. getContainer: () => internalRefs.body
  182. });
  183. }
  184. onChange === null || onChange === void 0 ? void 0 : onChange(changeInfo.pagination, changeInfo.filters, changeInfo.sorter, {
  185. currentDataSource: (0, _useFilter.getFilterData)((0, _useSorter.getSortData)(rawData.value, changeInfo.sorterStates, childrenColumnName.value), changeInfo.filterStates),
  186. action
  187. });
  188. };
  189. /**
  190. * Controlled state in `columns` is not a good idea that makes too many code (1000+ line?) to read
  191. * state out and then put it back to title render. Move these code into `hooks` but still too
  192. * complex. We should provides Table props like `sorter` & `filter` to handle control in next big version.
  193. */
  194. // ============================ Sorter =============================
  195. const onSorterChange = (sorter, sorterStates) => {
  196. triggerOnChange({
  197. sorter,
  198. sorterStates
  199. }, 'sort', false);
  200. };
  201. const [transformSorterColumns, sortStates, sorterTitleProps, sorters] = (0, _useSorter.default)({
  202. prefixCls,
  203. mergedColumns,
  204. onSorterChange,
  205. sortDirections: (0, _vue.computed)(() => props.sortDirections || ['ascend', 'descend']),
  206. tableLocale,
  207. showSorterTooltip: (0, _vue.toRef)(props, 'showSorterTooltip')
  208. });
  209. const sortedData = (0, _vue.computed)(() => (0, _useSorter.getSortData)(rawData.value, sortStates.value, childrenColumnName.value));
  210. // ============================ Filter ============================
  211. const onFilterChange = (filters, filterStates) => {
  212. triggerOnChange({
  213. filters,
  214. filterStates
  215. }, 'filter', true);
  216. };
  217. const [transformFilterColumns, filterStates, filters] = (0, _useFilter.default)({
  218. prefixCls,
  219. locale: tableLocale,
  220. dropdownPrefixCls,
  221. mergedColumns,
  222. onFilterChange,
  223. getPopupContainer: (0, _vue.toRef)(props, 'getPopupContainer')
  224. });
  225. const mergedData = (0, _vue.computed)(() => (0, _useFilter.getFilterData)(sortedData.value, filterStates.value));
  226. // ============================ Column ============================
  227. const [transformBasicColumns] = (0, _useColumns.default)((0, _vue.toRef)(props, 'contextSlots'));
  228. const columnTitleProps = (0, _vue.computed)(() => {
  229. const mergedFilters = {};
  230. const filtersValue = filters.value;
  231. Object.keys(filtersValue).forEach(filterKey => {
  232. if (filtersValue[filterKey] !== null) {
  233. mergedFilters[filterKey] = filtersValue[filterKey];
  234. }
  235. });
  236. return (0, _extends2.default)((0, _extends2.default)({}, sorterTitleProps.value), {
  237. filters: mergedFilters
  238. });
  239. });
  240. const [transformTitleColumns] = (0, _useTitleColumns.default)(columnTitleProps);
  241. // ========================== Pagination ==========================
  242. const onPaginationChange = (current, pageSize) => {
  243. triggerOnChange({
  244. pagination: (0, _extends2.default)((0, _extends2.default)({}, changeEventInfo.pagination), {
  245. current,
  246. pageSize
  247. })
  248. }, 'paginate');
  249. };
  250. const [mergedPagination, resetPagination] = (0, _usePagination.default)((0, _vue.computed)(() => mergedData.value.length), (0, _vue.toRef)(props, 'pagination'), onPaginationChange);
  251. (0, _vue.watchEffect)(() => {
  252. changeEventInfo.sorter = sorters.value;
  253. changeEventInfo.sorterStates = sortStates.value;
  254. changeEventInfo.filters = filters.value;
  255. changeEventInfo.filterStates = filterStates.value;
  256. changeEventInfo.pagination = props.pagination === false ? {} : (0, _usePagination.getPaginationParam)(mergedPagination.value, props.pagination);
  257. changeEventInfo.resetPagination = resetPagination;
  258. });
  259. // ============================= Data =============================
  260. const pageData = (0, _vue.computed)(() => {
  261. if (props.pagination === false || !mergedPagination.value.pageSize) {
  262. return mergedData.value;
  263. }
  264. const {
  265. current = 1,
  266. total,
  267. pageSize = _usePagination.DEFAULT_PAGE_SIZE
  268. } = mergedPagination.value;
  269. (0, _devWarning.default)(current > 0, 'Table', '`current` should be positive number.');
  270. // Dynamic table data
  271. if (mergedData.value.length < total) {
  272. if (mergedData.value.length > pageSize) {
  273. return mergedData.value.slice((current - 1) * pageSize, current * pageSize);
  274. }
  275. return mergedData.value;
  276. }
  277. return mergedData.value.slice((current - 1) * pageSize, current * pageSize);
  278. });
  279. (0, _vue.watchEffect)(() => {
  280. (0, _vue.nextTick)(() => {
  281. const {
  282. total,
  283. pageSize = _usePagination.DEFAULT_PAGE_SIZE
  284. } = mergedPagination.value;
  285. // Dynamic table data
  286. if (mergedData.value.length < total) {
  287. if (mergedData.value.length > pageSize) {
  288. (0, _devWarning.default)(false, 'Table', '`dataSource` length is less than `pagination.total` but large than `pagination.pageSize`. Please make sure your config correct data with async mode.');
  289. }
  290. }
  291. });
  292. }, {
  293. flush: 'post'
  294. });
  295. const expandIconColumnIndex = (0, _vue.computed)(() => {
  296. if (props.showExpandColumn === false) return -1;
  297. // Adjust expand icon index, no overwrite expandIconColumnIndex if set.
  298. if (expandType.value === 'nest' && props.expandIconColumnIndex === undefined) {
  299. return props.rowSelection ? 1 : 0;
  300. } else if (props.expandIconColumnIndex > 0 && props.rowSelection) {
  301. return props.expandIconColumnIndex - 1;
  302. }
  303. return props.expandIconColumnIndex;
  304. });
  305. const rowSelection = (0, _vue.ref)();
  306. (0, _vue.watch)(() => props.rowSelection, () => {
  307. rowSelection.value = props.rowSelection ? (0, _extends2.default)({}, props.rowSelection) : props.rowSelection;
  308. }, {
  309. deep: true,
  310. immediate: true
  311. });
  312. // ========================== Selections ==========================
  313. const [transformSelectionColumns, selectedKeySet] = (0, _useSelection.default)(rowSelection, {
  314. prefixCls,
  315. data: mergedData,
  316. pageData,
  317. getRowKey,
  318. getRecordByKey,
  319. expandType,
  320. childrenColumnName,
  321. locale: tableLocale,
  322. getPopupContainer: (0, _vue.computed)(() => props.getPopupContainer)
  323. });
  324. const internalRowClassName = (record, index, indent) => {
  325. let mergedRowClassName;
  326. const {
  327. rowClassName
  328. } = props;
  329. if (typeof rowClassName === 'function') {
  330. mergedRowClassName = (0, _classNames.default)(rowClassName(record, index, indent));
  331. } else {
  332. mergedRowClassName = (0, _classNames.default)(rowClassName);
  333. }
  334. return (0, _classNames.default)({
  335. [`${prefixCls.value}-row-selected`]: selectedKeySet.value.has(getRowKey.value(record, index))
  336. }, mergedRowClassName);
  337. };
  338. expose({
  339. selectedKeySet
  340. });
  341. const indentSize = (0, _vue.computed)(() => {
  342. // Indent size
  343. return typeof props.indentSize === 'number' ? props.indentSize : 15;
  344. });
  345. const transformColumns = innerColumns => {
  346. const res = transformTitleColumns(transformSelectionColumns(transformFilterColumns(transformSorterColumns(transformBasicColumns(innerColumns)))));
  347. return res;
  348. };
  349. return () => {
  350. var _a;
  351. const {
  352. expandIcon = slots.expandIcon || (0, _ExpandIcon.default)(tableLocale.value),
  353. pagination,
  354. loading,
  355. bordered
  356. } = props;
  357. let topPaginationNode;
  358. let bottomPaginationNode;
  359. if (pagination !== false && ((_a = mergedPagination.value) === null || _a === void 0 ? void 0 : _a.total)) {
  360. let paginationSize;
  361. if (mergedPagination.value.size) {
  362. paginationSize = mergedPagination.value.size;
  363. } else {
  364. paginationSize = mergedSize.value === 'small' || mergedSize.value === 'middle' ? 'small' : undefined;
  365. }
  366. const renderPagination = position => (0, _vue.createVNode)(_pagination.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, mergedPagination.value), {}, {
  367. "class": [`${prefixCls.value}-pagination ${prefixCls.value}-pagination-${position}`, mergedPagination.value.class],
  368. "size": paginationSize
  369. }), null);
  370. const defaultPosition = direction.value === 'rtl' ? 'left' : 'right';
  371. const {
  372. position
  373. } = mergedPagination.value;
  374. if (position !== null && Array.isArray(position)) {
  375. const topPos = position.find(p => p.includes('top'));
  376. const bottomPos = position.find(p => p.includes('bottom'));
  377. const isDisable = position.every(p => `${p}` === 'none');
  378. if (!topPos && !bottomPos && !isDisable) {
  379. bottomPaginationNode = renderPagination(defaultPosition);
  380. }
  381. if (topPos) {
  382. topPaginationNode = renderPagination(topPos.toLowerCase().replace('top', ''));
  383. }
  384. if (bottomPos) {
  385. bottomPaginationNode = renderPagination(bottomPos.toLowerCase().replace('bottom', ''));
  386. }
  387. } else {
  388. bottomPaginationNode = renderPagination(defaultPosition);
  389. }
  390. }
  391. // >>>>>>>>> Spinning
  392. let spinProps;
  393. if (typeof loading === 'boolean') {
  394. spinProps = {
  395. spinning: loading
  396. };
  397. } else if (typeof loading === 'object') {
  398. spinProps = (0, _extends2.default)({
  399. spinning: true
  400. }, loading);
  401. }
  402. const wrapperClassNames = (0, _classNames.default)(`${prefixCls.value}-wrapper`, {
  403. [`${prefixCls.value}-wrapper-rtl`]: direction.value === 'rtl'
  404. }, attrs.class, hashId.value);
  405. const tableProps = (0, _omit.default)(props, ['columns']);
  406. return wrapSSR((0, _vue.createVNode)("div", {
  407. "class": wrapperClassNames,
  408. "style": attrs.style
  409. }, [(0, _vue.createVNode)(_spin.default, (0, _objectSpread2.default)({
  410. "spinning": false
  411. }, spinProps), {
  412. default: () => [topPaginationNode, (0, _vue.createVNode)(_vcTable.default, (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, attrs), tableProps), {}, {
  413. "expandedRowKeys": props.expandedRowKeys,
  414. "defaultExpandedRowKeys": props.defaultExpandedRowKeys,
  415. "expandIconColumnIndex": expandIconColumnIndex.value,
  416. "indentSize": indentSize.value,
  417. "expandIcon": expandIcon,
  418. "columns": mergedColumns.value,
  419. "direction": direction.value,
  420. "prefixCls": prefixCls.value,
  421. "class": (0, _classNames.default)({
  422. [`${prefixCls.value}-middle`]: mergedSize.value === 'middle',
  423. [`${prefixCls.value}-small`]: mergedSize.value === 'small',
  424. [`${prefixCls.value}-bordered`]: bordered,
  425. [`${prefixCls.value}-empty`]: rawData.value.length === 0
  426. }),
  427. "data": pageData.value,
  428. "rowKey": getRowKey.value,
  429. "rowClassName": internalRowClassName,
  430. "internalHooks": _Table.INTERNAL_HOOKS,
  431. "internalRefs": internalRefs,
  432. "onUpdateInternalRefs": updateInternalRefs,
  433. "transformColumns": transformColumns,
  434. "transformCellText": transformCellText.value
  435. }), (0, _extends2.default)((0, _extends2.default)({}, slots), {
  436. emptyText: () => {
  437. var _a, _b;
  438. return ((_a = slots.emptyText) === null || _a === void 0 ? void 0 : _a.call(slots)) || ((_b = props.locale) === null || _b === void 0 ? void 0 : _b.emptyText) || renderEmpty('Table');
  439. }
  440. })), bottomPaginationNode]
  441. })]));
  442. };
  443. }
  444. });
  445. const Table = (0, _vue.defineComponent)({
  446. name: 'ATable',
  447. inheritAttrs: false,
  448. props: (0, _propsUtil.initDefaultProps)(tableProps(), {
  449. rowKey: 'key'
  450. }),
  451. slots: Object,
  452. setup(props, _ref2) {
  453. let {
  454. attrs,
  455. slots,
  456. expose
  457. } = _ref2;
  458. const table = (0, _vue.ref)();
  459. expose({
  460. table
  461. });
  462. return () => {
  463. var _a;
  464. const columns = props.columns || (0, _util.convertChildrenToColumns)((_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
  465. return (0, _vue.createVNode)(InternalTable, (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({
  466. "ref": table
  467. }, attrs), props), {}, {
  468. "columns": columns || [],
  469. "expandedRowRender": slots.expandedRowRender || props.expandedRowRender,
  470. "contextSlots": (0, _extends2.default)({}, slots)
  471. }), slots);
  472. };
  473. }
  474. });
  475. var _default = exports.default = Table;