zhangyong
2023-08-22 1353e87cb21a4032d585d7404bae9042f2ebcf08
1
{"version":3,"file":"dynamic-size-list.mjs","sources":["../../../../../../../packages/components/virtual-list/src/components/dynamic-size-list.ts"],"sourcesContent":["import { throwError } from '@element-plus/utils'\n\nimport createList from '../builders/build-list'\n\nimport { isHorizontal } from '../utils'\nimport {\n  AUTO_ALIGNMENT,\n  CENTERED_ALIGNMENT,\n  DEFAULT_DYNAMIC_LIST_ITEM_SIZE,\n  END_ALIGNMENT,\n  SMART_ALIGNMENT,\n  START_ALIGNMENT,\n} from '../defaults'\nimport type { VirtualizedListProps } from '../props'\n\nimport type { ItemSize, ListCache, ListItem } from '../types'\n\ntype Props = VirtualizedListProps\n\nconst SCOPE = 'ElDynamicSizeList'\nconst getItemFromCache = (\n  props: Props,\n  index: number,\n  listCache: ListCache\n): ListItem => {\n  const { itemSize } = props\n  const { items, lastVisitedIndex } = listCache\n\n  if (index > lastVisitedIndex) {\n    let offset = 0\n    if (lastVisitedIndex >= 0) {\n      const item = items[lastVisitedIndex]\n      offset = item.offset + item.size\n    }\n\n    for (let i = lastVisitedIndex + 1; i <= index; i++) {\n      const size = (itemSize as ItemSize)(i)\n\n      items[i] = {\n        offset,\n        size,\n      }\n\n      offset += size\n    }\n\n    listCache.lastVisitedIndex = index\n  }\n\n  return items[index]\n}\n\nconst findItem = (props: Props, listCache: ListCache, offset: number) => {\n  const { items, lastVisitedIndex } = listCache\n\n  const lastVisitedOffset =\n    lastVisitedIndex > 0 ? items[lastVisitedIndex].offset : 0\n\n  if (lastVisitedOffset >= offset) {\n    return bs(props, listCache, 0, lastVisitedIndex, offset)\n  }\n  return es(props, listCache, Math.max(0, lastVisitedIndex), offset)\n}\n\n// bs stands for binary search which has approximately time complexity of O(Log n)\n// space complexity of O(1)\n// in this case we use it for search the offset of each item, since\n// the cached items' offset is monotonically increasing\nconst bs = (\n  props: Props,\n  listCache: ListCache,\n  low: number,\n  high: number,\n  offset: number\n) => {\n  while (low <= high) {\n    const mid = low + Math.floor((high - low) / 2)\n    const currentOffset = getItemFromCache(props, mid, listCache).offset\n\n    if (currentOffset === offset) {\n      return mid\n    } else if (currentOffset < offset) {\n      low = mid + 1\n    } else if (currentOffset > offset) {\n      high = mid - 1\n    }\n  }\n\n  return Math.max(0, low - 1)\n}\n\n// es stands for exponential search which has time complexity of O(Log n) and\n// space complexity of O(1) in the case of finding the boundary element.\n// the exponential indicator in this case is 2.\n// for more detail about exponential search click this link\n// https://www.freecodecamp.org/news/search-algorithms-exponential-search-explained/\n\nconst es = (\n  props: Props,\n  listCache: ListCache,\n  index: number,\n  offset: number\n) => {\n  const { total } = props\n  let exponent = 1\n\n  while (\n    index < total &&\n    getItemFromCache(props, index, listCache).offset < offset\n  ) {\n    index += exponent\n    exponent *= 2\n  }\n\n  return bs(\n    props,\n    listCache,\n    Math.floor(index / 2),\n    Math.min(index, total - 1),\n    offset\n  )\n}\n\nconst getEstimatedTotalSize = (\n  { total }: Props,\n  { items, estimatedItemSize, lastVisitedIndex }: ListCache\n) => {\n  let totalSizeOfMeasuredItems = 0\n\n  if (lastVisitedIndex >= total) {\n    lastVisitedIndex = total - 1\n  }\n\n  if (lastVisitedIndex >= 0) {\n    const item = items[lastVisitedIndex]\n    totalSizeOfMeasuredItems = item.offset + item.size\n  }\n\n  const numUnmeasuredItems = total - lastVisitedIndex - 1\n  const totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedItemSize\n  return totalSizeOfMeasuredItems + totalSizeOfUnmeasuredItems\n}\n\nconst DynamicSizeList = createList({\n  name: 'ElDynamicSizeList',\n  getItemOffset: (props, index, listCache) =>\n    getItemFromCache(props, index, listCache).offset,\n\n  getItemSize: (_, index, { items }) => items[index].size,\n\n  getEstimatedTotalSize,\n\n  getOffset: (props, index, alignment, scrollOffset, listCache) => {\n    const { height, layout, width } = props\n\n    const size = (isHorizontal(layout) ? width : height) as number\n    const item = getItemFromCache(props, index, listCache)\n\n    const estimatedTotalSize = getEstimatedTotalSize(props, listCache)\n\n    const maxOffset = Math.max(\n      0,\n      Math.min(estimatedTotalSize - size, item.offset)\n    )\n    const minOffset = Math.max(0, item.offset - size + item.size)\n\n    if (alignment === SMART_ALIGNMENT) {\n      if (\n        scrollOffset >= minOffset - size &&\n        scrollOffset <= maxOffset + size\n      ) {\n        alignment = AUTO_ALIGNMENT\n      } else {\n        alignment = CENTERED_ALIGNMENT\n      }\n    }\n\n    switch (alignment) {\n      case START_ALIGNMENT: {\n        return maxOffset\n      }\n      case END_ALIGNMENT: {\n        return minOffset\n      }\n      case CENTERED_ALIGNMENT: {\n        return Math.round(minOffset + (maxOffset - minOffset) / 2)\n      }\n      case AUTO_ALIGNMENT:\n      default: {\n        if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {\n          return scrollOffset\n        } else if (scrollOffset < minOffset) {\n          return minOffset\n        } else {\n          return maxOffset\n        }\n      }\n    }\n  },\n\n  getStartIndexForOffset: (props, offset, listCache) =>\n    findItem(props, listCache, offset),\n\n  getStopIndexForStartIndex: (props, startIndex, scrollOffset, listCache) => {\n    const { height, total, layout, width } = props\n\n    const size = (isHorizontal(layout) ? width : height) as number\n    const item = getItemFromCache(props, startIndex, listCache)\n    const maxOffset = scrollOffset + size\n\n    let offset = item.offset + item.size\n    let stopIndex = startIndex\n\n    while (stopIndex < total - 1 && offset < maxOffset) {\n      stopIndex++\n      offset += getItemFromCache(props, stopIndex, listCache).size\n    }\n\n    return stopIndex\n  },\n\n  initCache({ estimatedItemSize = DEFAULT_DYNAMIC_LIST_ITEM_SIZE }, instance) {\n    const cache = {\n      items: {},\n      estimatedItemSize,\n      lastVisitedIndex: -1,\n    } as ListCache\n\n    cache.clearCacheAfterIndex = (index: number, forceUpdate = true) => {\n      cache.lastVisitedIndex = Math.min(cache.lastVisitedIndex, index - 1)\n      instance.exposed?.getItemStyleCache(-1)\n\n      if (forceUpdate) {\n        instance.proxy?.$forceUpdate()\n      }\n    }\n\n    return cache\n  },\n\n  clearCache: false,\n\n  validateProps: ({ itemSize }) => {\n    if (process.env.NODE_ENV !== 'production') {\n      if (typeof itemSize !== 'function') {\n        throwError(\n          SCOPE,\n          `\n          itemSize is required as function, but the given value was ${typeof itemSize}\n        `\n        )\n      }\n    }\n  },\n})\n\nexport default DynamicSizeList\n"],"names":[],"mappings":"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"}