BodyGrid.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import _typeof from "@babel/runtime/helpers/esm/typeof";
  2. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  3. import { useContext } from '@rc-component/context';
  4. import VirtualList from 'rc-virtual-list';
  5. import * as React from 'react';
  6. import TableContext, { responseImmutable } from "../context/TableContext";
  7. import useFlattenRecords from "../hooks/useFlattenRecords";
  8. import BodyLine from "./BodyLine";
  9. import { GridContext, StaticContext } from "./context";
  10. var Grid = /*#__PURE__*/React.forwardRef(function (props, ref) {
  11. var data = props.data,
  12. onScroll = props.onScroll;
  13. var _useContext = useContext(TableContext, ['flattenColumns', 'onColumnResize', 'getRowKey', 'prefixCls', 'expandedKeys', 'childrenColumnName', 'scrollX', 'direction']),
  14. flattenColumns = _useContext.flattenColumns,
  15. onColumnResize = _useContext.onColumnResize,
  16. getRowKey = _useContext.getRowKey,
  17. expandedKeys = _useContext.expandedKeys,
  18. prefixCls = _useContext.prefixCls,
  19. childrenColumnName = _useContext.childrenColumnName,
  20. scrollX = _useContext.scrollX,
  21. direction = _useContext.direction;
  22. var _useContext2 = useContext(StaticContext),
  23. sticky = _useContext2.sticky,
  24. scrollY = _useContext2.scrollY,
  25. listItemHeight = _useContext2.listItemHeight,
  26. getComponent = _useContext2.getComponent,
  27. onTablePropScroll = _useContext2.onScroll;
  28. // =========================== Ref ============================
  29. var listRef = React.useRef();
  30. // =========================== Data ===========================
  31. var flattenData = useFlattenRecords(data, childrenColumnName, expandedKeys, getRowKey);
  32. // ========================== Column ==========================
  33. var columnsWidth = React.useMemo(function () {
  34. var total = 0;
  35. return flattenColumns.map(function (_ref) {
  36. var width = _ref.width,
  37. minWidth = _ref.minWidth,
  38. key = _ref.key;
  39. var finalWidth = Math.max(width || 0, minWidth || 0);
  40. total += finalWidth;
  41. return [key, finalWidth, total];
  42. });
  43. }, [flattenColumns]);
  44. var columnsOffset = React.useMemo(function () {
  45. return columnsWidth.map(function (colWidth) {
  46. return colWidth[2];
  47. });
  48. }, [columnsWidth]);
  49. React.useEffect(function () {
  50. columnsWidth.forEach(function (_ref2) {
  51. var _ref3 = _slicedToArray(_ref2, 2),
  52. key = _ref3[0],
  53. width = _ref3[1];
  54. onColumnResize(key, width);
  55. });
  56. }, [columnsWidth]);
  57. // =========================== Ref ============================
  58. React.useImperativeHandle(ref, function () {
  59. var _listRef$current2;
  60. var obj = {
  61. scrollTo: function scrollTo(config) {
  62. var _listRef$current;
  63. (_listRef$current = listRef.current) === null || _listRef$current === void 0 || _listRef$current.scrollTo(config);
  64. },
  65. nativeElement: (_listRef$current2 = listRef.current) === null || _listRef$current2 === void 0 ? void 0 : _listRef$current2.nativeElement
  66. };
  67. Object.defineProperty(obj, 'scrollLeft', {
  68. get: function get() {
  69. var _listRef$current3;
  70. return ((_listRef$current3 = listRef.current) === null || _listRef$current3 === void 0 ? void 0 : _listRef$current3.getScrollInfo().x) || 0;
  71. },
  72. set: function set(value) {
  73. var _listRef$current4;
  74. (_listRef$current4 = listRef.current) === null || _listRef$current4 === void 0 || _listRef$current4.scrollTo({
  75. left: value
  76. });
  77. }
  78. });
  79. // https://github.com/ant-design/ant-design/issues/54734
  80. Object.defineProperty(obj, 'scrollTop', {
  81. get: function get() {
  82. var _listRef$current5;
  83. return ((_listRef$current5 = listRef.current) === null || _listRef$current5 === void 0 ? void 0 : _listRef$current5.getScrollInfo().y) || 0;
  84. },
  85. set: function set(value) {
  86. var _listRef$current6;
  87. (_listRef$current6 = listRef.current) === null || _listRef$current6 === void 0 || _listRef$current6.scrollTo({
  88. top: value
  89. });
  90. }
  91. });
  92. return obj;
  93. });
  94. // ======================= Col/Row Span =======================
  95. var getRowSpan = function getRowSpan(column, index) {
  96. var _flattenData$index;
  97. var record = (_flattenData$index = flattenData[index]) === null || _flattenData$index === void 0 ? void 0 : _flattenData$index.record;
  98. var onCell = column.onCell;
  99. if (onCell) {
  100. var _cellProps$rowSpan;
  101. var cellProps = onCell(record, index);
  102. return (_cellProps$rowSpan = cellProps === null || cellProps === void 0 ? void 0 : cellProps.rowSpan) !== null && _cellProps$rowSpan !== void 0 ? _cellProps$rowSpan : 1;
  103. }
  104. return 1;
  105. };
  106. var extraRender = function extraRender(info) {
  107. var start = info.start,
  108. end = info.end,
  109. getSize = info.getSize,
  110. offsetY = info.offsetY;
  111. // Do nothing if no data
  112. if (end < 0) {
  113. return null;
  114. }
  115. // Find first rowSpan column
  116. var firstRowSpanColumns = flattenColumns.filter(
  117. // rowSpan is 0
  118. function (column) {
  119. return getRowSpan(column, start) === 0;
  120. });
  121. var startIndex = start;
  122. var _loop = function _loop(i) {
  123. firstRowSpanColumns = firstRowSpanColumns.filter(function (column) {
  124. return getRowSpan(column, i) === 0;
  125. });
  126. if (!firstRowSpanColumns.length) {
  127. startIndex = i;
  128. return 1; // break
  129. }
  130. };
  131. for (var i = start; i >= 0; i -= 1) {
  132. if (_loop(i)) break;
  133. }
  134. // Find last rowSpan column
  135. var lastRowSpanColumns = flattenColumns.filter(
  136. // rowSpan is not 1
  137. function (column) {
  138. return getRowSpan(column, end) !== 1;
  139. });
  140. var endIndex = end;
  141. var _loop2 = function _loop2(_i) {
  142. lastRowSpanColumns = lastRowSpanColumns.filter(function (column) {
  143. return getRowSpan(column, _i) !== 1;
  144. });
  145. if (!lastRowSpanColumns.length) {
  146. endIndex = Math.max(_i - 1, end);
  147. return 1; // break
  148. }
  149. };
  150. for (var _i = end; _i < flattenData.length; _i += 1) {
  151. if (_loop2(_i)) break;
  152. }
  153. // Collect the line who has rowSpan
  154. var spanLines = [];
  155. var _loop3 = function _loop3(_i2) {
  156. var item = flattenData[_i2];
  157. // This code will never reach, just incase
  158. if (!item) {
  159. return 1; // continue
  160. }
  161. if (flattenColumns.some(function (column) {
  162. return getRowSpan(column, _i2) > 1;
  163. })) {
  164. spanLines.push(_i2);
  165. }
  166. };
  167. for (var _i2 = startIndex; _i2 <= endIndex; _i2 += 1) {
  168. if (_loop3(_i2)) continue;
  169. }
  170. // Patch extra line on the page
  171. var nodes = spanLines.map(function (index) {
  172. var item = flattenData[index];
  173. var rowKey = getRowKey(item.record, index);
  174. var getHeight = function getHeight(rowSpan) {
  175. var endItemIndex = index + rowSpan - 1;
  176. var endItemKey = getRowKey(flattenData[endItemIndex].record, endItemIndex);
  177. var sizeInfo = getSize(rowKey, endItemKey);
  178. return sizeInfo.bottom - sizeInfo.top;
  179. };
  180. var sizeInfo = getSize(rowKey);
  181. return /*#__PURE__*/React.createElement(BodyLine, {
  182. key: index,
  183. data: item,
  184. rowKey: rowKey,
  185. index: index,
  186. style: {
  187. top: -offsetY + sizeInfo.top
  188. },
  189. extra: true,
  190. getHeight: getHeight
  191. });
  192. });
  193. return nodes;
  194. };
  195. // ========================= Context ==========================
  196. var gridContext = React.useMemo(function () {
  197. return {
  198. columnsOffset: columnsOffset
  199. };
  200. }, [columnsOffset]);
  201. // ========================== Render ==========================
  202. var tblPrefixCls = "".concat(prefixCls, "-tbody");
  203. // default 'div' in rc-virtual-list
  204. var wrapperComponent = getComponent(['body', 'wrapper']);
  205. // ========================== Sticky Scroll Bar ==========================
  206. var horizontalScrollBarStyle = {};
  207. if (sticky) {
  208. horizontalScrollBarStyle.position = 'sticky';
  209. horizontalScrollBarStyle.bottom = 0;
  210. if (_typeof(sticky) === 'object' && sticky.offsetScroll) {
  211. horizontalScrollBarStyle.bottom = sticky.offsetScroll;
  212. }
  213. }
  214. return /*#__PURE__*/React.createElement(GridContext.Provider, {
  215. value: gridContext
  216. }, /*#__PURE__*/React.createElement(VirtualList, {
  217. fullHeight: false,
  218. ref: listRef,
  219. prefixCls: "".concat(tblPrefixCls, "-virtual"),
  220. styles: {
  221. horizontalScrollBar: horizontalScrollBarStyle
  222. },
  223. className: tblPrefixCls,
  224. height: scrollY,
  225. itemHeight: listItemHeight || 24,
  226. data: flattenData,
  227. itemKey: function itemKey(item) {
  228. return getRowKey(item.record);
  229. },
  230. component: wrapperComponent,
  231. scrollWidth: scrollX,
  232. direction: direction,
  233. onVirtualScroll: function onVirtualScroll(_ref4) {
  234. var _listRef$current7;
  235. var x = _ref4.x;
  236. onScroll({
  237. currentTarget: (_listRef$current7 = listRef.current) === null || _listRef$current7 === void 0 ? void 0 : _listRef$current7.nativeElement,
  238. scrollLeft: x
  239. });
  240. },
  241. onScroll: onTablePropScroll,
  242. extraRender: extraRender
  243. }, function (item, index, itemProps) {
  244. var rowKey = getRowKey(item.record, index);
  245. return /*#__PURE__*/React.createElement(BodyLine, {
  246. data: item,
  247. rowKey: rowKey,
  248. index: index,
  249. style: itemProps.style
  250. });
  251. }));
  252. });
  253. var ResponseGrid = responseImmutable(Grid);
  254. if (process.env.NODE_ENV !== 'production') {
  255. ResponseGrid.displayName = 'ResponseGrid';
  256. }
  257. export default ResponseGrid;