Skip to content

Commit 2266b2b

Browse files
atkgithub-actions[bot]
authored andcommitted
Format
1 parent 818dc25 commit 2266b2b

File tree

4 files changed

+80
-47
lines changed

4 files changed

+80
-47
lines changed

packages/pagination/README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,22 +119,18 @@ It is a common requirement to put multiple items on a single page, which exactly
119119
```tsx
120120
const segment = createSegment(items, limit, page);
121121

122-
return (
123-
<For each={segment()}>{(item) => <Item item={item} />}</For>
124-
)
122+
return <For each={segment()}>{item => <Item item={item} />}</For>;
125123
```
126124

127-
* `items` can be any array of items or an accessor with an array of items; even if the array increases in size, the segment will only change if the growth brings an actual change
128-
* `limit` is the limit for the number of items within a segment; this can be a number or an accessor containing a number
129-
* `page` is an accessor with the number or the segment page, starting with 1
130-
125+
- `items` can be any array of items or an accessor with an array of items; even if the array increases in size, the segment will only change if the growth brings an actual change
126+
- `limit` is the limit for the number of items within a segment; this can be a number or an accessor containing a number
127+
- `page` is an accessor with the number or the segment page, starting with 1
131128

132129
### Demo
133130

134131
You may view a working example here:
135132
https://primitives.solidjs.community/playground/pagination/
136133

137-
138134
## `createInfiniteScroll`
139135

140136
Combines [`createResource`](https://www.solidjs.com/docs/latest/api#createresource) with [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to provide an easy way to implement infinite scrolling.

packages/pagination/dev/index.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,45 @@ async function fetcher(page: number) {
1717
const PaginationSegmentationDemo: Component = () => {
1818
const items = Array.from({ length: 1000 }, (_, i) => i + 1);
1919
const [limit, setLimit] = createSignal(10);
20-
const [paginationProps, page, setPage] = createPagination(() => ({
20+
const [paginationProps, page, setPage] = createPagination(() => ({
2121
pages: Math.ceil(items.length / limit()),
2222
maxPages: 8,
2323
jumpPages: 10,
2424
}));
2525
const segment = createSegment(items, limit, page);
2626

2727
return (
28-
<div class="box-border flex w-1/2 mx-auto flex-col items-center justify-center space-y-4 bg-gray-800 p-24 text-white">
28+
<div class="mx-auto box-border flex w-1/2 flex-col items-center justify-center space-y-4 bg-gray-800 p-24 text-white">
2929
<h4 class="text-xl">Pagination & Segmentation:</h4>
30-
<For each={segment()}>{(i) => (<p class="border-1 w-full text-center">{i}</p>)}</For>
30+
<For each={segment()}>{i => <p class="border-1 w-full text-center">{i}</p>}</For>
3131
<nav class="flex flex-row">
32-
<For each={paginationProps()}>{props => <button class="whitespace-nowrap" {...props} />}</For>
32+
<For each={paginationProps()}>
33+
{props => <button class="whitespace-nowrap" {...props} />}
34+
</For>
3335
</nav>
3436
<div class="flex flex-row">
35-
<button onClick={() => setLimit(5)} disabled={limit() === 5}>5 items/page</button>
36-
<button onClick={() => setLimit(10)} disabled={limit() === 10}>10 items/page</button>
37-
<button onClick={() => setLimit(20)} disabled={limit() === 20}>20 items/page</button>
38-
<button onClick={() => setPage(Math.round(Math.random() * 1000 / limit() + 1))}>jump to random page</button>
37+
<button onClick={() => setLimit(5)} disabled={limit() === 5}>
38+
5 items/page
39+
</button>
40+
<button onClick={() => setLimit(10)} disabled={limit() === 10}>
41+
10 items/page
42+
</button>
43+
<button onClick={() => setLimit(20)} disabled={limit() === 20}>
44+
20 items/page
45+
</button>
46+
<button onClick={() => setPage(Math.round((Math.random() * 1000) / limit() + 1))}>
47+
jump to random page
48+
</button>
3949
</div>
4050
</div>
4151
);
42-
}
52+
};
4353

4454
const InfiniteScrollDemo = () => {
4555
const [pages, infiniteScrollLoader, { end }] = createInfiniteScroll(fetcher);
4656
infiniteScrollLoader;
4757
return (
48-
<div class="flex max-h-screen w-1/2 mx-auto mt-10 p-4 flex-col bg-gray-800 text-white">
58+
<div class="mx-auto mt-10 flex max-h-screen w-1/2 flex-col bg-gray-800 p-4 text-white">
4959
<div class="flex items-center justify-center">
5060
<h4 class="text-xl">Infinite Scrolling:</h4>
5161
</div>
@@ -61,7 +71,7 @@ const InfiniteScrollDemo = () => {
6171

6272
const App: Component = () => {
6373
return (
64-
<div class="flex flex-col min-h-screen w-full">
74+
<div class="flex min-h-screen w-full flex-col">
6575
<PaginationSegmentationDemo />
6676
<InfiniteScrollDemo />
6777
</div>

packages/pagination/src/index.ts

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,25 @@ import { isServer } from "solid-js/web";
3030
export const createSegment = <T>(
3131
items: MaybeAccessor<T[]>,
3232
limit: MaybeAccessor<number>,
33-
page: Accessor<number>
33+
page: Accessor<number>,
3434
): Accessor<T[]> => {
35-
let previousStart = NaN, previousEnd = NaN;
36-
return createMemo((previous) => {
35+
let previousStart = NaN,
36+
previousEnd = NaN;
37+
return createMemo(previous => {
3738
const currentItems = access(items);
3839
const start = (page() - 1) * access(limit);
3940
const end = Math.min(start + access(limit), currentItems.length);
40-
if (previous && (previous.length === 0 && end <= start || start === previousStart && end === previousEnd)) {
41+
if (
42+
previous &&
43+
((previous.length === 0 && end <= start) || (start === previousStart && end === previousEnd))
44+
) {
4145
return previous;
4246
}
4347
previousStart = start;
4448
previousEnd = end;
4549
return currentItems.slice(start, end);
4650
});
47-
}
51+
};
4852

4953
export type PaginationOptions = {
5054
/** the overall number of pages */
@@ -151,16 +155,18 @@ export const createPagination = (
151155
};
152156

153157
// normalize in case the number of pages changes, do not run the first time
154-
createComputed((previous) => {
158+
createComputed(previous => {
155159
opts().pages;
156160
return previous ? setPage(untrack(page)) : true;
157161
});
158162

159163
const goPage = (p: number | ((p: number) => number), ev: KeyboardEvent) => {
160164
setPage(p);
161-
if ('currentTarget' in ev)
162-
(ev.currentTarget as HTMLElement).parentNode?.querySelector<HTMLElement>('[aria-current="true"]')?.focus();
163-
}
165+
if ("currentTarget" in ev)
166+
(ev.currentTarget as HTMLElement).parentNode
167+
?.querySelector<HTMLElement>('[aria-current="true"]')
168+
?.focus();
169+
};
164170

165171
const onKeyUp = (pageNo: number, ev: KeyboardEvent) =>
166172
(
@@ -258,28 +264,40 @@ export const createPagination = (
258264
isServer
259265
? ({} as PaginationProps[number])
260266
: ({
261-
onClick: () => setPage(Math.max(1, page() - (opts().jumpPages || Infinity))),
262-
onKeyUp: (ev: KeyboardEvent) => onKeyUp(page() - (opts().jumpPages || Infinity), ev),
263-
} as unknown as PaginationProps[number]),
267+
onClick: () => setPage(Math.max(1, page() - (opts().jumpPages || Infinity))),
268+
onKeyUp: (ev: KeyboardEvent) => onKeyUp(page() - (opts().jumpPages || Infinity), ev),
269+
} as unknown as PaginationProps[number]),
264270
{
265-
disabled: { get: () => page() - (opts().jumpPages || Infinity) < 0, set: noop, enumerable: true },
271+
disabled: {
272+
get: () => page() - (opts().jumpPages || Infinity) < 0,
273+
set: noop,
274+
enumerable: true,
275+
},
266276
children: { get: () => `-${opts().jumpPages}`, set: noop, enumerable: true },
267277
page: { get: () => Math.max(1, page() - (opts().jumpPages || Infinity)), enumerable: false },
268-
}
278+
},
269279
);
270280
const jumpForth = Object.defineProperties(
271281
isServer
272282
? ({} as PaginationProps[number])
273283
: ({
274-
onClick: () => setPage(Math.min(opts().pages, page() + (opts().jumpPages || Infinity))),
275-
onKeyUp: (ev: KeyboardEvent) => onKeyUp(Math.min(opts().pages, page() + (opts().jumpPages || Infinity)), ev),
276-
} as unknown as PaginationProps[number]),
284+
onClick: () => setPage(Math.min(opts().pages, page() + (opts().jumpPages || Infinity))),
285+
onKeyUp: (ev: KeyboardEvent) =>
286+
onKeyUp(Math.min(opts().pages, page() + (opts().jumpPages || Infinity)), ev),
287+
} as unknown as PaginationProps[number]),
277288
{
278-
disabled: { get: () => page() + (opts().jumpPages || Infinity) > opts().pages, set: noop, enumerable: true },
289+
disabled: {
290+
get: () => page() + (opts().jumpPages || Infinity) > opts().pages,
291+
set: noop,
292+
enumerable: true,
293+
},
279294
children: { get: () => `+${opts().jumpPages}`, set: noop, enumerable: true },
280-
page: { get: () => Math.min(opts().pages, page() + (opts().jumpPages || Infinity)), enumerable: false },
281-
}
282-
)
295+
page: {
296+
get: () => Math.min(opts().pages, page() + (opts().jumpPages || Infinity)),
297+
enumerable: false,
298+
},
299+
},
300+
);
283301

284302
const start = createMemo(() =>
285303
Math.min(opts().pages - maxPages(), Math.max(1, page() - (maxPages() >> 1)) - 1),

packages/pagination/test/index.test.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { describe, test, expect } from "vitest";
22
import { createMemo, createRoot, createSignal } from "solid-js";
3-
import { createInfiniteScroll, createPagination, createSegment, PaginationOptions } from "../src/index.js";
3+
import {
4+
createInfiniteScroll,
5+
createPagination,
6+
createSegment,
7+
PaginationOptions,
8+
} from "../src/index.js";
49
import { testEffect } from "../../resource/test/index.test.js";
510

611
describe("createPagination", () => {
@@ -104,7 +109,7 @@ describe("createPagination", () => {
104109
createRoot(dispose => {
105110
const [paginationProps, page, setPage] = createPagination({
106111
pages: 10,
107-
maxPages: 5
112+
maxPages: 5,
108113
});
109114

110115
expect(page()).toBe(1);
@@ -114,15 +119,15 @@ describe("createPagination", () => {
114119
expect(page()).toBe(1);
115120

116121
dispose();
117-
})
122+
});
118123
});
119124

120125
test("setting page beyond the number pages will yield the last page", () => {
121126
createRoot(dispose => {
122127
const [paginationProps, page, setPage] = createPagination({
123128
pages: 10,
124129
maxPages: 5,
125-
initialPage: 10
130+
initialPage: 10,
126131
});
127132

128133
expect(page()).toBe(10);
@@ -137,7 +142,11 @@ describe("createPagination", () => {
137142

138143
test("lowering the number of pages will not make the page go beyond it", () => {
139144
createRoot(dispose => {
140-
const [options, setOptions] = createSignal<PaginationOptions>({ pages: 10, maxPages: 5, initialPage: 10 });
145+
const [options, setOptions] = createSignal<PaginationOptions>({
146+
pages: 10,
147+
maxPages: 5,
148+
initialPage: 10,
149+
});
141150
const [paginationProps, page, setPage] = createPagination(options);
142151

143152
expect(page()).toBe(10);
@@ -193,7 +202,7 @@ describe("createSegment", () => {
193202
const items = createMemo(() => Array.from({ length: length() }, (_, i) => i + 1));
194203
const [page, setPage] = createSignal(6);
195204
const segment = createSegment(items, 10, page);
196-
205+
197206
const seg1 = segment();
198207
expect(seg1).toEqual([51, 52, 53, 54, 55]);
199208
setLength(57);
@@ -203,7 +212,7 @@ describe("createSegment", () => {
203212

204213
dispose();
205214
});
206-
})
215+
});
207216
});
208217

209218
//@ts-ignore

0 commit comments

Comments
 (0)