d7ab45c8ef144d8c60324f3ec11e819f1e4d64cfc23ac1548c43bdf3e6ff1fd570ef7b3aea51c2a951a8a6c19f267f6217732dcae03cfcb91ae2df23647ae2 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var buildList = require('../builders/build-list.js');
  4. var utils = require('../utils.js');
  5. var defaults = require('../defaults.js');
  6. const getItemFromCache = (props, index, listCache) => {
  7. const { itemSize } = props;
  8. const { items, lastVisitedIndex } = listCache;
  9. if (index > lastVisitedIndex) {
  10. let offset = 0;
  11. if (lastVisitedIndex >= 0) {
  12. const item = items[lastVisitedIndex];
  13. offset = item.offset + item.size;
  14. }
  15. for (let i = lastVisitedIndex + 1; i <= index; i++) {
  16. const size = itemSize(i);
  17. items[i] = {
  18. offset,
  19. size
  20. };
  21. offset += size;
  22. }
  23. listCache.lastVisitedIndex = index;
  24. }
  25. return items[index];
  26. };
  27. const findItem = (props, listCache, offset) => {
  28. const { items, lastVisitedIndex } = listCache;
  29. const lastVisitedOffset = lastVisitedIndex > 0 ? items[lastVisitedIndex].offset : 0;
  30. if (lastVisitedOffset >= offset) {
  31. return bs(props, listCache, 0, lastVisitedIndex, offset);
  32. }
  33. return es(props, listCache, Math.max(0, lastVisitedIndex), offset);
  34. };
  35. const bs = (props, listCache, low, high, offset) => {
  36. while (low <= high) {
  37. const mid = low + Math.floor((high - low) / 2);
  38. const currentOffset = getItemFromCache(props, mid, listCache).offset;
  39. if (currentOffset === offset) {
  40. return mid;
  41. } else if (currentOffset < offset) {
  42. low = mid + 1;
  43. } else if (currentOffset > offset) {
  44. high = mid - 1;
  45. }
  46. }
  47. return Math.max(0, low - 1);
  48. };
  49. const es = (props, listCache, index, offset) => {
  50. const { total } = props;
  51. let exponent = 1;
  52. while (index < total && getItemFromCache(props, index, listCache).offset < offset) {
  53. index += exponent;
  54. exponent *= 2;
  55. }
  56. return bs(props, listCache, Math.floor(index / 2), Math.min(index, total - 1), offset);
  57. };
  58. const getEstimatedTotalSize = ({ total }, { items, estimatedItemSize, lastVisitedIndex }) => {
  59. let totalSizeOfMeasuredItems = 0;
  60. if (lastVisitedIndex >= total) {
  61. lastVisitedIndex = total - 1;
  62. }
  63. if (lastVisitedIndex >= 0) {
  64. const item = items[lastVisitedIndex];
  65. totalSizeOfMeasuredItems = item.offset + item.size;
  66. }
  67. const numUnmeasuredItems = total - lastVisitedIndex - 1;
  68. const totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedItemSize;
  69. return totalSizeOfMeasuredItems + totalSizeOfUnmeasuredItems;
  70. };
  71. const DynamicSizeList = buildList["default"]({
  72. name: "ElDynamicSizeList",
  73. getItemOffset: (props, index, listCache) => getItemFromCache(props, index, listCache).offset,
  74. getItemSize: (_, index, { items }) => items[index].size,
  75. getEstimatedTotalSize,
  76. getOffset: (props, index, alignment, scrollOffset, listCache) => {
  77. const { height, layout, width } = props;
  78. const size = utils.isHorizontal(layout) ? width : height;
  79. const item = getItemFromCache(props, index, listCache);
  80. const estimatedTotalSize = getEstimatedTotalSize(props, listCache);
  81. const maxOffset = Math.max(0, Math.min(estimatedTotalSize - size, item.offset));
  82. const minOffset = Math.max(0, item.offset - size + item.size);
  83. if (alignment === defaults.SMART_ALIGNMENT) {
  84. if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
  85. alignment = defaults.AUTO_ALIGNMENT;
  86. } else {
  87. alignment = defaults.CENTERED_ALIGNMENT;
  88. }
  89. }
  90. switch (alignment) {
  91. case defaults.START_ALIGNMENT: {
  92. return maxOffset;
  93. }
  94. case defaults.END_ALIGNMENT: {
  95. return minOffset;
  96. }
  97. case defaults.CENTERED_ALIGNMENT: {
  98. return Math.round(minOffset + (maxOffset - minOffset) / 2);
  99. }
  100. case defaults.AUTO_ALIGNMENT:
  101. default: {
  102. if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
  103. return scrollOffset;
  104. } else if (scrollOffset < minOffset) {
  105. return minOffset;
  106. } else {
  107. return maxOffset;
  108. }
  109. }
  110. }
  111. },
  112. getStartIndexForOffset: (props, offset, listCache) => findItem(props, listCache, offset),
  113. getStopIndexForStartIndex: (props, startIndex, scrollOffset, listCache) => {
  114. const { height, total, layout, width } = props;
  115. const size = utils.isHorizontal(layout) ? width : height;
  116. const item = getItemFromCache(props, startIndex, listCache);
  117. const maxOffset = scrollOffset + size;
  118. let offset = item.offset + item.size;
  119. let stopIndex = startIndex;
  120. while (stopIndex < total - 1 && offset < maxOffset) {
  121. stopIndex++;
  122. offset += getItemFromCache(props, stopIndex, listCache).size;
  123. }
  124. return stopIndex;
  125. },
  126. initCache({ estimatedItemSize = defaults.DEFAULT_DYNAMIC_LIST_ITEM_SIZE }, instance) {
  127. const cache = {
  128. items: {},
  129. estimatedItemSize,
  130. lastVisitedIndex: -1
  131. };
  132. cache.clearCacheAfterIndex = (index, forceUpdate = true) => {
  133. var _a, _b;
  134. cache.lastVisitedIndex = Math.min(cache.lastVisitedIndex, index - 1);
  135. (_a = instance.exposed) == null ? void 0 : _a.getItemStyleCache(-1);
  136. if (forceUpdate) {
  137. (_b = instance.proxy) == null ? void 0 : _b.$forceUpdate();
  138. }
  139. };
  140. return cache;
  141. },
  142. clearCache: false,
  143. validateProps: ({ itemSize }) => {
  144. }
  145. });
  146. exports["default"] = DynamicSizeList;
  147. //# sourceMappingURL=dynamic-size-list.js.map