@pallasoft/ps-table-components 1.26.0 → 1.27.1

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.
Files changed (43) hide show
  1. package/dist/components/ps-data-table.d.ts +9 -1
  2. package/dist/components/ps-data-table.js +81 -12
  3. package/dist/components/ps-select-all-matching-banner.d.ts +10 -0
  4. package/dist/components/ps-select-all-matching-banner.js +10 -0
  5. package/dist/components/ps-table-pagination.d.ts +3 -1
  6. package/dist/components/ps-table-pagination.js +12 -4
  7. package/dist/constants/ps-server-rows-config.d.ts +8 -0
  8. package/dist/constants/ps-server-rows-config.js +11 -0
  9. package/dist/constants/ps-table-pagination-config.d.ts +3 -0
  10. package/dist/constants/ps-table-pagination-config.js +6 -0
  11. package/dist/esm/components/ps-data-table.js +82 -13
  12. package/dist/esm/components/ps-select-all-matching-banner.js +6 -0
  13. package/dist/esm/components/ps-table-pagination.js +12 -4
  14. package/dist/esm/constants/ps-server-rows-config.js +8 -0
  15. package/dist/esm/constants/ps-table-pagination-config.js +3 -0
  16. package/dist/esm/hooks/use-ps-server-rows.js +209 -0
  17. package/dist/esm/index.js +11 -0
  18. package/dist/esm/interfaces/ps-server-entry.js +1 -0
  19. package/dist/esm/interfaces/ps-server-page.js +1 -0
  20. package/dist/esm/interfaces/ps-server-rows-input.js +1 -0
  21. package/dist/esm/interfaces/ps-server-rows-result.js +1 -0
  22. package/dist/esm/interfaces/ps-table-cursor-paging.js +1 -0
  23. package/dist/esm/interfaces/ps-table-select-all-matching.js +1 -0
  24. package/dist/esm/services/ps-server-rows-service.js +36 -0
  25. package/dist/hooks/use-ps-server-rows.d.ts +3 -0
  26. package/dist/hooks/use-ps-server-rows.js +213 -0
  27. package/dist/index.d.ts +11 -0
  28. package/dist/index.js +11 -0
  29. package/dist/interfaces/ps-server-entry.d.ts +6 -0
  30. package/dist/interfaces/ps-server-entry.js +2 -0
  31. package/dist/interfaces/ps-server-page.d.ts +7 -0
  32. package/dist/interfaces/ps-server-page.js +2 -0
  33. package/dist/interfaces/ps-server-rows-input.d.ts +13 -0
  34. package/dist/interfaces/ps-server-rows-input.js +2 -0
  35. package/dist/interfaces/ps-server-rows-result.d.ts +18 -0
  36. package/dist/interfaces/ps-server-rows-result.js +2 -0
  37. package/dist/interfaces/ps-table-cursor-paging.d.ts +12 -0
  38. package/dist/interfaces/ps-table-cursor-paging.js +2 -0
  39. package/dist/interfaces/ps-table-select-all-matching.d.ts +7 -0
  40. package/dist/interfaces/ps-table-select-all-matching.js +2 -0
  41. package/dist/services/ps-server-rows-service.d.ts +11 -0
  42. package/dist/services/ps-server-rows-service.js +40 -0
  43. package/package.json +1 -1
@@ -0,0 +1,209 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { PsServerRowsConfig } from '../constants/ps-server-rows-config';
3
+ import { PsServerRowsService } from '../services/ps-server-rows-service';
4
+ const scheduleIdle = (run) => {
5
+ if (typeof window.requestIdleCallback === 'function') {
6
+ const handle = window.requestIdleCallback(run, { timeout: PsServerRowsConfig.idleTimeoutMs });
7
+ return () => window.cancelIdleCallback(handle);
8
+ }
9
+ const timer = window.setTimeout(run, PsServerRowsConfig.idleFallbackMs);
10
+ return () => window.clearTimeout(timer);
11
+ };
12
+ export const usePsServerRows = ({ columns, debounceMs = PsServerRowsConfig.debounceMs, getSearchText, initialPage = null, initialQuery, isPrefetching = true, load, pageSize, }) => {
13
+ const [query, setQuery] = useState(initialQuery);
14
+ const [search, setSearch] = useState(initialQuery.search);
15
+ const [reloadToken, setReloadToken] = useState(0);
16
+ const [isLoading, setIsLoading] = useState(initialPage === null);
17
+ const [error, setError] = useState(null);
18
+ const queryKey = PsServerRowsService.queryKey(query, search, pageSize);
19
+ const [navigation, setNavigation] = useState({
20
+ cursor: null,
21
+ pageNumber: 1,
22
+ queryKey,
23
+ });
24
+ const [entry, setEntry] = useState(() => initialPage === null
25
+ ? null
26
+ : {
27
+ key: PsServerRowsService.cacheKey(queryKey, null),
28
+ page: initialPage,
29
+ queryKey,
30
+ });
31
+ const cache = useRef(new Map());
32
+ const inflight = useRef(new Map());
33
+ const loadRef = useRef(load);
34
+ const limitRef = useRef(pageSize);
35
+ const queryRef = useRef(query);
36
+ const searchRef = useRef(search);
37
+ const isPrimed = useRef(false);
38
+ loadRef.current = load;
39
+ limitRef.current = pageSize;
40
+ queryRef.current = query;
41
+ searchRef.current = search;
42
+ if (initialPage !== null && !isPrimed.current) {
43
+ isPrimed.current = true;
44
+ PsServerRowsService.remember(cache.current, PsServerRowsService.cacheKey(queryKey, null), initialPage);
45
+ }
46
+ if (navigation.queryKey !== queryKey)
47
+ setNavigation({ cursor: null, pageNumber: 1, queryKey });
48
+ useEffect(() => {
49
+ if (query.search === search)
50
+ return;
51
+ const timer = window.setTimeout(() => setSearch(query.search), debounceMs);
52
+ return () => window.clearTimeout(timer);
53
+ }, [debounceMs, query.search, search]);
54
+ const fetchPage = useCallback((cursor, signal, key) => {
55
+ const pending = inflight.current.get(key);
56
+ if (pending !== undefined)
57
+ return pending;
58
+ const request = loadRef.current({ ...queryRef.current, search: searchRef.current }, cursor, signal, limitRef.current);
59
+ const tracked = request.then((page) => {
60
+ inflight.current.delete(key);
61
+ if (!signal.aborted)
62
+ PsServerRowsService.remember(cache.current, key, page);
63
+ return page;
64
+ }, (failure) => {
65
+ inflight.current.delete(key);
66
+ throw failure;
67
+ });
68
+ inflight.current.set(key, tracked);
69
+ return tracked;
70
+ }, []);
71
+ const generation = useRef(null);
72
+ useEffect(() => {
73
+ const controller = new AbortController();
74
+ generation.current = controller;
75
+ return () => {
76
+ controller.abort();
77
+ inflight.current.clear();
78
+ };
79
+ }, [queryKey, reloadToken]);
80
+ useEffect(() => {
81
+ const controller = generation.current;
82
+ if (controller === null)
83
+ return;
84
+ const key = PsServerRowsService.cacheKey(queryKey, navigation.cursor);
85
+ const cached = PsServerRowsService.recall(cache.current, key);
86
+ let isStale = false;
87
+ if (cached !== undefined) {
88
+ setEntry({ key, page: cached, queryKey });
89
+ setIsLoading(false);
90
+ setError(null);
91
+ return;
92
+ }
93
+ setIsLoading(true);
94
+ setError(null);
95
+ fetchPage(navigation.cursor, controller.signal, key).then((page) => {
96
+ if (isStale || controller.signal.aborted)
97
+ return;
98
+ setEntry({ key, page, queryKey });
99
+ setIsLoading(false);
100
+ }, (failure) => {
101
+ if (isStale || controller.signal.aborted)
102
+ return;
103
+ setError(failure);
104
+ setIsLoading(false);
105
+ });
106
+ return () => {
107
+ isStale = true;
108
+ };
109
+ }, [fetchPage, navigation.cursor, queryKey, reloadToken]);
110
+ const nextCursor = entry !== null && entry.queryKey === queryKey ? entry.page.nextCursor : null;
111
+ const prefetch = useCallback(() => {
112
+ const controller = generation.current;
113
+ if (controller === null || controller.signal.aborted || nextCursor === null)
114
+ return;
115
+ const key = PsServerRowsService.cacheKey(queryKey, nextCursor);
116
+ if (cache.current.has(key) || inflight.current.has(key))
117
+ return;
118
+ fetchPage(nextCursor, controller.signal, key).catch(() => undefined);
119
+ }, [fetchPage, nextCursor, queryKey]);
120
+ useEffect(() => {
121
+ if (!isPrefetching || isLoading || nextCursor === null)
122
+ return;
123
+ return scheduleIdle(prefetch);
124
+ }, [isLoading, isPrefetching, nextCursor, prefetch]);
125
+ const onQueryChange = useCallback((next) => setQuery(next), []);
126
+ const goNext = useCallback(() => {
127
+ if (nextCursor === null)
128
+ return;
129
+ setNavigation((current) => ({
130
+ ...current,
131
+ cursor: nextCursor,
132
+ pageNumber: current.pageNumber + 1,
133
+ }));
134
+ }, [nextCursor]);
135
+ const previousCursor = entry !== null && entry.queryKey === queryKey ? entry.page.prevCursor : null;
136
+ const goPrevious = useCallback(() => {
137
+ if (previousCursor === null)
138
+ return;
139
+ setNavigation((current) => ({
140
+ ...current,
141
+ cursor: previousCursor,
142
+ pageNumber: Math.max(current.pageNumber - 1, 1),
143
+ }));
144
+ }, [previousCursor]);
145
+ const reload = useCallback(() => {
146
+ cache.current.clear();
147
+ setNavigation((current) => ({ ...current, cursor: null, pageNumber: 1 }));
148
+ setReloadToken((current) => current + 1);
149
+ }, []);
150
+ const retry = useCallback(() => setReloadToken((current) => current + 1), []);
151
+ const updateRows = useCallback((update, totalDelta = 0) => {
152
+ setEntry((current) => {
153
+ if (current === null)
154
+ return current;
155
+ const page = {
156
+ ...current.page,
157
+ rows: update(current.page.rows),
158
+ total: Math.max(current.page.total + totalDelta, 0),
159
+ };
160
+ cache.current.clear();
161
+ PsServerRowsService.remember(cache.current, current.key, page);
162
+ return { ...current, page };
163
+ });
164
+ }, []);
165
+ const isCurrent = entry !== null &&
166
+ entry.queryKey === queryKey &&
167
+ entry.key === PsServerRowsService.cacheKey(queryKey, navigation.cursor);
168
+ const baseRows = useMemo(() => (entry === null ? [] : entry.page.rows), [entry]);
169
+ const isSameQuery = entry !== null && entry.queryKey === queryKey;
170
+ const rows = useMemo(() => isSameQuery ? baseRows : PsServerRowsService.preview(baseRows, columns, query, getSearchText), [baseRows, columns, getSearchText, isSameQuery, query]);
171
+ const total = entry === null ? 0 : entry.page.total;
172
+ const totalIsEstimate = entry === null ? false : entry.page.totalIsEstimate;
173
+ const isPending = isLoading || query.search !== search || !isCurrent;
174
+ const cursorPaging = useMemo(() => ({
175
+ hasNext: nextCursor !== null,
176
+ hasPrevious: previousCursor !== null,
177
+ isEstimate: totalIsEstimate,
178
+ isPending,
179
+ onNext: goNext,
180
+ onNextIntent: prefetch,
181
+ onPrevious: goPrevious,
182
+ pageNumber: navigation.pageNumber,
183
+ }), [
184
+ goNext,
185
+ goPrevious,
186
+ isPending,
187
+ navigation.pageNumber,
188
+ nextCursor,
189
+ prefetch,
190
+ previousCursor,
191
+ totalIsEstimate,
192
+ ]);
193
+ return {
194
+ cursorPaging,
195
+ error,
196
+ hasFailed: error !== null,
197
+ isPending,
198
+ onQueryChange,
199
+ pageCount: PsServerRowsService.pageCount(total, pageSize),
200
+ pageNumber: navigation.pageNumber,
201
+ query,
202
+ reload,
203
+ retry,
204
+ rows,
205
+ total,
206
+ totalIsEstimate,
207
+ updateRows,
208
+ };
209
+ };
package/dist/esm/index.js CHANGED
@@ -47,5 +47,16 @@ export * from './interfaces/table-reorder-nesting';
47
47
  export * from './interfaces/table-nesting-announcements';
48
48
  export * from './constants/ps-table-drop-placement';
49
49
  export * from './services/ps-table-reorder-service';
50
+ export * from './constants/ps-table-pagination-config';
50
51
  export * from './constants/ps-table-pagination-position';
51
52
  export * from './interfaces/table-drag-size';
53
+ export * from './components/ps-select-all-matching-banner';
54
+ export * from './constants/ps-server-rows-config';
55
+ export * from './hooks/use-ps-server-rows';
56
+ export * from './interfaces/ps-server-entry';
57
+ export * from './interfaces/ps-server-page';
58
+ export * from './interfaces/ps-server-rows-input';
59
+ export * from './interfaces/ps-server-rows-result';
60
+ export * from './interfaces/ps-table-cursor-paging';
61
+ export * from './interfaces/ps-table-select-all-matching';
62
+ export * from './services/ps-server-rows-service';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ import { PsServerRowsConfig } from '../constants/ps-server-rows-config';
2
+ import { PsTableQueryService } from './ps-table-query-service';
3
+ export class PsServerRowsService {
4
+ static queryKey(query, search, pageSize) {
5
+ const filters = Object.entries(query.filters)
6
+ .filter(([, value]) => PsTableQueryService.isActive(value))
7
+ .sort(([left], [right]) => left.localeCompare(right));
8
+ return JSON.stringify([filters, search.trim(), query.sort, pageSize]);
9
+ }
10
+ static cacheKey(queryKey, cursor) {
11
+ return `${queryKey}|${cursor === null ? '' : cursor}`;
12
+ }
13
+ static remember(cache, key, page) {
14
+ cache.delete(key);
15
+ cache.set(key, page);
16
+ for (const oldest of cache.keys()) {
17
+ if (cache.size <= PsServerRowsConfig.cacheSize)
18
+ return;
19
+ cache.delete(oldest);
20
+ }
21
+ }
22
+ static recall(cache, key) {
23
+ const page = cache.get(key);
24
+ if (page === undefined)
25
+ return undefined;
26
+ cache.delete(key);
27
+ cache.set(key, page);
28
+ return page;
29
+ }
30
+ static preview(rows, columns, query, getSearchText) {
31
+ return PsTableQueryService.apply(rows, columns, query.filters, query.search, getSearchText, query.sort);
32
+ }
33
+ static pageCount(total, pageSize) {
34
+ return Math.max(Math.ceil(total / pageSize), 1);
35
+ }
36
+ }
@@ -0,0 +1,3 @@
1
+ import type { PsServerRowsInput } from '../interfaces/ps-server-rows-input';
2
+ import type { PsServerRowsResult } from '../interfaces/ps-server-rows-result';
3
+ export declare const usePsServerRows: <RowData>({ columns, debounceMs, getSearchText, initialPage, initialQuery, isPrefetching, load, pageSize, }: PsServerRowsInput<RowData>) => PsServerRowsResult<RowData>;
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsServerRows = void 0;
4
+ const react_1 = require("react");
5
+ const ps_server_rows_config_1 = require("../constants/ps-server-rows-config");
6
+ const ps_server_rows_service_1 = require("../services/ps-server-rows-service");
7
+ const scheduleIdle = (run) => {
8
+ if (typeof window.requestIdleCallback === 'function') {
9
+ const handle = window.requestIdleCallback(run, { timeout: ps_server_rows_config_1.PsServerRowsConfig.idleTimeoutMs });
10
+ return () => window.cancelIdleCallback(handle);
11
+ }
12
+ const timer = window.setTimeout(run, ps_server_rows_config_1.PsServerRowsConfig.idleFallbackMs);
13
+ return () => window.clearTimeout(timer);
14
+ };
15
+ const usePsServerRows = ({ columns, debounceMs = ps_server_rows_config_1.PsServerRowsConfig.debounceMs, getSearchText, initialPage = null, initialQuery, isPrefetching = true, load, pageSize, }) => {
16
+ const [query, setQuery] = (0, react_1.useState)(initialQuery);
17
+ const [search, setSearch] = (0, react_1.useState)(initialQuery.search);
18
+ const [reloadToken, setReloadToken] = (0, react_1.useState)(0);
19
+ const [isLoading, setIsLoading] = (0, react_1.useState)(initialPage === null);
20
+ const [error, setError] = (0, react_1.useState)(null);
21
+ const queryKey = ps_server_rows_service_1.PsServerRowsService.queryKey(query, search, pageSize);
22
+ const [navigation, setNavigation] = (0, react_1.useState)({
23
+ cursor: null,
24
+ pageNumber: 1,
25
+ queryKey,
26
+ });
27
+ const [entry, setEntry] = (0, react_1.useState)(() => initialPage === null
28
+ ? null
29
+ : {
30
+ key: ps_server_rows_service_1.PsServerRowsService.cacheKey(queryKey, null),
31
+ page: initialPage,
32
+ queryKey,
33
+ });
34
+ const cache = (0, react_1.useRef)(new Map());
35
+ const inflight = (0, react_1.useRef)(new Map());
36
+ const loadRef = (0, react_1.useRef)(load);
37
+ const limitRef = (0, react_1.useRef)(pageSize);
38
+ const queryRef = (0, react_1.useRef)(query);
39
+ const searchRef = (0, react_1.useRef)(search);
40
+ const isPrimed = (0, react_1.useRef)(false);
41
+ loadRef.current = load;
42
+ limitRef.current = pageSize;
43
+ queryRef.current = query;
44
+ searchRef.current = search;
45
+ if (initialPage !== null && !isPrimed.current) {
46
+ isPrimed.current = true;
47
+ ps_server_rows_service_1.PsServerRowsService.remember(cache.current, ps_server_rows_service_1.PsServerRowsService.cacheKey(queryKey, null), initialPage);
48
+ }
49
+ if (navigation.queryKey !== queryKey)
50
+ setNavigation({ cursor: null, pageNumber: 1, queryKey });
51
+ (0, react_1.useEffect)(() => {
52
+ if (query.search === search)
53
+ return;
54
+ const timer = window.setTimeout(() => setSearch(query.search), debounceMs);
55
+ return () => window.clearTimeout(timer);
56
+ }, [debounceMs, query.search, search]);
57
+ const fetchPage = (0, react_1.useCallback)((cursor, signal, key) => {
58
+ const pending = inflight.current.get(key);
59
+ if (pending !== undefined)
60
+ return pending;
61
+ const request = loadRef.current({ ...queryRef.current, search: searchRef.current }, cursor, signal, limitRef.current);
62
+ const tracked = request.then((page) => {
63
+ inflight.current.delete(key);
64
+ if (!signal.aborted)
65
+ ps_server_rows_service_1.PsServerRowsService.remember(cache.current, key, page);
66
+ return page;
67
+ }, (failure) => {
68
+ inflight.current.delete(key);
69
+ throw failure;
70
+ });
71
+ inflight.current.set(key, tracked);
72
+ return tracked;
73
+ }, []);
74
+ const generation = (0, react_1.useRef)(null);
75
+ (0, react_1.useEffect)(() => {
76
+ const controller = new AbortController();
77
+ generation.current = controller;
78
+ return () => {
79
+ controller.abort();
80
+ inflight.current.clear();
81
+ };
82
+ }, [queryKey, reloadToken]);
83
+ (0, react_1.useEffect)(() => {
84
+ const controller = generation.current;
85
+ if (controller === null)
86
+ return;
87
+ const key = ps_server_rows_service_1.PsServerRowsService.cacheKey(queryKey, navigation.cursor);
88
+ const cached = ps_server_rows_service_1.PsServerRowsService.recall(cache.current, key);
89
+ let isStale = false;
90
+ if (cached !== undefined) {
91
+ setEntry({ key, page: cached, queryKey });
92
+ setIsLoading(false);
93
+ setError(null);
94
+ return;
95
+ }
96
+ setIsLoading(true);
97
+ setError(null);
98
+ fetchPage(navigation.cursor, controller.signal, key).then((page) => {
99
+ if (isStale || controller.signal.aborted)
100
+ return;
101
+ setEntry({ key, page, queryKey });
102
+ setIsLoading(false);
103
+ }, (failure) => {
104
+ if (isStale || controller.signal.aborted)
105
+ return;
106
+ setError(failure);
107
+ setIsLoading(false);
108
+ });
109
+ return () => {
110
+ isStale = true;
111
+ };
112
+ }, [fetchPage, navigation.cursor, queryKey, reloadToken]);
113
+ const nextCursor = entry !== null && entry.queryKey === queryKey ? entry.page.nextCursor : null;
114
+ const prefetch = (0, react_1.useCallback)(() => {
115
+ const controller = generation.current;
116
+ if (controller === null || controller.signal.aborted || nextCursor === null)
117
+ return;
118
+ const key = ps_server_rows_service_1.PsServerRowsService.cacheKey(queryKey, nextCursor);
119
+ if (cache.current.has(key) || inflight.current.has(key))
120
+ return;
121
+ fetchPage(nextCursor, controller.signal, key).catch(() => undefined);
122
+ }, [fetchPage, nextCursor, queryKey]);
123
+ (0, react_1.useEffect)(() => {
124
+ if (!isPrefetching || isLoading || nextCursor === null)
125
+ return;
126
+ return scheduleIdle(prefetch);
127
+ }, [isLoading, isPrefetching, nextCursor, prefetch]);
128
+ const onQueryChange = (0, react_1.useCallback)((next) => setQuery(next), []);
129
+ const goNext = (0, react_1.useCallback)(() => {
130
+ if (nextCursor === null)
131
+ return;
132
+ setNavigation((current) => ({
133
+ ...current,
134
+ cursor: nextCursor,
135
+ pageNumber: current.pageNumber + 1,
136
+ }));
137
+ }, [nextCursor]);
138
+ const previousCursor = entry !== null && entry.queryKey === queryKey ? entry.page.prevCursor : null;
139
+ const goPrevious = (0, react_1.useCallback)(() => {
140
+ if (previousCursor === null)
141
+ return;
142
+ setNavigation((current) => ({
143
+ ...current,
144
+ cursor: previousCursor,
145
+ pageNumber: Math.max(current.pageNumber - 1, 1),
146
+ }));
147
+ }, [previousCursor]);
148
+ const reload = (0, react_1.useCallback)(() => {
149
+ cache.current.clear();
150
+ setNavigation((current) => ({ ...current, cursor: null, pageNumber: 1 }));
151
+ setReloadToken((current) => current + 1);
152
+ }, []);
153
+ const retry = (0, react_1.useCallback)(() => setReloadToken((current) => current + 1), []);
154
+ const updateRows = (0, react_1.useCallback)((update, totalDelta = 0) => {
155
+ setEntry((current) => {
156
+ if (current === null)
157
+ return current;
158
+ const page = {
159
+ ...current.page,
160
+ rows: update(current.page.rows),
161
+ total: Math.max(current.page.total + totalDelta, 0),
162
+ };
163
+ cache.current.clear();
164
+ ps_server_rows_service_1.PsServerRowsService.remember(cache.current, current.key, page);
165
+ return { ...current, page };
166
+ });
167
+ }, []);
168
+ const isCurrent = entry !== null &&
169
+ entry.queryKey === queryKey &&
170
+ entry.key === ps_server_rows_service_1.PsServerRowsService.cacheKey(queryKey, navigation.cursor);
171
+ const baseRows = (0, react_1.useMemo)(() => (entry === null ? [] : entry.page.rows), [entry]);
172
+ const isSameQuery = entry !== null && entry.queryKey === queryKey;
173
+ const rows = (0, react_1.useMemo)(() => isSameQuery ? baseRows : ps_server_rows_service_1.PsServerRowsService.preview(baseRows, columns, query, getSearchText), [baseRows, columns, getSearchText, isSameQuery, query]);
174
+ const total = entry === null ? 0 : entry.page.total;
175
+ const totalIsEstimate = entry === null ? false : entry.page.totalIsEstimate;
176
+ const isPending = isLoading || query.search !== search || !isCurrent;
177
+ const cursorPaging = (0, react_1.useMemo)(() => ({
178
+ hasNext: nextCursor !== null,
179
+ hasPrevious: previousCursor !== null,
180
+ isEstimate: totalIsEstimate,
181
+ isPending,
182
+ onNext: goNext,
183
+ onNextIntent: prefetch,
184
+ onPrevious: goPrevious,
185
+ pageNumber: navigation.pageNumber,
186
+ }), [
187
+ goNext,
188
+ goPrevious,
189
+ isPending,
190
+ navigation.pageNumber,
191
+ nextCursor,
192
+ prefetch,
193
+ previousCursor,
194
+ totalIsEstimate,
195
+ ]);
196
+ return {
197
+ cursorPaging,
198
+ error,
199
+ hasFailed: error !== null,
200
+ isPending,
201
+ onQueryChange,
202
+ pageCount: ps_server_rows_service_1.PsServerRowsService.pageCount(total, pageSize),
203
+ pageNumber: navigation.pageNumber,
204
+ query,
205
+ reload,
206
+ retry,
207
+ rows,
208
+ total,
209
+ totalIsEstimate,
210
+ updateRows,
211
+ };
212
+ };
213
+ exports.usePsServerRows = usePsServerRows;
package/dist/index.d.ts CHANGED
@@ -47,5 +47,16 @@ export * from './interfaces/table-reorder-nesting';
47
47
  export * from './interfaces/table-nesting-announcements';
48
48
  export * from './constants/ps-table-drop-placement';
49
49
  export * from './services/ps-table-reorder-service';
50
+ export * from './constants/ps-table-pagination-config';
50
51
  export * from './constants/ps-table-pagination-position';
51
52
  export * from './interfaces/table-drag-size';
53
+ export * from './components/ps-select-all-matching-banner';
54
+ export * from './constants/ps-server-rows-config';
55
+ export * from './hooks/use-ps-server-rows';
56
+ export * from './interfaces/ps-server-entry';
57
+ export * from './interfaces/ps-server-page';
58
+ export * from './interfaces/ps-server-rows-input';
59
+ export * from './interfaces/ps-server-rows-result';
60
+ export * from './interfaces/ps-table-cursor-paging';
61
+ export * from './interfaces/ps-table-select-all-matching';
62
+ export * from './services/ps-server-rows-service';
package/dist/index.js CHANGED
@@ -63,5 +63,16 @@ __exportStar(require("./interfaces/table-reorder-nesting"), exports);
63
63
  __exportStar(require("./interfaces/table-nesting-announcements"), exports);
64
64
  __exportStar(require("./constants/ps-table-drop-placement"), exports);
65
65
  __exportStar(require("./services/ps-table-reorder-service"), exports);
66
+ __exportStar(require("./constants/ps-table-pagination-config"), exports);
66
67
  __exportStar(require("./constants/ps-table-pagination-position"), exports);
67
68
  __exportStar(require("./interfaces/table-drag-size"), exports);
69
+ __exportStar(require("./components/ps-select-all-matching-banner"), exports);
70
+ __exportStar(require("./constants/ps-server-rows-config"), exports);
71
+ __exportStar(require("./hooks/use-ps-server-rows"), exports);
72
+ __exportStar(require("./interfaces/ps-server-entry"), exports);
73
+ __exportStar(require("./interfaces/ps-server-page"), exports);
74
+ __exportStar(require("./interfaces/ps-server-rows-input"), exports);
75
+ __exportStar(require("./interfaces/ps-server-rows-result"), exports);
76
+ __exportStar(require("./interfaces/ps-table-cursor-paging"), exports);
77
+ __exportStar(require("./interfaces/ps-table-select-all-matching"), exports);
78
+ __exportStar(require("./services/ps-server-rows-service"), exports);
@@ -0,0 +1,6 @@
1
+ import type { PsServerPage } from './ps-server-page';
2
+ export interface PsServerEntry<RowData> {
3
+ key: string;
4
+ page: PsServerPage<RowData>;
5
+ queryKey: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ export interface PsServerPage<RowData> {
2
+ nextCursor: string | null;
3
+ prevCursor: string | null;
4
+ rows: RowData[];
5
+ total: number;
6
+ totalIsEstimate: boolean;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,13 @@
1
+ import type { PsServerPage } from './ps-server-page';
2
+ import type { PsTableColumn } from './table-column';
3
+ import type { PsTableQuery } from './table-query';
4
+ export interface PsServerRowsInput<RowData> {
5
+ columns: PsTableColumn<RowData>[];
6
+ debounceMs?: number;
7
+ getSearchText?: (row: RowData) => string;
8
+ initialPage?: PsServerPage<RowData> | null;
9
+ initialQuery: PsTableQuery;
10
+ isPrefetching?: boolean;
11
+ load: (query: PsTableQuery, cursor: string | null, signal: AbortSignal, limit: number) => Promise<PsServerPage<RowData>>;
12
+ pageSize: number;
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,18 @@
1
+ import type { PsTableCursorPaging } from './ps-table-cursor-paging';
2
+ import type { PsTableQuery } from './table-query';
3
+ export interface PsServerRowsResult<RowData> {
4
+ cursorPaging: PsTableCursorPaging;
5
+ error: unknown;
6
+ hasFailed: boolean;
7
+ isPending: boolean;
8
+ onQueryChange: (query: PsTableQuery) => void;
9
+ pageCount: number;
10
+ pageNumber: number;
11
+ query: PsTableQuery;
12
+ reload: () => void;
13
+ retry: () => void;
14
+ rows: RowData[];
15
+ total: number;
16
+ totalIsEstimate: boolean;
17
+ updateRows: (update: (rows: RowData[]) => RowData[], totalDelta?: number) => void;
18
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ export interface PsTableCursorPaging {
2
+ hasNext: boolean;
3
+ hasPrevious: boolean;
4
+ isEstimate: boolean;
5
+ isPending?: boolean;
6
+ onNext: () => void;
7
+ onNextIntent?: () => void;
8
+ onPageSizeChange?: (pageSize: number) => void;
9
+ onPrevious: () => void;
10
+ pageNumber: number;
11
+ pageSizeOptions?: number[];
12
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ export interface PsTableSelectAllMatching {
2
+ isActive: boolean;
3
+ noun?: string;
4
+ onActivate: () => void;
5
+ onDeactivate: () => void;
6
+ total: number;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,11 @@
1
+ import type { PsServerPage } from '../interfaces/ps-server-page';
2
+ import type { PsTableColumn } from '../interfaces/table-column';
3
+ import type { PsTableQuery } from '../interfaces/table-query';
4
+ export declare class PsServerRowsService {
5
+ static queryKey(query: PsTableQuery, search: string, pageSize: number): string;
6
+ static cacheKey(queryKey: string, cursor: string | null): string;
7
+ static remember<RowData>(cache: Map<string, PsServerPage<RowData>>, key: string, page: PsServerPage<RowData>): void;
8
+ static recall<RowData>(cache: Map<string, PsServerPage<RowData>>, key: string): PsServerPage<RowData> | undefined;
9
+ static preview<RowData>(rows: RowData[], columns: PsTableColumn<RowData>[], query: PsTableQuery, getSearchText: ((row: RowData) => string) | undefined): RowData[];
10
+ static pageCount(total: number, pageSize: number): number;
11
+ }