1057692024e2d1b51d410a07c528f4c73a6f5180f4702233525205b2c822f3a320780a1f476b382797447e20c086e39e5f89ebbcb6b3bf5049def4a9f784f0 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import createGrid from '../builders/build-grid.mjs';
  2. import { DEFAULT_DYNAMIC_LIST_ITEM_SIZE, AUTO_ALIGNMENT, CENTERED_ALIGNMENT, END_ALIGNMENT, START_ALIGNMENT, SMART_ALIGNMENT } from '../defaults.mjs';
  3. import { isNumber, isUndefined } from '../../../../utils/types.mjs';
  4. const { max, min, floor } = Math;
  5. const ACCESS_SIZER_KEY_MAP = {
  6. column: "columnWidth",
  7. row: "rowHeight"
  8. };
  9. const ACCESS_LAST_VISITED_KEY_MAP = {
  10. column: "lastVisitedColumnIndex",
  11. row: "lastVisitedRowIndex"
  12. };
  13. const getItemFromCache = (props, index, gridCache, type) => {
  14. const [cachedItems, sizer, lastVisited] = [
  15. gridCache[type],
  16. props[ACCESS_SIZER_KEY_MAP[type]],
  17. gridCache[ACCESS_LAST_VISITED_KEY_MAP[type]]
  18. ];
  19. if (index > lastVisited) {
  20. let offset = 0;
  21. if (lastVisited >= 0) {
  22. const item = cachedItems[lastVisited];
  23. offset = item.offset + item.size;
  24. }
  25. for (let i = lastVisited + 1; i <= index; i++) {
  26. const size = sizer(i);
  27. cachedItems[i] = {
  28. offset,
  29. size
  30. };
  31. offset += size;
  32. }
  33. gridCache[ACCESS_LAST_VISITED_KEY_MAP[type]] = index;
  34. }
  35. return cachedItems[index];
  36. };
  37. const bs = (props, gridCache, low, high, offset, type) => {
  38. while (low <= high) {
  39. const mid = low + floor((high - low) / 2);
  40. const currentOffset = getItemFromCache(props, mid, gridCache, type).offset;
  41. if (currentOffset === offset) {
  42. return mid;
  43. } else if (currentOffset < offset) {
  44. low = mid + 1;
  45. } else {
  46. high = mid - 1;
  47. }
  48. }
  49. return max(0, low - 1);
  50. };
  51. const es = (props, gridCache, idx, offset, type) => {
  52. const total = type === "column" ? props.totalColumn : props.totalRow;
  53. let exponent = 1;
  54. while (idx < total && getItemFromCache(props, idx, gridCache, type).offset < offset) {
  55. idx += exponent;
  56. exponent *= 2;
  57. }
  58. return bs(props, gridCache, floor(idx / 2), min(idx, total - 1), offset, type);
  59. };
  60. const findItem = (props, gridCache, offset, type) => {
  61. const [cache, lastVisitedIndex] = [
  62. gridCache[type],
  63. gridCache[ACCESS_LAST_VISITED_KEY_MAP[type]]
  64. ];
  65. const lastVisitedItemOffset = lastVisitedIndex > 0 ? cache[lastVisitedIndex].offset : 0;
  66. if (lastVisitedItemOffset >= offset) {
  67. return bs(props, gridCache, 0, lastVisitedIndex, offset, type);
  68. }
  69. return es(props, gridCache, max(0, lastVisitedIndex), offset, type);
  70. };
  71. const getEstimatedTotalHeight = ({ totalRow }, { estimatedRowHeight, lastVisitedRowIndex, row }) => {
  72. let sizeOfVisitedRows = 0;
  73. if (lastVisitedRowIndex >= totalRow) {
  74. lastVisitedRowIndex = totalRow - 1;
  75. }
  76. if (lastVisitedRowIndex >= 0) {
  77. const item = row[lastVisitedRowIndex];
  78. sizeOfVisitedRows = item.offset + item.size;
  79. }
  80. const unvisitedItems = totalRow - lastVisitedRowIndex - 1;
  81. const sizeOfUnvisitedItems = unvisitedItems * estimatedRowHeight;
  82. return sizeOfVisitedRows + sizeOfUnvisitedItems;
  83. };
  84. const getEstimatedTotalWidth = ({ totalColumn }, { column, estimatedColumnWidth, lastVisitedColumnIndex }) => {
  85. let sizeOfVisitedColumns = 0;
  86. if (lastVisitedColumnIndex > totalColumn) {
  87. lastVisitedColumnIndex = totalColumn - 1;
  88. }
  89. if (lastVisitedColumnIndex >= 0) {
  90. const item = column[lastVisitedColumnIndex];
  91. sizeOfVisitedColumns = item.offset + item.size;
  92. }
  93. const unvisitedItems = totalColumn - lastVisitedColumnIndex - 1;
  94. const sizeOfUnvisitedItems = unvisitedItems * estimatedColumnWidth;
  95. return sizeOfVisitedColumns + sizeOfUnvisitedItems;
  96. };
  97. const ACCESS_ESTIMATED_SIZE_KEY_MAP = {
  98. column: getEstimatedTotalWidth,
  99. row: getEstimatedTotalHeight
  100. };
  101. const getOffset = (props, index, alignment, scrollOffset, cache, type, scrollBarWidth) => {
  102. const [size, estimatedSizeAssociates] = [
  103. type === "row" ? props.height : props.width,
  104. ACCESS_ESTIMATED_SIZE_KEY_MAP[type]
  105. ];
  106. const item = getItemFromCache(props, index, cache, type);
  107. const estimatedSize = estimatedSizeAssociates(props, cache);
  108. const maxOffset = max(0, min(estimatedSize - size, item.offset));
  109. const minOffset = max(0, item.offset - size + scrollBarWidth + item.size);
  110. if (alignment === SMART_ALIGNMENT) {
  111. if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
  112. alignment = AUTO_ALIGNMENT;
  113. } else {
  114. alignment = CENTERED_ALIGNMENT;
  115. }
  116. }
  117. switch (alignment) {
  118. case START_ALIGNMENT: {
  119. return maxOffset;
  120. }
  121. case END_ALIGNMENT: {
  122. return minOffset;
  123. }
  124. case CENTERED_ALIGNMENT: {
  125. return Math.round(minOffset + (maxOffset - minOffset) / 2);
  126. }
  127. case AUTO_ALIGNMENT:
  128. default: {
  129. if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
  130. return scrollOffset;
  131. } else if (minOffset > maxOffset) {
  132. return minOffset;
  133. } else if (scrollOffset < minOffset) {
  134. return minOffset;
  135. } else {
  136. return maxOffset;
  137. }
  138. }
  139. }
  140. };
  141. const DynamicSizeGrid = createGrid({
  142. name: "ElDynamicSizeGrid",
  143. getColumnPosition: (props, idx, cache) => {
  144. const item = getItemFromCache(props, idx, cache, "column");
  145. return [item.size, item.offset];
  146. },
  147. getRowPosition: (props, idx, cache) => {
  148. const item = getItemFromCache(props, idx, cache, "row");
  149. return [item.size, item.offset];
  150. },
  151. getColumnOffset: (props, columnIndex, alignment, scrollLeft, cache, scrollBarWidth) => getOffset(props, columnIndex, alignment, scrollLeft, cache, "column", scrollBarWidth),
  152. getRowOffset: (props, rowIndex, alignment, scrollTop, cache, scrollBarWidth) => getOffset(props, rowIndex, alignment, scrollTop, cache, "row", scrollBarWidth),
  153. getColumnStartIndexForOffset: (props, scrollLeft, cache) => findItem(props, cache, scrollLeft, "column"),
  154. getColumnStopIndexForStartIndex: (props, startIndex, scrollLeft, cache) => {
  155. const item = getItemFromCache(props, startIndex, cache, "column");
  156. const maxOffset = scrollLeft + props.width;
  157. let offset = item.offset + item.size;
  158. let stopIndex = startIndex;
  159. while (stopIndex < props.totalColumn - 1 && offset < maxOffset) {
  160. stopIndex++;
  161. offset += getItemFromCache(props, startIndex, cache, "column").size;
  162. }
  163. return stopIndex;
  164. },
  165. getEstimatedTotalHeight,
  166. getEstimatedTotalWidth,
  167. getRowStartIndexForOffset: (props, scrollTop, cache) => findItem(props, cache, scrollTop, "row"),
  168. getRowStopIndexForStartIndex: (props, startIndex, scrollTop, cache) => {
  169. const { totalRow, height } = props;
  170. const item = getItemFromCache(props, startIndex, cache, "row");
  171. const maxOffset = scrollTop + height;
  172. let offset = item.size + item.offset;
  173. let stopIndex = startIndex;
  174. while (stopIndex < totalRow - 1 && offset < maxOffset) {
  175. stopIndex++;
  176. offset += getItemFromCache(props, stopIndex, cache, "row").size;
  177. }
  178. return stopIndex;
  179. },
  180. injectToInstance: (instance, cache) => {
  181. const resetAfter = ({ columnIndex, rowIndex }, forceUpdate) => {
  182. var _a, _b;
  183. forceUpdate = isUndefined(forceUpdate) ? true : forceUpdate;
  184. if (isNumber(columnIndex)) {
  185. cache.value.lastVisitedColumnIndex = Math.min(cache.value.lastVisitedColumnIndex, columnIndex - 1);
  186. }
  187. if (isNumber(rowIndex)) {
  188. cache.value.lastVisitedRowIndex = Math.min(cache.value.lastVisitedRowIndex, rowIndex - 1);
  189. }
  190. (_a = instance.exposed) == null ? void 0 : _a.getItemStyleCache.value(-1, null, null);
  191. if (forceUpdate)
  192. (_b = instance.proxy) == null ? void 0 : _b.$forceUpdate();
  193. };
  194. const resetAfterColumnIndex = (columnIndex, forceUpdate) => {
  195. resetAfter({
  196. columnIndex
  197. }, forceUpdate);
  198. };
  199. const resetAfterRowIndex = (rowIndex, forceUpdate) => {
  200. resetAfter({
  201. rowIndex
  202. }, forceUpdate);
  203. };
  204. Object.assign(instance.proxy, {
  205. resetAfterColumnIndex,
  206. resetAfterRowIndex,
  207. resetAfter
  208. });
  209. },
  210. initCache: ({
  211. estimatedColumnWidth = DEFAULT_DYNAMIC_LIST_ITEM_SIZE,
  212. estimatedRowHeight = DEFAULT_DYNAMIC_LIST_ITEM_SIZE
  213. }) => {
  214. const cache = {
  215. column: {},
  216. estimatedColumnWidth,
  217. estimatedRowHeight,
  218. lastVisitedColumnIndex: -1,
  219. lastVisitedRowIndex: -1,
  220. row: {}
  221. };
  222. return cache;
  223. },
  224. clearCache: false,
  225. validateProps: ({ columnWidth, rowHeight }) => {
  226. }
  227. });
  228. export { DynamicSizeGrid as default };
  229. //# sourceMappingURL=dynamic-size-grid.mjs.map