@humanspeak/svelte-virtual-list 0.2.1 โ†’ 0.2.3

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 CHANGED
@@ -1,4 +1,4 @@
1
- # Svelte Virtual List
1
+ # @humanspeak/svelte-virtual-list
2
2
 
3
3
  [![NPM version](https://img.shields.io/npm/v/@humanspeak/svelte-virtual-list.svg)](https://www.npmjs.com/package/@humanspeak/svelte-virtual-list)
4
4
  [![Build Status](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/npm-publish.yml)
@@ -6,23 +6,27 @@
6
6
  [![License](https://img.shields.io/npm/l/@humanspeak/svelte-virtual-list.svg)](https://github.com/humanspeak/svelte-virtual-list/blob/main/LICENSE.md)
7
7
  [![Downloads](https://img.shields.io/npm/dm/@humanspeak/svelte-virtual-list.svg)](https://www.npmjs.com/package/@humanspeak/svelte-virtual-list)
8
8
  [![CodeQL](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/codeql.yml/badge.svg)](https://github.com/humanspeak/svelte-virtual-list/actions/workflows/codeql.yml)
9
+ [![Code Style: Trunk](https://img.shields.io/badge/code%20style-trunk-blue.svg)](https://trunk.io)
9
10
  [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
10
11
  [![Types](https://img.shields.io/npm/types/@humanspeak/svelte-virtual-list.svg)](https://www.npmjs.com/package/@humanspeak/svelte-virtual-list)
11
12
  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/humanspeak/svelte-virtual-list/graphs/commit-activity)
12
13
 
13
- A virtual list component for Svelte applications. Built for Svelte 5 with TypeScript support.
14
+ A high-performance virtual list component for Svelte 5 applications that efficiently renders large datasets with minimal memory usage.
14
15
 
15
16
  ## Features
16
17
 
17
- - Efficient rendering of large lists with dynamic heights
18
- - Bi-directional scrolling (top-to-bottom and bottom-to-top)
19
- - Automatic resize handling and content updates
20
- - TypeScript support with full type safety
21
- - SSR compatible with hydration support
22
- - Svelte 5 runes and snippets support
23
- - Customizable styling with class props
24
- - Debug mode for development
25
- - Smooth scrolling with configurable buffer zones
18
+ - ๐Ÿ“ Dynamic item height handling - no fixed height required
19
+ - ๐Ÿ”„ Bi-directional scrolling support (top-to-bottom and bottom-to-top)
20
+ - ๐Ÿ”„ Automatic resize handling for dynamic content
21
+ - ๐Ÿ“ TypeScript support with full type safety
22
+ - ๐Ÿš€ SSR compatible with hydration support
23
+ - โœจ Svelte 5 runes and snippets support
24
+ - ๐ŸŽจ Customizable styling with class props
25
+ - ๐Ÿ› Debug mode for development
26
+ - ๐ŸŽฏ Smooth scrolling with configurable buffer zones
27
+ - ๐Ÿง  Memory-optimized for 10k+ items
28
+ - ๐Ÿงช Comprehensive test coverage (vitest and playwright)
29
+ - ๐Ÿš€ Progressive initialization for large datasets
26
30
 
27
31
  ## Installation
28
32
 
@@ -49,155 +53,8 @@ npm install @humanspeak/svelte-virtual-list
49
53
  </SvelteVirtualList>
50
54
  ```
51
55
 
52
- ## Props
53
-
54
- | Prop | Type | Default | Description |
55
- | ------------------- | -------------------------------- | --------------- | ------------------------------------------- |
56
- | `items` | `T[]` | Required | Array of items to render |
57
- | `defaultItemHeight` | `number` | `40` | Initial height for items before measurement |
58
- | `mode` | `'topToBottom' \| 'bottomToTop'` | `'topToBottom'` | Scroll direction |
59
- | `bufferSize` | `number` | `20` | Number of items to render outside viewport |
60
- | `debug` | `boolean` | `false` | Enable debug logging and visualizations |
61
- | `containerClass` | `string` | `''` | Class for outer container |
62
- | `viewportClass` | `string` | `''` | Class for scrollable viewport |
63
- | `contentClass` | `string` | `''` | Class for content wrapper |
64
- | `itemsClass` | `string` | `''` | Class for items container |
65
-
66
- ## Dependencies
67
-
68
- - [esm-env](https://github.com/benmccann/esm-env) - svelte5 suggested environment detecting
69
-
70
- ## Usage
71
-
72
- ```svelte
73
- <script lang="ts">
74
- import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
75
- import { onMount } from 'svelte'
76
-
77
- type Item = {
78
- id: number
79
- text: string
80
- }
81
-
82
- const items: Item[] = Array.from({ length: 10000 }, (_, i) => ({
83
- id: i,
84
- text: `Item ${i}`
85
- }))
86
- </script>
87
-
88
- <div class="grid grid-cols-2 gap-8">
89
- <!-- Top to bottom scrolling -->
90
- <div>
91
- <SvelteVirtualList {items}>
92
- {#snippet renderItem(item: Item, index: number)}
93
- <div>
94
- {item.text}
95
- </div>
96
- {/snippet}
97
- </SvelteVirtualList>
98
- </div>
99
-
100
- <!-- Bottom to top scrolling -->
101
- <div>
102
- <SvelteVirtualList {items} mode="bottomToTop">
103
- {#snippet renderItem(item: Item, index: number)}
104
- <div>
105
- {item.text}
106
- </div>
107
- {/snippet}
108
- </SvelteVirtualList>
109
- </div>
110
- </div>
111
- ```
112
-
113
- ## Development
114
-
115
- ```bash
116
- npm install
117
- npm run dev
118
- ```
119
-
120
- ## Testing
121
-
122
- ```bash
123
- npm run test
124
- ```
125
-
126
- ## Building
127
-
128
- ```bash
129
- npm run build
130
- ```
131
-
132
- ## License
133
-
134
- [MIT](LICENSE.md)
135
-
136
- ## Key Features
137
-
138
- - Dynamic item height handling - no fixed height required
139
- - Bi-directional scrolling support (top-to-bottom and bottom-to-top)
140
- - Automatic resize handling for dynamic content
141
- - Efficient rendering of large lists
142
- - TypeScript support
143
- - Customizable styling
144
- - Debug mode for development
145
- - Smooth scrolling with buffer zones
146
- - SSR compatible
147
- - Svelte 5 runes support
148
-
149
- ## Usage Examples
150
-
151
- ### Basic Usage
152
-
153
- ### Default display
154
-
155
- ```svelte
156
- <script lang="ts">
157
- import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
158
-
159
- const items = Array.from({ length: 1000 }, (_, i) => ({
160
- id: i,
161
- text: `Item ${i}`
162
- }))
163
- </script>
164
-
165
- <SvelteVirtualList {items}>
166
- {#snippet renderItem(item)}
167
- <div>
168
- {item.text}
169
- </div>
170
- {/snippet}
171
- </SvelteVirtualList>
172
- ```
173
-
174
- ### Bottom-to-Top Scrolling
175
-
176
- The component supports reverse scrolling, which is useful for chat applications or logs:
177
-
178
- ```svelte
179
- <SvelteVirtualList {items} mode="bottomToTop">
180
- {#snippet renderItem(item)}
181
- <div>{item.text}</div>
182
- {/snippet}
183
- </SvelteVirtualList>
184
- ```
185
-
186
56
  ## Advanced Features
187
57
 
188
- ### Auto-resize Handling
189
-
190
- The component automatically handles:
191
-
192
- - Dynamic content changes within items
193
- - Window resize events
194
- - Container resize events
195
- - Dynamic height calculations
196
-
197
- No manual intervention is needed when item contents or dimensions change.
198
-
199
- ## Advanced Usage
200
-
201
58
  ### Chat Application Example
202
59
 
203
60
  ```svelte
@@ -229,20 +86,21 @@ No manual intervention is needed when item contents or dimensions change.
229
86
  {/snippet}
230
87
  </SvelteVirtualList>
231
88
  </div>
89
+ ```
232
90
 
233
- <style>
234
- .message-container {
235
- padding: 1rem;
236
- border-radius: 0.5rem;
237
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
238
- }
91
+ ## Props
239
92
 
240
- .timestamp {
241
- font-size: 0.875rem;
242
- color: #6b7280;
243
- }
244
- </style>
245
- ```
93
+ | Prop | Type | Default | Description |
94
+ | ------------------- | -------------------------------- | --------------- | ------------------------------------------- |
95
+ | `items` | `T[]` | Required | Array of items to render |
96
+ | `defaultItemHeight` | `number` | `40` | Initial height for items before measurement |
97
+ | `mode` | `'topToBottom' \| 'bottomToTop'` | `'topToBottom'` | Scroll direction |
98
+ | `bufferSize` | `number` | `20` | Number of items to render outside viewport |
99
+ | `debug` | `boolean` | `false` | Enable debug logging and visualizations |
100
+ | `containerClass` | `string` | `''` | Class for outer container |
101
+ | `viewportClass` | `string` | `''` | Class for scrollable viewport |
102
+ | `contentClass` | `string` | `''` | Class for content wrapper |
103
+ | `itemsClass` | `string` | `''` | Class for items container |
246
104
 
247
105
  ## Performance Considerations
248
106
 
@@ -252,8 +110,10 @@ No manual intervention is needed when item contents or dimensions change.
252
110
  - Resize observers handle container/content changes
253
111
  - Virtual DOM updates are batched for efficiency
254
112
 
255
- ## Related
113
+ ## License
114
+
115
+ MIT ยฉ [Humanspeak, Inc.](LICENSE.md)
256
116
 
257
- - [Svelte](https://svelte.dev) - JavaScript front-end framework
117
+ ## Credits
258
118
 
259
119
  Made with โ™ฅ by [Humanspeak](https://humanspeak.com)
@@ -15,6 +15,7 @@
15
15
  - `contentClass` - Custom class for content wrapper
16
16
  - `itemsClass` - Custom class for items wrapper
17
17
  - `debugFunction` - Custom debug logging function
18
+ - `testId` - Base test ID for component elements
18
19
 
19
20
  Usage:
20
21
  ```svelte
@@ -150,7 +151,8 @@
150
151
  itemsClass, // Custom class for the items wrapper
151
152
  debugFunction, // Custom debug logging function
152
153
  mode = 'topToBottom', // Scroll direction mode
153
- bufferSize = 20 // Number of items to render outside visible area
154
+ bufferSize = 20, // Number of items to render outside visible area
155
+ testId // Base test ID for component elements (undefined = no data-testid attributes)
154
156
  }: SvelteVirtualListProps = $props()
155
157
 
156
158
  /**
@@ -550,14 +552,14 @@
550
552
  -->
551
553
  <div
552
554
  id="virtual-list-container"
553
- data-testid="virtual-list-container"
555
+ {...testId ? { 'data-testid': `${testId}-container` } : {}}
554
556
  class={containerClass ?? 'virtual-list-container'}
555
557
  bind:this={containerElement}
556
558
  >
557
559
  <!-- Viewport handles scrolling -->
558
560
  <div
559
561
  id="virtual-list-viewport"
560
- data-testid="virtual-list-viewport"
562
+ {...testId ? { 'data-testid': `${testId}-viewport` } : {}}
561
563
  class={viewportClass ?? 'virtual-list-viewport'}
562
564
  bind:this={viewportElement}
563
565
  onscroll={handleScroll}
@@ -565,13 +567,14 @@
565
567
  <!-- Content provides full scrollable height -->
566
568
  <div
567
569
  id="virtual-list-content"
570
+ {...testId ? { 'data-testid': `${testId}-content` } : {}}
568
571
  class={contentClass ?? 'virtual-list-content'}
569
- data-testid="virtual-list-content"
570
572
  style:height="{Math.max(height, items.length * calculatedItemHeight)}px"
571
573
  >
572
574
  <!-- Items container is translated to show correct items -->
573
575
  <div
574
576
  id="virtual-list-items"
577
+ {...testId ? { 'data-testid': `${testId}-items` } : {}}
575
578
  class={itemsClass ?? 'virtual-list-items'}
576
579
  style:transform="translateY({calculateTransformY(
577
580
  mode,
@@ -15,6 +15,7 @@ import type { SvelteVirtualListProps } from './types.js';
15
15
  * - `contentClass` - Custom class for content wrapper
16
16
  * - `itemsClass` - Custom class for items wrapper
17
17
  * - `debugFunction` - Custom debug logging function
18
+ * - `testId` - Base test ID for component elements
18
19
  *
19
20
  * Usage:
20
21
  * ```svelte
package/dist/types.d.ts CHANGED
@@ -23,6 +23,7 @@ export type SvelteVirtualListMode = 'topToBottom' | 'bottomToTop';
23
23
  * @property {SvelteVirtualListMode} [mode='topToBottom'] - Determines the scroll and render direction.
24
24
  * @property {Snippet<[item: any, index: number]>} renderItem - Svelte snippet function that defines
25
25
  * how each item should be rendered. Receives the item and its index as arguments.
26
+ * @property {string} [testId] - Base test ID for component elements to facilitate testing.
26
27
  * @property {string} [viewportClass] - CSS class to apply to the scrollable viewport element.
27
28
  */
28
29
  export type SvelteVirtualListProps = {
@@ -36,6 +37,7 @@ export type SvelteVirtualListProps = {
36
37
  itemsClass?: string;
37
38
  mode?: SvelteVirtualListMode;
38
39
  renderItem: Snippet<[item: any, index: number]>;
40
+ testId?: string;
39
41
  viewportClass?: string;
40
42
  };
41
43
  /**
package/package.json CHANGED
@@ -1,108 +1,106 @@
1
1
  {
2
2
  "name": "@humanspeak/svelte-virtual-list",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
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
+ "keywords": [
6
+ "svelte",
7
+ "virtual-list",
8
+ "virtual-scroll",
9
+ "infinite-scroll",
10
+ "performance",
11
+ "ui-component",
12
+ "svelte5",
13
+ "dom-recycling",
14
+ "large-lists",
15
+ "scroll-optimization"
16
+ ],
17
+ "homepage": "https://virtuallist.svelte.page",
18
+ "bugs": {
19
+ "url": "https://github.com/humanspeak/svelte-virtual-list/issues"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/humanspeak/svelte-virtual-list.git"
24
+ },
25
+ "funding": {
26
+ "type": "github",
27
+ "url": "https://github.com/sponsors/humanspeak"
28
+ },
29
+ "license": "MIT",
30
+ "author": "Humanspeak, Inc.",
31
+ "sideEffects": [
32
+ "**/*.css"
33
+ ],
5
34
  "type": "module",
6
- "svelte": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
35
  "exports": {
9
36
  ".": {
10
37
  "types": "./dist/index.d.ts",
11
38
  "svelte": "./dist/index.js"
12
39
  }
13
40
  },
41
+ "svelte": "./dist/index.js",
42
+ "types": "./dist/index.d.ts",
14
43
  "files": [
15
44
  "dist",
16
45
  "!dist/**/*.test.*",
17
46
  "!dist/**/*.spec.*"
18
47
  ],
19
- "sideEffects": [
20
- "**/*.css"
21
- ],
22
48
  "scripts": {
23
- "dev": "vite dev",
24
49
  "build": "vite build && npm run package",
25
- "preview": "vite preview",
26
- "package": "svelte-kit sync && svelte-package && publint",
27
- "prepublishOnly": "npm run package",
28
50
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
29
51
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
30
- "test": "vitest run --coverage",
31
- "test:only": "vitest run",
32
- "test:watch": "vitest",
52
+ "dev": "vite dev",
53
+ "format": "prettier --write .",
33
54
  "lint": "prettier --check . && eslint .",
34
55
  "lint:fix": "npm run format && eslint . --fix",
35
- "format": "prettier --write ."
56
+ "package": "svelte-kit sync && svelte-package && publint",
57
+ "prepublishOnly": "npm run package",
58
+ "preview": "vite preview",
59
+ "test": "vitest run --coverage",
60
+ "test:e2e": "playwright test",
61
+ "test:e2e:debug": "playwright test --debug",
62
+ "test:e2e:report": "playwright show-report",
63
+ "test:e2e:ui": "playwright test --ui",
64
+ "test:only": "vitest run",
65
+ "test:watch": "vitest"
36
66
  },
37
67
  "dependencies": {
38
- "esm-env": "^1.2.1"
39
- },
40
- "peerDependencies": {
41
- "svelte": "^5.0.0"
68
+ "esm-env": "^1.2.2"
42
69
  },
43
70
  "devDependencies": {
44
- "@eslint/js": "^9.17.0",
71
+ "@eslint/js": "^9.18.0",
72
+ "@playwright/test": "^1.49.1",
45
73
  "@sveltejs/adapter-auto": "^3.3.1",
46
- "@sveltejs/kit": "^2.15.1",
74
+ "@sveltejs/kit": "^2.15.2",
47
75
  "@sveltejs/package": "^2.3.7",
48
76
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
49
77
  "@testing-library/jest-dom": "^6.6.3",
50
78
  "@testing-library/svelte": "^5.2.6",
51
79
  "@testing-library/user-event": "^14.5.2",
52
- "@types/node": "^22.10.5",
53
- "@typescript-eslint/eslint-plugin": "^8.19.0",
54
- "@typescript-eslint/parser": "^8.19.0",
55
- "@vitest/coverage-v8": "^3.0.0-beta.3",
56
- "eslint": "^9.17.0",
57
- "eslint-config-prettier": "^9.1.0",
80
+ "@types/node": "^22.10.6",
81
+ "@typescript-eslint/eslint-plugin": "^8.20.0",
82
+ "@typescript-eslint/parser": "^8.20.0",
83
+ "@vitest/coverage-v8": "^3.0.0-beta.4",
84
+ "eslint": "^9.18.0",
85
+ "eslint-config-prettier": "^10.0.1",
58
86
  "eslint-plugin-svelte": "^2.46.1",
59
87
  "globals": "^15.14.0",
60
- "jsdom": "^25.0.1",
88
+ "jsdom": "^26.0.0",
61
89
  "prettier": "^3.4.2",
62
90
  "prettier-plugin-organize-imports": "^4.1.0",
63
- "prettier-plugin-svelte": "^3.3.2",
64
- "publint": "^0.2.12",
65
- "svelte": "^5.16.2",
66
- "svelte-check": "^4.1.1",
67
- "typescript": "^5.7.2",
91
+ "prettier-plugin-svelte": "^3.3.3",
92
+ "publint": "^0.3.2",
93
+ "svelte": "^5.18.0",
94
+ "svelte-check": "^4.1.4",
95
+ "typescript": "^5.7.3",
68
96
  "vite": "^6.0.7",
69
- "vitest": "^3.0.0-beta.3"
70
- },
71
- "keywords": [
72
- "svelte",
73
- "virtual-list",
74
- "virtual-scroll",
75
- "infinite-scroll",
76
- "performance",
77
- "ui-component",
78
- "svelte5",
79
- "dom-recycling",
80
- "large-lists",
81
- "scroll-optimization"
82
- ],
83
- "tags": [
84
- "svelte",
85
- "virtual-list",
86
- "virtual-scroll",
87
- "virtual-scroller",
88
- "infinite-scroll",
89
- "performance",
90
- "ui-component",
91
- "svelte5"
92
- ],
93
- "author": "Humanspeak, Inc.",
94
- "license": "MIT",
95
- "repository": {
96
- "type": "git",
97
- "url": "git+https://github.com/humanspeak/svelte-virtual-list.git"
97
+ "vitest": "^3.0.0-beta.4"
98
98
  },
99
- "homepage": "https://virtuallist.svelte.page",
100
- "bugs": {
101
- "url": "https://github.com/humanspeak/svelte-virtual-list/issues"
99
+ "peerDependencies": {
100
+ "svelte": "^5.0.0"
102
101
  },
103
- "funding": {
104
- "type": "github",
105
- "url": "https://github.com/sponsors/humanspeak"
102
+ "volta": {
103
+ "node": "22.12.0"
106
104
  },
107
105
  "publishConfig": {
108
106
  "access": "public"
@@ -110,9 +108,20 @@
110
108
  "overrides": {
111
109
  "@sveltejs/kit": {
112
110
  "cookie": "^0.7.0"
111
+ },
112
+ "jsdom": {
113
+ "cssstyle": "2.3.0",
114
+ "@asamuzakjp/css-color": "1.0.0"
113
115
  }
114
116
  },
115
- "volta": {
116
- "node": "22.12.0"
117
- }
117
+ "tags": [
118
+ "svelte",
119
+ "virtual-list",
120
+ "virtual-scroll",
121
+ "virtual-scroller",
122
+ "infinite-scroll",
123
+ "performance",
124
+ "ui-component",
125
+ "svelte5"
126
+ ]
118
127
  }