index.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { createVNode as _createVNode } from "vue";
  4. import { provide, defineComponent, ref, watch, computed, toRef } from 'vue';
  5. import classNames from '../_util/classNames';
  6. import Spin from '../spin';
  7. import Pagination from '../pagination';
  8. import { Row } from '../grid';
  9. import Item from './Item';
  10. import { flattenChildren } from '../_util/props-util';
  11. import initDefaultProps from '../_util/props-util/initDefaultProps';
  12. import { arrayType, someType, booleanType, objectType, vNodeType, functionType } from '../_util/type';
  13. import ItemMeta from './ItemMeta';
  14. import useConfigInject from '../config-provider/hooks/useConfigInject';
  15. import useBreakpoint from '../_util/hooks/useBreakpoint';
  16. import { responsiveArray } from '../_util/responsiveObserve';
  17. import eagerComputed from '../_util/eagerComputed';
  18. // CSSINJS
  19. import useStyle from './style';
  20. export const listProps = () => ({
  21. bordered: booleanType(),
  22. dataSource: arrayType(),
  23. extra: vNodeType(),
  24. grid: objectType(),
  25. itemLayout: String,
  26. loading: someType([Boolean, Object]),
  27. loadMore: vNodeType(),
  28. pagination: someType([Boolean, Object]),
  29. prefixCls: String,
  30. rowKey: someType([String, Number, Function]),
  31. renderItem: functionType(),
  32. size: String,
  33. split: booleanType(),
  34. header: vNodeType(),
  35. footer: vNodeType(),
  36. locale: objectType()
  37. });
  38. import { ListContextKey } from './contextKey';
  39. const List = defineComponent({
  40. compatConfig: {
  41. MODE: 3
  42. },
  43. name: 'AList',
  44. inheritAttrs: false,
  45. Item,
  46. props: initDefaultProps(listProps(), {
  47. dataSource: [],
  48. bordered: false,
  49. split: true,
  50. loading: false,
  51. pagination: false
  52. }),
  53. slots: Object,
  54. setup(props, _ref) {
  55. let {
  56. slots,
  57. attrs
  58. } = _ref;
  59. var _a, _b;
  60. provide(ListContextKey, {
  61. grid: toRef(props, 'grid'),
  62. itemLayout: toRef(props, 'itemLayout')
  63. });
  64. const defaultPaginationProps = {
  65. current: 1,
  66. total: 0
  67. };
  68. const {
  69. prefixCls,
  70. direction,
  71. renderEmpty
  72. } = useConfigInject('list', props);
  73. // Style
  74. const [wrapSSR, hashId] = useStyle(prefixCls);
  75. const paginationObj = computed(() => props.pagination && typeof props.pagination === 'object' ? props.pagination : {});
  76. const paginationCurrent = ref((_a = paginationObj.value.defaultCurrent) !== null && _a !== void 0 ? _a : 1);
  77. const paginationSize = ref((_b = paginationObj.value.defaultPageSize) !== null && _b !== void 0 ? _b : 10);
  78. watch(paginationObj, () => {
  79. if ('current' in paginationObj.value) {
  80. paginationCurrent.value = paginationObj.value.current;
  81. }
  82. if ('pageSize' in paginationObj.value) {
  83. paginationSize.value = paginationObj.value.pageSize;
  84. }
  85. });
  86. const listItemsKeys = [];
  87. const triggerPaginationEvent = eventName => (page, pageSize) => {
  88. paginationCurrent.value = page;
  89. paginationSize.value = pageSize;
  90. if (paginationObj.value[eventName]) {
  91. paginationObj.value[eventName](page, pageSize);
  92. }
  93. };
  94. const onPaginationChange = triggerPaginationEvent('onChange');
  95. const onPaginationShowSizeChange = triggerPaginationEvent('onShowSizeChange');
  96. const loadingProp = computed(() => {
  97. if (typeof props.loading === 'boolean') {
  98. return {
  99. spinning: props.loading
  100. };
  101. } else {
  102. return props.loading;
  103. }
  104. });
  105. const isLoading = computed(() => loadingProp.value && loadingProp.value.spinning);
  106. const sizeCls = computed(() => {
  107. let size = '';
  108. switch (props.size) {
  109. case 'large':
  110. size = 'lg';
  111. break;
  112. case 'small':
  113. size = 'sm';
  114. break;
  115. default:
  116. break;
  117. }
  118. return size;
  119. });
  120. const classObj = computed(() => ({
  121. [`${prefixCls.value}`]: true,
  122. [`${prefixCls.value}-vertical`]: props.itemLayout === 'vertical',
  123. [`${prefixCls.value}-${sizeCls.value}`]: sizeCls.value,
  124. [`${prefixCls.value}-split`]: props.split,
  125. [`${prefixCls.value}-bordered`]: props.bordered,
  126. [`${prefixCls.value}-loading`]: isLoading.value,
  127. [`${prefixCls.value}-grid`]: !!props.grid,
  128. [`${prefixCls.value}-rtl`]: direction.value === 'rtl'
  129. }));
  130. const paginationProps = computed(() => {
  131. const pp = _extends(_extends(_extends({}, defaultPaginationProps), {
  132. total: props.dataSource.length,
  133. current: paginationCurrent.value,
  134. pageSize: paginationSize.value
  135. }), props.pagination || {});
  136. const largestPage = Math.ceil(pp.total / pp.pageSize);
  137. if (pp.current > largestPage) {
  138. pp.current = largestPage;
  139. }
  140. return pp;
  141. });
  142. const splitDataSource = computed(() => {
  143. let dd = [...props.dataSource];
  144. if (props.pagination) {
  145. if (props.dataSource.length > (paginationProps.value.current - 1) * paginationProps.value.pageSize) {
  146. dd = [...props.dataSource].splice((paginationProps.value.current - 1) * paginationProps.value.pageSize, paginationProps.value.pageSize);
  147. }
  148. }
  149. return dd;
  150. });
  151. const screens = useBreakpoint();
  152. const currentBreakpoint = eagerComputed(() => {
  153. for (let i = 0; i < responsiveArray.length; i += 1) {
  154. const breakpoint = responsiveArray[i];
  155. if (screens.value[breakpoint]) {
  156. return breakpoint;
  157. }
  158. }
  159. return undefined;
  160. });
  161. const colStyle = computed(() => {
  162. if (!props.grid) {
  163. return undefined;
  164. }
  165. const columnCount = currentBreakpoint.value && props.grid[currentBreakpoint.value] ? props.grid[currentBreakpoint.value] : props.grid.column;
  166. if (columnCount) {
  167. return {
  168. width: `${100 / columnCount}%`,
  169. maxWidth: `${100 / columnCount}%`
  170. };
  171. }
  172. return undefined;
  173. });
  174. const renderInnerItem = (item, index) => {
  175. var _a;
  176. const renderItem = (_a = props.renderItem) !== null && _a !== void 0 ? _a : slots.renderItem;
  177. if (!renderItem) return null;
  178. let key;
  179. const rowKeyType = typeof props.rowKey;
  180. if (rowKeyType === 'function') {
  181. key = props.rowKey(item);
  182. } else if (rowKeyType === 'string' || rowKeyType === 'number') {
  183. key = item[props.rowKey];
  184. } else {
  185. key = item.key;
  186. }
  187. if (!key) {
  188. key = `list-item-${index}`;
  189. }
  190. listItemsKeys[index] = key;
  191. return renderItem({
  192. item,
  193. index
  194. });
  195. };
  196. return () => {
  197. var _a, _b, _c, _d, _e, _f, _g, _h;
  198. const loadMore = (_a = props.loadMore) !== null && _a !== void 0 ? _a : (_b = slots.loadMore) === null || _b === void 0 ? void 0 : _b.call(slots);
  199. const footer = (_c = props.footer) !== null && _c !== void 0 ? _c : (_d = slots.footer) === null || _d === void 0 ? void 0 : _d.call(slots);
  200. const header = (_e = props.header) !== null && _e !== void 0 ? _e : (_f = slots.header) === null || _f === void 0 ? void 0 : _f.call(slots);
  201. const children = flattenChildren((_g = slots.default) === null || _g === void 0 ? void 0 : _g.call(slots));
  202. const isSomethingAfterLastItem = !!(loadMore || props.pagination || footer);
  203. const classString = classNames(_extends(_extends({}, classObj.value), {
  204. [`${prefixCls.value}-something-after-last-item`]: isSomethingAfterLastItem
  205. }), attrs.class, hashId.value);
  206. const paginationContent = props.pagination ? _createVNode("div", {
  207. "class": `${prefixCls.value}-pagination`
  208. }, [_createVNode(Pagination, _objectSpread(_objectSpread({}, paginationProps.value), {}, {
  209. "onChange": onPaginationChange,
  210. "onShowSizeChange": onPaginationShowSizeChange
  211. }), null)]) : null;
  212. let childrenContent = isLoading.value && _createVNode("div", {
  213. "style": {
  214. minHeight: '53px'
  215. }
  216. }, null);
  217. if (splitDataSource.value.length > 0) {
  218. listItemsKeys.length = 0;
  219. const items = splitDataSource.value.map((item, index) => renderInnerItem(item, index));
  220. const childrenList = items.map((child, index) => _createVNode("div", {
  221. "key": listItemsKeys[index],
  222. "style": colStyle.value
  223. }, [child]));
  224. childrenContent = props.grid ? _createVNode(Row, {
  225. "gutter": props.grid.gutter
  226. }, {
  227. default: () => [childrenList]
  228. }) : _createVNode("ul", {
  229. "class": `${prefixCls.value}-items`
  230. }, [items]);
  231. } else if (!children.length && !isLoading.value) {
  232. childrenContent = _createVNode("div", {
  233. "class": `${prefixCls.value}-empty-text`
  234. }, [((_h = props.locale) === null || _h === void 0 ? void 0 : _h.emptyText) || renderEmpty('List')]);
  235. }
  236. const paginationPosition = paginationProps.value.position || 'bottom';
  237. return wrapSSR(_createVNode("div", _objectSpread(_objectSpread({}, attrs), {}, {
  238. "class": classString
  239. }), [(paginationPosition === 'top' || paginationPosition === 'both') && paginationContent, header && _createVNode("div", {
  240. "class": `${prefixCls.value}-header`
  241. }, [header]), _createVNode(Spin, loadingProp.value, {
  242. default: () => [childrenContent, children]
  243. }), footer && _createVNode("div", {
  244. "class": `${prefixCls.value}-footer`
  245. }, [footer]), loadMore || (paginationPosition === 'bottom' || paginationPosition === 'both') && paginationContent]));
  246. };
  247. }
  248. });
  249. /* istanbul ignore next */
  250. List.install = function (app) {
  251. app.component(List.name, List);
  252. app.component(List.Item.name, List.Item);
  253. app.component(List.Item.Meta.name, List.Item.Meta);
  254. return app;
  255. };
  256. export { ItemMeta as ListItemMeta, Item as ListItem };
  257. export default List;