UNPKG

vuetify

Version:

Vue Material Component Framework

1 lines 10.1 kB
{"version":3,"file":"virtual.mjs","names":["useDisplay","useResizeObserver","computed","onMounted","ref","shallowRef","watch","watchEffect","clamp","createRange","propsFactory","UP","DOWN","makeVirtualProps","itemHeight","Number","String","useVirtual","props","items","offset","first","baseItemHeight","get","parseInt","value","set","val","containerRef","resizeRef","contentRect","display","sizeMap","Map","sizes","length","map","visibleItems","height","Math","max","ceil","handleItemResize","index","calculateOffset","slice","reduce","curr","calculateMidPointIndex","scrollTop","end","middle","middleOffset","lastScrollTop","handleScroll","direction","midPointIndex","buffer","round","scrollToIndex","allItems","item","raw","last","min","computedItems","paddingTop","paddingBottom","forEach","indexOf","delete"],"sources":["../../src/composables/virtual.ts"],"sourcesContent":["// Composables\nimport { useDisplay } from '@/composables/display'\nimport { useResizeObserver } from '@/composables/resizeObserver'\n\n// Utilities\nimport { computed, onMounted, ref, shallowRef, watch, watchEffect } from 'vue'\nimport {\n clamp,\n createRange,\n propsFactory,\n} from '@/util'\n\n// Types\nimport type { Ref } from 'vue'\n\nconst UP = -1\nconst DOWN = 1\n\ntype VirtualProps = {\n itemHeight?: number | string\n}\n\nexport const makeVirtualProps = propsFactory({\n itemHeight: [Number, String],\n}, 'virtual')\n\nexport function useVirtual <T> (props: VirtualProps, items: Ref<readonly T[]>, offset?: Ref<number>) {\n const first = shallowRef(0)\n const baseItemHeight = shallowRef(props.itemHeight)\n const itemHeight = computed({\n get: () => parseInt(baseItemHeight.value ?? 0, 10),\n set (val) {\n baseItemHeight.value = val\n },\n })\n const containerRef = ref<HTMLDivElement>()\n const { resizeRef, contentRect } = useResizeObserver()\n watchEffect(() => {\n resizeRef.value = containerRef.value\n })\n const display = useDisplay()\n\n const sizeMap = new Map<any, number>()\n let sizes = createRange(items.value.length).map(() => itemHeight.value)\n const visibleItems = computed(() => {\n const height = (contentRect.value?.height ?? display.height.value) - (offset?.value ?? 0)\n return itemHeight.value\n ? Math.max(12,\n Math.ceil((height / itemHeight.value) * 1.7 + 1)\n )\n : 12\n })\n\n function handleItemResize (index: number, height: number) {\n itemHeight.value = Math.max(itemHeight.value, height)\n sizes[index] = height\n sizeMap.set(items.value[index], height)\n }\n\n function calculateOffset (index: number) {\n return sizes.slice(0, index).reduce((curr, value) => curr + (value || itemHeight.value), 0)\n }\n\n function calculateMidPointIndex (scrollTop: number) {\n const end = items.value.length\n\n let middle = 0\n let middleOffset = 0\n while (middleOffset < scrollTop && middle < end) {\n middleOffset += sizes[middle++] || itemHeight.value\n }\n\n return middle - 1\n }\n\n let lastScrollTop = 0\n function handleScroll () {\n if (!containerRef.value || !contentRect.value) return\n\n const height = contentRect.value.height - 56\n const scrollTop = containerRef.value.scrollTop\n const direction = scrollTop < lastScrollTop ? UP : DOWN\n\n const midPointIndex = calculateMidPointIndex(scrollTop + height / 2)\n const buffer = Math.round(visibleItems.value / 3)\n if (direction === UP && midPointIndex <= first.value + (buffer * 2) - 1) {\n first.value = clamp(midPointIndex - buffer, 0, items.value.length)\n } else if (direction === DOWN && midPointIndex >= first.value + (buffer * 2) - 1) {\n first.value = clamp(midPointIndex - buffer, 0, items.value.length - visibleItems.value)\n }\n\n lastScrollTop = containerRef.value.scrollTop\n }\n\n function scrollToIndex (index: number) {\n if (!containerRef.value) return\n\n const offset = calculateOffset(index)\n containerRef.value.scrollTop = offset\n }\n\n const allItems = computed(() => items.value.map((item, index) => ({\n raw: item,\n index,\n })))\n const last = computed(() => Math.min(items.value.length, first.value + visibleItems.value))\n const computedItems = computed(() => allItems.value.slice(first.value, last.value))\n const paddingTop = computed(() => calculateOffset(first.value))\n const paddingBottom = computed(() => calculateOffset(items.value.length) - calculateOffset(last.value))\n\n onMounted(() => {\n if (!itemHeight.value) {\n // If itemHeight prop is not set, then calculate an estimated height from the average of inital items\n itemHeight.value = sizes.slice(first.value, last.value).reduce((curr, height) => curr + height, 0) / (visibleItems.value)\n }\n })\n\n watch(() => items.value.length, () => {\n sizes = createRange(items.value.length).map(() => itemHeight.value)\n sizeMap.forEach((height, item) => {\n const index = items.value.indexOf(item)\n if (index === -1) {\n sizeMap.delete(item)\n } else {\n sizes[index] = height\n }\n })\n })\n\n return {\n containerRef,\n computedItems,\n itemHeight,\n paddingTop,\n paddingBottom,\n scrollToIndex,\n handleScroll,\n handleItemResize,\n }\n}\n"],"mappings":"AAAA;AAAA,SACSA,UAAU;AAAA,SACVC,iBAAiB,gCAE1B;AACA,SAASC,QAAQ,EAAEC,SAAS,EAAEC,GAAG,EAAEC,UAAU,EAAEC,KAAK,EAAEC,WAAW,QAAQ,KAAK;AAAA,SAE5EC,KAAK,EACLC,WAAW,EACXC,YAAY,6BAGd;AAGA,MAAMC,EAAE,GAAG,CAAC,CAAC;AACb,MAAMC,IAAI,GAAG,CAAC;AAMd,OAAO,MAAMC,gBAAgB,GAAGH,YAAY,CAAC;EAC3CI,UAAU,EAAE,CAACC,MAAM,EAAEC,MAAM;AAC7B,CAAC,EAAE,SAAS,CAAC;AAEb,OAAO,SAASC,UAAUA,CAAMC,KAAmB,EAAEC,KAAwB,EAAEC,MAAoB,EAAE;EACnG,MAAMC,KAAK,GAAGhB,UAAU,CAAC,CAAC,CAAC;EAC3B,MAAMiB,cAAc,GAAGjB,UAAU,CAACa,KAAK,CAACJ,UAAU,CAAC;EACnD,MAAMA,UAAU,GAAGZ,QAAQ,CAAC;IAC1BqB,GAAG,EAAEA,CAAA,KAAMC,QAAQ,CAACF,cAAc,CAACG,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;IAClDC,GAAGA,CAAEC,GAAG,EAAE;MACRL,cAAc,CAACG,KAAK,GAAGE,GAAG;IAC5B;EACF,CAAC,CAAC;EACF,MAAMC,YAAY,GAAGxB,GAAG,EAAkB;EAC1C,MAAM;IAAEyB,SAAS;IAAEC;EAAY,CAAC,GAAG7B,iBAAiB,EAAE;EACtDM,WAAW,CAAC,MAAM;IAChBsB,SAAS,CAACJ,KAAK,GAAGG,YAAY,CAACH,KAAK;EACtC,CAAC,CAAC;EACF,MAAMM,OAAO,GAAG/B,UAAU,EAAE;EAE5B,MAAMgC,OAAO,GAAG,IAAIC,GAAG,EAAe;EACtC,IAAIC,KAAK,GAAGzB,WAAW,CAACU,KAAK,CAACM,KAAK,CAACU,MAAM,CAAC,CAACC,GAAG,CAAC,MAAMtB,UAAU,CAACW,KAAK,CAAC;EACvE,MAAMY,YAAY,GAAGnC,QAAQ,CAAC,MAAM;IAClC,MAAMoC,MAAM,GAAG,CAACR,WAAW,CAACL,KAAK,EAAEa,MAAM,IAAIP,OAAO,CAACO,MAAM,CAACb,KAAK,KAAKL,MAAM,EAAEK,KAAK,IAAI,CAAC,CAAC;IACzF,OAAOX,UAAU,CAACW,KAAK,GACnBc,IAAI,CAACC,GAAG,CAAC,EAAE,EACXD,IAAI,CAACE,IAAI,CAAEH,MAAM,GAAGxB,UAAU,CAACW,KAAK,GAAI,GAAG,GAAG,CAAC,CAAC,CACjD,GACC,EAAE;EACR,CAAC,CAAC;EAEF,SAASiB,gBAAgBA,CAAEC,KAAa,EAAEL,MAAc,EAAE;IACxDxB,UAAU,CAACW,KAAK,GAAGc,IAAI,CAACC,GAAG,CAAC1B,UAAU,CAACW,KAAK,EAAEa,MAAM,CAAC;IACrDJ,KAAK,CAACS,KAAK,CAAC,GAAGL,MAAM;IACrBN,OAAO,CAACN,GAAG,CAACP,KAAK,CAACM,KAAK,CAACkB,KAAK,CAAC,EAAEL,MAAM,CAAC;EACzC;EAEA,SAASM,eAAeA,CAAED,KAAa,EAAE;IACvC,OAAOT,KAAK,CAACW,KAAK,CAAC,CAAC,EAAEF,KAAK,CAAC,CAACG,MAAM,CAAC,CAACC,IAAI,EAAEtB,KAAK,KAAKsB,IAAI,IAAItB,KAAK,IAAIX,UAAU,CAACW,KAAK,CAAC,EAAE,CAAC,CAAC;EAC7F;EAEA,SAASuB,sBAAsBA,CAAEC,SAAiB,EAAE;IAClD,MAAMC,GAAG,GAAG/B,KAAK,CAACM,KAAK,CAACU,MAAM;IAE9B,IAAIgB,MAAM,GAAG,CAAC;IACd,IAAIC,YAAY,GAAG,CAAC;IACpB,OAAOA,YAAY,GAAGH,SAAS,IAAIE,MAAM,GAAGD,GAAG,EAAE;MAC/CE,YAAY,IAAIlB,KAAK,CAACiB,MAAM,EAAE,CAAC,IAAIrC,UAAU,CAACW,KAAK;IACrD;IAEA,OAAO0B,MAAM,GAAG,CAAC;EACnB;EAEA,IAAIE,aAAa,GAAG,CAAC;EACrB,SAASC,YAAYA,CAAA,EAAI;IACvB,IAAI,CAAC1B,YAAY,CAACH,KAAK,IAAI,CAACK,WAAW,CAACL,KAAK,EAAE;IAE/C,MAAMa,MAAM,GAAGR,WAAW,CAACL,KAAK,CAACa,MAAM,GAAG,EAAE;IAC5C,MAAMW,SAAS,GAAGrB,YAAY,CAACH,KAAK,CAACwB,SAAS;IAC9C,MAAMM,SAAS,GAAGN,SAAS,GAAGI,aAAa,GAAG1C,EAAE,GAAGC,IAAI;IAEvD,MAAM4C,aAAa,GAAGR,sBAAsB,CAACC,SAAS,GAAGX,MAAM,GAAG,CAAC,CAAC;IACpE,MAAMmB,MAAM,GAAGlB,IAAI,CAACmB,KAAK,CAACrB,YAAY,CAACZ,KAAK,GAAG,CAAC,CAAC;IACjD,IAAI8B,SAAS,KAAK5C,EAAE,IAAI6C,aAAa,IAAInC,KAAK,CAACI,KAAK,GAAIgC,MAAM,GAAG,CAAE,GAAG,CAAC,EAAE;MACvEpC,KAAK,CAACI,KAAK,GAAGjB,KAAK,CAACgD,aAAa,GAAGC,MAAM,EAAE,CAAC,EAAEtC,KAAK,CAACM,KAAK,CAACU,MAAM,CAAC;IACpE,CAAC,MAAM,IAAIoB,SAAS,KAAK3C,IAAI,IAAI4C,aAAa,IAAInC,KAAK,CAACI,KAAK,GAAIgC,MAAM,GAAG,CAAE,GAAG,CAAC,EAAE;MAChFpC,KAAK,CAACI,KAAK,GAAGjB,KAAK,CAACgD,aAAa,GAAGC,MAAM,EAAE,CAAC,EAAEtC,KAAK,CAACM,KAAK,CAACU,MAAM,GAAGE,YAAY,CAACZ,KAAK,CAAC;IACzF;IAEA4B,aAAa,GAAGzB,YAAY,CAACH,KAAK,CAACwB,SAAS;EAC9C;EAEA,SAASU,aAAaA,CAAEhB,KAAa,EAAE;IACrC,IAAI,CAACf,YAAY,CAACH,KAAK,EAAE;IAEzB,MAAML,MAAM,GAAGwB,eAAe,CAACD,KAAK,CAAC;IACrCf,YAAY,CAACH,KAAK,CAACwB,SAAS,GAAG7B,MAAM;EACvC;EAEA,MAAMwC,QAAQ,GAAG1D,QAAQ,CAAC,MAAMiB,KAAK,CAACM,KAAK,CAACW,GAAG,CAAC,CAACyB,IAAI,EAAElB,KAAK,MAAM;IAChEmB,GAAG,EAAED,IAAI;IACTlB;EACF,CAAC,CAAC,CAAC,CAAC;EACJ,MAAMoB,IAAI,GAAG7D,QAAQ,CAAC,MAAMqC,IAAI,CAACyB,GAAG,CAAC7C,KAAK,CAACM,KAAK,CAACU,MAAM,EAAEd,KAAK,CAACI,KAAK,GAAGY,YAAY,CAACZ,KAAK,CAAC,CAAC;EAC3F,MAAMwC,aAAa,GAAG/D,QAAQ,CAAC,MAAM0D,QAAQ,CAACnC,KAAK,CAACoB,KAAK,CAACxB,KAAK,CAACI,KAAK,EAAEsC,IAAI,CAACtC,KAAK,CAAC,CAAC;EACnF,MAAMyC,UAAU,GAAGhE,QAAQ,CAAC,MAAM0C,eAAe,CAACvB,KAAK,CAACI,KAAK,CAAC,CAAC;EAC/D,MAAM0C,aAAa,GAAGjE,QAAQ,CAAC,MAAM0C,eAAe,CAACzB,KAAK,CAACM,KAAK,CAACU,MAAM,CAAC,GAAGS,eAAe,CAACmB,IAAI,CAACtC,KAAK,CAAC,CAAC;EAEvGtB,SAAS,CAAC,MAAM;IACd,IAAI,CAACW,UAAU,CAACW,KAAK,EAAE;MACrB;MACAX,UAAU,CAACW,KAAK,GAAGS,KAAK,CAACW,KAAK,CAACxB,KAAK,CAACI,KAAK,EAAEsC,IAAI,CAACtC,KAAK,CAAC,CAACqB,MAAM,CAAC,CAACC,IAAI,EAAET,MAAM,KAAKS,IAAI,GAAGT,MAAM,EAAE,CAAC,CAAC,GAAID,YAAY,CAACZ,KAAM;IAC3H;EACF,CAAC,CAAC;EAEFnB,KAAK,CAAC,MAAMa,KAAK,CAACM,KAAK,CAACU,MAAM,EAAE,MAAM;IACpCD,KAAK,GAAGzB,WAAW,CAACU,KAAK,CAACM,KAAK,CAACU,MAAM,CAAC,CAACC,GAAG,CAAC,MAAMtB,UAAU,CAACW,KAAK,CAAC;IACnEO,OAAO,CAACoC,OAAO,CAAC,CAAC9B,MAAM,EAAEuB,IAAI,KAAK;MAChC,MAAMlB,KAAK,GAAGxB,KAAK,CAACM,KAAK,CAAC4C,OAAO,CAACR,IAAI,CAAC;MACvC,IAAIlB,KAAK,KAAK,CAAC,CAAC,EAAE;QAChBX,OAAO,CAACsC,MAAM,CAACT,IAAI,CAAC;MACtB,CAAC,MAAM;QACL3B,KAAK,CAACS,KAAK,CAAC,GAAGL,MAAM;MACvB;IACF,CAAC,CAAC;EACJ,CAAC,CAAC;EAEF,OAAO;IACLV,YAAY;IACZqC,aAAa;IACbnD,UAAU;IACVoD,UAAU;IACVC,aAAa;IACbR,aAAa;IACbL,YAAY;IACZZ;EACF,CAAC;AACH"}