@humanspeak/svelte-virtual-list 0.2.5 โ 0.2.6
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 +7 -6
- package/dist/SvelteVirtualList.svelte +172 -61
- package/dist/SvelteVirtualList.svelte.d.ts +78 -31
- package/dist/index.d.ts +2 -2
- package/dist/types.d.ts +18 -0
- package/dist/types.js +8 -1
- package/package.json +23 -20
package/README.md
CHANGED
|
@@ -28,11 +28,11 @@ A high-performance virtual list component for Svelte 5 applications that efficie
|
|
|
28
28
|
- ๐ง Memory-optimized for 10k+ items
|
|
29
29
|
- ๐งช Comprehensive test coverage (vitest and playwright)
|
|
30
30
|
- ๐ Progressive initialization for large datasets
|
|
31
|
-
- ๐น๏ธ Programmatic scrolling with `
|
|
31
|
+
- ๐น๏ธ Programmatic scrolling with `scroll`
|
|
32
32
|
|
|
33
|
-
##
|
|
33
|
+
## scroll: Programmatic Scrolling
|
|
34
34
|
|
|
35
|
-
You can now programmatically scroll to any item in the list using the `
|
|
35
|
+
You can now programmatically scroll to any item in the list using the `scroll` method. This is useful for chat apps, jump-to-item navigation, and more. You can check the usage in `src/routes/tests/scroll`. Thank you for the feature request!
|
|
36
36
|
|
|
37
37
|
### Usage Example
|
|
38
38
|
|
|
@@ -43,8 +43,8 @@ You can now programmatically scroll to any item in the list using the `scrollToI
|
|
|
43
43
|
const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }))
|
|
44
44
|
|
|
45
45
|
function goToItem5000() {
|
|
46
|
-
// Scroll to item 5000 with smooth scrolling
|
|
47
|
-
listRef.
|
|
46
|
+
// Scroll to item 5000 with smooth scrolling and auto alignment
|
|
47
|
+
listRef.scroll({ index: 5000, smoothScroll: true, align: 'auto' })
|
|
48
48
|
}
|
|
49
49
|
</script>
|
|
50
50
|
|
|
@@ -58,10 +58,11 @@ You can now programmatically scroll to any item in the list using the `scrollToI
|
|
|
58
58
|
|
|
59
59
|
### API
|
|
60
60
|
|
|
61
|
-
- `
|
|
61
|
+
- `scroll(options: { index: number; smoothScroll?: boolean; shouldThrowOnBounds?: boolean; align?: 'auto' | 'top' | 'bottom' })`
|
|
62
62
|
- `index`: The item index to scroll to (0-based)
|
|
63
63
|
- `smoothScroll`: If true, uses smooth scrolling (default: true)
|
|
64
64
|
- `shouldThrowOnBounds`: If true, throws if index is out of bounds (default: true)
|
|
65
|
+
- `align`: Where to align the item in the viewport. `'auto'` (default) scrolls only if the item is out of view, aligning to top or bottom as needed. `'top'` always aligns to the top, `'bottom'` always aligns to the bottom.
|
|
65
66
|
|
|
66
67
|
## Installation
|
|
67
68
|
|
|
@@ -1,45 +1,63 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
@component
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
@component SvelteVirtualList
|
|
3
|
+
|
|
4
|
+
A high-performance, memory-efficient virtualized list component for Svelte 5.
|
|
5
|
+
Renders only visible items plus a buffer, supporting dynamic item heights,
|
|
6
|
+
bi-directional (top-to-bottom and bottom-to-top) scrolling, and programmatic control.
|
|
7
|
+
|
|
8
|
+
=============================
|
|
9
|
+
== Key Features ==
|
|
10
|
+
=============================
|
|
11
|
+
- Dynamic item height support (no fixed height required)
|
|
12
|
+
- Top-to-bottom and bottom-to-top (chat-style) scrolling
|
|
13
|
+
- Programmatic scrolling with flexible alignment (top, bottom, auto)
|
|
14
|
+
- Smooth scrolling and buffer size configuration
|
|
15
|
+
- SSR compatible and hydration-friendly
|
|
16
|
+
- TypeScript and Svelte 5 runes/snippets support
|
|
17
|
+
- Customizable styling via class props
|
|
18
|
+
- Debug mode for development and testing
|
|
19
|
+
- Optimized for large lists (10k+ items)
|
|
20
|
+
- Comprehensive test coverage (unit and E2E)
|
|
21
|
+
|
|
22
|
+
=============================
|
|
23
|
+
== Usage Example ==
|
|
24
|
+
=============================
|
|
21
25
|
```svelte
|
|
22
26
|
<SvelteVirtualList
|
|
23
27
|
items={data}
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
mode="bottomToTop"
|
|
29
|
+
bind:this={listRef}
|
|
26
30
|
>
|
|
27
|
-
{#snippet renderItem(item
|
|
28
|
-
<div
|
|
31
|
+
{#snippet renderItem(item)}
|
|
32
|
+
<div>{item.text}</div>
|
|
29
33
|
{/snippet}
|
|
30
34
|
</SvelteVirtualList>
|
|
31
35
|
```
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
37
|
+
=============================
|
|
38
|
+
== Architecture Notes ==
|
|
39
|
+
=============================
|
|
40
|
+
- Uses a four-layer DOM structure for optimal performance
|
|
41
|
+
- Only visible items + buffer are mounted in the DOM
|
|
42
|
+
- Height caching and estimation for dynamic content
|
|
43
|
+
- Handles resize events and dynamic content changes
|
|
44
|
+
- Supports chunked initialization for very large lists
|
|
45
|
+
- All scrolling logic is centralized in the scroll() method
|
|
46
|
+
- Bi-directional support: mode="topToBottom" or "bottomToTop"
|
|
47
|
+
- Designed for extensibility and easy debugging
|
|
48
|
+
|
|
49
|
+
=============================
|
|
50
|
+
== For Contributors ==
|
|
51
|
+
=============================
|
|
52
|
+
- Please keep all scrolling logic in the scroll() method
|
|
53
|
+
- Add new features behind feature flags or as optional props
|
|
54
|
+
- Write tests for all new features (see /test and /tests/scroll)
|
|
55
|
+
- Use TypeScript and Svelte 5 runes for all new code
|
|
56
|
+
- Document all exported functions and props with JSDoc
|
|
57
|
+
- See README.md for API and usage details
|
|
58
|
+
- For questions, open an issue or discussion on GitHub
|
|
59
|
+
|
|
60
|
+
MIT License ยฉ Humanspeak, Inc.
|
|
43
61
|
-->
|
|
44
62
|
|
|
45
63
|
<script lang="ts">
|
|
@@ -122,16 +140,20 @@
|
|
|
122
140
|
* - Progressive size adjustment system
|
|
123
141
|
*/
|
|
124
142
|
|
|
125
|
-
import
|
|
143
|
+
import {
|
|
144
|
+
DEFAULT_SCROLL_OPTIONS,
|
|
145
|
+
type SvelteVirtualListProps,
|
|
146
|
+
type SvelteVirtualListScrollOptions
|
|
147
|
+
} from './types.js'
|
|
126
148
|
import { calculateAverageHeightDebounced } from './utils/heightCalculation.js'
|
|
127
149
|
import { createRafScheduler } from './utils/raf.js'
|
|
128
150
|
import {
|
|
129
151
|
calculateScrollPosition,
|
|
130
152
|
calculateTransformY,
|
|
131
153
|
calculateVisibleRange,
|
|
154
|
+
getScrollOffsetForIndex,
|
|
132
155
|
processChunked,
|
|
133
|
-
updateHeightAndScroll as utilsUpdateHeightAndScroll
|
|
134
|
-
getScrollOffsetForIndex
|
|
156
|
+
updateHeightAndScroll as utilsUpdateHeightAndScroll
|
|
135
157
|
} from './utils/virtualList.js'
|
|
136
158
|
import { createDebugInfo, shouldShowDebugInfo } from './utils/virtualListDebug.js'
|
|
137
159
|
import { BROWSER } from 'esm-env'
|
|
@@ -495,6 +517,9 @@
|
|
|
495
517
|
/**
|
|
496
518
|
* Scrolls the virtual list to the item at the given index.
|
|
497
519
|
*
|
|
520
|
+
* @deprecated This function is deprecated and will be removed in a future version.
|
|
521
|
+
* Use the new scroll method from the component instance instead.
|
|
522
|
+
*
|
|
498
523
|
* @function scrollToIndex
|
|
499
524
|
* @param index The index of the item to scroll to.
|
|
500
525
|
* @param smoothScroll (default: true) Whether to use smooth scrolling.
|
|
@@ -525,51 +550,137 @@
|
|
|
525
550
|
smoothScroll = true,
|
|
526
551
|
shouldThrowOnBounds = true
|
|
527
552
|
): void => {
|
|
553
|
+
// Deprecation warning
|
|
554
|
+
console.warn(
|
|
555
|
+
'SvelteVirtualList: scrollToIndex is deprecated and will be removed in a future version. ' +
|
|
556
|
+
'Use the new scroll method from the component instance instead.'
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
// Call the new scroll function with the provided parameters
|
|
560
|
+
scroll({ index, smoothScroll, shouldThrowOnBounds })
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Scrolls the virtual list to the item at the given index using a type-based options approach.
|
|
565
|
+
*
|
|
566
|
+
* @function scroll
|
|
567
|
+
* @param options Configuration options for scrolling behavior.
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* // Svelte usage:
|
|
571
|
+
* // In your <script> block:
|
|
572
|
+
* import SvelteVirtualList from './index.js';
|
|
573
|
+
* let virtualList;
|
|
574
|
+
* const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }));
|
|
575
|
+
*
|
|
576
|
+
* <button onclick={() => virtualList.scroll({ index: 5000 })}>
|
|
577
|
+
* Scroll to 5000
|
|
578
|
+
* </button>
|
|
579
|
+
* <SvelteVirtualList {items} bind:this={virtualList}>
|
|
580
|
+
* {#snippet renderItem(item)}
|
|
581
|
+
* <div>{item.text}</div>
|
|
582
|
+
* {/snippet}
|
|
583
|
+
* </SvelteVirtualList>
|
|
584
|
+
*
|
|
585
|
+
* @returns {void}
|
|
586
|
+
* @throws {Error} If the index is out of bounds and shouldThrowOnBounds is true
|
|
587
|
+
*/
|
|
588
|
+
export const scroll = (options: SvelteVirtualListScrollOptions): void => {
|
|
589
|
+
const { index, smoothScroll, shouldThrowOnBounds, align } = {
|
|
590
|
+
...DEFAULT_SCROLL_OPTIONS,
|
|
591
|
+
...options
|
|
592
|
+
}
|
|
593
|
+
|
|
528
594
|
if (!items.length) return
|
|
529
595
|
if (!viewportElement) {
|
|
530
596
|
tick().then(() => {
|
|
531
597
|
if (!viewportElement) return
|
|
532
|
-
|
|
598
|
+
scroll({ index, smoothScroll, shouldThrowOnBounds, align })
|
|
533
599
|
})
|
|
534
600
|
return
|
|
535
601
|
}
|
|
536
|
-
doScroll()
|
|
537
602
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
if (
|
|
603
|
+
// Bounds checking
|
|
604
|
+
let targetIndex = index
|
|
605
|
+
if (targetIndex < 0 || targetIndex >= items.length) {
|
|
606
|
+
if (shouldThrowOnBounds) {
|
|
542
607
|
throw new Error(
|
|
543
|
-
`
|
|
608
|
+
`scroll: index ${targetIndex} is out of bounds (0-${items.length - 1})`
|
|
544
609
|
)
|
|
610
|
+
} else {
|
|
611
|
+
targetIndex = Math.max(0, Math.min(targetIndex, items.length - 1))
|
|
545
612
|
}
|
|
546
|
-
|
|
547
|
-
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const { start: firstVisibleIndex, end: lastVisibleIndex } = visibleItems()
|
|
616
|
+
let scrollTarget: number | null = null
|
|
617
|
+
|
|
618
|
+
if (mode === 'bottomToTop') {
|
|
619
|
+
const totalHeight = items.length * calculatedItemHeight
|
|
620
|
+
const itemOffset = targetIndex * calculatedItemHeight
|
|
621
|
+
const itemHeight = calculatedItemHeight
|
|
622
|
+
if (align === 'auto') {
|
|
623
|
+
if (targetIndex < firstVisibleIndex) {
|
|
624
|
+
// Align to top
|
|
625
|
+
scrollTarget = Math.max(0, totalHeight - (itemOffset + itemHeight))
|
|
626
|
+
} else if (targetIndex > lastVisibleIndex - 1) {
|
|
627
|
+
// Align to bottom
|
|
628
|
+
scrollTarget = Math.max(0, totalHeight - itemOffset - height)
|
|
629
|
+
} else {
|
|
630
|
+
// Already in view, do nothing
|
|
631
|
+
return
|
|
632
|
+
}
|
|
633
|
+
} else if (align === 'top') {
|
|
634
|
+
// Align to top
|
|
635
|
+
scrollTarget = Math.max(0, totalHeight - (itemOffset + itemHeight))
|
|
636
|
+
} else if (align === 'bottom') {
|
|
637
|
+
// Align to bottom
|
|
638
|
+
scrollTarget = Math.max(0, totalHeight - itemOffset - height)
|
|
639
|
+
}
|
|
640
|
+
} else {
|
|
641
|
+
// topToBottom (default)
|
|
642
|
+
if (align === 'auto') {
|
|
643
|
+
if (targetIndex < firstVisibleIndex) {
|
|
644
|
+
// Scroll so item is at the top
|
|
645
|
+
scrollTarget = getScrollOffsetForIndex(
|
|
646
|
+
heightCache,
|
|
647
|
+
calculatedItemHeight,
|
|
648
|
+
targetIndex
|
|
649
|
+
)
|
|
650
|
+
} else if (targetIndex > lastVisibleIndex - 1) {
|
|
651
|
+
// Scroll so item is at the bottom
|
|
652
|
+
const itemBottom = getScrollOffsetForIndex(
|
|
653
|
+
heightCache,
|
|
654
|
+
calculatedItemHeight,
|
|
655
|
+
targetIndex + 1
|
|
656
|
+
)
|
|
657
|
+
scrollTarget = Math.max(0, itemBottom - height)
|
|
658
|
+
} else {
|
|
659
|
+
// Already in view, do nothing
|
|
660
|
+
return
|
|
661
|
+
}
|
|
662
|
+
} else if (align === 'top') {
|
|
663
|
+
scrollTarget = getScrollOffsetForIndex(
|
|
548
664
|
heightCache,
|
|
549
665
|
calculatedItemHeight,
|
|
550
|
-
|
|
666
|
+
targetIndex
|
|
551
667
|
)
|
|
552
|
-
|
|
553
|
-
top: scrollTopTarget,
|
|
554
|
-
behavior: smoothScroll ? 'smooth' : 'auto'
|
|
555
|
-
})
|
|
556
|
-
} else if (mode === 'bottomToTop') {
|
|
557
|
-
// Invert the index for reversed rendering
|
|
558
|
-
const reversedIndex = items.length - 1 - clampedIndex
|
|
668
|
+
} else if (align === 'bottom') {
|
|
559
669
|
const itemBottom = getScrollOffsetForIndex(
|
|
560
670
|
heightCache,
|
|
561
671
|
calculatedItemHeight,
|
|
562
|
-
|
|
672
|
+
targetIndex + 1
|
|
563
673
|
)
|
|
564
|
-
|
|
565
|
-
viewportElement.scrollTo({
|
|
566
|
-
top: scrollTopTarget,
|
|
567
|
-
behavior: smoothScroll ? 'smooth' : 'auto'
|
|
568
|
-
})
|
|
569
|
-
} else {
|
|
570
|
-
console.warn('scrollToIndex: unknown mode:', mode)
|
|
674
|
+
scrollTarget = Math.max(0, itemBottom - height)
|
|
571
675
|
}
|
|
572
676
|
}
|
|
677
|
+
|
|
678
|
+
if (scrollTarget !== null) {
|
|
679
|
+
viewportElement.scrollTo({
|
|
680
|
+
top: scrollTarget,
|
|
681
|
+
behavior: smoothScroll ? 'smooth' : 'auto'
|
|
682
|
+
})
|
|
683
|
+
}
|
|
573
684
|
}
|
|
574
685
|
</script>
|
|
575
686
|
|
|
@@ -76,53 +76,75 @@
|
|
|
76
76
|
* - Height caching and estimation system
|
|
77
77
|
* - Progressive size adjustment system
|
|
78
78
|
*/
|
|
79
|
-
import type
|
|
79
|
+
import { type SvelteVirtualListProps, type SvelteVirtualListScrollOptions } from './types.js';
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
82
|
-
* by only mounting DOM nodes for visible items and a small buffer. Optimized for handling
|
|
83
|
-
* lists of 10k+ items through chunked processing and progressive initialization.
|
|
81
|
+
* SvelteVirtualList
|
|
84
82
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* -
|
|
88
|
-
* - `mode` - Scroll direction: 'topToBottom' or 'bottomToTop' (default: 'topToBottom')
|
|
89
|
-
* - `debug` - Enable debug logging (default: false)
|
|
90
|
-
* - `bufferSize` - Number of items to render outside visible area (default: 20)
|
|
91
|
-
* - `containerClass` - Custom class for container element
|
|
92
|
-
* - `viewportClass` - Custom class for viewport element
|
|
93
|
-
* - `contentClass` - Custom class for content wrapper
|
|
94
|
-
* - `itemsClass` - Custom class for items wrapper
|
|
95
|
-
* - `debugFunction` - Custom debug logging function
|
|
96
|
-
* - `testId` - Base test ID for component elements
|
|
83
|
+
* A high-performance, memory-efficient virtualized list component for Svelte 5.
|
|
84
|
+
* Renders only visible items plus a buffer, supporting dynamic item heights,
|
|
85
|
+
* bi-directional (top-to-bottom and bottom-to-top) scrolling, and programmatic control.
|
|
97
86
|
*
|
|
98
|
-
*
|
|
87
|
+
* =============================
|
|
88
|
+
* == Key Features ==
|
|
89
|
+
* =============================
|
|
90
|
+
* - Dynamic item height support (no fixed height required)
|
|
91
|
+
* - Top-to-bottom and bottom-to-top (chat-style) scrolling
|
|
92
|
+
* - Programmatic scrolling with flexible alignment (top, bottom, auto)
|
|
93
|
+
* - Smooth scrolling and buffer size configuration
|
|
94
|
+
* - SSR compatible and hydration-friendly
|
|
95
|
+
* - TypeScript and Svelte 5 runes/snippets support
|
|
96
|
+
* - Customizable styling via class props
|
|
97
|
+
* - Debug mode for development and testing
|
|
98
|
+
* - Optimized for large lists (10k+ items)
|
|
99
|
+
* - Comprehensive test coverage (unit and E2E)
|
|
100
|
+
*
|
|
101
|
+
* =============================
|
|
102
|
+
* == Usage Example ==
|
|
103
|
+
* =============================
|
|
99
104
|
* ```svelte
|
|
100
105
|
* <SvelteVirtualList
|
|
101
106
|
* items={data}
|
|
102
|
-
*
|
|
103
|
-
*
|
|
107
|
+
* mode="bottomToTop"
|
|
108
|
+
* bind:this={listRef}
|
|
104
109
|
* >
|
|
105
|
-
* {#snippet renderItem(item
|
|
106
|
-
* <div
|
|
110
|
+
* {#snippet renderItem(item)}
|
|
111
|
+
* <div>{item.text}</div>
|
|
107
112
|
* {/snippet}
|
|
108
113
|
* </SvelteVirtualList>
|
|
109
114
|
* ```
|
|
110
115
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* -
|
|
115
|
-
* -
|
|
116
|
-
* -
|
|
117
|
-
* -
|
|
118
|
-
* -
|
|
119
|
-
* -
|
|
120
|
-
* -
|
|
116
|
+
* =============================
|
|
117
|
+
* == Architecture Notes ==
|
|
118
|
+
* =============================
|
|
119
|
+
* - Uses a four-layer DOM structure for optimal performance
|
|
120
|
+
* - Only visible items + buffer are mounted in the DOM
|
|
121
|
+
* - Height caching and estimation for dynamic content
|
|
122
|
+
* - Handles resize events and dynamic content changes
|
|
123
|
+
* - Supports chunked initialization for very large lists
|
|
124
|
+
* - All scrolling logic is centralized in the scroll() method
|
|
125
|
+
* - Bi-directional support: mode="topToBottom" or "bottomToTop"
|
|
126
|
+
* - Designed for extensibility and easy debugging
|
|
127
|
+
*
|
|
128
|
+
* =============================
|
|
129
|
+
* == For Contributors ==
|
|
130
|
+
* =============================
|
|
131
|
+
* - Please keep all scrolling logic in the scroll() method
|
|
132
|
+
* - Add new features behind feature flags or as optional props
|
|
133
|
+
* - Write tests for all new features (see /test and /tests/scroll)
|
|
134
|
+
* - Use TypeScript and Svelte 5 runes for all new code
|
|
135
|
+
* - Document all exported functions and props with JSDoc
|
|
136
|
+
* - See README.md for API and usage details
|
|
137
|
+
* - For questions, open an issue or discussion on GitHub
|
|
138
|
+
*
|
|
139
|
+
* MIT License ยฉ Humanspeak, Inc.
|
|
121
140
|
*/
|
|
122
141
|
declare const SvelteVirtualList: import("svelte").Component<SvelteVirtualListProps, {
|
|
123
142
|
/**
|
|
124
143
|
* Scrolls the virtual list to the item at the given index.
|
|
125
144
|
*
|
|
145
|
+
* @deprecated This function is deprecated and will be removed in a future version.
|
|
146
|
+
* Use the new scroll method from the component instance instead.
|
|
147
|
+
*
|
|
126
148
|
* @function scrollToIndex
|
|
127
149
|
* @param index The index of the item to scroll to.
|
|
128
150
|
* @param smoothScroll (default: true) Whether to use smooth scrolling.
|
|
@@ -148,6 +170,31 @@ declare const SvelteVirtualList: import("svelte").Component<SvelteVirtualListPro
|
|
|
148
170
|
* @returns {void}
|
|
149
171
|
* @throws {Error} If the index is out of bounds and shouldThrowOnBounds is true
|
|
150
172
|
*/ scrollToIndex: (index: number, smoothScroll?: boolean, shouldThrowOnBounds?: boolean) => void;
|
|
173
|
+
/**
|
|
174
|
+
* Scrolls the virtual list to the item at the given index using a type-based options approach.
|
|
175
|
+
*
|
|
176
|
+
* @function scroll
|
|
177
|
+
* @param options Configuration options for scrolling behavior.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* // Svelte usage:
|
|
181
|
+
* // In your <script> block:
|
|
182
|
+
* import SvelteVirtualList from './index.js';
|
|
183
|
+
* let virtualList;
|
|
184
|
+
* const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }));
|
|
185
|
+
*
|
|
186
|
+
* <button onclick={() => virtualList.scroll({ index: 5000 })}>
|
|
187
|
+
* Scroll to 5000
|
|
188
|
+
* </button>
|
|
189
|
+
* <SvelteVirtualList {items} bind:this={virtualList}>
|
|
190
|
+
* {#snippet renderItem(item)}
|
|
191
|
+
* <div>{item.text}</div>
|
|
192
|
+
* {/snippet}
|
|
193
|
+
* </SvelteVirtualList>
|
|
194
|
+
*
|
|
195
|
+
* @returns {void}
|
|
196
|
+
* @throws {Error} If the index is out of bounds and shouldThrowOnBounds is true
|
|
197
|
+
*/ scroll: (options: SvelteVirtualListScrollOptions) => void;
|
|
151
198
|
}, "">;
|
|
152
199
|
type SvelteVirtualList = ReturnType<typeof SvelteVirtualList>;
|
|
153
200
|
export default SvelteVirtualList;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import SvelteVirtualList from './SvelteVirtualList.svelte';
|
|
2
|
-
import type { SvelteVirtualListDebugInfo, SvelteVirtualListMode, SvelteVirtualListProps } from './types.js';
|
|
2
|
+
import type { SvelteVirtualListDebugInfo, SvelteVirtualListMode, SvelteVirtualListProps, SvelteVirtualListScrollAlign, SvelteVirtualListScrollOptions } from './types.js';
|
|
3
3
|
export default SvelteVirtualList;
|
|
4
|
-
export type { SvelteVirtualListDebugInfo, SvelteVirtualListMode, SvelteVirtualListProps };
|
|
4
|
+
export type { SvelteVirtualListDebugInfo, SvelteVirtualListMode, SvelteVirtualListProps, SvelteVirtualListScrollAlign, SvelteVirtualListScrollOptions };
|
package/dist/types.d.ts
CHANGED
|
@@ -82,3 +82,21 @@ export type SvelteVirtualListDebugInfo = {
|
|
|
82
82
|
processedItems: number;
|
|
83
83
|
averageItemHeight: number;
|
|
84
84
|
};
|
|
85
|
+
export type SvelteVirtualListScrollAlign = 'auto' | 'top' | 'bottom';
|
|
86
|
+
/**
|
|
87
|
+
* Options for scrolling to a specific index in the virtual list.
|
|
88
|
+
*/
|
|
89
|
+
export interface SvelteVirtualListScrollOptions {
|
|
90
|
+
/** The index of the item to scroll to. */
|
|
91
|
+
index: number;
|
|
92
|
+
/** Whether to use smooth scrolling animation. Default: true */
|
|
93
|
+
smoothScroll?: boolean;
|
|
94
|
+
/** Whether to throw an error if the index is out of bounds. Default: true */
|
|
95
|
+
shouldThrowOnBounds?: boolean;
|
|
96
|
+
/** Alignment for the scrolled item: 'auto', 'top', or 'bottom'. Default: 'auto' */
|
|
97
|
+
align?: SvelteVirtualListScrollAlign;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Default options for scrolling.
|
|
101
|
+
*/
|
|
102
|
+
export declare const DEFAULT_SCROLL_OPTIONS: Partial<SvelteVirtualListScrollOptions>;
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humanspeak/svelte-virtual-list",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "A lightweight, high-performance virtual list component for Svelte 5 that renders large datasets with minimal memory usage. Features include dynamic height support, smooth scrolling, TypeScript support, and efficient DOM recycling. Ideal for infinite scrolling lists, data tables, chat interfaces, and any application requiring the rendering of thousands of items without compromising performance. Zero dependencies and fully customizable.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"files": [
|
|
44
44
|
"dist",
|
|
45
45
|
"!dist/**/*.test.*",
|
|
46
|
-
"!dist/**/*.spec.*"
|
|
46
|
+
"!dist/**/*.spec.*",
|
|
47
|
+
"!dist/test/**/*"
|
|
47
48
|
],
|
|
48
49
|
"scripts": {
|
|
49
50
|
"build": "vite build && npm run package",
|
|
@@ -74,38 +75,40 @@
|
|
|
74
75
|
"esm-env": "^1.2.2"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
77
|
-
"@eslint/compat": "^1.
|
|
78
|
-
"@eslint/js": "^9.
|
|
78
|
+
"@eslint/compat": "^1.3.1",
|
|
79
|
+
"@eslint/js": "^9.29.0",
|
|
79
80
|
"@faker-js/faker": "^9.8.0",
|
|
80
|
-
"@playwright/test": "^1.
|
|
81
|
+
"@playwright/test": "^1.53.1",
|
|
81
82
|
"@sveltejs/adapter-auto": "^6.0.1",
|
|
82
|
-
"@sveltejs/kit": "^2.
|
|
83
|
-
"@sveltejs/package": "^2.3.
|
|
84
|
-
"@sveltejs/vite-plugin-svelte": "^5.0
|
|
83
|
+
"@sveltejs/kit": "^2.22.2",
|
|
84
|
+
"@sveltejs/package": "^2.3.12",
|
|
85
|
+
"@sveltejs/vite-plugin-svelte": "^5.1.0",
|
|
85
86
|
"@testing-library/jest-dom": "^6.6.3",
|
|
86
87
|
"@testing-library/svelte": "^5.2.8",
|
|
87
88
|
"@testing-library/user-event": "^14.6.1",
|
|
88
|
-
"@types/node": "^
|
|
89
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
90
|
-
"@typescript-eslint/parser": "^8.
|
|
91
|
-
"@vitest/coverage-v8": "^3.
|
|
92
|
-
"eslint": "^9.
|
|
89
|
+
"@types/node": "^24.0.4",
|
|
90
|
+
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
|
91
|
+
"@typescript-eslint/parser": "^8.35.0",
|
|
92
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
93
|
+
"eslint": "^9.29.0",
|
|
93
94
|
"eslint-config-prettier": "^10.1.5",
|
|
94
|
-
"eslint-plugin-import": "^2.
|
|
95
|
-
"eslint-plugin-svelte": "^3.
|
|
95
|
+
"eslint-plugin-import": "^2.32.0",
|
|
96
|
+
"eslint-plugin-svelte": "^3.10.0",
|
|
96
97
|
"eslint-plugin-unused-imports": "^4.1.4",
|
|
97
98
|
"globals": "^16.2.0",
|
|
98
99
|
"jsdom": "^26.1.0",
|
|
99
|
-
"prettier": "^3.
|
|
100
|
+
"prettier": "^3.6.1",
|
|
100
101
|
"prettier-plugin-organize-imports": "^4.1.0",
|
|
102
|
+
"prettier-plugin-sort-json": "^4.1.1",
|
|
101
103
|
"prettier-plugin-svelte": "^3.4.0",
|
|
104
|
+
"prettier-plugin-tailwindcss": "^0.6.13",
|
|
102
105
|
"publint": "^0.3.12",
|
|
103
|
-
"svelte": "^5.
|
|
104
|
-
"svelte-check": "^4.2.
|
|
106
|
+
"svelte": "^5.34.8",
|
|
107
|
+
"svelte-check": "^4.2.2",
|
|
105
108
|
"typescript": "^5.8.3",
|
|
106
|
-
"typescript-eslint": "^8.
|
|
109
|
+
"typescript-eslint": "^8.35.0",
|
|
107
110
|
"vite": "^6.3.5",
|
|
108
|
-
"vitest": "^3.
|
|
111
|
+
"vitest": "^3.2.4"
|
|
109
112
|
},
|
|
110
113
|
"peerDependencies": {
|
|
111
114
|
"svelte": "^5.0.0"
|