svelte-tiny-virtual-list
Advanced tools
Comparing version
@@ -1,1 +0,1 @@ | ||
export { default as default } from './VirtualList.svelte'; | ||
export { default } from './VirtualList.svelte'; |
@@ -184,3 +184,3 @@ /* | ||
if (size == null || isNaN(size)) { | ||
if (size == null || Number.isNaN(size)) { | ||
throw Error(`Invalid size returned for index ${i} of value ${size}`); | ||
@@ -332,3 +332,3 @@ } | ||
findNearestItem(offset) { | ||
if (isNaN(offset)) { | ||
if (Number.isNaN(offset)) { | ||
throw Error(`Invalid offset ${offset} specified`); | ||
@@ -335,0 +335,0 @@ } |
// TODO: Refactor further | ||
export class ListProps { | ||
scrollToIndex = $state(-1); | ||
scrollToAlignment = $state(''); | ||
scrollOffset = $state(0); | ||
itemCount = $state(0); | ||
itemSize = $state(0); | ||
estimatedItemSize = $state(0); | ||
height = $state(400); | ||
width = $state(400); | ||
stickyIndices = $state([]); | ||
scrollToIndex = $state(-1); | ||
scrollToAlignment = $state(""); | ||
scrollOffset = $state(0); | ||
itemCount = $state(0); | ||
itemSize = $state(0); | ||
estimatedItemSize = $state(0); | ||
height = $state(400); | ||
width = $state(400); | ||
stickyIndices = $state([]); | ||
// Default values | ||
previousState = $state.raw({ | ||
scrollToIndex: -1, | ||
scrollToAlignment: 'start', | ||
scrollOffset: 0, | ||
itemCount: 0, | ||
itemSize: 0, | ||
estimatedItemSize: 50, | ||
height: 400, | ||
width: 400, | ||
stickyIndices: [] | ||
}); | ||
// Default values | ||
previousState = $state.raw({ | ||
scrollToIndex: -1, | ||
scrollToAlignment: "start", | ||
scrollOffset: 0, | ||
itemCount: 0, | ||
itemSize: 0, | ||
estimatedItemSize: 50, | ||
height: 400, | ||
width: 400, | ||
stickyIndices: [] | ||
}); | ||
get hasScrollOffsetChanged() { | ||
return this.previousState.scrollOffset !== this.scrollOffset; | ||
} | ||
get hasScrollOffsetChanged () { | ||
return this.previousState.scrollOffset !== this.scrollOffset; | ||
} | ||
get haveScrollPropsChanged() { | ||
return ( | ||
this.previousState.scrollToIndex !== this.scrollToIndex || | ||
this.previousState.scrollToAlignment !== this.scrollToAlignment | ||
); | ||
} | ||
get haveScrollPropsChanged () { | ||
return this.previousState.scrollToIndex !== this.scrollToIndex || | ||
this.previousState.scrollToAlignment !== this.scrollToAlignment; | ||
} | ||
get haveSizesChanged() { | ||
return ( | ||
this.previousState.itemCount !== this.itemCount || | ||
this.previousState.itemSize !== this.itemSize || | ||
this.previousState.estimatedItemSize !== this.estimatedItemSize | ||
); | ||
} | ||
get haveSizesChanged () { | ||
return this.previousState.itemCount !== this.itemCount || | ||
this.previousState.itemSize !== this.itemSize || | ||
this.previousState.estimatedItemSize !== this.estimatedItemSize; | ||
} | ||
get hasScrollIndexChanged() { | ||
return this.scrollToIndex > -1 && (this.haveScrollPropsChanged || this.haveSizesChanged); | ||
} | ||
get hasScrollIndexChanged () { | ||
return this.scrollToIndex > -1 && | ||
(this.haveScrollPropsChanged || this.haveSizesChanged); | ||
} | ||
get haveDimsOrStickyIndicesChanged() { | ||
return ( | ||
this.previousState.height !== this.height || | ||
this.previousState.width !== this.width || | ||
this.previousState.stickyIndices.toString() !== $state.snapshot(this.stickyIndices).toString() | ||
); | ||
} | ||
get haveDimsOrStickyIndicesChanged () { | ||
return this.previousState.height !== this.height || | ||
this.previousState.width !== this.width || | ||
this.previousState.stickyIndices.toString() !== $state.snapshot(this.stickyIndices).toString() | ||
} | ||
constructor( | ||
scrollToIndex = -1, | ||
scrollToAlignment = 'start', | ||
scrollOffset = 0, | ||
itemCount = 0, | ||
itemSize = 0, | ||
estimatedItemSize = 50, | ||
height = 400, | ||
width = 400, | ||
stickyIndices = [] | ||
) { | ||
this.scrollToIndex = scrollToIndex; | ||
this.scrollToAlignment = scrollToAlignment; | ||
this.scrollOffset = scrollOffset; | ||
this.itemCount = itemCount; | ||
this.itemSize = itemSize; | ||
this.estimatedItemSize = estimatedItemSize; | ||
this.height = height; | ||
this.width = width; | ||
this.stickyIndices = stickyIndices; | ||
} | ||
constructor ( | ||
scrollToIndex = -1, | ||
scrollToAlignment = "start", | ||
scrollOffset = 0, | ||
itemCount = 0, | ||
itemSize = 0, | ||
estimatedItemSize = 50, | ||
height = 400, | ||
width = 400, | ||
stickyIndices = [] | ||
) { | ||
this.scrollToIndex = scrollToIndex; | ||
this.scrollToAlignment = scrollToAlignment; | ||
this.scrollOffset = scrollOffset; | ||
this.itemCount = itemCount; | ||
this.itemSize = itemSize; | ||
this.estimatedItemSize = estimatedItemSize; | ||
this.height = height; | ||
this.width = width; | ||
this.stickyIndices = stickyIndices; | ||
} | ||
listen( | ||
scrollToIndex, | ||
scrollToAlignment, | ||
scrollOffset, | ||
itemCount, | ||
itemSize, | ||
estimatedItemSize, | ||
height, | ||
width, | ||
stickyIndices | ||
) { | ||
if (typeof scrollToIndex === 'number') this.scrollToIndex = scrollToIndex; | ||
listen ( | ||
scrollToIndex, | ||
scrollToAlignment, | ||
scrollOffset, | ||
itemCount, | ||
itemSize, | ||
estimatedItemSize, | ||
height, | ||
width, | ||
stickyIndices | ||
) { | ||
if (typeof scrollToIndex === "number") | ||
this.scrollToIndex = scrollToIndex; | ||
if (typeof scrollToAlignment === 'string') this.scrollToAlignment = scrollToAlignment; | ||
if (typeof scrollToAlignment === "string") | ||
this.scrollToAlignment = scrollToAlignment; | ||
if (typeof scrollOffset === 'number') this.scrollOffset = scrollOffset; | ||
if (typeof scrollOffset === "number") | ||
this.scrollOffset = scrollOffset; | ||
if (typeof itemCount === 'number') this.itemCount = itemCount; | ||
if (typeof itemCount === "number") | ||
this.itemCount = itemCount; | ||
if (typeof itemCount === 'number') this.itemCount = itemCount; | ||
if (typeof itemCount === "number") | ||
this.itemCount = itemCount; | ||
if (typeof itemSize === 'number' || typeof itemSize === 'function' || Array.isArray(itemSize)) | ||
this.itemSize = itemSize; | ||
if (typeof itemSize === "number" || typeof itemSize === "function" || Array.isArray(itemSize)) | ||
this.itemSize = itemSize; | ||
if (typeof estimatedItemSize === 'number') | ||
this.estimatedItemSize = estimatedItemSize || this.itemSize || 50; | ||
if (typeof estimatedItemSize === "number") | ||
this.estimatedItemSize = estimatedItemSize || this.itemSize || 50; | ||
if (typeof height === 'number') this.height = height; | ||
if (typeof height === "number") | ||
this.height = height; | ||
if (typeof width === 'number') this.width = width; | ||
if (typeof width === "number") | ||
this.width = width; | ||
if (Array.isArray(stickyIndices)) this.stickyIndices = stickyIndices; | ||
} | ||
if (Array.isArray(stickyIndices)) | ||
this.stickyIndices = stickyIndices; | ||
} | ||
update() { | ||
this.#updateRenderedStateSnapshot(); | ||
} | ||
update () { | ||
this.#updateRenderedStateSnapshot(); | ||
} | ||
#updateRenderedStateSnapshot () { | ||
this.previousState = { | ||
scrollToIndex: $state.snapshot(this.scrollToIndex), | ||
scrollToAlignment: $state.snapshot(this.scrollToAlignment), | ||
scrollOffset: $state.snapshot(this.scrollOffset), | ||
itemCount: $state.snapshot(this.itemCount), | ||
itemSize: $state.snapshot(this.itemSize), | ||
estimatedItemSize: $state.snapshot(this.estimatedItemSize) | ||
}; | ||
} | ||
#updateRenderedStateSnapshot() { | ||
this.previousState = { | ||
scrollToIndex: $state.snapshot(this.scrollToIndex), | ||
scrollToAlignment: $state.snapshot(this.scrollToAlignment), | ||
scrollOffset: $state.snapshot(this.scrollOffset), | ||
itemCount: $state.snapshot(this.itemCount), | ||
itemSize: $state.snapshot(this.itemSize), | ||
estimatedItemSize: $state.snapshot(this.estimatedItemSize) | ||
}; | ||
} | ||
} |
@@ -1,46 +0,47 @@ | ||
import { SCROLL_CHANGE_REASON } from "../constants.js"; | ||
import { SCROLL_CHANGE_REASON } from '../constants.js'; | ||
// TODO: Refactor further | ||
export class ListState { | ||
offset = $state(0); | ||
scrollChangeReason = $state(SCROLL_CHANGE_REASON.REQUESTED); | ||
offset = $state(0); | ||
scrollChangeReason = $state(SCROLL_CHANGE_REASON.REQUESTED); | ||
previousState = $state.raw({ | ||
offset: 0, | ||
scrollChangeReason: SCROLL_CHANGE_REASON.REQUESTED | ||
}); | ||
previousState = $state.raw({ | ||
offset: 0, | ||
scrollChangeReason: SCROLL_CHANGE_REASON.REQUESTED | ||
}); | ||
get doRefresh() { | ||
return ( | ||
this.offset !== this.previousState.offset || | ||
this.scrollChangeReason !== this.previousState.scrollChangeReason | ||
); | ||
} | ||
get doRefresh () { | ||
return this.offset !== this.previousState.offset || | ||
this.scrollChangeReason !== this.previousState.scrollChangeReason; | ||
}; | ||
get doScrollToOffset() { | ||
return ( | ||
this.offset !== this.previousState.offset && | ||
this.scrollChangeReason === SCROLL_CHANGE_REASON.REQUESTED | ||
); | ||
} | ||
get doScrollToOffset () { | ||
return this.offset !== this.previousState.offset && | ||
this.scrollChangeReason === SCROLL_CHANGE_REASON.REQUESTED; | ||
}; | ||
constructor(offset = 0) { | ||
this.offset = offset; | ||
} | ||
constructor (offset = 0) { | ||
this.offset = offset; | ||
} | ||
listen(offset, scrollChangeReason) { | ||
if (typeof offset === 'number') this.offset = offset; | ||
listen (offset, scrollChangeReason) { | ||
if (typeof offset === "number") | ||
this.offset = offset; | ||
if (typeof scrollChangeReason === 'number') this.scrollChangeReason = scrollChangeReason; | ||
} | ||
if (typeof scrollChangeReason === "number") | ||
this.scrollChangeReason = scrollChangeReason; | ||
} | ||
update() { | ||
this.#updateRenderedStateSnapshot(); | ||
} | ||
update () { | ||
this.#updateRenderedStateSnapshot(); | ||
} | ||
#updateRenderedStateSnapshot () { | ||
this.previousState = { | ||
offset: $state.snapshot(this.offset), | ||
scrollChangeReason: $state.snapshot(this.scrollChangeReason) | ||
}; | ||
} | ||
#updateRenderedStateSnapshot() { | ||
this.previousState = { | ||
offset: $state.snapshot(this.offset), | ||
scrollChangeReason: $state.snapshot(this.scrollChangeReason) | ||
}; | ||
} | ||
} |
MIT License | ||
=========== | ||
Copyright (c) 2024 Jonas Geiler | ||
Copyright (c) 2025 Jonas Geiler | ||
@@ -6,0 +6,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
{ | ||
"name": "svelte-tiny-virtual-list", | ||
"version": "4.0.0-rc.0", | ||
"version": "4.0.0-rc.1", | ||
"description": "A tiny but mighty list virtualization component for svelte, with zero dependencies 💪", | ||
"homepage": "https://github.com/jonasgeiler/svelte-tiny-virtual-list#readme", | ||
"homepage": "https://svelte-tiny-virtual-list.jonasgeiler.com", | ||
"bugs": "https://github.com/jonasgeiler/svelte-tiny-virtual-list/issues", | ||
"funding": "https://github.com/sponsors/jonasgeiler", | ||
"license": "MIT", | ||
@@ -13,2 +14,5 @@ "author": "Jonas Geiler <npm@jonasgeiler.com> (https://jonasgeiler.com)", | ||
"repository": "github:jonasgeiler/svelte-tiny-virtual-list", | ||
"engines": { | ||
"node": ">=20.17.0" | ||
}, | ||
"peerDependencies": { | ||
@@ -18,2 +22,5 @@ "svelte": "^5.0.0" | ||
"devDependencies": { | ||
"@biomejs/biome": "^2.0.6", | ||
"@eslint/compat": "^1.2.5", | ||
"@eslint/js": "^9.18.0", | ||
"@playwright/test": "^1.53.0", | ||
@@ -24,3 +31,3 @@ "@sveltejs/adapter-static": "^3.0.8", | ||
"@sveltejs/vite-plugin-svelte": "^5.1.0", | ||
"@types/eslint": "^9.6.1", | ||
"@vitest/browser": "^3.2.3", | ||
"beercss": "3.6.13", | ||
@@ -30,5 +37,8 @@ "eslint": "^9.29.0", | ||
"eslint-plugin-svelte": "^3.9.2", | ||
"globals": "^16.0.0", | ||
"lint-staged": "^16.1.2", | ||
"marked": "^15.0.12", | ||
"marked-base-url": "1.1.6", | ||
"marked-gfm-heading-id": "4.1.1", | ||
"playwright": "^1.53.0", | ||
"prettier": "^3.5.3", | ||
@@ -38,8 +48,7 @@ "prettier-plugin-svelte": "^3.4.0", | ||
"svelte": "^5.34.5", | ||
"svelte-check": "^4.2.1", | ||
"svelte-infinite-loading": "1.4.0", | ||
"tslib": "2.8.1", | ||
"typescript": "^5.8.3", | ||
"typescript": "^5.3.2", | ||
"vite": "^6.3.5", | ||
"vitest": "^3.2.4" | ||
"vitest": "^3.2.4", | ||
"vitest-browser-svelte": "^0.1.0" | ||
}, | ||
@@ -51,2 +60,5 @@ "files": [ | ||
], | ||
"sideEffects": [ | ||
"**/*.css" | ||
], | ||
"type": "module", | ||
@@ -61,5 +73,2 @@ "svelte": "./dist/index.js", | ||
}, | ||
"engines": { | ||
"node": ">=18.18.0" | ||
}, | ||
"keywords": [ | ||
@@ -78,13 +87,18 @@ "svelte", | ||
"dev": "vite dev", | ||
"build": "vite build && pnpm run package", | ||
"start": "pnpm run dev", | ||
"build": "vite build && pnpm run prepack", | ||
"preview": "vite preview", | ||
"package": "svelte-kit sync && svelte-package && publint", | ||
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json", | ||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch", | ||
"test": "pnpm run test:integration && pnpm run test:unit", | ||
"lint": "prettier --check . && eslint .", | ||
"format": "prettier --write .", | ||
"test:integration": "playwright test", | ||
"test:unit": "vitest" | ||
"check": "pnpm run '/^check:.*/'", | ||
"check:biome": "biome check", | ||
"check:eslint": "eslint .", | ||
"check:prettier": "prettier --check .", | ||
"check:vitest": "vitest run", | ||
"check:playwright": "playwright test", | ||
"fix": "pnpm run fix:biome && pnpm run fix:eslint && pnpm run fix:prettier", | ||
"fix:biome": "biome check --fix", | ||
"fix:eslint": "eslint --fix .", | ||
"fix:prettier": "prettier --write .", | ||
"fix-unsafe": "pnpm run fix-unsafe:biome", | ||
"fix-unsafe:biome": "biome check --fix --unsafe" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
<p align="center"><img src="https://raw.githubusercontent.com/jonasgeiler/svelte-tiny-virtual-list/main/static/logo.svg" alt="Logo" width="225"></p> | ||
<p align="center"><img src="./static/logo.svg" alt="Logo" width="225"></p> | ||
<h2 align="center">svelte-tiny-virtual-list</h2> | ||
@@ -14,3 +14,3 @@ <p align="center">A tiny but mighty list virtualization library, with zero dependencies 💪</p> | ||
<a href="#usage">Usage</a> • | ||
<a href="#examples--demo-outdated">Examples</a> • | ||
<a href="#examples--demo">Examples</a> • | ||
<a href="#license">License</a> | ||
@@ -111,19 +111,19 @@ </p> | ||
| Property | Type | Required? | Description | | ||
| ----------------- | ------------------------------------------------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| width | `number \| string` | ✓ | Width of List. This property will determine the number of rendered items when scrollDirection is `'horizontal'`. | | ||
| height | `number \| string` | ✓ | Height of List. This property will determine the number of rendered items when scrollDirection is `'vertical'`. | | ||
| itemCount | `number` | ✓ | The number of items you want to render | | ||
| itemSize | `number \| number[] \| (index: number) => number` | ✓ | Either a fixed height/width (depending on the scrollDirection), an array containing the heights of all the items in your list, or a function that returns the height of an item given its index: `(index: number): number` | | ||
| scrollDirection | `string` | | Whether the list should scroll vertically or horizontally. One of `'vertical'` (default) or `'horizontal'`. | | ||
| scrollOffset | `number` | | Can be used to control the scroll offset; Also useful for setting an initial scroll offset | | ||
| scrollToIndex | `number` | | Item index to scroll to (by forcefully scrolling if necessary) | | ||
| scrollToAlignment | `string` | | Used in combination with `scrollToIndex`, this prop controls the alignment of the scrolled to item. One of: `'start'`, `'center'`, `'end'` or `'auto'`. Use `'start'` to always align items to the top of the container and `'end'` to align them bottom. Use `'center`' to align them in the middle of the container. `'auto'` scrolls the least amount possible to ensure that the specified `scrollToIndex` item is fully visible. | | ||
| scrollToBehaviour | `string` | | Used in combination with `scrollToIndex`, this prop controls the behaviour of the scrolling. One of: `'auto'`, `'smooth'` or `'instant'` (default). | | ||
| stickyIndices | `number[]` | | An array of indexes (eg. `[0, 10, 25, 30]`) to make certain items in the list sticky (`position: sticky`) | | ||
| overscanCount | `number` | | Number of extra buffer items to render above/below the visible items. Tweaking this can help reduce scroll flickering on certain browsers/devices. | | ||
| estimatedItemSize | `number` | | Used to estimate the total size of the list before all of its items have actually been measured. The estimated total height is progressively adjusted as items are rendered. | | ||
| getKey | `(index: number) => any` | | Function that returns the key of an item in the list, which is used to uniquely identify an item. This is useful for dynamic data coming from a database or similar. By default, it's using the item's index. | ||
| onAfterScroll | `({ event: ScrollEvent, offset: number }) => any` | | Function that fires after handling the scroll event. Props: `event: ScrollEvent` - The original scroll event, `offset: number` - Either the value of `wrapper.scrollTop` or `wrapper.scrollLeft` | ||
| onListItemsUpdate | `({ start: number, end: number }) => any` | | Function that fires when the visible items are updated. Props: `start: number` - Index of the first visible item, `end: number` - Index of the last visible item. | | ||
| Property | Type | Required? | Description | | ||
| ----------------- | -------------------------------------------------- | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| width | `number \| string` | ✓ | Width of List. This property will determine the number of rendered items when scrollDirection is `'horizontal'`. | | ||
| height | `number \| string` | ✓ | Height of List. This property will determine the number of rendered items when scrollDirection is `'vertical'`. | | ||
| itemCount | `number` | ✓ | The number of items you want to render | | ||
| itemSize | `number \| number[] \| (index: number) => number` | ✓ | Either a fixed height/width (depending on the scrollDirection), an array containing the heights of all the items in your list, or a function that returns the height of an item given its index: `(index: number): number` | | ||
| scrollDirection | `string` | | Whether the list should scroll vertically or horizontally. One of `'vertical'` (default) or `'horizontal'`. | | ||
| scrollOffset | `number` | | Can be used to control the scroll offset; Also useful for setting an initial scroll offset | | ||
| scrollToIndex | `number` | | Item index to scroll to (by forcefully scrolling if necessary) | | ||
| scrollToAlignment | `string` | | Used in combination with `scrollToIndex`, this prop controls the alignment of the scrolled to item. One of: `'start'`, `'center'`, `'end'` or `'auto'`. Use `'start'` to always align items to the top of the container and `'end'` to align them bottom. Use `'center`' to align them in the middle of the container. `'auto'` scrolls the least amount possible to ensure that the specified `scrollToIndex` item is fully visible. | | ||
| scrollToBehaviour | `string` | | Used in combination with `scrollToIndex`, this prop controls the behaviour of the scrolling. One of: `'auto'`, `'smooth'` or `'instant'` (default). | | ||
| stickyIndices | `number[]` | | An array of indexes (eg. `[0, 10, 25, 30]`) to make certain items in the list sticky (`position: sticky`) | | ||
| overscanCount | `number` | | Number of extra buffer items to render above/below the visible items. Tweaking this can help reduce scroll flickering on certain browsers/devices. | | ||
| estimatedItemSize | `number` | | Used to estimate the total size of the list before all of its items have actually been measured. The estimated total height is progressively adjusted as items are rendered. | | ||
| getKey | `(index: number) => any` | | Function that returns the key of an item in the list, which is used to uniquely identify an item. This is useful for dynamic data coming from a database or similar. By default, it's using the item's index. | | ||
| onAfterScroll | `({ event: ScrollEvent, offset: number }) => void` | | Function that fires after handling the scroll event. Props: `event: ScrollEvent` - The original scroll event, `offset: number` - Either the value of `wrapper.scrollTop` or `wrapper.scrollLeft` | | ||
| onListItemsUpdate | `({ start: number, end: number }) => void` | | Function that fires when the visible items are updated. Props: `start: number` - Index of the first visible item, `end: number` - Index of the last visible item. | | ||
@@ -213,12 +213,12 @@ ### Snippets | ||
## Examples / Demo (OUTDATED) | ||
## Examples / Demo | ||
- **Basic setup** | ||
- [Elements of equal height](https://svelte.dev/playground/e3811b44f311461dbbc7c2df830cde68) | ||
- [Variable heights](https://svelte.dev/playground/93795c812f8d4541b6b942535b2ed855) | ||
- [Horizontal list](https://svelte.dev/playground/4cd8acdfc96843b68265a19451b1bf3d) | ||
- [Elements of equal height](https://svelte.dev/playground/59a98b2a0b53421e8fce3df8e66f5e3b) | ||
- [Variable heights](https://svelte.dev/playground/51952d1becb345c18154a0a61106617f) | ||
- [Horizontal list](https://svelte.dev/playground/d1ca5e2462cf46d5966c98c2cbf80be5) | ||
- **Controlled props** | ||
- [Scroll to index](https://svelte.dev/playground/bdf5ceb63f6e45f7bb14b90dbd2c11d9) | ||
- [Controlled scroll offset](https://svelte.dev/playground/68576a3919c44033a74416d4bc4fde7e) | ||
- [Hacker News using svelte-infinite-loading](https://svelte.dev/playground/2239cc4c861c41d18abbc858248f5a0d) | ||
- [Scroll to index](https://svelte.dev/playground/8610d15e77d34667a65d981b9327a7ad) | ||
- [Controlled scroll offset](https://svelte.dev/playground/39452c8fe30b4f618760a1198f6b9769) | ||
- [Hacker News using svelte-infinite-loading](https://svelte.dev/playground/6719ab725cfd440b9bd3cfa9b85d9d3a) | ||
@@ -225,0 +225,0 @@ ## License |
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
48662
028
21.74%789
-0.13%1
Infinity%