@pdanpdan/virtual-scroll 0.2.1 → 0.3.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/README.md +182 -88
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +100 -35
- package/dist/index.js +1 -844
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +902 -0
- package/dist/index.mjs.map +1 -0
- package/dist/virtual-scroll.css +2 -0
- package/package.json +8 -5
- package/src/components/VirtualScroll.test.ts +62 -15
- package/src/components/VirtualScroll.vue +83 -19
- package/src/composables/useVirtualScroll.test.ts +501 -68
- package/src/composables/useVirtualScroll.ts +150 -65
- package/dist/index.css +0 -2
package/README.md
CHANGED
|
@@ -57,6 +57,45 @@ import VirtualScroll from '@pdanpdan/virtual-scroll/VirtualScroll.vue';
|
|
|
57
57
|
- Enables deep integration with your project's CSS-in-JS or specialized styling solutions.
|
|
58
58
|
- Easier debugging of the component source in some IDEs.
|
|
59
59
|
|
|
60
|
+
### 3. CDN Usage
|
|
61
|
+
|
|
62
|
+
You can use the library directly from a CDN like unpkg or jsdelivr.
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<!-- Import Vue 3 first -->
|
|
66
|
+
<script src="https://unpkg.com/vue@3"></script>
|
|
67
|
+
|
|
68
|
+
<!-- Import VirtualScroll CSS -->
|
|
69
|
+
<link rel="stylesheet" href="https://unpkg.com/@pdanpdan/virtual-scroll/dist/virtual-scroll.css">
|
|
70
|
+
|
|
71
|
+
<!-- Import VirtualScroll JavaScript -->
|
|
72
|
+
<script src="https://unpkg.com/@pdanpdan/virtual-scroll"></script>
|
|
73
|
+
|
|
74
|
+
<div id="app">
|
|
75
|
+
<div style="height: 400px; overflow: auto;">
|
|
76
|
+
<virtual-scroll :items="items" :item-size="50">
|
|
77
|
+
<template #item="{ item, index }">
|
|
78
|
+
<div style="height: 50px;">{{ index }}: {{ item.label }}</div>
|
|
79
|
+
</template>
|
|
80
|
+
</virtual-scroll>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<script>
|
|
85
|
+
const { createApp, ref } = Vue;
|
|
86
|
+
const { VirtualScroll } = window.VirtualScroll;
|
|
87
|
+
|
|
88
|
+
createApp({
|
|
89
|
+
setup() {
|
|
90
|
+
const items = ref(Array.from({ length: 1000 }, (_, i) => ({ label: `Item ${i}` })));
|
|
91
|
+
return { items };
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
.component('VirtualScroll', VirtualScroll)
|
|
95
|
+
.mount('#app');
|
|
96
|
+
</script>
|
|
97
|
+
```
|
|
98
|
+
|
|
60
99
|
## Basic Usage
|
|
61
100
|
|
|
62
101
|
```vue
|
|
@@ -91,54 +130,87 @@ const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, label: `Item ${
|
|
|
91
130
|
</style>
|
|
92
131
|
```
|
|
93
132
|
|
|
94
|
-
##
|
|
133
|
+
## Sizing Guide
|
|
134
|
+
|
|
135
|
+
The component offers flexible ways to define item and column sizes. Understanding how these options interact is key to achieving smooth scrolling and correct layout.
|
|
136
|
+
|
|
137
|
+
### Sizing Options
|
|
138
|
+
|
|
139
|
+
| Option Type | `itemSize` / `columnWidth` | Performance | Description |
|
|
140
|
+
|-------------|----------------------------|-------------|-------------|
|
|
141
|
+
| **Fixed** | `number` (e.g., `50`) | **Best** | Every item has the exact same size. Calculations are *O(1)*. |
|
|
142
|
+
| **Array** | `number[]` (cols only) | **Great** | Each column has a fixed size from the array (cycles if shorter). |
|
|
143
|
+
| **Function** | `(item, index) => number` | **Good** | Size is known but varies per item. No `ResizeObserver` overhead unless it differs from measured size. |
|
|
144
|
+
| **Dynamic** | `0`, `null`, or `undefined` | **Fair** | Sizes are measured automatically via `ResizeObserver` after rendering. |
|
|
145
|
+
|
|
146
|
+
### How Sizing Works
|
|
147
|
+
|
|
148
|
+
1. **Initial Estimate**:
|
|
149
|
+
- If a **fixed size** or **function** is provided, it's used as the initial size.
|
|
150
|
+
- If **dynamic** is used, the component uses `defaultItemSize` (default: `40`) or `defaultColumnWidth` (default: `100`) as the initial estimate.
|
|
151
|
+
2. **Measurement**:
|
|
152
|
+
- When an item is rendered, its actual size is measured using `ResizeObserver`.
|
|
153
|
+
- If the measured size differs from the estimate (by more than 0.5px), the internal Fenwick Tree is updated.
|
|
154
|
+
3. **Refinement**:
|
|
155
|
+
- All subsequent item positions are automatically adjusted based on the new measurement.
|
|
156
|
+
- The total scrollable area (`totalWidth`/`totalHeight`) is updated to reflect the real content size.
|
|
157
|
+
|
|
158
|
+
### Fallback Logic
|
|
159
|
+
|
|
160
|
+
- **Unset Props**: If `itemSize` or `columnWidth` are not provided, they default to `40` and `100` respectively (fixed).
|
|
161
|
+
- **Dynamic Fallback**: When using dynamic sizing, `defaultItemSize` and `defaultColumnWidth` act as the source of truth for items that haven't been rendered yet.
|
|
162
|
+
- **Function/Array Fallback**: If a function or array returns an invalid value, it falls back to the respective `default...` prop.
|
|
163
|
+
|
|
164
|
+
### Recommendations for Smooth Scrolling
|
|
165
|
+
|
|
166
|
+
1. **Accurate Estimates**: When using dynamic sizing, set `defaultItemSize` as close as possible to the *average* height of your items. This minimizes scrollbar "jumping".
|
|
167
|
+
2. **Avoid 0 sizes**: Ensure your items have a minimum height/width (e.g., via CSS `min-height`). Items with 0 size might not be detected correctly by the virtualizer.
|
|
168
|
+
3. **Box Sizing**: Use `box-sizing: border-box` on your items to ensure padding and borders are included in the measured size.
|
|
169
|
+
4. **Manual Refresh**: If you change external state that affects a sizing function's output without changing the function reference itself, call `virtualScrollRef.refresh()` to force a full re-calculation.
|
|
170
|
+
|
|
171
|
+
## Component Reference
|
|
172
|
+
|
|
173
|
+
The `VirtualScroll` component provides a declarative interface for virtualizing lists and grids. It automatically manages the rendering lifecycle of items, measures dynamic sizes, and handles complex scroll behaviors like stickiness and restoration.
|
|
95
174
|
|
|
96
|
-
###
|
|
175
|
+
### Props
|
|
176
|
+
|
|
177
|
+
#### Core Configuration
|
|
97
178
|
| Prop | Type | Default | Description |
|
|
98
179
|
|------|------|---------|-------------|
|
|
99
180
|
| `items` | `T[]` | Required | Array of items to be virtualized. |
|
|
100
|
-
| `itemSize` | `number \| ((item: T, index: number) => number) \| null` | `
|
|
101
|
-
| `direction` | `'vertical' \| 'horizontal' \| 'both'` | `'vertical'` |
|
|
102
|
-
| `gap` | `number` | `0` |
|
|
181
|
+
| `itemSize` | `number \| ((item: T, index: number) => number) \| null` | `40` | Fixed size or function. Pass `0`/`null` for dynamic. |
|
|
182
|
+
| `direction` | `'vertical' \| 'horizontal' \| 'both'` | `'vertical'` | Scroll direction. |
|
|
183
|
+
| `gap` | `number` | `0` | Spacing between items. |
|
|
103
184
|
|
|
104
185
|
### Grid Configuration (direction="both")
|
|
105
186
|
| Prop | Type | Default | Description |
|
|
106
187
|
|------|------|---------|-------------|
|
|
107
|
-
| `columnCount` | `number` | `0` | Number of columns
|
|
108
|
-
| `columnWidth` | `
|
|
109
|
-
| `columnGap` | `number` | `0` |
|
|
188
|
+
| `columnCount` | `number` | `0` | Number of columns. |
|
|
189
|
+
| `columnWidth` | `num \| num[] \| fn \| null` | `100` | Width for columns. |
|
|
190
|
+
| `columnGap` | `number` | `0` | Spacing between columns. |
|
|
110
191
|
|
|
111
|
-
###
|
|
112
|
-
| Prop | Type | Default | Description |
|
|
113
|
-
|------|------|---------|-------------|
|
|
114
|
-
| `stickyIndices` | `number[]` | `[]` | Indices of items that should stick to the top/start. Supports iOS-style pushing effect. |
|
|
115
|
-
| `stickyHeader` | `boolean` | `false` | Whether the header slot content is sticky. If true, header size is measured and added to `scrollPaddingStart`. |
|
|
116
|
-
| `stickyFooter` | `boolean` | `false` | Whether the footer slot content is sticky. If true, footer size is measured and added to `scrollPaddingEnd`. |
|
|
117
|
-
| `loading` | `boolean` | `false` | Whether items are currently being loaded. Prevents multiple `load` events and displays the `#loading` slot. |
|
|
118
|
-
| `loadDistance` | `number` | `200` | Distance from the end of the scrollable area to trigger `load` event. |
|
|
119
|
-
| `restoreScrollOnPrepend` | `boolean` | `false` | Whether to automatically restore scroll position when items are prepended to the list. |
|
|
120
|
-
|
|
121
|
-
### Advanced Configuration
|
|
192
|
+
### Features & Behavior
|
|
122
193
|
| Prop | Type | Default | Description |
|
|
123
194
|
|------|------|---------|-------------|
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
| `initialScrollAlign` | `ScrollAlignment \| ScrollAlignmentOptions` | `'start'` | Alignment for the initial scroll index. |
|
|
135
|
-
|
|
136
|
-
### Development
|
|
195
|
+
| `stickyIndices` | `number[]` | `[]` | Indices of items that should remain sticky. |
|
|
196
|
+
| `stickyHeader` / `stickyFooter` | `boolean` | `false` | If true, measures and adds slot size to padding. |
|
|
197
|
+
| `ssrRange` | `object` | `undefined` | Items to pre-render on server. |
|
|
198
|
+
| `loading` | `boolean` | `false` | Shows loading state and prevents duplicate events. |
|
|
199
|
+
| `loadDistance` | `number` | `200` | Distance from end to trigger `load` event. |
|
|
200
|
+
| `restoreScrollOnPrepend` | `boolean` | `false` | Maintain position when items added to top. |
|
|
201
|
+
| `initialScrollIndex` | `number` | `undefined` | Index to jump to on mount. |
|
|
202
|
+
| `initialScrollAlign` | `string \| object` | `'start'` | Alignment for initial jump. |
|
|
203
|
+
|
|
204
|
+
### Advanced & Performance
|
|
137
205
|
| Prop | Type | Default | Description |
|
|
138
206
|
|------|------|---------|-------------|
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
207
|
+
| `container` | `HTMLElement \| Window` | `host element` | The scrollable container element. |
|
|
208
|
+
| `scrollPaddingStart` / `End` | `num \| {x, y}` | `0` | Padding for scroll calculations. |
|
|
209
|
+
| `containerTag` / `wrapperTag` / `itemTag` | `string` | `'div'` | HTML tags for component parts. |
|
|
210
|
+
| `bufferBefore` / `bufferAfter` | `number` | `5` | Items to render outside the viewport. |
|
|
211
|
+
| `defaultItemSize` | `number` | `40` | Initial estimate for items. |
|
|
212
|
+
| `defaultColumnWidth` | `number` | `100` | Initial estimate for columns. |
|
|
213
|
+
| `debug` | `boolean` | `false` | Enables debug visualization. |
|
|
142
214
|
|
|
143
215
|
## Slots
|
|
144
216
|
|
|
@@ -165,72 +237,71 @@ const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, label: `Item ${
|
|
|
165
237
|
## Keyboard Navigation
|
|
166
238
|
|
|
167
239
|
When the container is focused, it supports the following keys:
|
|
168
|
-
- `Home
|
|
169
|
-
- `
|
|
170
|
-
- `
|
|
240
|
+
- `Home`: Scroll to the beginning of the list (index 0).
|
|
241
|
+
- `End`: Scroll to the last item in the list.
|
|
242
|
+
- `ArrowUp` / `ArrowDown`: Scroll up/down by 40px (or `DEFAULT_ITEM_SIZE`).
|
|
243
|
+
- `ArrowLeft` / `ArrowRight`: Scroll left/right by 40px (or `DEFAULT_ITEM_SIZE`).
|
|
171
244
|
- `PageUp` / `PageDown`: Scroll up/down (or left/right) by one viewport size.
|
|
172
245
|
|
|
173
246
|
## Methods (Exposed)
|
|
174
247
|
|
|
175
248
|
- `scrollToIndex(rowIndex: number | null, colIndex: number | null, options?: ScrollAlignment | ScrollAlignmentOptions | ScrollToIndexOptions)`
|
|
176
|
-
- `rowIndex`: Row index to scroll to.
|
|
177
|
-
- `colIndex`: Column index to scroll to
|
|
249
|
+
- `rowIndex`: Row index to scroll to. Pass `null` to only scroll horizontally.
|
|
250
|
+
- `colIndex`: Column index to scroll to. Pass `null` to only scroll vertically.
|
|
178
251
|
- `options`:
|
|
179
|
-
- `align`: `'start' | 'center' | 'end' | 'auto'` or `{ x, y }
|
|
252
|
+
- `align`: `'start' | 'center' | 'end' | 'auto'` or `{ x: ScrollAlignment, y: ScrollAlignment }`.
|
|
180
253
|
- `behavior`: `'auto' | 'smooth'`.
|
|
181
254
|
- `scrollToOffset(x: number | null, y: number | null, options?: { behavior?: 'auto' | 'smooth' })`
|
|
182
|
-
- `x`: Pixel offset on X axis.
|
|
183
|
-
- `y`: Pixel offset on Y axis.
|
|
255
|
+
- `x`: Pixel offset on X axis. Pass `null` to keep current position.
|
|
256
|
+
- `y`: Pixel offset on Y axis. Pass `null` to keep current position.
|
|
257
|
+
- `options`:
|
|
258
|
+
- `behavior`: `'auto' | 'smooth'`.
|
|
184
259
|
- `refresh()`: Resets all dynamic measurements and re-initializes sizes from current items and props.
|
|
260
|
+
- `stopProgrammaticScroll()`: Immediately stops any active smooth scroll.
|
|
185
261
|
|
|
186
262
|
## Types
|
|
187
263
|
|
|
188
264
|
### ScrollDetails<T>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
currentColIndex: number;
|
|
205
|
-
scrollOffset: { x: number; y: number; };
|
|
206
|
-
viewportSize: { width: number; height: number; };
|
|
207
|
-
totalSize: { width: number; height: number; };
|
|
208
|
-
isScrolling: boolean;
|
|
209
|
-
isProgrammaticScroll: boolean;
|
|
210
|
-
range: { start: number; end: number; };
|
|
211
|
-
columnRange: { start: number; end: number; padStart: number; padEnd: number; };
|
|
212
|
-
}
|
|
213
|
-
```
|
|
265
|
+
|
|
266
|
+
The full state of the virtualizer, emitted in the `scroll` event and available via the `scrollDetails` ref.
|
|
267
|
+
|
|
268
|
+
| Property | Type | Description |
|
|
269
|
+
|----------|------|-------------|
|
|
270
|
+
| `items` | `RenderedItem<T>[]` | List of items currently rendered with their offsets and sizes. |
|
|
271
|
+
| `currentIndex` | `number` | Index of the first item partially or fully visible in the viewport. |
|
|
272
|
+
| `currentColIndex` | `number` | Index of the first column partially or fully visible. |
|
|
273
|
+
| `scrollOffset` | `{ x: number, y: number }` | Current scroll position relative to content start. |
|
|
274
|
+
| `viewportSize` | `{ width: number, height: number }` | Dimensions of the visible area. |
|
|
275
|
+
| `totalSize` | `{ width: number, height: number }` | Total calculated size of all items and gaps. |
|
|
276
|
+
| `isScrolling` | `boolean` | Whether the container is currently being scrolled. |
|
|
277
|
+
| `isProgrammaticScroll` | `boolean` | Whether the current scroll was initiated by a method call. |
|
|
278
|
+
| `range` | `{ start: number, end: number }` | Current rendered item indices. |
|
|
279
|
+
| `columnRange` | `{ start: number, end: number, padStart: number, padEnd: number }` | Visible column range and paddings. |
|
|
214
280
|
|
|
215
281
|
### RenderedItem<T>
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
282
|
+
|
|
283
|
+
| Property | Type | Description |
|
|
284
|
+
|----------|------|-------------|
|
|
285
|
+
| `item` | `T` | The data item. |
|
|
286
|
+
| `index` | `number` | The item's index in the original array. |
|
|
287
|
+
| `offset` | `{ x: number, y: number }` | Calculated position for rendering. |
|
|
288
|
+
| `size` | `{ width: number, height: number }` | Measured or estimated size. |
|
|
289
|
+
| `originalX` / `originalY` | `number` | Raw offsets before sticky adjustments. |
|
|
290
|
+
| `isSticky` | `boolean` | Whether the item is configured to be sticky. |
|
|
291
|
+
| `isStickyActive` | `boolean` | Whether the item is currently stuck. |
|
|
292
|
+
| `stickyOffset` | `{ x: number, y: number }` | Offset applied for the pushing effect. |
|
|
293
|
+
|
|
294
|
+
### ScrollAlignment
|
|
295
|
+
|
|
296
|
+
- `'start'`: Aligns the item to the top/left of the viewport.
|
|
297
|
+
- `'center'`: Aligns the item to the center of the viewport.
|
|
298
|
+
- `'end'`: Aligns the item to the bottom/right of the viewport.
|
|
299
|
+
- `'auto'`: Smart alignment - if the item is already visible, do nothing; if it's above/left, align to `start`; if it's below/right, align to `end`.
|
|
230
300
|
|
|
231
301
|
## CSS Classes
|
|
232
302
|
|
|
233
303
|
- `.virtual-scroll-container`: Root container.
|
|
304
|
+
- `.virtual-scroll--vertical`, `.virtual-scroll--horizontal`, `.virtual-scroll--both`: Direction modifier.
|
|
234
305
|
- `.virtual-scroll-wrapper`: Items wrapper.
|
|
235
306
|
- `.virtual-scroll-item`: Individual item.
|
|
236
307
|
- `.virtual-scroll-header` / `.virtual-scroll-footer`: Header/Footer slots.
|
|
@@ -239,6 +310,7 @@ interface RenderedItem<T = unknown> {
|
|
|
239
310
|
- `.virtual-scroll--hydrated`: Applied when client-side mount is complete.
|
|
240
311
|
- `.virtual-scroll--window`: Applied when using window/body scroll.
|
|
241
312
|
- `.virtual-scroll--table`: Applied when `containerTag="table"` is used.
|
|
313
|
+
- `.virtual-scroll--debug`: Applied when debug mode is enabled.
|
|
242
314
|
|
|
243
315
|
## SSR Support
|
|
244
316
|
|
|
@@ -264,28 +336,50 @@ When `ssrRange` is provided:
|
|
|
264
336
|
|
|
265
337
|
For advanced use cases, you can use the underlying logic via the `useVirtualScroll` composable.
|
|
266
338
|
|
|
339
|
+
### Example
|
|
340
|
+
|
|
267
341
|
```typescript
|
|
342
|
+
/* eslint-disable unused-imports/no-unused-vars */
|
|
268
343
|
import { useVirtualScroll } from '@pdanpdan/virtual-scroll';
|
|
269
344
|
import { computed, ref } from 'vue';
|
|
270
345
|
|
|
271
346
|
const items = ref([ { id: 1 }, { id: 2 } ]);
|
|
347
|
+
const containerRef = ref<HTMLElement | null>(null);
|
|
348
|
+
|
|
272
349
|
const props = computed(() => ({
|
|
273
350
|
items: items.value,
|
|
274
351
|
itemSize: 50,
|
|
352
|
+
container: containerRef.value,
|
|
275
353
|
direction: 'vertical' as const,
|
|
276
354
|
}));
|
|
277
355
|
|
|
278
|
-
const { renderedItems, scrollDetails } = useVirtualScroll(props);
|
|
279
|
-
console.log(renderedItems.value, scrollDetails.value);
|
|
356
|
+
const { renderedItems, scrollDetails, totalHeight } = useVirtualScroll(props);
|
|
280
357
|
```
|
|
281
358
|
|
|
359
|
+
### Return Values
|
|
360
|
+
|
|
361
|
+
| Member | Type | Description |
|
|
362
|
+
|--------|------|-------------|
|
|
363
|
+
| `renderedItems` | `Ref<RenderedItem<T>[]>` | List of items to be rendered. |
|
|
364
|
+
| `scrollDetails` | `Ref<ScrollDetails<T>>` | Full state of the virtualizer. |
|
|
365
|
+
| `totalWidth` / `totalHeight` | `Ref<number>` | Calculated total dimensions. |
|
|
366
|
+
| `columnRange` | `Ref<object>` | Visible column range. |
|
|
367
|
+
| `isHydrated` | `Ref<boolean>` | Whether hydration is complete. |
|
|
368
|
+
| `scrollToIndex` | `Function` | Programmatic scroll to index. |
|
|
369
|
+
| `scrollToOffset` | `Function` | Programmatic scroll to offset. |
|
|
370
|
+
| `refresh` | `Function` | Resets and recalculates all sizes. |
|
|
371
|
+
| `updateItemSize` | `Function` | Manually update an item's size. |
|
|
372
|
+
|
|
282
373
|
## Utilities
|
|
283
374
|
|
|
284
|
-
The library exports several utility functions
|
|
375
|
+
The library exports several utility functions and classes:
|
|
285
376
|
|
|
286
|
-
- `isElement(
|
|
287
|
-
- `isScrollableElement(
|
|
288
|
-
- `isScrollToIndexOptions(
|
|
377
|
+
- `isElement(val: any): val is HTMLElement`: Checks if value is an `HTMLElement` (excludes `window`).
|
|
378
|
+
- `isScrollableElement(val: any): val is HTMLElement | Window`: Checks if value has scroll properties.
|
|
379
|
+
- `isScrollToIndexOptions(val: any): val is ScrollToIndexOptions`: Type guard for scroll options.
|
|
380
|
+
- `getPaddingX / getPaddingY`: Internal helpers for extraction of padding from props.
|
|
381
|
+
- `FenwickTree`: The underlying data structure for efficient size and offset management.
|
|
382
|
+
- `DEFAULT_ITEM_SIZE / DEFAULT_COLUMN_WIDTH / DEFAULT_BUFFER`: The default values used by the library.
|
|
289
383
|
|
|
290
384
|
## License
|
|
291
385
|
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vue`);var t=class{tree;values;constructor(e){this.tree=new Float64Array(e+1),this.values=new Float64Array(e)}update(e,t){if(!(e<0||e>=this.values.length))for(this.values[e]=this.values[e]+t,e++;e<this.tree.length;)this.tree[e]=this.tree[e]+t,e+=e&-e}query(e){let t=0;for(;e>0;)t+=this.tree[e]||0,e-=e&-e;return t}set(e,t){e<0||e>=this.values.length||(this.values[e]=t)}get length(){return this.values.length}get(e){return this.values[e]||0}getValues(){return this.values}findLowerBound(e){let t=0,n=this.tree.length,r=1<<Math.floor(Math.log2(n-1));for(;r>0;){let i=t+r;if(i<n){let n=this.tree[i]||0;n<=e&&(t=i,e-=n)}r>>=1}return t}rebuild(){this.tree.fill(0);for(let e=0;e<this.values.length;e++)this.tree[e+1]=this.values[e]||0;for(let e=1;e<this.tree.length;e++){let t=e+(e&-e);t<this.tree.length&&(this.tree[t]=this.tree[t]+this.tree[e])}}resize(e){if(e===this.values.length)return;let t=new Float64Array(e);t.set(this.values.subarray(0,Math.min(e,this.values.length))),this.values=t,this.tree=new Float64Array(e+1),this.rebuild()}shift(e){if(e===0)return;let t=this.values.length,n=new Float64Array(t);e>0?n.set(this.values.subarray(0,Math.min(t-e,this.values.length)),e):n.set(this.values.subarray(-e)),this.values=n,this.rebuild()}};function n(e){return!!e&&`getBoundingClientRect`in e}function r(e){return!!e&&`scrollLeft`in e}function i(e){return typeof e==`object`&&!!e&&(`align`in e||`behavior`in e||`isCorrection`in e)}function a(e,t){return typeof e==`object`&&e?e.x||0:t===`horizontal`&&e||0}function o(e,t){return typeof e==`object`&&e?e.y||0:(t===`vertical`||t===`both`)&&e||0}const s=40,c=100,l=5;function u(s){let c=(0,e.ref)(0),l=(0,e.ref)(0),u=(0,e.ref)(!1),d=(0,e.ref)(!1),f=(0,e.ref)(!1),p=(0,e.ref)(!1),m=(0,e.ref)(0),h=(0,e.ref)(0),g=(0,e.reactive)({x:0,y:0}),_,v=(0,e.ref)(!1),y=new t(s.value.items.length),b=new t(s.value.items.length),x=new t(s.value.columnCount||0),S=(0,e.ref)(0),C=new Uint8Array,w=new Uint8Array,T=new Uint8Array,E=(0,e.ref)(null),D=(0,e.ref)(!1),O=[],k=(0,e.computed)(()=>s.value.itemSize===void 0||s.value.itemSize===null||s.value.itemSize===0),A=(0,e.computed)(()=>s.value.columnWidth===void 0||s.value.columnWidth===null||s.value.columnWidth===0),j=(0,e.computed)(()=>typeof s.value.itemSize==`number`&&s.value.itemSize>0?s.value.itemSize:null),M=(0,e.computed)(()=>s.value.defaultItemSize||j.value||40),N=(0,e.computed)(()=>[...s.value.stickyIndices||[]].sort((e,t)=>e-t)),P=(0,e.computed)(()=>{if(S.value,!d.value&&s.value.ssrRange&&!p.value){let{start:e=0,end:t=0,colStart:n=0,colEnd:r=0}=s.value.ssrRange,i=s.value.columnCount||0;if(s.value.direction===`both`){if(i<=0)return 0;let e=r||i,t=x.query(e)-x.query(n);return Math.max(0,t-(e>n&&s.value.columnGap||0))}if(s.value.direction===`horizontal`){if(j.value!==null){let n=t-e;return Math.max(0,n*(j.value+(s.value.columnGap||0))-(n>0&&s.value.columnGap||0))}let n=y.query(t)-y.query(e);return Math.max(0,n-(t>e&&s.value.columnGap||0))}}if(s.value.direction===`both`){let e=s.value.columnCount||0;if(e<=0)return 0;let t=x.query(e);return Math.max(0,t-(s.value.columnGap||0))}if(s.value.direction===`vertical`)return 0;if(j.value!==null){let e=s.value.items.length;return Math.max(0,e*(j.value+(s.value.columnGap||0))-(e>0&&s.value.columnGap||0))}let e=y.query(s.value.items.length);return Math.max(0,e-(s.value.items.length>0&&s.value.columnGap||0))}),F=(0,e.computed)(()=>{if(S.value,!d.value&&s.value.ssrRange&&!p.value){let{start:e,end:t}=s.value.ssrRange;if(s.value.direction===`vertical`||s.value.direction===`both`){if(j.value!==null){let n=t-e;return Math.max(0,n*(j.value+(s.value.gap||0))-(n>0&&s.value.gap||0))}let n=b.query(t)-b.query(e);return Math.max(0,n-(t>e&&s.value.gap||0))}}if(s.value.direction===`horizontal`)return 0;if(j.value!==null){let e=s.value.items.length;return Math.max(0,e*(j.value+(s.value.gap||0))-(e>0&&s.value.gap||0))}let e=b.query(s.value.items.length);return Math.max(0,e-(s.value.items.length>0&&s.value.gap||0))}),I=(0,e.computed)(()=>{let e=s.value.direction===`horizontal`||s.value.direction===`both`?a(s.value.scrollPaddingStart,s.value.direction):0;return Math.max(0,c.value+e-g.x)}),L=(0,e.computed)(()=>{let e=s.value.direction===`vertical`||s.value.direction===`both`?o(s.value.scrollPaddingStart,s.value.direction):0;return Math.max(0,l.value+e-g.y)}),R=e=>{S.value;let t=s.value.columnWidth;if(typeof t==`number`&&t>0)return t;if(Array.isArray(t)&&t.length>0){let n=t[e%t.length];return n!=null&&n>0?n:s.value.defaultColumnWidth||100}return typeof t==`function`?t(e):x.get(e)||s.value.defaultColumnWidth||100},z=(e,t,d)=>{let f=typeof d==`object`&&d&&`isCorrection`in d?d.isCorrection:!1;f||(E.value={rowIndex:e,colIndex:t,options:d});let p=s.value.container||window,_=j.value,S=s.value.gap||0,C=s.value.columnGap||0,w,T;i(d)?(w=d.align,T=d.behavior):w=d;let D=(typeof w==`object`?w.x:w)||`auto`,O=(typeof w==`object`?w.y:w)||`auto`,k=a(s.value.scrollPaddingStart,s.value.direction),A=a(s.value.scrollPaddingEnd,s.value.direction),M=o(s.value.scrollPaddingStart,s.value.direction),N=o(s.value.scrollPaddingEnd,s.value.direction),R=s.value.direction===`vertical`||s.value.direction===`both`,z=s.value.direction===`horizontal`||s.value.direction===`both`,B=m.value-(z?k+A:0),V=h.value-(R?M+N:0),H=I.value,U=L.value,W=0,G=0;if(e!=null&&(e>=s.value.items.length?(U=F.value,G=0):(U=_===null?b.query(e):e*(_+S),G=_===null?b.get(e)-S:_),O===`start`||(O===`center`?U-=(V-G)/2:O===`end`?U-=V-G:U>=L.value&&U+G<=L.value+V||U<L.value||(U-=V-G))),t!=null){let e=s.value.columnCount||0;t>=e&&e>0?(H=P.value,W=0):s.value.direction===`horizontal`?(H=_===null?y.query(t):t*(_+C),W=_===null?y.get(t)-C:_):(H=x.query(t),W=x.get(t)-C),D===`start`||(D===`center`?H-=(B-W)/2:D===`end`?H-=B-W:H>=I.value&&H+W<=I.value+B||H<I.value||(H-=B-W))}H=Math.max(0,Math.min(H,Math.max(0,P.value-B))),U=Math.max(0,Math.min(U,Math.max(0,F.value-V)));let K=H+g.x-(z?k:0),q=U+g.y-(R?M:0),J=t==null||Math.abs(I.value-H)<1,Y=e==null||Math.abs(L.value-U)<1;if(!J||!Y){let r=0,i=0,a=0,o=0,s=0,c=0;if(typeof window<`u`){if(p===window?(r=window.scrollX,i=window.scrollY,a=document.documentElement.scrollWidth,o=document.documentElement.scrollHeight,s=window.innerWidth,c=window.innerHeight):n(p)&&(r=p.scrollLeft,i=p.scrollTop,a=p.scrollWidth,o=p.scrollHeight,s=p.clientWidth,c=p.clientHeight),!J&&t!=null){let e=r<=1&&K<=1,t=r>=a-s-1&&K>=a-s-1;(e||t)&&(J=!0)}if(!Y&&e!=null){let e=i<=1&&q<=1,t=i>=o-c-1&&q>=o-c-1;(e||t)&&(Y=!0)}}}let X=f?`auto`:T||`smooth`;if(v.value=!0,typeof window<`u`&&p===window)window.scrollTo({left:t==null?void 0:Math.max(0,K),top:e==null?void 0:Math.max(0,q),behavior:X});else if(r(p)){let n={behavior:X};t!=null&&(n.left=Math.max(0,K)),e!=null&&(n.top=Math.max(0,q)),typeof p.scrollTo==`function`?p.scrollTo(n):(n.left!==void 0&&(p.scrollLeft=n.left),n.top!==void 0&&(p.scrollTop=n.top))}(X===`auto`||X===void 0)&&(t!=null&&(c.value=Math.max(0,K)),e!=null&&(l.value=Math.max(0,q))),J&&Y&&!u.value&&(E.value=null)},B=(e,t,n)=>{let i=s.value.container||window;v.value=!0;let u=s.value.direction===`vertical`||s.value.direction===`both`,d=s.value.direction===`horizontal`||s.value.direction===`both`,f=a(s.value.scrollPaddingStart,s.value.direction),p=o(s.value.scrollPaddingStart,s.value.direction),_=a(s.value.scrollPaddingEnd,s.value.direction),y=o(s.value.scrollPaddingEnd,s.value.direction),b=m.value-(d?f+_:0),x=h.value-(u?p+y:0),S=e==null?null:d?Math.max(0,Math.min(e,Math.max(0,P.value-b))):Math.max(0,e),C=t==null?null:u?Math.max(0,Math.min(t,Math.max(0,F.value-x))):Math.max(0,t),w=typeof window<`u`&&i===window?window.scrollX:i.scrollLeft,T=typeof window<`u`&&i===window?window.scrollY:i.scrollTop,E=S===null?w:S+g.x-(d?f:0),D=C===null?T:C+g.y-(u?p:0);if(typeof window<`u`&&i===window)window.scrollTo({left:e==null?void 0:E,top:t==null?void 0:D,behavior:n?.behavior||`auto`});else if(r(i)){let r={behavior:n?.behavior||`auto`};e!=null&&(r.left=E),t!=null&&(r.top=D),typeof i.scrollTo==`function`?i.scrollTo(r):(r.left!==void 0&&(i.scrollLeft=r.left),r.top!==void 0&&(i.scrollTop=r.top))}(n?.behavior===`auto`||n?.behavior===void 0)&&(e!=null&&(c.value=E),t!=null&&(l.value=D))},V=()=>{let t=s.value.items,n=t.length,r=s.value.columnCount||0;if(y.resize(n),b.resize(n),x.resize(r),w.length!==n){let e=new Uint8Array(n);e.set(w.subarray(0,Math.min(n,w.length))),w=e}if(T.length!==n){let e=new Uint8Array(n);e.set(T.subarray(0,Math.min(n,T.length))),T=e}if(C.length!==r){let e=new Uint8Array(r);e.set(C.subarray(0,Math.min(r,C.length))),C=e}let i=0;if(s.value.restoreScrollOnPrepend&&O.length>0&&n>O.length){let e=O[0];if(e!==void 0){for(let r=1;r<=n-O.length;r++)if(t[r]===e){i=r;break}}}if(i>0){y.shift(i),b.shift(i),E.value&&E.value.rowIndex!==null&&E.value.rowIndex!==void 0&&(E.value.rowIndex+=i);let r=new Uint8Array(n),a=new Uint8Array(n);r.set(w.subarray(0,Math.min(n-i,w.length)),i),a.set(T.subarray(0,Math.min(n-i,T.length)),i),w=r,T=a;let o=s.value.gap||0,c=s.value.columnGap||0,l=0,u=0;for(let e=0;e<i;e++){let n=typeof s.value.itemSize==`function`?s.value.itemSize(t[e],e):M.value;s.value.direction===`horizontal`?l+=n+c:u+=n+o}(l>0||u>0)&&(0,e.nextTick)(()=>{B(l>0?I.value+l:null,u>0?L.value+u:null,{behavior:`auto`})})}if(r>0){let e=s.value.columnGap||0,t=!1;for(let n=0;n<r;n++){let r=R(n),i=x.get(n),a=C[n]===1;if(!A.value||!a||i===0){let a=r+e;Math.abs(i-a)>.5?(x.set(n,a),C[n]=A.value?0:1,t=!0):A.value||(C[n]=1)}}t&&x.rebuild()}let a=s.value.gap||0,o=s.value.columnGap||0,c=!1;for(let e=0;e<n;e++){let t=s.value.items[e],n=y.get(e),r=b.get(e),i=typeof s.value.itemSize==`function`?s.value.itemSize(t,e):M.value,l=s.value.direction===`vertical`,u=s.value.direction===`horizontal`,d=s.value.direction===`both`,f=u?i+o:0,p=l||d?i+a:0,m=w[e]===1,h=T[e]===1;u?(!k.value||!m||n===0)&&(Math.abs(n-f)>.5?(y.set(e,f),w[e]=k.value?0:1,c=!0):k.value||(w[e]=1)):n!==0&&(y.set(e,0),w[e]=0,c=!0),l||d?(!k.value||!h||r===0)&&(Math.abs(r-p)>.5?(b.set(e,p),T[e]=k.value?0:1,c=!0):k.value||(T[e]=1)):r!==0&&(b.set(e,0),T[e]=0,c=!0)}c&&(y.rebuild(),b.rebuild()),O=[...t],D.value=!0,S.value++},H=()=>{if(s.value.hostElement&&typeof window<`u`){let e=s.value.hostElement.getBoundingClientRect(),t=s.value.container||window,r=0,i=0;if(t===window)r=e.left+window.scrollX,i=e.top+window.scrollY;else if(t===s.value.hostElement)r=0,i=0;else if(n(t)){let n=t.getBoundingClientRect();r=e.left-n.left+t.scrollLeft,i=e.top-n.top+t.scrollTop}(Math.abs(g.x-r)>.1||Math.abs(g.y-i)>.1)&&(g.x=r,g.y=i)}};(0,e.watch)([()=>s.value.items,()=>s.value.direction,()=>s.value.columnCount,()=>s.value.columnWidth,()=>s.value.itemSize,()=>s.value.gap,()=>s.value.columnGap,()=>s.value.defaultItemSize,()=>s.value.defaultColumnWidth],V,{immediate:!0}),(0,e.watch)(()=>[s.value.container,s.value.hostElement],()=>{H()});let U=(0,e.computed)(()=>{if(S.value,(!d.value||f.value)&&s.value.ssrRange)return{start:s.value.ssrRange.start,end:s.value.ssrRange.end};let e=s.value.direction||`vertical`,t=s.value.ssrRange&&!u.value?0:s.value.bufferBefore??5,n=s.value.bufferAfter??5,r=s.value.gap||0,i=s.value.columnGap||0,c=j.value,l=a(s.value.scrollPaddingStart,e),p=a(s.value.scrollPaddingEnd,e),g=o(s.value.scrollPaddingStart,e),_=o(s.value.scrollPaddingEnd,e),v=e===`vertical`||e===`both`,x=e===`horizontal`||e===`both`,C=m.value-(x?l+p:0),w=h.value-(v?g+_:0),T=0,E=s.value.items.length;if(v)if(c!==null)T=Math.floor(L.value/(c+r)),E=Math.ceil((L.value+w)/(c+r));else{T=b.findLowerBound(L.value);let e=b.query(T),t=T;for(;t<s.value.items.length&&e<L.value+w;)e=b.query(++t);E=t}else if(c!==null)T=Math.floor(I.value/(c+i)),E=Math.ceil((I.value+C)/(c+i));else{T=y.findLowerBound(I.value);let e=y.query(T),t=T;for(;t<s.value.items.length&&e<I.value+C;)e=y.query(++t);E=t}return{start:Math.max(0,T-t),end:Math.min(s.value.items.length,E+n)}}),W=(0,e.computed)(()=>{S.value;let e=j.value,t=s.value.gap||0,n=s.value.columnGap||0;return s.value.direction===`horizontal`?e===null?y.findLowerBound(I.value):Math.floor(I.value/(e+n)):e===null?b.findLowerBound(L.value):Math.floor(L.value/(e+t))}),G=(0,e.computed)(()=>{S.value;let{start:e,end:t}=U.value,n=[],r=j.value,i=s.value.gap||0,a=s.value.columnGap||0,o=N.value,c=new Set;for(let n=e;n<t;n++)c.add(n);if(d.value||!s.value.ssrRange){let n=W.value,r,i=0,a=o.length-1;for(;i<=a;){let e=i+a>>>1;o[e]<n?(r=o[e],i=e+1):a=e-1}r!==void 0&&c.add(r);for(let n of o)n>=e&&n<t&&c.add(n)}let l=Array.from(c).sort((e,t)=>e-t),u=s.value.ssrRange?.start||0,f=s.value.ssrRange?.colStart||0,p=0,g=0;!d.value&&s.value.ssrRange&&(g=s.value.direction===`vertical`||s.value.direction===`both`?r===null?b.query(u):u*(r+i):0,s.value.direction===`horizontal`?p=r===null?y.query(f):f*(r+a):s.value.direction===`both`&&(p=x.query(f)));for(let e of l){let t=s.value.items[e];if(t===void 0)continue;let c=0,l=0,u=0,d=0;s.value.direction===`horizontal`?(c=r===null?y.query(e):e*(r+a),u=r===null?y.get(e)-a:r,d=h.value):(l=(s.value.direction===`vertical`||s.value.direction===`both`)&&r!==null?e*(r+i):b.query(e),d=r===null?b.get(e)-i:r,u=s.value.direction===`both`?P.value:m.value);let f=o.includes(e),_=c,v=l,x=!1,S={x:0,y:0};if(f){if(s.value.direction===`vertical`||s.value.direction===`both`){if(L.value>v){x=!0;let t,n=0,a=o.length-1;for(;n<=a;){let r=n+a>>>1;o[r]>e?(t=o[r],a=r-1):n=r+1}if(t!==void 0){let e=(r===null?b.query(t):t*(r+i))-L.value;e<d&&(S.y=-(d-e))}}}else if(s.value.direction===`horizontal`&&I.value>_){x=!0;let t,n=0,i=o.length-1;for(;n<=i;){let r=n+i>>>1;o[r]>e?(t=o[r],i=r-1):n=r+1}if(t!==void 0){let e=(r===null?y.query(t):t*(r+a))-I.value;e<u&&(S.x=-(u-e))}}}n.push({item:t,index:e,offset:{x:_-p,y:v-g},size:{width:u,height:d},originalX:_,originalY:v,isSticky:f,isStickyActive:x,stickyOffset:S})}return n}),K=(0,e.computed)(()=>{S.value;let e=s.value.columnCount||0;if(!e)return{start:0,end:0,padStart:0,padEnd:0};if((!d.value||f.value)&&s.value.ssrRange){let{colStart:t=0,colEnd:n=0}=s.value.ssrRange;return{start:Math.max(0,t),end:Math.min(e,n||e),padStart:0,padEnd:0}}let t=x.findLowerBound(I.value),n=x.query(t),r=t;for(;r<e&&n<I.value+m.value;)n=x.query(++r);let i=s.value.ssrRange&&!u.value?0:2,a=Math.max(0,t-i),o=Math.min(e,r+i);return{start:a,end:o,padStart:x.query(a),padEnd:x.query(e)-x.query(o)}}),q=(0,e.computed)(()=>{S.value;let e=j.value,t=s.value.columnGap||0,n=0;return(s.value.direction===`horizontal`||s.value.direction===`both`)&&(n=e===null?y.findLowerBound(I.value):Math.floor(I.value/(e+t))),{items:G.value,currentIndex:W.value,currentColIndex:n,scrollOffset:{x:I.value,y:L.value},viewportSize:{width:m.value,height:h.value},totalSize:{width:P.value,height:F.value},isScrolling:u.value,isProgrammaticScroll:v.value,range:U.value,columnRange:K.value}}),J=()=>{v.value=!1,E.value=null},Y=e=>{let t=e.target;typeof window>`u`||(t===window||t===document?(c.value=window.scrollX,l.value=window.scrollY):r(t)&&(c.value=t.scrollLeft,l.value=t.scrollTop),u.value||=(v.value||(E.value=null),!0),clearTimeout(_),_=setTimeout(()=>{u.value=!1,v.value=!1},250))},X=e=>{let t=!1,n=s.value.gap||0,r=s.value.columnGap||0;for(let{index:i,inlineSize:a,blockSize:o,element:c}of e){if((k.value||typeof s.value.itemSize==`function`)&&i>=0){if(s.value.direction===`horizontal`){let e=y.get(i),n=a+r;(!w[i]||Math.abs(n-e)>.5)&&(y.update(i,n-e),w[i]=1,t=!0)}if(s.value.direction===`vertical`||s.value.direction===`both`){let e=b.get(i),r=o+n;s.value.direction,(!T[i]||Math.abs(r-e)>.5)&&(b.update(i,r-e),T[i]=1,t=!0)}}let e=A.value||typeof s.value.columnWidth==`function`;if(s.value.direction===`both`&&c&&s.value.columnCount&&e){let e=c.dataset.colIndex===void 0?Array.from(c.querySelectorAll(`[data-col-index]`)):[c];for(let n of e){let e=Number.parseInt(n.dataset.colIndex,10);if(e>=0&&e<(s.value.columnCount||0)){let i=n.offsetWidth,a=x.get(e),o=i+r;Math.abs(a-o)>.5&&(x.update(e,o-a),C[e]=1,t=!0)}}}}t&&S.value++},ee=(e,t,n,r)=>{X([{index:e,inlineSize:t,blockSize:n,element:r}])},Z=()=>{if(E.value&&!f.value){let{rowIndex:e,colIndex:t,options:n}=E.value;z(e,t,i(n)?{...n,isCorrection:!0}:{align:n,isCorrection:!0})}};(0,e.watch)(S,Z),(0,e.watch)(u,e=>{e||Z()});let Q=null,te=e=>{if(!e||typeof window>`u`)return;let t=e===window?document:e;if(t.addEventListener(`scroll`,Y,{passive:!0}),e===window){m.value=window.innerWidth,h.value=window.innerHeight,c.value=window.scrollX,l.value=window.scrollY;let e=()=>{m.value=window.innerWidth,h.value=window.innerHeight,H()};return window.addEventListener(`resize`,e),()=>{t.removeEventListener(`scroll`,Y),window.removeEventListener(`resize`,e)}}else return m.value=e.clientWidth,h.value=e.clientHeight,c.value=e.scrollLeft,l.value=e.scrollTop,Q=new ResizeObserver(t=>{for(let n of t)n.target===e&&(m.value=e.clientWidth,h.value=e.clientHeight,H())}),Q.observe(e),()=>{t.removeEventListener(`scroll`,Y),Q?.disconnect()}},$;return(0,e.getCurrentInstance)()&&((0,e.onMounted)(()=>{p.value=!0,(0,e.watch)(()=>s.value.container,e=>{$?.(),$=te(e||null)},{immediate:!0}),H(),s.value.ssrRange||s.value.initialScrollIndex!==void 0?(0,e.nextTick)(()=>{H();let t=s.value.initialScrollIndex===void 0?s.value.ssrRange?.start:s.value.initialScrollIndex,n=s.value.initialScrollAlign||`start`;t!=null&&z(t,s.value.ssrRange?.colStart,{align:n,behavior:`auto`}),d.value=!0,f.value=!0,(0,e.nextTick)(()=>{f.value=!1})}):d.value=!0}),(0,e.onUnmounted)(()=>{$?.()})),{renderedItems:G,totalWidth:P,totalHeight:F,scrollDetails:q,scrollToIndex:z,scrollToOffset:B,stopProgrammaticScroll:J,updateItemSize:ee,updateItemSizes:X,updateHostOffset:H,columnRange:K,getColumnWidth:R,refresh:()=>{y.resize(0),b.resize(0),x.resize(0),C.fill(0),w.fill(0),T.fill(0),V()},isHydrated:d}}var d={key:0,class:`virtual-scroll-debug-info`},f=(0,e.defineComponent)({__name:`VirtualScroll`,props:{items:{},itemSize:{},direction:{default:`vertical`},bufferBefore:{default:5},bufferAfter:{default:5},container:{},ssrRange:{},columnCount:{default:0},columnWidth:{},containerTag:{default:`div`},wrapperTag:{default:`div`},itemTag:{default:`div`},scrollPaddingStart:{default:0},scrollPaddingEnd:{default:0},stickyHeader:{type:Boolean,default:!1},stickyFooter:{type:Boolean,default:!1},gap:{default:0},columnGap:{default:0},stickyIndices:{default:()=>[]},loadDistance:{default:200},loading:{type:Boolean,default:!1},restoreScrollOnPrepend:{type:Boolean,default:!1},initialScrollIndex:{},initialScrollAlign:{},defaultItemSize:{},defaultColumnWidth:{},debug:{type:Boolean,default:!1}},emits:[`scroll`,`load`,`visibleRangeChange`],setup(t,{expose:n,emit:r}){let i=t,s=r,c=(0,e.useSlots)(),l=(0,e.ref)(null),f=(0,e.ref)(null),p=(0,e.ref)(null),m=(0,e.ref)(null),h=new Map,g=(0,e.ref)(0),_=(0,e.ref)(0),v=(0,e.computed)(()=>{let e=i.container===void 0?l.value:i.container;return e===l.value||typeof window<`u`&&(e===window||e===null)}),{isHydrated:y,columnRange:b,renderedItems:x,scrollDetails:S,totalHeight:C,totalWidth:w,getColumnWidth:T,scrollToIndex:E,scrollToOffset:D,updateHostOffset:O,updateItemSizes:k,refresh:A,stopProgrammaticScroll:j}=u((0,e.computed)(()=>{let e=i.scrollPaddingStart,t=i.scrollPaddingEnd,n=typeof e==`object`?e.x||0:i.direction===`horizontal`&&e||0,r=typeof e==`object`?e.y||0:i.direction===`horizontal`?0:e||0,a=typeof t==`object`?t.x||0:i.direction===`horizontal`&&t||0,o=typeof t==`object`?t.y||0:i.direction===`horizontal`?0:t||0;return{items:i.items,itemSize:i.itemSize,direction:i.direction,bufferBefore:i.bufferBefore,bufferAfter:i.bufferAfter,container:i.container===void 0?l.value:i.container,hostElement:f.value,ssrRange:i.ssrRange,columnCount:i.columnCount,columnWidth:i.columnWidth,scrollPaddingStart:{x:n,y:r+(i.stickyHeader&&v.value?g.value:0)},scrollPaddingEnd:{x:a,y:o+(i.stickyFooter&&v.value?_.value:0)},gap:i.gap,columnGap:i.columnGap,stickyIndices:i.stickyIndices,loadDistance:i.loadDistance,loading:i.loading,restoreScrollOnPrepend:i.restoreScrollOnPrepend,initialScrollIndex:i.initialScrollIndex,initialScrollAlign:i.initialScrollAlign,defaultItemSize:i.defaultItemSize,defaultColumnWidth:i.defaultColumnWidth,debug:i.debug}}));function M(){A(),(0,e.nextTick)(()=>{let e=[];for(let[t,n]of h.entries())n&&e.push({index:t,inlineSize:n.offsetWidth,blockSize:n.offsetHeight,element:n});e.length>0&&k(e)})}(0,e.watch)(S,(e,t)=>{y.value&&(s(`scroll`,e),(!t||e.range.start!==t.range.start||e.range.end!==t.range.end||e.columnRange.start!==t.columnRange.start||e.columnRange.end!==t.columnRange.end)&&s(`visibleRangeChange`,{start:e.range.start,end:e.range.end,colStart:e.columnRange.start,colEnd:e.columnRange.end}),!i.loading&&(i.direction!==`horizontal`&&e.totalSize.height-(e.scrollOffset.y+e.viewportSize.height)<=i.loadDistance&&s(`load`,`vertical`),i.direction!==`vertical`&&e.totalSize.width-(e.scrollOffset.x+e.viewportSize.width)<=i.loadDistance&&s(`load`,`horizontal`)))}),(0,e.watch)(y,e=>{e&&s(`visibleRangeChange`,{start:S.value.range.start,end:S.value.range.end,colStart:S.value.columnRange.start,colEnd:S.value.columnRange.end})},{once:!0});let N=typeof window>`u`?null:new ResizeObserver(O),P=typeof window>`u`?null:new ResizeObserver(e=>{let t=[];for(let n of e){let e=n.target,r=Number(e.dataset.index);if(e.dataset.colIndex!==void 0)t.push({index:-1,inlineSize:0,blockSize:0,element:e});else if(!Number.isNaN(r)){let i=n.contentRect.width,a=n.contentRect.height;n.borderBoxSize&&n.borderBoxSize.length>0?(i=n.borderBoxSize[0].inlineSize,a=n.borderBoxSize[0].blockSize):(i=e.offsetWidth,a=e.offsetHeight),t.push({index:r,inlineSize:i,blockSize:a,element:e})}}t.length>0&&k(t)}),F=typeof window>`u`?null:new ResizeObserver(()=>{g.value=p.value?.offsetHeight||0,_.value=m.value?.offsetHeight||0,O()});(0,e.watch)(p,(e,t)=>{t&&F?.unobserve(t),e&&F?.observe(e)},{immediate:!0}),(0,e.watch)(m,(e,t)=>{t&&F?.unobserve(t),e&&F?.observe(e)},{immediate:!0});let I=(0,e.computed)(()=>x.value[0]?.index);(0,e.watch)(I,(e,t)=>{if(i.direction===`both`){if(t!==void 0){let e=h.get(t);e&&e.querySelectorAll(`[data-col-index]`).forEach(e=>P?.unobserve(e))}if(e!==void 0){let t=h.get(e);t&&t.querySelectorAll(`[data-col-index]`).forEach(e=>P?.observe(e))}}},{flush:`post`}),(0,e.onMounted)(()=>{l.value&&N?.observe(l.value);for(let e of h.values())P?.observe(e);if(I.value!==void 0){let e=h.get(I.value);e&&e.querySelectorAll(`[data-col-index]`).forEach(e=>P?.observe(e))}}),(0,e.watch)([l,f],([e],[t])=>{t&&N?.unobserve(t),e&&N?.observe(e)});function L(e,t){if(e)h.set(t,e),P?.observe(e);else{let e=h.get(t);e&&(P?.unobserve(e),h.delete(t))}}function R(e){j();let{viewportSize:t,scrollOffset:n}=S.value,r=i.direction!==`vertical`,a=i.direction!==`horizontal`;if(e.key===`Home`){e.preventDefault(),E(0,0,`start`);return}if(e.key===`End`){e.preventDefault();let t=i.items.length-1,n=(i.columnCount||0)>0?i.columnCount-1:0;r?a?E(t,n,`end`):E(0,t,`end`):E(t,0,`end`);return}if(e.key===`ArrowUp`){e.preventDefault(),D(null,n.y-40);return}if(e.key===`ArrowDown`){e.preventDefault(),D(null,n.y+40);return}if(e.key===`ArrowLeft`){e.preventDefault(),D(n.x-40,null);return}if(e.key===`ArrowRight`){e.preventDefault(),D(n.x+40,null);return}if(e.key===`PageUp`){e.preventDefault(),D(!a&&r?n.x-t.width:null,a?n.y-t.height:null);return}e.key===`PageDown`&&(e.preventDefault(),D(!a&&r?n.x+t.width:null,a?n.y+t.height:null))}(0,e.onUnmounted)(()=>{N?.disconnect(),P?.disconnect(),F?.disconnect()});let z=(0,e.computed)(()=>{let e=i.container;return e===null||typeof window<`u`&&e===window?!0:e&&typeof e==`object`&&`tagName`in e?e.tagName===`BODY`:!1}),B=(0,e.computed)(()=>z.value?{...i.direction===`vertical`?{}:{whiteSpace:`nowrap`}}:i.containerTag===`table`?{minInlineSize:i.direction===`vertical`?`100%`:`auto`}:{...i.direction===`vertical`?{}:{whiteSpace:`nowrap`}}),V=(0,e.computed)(()=>({inlineSize:i.direction===`vertical`?`100%`:`${w.value}px`,blockSize:i.direction===`horizontal`?`100%`:`${C.value}px`})),H=(0,e.computed)(()=>{let e=i.direction===`horizontal`;return{display:e?`inline-block`:`block`,...e?{blockSize:`100%`,verticalAlign:`top`}:{inlineSize:`100%`}}}),U=(0,e.computed)(()=>({inlineSize:i.direction===`vertical`?`1px`:`${w.value}px`,blockSize:i.direction===`horizontal`?`1px`:`${C.value}px`}));function W(e){let t=i.direction===`vertical`,n=i.direction===`horizontal`,r=i.direction===`both`,s=i.itemSize===void 0||i.itemSize===null||i.itemSize===0,c={blockSize:n?`100%`:s?`auto`:`${e.size.height}px`};return t&&i.containerTag===`table`?c.minInlineSize=`100%`:c.inlineSize=t?`100%`:s?`auto`:`${e.size.width}px`,s&&(t||(c.minInlineSize=`1px`),n||(c.minBlockSize=`1px`)),y.value&&(e.isStickyActive?((t||r)&&(c.insetBlockStart=`${o(i.scrollPaddingStart,i.direction)}px`),(n||r)&&(c.insetInlineStart=`${a(i.scrollPaddingStart,i.direction)}px`),c.transform=`translate(${e.stickyOffset.x}px, ${e.stickyOffset.y}px)`):c.transform=`translate(${e.offset.x}px, ${e.offset.y}px)`),c}let G=(0,e.computed)(()=>i.debug),K=(0,e.computed)(()=>i.containerTag===`table`),q=(0,e.computed)(()=>K.value?`thead`:`div`),J=(0,e.computed)(()=>K.value?`tfoot`:`div`);return n({scrollDetails:S,columnRange:b,getColumnWidth:T,scrollToIndex:E,scrollToOffset:D,refresh:M,stopProgrammaticScroll:j}),(n,r)=>((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(t.containerTag),{ref_key:`hostRef`,ref:l,class:(0,e.normalizeClass)([`virtual-scroll-container`,[`virtual-scroll--${t.direction}`,{"virtual-scroll--hydrated":(0,e.unref)(y),"virtual-scroll--window":z.value,"virtual-scroll--table":K.value}]]),style:(0,e.normalizeStyle)(B.value),tabindex:`0`,onKeydown:R,onWheelPassive:(0,e.unref)(j),onPointerdownPassive:(0,e.unref)(j),onTouchstartPassive:(0,e.unref)(j)},{default:(0,e.withCtx)(()=>[c.header?((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(q.value),{key:0,ref_key:`headerRef`,ref:p,class:(0,e.normalizeClass)([`virtual-scroll-header`,{"virtual-scroll--sticky":t.stickyHeader}])},{default:(0,e.withCtx)(()=>[(0,e.renderSlot)(n.$slots,`header`,{},void 0,!0)]),_:3},8,[`class`])):(0,e.createCommentVNode)(``,!0),((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(t.wrapperTag),{ref_key:`wrapperRef`,ref:f,class:`virtual-scroll-wrapper`,style:(0,e.normalizeStyle)(V.value)},{default:(0,e.withCtx)(()=>[K.value?((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(t.itemTag),{key:0,class:`virtual-scroll-spacer`,style:(0,e.normalizeStyle)(U.value)},{default:(0,e.withCtx)(()=>[...r[0]||=[(0,e.createElementVNode)(`td`,{style:{padding:`0`,border:`none`,"block-size":`inherit`}},null,-1)]]),_:1},8,[`style`])):(0,e.createCommentVNode)(``,!0),((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)((0,e.unref)(x),r=>((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(t.itemTag),{key:r.index,ref_for:!0,ref:e=>L(e,r.index),"data-index":r.index,class:(0,e.normalizeClass)([`virtual-scroll-item`,{"virtual-scroll--sticky":r.isStickyActive,"virtual-scroll--debug":G.value}]),style:(0,e.normalizeStyle)(W(r))},{default:(0,e.withCtx)(()=>[(0,e.renderSlot)(n.$slots,`item`,{item:r.item,index:r.index,columnRange:(0,e.unref)(b),getColumnWidth:(0,e.unref)(T),isSticky:r.isSticky,isStickyActive:r.isStickyActive},void 0,!0),G.value?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,d,` #`+(0,e.toDisplayString)(r.index)+` (`+(0,e.toDisplayString)(Math.round(r.offset.x))+`, `+(0,e.toDisplayString)(Math.round(r.offset.y))+`) `,1)):(0,e.createCommentVNode)(``,!0)]),_:2},1032,[`data-index`,`class`,`style`]))),128))]),_:3},8,[`style`])),t.loading&&c.loading?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{key:1,class:`virtual-scroll-loading`,style:(0,e.normalizeStyle)(H.value)},[(0,e.renderSlot)(n.$slots,`loading`,{},void 0,!0)],4)):(0,e.createCommentVNode)(``,!0),c.footer?((0,e.openBlock)(),(0,e.createBlock)((0,e.resolveDynamicComponent)(J.value),{key:2,ref_key:`footerRef`,ref:m,class:(0,e.normalizeClass)([`virtual-scroll-footer`,{"virtual-scroll--sticky":t.stickyFooter}])},{default:(0,e.withCtx)(()=>[(0,e.renderSlot)(n.$slots,`footer`,{},void 0,!0)]),_:3},8,[`class`])):(0,e.createCommentVNode)(``,!0)]),_:3},40,[`class`,`style`,`onWheelPassive`,`onPointerdownPassive`,`onTouchstartPassive`]))}}),p=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},m=p(f,[[`__scopeId`,`data-v-d61a0f1d`]]);exports.DEFAULT_BUFFER=5,exports.DEFAULT_COLUMN_WIDTH=100,exports.DEFAULT_ITEM_SIZE=40,exports.FenwickTree=t,exports.VirtualScroll=m,exports.getPaddingX=a,exports.getPaddingY=o,exports.isElement=n,exports.isScrollToIndexOptions=i,exports.isScrollableElement=r,exports.useVirtualScroll=u;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|