@glhrmoura/vue-virtualize 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Guilherme Moura
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ <p align="center">
2
+ <img src="docs/public/logo.png" alt="" width="144" height="96" />
3
+ </p>
4
+
5
+ # Vue Virtualize
6
+
7
+ Headless virtualization for Vue 3 lists, grids, and tables.
8
+
9
+ [![License](https://img.shields.io/npm/l/@glhrmoura/vue-virtualize.svg?style=for-the-badge)](https://github.com/glhrmoura/vue-virtualize/blob/main/LICENSE)
10
+
11
+ `@glhrmoura/vue-virtualize` mounts only the items that intersect the viewport. The layout engine is plain TypeScript: it does not import Vue and it does not touch the DOM. Components and composables subscribe to scroll and resize, then render the window the engine returns.
12
+
13
+ ## Features
14
+
15
+ - Vertical and horizontal lists
16
+ - Two-axis grids
17
+ - Tables with virtualized rows and placed columns
18
+ - Configurable overscan
19
+ - Fixed estimates and measured dynamic sizes
20
+ - Programmatic `scrollToIndex` and `scrollToOffset`
21
+ - Reactive updates when the collection changes
22
+ - Container resize handling and listener cleanup
23
+ - Empty states and stable item keys
24
+ - SSR-safe: no browser APIs at import time
25
+ - TypeScript generics for item types
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ yarn add @glhrmoura/vue-virtualize
31
+ ```
32
+
33
+ ```bash
34
+ npm install @glhrmoura/vue-virtualize
35
+ ```
36
+
37
+ Vue 3.5+ is a peer dependency.
38
+
39
+ ## Quick start
40
+
41
+ ```vue
42
+ <script setup lang="ts">
43
+ import { VirtualList } from '@glhrmoura/vue-virtualize'
44
+ import { shallowRef } from 'vue'
45
+
46
+ interface User {
47
+ id: number
48
+ name: string
49
+ }
50
+
51
+ const users = shallowRef<User[]>(
52
+ Array.from({ length: 100_000 }, (_, index) => ({
53
+ id: index + 1,
54
+ name: `User ${index + 1}`,
55
+ })),
56
+ )
57
+ </script>
58
+
59
+ <template>
60
+ <VirtualList :items="users" :estimate-size="60" :height="500" :get-item-key="(user) => user.id">
61
+ <template #default="{ item, index }">
62
+ <UserCard :user="item" :index="index" />
63
+ </template>
64
+ </VirtualList>
65
+ </template>
66
+ ```
67
+
68
+ ## Examples
69
+
70
+ | Component | Use |
71
+ | ---------------- | ------------------------------------------------------ |
72
+ | `VirtualList` | One axis, vertical or `horizontal` |
73
+ | `VirtualGrid` | Flat array, `columnCount`, row and column estimates |
74
+ | `VirtualTable` | `rows`, `columns`, windowed body |
75
+ | `useVirtualizer` | Custom markup driven by `virtualItems` and `totalSize` |
76
+
77
+ The playground (`yarn dev`) includes 1,000, 10,000, and 100,000 row lists, a measured-height list, a grid, and a table.
78
+
79
+ ## Documentation
80
+
81
+ Guides and the API reference live in `docs/` and are built with VitePress:
82
+
83
+ ```bash
84
+ yarn docs:dev
85
+ ```
86
+
87
+ ## Scripts
88
+
89
+ ```bash
90
+ yarn test
91
+ yarn typecheck
92
+ yarn lint
93
+ yarn build
94
+ yarn bench
95
+ ```
96
+
97
+ `yarn bench` measures the engine locally. This repository does not publish benchmark numbers.
98
+
99
+ ## Publishing
100
+
101
+ Changesets tracks versions. CI runs lint, typecheck, tests, and the library build. Publishing to npm is a manual step after `yarn build`. The package name is `@glhrmoura/vue-virtualize`.
102
+
103
+ ## Contributing
104
+
105
+ 1. Install dependencies with yarn (`packageManager` is pinned in `package.json`).
106
+ 2. Branch from the default branch.
107
+ 3. Add a changeset when the public API or behavior changes.
108
+ 4. Run `yarn lint`, `yarn typecheck`, `yarn test`, and `yarn build`.
109
+
110
+ ## License
111
+
112
+ MIT
@@ -0,0 +1,53 @@
1
+ import { type HTMLAttributes } from 'vue';
2
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<{
4
+ items: readonly T[];
5
+ columnCount?: number;
6
+ estimateRowSize?: number | ((rowIndex: number) => number);
7
+ estimateColumnSize?: number | ((columnIndex: number) => number);
8
+ height?: number | string;
9
+ width?: number | string;
10
+ overscan?: number;
11
+ overscanRows?: number;
12
+ overscanColumns?: number;
13
+ rowGap?: number;
14
+ columnGap?: number;
15
+ getItemKey?: (item: T, index: number) => string | number;
16
+ tag?: string;
17
+ itemAttrs?: HTMLAttributes;
18
+ revision?: unknown;
19
+ }> & (typeof globalThis extends {
20
+ __VLS_PROPS_FALLBACK: infer P;
21
+ } ? P : {});
22
+ expose: (exposed: import("vue").ShallowUnwrapRef<{
23
+ scrollToIndex: (index: number, scrollOptions?: import("..").ScrollToIndexOptions) => void;
24
+ scrollToOffset: (offset: {
25
+ top?: number;
26
+ left?: number;
27
+ }, behavior?: ScrollBehavior) => void;
28
+ measureRow: (rowIndex: number, size: number) => void;
29
+ }>) => void;
30
+ attrs: any;
31
+ slots: {
32
+ empty?: (props: {}) => any;
33
+ } & {
34
+ default?: (props: {
35
+ item: T;
36
+ index: number;
37
+ rowIndex: number;
38
+ columnIndex: number;
39
+ row: import("..").VirtualItem;
40
+ column: import("..").VirtualItem;
41
+ }) => any;
42
+ };
43
+ emit: {};
44
+ }>) => import("vue").VNode & {
45
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
46
+ };
47
+ declare const _default: typeof __VLS_export;
48
+ export default _default;
49
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
50
+ [K in keyof T]: T[K];
51
+ } : {
52
+ [K in keyof T as K]: T[K];
53
+ }) & {};
@@ -0,0 +1,48 @@
1
+ import { type HTMLAttributes } from 'vue';
2
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<{
4
+ items: readonly T[];
5
+ estimateSize?: number | ((index: number, item: T) => number);
6
+ height?: number | string;
7
+ width?: number | string;
8
+ horizontal?: boolean;
9
+ overscan?: number;
10
+ gap?: number;
11
+ paddingStart?: number;
12
+ paddingEnd?: number;
13
+ getItemKey?: (item: T, index: number) => string | number;
14
+ tag?: string;
15
+ itemTag?: string;
16
+ itemAttrs?: HTMLAttributes;
17
+ revision?: unknown;
18
+ }> & (typeof globalThis extends {
19
+ __VLS_PROPS_FALLBACK: infer P;
20
+ } ? P : {});
21
+ expose: (exposed: import("vue").ShallowUnwrapRef<{
22
+ scrollToIndex: (index: number, scrollOptions?: import("..").ScrollToIndexOptions) => void;
23
+ scrollToOffset: (offset: number, behavior?: ScrollBehavior) => void;
24
+ measure: (index: number, size: number) => void;
25
+ }>) => void;
26
+ attrs: any;
27
+ slots: {
28
+ empty?: (props: {}) => any;
29
+ } & {
30
+ default?: (props: {
31
+ item: T;
32
+ index: number;
33
+ start: number;
34
+ size: number;
35
+ end: number;
36
+ }) => any;
37
+ };
38
+ emit: {};
39
+ }>) => import("vue").VNode & {
40
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
41
+ };
42
+ declare const _default: typeof __VLS_export;
43
+ export default _default;
44
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
45
+ [K in keyof T]: T[K];
46
+ } : {
47
+ [K in keyof T as K]: T[K];
48
+ }) & {};
@@ -0,0 +1,49 @@
1
+ import { type HTMLAttributes } from 'vue';
2
+ import { type VirtualTableColumn } from '../composables/useVirtualTable';
3
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
4
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<{
5
+ rows: readonly T[];
6
+ columns: readonly VirtualTableColumn<T>[];
7
+ estimateRowSize?: number | ((index: number, row: T) => number);
8
+ height?: number | string;
9
+ width?: number | string;
10
+ overscan?: number;
11
+ getRowKey?: (row: T, index: number) => string | number;
12
+ stickyHeader?: boolean;
13
+ tag?: string;
14
+ rowAttrs?: HTMLAttributes;
15
+ revision?: unknown;
16
+ }> & (typeof globalThis extends {
17
+ __VLS_PROPS_FALLBACK: infer P;
18
+ } ? P : {});
19
+ expose: (exposed: import("vue").ShallowUnwrapRef<{
20
+ scrollToIndex: (index: number, scrollOptions?: import("..").ScrollToIndexOptions) => void;
21
+ scrollToOffset: (offset: number, behavior?: ScrollBehavior) => void;
22
+ measure: (index: number, size: number) => void;
23
+ }>) => void;
24
+ attrs: any;
25
+ slots: {
26
+ header?: (props: {
27
+ columns: import("..").PlacedVirtualTableColumn<T>[];
28
+ }) => any;
29
+ } & {
30
+ empty?: (props: {}) => any;
31
+ } & {
32
+ cell?: (props: {
33
+ row: T;
34
+ column: import("..").PlacedVirtualTableColumn<T>;
35
+ rowIndex: number;
36
+ value: unknown;
37
+ }) => any;
38
+ };
39
+ emit: {};
40
+ }>) => import("vue").VNode & {
41
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
42
+ };
43
+ declare const _default: typeof __VLS_export;
44
+ export default _default;
45
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
46
+ [K in keyof T]: T[K];
47
+ } : {
48
+ [K in keyof T as K]: T[K];
49
+ }) & {};
@@ -0,0 +1,40 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ import type { ScrollToIndexOptions, VirtualItem } from '../core/types';
3
+ import { type UseVirtualizerOptions } from './useVirtualizer';
4
+ export interface VirtualGridCell<T> {
5
+ index: number;
6
+ key: string | number;
7
+ item: T;
8
+ row: VirtualItem;
9
+ column: VirtualItem;
10
+ }
11
+ export interface UseVirtualGridOptions<T> {
12
+ items: MaybeRefOrGetter<readonly T[]>;
13
+ columnCount: MaybeRefOrGetter<number>;
14
+ estimateRowSize?: MaybeRefOrGetter<number | ((rowIndex: number) => number)>;
15
+ estimateColumnSize?: MaybeRefOrGetter<number | ((columnIndex: number) => number)>;
16
+ container?: UseVirtualizerOptions['container'];
17
+ overscan?: MaybeRefOrGetter<number | undefined>;
18
+ overscanRows?: MaybeRefOrGetter<number | undefined>;
19
+ overscanColumns?: MaybeRefOrGetter<number | undefined>;
20
+ rowGap?: MaybeRefOrGetter<number | undefined>;
21
+ columnGap?: MaybeRefOrGetter<number | undefined>;
22
+ getItemKey?: (item: T, index: number) => string | number;
23
+ initialRect?: UseVirtualizerOptions['initialRect'];
24
+ revision?: UseVirtualizerOptions['revision'];
25
+ }
26
+ export declare function useVirtualGrid<T>(options: UseVirtualGridOptions<T>): {
27
+ virtualRows: import("vue").ComputedRef<VirtualItem[]>;
28
+ virtualColumns: import("vue").ComputedRef<VirtualItem[]>;
29
+ virtualCells: import("vue").ComputedRef<VirtualGridCell<T>[]>;
30
+ totalHeight: import("vue").ComputedRef<number>;
31
+ totalWidth: import("vue").ComputedRef<number>;
32
+ scrollToIndex: (index: number, scrollOptions?: ScrollToIndexOptions) => void;
33
+ scrollToOffset: (offset: {
34
+ top?: number;
35
+ left?: number;
36
+ }, behavior?: ScrollBehavior) => void;
37
+ measureRow: (rowIndex: number, size: number) => void;
38
+ measureRowElement: (target: unknown, rowIndex: number) => void;
39
+ measureColumn: (index: number, size: number) => void;
40
+ };
@@ -0,0 +1,31 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ import type { VirtualItem } from '../core/types';
3
+ import { type UseVirtualizerOptions } from './useVirtualizer';
4
+ export interface VirtualListItem<T> extends VirtualItem {
5
+ item: T;
6
+ }
7
+ export interface UseVirtualListOptions<T> {
8
+ items: MaybeRefOrGetter<readonly T[]>;
9
+ estimateSize?: number | ((index: number, item: T) => number);
10
+ container?: UseVirtualizerOptions['container'];
11
+ horizontal?: UseVirtualizerOptions['horizontal'];
12
+ overscan?: UseVirtualizerOptions['overscan'];
13
+ gap?: UseVirtualizerOptions['gap'];
14
+ paddingStart?: UseVirtualizerOptions['paddingStart'];
15
+ paddingEnd?: UseVirtualizerOptions['paddingEnd'];
16
+ itemSize?: UseVirtualizerOptions['itemSize'];
17
+ getItemKey?: (item: T, index: number) => string | number;
18
+ initialRect?: UseVirtualizerOptions['initialRect'];
19
+ viewportInset?: UseVirtualizerOptions['viewportInset'];
20
+ revision?: UseVirtualizerOptions['revision'];
21
+ }
22
+ export declare function useVirtualList<T>(options: UseVirtualListOptions<T>): {
23
+ virtualItems: import("vue").ComputedRef<VirtualListItem<T>[]>;
24
+ totalSize: import("vue").ComputedRef<number>;
25
+ scrollOffset: import("vue").ComputedRef<number>;
26
+ isScrolling: import("vue").ComputedRef<boolean>;
27
+ scrollToIndex: (index: number, scrollOptions?: import("..").ScrollToIndexOptions) => void;
28
+ scrollToOffset: (offset: number, behavior?: ScrollBehavior) => void;
29
+ measure: (index: number, size: number) => void;
30
+ measureElement: (target: unknown, index: number) => void;
31
+ };
@@ -0,0 +1,39 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ import { type UseVirtualListOptions, type VirtualListItem } from './useVirtualList';
3
+ export interface VirtualTableColumn<T> {
4
+ id: string;
5
+ header: string;
6
+ width?: number;
7
+ minWidth?: number;
8
+ align?: 'left' | 'center' | 'right';
9
+ accessor?: (row: T, index: number) => unknown;
10
+ }
11
+ export interface PlacedVirtualTableColumn<T> extends VirtualTableColumn<T> {
12
+ start: number;
13
+ size: number;
14
+ end: number;
15
+ }
16
+ export interface UseVirtualTableOptions<T> {
17
+ rows: MaybeRefOrGetter<readonly T[]>;
18
+ columns: MaybeRefOrGetter<readonly VirtualTableColumn<T>[]>;
19
+ estimateRowSize?: number | ((index: number, row: T) => number);
20
+ container?: UseVirtualListOptions<T>['container'];
21
+ overscan?: UseVirtualListOptions<T>['overscan'];
22
+ getRowKey?: (row: T, index: number) => string | number;
23
+ initialRect?: UseVirtualListOptions<T>['initialRect'];
24
+ viewportInset?: UseVirtualListOptions<T>['viewportInset'];
25
+ revision?: UseVirtualListOptions<T>['revision'];
26
+ itemSize?: UseVirtualListOptions<T>['itemSize'];
27
+ }
28
+ export declare function useVirtualTable<T>(options: UseVirtualTableOptions<T>): {
29
+ virtualRows: import("vue").ComputedRef<VirtualListItem<T>[]>;
30
+ columns: import("vue").ComputedRef<PlacedVirtualTableColumn<T>[]>;
31
+ totalHeight: import("vue").ComputedRef<number>;
32
+ totalWidth: import("vue").ComputedRef<number>;
33
+ scrollOffset: import("vue").ComputedRef<number>;
34
+ isScrolling: import("vue").ComputedRef<boolean>;
35
+ scrollToIndex: (index: number, scrollOptions?: import("..").ScrollToIndexOptions) => void;
36
+ scrollToOffset: (offset: number, behavior?: ScrollBehavior) => void;
37
+ measure: (index: number, size: number) => void;
38
+ measureElement: (target: unknown, index: number) => void;
39
+ };
@@ -0,0 +1,31 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ import type { ScrollToIndexOptions, VirtualItem } from '../core/types';
3
+ export interface UseVirtualizerOptions {
4
+ count: MaybeRefOrGetter<number>;
5
+ estimateSize: (index: number) => number;
6
+ container?: MaybeRefOrGetter<HTMLElement | null | undefined>;
7
+ horizontal?: MaybeRefOrGetter<boolean>;
8
+ overscan?: MaybeRefOrGetter<number>;
9
+ gap?: MaybeRefOrGetter<number>;
10
+ paddingStart?: MaybeRefOrGetter<number>;
11
+ paddingEnd?: MaybeRefOrGetter<number>;
12
+ lanes?: MaybeRefOrGetter<number>;
13
+ itemSize?: MaybeRefOrGetter<number | null | undefined>;
14
+ getItemKey?: (index: number) => string | number;
15
+ initialRect?: MaybeRefOrGetter<{
16
+ width: number;
17
+ height: number;
18
+ } | undefined>;
19
+ viewportInset?: MaybeRefOrGetter<number>;
20
+ revision?: MaybeRefOrGetter<unknown>;
21
+ }
22
+ export declare function useVirtualizer(options: UseVirtualizerOptions): {
23
+ virtualItems: import("vue").ComputedRef<VirtualItem[]>;
24
+ totalSize: import("vue").ComputedRef<number>;
25
+ scrollOffset: import("vue").ComputedRef<number>;
26
+ isScrolling: import("vue").ComputedRef<boolean>;
27
+ scrollToIndex: (index: number, scrollOptions?: ScrollToIndexOptions) => void;
28
+ scrollToOffset: (offset: number, behavior?: ScrollBehavior) => void;
29
+ measure: (index: number, size: number) => void;
30
+ measureElement: (target: unknown, index: number) => void;
31
+ };
@@ -0,0 +1,10 @@
1
+ export declare function normalizeSize(size: number): number;
2
+ export declare class MeasurementCache {
3
+ private readonly sizes;
4
+ private divergent;
5
+ get(index: number): number | undefined;
6
+ set(index: number, size: number, baseline: number | null): void;
7
+ get hasDivergent(): boolean;
8
+ clear(): void;
9
+ trim(count: number, baseline: number | null): void;
10
+ }
@@ -0,0 +1,11 @@
1
+ import type { ScrollAlignment } from './types';
2
+ export declare function clampScrollOffset(offset: number, totalSize: number, viewport: number): number;
3
+ export declare function findFirstIndexPast(count: number, target: number, getEnd: (index: number) => number): number;
4
+ export declare function findLastIndexBefore(count: number, target: number, getStart: (index: number) => number): number;
5
+ export declare function resolveScrollOffset(input: {
6
+ start: number;
7
+ size: number;
8
+ viewport: number;
9
+ current: number;
10
+ align: ScrollAlignment;
11
+ }): number;
@@ -0,0 +1,25 @@
1
+ export type ScrollAlignment = 'start' | 'center' | 'end' | 'auto';
2
+ export interface VirtualItem {
3
+ index: number;
4
+ key: string | number;
5
+ start: number;
6
+ size: number;
7
+ end: number;
8
+ lane: number;
9
+ }
10
+ export interface VirtualizerOptions {
11
+ count: number;
12
+ estimateSize: (index: number) => number;
13
+ overscan?: number;
14
+ gap?: number;
15
+ paddingStart?: number;
16
+ paddingEnd?: number;
17
+ lanes?: number;
18
+ itemSize?: number | null;
19
+ viewportSize?: number;
20
+ getItemKey?: (index: number) => string | number;
21
+ }
22
+ export interface ScrollToIndexOptions {
23
+ align?: ScrollAlignment;
24
+ behavior?: ScrollBehavior;
25
+ }
@@ -0,0 +1,35 @@
1
+ import type { ScrollAlignment, VirtualItem, VirtualizerOptions } from './types';
2
+ export declare class Virtualizer {
3
+ private count;
4
+ private estimateSize;
5
+ private overscan;
6
+ private gap;
7
+ private paddingStart;
8
+ private paddingEnd;
9
+ private lanes;
10
+ private itemSize;
11
+ private viewportSize;
12
+ private scrollOffset;
13
+ private getItemKey;
14
+ private readonly measurements;
15
+ private built;
16
+ private offsets;
17
+ private laneCursor;
18
+ private laneEnd;
19
+ setOptions(options: VirtualizerOptions): void;
20
+ setScrollOffset(offset: number): void;
21
+ getScrollOffset(): number;
22
+ getViewportSize(): number;
23
+ measure(index: number, size: number): boolean;
24
+ clearMeasurements(): void;
25
+ getItemSize(index: number): number;
26
+ getItemOffset(index: number): number;
27
+ getTotalSize(): number;
28
+ getVirtualItems(): VirtualItem[];
29
+ getOffsetForIndex(index: number, align?: ScrollAlignment): number;
30
+ private usesFixedPath;
31
+ private ordinalIndex;
32
+ private laneLength;
33
+ private ensure;
34
+ private resetGeometry;
35
+ }
@@ -0,0 +1,15 @@
1
+ export { Virtualizer } from './core/virtualizer';
2
+ export { MeasurementCache, normalizeSize } from './core/measurements';
3
+ export { clampScrollOffset, resolveScrollOffset } from './core/scrolling';
4
+ export type { ScrollAlignment, ScrollToIndexOptions, VirtualItem, VirtualizerOptions, } from './core/types';
5
+ export { useVirtualizer } from './composables/useVirtualizer';
6
+ export type { UseVirtualizerOptions } from './composables/useVirtualizer';
7
+ export { useVirtualList } from './composables/useVirtualList';
8
+ export type { UseVirtualListOptions, VirtualListItem } from './composables/useVirtualList';
9
+ export { useVirtualGrid } from './composables/useVirtualGrid';
10
+ export type { UseVirtualGridOptions, VirtualGridCell } from './composables/useVirtualGrid';
11
+ export { useVirtualTable } from './composables/useVirtualTable';
12
+ export type { PlacedVirtualTableColumn, UseVirtualTableOptions, VirtualTableColumn, } from './composables/useVirtualTable';
13
+ export { default as VirtualList } from './components/VirtualList.vue';
14
+ export { default as VirtualGrid } from './components/VirtualGrid.vue';
15
+ export { default as VirtualTable } from './components/VirtualTable.vue';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue");function K(e){return!Number.isFinite(e)||e<0?0:e}class Z{sizes=new Map;divergent=!1;get(n){return this.sizes.get(n)}set(n,i,r){this.sizes.set(n,i),r!==null&&Math.abs(i-r)>=.5&&(this.divergent=!0)}get hasDivergent(){return this.divergent}clear(){this.sizes.clear(),this.divergent=!1}trim(n,i){let r=!1;for(const s of this.sizes.keys())s>=n&&(this.sizes.delete(s),r=!0);if(r&&(this.divergent=!1,i!==null)){for(const s of this.sizes.values())if(Math.abs(s-i)>=.5){this.divergent=!0;return}}}}function ee(e,n,i){return Math.min(i,Math.max(n,e))}function G(e,n,i){const r=Math.max(0,n-Math.max(0,i));return ee(Number.isFinite(e)?e:0,0,r)}function le(e,n,i){if(e<=0)return 0;let r=0,s=e-1,o=e-1;for(;r<=s;){const d=r+s>>>1;i(d)>n?(o=d,s=d-1):r=d+1}return o}function ue(e,n,i){if(e<=0)return 0;let r=0,s=e-1,o=0;for(;r<=s;){const d=r+s>>>1;i(d)<n?(o=d,r=d+1):s=d-1}return o}function te(e){const n=e.start+e.size;let i=e.align;if(i==="auto"){const r=e.current+e.viewport;if(e.start>=e.current&&n<=r)return e.current;i=e.start<e.current?"start":"end"}return i==="center"?e.start-(e.viewport-e.size)/2:i==="end"?n-e.viewport:e.start}class ne{count=0;estimateSize=()=>0;overscan=0;gap=0;paddingStart=0;paddingEnd=0;lanes=1;itemSize=null;viewportSize=0;scrollOffset=0;getItemKey=n=>n;measurements=new Z;built=0;offsets=[];laneCursor=[];laneEnd=[];setOptions(n){const i=Math.max(1,Math.floor(n.lanes??1)),r=n.gap??0,s=n.paddingStart??0,o=n.paddingEnd??0,d=Math.max(0,Math.floor(n.count)),h=n.itemSize===void 0||n.itemSize===null?null:K(n.itemSize),y=this.itemSize,x=i!==this.lanes||r!==this.gap||s!==this.paddingStart||o!==this.paddingEnd||n.estimateSize!==this.estimateSize||h!==this.itemSize;this.count=d,this.lanes=i,this.gap=r,this.paddingStart=s,this.paddingEnd=o,this.overscan=Math.max(0,Math.floor(n.overscan??0)),this.estimateSize=n.estimateSize,this.itemSize=h,this.getItemKey=n.getItemKey??(v=>v),n.viewportSize!==void 0&&(this.viewportSize=Math.max(0,n.viewportSize)),h!==y&&this.measurements.clear(),this.measurements.trim(this.count,this.itemSize),(x||this.built>this.count)&&this.resetGeometry()}setScrollOffset(n){this.scrollOffset=Number.isFinite(n)?n:0}getScrollOffset(){return this.scrollOffset}getViewportSize(){return this.viewportSize}measure(n,i){if(n<0||n>=this.count)return!1;const r=K(i),s=this.measurements.get(n);if(s!==void 0&&Math.abs(s-r)<.5)return!1;const o=this.getItemSize(n);return this.measurements.set(n,r,this.itemSize),Math.abs(o-r)<.5?!1:(this.resetGeometry(),!0)}clearMeasurements(){this.measurements.clear(),this.resetGeometry()}getItemSize(n){const i=this.measurements.get(n);return i!==void 0?i:this.itemSize!==null?this.itemSize:K(this.estimateSize(n))}getItemOffset(n){if(n<=0||this.count<=0)return this.paddingStart;const i=Math.min(n,this.count-1);if(this.usesFixedPath()){const r=Math.floor(i/this.lanes);return this.paddingStart+r*((this.itemSize??0)+this.gap)}return this.ensure(i),this.offsets[i]??this.paddingStart}getTotalSize(){if(this.count<=0)return this.paddingStart+this.paddingEnd;if(this.usesFixedPath()){let i=this.paddingStart;const r=this.itemSize??0;for(let s=0;s<this.lanes&&s<this.count;s+=1){const o=this.laneLength(s),d=this.paddingStart+o*r+Math.max(0,o-1)*this.gap;d>i&&(i=d)}return i+this.paddingEnd}this.ensure(this.count-1);let n=this.paddingStart;for(let i=0;i<this.lanes&&i<this.count;i+=1){const r=this.laneEnd[i]??this.paddingStart;r>n&&(n=r)}return n+this.paddingEnd}getVirtualItems(){if(this.count<=0||this.viewportSize<=0)return[];const n=G(this.scrollOffset,this.getTotalSize(),this.viewportSize),i=n+this.viewportSize,r=[];for(let s=0;s<this.lanes;s+=1){const o=this.laneLength(s);if(o<=0)continue;const d=le(o,n,v=>{const p=this.ordinalIndex(s,v);return this.getItemOffset(p)+this.getItemSize(p)}),h=ue(o,i,v=>this.getItemOffset(this.ordinalIndex(s,v))),y=Math.max(0,Math.min(d,h)-this.overscan),x=Math.min(o-1,Math.max(d,h)+this.overscan);for(let v=y;v<=x;v+=1){const p=this.ordinalIndex(s,v),I=this.getItemOffset(p),E=this.getItemSize(p);r.push({index:p,key:this.getItemKey(p),start:I,size:E,end:I+E,lane:s})}}return r.sort((s,o)=>s.index-o.index),r}getOffsetForIndex(n,i="auto"){if(this.count<=0)return 0;const r=ee(n,0,this.count-1),s=this.getItemOffset(r),o=this.getItemSize(r),d=te({start:s,size:o,viewport:this.viewportSize,current:this.scrollOffset,align:i});return G(d,this.getTotalSize(),this.viewportSize)}usesFixedPath(){return this.itemSize!==null&&!this.measurements.hasDivergent}ordinalIndex(n,i){return n+i*this.lanes}laneLength(n){return n<0||n>=this.lanes||n>=this.count?0:Math.floor((this.count-n-1)/this.lanes)+1}ensure(n){if(n<this.built)return;const i=Math.min(n,this.count-1);for(;this.built<=i;){const r=this.built%this.lanes,s=this.laneCursor[r]??this.paddingStart;this.offsets[this.built]=s;const o=s+this.getItemSize(this.built);this.laneEnd[r]=o,this.laneCursor[r]=o+this.gap,this.built+=1}}resetGeometry(){this.built=0,this.offsets=[],this.laneCursor=Array.from({length:this.lanes},()=>this.paddingStart),this.laneEnd=Array.from({length:this.lanes},()=>this.paddingStart)}}function F(){return typeof window<"u"&&typeof document<"u"}function ie(e){return typeof Element>"u"?null:e instanceof Element?e:null}function N(e,n,i,r){if(r==="smooth"&&typeof e.scrollTo=="function"){e.scrollTo({top:i?e.scrollTop:n,left:i?n:e.scrollLeft,behavior:r});return}i?e.scrollLeft=n:e.scrollTop=n}function P(e,n){return n?e.scrollLeft:e.scrollTop}function U(e,n){return n?e.clientWidth:e.clientHeight}function Y(e){return typeof requestAnimationFrame=="function"?requestAnimationFrame(e):setTimeout(e,0)}function X(e){e&&(typeof cancelAnimationFrame=="function"?cancelAnimationFrame(e):clearTimeout(e))}function ce(e,n){if(e.length!==n.length)return!1;for(let i=0;i<e.length;i+=1){const r=e[i],s=n[i];if(!r||!s||r.index!==s.index||r.start!==s.start||r.size!==s.size||r.end!==s.end||r.lane!==s.lane||r.key!==s.key)return!1}return!0}function A(e){const n=new ne,i=t.shallowRef([]),r=t.ref(0),s=t.ref(0),o=t.ref(!1),d=c=>e.estimateSize(c);let h=null,y=null,x=null,v=0,p=0,I=0,E=t.toValue(e.revision);const l=new Map,u=new Map,a=[];function f(){const c=t.toValue(e.container);return typeof HTMLElement>"u"?null:c instanceof HTMLElement?c:null}function S(){return t.toValue(e.horizontal)??!1}function C(){const c=t.toValue(e.initialRect);return c?S()?c.width:c.height:0}function O(){const c=t.toValue(e.revision);Object.is(c,E)||(E=c,n.clearMeasurements());const z=f(),w=z?U(z,S()):0,V=t.toValue(e.viewportInset)??0,k=Math.max(0,(w>0?w:C())-V),T=t.toValue(e.itemSize);n.setOptions({count:t.toValue(e.count),estimateSize:d,overscan:t.toValue(e.overscan)??5,gap:t.toValue(e.gap)??0,paddingStart:t.toValue(e.paddingStart)??0,paddingEnd:t.toValue(e.paddingEnd)??0,lanes:t.toValue(e.lanes)??1,itemSize:T??null,getItemKey:e.getItemKey,viewportSize:k});const M=Math.max(0,n.getTotalSize()-k);n.getScrollOffset()>M&&(n.setScrollOffset(M),z&&P(z,S())!==M&&N(z,M,S(),"auto"));const _=n.getVirtualItems();ce(i.value,_)||(i.value=_);const j=n.getTotalSize();r.value!==j&&(r.value=j);const q=n.getScrollOffset();s.value!==q&&(s.value=q)}function $(){if(!F()){O();return}v||(v=Y(()=>{v=0,o.value=!0,O(),typeof window<"u"&&(window.clearTimeout(I),I=window.setTimeout(()=>{o.value=!1},150))}))}function m(){const c=f();c&&(n.setScrollOffset(P(c,S())),$())}function b(){const c=f();if(c===h||(h&&(h.removeEventListener("scroll",m),y?.disconnect(),y=null),h=c,!c||!F()))return;const z=S();n.getScrollOffset()>0?N(c,n.getScrollOffset(),z,"auto"):n.setScrollOffset(P(c,z)),c.addEventListener("scroll",m,{passive:!0}),typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>O()),y.observe(c))}function g(){return!F()||typeof ResizeObserver>"u"?null:(x||(x=new ResizeObserver(c=>{const z=S();let w=!1;for(const V of c){const k=l.get(V.target);if(k===void 0)continue;const T=V.borderBoxSize?.[0],M=z?T?.inlineSize??V.contentRect.width:T?.blockSize??V.contentRect.height;M>0&&n.measure(k,M)&&(w=!0)}w&&O()})),x)}function R(){p=0;const c=a.splice(0,a.length),z=S();let w=!1;for(const V of c){if(!V.element.isConnected)continue;const k=V.element.getBoundingClientRect(),T=z?k.width:k.height;T>0&&n.measure(V.index,T)&&(w=!0)}w&&O()}function L(c,z){const w=ie(c),V=g(),k=u.get(z);k&&k!==w&&(V?.unobserve(k),l.delete(k),u.delete(z)),w&&(u.set(z,w),l.set(w,z),V?.observe(w),a.push({element:w,index:z}),!p&&(p=Y(R)))}function W(c,z="auto"){const w=f(),V=w?U(w,S()):0,k=V>0?V:n.getViewportSize(),T=G(c,n.getTotalSize(),k);n.setScrollOffset(T),w&&N(w,T,S(),z),O()}function oe(c,z){const w=n.getOffsetForIndex(c,z?.align??"auto");W(w,z?.behavior??"auto")}function ae(c,z){n.measure(c,z)&&O()}return O(),t.watch(()=>[t.toValue(e.count),t.toValue(e.overscan),t.toValue(e.gap),t.toValue(e.paddingStart),t.toValue(e.paddingEnd),t.toValue(e.lanes),t.toValue(e.horizontal),t.toValue(e.itemSize),t.toValue(e.viewportInset),t.toValue(e.revision),t.toValue(e.container),t.toValue(e.initialRect)?.width,t.toValue(e.initialRect)?.height],()=>{b(),O()},{flush:"post"}),t.onBeforeUnmount(()=>{h&&h.removeEventListener("scroll",m),y?.disconnect(),x?.disconnect(),X(v),X(p),typeof window<"u"&&window.clearTimeout(I),l.clear(),u.clear(),a.length=0}),{virtualItems:t.computed(()=>i.value),totalSize:t.computed(()=>r.value),scrollOffset:t.computed(()=>s.value),isScrolling:t.computed(()=>o.value),scrollToIndex:oe,scrollToOffset:W,measure:ae,measureElement:L}}function de(e,n,i){return typeof e=="function"?e(n,i):typeof e=="number"?e:48}function H(e){const n=A({count:()=>t.toValue(e.items).length,estimateSize:r=>{const s=t.toValue(e.items);return de(e.estimateSize,r,s[r])},getItemKey:r=>{const o=t.toValue(e.items)[r];return e.getItemKey?.(o,r)??r},itemSize:()=>e.itemSize!==void 0?t.toValue(e.itemSize):typeof e.estimateSize=="number"?e.estimateSize:void 0,container:e.container,horizontal:e.horizontal,overscan:e.overscan,gap:e.gap,paddingStart:e.paddingStart,paddingEnd:e.paddingEnd,initialRect:e.initialRect,viewportInset:e.viewportInset,revision:e.revision});return{virtualItems:t.computed(()=>{const r=t.toValue(e.items);return n.virtualItems.value.map(s=>{const o=r[s.index];return{...s,item:o,key:e.getItemKey?.(o,s.index)??s.key}})}),totalSize:n.totalSize,scrollOffset:n.scrollOffset,isScrolling:n.isScrolling,scrollToIndex:n.scrollToIndex,scrollToOffset:n.scrollToOffset,measure:n.measure,measureElement:n.measureElement}}function J(e,n,i){return typeof e=="function"?e(n):typeof e=="number"?e:i}function re(e){const n=t.computed(()=>Math.max(1,Math.floor(t.toValue(e.columnCount)||1))),i=t.computed(()=>Math.ceil(t.toValue(e.items).length/n.value)),r=new Map,s=A({count:()=>i.value,estimateSize:l=>J(t.toValue(e.estimateRowSize),l,48),itemSize:()=>{const l=t.toValue(e.estimateRowSize);return typeof l=="number"?l:void 0},overscan:()=>t.toValue(e.overscanRows)??t.toValue(e.overscan)??2,gap:()=>t.toValue(e.rowGap)??0,horizontal:!1,container:e.container,initialRect:e.initialRect,revision:e.revision}),o=A({count:()=>n.value,estimateSize:l=>J(t.toValue(e.estimateColumnSize),l,160),itemSize:()=>{const l=t.toValue(e.estimateColumnSize);return typeof l=="number"?l:void 0},overscan:()=>t.toValue(e.overscanColumns)??t.toValue(e.overscan)??1,gap:()=>t.toValue(e.columnGap)??0,horizontal:!0,container:e.container,initialRect:e.initialRect,revision:e.revision}),d=t.computed(()=>{const l=t.toValue(e.items),u=n.value,a=[];for(const f of s.virtualItems.value)for(const S of o.virtualItems.value){const C=f.index*u+S.index;if(C>=l.length)continue;const O=l[C];a.push({index:C,key:e.getItemKey?.(O,C)??C,item:O,row:f,column:S})}return a});function h(l,u){const a=t.toValue(e.items);if(!a.length)return;const f=Math.min(Math.max(l,0),a.length-1),S=n.value;s.scrollToIndex(Math.floor(f/S),u),o.scrollToIndex(f%S,u)}function y(l,u="auto"){l.top!==void 0&&s.scrollToOffset(l.top,u),l.left!==void 0&&o.scrollToOffset(l.left,u)}function x(l,u){const a=Math.max(r.get(l)??0,u);a<=0||a===r.get(l)||(r.set(l,a),s.measure(l,a))}let v=null;const p=new Map;function I(){return!F()||typeof ResizeObserver>"u"?null:(v||(v=new ResizeObserver(l=>{for(const u of l){const a=p.get(u.target);if(a===void 0)continue;const S=u.borderBoxSize?.[0]?.blockSize??u.contentRect.height;S>0&&x(a,S)}})),v)}function E(l,u){const a=ie(l),f=I();if(!a)return;p.set(a,u),f?.observe(a);const S=a.getBoundingClientRect().height;S>0&&x(u,S)}return t.onBeforeUnmount(()=>{v?.disconnect(),p.clear()}),{virtualRows:s.virtualItems,virtualColumns:o.virtualItems,virtualCells:d,totalHeight:s.totalSize,totalWidth:o.totalSize,scrollToIndex:h,scrollToOffset:y,measureRow:x,measureRowElement:E,measureColumn:o.measure}}function se(e){const n=H({items:e.rows,estimateSize:e.estimateRowSize,container:e.container,overscan:e.overscan,getItemKey:e.getRowKey,initialRect:e.initialRect,viewportInset:e.viewportInset,revision:e.revision,itemSize:e.itemSize}),i=t.computed(()=>{const o=t.toValue(e.columns);let d=0;return o.map(h=>{const y=h.width??h.minWidth??160,x={...h,start:d,size:y,end:d+y};return d+=y,x})}),r=t.computed(()=>{const o=i.value;return o.length?o[o.length-1]?.end??0:0});return{virtualRows:t.computed(()=>n.virtualItems.value),columns:i,totalHeight:n.totalSize,totalWidth:r,scrollOffset:n.scrollOffset,isScrolling:n.isScrolling,scrollToIndex:n.scrollToIndex,scrollToOffset:n.scrollToOffset,measure:n.measure,measureElement:n.measureElement}}function Q(e){if(typeof e=="number"&&Number.isFinite(e))return`${e}px`;if(typeof e=="string"&&e.trim())return e}function B(e){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e!="string")return 0;const n=/^(-?\d+(?:\.\d+)?)px$/.exec(e.trim());if(!n?.[1])return 0;const i=Number(n[1]);return Number.isFinite(i)?i:0}function D(e){return{overflow:"auto",position:"relative",height:Q(e.height)??(e.horizontal?"100%":void 0),width:Q(e.width)??(e.horizontal?void 0:"100%"),overflowAnchor:"none"}}function fe(e,n){return{position:"relative",width:n?`${e}px`:"100%",height:n?"100%":`${e}px`}}function me(e,n){return{position:"absolute",top:0,left:0,width:n?void 0:"100%",height:n?"100%":void 0,transform:n?`translateX(${e}px)`:`translateY(${e}px)`}}const he=t.defineComponent({__name:"VirtualList",props:{items:{},estimateSize:{type:[Number,Function],default:48},height:{},width:{},horizontal:{type:Boolean,default:!1},overscan:{default:5},gap:{default:0},paddingStart:{default:0},paddingEnd:{default:0},getItemKey:{},tag:{default:"div"},itemTag:{default:"div"},itemAttrs:{},revision:{}},setup(e,{expose:n}){const i=e,r=t.ref(null),{virtualItems:s,totalSize:o,scrollToIndex:d,scrollToOffset:h,measure:y,measureElement:x}=H({items:()=>i.items,estimateSize:(l,u)=>{const a=i.estimateSize;return typeof a=="number"?a:a(l,u)},itemSize:()=>typeof i.estimateSize=="number"?i.estimateSize:void 0,container:r,horizontal:()=>i.horizontal,overscan:()=>i.overscan,gap:()=>i.gap,paddingStart:()=>i.paddingStart,paddingEnd:()=>i.paddingEnd,getItemKey:(l,u)=>i.getItemKey?.(l,u)??u,initialRect:()=>({width:B(i.width),height:B(i.height)}),revision:()=>i.revision}),v=t.computed(()=>D({height:i.height,width:i.width,horizontal:i.horizontal})),p=t.computed(()=>fe(o.value,i.horizontal));function I(l){return me(l,i.horizontal)}function E(l){return u=>{x(u,l)}}return n({scrollToIndex:d,scrollToOffset:h,measure:y}),(l,u)=>(t.openBlock(),t.createBlock(t.resolveDynamicComponent(e.tag),{ref_key:"container",ref:r,"data-virtual-container":"",role:"list",style:t.normalizeStyle(v.value)},{default:t.withCtx(()=>[e.items.length?(t.openBlock(),t.createElementBlock("div",{key:1,"data-virtual-spacer":"",style:t.normalizeStyle(p.value)},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(t.unref(s),a=>(t.openBlock(),t.createBlock(t.resolveDynamicComponent(e.itemTag),t.mergeProps({key:a.key,ref_for:!0,ref:E(a.index),role:"listitem","data-index":a.index,"data-key":String(a.key),"aria-setsize":e.items.length,"aria-posinset":a.index+1,style:I(a.start)},{ref_for:!0},e.itemAttrs),{default:t.withCtx(()=>[t.renderSlot(l.$slots,"default",{item:a.item,index:a.index,start:a.start,size:a.size,end:a.end})]),_:2},1040,["data-index","data-key","aria-setsize","aria-posinset","style"]))),128))],4)):t.renderSlot(l.$slots,"empty",{},void 0,void 0,0)]),_:3},8,["style"]))}}),ge=["data-index","data-key"],ve=t.defineComponent({__name:"VirtualGrid",props:{items:{},columnCount:{default:1},estimateRowSize:{type:[Number,Function],default:48},estimateColumnSize:{type:[Number,Function],default:160},height:{},width:{},overscan:{default:2},overscanRows:{},overscanColumns:{},rowGap:{default:0},columnGap:{default:0},getItemKey:{},tag:{default:"div"},itemAttrs:{},revision:{}},setup(e,{expose:n}){const i=e,r=t.ref(null),{virtualCells:s,totalWidth:o,totalHeight:d,scrollToIndex:h,scrollToOffset:y,measureRow:x,measureRowElement:v}=re({items:()=>i.items,columnCount:()=>i.columnCount,estimateRowSize:()=>i.estimateRowSize,estimateColumnSize:()=>i.estimateColumnSize,container:r,overscan:()=>i.overscan,overscanRows:()=>i.overscanRows,overscanColumns:()=>i.overscanColumns,rowGap:()=>i.rowGap,columnGap:()=>i.columnGap,getItemKey:(u,a)=>i.getItemKey?.(u,a)??a,initialRect:()=>({width:B(i.width),height:B(i.height)}),revision:()=>i.revision}),p=t.computed(()=>D({height:i.height,width:i.width,horizontal:!1})),I=t.computed(()=>({position:"relative",width:`${o.value}px`,height:`${d.value}px`}));function E(u){return a=>{v(a,u)}}function l(u,a,f){return{position:"absolute",top:0,left:0,width:`${a}px`,transform:`translate(${u}px, ${f}px)`}}return n({scrollToIndex:h,scrollToOffset:y,measureRow:x}),(u,a)=>(t.openBlock(),t.createBlock(t.resolveDynamicComponent(e.tag),{ref_key:"container",ref:r,"data-virtual-container":"",role:"grid",style:t.normalizeStyle(p.value)},{default:t.withCtx(()=>[e.items.length?(t.openBlock(),t.createElementBlock("div",{key:1,"data-virtual-spacer":"",style:t.normalizeStyle(I.value)},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(t.unref(s),f=>(t.openBlock(),t.createElementBlock("div",t.mergeProps({key:f.key,ref_for:!0,ref:E(f.row.index),role:"gridcell","data-index":f.index,"data-key":String(f.key),style:l(f.column.start,f.column.size,f.row.start)},{ref_for:!0},e.itemAttrs),[t.renderSlot(u.$slots,"default",{item:f.item,index:f.index,rowIndex:f.row.index,columnIndex:f.column.index,row:f.row,column:f.column})],16,ge))),128))],4)):t.renderSlot(u.$slots,"empty",{},void 0,void 0,0)]),_:3},8,["style"]))}}),Se=["data-index","data-key","aria-rowindex"],ze=t.defineComponent({__name:"VirtualTable",props:{rows:{},columns:{},estimateRowSize:{type:[Number,Function],default:44},height:{},width:{},overscan:{default:5},getRowKey:{},stickyHeader:{type:Boolean,default:!0},tag:{default:"div"},rowAttrs:{},revision:{}},setup(e,{expose:n}){const i=e,r=t.ref(null),s=t.ref(null),o=t.ref(0),{virtualRows:d,columns:h,totalWidth:y,totalHeight:x,scrollToIndex:v,scrollToOffset:p,measure:I,measureElement:E}=se({rows:()=>i.rows,columns:()=>i.columns,estimateRowSize:(m,b)=>{const g=i.estimateRowSize;return typeof g=="number"?g:g(m,b)},container:r,overscan:()=>i.overscan,getRowKey:(m,b)=>i.getRowKey?.(m,b)??b,initialRect:()=>({width:B(i.width),height:B(i.height)}),viewportInset:o,revision:()=>i.revision,itemSize:()=>typeof i.estimateRowSize=="number"?i.estimateRowSize:void 0});t.watch(s,(m,b,g)=>{if(b===m&&!m||!m||!F()||typeof ResizeObserver>"u")return;const R=()=>{o.value=m.getBoundingClientRect().height},L=new ResizeObserver(R);L.observe(m),R(),g(()=>L.disconnect())});const l=t.computed(()=>D({height:i.height,width:i.width,horizontal:!1})),u=t.computed(()=>({minWidth:`${y.value}px`})),a=t.computed(()=>({position:i.stickyHeader?"sticky":"relative",top:i.stickyHeader?"0px":void 0,zIndex:1,display:"flex",width:`${y.value}px`})),f=t.computed(()=>({position:"relative",height:`${x.value}px`,width:`${y.value}px`}));function S(m){return{width:`${m.size}px`,minWidth:`${m.size}px`,flex:"0 0 auto",textAlign:m.align??"left"}}function C(m){return{position:"absolute",top:0,left:0,width:"100%",display:"flex",transform:`translateY(${m}px)`}}function O(m){return b=>{E(b,m)}}function $(m,b,g){return b.accessor?b.accessor(m,g):m&&typeof m=="object"&&b.id in m?m[b.id]:""}return n({scrollToIndex:v,scrollToOffset:p,measure:I}),(m,b)=>(t.openBlock(),t.createBlock(t.resolveDynamicComponent(e.tag),{ref_key:"container",ref:r,"data-virtual-container":"",role:"table",style:t.normalizeStyle(l.value)},{default:t.withCtx(()=>[t.createElementVNode("div",{style:t.normalizeStyle(u.value)},[t.createElementVNode("div",{ref_key:"header",ref:s,role:"row",style:t.normalizeStyle(a.value)},[t.renderSlot(m.$slots,"header",{columns:t.unref(h)},()=>[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(t.unref(h),g=>(t.openBlock(),t.createElementBlock("div",{key:g.id,role:"columnheader",style:t.normalizeStyle(S(g))},t.toDisplayString(g.header),5))),128))])],4),e.rows.length?(t.openBlock(),t.createElementBlock("div",{key:1,"data-virtual-spacer":"",role:"rowgroup",style:t.normalizeStyle(f.value)},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(t.unref(d),g=>(t.openBlock(),t.createElementBlock("div",t.mergeProps({key:g.key,ref_for:!0,ref:O(g.index),role:"row","data-index":g.index,"data-key":String(g.key),"aria-rowindex":g.index+1,style:C(g.start)},{ref_for:!0},e.rowAttrs),[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(t.unref(h),R=>(t.openBlock(),t.createElementBlock("div",{key:R.id,role:"cell",style:t.normalizeStyle(S(R))},[t.renderSlot(m.$slots,"cell",{row:g.item,column:R,rowIndex:g.index,value:$(g.item,R,g.index)},()=>[t.createTextVNode(t.toDisplayString($(g.item,R,g.index)),1)])],4))),128))],16,Se))),128))],4)):t.renderSlot(m.$slots,"empty",{},void 0,void 0,0)],4)]),_:3},8,["style"]))}});exports.MeasurementCache=Z;exports.VirtualGrid=ve;exports.VirtualList=he;exports.VirtualTable=ze;exports.Virtualizer=ne;exports.clampScrollOffset=G;exports.normalizeSize=K;exports.resolveScrollOffset=te;exports.useVirtualGrid=re;exports.useVirtualList=H;exports.useVirtualTable=se;exports.useVirtualizer=A;
2
+ //# sourceMappingURL=index.js.map