svelte-infinite 0.4.0 → 0.5.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 +19 -18
- package/dist/InfiniteLoader.svelte +3 -1
- package/dist/InfiniteLoader.svelte.d.ts +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/loaderState.svelte.d.ts +1 -3
- package/dist/loaderState.svelte.js +1 -2
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -14,17 +14,13 @@
|
|
|
14
14
|
|
|
15
15
|
> Svelte Infinite Loader designed and rebuilt specifically for use with **Svelte 5**
|
|
16
16
|
|
|
17
|
-
✨ Flexible
|
|
18
|
-
⏰ Infinite Loop Detection
|
|
19
|
-
📣 Control Loader State
|
|
20
|
-
🔎 `IntersectionObserver` based
|
|
21
|
-
🔥 Using Runes and Snippets
|
|
17
|
+
✨ Flexible
|
|
18
|
+
⏰ Infinite Loop Detection
|
|
19
|
+
📣 Control Loader State
|
|
20
|
+
🔎 `IntersectionObserver` based
|
|
21
|
+
🔥 Using Runes and Snippets
|
|
22
22
|
🧑🔧 **Demo**: [svelte-5-infinite.vercel.app](https://svelte-5-infinite.vercel.app)
|
|
23
23
|
|
|
24
|
-
Svelte 5 is still early days, but I couldn't find an infinite loader-type component that was maintained for the last few years of Svelte 4 even. So I had recently built this for a Svelte 5-based application I'm working on and was pretty happy with it, so I decided to share it with the world!
|
|
25
|
-
|
|
26
|
-
As Svelte 5 inevitably changes over the next weeks and months, I plan to keep this package updated and working with the latest available version of Svelte 5. Don't hesitate to open an issue if something has changed in the latest Svelte releases or you come across a bug!
|
|
27
|
-
|
|
28
24
|
## 🏗️ Getting Started
|
|
29
25
|
|
|
30
26
|
1. Install `svelte-infinite`
|
|
@@ -35,23 +31,24 @@ pnpm install svelte-infinite
|
|
|
35
31
|
yarn add svelte-infinite
|
|
36
32
|
```
|
|
37
33
|
|
|
38
|
-
2. Import both `InfiniteLoader` and `
|
|
34
|
+
2. Import both `InfiniteLoader` and `LoaderState` from `svelte-infinite`
|
|
39
35
|
|
|
40
36
|
```svelte
|
|
41
37
|
<script lang="ts">
|
|
42
|
-
import { InfiniteLoader,
|
|
38
|
+
import { InfiniteLoader, LoaderState } from "svelte-infinite"
|
|
43
39
|
|
|
40
|
+
const loaderState = new LoaderState()
|
|
44
41
|
const allItems = $state([])
|
|
45
42
|
|
|
46
43
|
const loadMore = async () => {
|
|
47
44
|
const res = fetch("...")
|
|
48
|
-
const data = await
|
|
45
|
+
const data = await res.json()
|
|
49
46
|
allItems.push(...data)
|
|
50
47
|
loaderState.loaded()
|
|
51
48
|
}
|
|
52
49
|
</script>
|
|
53
50
|
|
|
54
|
-
<InfiniteLoader triggerLoad={loadMore}>
|
|
51
|
+
<InfiniteLoader {loaderState} triggerLoad={loadMore}>
|
|
55
52
|
{#each allItems as user (user.id)}
|
|
56
53
|
<div>{user.name}</div>
|
|
57
54
|
{/each}
|
|
@@ -65,10 +62,10 @@ This is a more realistic example use-case which includes a paginated data endpoi
|
|
|
65
62
|
```svelte
|
|
66
63
|
<script lang="ts">
|
|
67
64
|
// +page.svelte
|
|
68
|
-
|
|
69
|
-
import { InfiniteLoader, loaderState } from "svelte-infinite"
|
|
65
|
+
import { InfiniteLoader, LoaderState } from "svelte-infinite"
|
|
70
66
|
import UserCard from "$components/UserCard.svelte"
|
|
71
67
|
|
|
68
|
+
const loaderState = new LoaderState()
|
|
72
69
|
const LOAD_LIMIT = 20
|
|
73
70
|
// Assume `$page.data.items` is the `+page.server.ts` server-side loaded
|
|
74
71
|
// and rendered initial 20 items of the list
|
|
@@ -132,8 +129,7 @@ This is a more realistic example use-case which includes a paginated data endpoi
|
|
|
132
129
|
<main class="container">
|
|
133
130
|
|
|
134
131
|
<!-- 2. Here you wrap your items with the InfiniteLoader component -->
|
|
135
|
-
|
|
136
|
-
<InfiniteLoader triggerLoad={loadMore}>
|
|
132
|
+
<InfiniteLoader {loaderState} triggerLoad={loadMore}>
|
|
137
133
|
{#each allItems as user (user.id)}
|
|
138
134
|
<UserCard {user} />
|
|
139
135
|
{/each}
|
|
@@ -157,7 +153,10 @@ This is a more realistic example use-case which includes a paginated data endpoi
|
|
|
157
153
|
|
|
158
154
|
This package consists of two parts, first the `InfiniteLoader` component which is a wrapper around your items. It will trigger whichever async function you've passed to the `triggerLoad` prop when the user scrolls to the bottom of the list.
|
|
159
155
|
|
|
160
|
-
Second, there is also a `
|
|
156
|
+
Second, there is also a `LoaderState` class which you should use to interact with the internal state of the loader. For example, if your `fetch` call errored, or you've reached the maximum number of items, etc. you can communicate that to the loader. The most basic usage example can be seen in the 'Getting Started' section above. A more complex example can be seen in the 'Example' section, and of course the application in `/src/routes/+page.svelte` in this repository also has a "real world" usage example.
|
|
157
|
+
|
|
158
|
+
> [!WARNING]
|
|
159
|
+
> As of `0.5.0` the `LoaderState` import is not an instance of the class, but the class itself. Meaning you'll need to instantiate it yourself with `new LoaderState()` per component instance. This gives the user more flexibility when trying to use multiple `svelte-infinite` instances per page, as well as resetting the state.
|
|
161
160
|
|
|
162
161
|
### `loaderState` Controller
|
|
163
162
|
|
|
@@ -174,6 +173,8 @@ The `loaderState` controller has 4 methods on it. You should call these at the a
|
|
|
174
173
|
|
|
175
174
|
### `InfiniteLoader` Props
|
|
176
175
|
|
|
176
|
+
- `loaderState: LoaderState`
|
|
177
|
+
- An instance of the `LoaderState` class.
|
|
177
178
|
- `triggerLoad: () => Promise<void>` - **required**
|
|
178
179
|
- The async function to call when we should attempt to load more data to show.
|
|
179
180
|
- `intersectionOptions: `[`IntersectionObserverInit`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options)` = { rootMargin: "0px 0px 200px 0px" }` - optional
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount, onDestroy, type Snippet } from "svelte"
|
|
3
|
-
import { STATUS,
|
|
3
|
+
import { STATUS, LoaderState } from "./loaderState.svelte"
|
|
4
4
|
|
|
5
5
|
type InfiniteLoaderProps = {
|
|
6
6
|
triggerLoad: () => Promise<void>
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
loopDetectionTimeout?: number
|
|
9
9
|
loopMaxCalls?: number
|
|
10
10
|
intersectionOptions?: Partial<IntersectionObserver>
|
|
11
|
+
loaderState: LoaderState
|
|
11
12
|
children: Snippet
|
|
12
13
|
loading?: Snippet
|
|
13
14
|
noResults?: Snippet
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
loopDetectionTimeout = 2000,
|
|
23
24
|
loopMaxCalls = 5,
|
|
24
25
|
intersectionOptions = {},
|
|
26
|
+
loaderState,
|
|
25
27
|
children,
|
|
26
28
|
loading: loadingSnippet,
|
|
27
29
|
noResults: noResultsSnippet,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type Snippet } from "svelte";
|
|
2
|
+
import { LoaderState } from "./loaderState.svelte";
|
|
2
3
|
declare const InfiniteLoader: import("svelte").Component<{
|
|
3
4
|
triggerLoad: () => Promise<void>;
|
|
4
5
|
loopTimeout?: number;
|
|
5
6
|
loopDetectionTimeout?: number;
|
|
6
7
|
loopMaxCalls?: number;
|
|
7
8
|
intersectionOptions?: Partial<IntersectionObserver>;
|
|
9
|
+
loaderState: LoaderState;
|
|
8
10
|
children: Snippet;
|
|
9
11
|
loading?: Snippet;
|
|
10
12
|
noResults?: Snippet;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import InfiniteLoader from "./InfiniteLoader.svelte";
|
|
2
|
-
import {
|
|
3
|
-
export { InfiniteLoader,
|
|
2
|
+
import { LoaderState } from "./loaderState.svelte";
|
|
3
|
+
export { InfiniteLoader, LoaderState };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import InfiniteLoader from "./InfiniteLoader.svelte";
|
|
2
|
-
import {
|
|
3
|
-
export { InfiniteLoader,
|
|
2
|
+
import { LoaderState } from "./loaderState.svelte";
|
|
3
|
+
export { InfiniteLoader, LoaderState };
|
|
@@ -4,7 +4,7 @@ export declare const STATUS: {
|
|
|
4
4
|
readonly COMPLETE: "COMPLETE";
|
|
5
5
|
readonly ERROR: "ERROR";
|
|
6
6
|
};
|
|
7
|
-
declare class LoaderState {
|
|
7
|
+
export declare class LoaderState {
|
|
8
8
|
isFirstLoad: boolean;
|
|
9
9
|
status: "READY" | "LOADING" | "COMPLETE" | "ERROR";
|
|
10
10
|
mounted: boolean;
|
|
@@ -13,5 +13,3 @@ declare class LoaderState {
|
|
|
13
13
|
reset: () => void;
|
|
14
14
|
error: () => void;
|
|
15
15
|
}
|
|
16
|
-
export declare const loaderState: LoaderState;
|
|
17
|
-
export {};
|
|
@@ -4,7 +4,7 @@ export const STATUS = {
|
|
|
4
4
|
COMPLETE: "COMPLETE",
|
|
5
5
|
ERROR: "ERROR"
|
|
6
6
|
};
|
|
7
|
-
class LoaderState {
|
|
7
|
+
export class LoaderState {
|
|
8
8
|
isFirstLoad = $state(true);
|
|
9
9
|
status = $state(STATUS.READY);
|
|
10
10
|
mounted = $state(false);
|
|
@@ -26,4 +26,3 @@ class LoaderState {
|
|
|
26
26
|
this.status = STATUS.ERROR;
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
export const loaderState = new LoaderState();
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"email": "yo@ndo.dev",
|
|
7
7
|
"url": "https://ndo.dev"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.5.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"homepage": "https://svelte-5-infinite.vercel.app",
|
|
12
12
|
"keywords": [
|
|
@@ -22,6 +22,18 @@
|
|
|
22
22
|
"bugs": {
|
|
23
23
|
"url": "https://github.com/ndom91/svelte-infinite/issues"
|
|
24
24
|
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "vite dev",
|
|
27
|
+
"build": "vite build && npm run package",
|
|
28
|
+
"preview": "vite preview",
|
|
29
|
+
"package": "svelte-kit sync && svelte-package && publint",
|
|
30
|
+
"prepublishOnly": "npm run package",
|
|
31
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
32
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
33
|
+
"test": "vitest",
|
|
34
|
+
"lint": "prettier --check . && eslint .",
|
|
35
|
+
"format": "prettier --write ."
|
|
36
|
+
},
|
|
25
37
|
"svelte": "./dist/index.js",
|
|
26
38
|
"types": "./dist/index.d.ts",
|
|
27
39
|
"type": "module",
|
|
@@ -65,15 +77,5 @@
|
|
|
65
77
|
"vite": "^5.4.11",
|
|
66
78
|
"vitest": "^2.1.5"
|
|
67
79
|
},
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
"build": "vite build && npm run package",
|
|
71
|
-
"preview": "vite preview",
|
|
72
|
-
"package": "svelte-kit sync && svelte-package && publint",
|
|
73
|
-
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
74
|
-
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
75
|
-
"test": "vitest",
|
|
76
|
-
"lint": "prettier --check . && eslint .",
|
|
77
|
-
"format": "prettier --write ."
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
+
"packageManager": "pnpm@9.0.6+sha256.0624e30eff866cdeb363b15061bdb7fd9425b17bc1bb42c22f5f4efdea21f6b3"
|
|
81
|
+
}
|