table-grid.mjs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import { isNumber, isObject } from "../../../utils/types.mjs";
  2. import FixedSizeGrid from "../../virtual-list/src/components/fixed-size-grid.mjs";
  3. import DynamicSizeGrid from "../../virtual-list/src/components/dynamic-size-grid.mjs";
  4. import { sum } from "./utils.mjs";
  5. import { TABLE_V2_GRID_INJECTION_KEY, TableV2InjectionKey } from "./tokens.mjs";
  6. import { tableV2GridProps } from "./grid.mjs";
  7. import TableV2Header from "./components/header.mjs";
  8. import { computed, createVNode, defineComponent, inject, nextTick, onActivated, provide, ref, unref, watch } from "vue";
  9. //#region ../../packages/components/table-v2/src/table-grid.tsx
  10. const COMPONENT_NAME = "ElTableV2Grid";
  11. const useTableGrid = (props) => {
  12. const headerRef = ref();
  13. const bodyRef = ref();
  14. const scrollLeft = ref(0);
  15. const totalHeight = computed(() => {
  16. const { data, rowHeight, estimatedRowHeight } = props;
  17. if (estimatedRowHeight) return;
  18. return data.length * rowHeight;
  19. });
  20. const fixedRowHeight = computed(() => {
  21. const { fixedData, rowHeight } = props;
  22. return (fixedData?.length || 0) * rowHeight;
  23. });
  24. const headerHeight = computed(() => sum(props.headerHeight));
  25. const gridHeight = computed(() => {
  26. const { height } = props;
  27. return Math.max(0, height - unref(headerHeight) - unref(fixedRowHeight));
  28. });
  29. const hasHeader = computed(() => {
  30. return unref(headerHeight) + unref(fixedRowHeight) > 0;
  31. });
  32. const itemKey = ({ data, rowIndex }) => data[rowIndex][props.rowKey];
  33. function onItemRendered({ rowCacheStart, rowCacheEnd, rowVisibleStart, rowVisibleEnd }) {
  34. props.onRowsRendered?.({
  35. rowCacheStart,
  36. rowCacheEnd,
  37. rowVisibleStart,
  38. rowVisibleEnd
  39. });
  40. }
  41. function resetAfterRowIndex(index, forceUpdate) {
  42. bodyRef.value?.resetAfterRowIndex(index, forceUpdate);
  43. }
  44. function scrollTo(leftOrOptions, top) {
  45. const header$ = unref(headerRef);
  46. const body$ = unref(bodyRef);
  47. if (isObject(leftOrOptions)) {
  48. header$?.scrollToLeft(leftOrOptions.scrollLeft);
  49. scrollLeft.value = leftOrOptions.scrollLeft;
  50. body$?.scrollTo(leftOrOptions);
  51. } else {
  52. header$?.scrollToLeft(leftOrOptions);
  53. scrollLeft.value = leftOrOptions;
  54. body$?.scrollTo({
  55. scrollLeft: leftOrOptions,
  56. scrollTop: top
  57. });
  58. }
  59. }
  60. function scrollToTop(scrollTop) {
  61. unref(bodyRef)?.scrollTo({ scrollTop });
  62. }
  63. function scrollToRow(row, strategy) {
  64. const body = unref(bodyRef);
  65. if (!body) return;
  66. const prevScrollLeft = scrollLeft.value;
  67. body.scrollToItem(row, 0, strategy);
  68. if (prevScrollLeft) scrollTo({ scrollLeft: prevScrollLeft });
  69. }
  70. function forceUpdate() {
  71. unref(bodyRef)?.$forceUpdate();
  72. unref(headerRef)?.$forceUpdate();
  73. }
  74. watch(() => props.bodyWidth, () => {
  75. if (isNumber(props.estimatedRowHeight)) bodyRef.value?.resetAfter({ columnIndex: 0 }, false);
  76. });
  77. return {
  78. bodyRef,
  79. forceUpdate,
  80. fixedRowHeight,
  81. gridHeight,
  82. hasHeader,
  83. headerHeight,
  84. headerRef,
  85. totalHeight,
  86. itemKey,
  87. onItemRendered,
  88. resetAfterRowIndex,
  89. scrollTo,
  90. scrollToTop,
  91. scrollToRow,
  92. scrollLeft
  93. };
  94. };
  95. const TableGrid = /* @__PURE__ */ defineComponent({
  96. name: COMPONENT_NAME,
  97. props: tableV2GridProps,
  98. setup(props, { slots, expose }) {
  99. const { ns } = inject(TableV2InjectionKey);
  100. const { bodyRef, fixedRowHeight, gridHeight, hasHeader, headerRef, headerHeight, totalHeight, forceUpdate, itemKey, onItemRendered, resetAfterRowIndex, scrollTo, scrollToTop, scrollToRow, scrollLeft } = useTableGrid(props);
  101. provide(TABLE_V2_GRID_INJECTION_KEY, scrollLeft);
  102. onActivated(async () => {
  103. await nextTick();
  104. const scrollTop = bodyRef.value?.states.scrollTop;
  105. scrollTop && scrollToTop(Math.round(scrollTop) + 1);
  106. });
  107. expose({
  108. forceUpdate,
  109. totalHeight,
  110. scrollTo,
  111. scrollToTop,
  112. scrollToRow,
  113. resetAfterRowIndex
  114. });
  115. const getColumnWidth = () => props.bodyWidth;
  116. return () => {
  117. const { cache, columns, data, fixedData, useIsScrolling, scrollbarAlwaysOn, scrollbarEndGap, scrollbarStartGap, style, rowHeight, bodyWidth, estimatedRowHeight, headerWidth, height, width, getRowHeight, onScroll } = props;
  118. const isDynamicRowEnabled = isNumber(estimatedRowHeight);
  119. const Grid = isDynamicRowEnabled ? DynamicSizeGrid : FixedSizeGrid;
  120. const _headerHeight = unref(headerHeight);
  121. return createVNode("div", {
  122. "role": "table",
  123. "class": [ns.e("table"), props.class],
  124. "style": style
  125. }, [createVNode(Grid, {
  126. "ref": bodyRef,
  127. "data": data,
  128. "useIsScrolling": useIsScrolling,
  129. "itemKey": itemKey,
  130. "columnCache": 0,
  131. "columnWidth": isDynamicRowEnabled ? getColumnWidth : bodyWidth,
  132. "totalColumn": 1,
  133. "totalRow": data.length,
  134. "rowCache": cache,
  135. "rowHeight": isDynamicRowEnabled ? getRowHeight : rowHeight,
  136. "width": width,
  137. "height": unref(gridHeight),
  138. "class": ns.e("body"),
  139. "role": "rowgroup",
  140. "scrollbarStartGap": scrollbarStartGap,
  141. "scrollbarEndGap": scrollbarEndGap,
  142. "scrollbarAlwaysOn": scrollbarAlwaysOn,
  143. "onScroll": onScroll,
  144. "onItemRendered": onItemRendered,
  145. "perfMode": false
  146. }, { default: (params) => {
  147. const rowData = data[params.rowIndex];
  148. return slots.row?.({
  149. ...params,
  150. columns,
  151. rowData
  152. });
  153. } }), unref(hasHeader) && createVNode(TableV2Header, {
  154. "ref": headerRef,
  155. "class": ns.e("header-wrapper"),
  156. "columns": columns,
  157. "headerData": data,
  158. "headerHeight": props.headerHeight,
  159. "fixedHeaderData": fixedData,
  160. "rowWidth": headerWidth,
  161. "rowHeight": rowHeight,
  162. "width": width,
  163. "height": Math.min(_headerHeight + unref(fixedRowHeight), height)
  164. }, {
  165. dynamic: slots.header,
  166. fixed: slots.row
  167. })]);
  168. };
  169. }
  170. });
  171. //#endregion
  172. export { TableGrid as default };
  173. //# sourceMappingURL=table-grid.mjs.map