@youp-grid/core 0.1.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.
@@ -0,0 +1,24 @@
1
+ export function getInfiniteScrollTrigger(options) {
2
+ const rowCount = Math.max(0, Math.trunc(options.rowCount));
3
+ const lastVisibleRowIndex = normalizeLastVisibleRowIndex(options.lastVisibleRowIndex, rowCount);
4
+ const threshold = Math.max(0, Math.trunc(options.threshold ?? 20));
5
+ const remainingRows = Math.max(0, rowCount - 1 - lastVisibleRowIndex);
6
+ const hasMoreRows = options.hasMoreRows ?? true;
7
+ const loading = options.loading ?? false;
8
+ return {
9
+ shouldLoadMore: rowCount > 0 && hasMoreRows && !loading && remainingRows <= threshold,
10
+ rowCount,
11
+ lastVisibleRowIndex,
12
+ threshold,
13
+ remainingRows,
14
+ };
15
+ }
16
+ function normalizeLastVisibleRowIndex(lastVisibleRowIndex, rowCount) {
17
+ if (rowCount === 0) {
18
+ return -1;
19
+ }
20
+ return clamp(Math.trunc(lastVisibleRowIndex), -1, rowCount - 1);
21
+ }
22
+ function clamp(value, min, max) {
23
+ return Math.min(Math.max(value, min), max);
24
+ }
@@ -0,0 +1,5 @@
1
+ import type { PaginationState, RowNode } from "./types.ts";
2
+ export declare function applyPagination<TRow>(rows: readonly RowNode<TRow>[], pagination?: PaginationState): {
3
+ rows: RowNode<TRow>[];
4
+ pageCount?: number;
5
+ };
@@ -0,0 +1,16 @@
1
+ export function applyPagination(rows, pagination) {
2
+ if (!pagination) {
3
+ return { rows: [...rows] };
4
+ }
5
+ const pageSize = Math.max(1, pagination.pageSize);
6
+ const pageCount = Math.max(1, Math.ceil(rows.length / pageSize));
7
+ const pageIndex = clamp(pagination.pageIndex, 0, pageCount - 1);
8
+ const start = pageIndex * pageSize;
9
+ return {
10
+ rows: rows.slice(start, start + pageSize),
11
+ pageCount,
12
+ };
13
+ }
14
+ function clamp(value, min, max) {
15
+ return Math.min(Math.max(value, min), max);
16
+ }
@@ -0,0 +1,3 @@
1
+ import type { ResolvedColumnDef, RowDisplayNode, RowGroupNode, RowGroupingState, RowNode } from "./types.ts";
2
+ export declare function applyRowGrouping<TRow>(rows: readonly RowNode<TRow>[], columns: readonly ResolvedColumnDef<TRow>[], rowGrouping?: RowGroupingState): RowDisplayNode<TRow>[];
3
+ export declare function isRowGroupNode<TRow>(row: RowDisplayNode<TRow>): row is RowGroupNode;
@@ -0,0 +1,65 @@
1
+ import { getColumnById } from "./columns.js";
2
+ export function applyRowGrouping(rows, columns, rowGrouping) {
3
+ const groupColumns = (rowGrouping?.columnIds ?? [])
4
+ .map((columnId) => getColumnById(columns, columnId))
5
+ .filter((column) => Boolean(column));
6
+ if (groupColumns.length === 0) {
7
+ return [...rows];
8
+ }
9
+ const collapsedGroupIds = new Set(rowGrouping?.collapsedGroupIds ?? []);
10
+ const groupedRows = groupRows(rows, groupColumns, collapsedGroupIds, 0, []);
11
+ return groupedRows.map((row, index) => isRowGroupNode(row) ? { ...row, index } : row);
12
+ }
13
+ export function isRowGroupNode(row) {
14
+ return "type" in row && row.type === "group";
15
+ }
16
+ function groupRows(rows, columns, collapsedGroupIds, depth, path) {
17
+ const column = columns[depth];
18
+ if (!column) {
19
+ return [...rows];
20
+ }
21
+ const grouped = new Map();
22
+ for (const row of rows) {
23
+ const value = column.accessor(row.original);
24
+ const key = stringifyGroupValue(value);
25
+ const existing = grouped.get(key);
26
+ if (existing) {
27
+ existing.rows.push(row);
28
+ continue;
29
+ }
30
+ grouped.set(key, { value, rows: [row] });
31
+ }
32
+ const result = [];
33
+ for (const [key, group] of grouped) {
34
+ const groupId = createGroupId([...path, `${column.id}:${key}`]);
35
+ const expanded = !collapsedGroupIds.has(groupId);
36
+ result.push({
37
+ type: "group",
38
+ id: groupId,
39
+ groupId,
40
+ index: result.length,
41
+ depth,
42
+ columnId: column.id,
43
+ value: group.value,
44
+ label: stringifyGroupLabel(group.value),
45
+ rowCount: group.rows.length,
46
+ expanded,
47
+ });
48
+ if (expanded) {
49
+ result.push(...groupRows(group.rows, columns, collapsedGroupIds, depth + 1, [
50
+ ...path,
51
+ `${column.id}:${key}`,
52
+ ]));
53
+ }
54
+ }
55
+ return result;
56
+ }
57
+ function createGroupId(path) {
58
+ return `group:${path.join("/")}`;
59
+ }
60
+ function stringifyGroupValue(value) {
61
+ return encodeURIComponent(stringifyGroupLabel(value));
62
+ }
63
+ function stringifyGroupLabel(value) {
64
+ return String(value ?? "(empty)");
65
+ }
@@ -0,0 +1,2 @@
1
+ import type { BuildRowModelOptions, RowModel } from "./types.ts";
2
+ export declare function buildRowModel<TRow>(options: BuildRowModelOptions<TRow>): RowModel<TRow>;
@@ -0,0 +1,72 @@
1
+ import { applyColumnState, getVisibleColumns } from "./column-state.js";
2
+ import { applyAggregation } from "./aggregation.js";
3
+ import { normalizeColumns } from "./columns.js";
4
+ import { applyFilters } from "./filtering.js";
5
+ import { applyPagination } from "./pagination.js";
6
+ import { applyRowGrouping } from "./row-grouping.js";
7
+ import { applySorting } from "./sorting.js";
8
+ export function buildRowModel(options) {
9
+ const columns = applyColumnState(normalizeColumns(options.columns), options.state?.columns);
10
+ const visibleColumns = getVisibleColumns(columns);
11
+ const allRows = createRowNodes(options.rows, options.getRowId);
12
+ if (options.rowModelType === "server") {
13
+ return buildServerRowModel({
14
+ allRows,
15
+ columns,
16
+ visibleColumns,
17
+ state: options.state,
18
+ serverRowCount: options.serverRowCount,
19
+ serverFilteredRowCount: options.serverFilteredRowCount,
20
+ });
21
+ }
22
+ const filteredRows = applyFilters(allRows, columns, options.state?.filters);
23
+ const sortedRows = applySorting(filteredRows, columns, options.state?.sort);
24
+ const paginated = applyPagination(sortedRows, options.state?.pagination);
25
+ const aggregation = applyAggregation(filteredRows, columns, options.state?.aggregation);
26
+ const displayRows = applyRowGrouping(paginated.rows, columns, options.state?.rowGrouping);
27
+ return {
28
+ columns,
29
+ visibleColumns,
30
+ allRows,
31
+ filteredRows,
32
+ sortedRows,
33
+ visibleRows: paginated.rows,
34
+ displayRows,
35
+ aggregation,
36
+ totalRowCount: allRows.length,
37
+ filteredRowCount: filteredRows.length,
38
+ visibleRowCount: paginated.rows.length,
39
+ pageCount: paginated.pageCount,
40
+ };
41
+ }
42
+ function buildServerRowModel(context) {
43
+ const totalRowCount = context.serverRowCount ?? context.allRows.length;
44
+ const filteredRowCount = context.serverFilteredRowCount ?? totalRowCount;
45
+ return {
46
+ columns: context.columns,
47
+ visibleColumns: context.visibleColumns,
48
+ allRows: context.allRows,
49
+ filteredRows: context.allRows,
50
+ sortedRows: context.allRows,
51
+ visibleRows: context.allRows,
52
+ displayRows: applyRowGrouping(context.allRows, context.columns, context.state?.rowGrouping),
53
+ aggregation: applyAggregation(context.allRows, context.columns, context.state?.aggregation),
54
+ totalRowCount,
55
+ filteredRowCount,
56
+ visibleRowCount: context.allRows.length,
57
+ pageCount: getServerPageCount(filteredRowCount, context.state?.pagination),
58
+ };
59
+ }
60
+ function getServerPageCount(rowCount, pagination) {
61
+ if (!pagination) {
62
+ return undefined;
63
+ }
64
+ return Math.ceil(Math.max(0, rowCount) / Math.max(1, pagination.pageSize));
65
+ }
66
+ function createRowNodes(rows, getRowId) {
67
+ return rows.map((row, index) => ({
68
+ id: getRowId ? getRowId(row, index) : index,
69
+ index,
70
+ original: row,
71
+ }));
72
+ }
@@ -0,0 +1,5 @@
1
+ import type { GridRowId, GridState } from "./types.ts";
2
+ export declare function setRowSelected(state: GridState, rowId: GridRowId, selected: boolean): GridState;
3
+ export declare function toggleRowSelected(state: GridState, rowId: GridRowId): GridState;
4
+ export declare function setSelectedRows(state: GridState, rowIds: readonly GridRowId[]): GridState;
5
+ export declare function clearSelection(state: GridState): GridState;
@@ -0,0 +1,28 @@
1
+ export function setRowSelected(state, rowId, selected) {
2
+ const selectedRowIds = new Set(state.selectedRowIds ?? []);
3
+ if (selected) {
4
+ selectedRowIds.add(rowId);
5
+ }
6
+ else {
7
+ selectedRowIds.delete(rowId);
8
+ }
9
+ return {
10
+ ...state,
11
+ selectedRowIds: [...selectedRowIds],
12
+ };
13
+ }
14
+ export function toggleRowSelected(state, rowId) {
15
+ return setRowSelected(state, rowId, !(state.selectedRowIds ?? []).includes(rowId));
16
+ }
17
+ export function setSelectedRows(state, rowIds) {
18
+ return {
19
+ ...state,
20
+ selectedRowIds: [...new Set(rowIds)],
21
+ };
22
+ }
23
+ export function clearSelection(state) {
24
+ return {
25
+ ...state,
26
+ selectedRowIds: [],
27
+ };
28
+ }
@@ -0,0 +1,2 @@
1
+ import type { ResolvedColumnDef, RowNode, SortRule } from "./types.ts";
2
+ export declare function applySorting<TRow>(rows: readonly RowNode<TRow>[], columns: readonly ResolvedColumnDef<TRow>[], sortRules?: readonly SortRule[]): RowNode<TRow>[];
@@ -0,0 +1,49 @@
1
+ import { getColumnById } from "./columns.js";
2
+ export function applySorting(rows, columns, sortRules = []) {
3
+ const activeRules = sortRules.filter((rule) => rule.direction);
4
+ if (activeRules.length === 0) {
5
+ return [...rows];
6
+ }
7
+ return [...rows].sort((left, right) => {
8
+ for (const rule of activeRules) {
9
+ const column = getColumnById(columns, rule.columnId);
10
+ if (!column) {
11
+ continue;
12
+ }
13
+ const result = compareRows(left, right, column);
14
+ if (result !== 0) {
15
+ return rule.direction === "desc" ? -result : result;
16
+ }
17
+ }
18
+ return left.index - right.index;
19
+ });
20
+ }
21
+ function compareRows(left, right, column) {
22
+ const leftValue = column.accessor(left.original);
23
+ const rightValue = column.accessor(right.original);
24
+ if (column.comparator) {
25
+ return column.comparator(leftValue, rightValue, left.original, right.original);
26
+ }
27
+ return comparePrimitive(leftValue, rightValue);
28
+ }
29
+ function comparePrimitive(left, right) {
30
+ if (left == null && right == null) {
31
+ return 0;
32
+ }
33
+ if (left == null) {
34
+ return -1;
35
+ }
36
+ if (right == null) {
37
+ return 1;
38
+ }
39
+ if (typeof left === "number" && typeof right === "number") {
40
+ return left - right;
41
+ }
42
+ if (left instanceof Date && right instanceof Date) {
43
+ return left.getTime() - right.getTime();
44
+ }
45
+ return String(left).localeCompare(String(right), undefined, {
46
+ numeric: true,
47
+ sensitivity: "base",
48
+ });
49
+ }
@@ -0,0 +1,28 @@
1
+ import type { AggregationRule, CursorPaginationState, FilterRule, GridState, PaginationState, RemoteCacheState, RowGroupingState, SortDirection } from "./types.ts";
2
+ export declare function createGridState(state?: GridState): GridState;
3
+ export declare function toggleSort(state: GridState, columnId: string, options?: {
4
+ multi?: boolean;
5
+ cycle?: readonly (SortDirection | undefined)[];
6
+ }): GridState;
7
+ export declare function setSort(state: GridState, columnId: string, direction: SortDirection, options?: {
8
+ multi?: boolean;
9
+ }): GridState;
10
+ export declare function clearSort(state: GridState, columnId: string): GridState;
11
+ export declare function setFilter(state: GridState, filter: FilterRule): GridState;
12
+ export declare function clearFilter(state: GridState, columnId: string): GridState;
13
+ export declare function setPagination(state: GridState, pagination: PaginationState): GridState;
14
+ export declare function setCursorPagination(state: GridState, cursorPagination: CursorPaginationState): GridState;
15
+ export declare function setCursorPage(state: GridState, cursor: string | undefined): GridState;
16
+ export declare function setCursorPageSize(state: GridState, pageSize: number): GridState;
17
+ export declare function setAggregation(state: GridState, aggregation: readonly AggregationRule[]): GridState;
18
+ export declare function setRowGrouping(state: GridState, rowGrouping: RowGroupingState | undefined): GridState;
19
+ export declare function toggleRowGroupExpanded(state: GridState, groupId: string): GridState;
20
+ export declare function startRemoteRequest(state: GridState, requestId: string): GridState;
21
+ export declare function finishRemoteRequest(state: GridState, requestId: string): GridState;
22
+ export declare function failRemoteRequest(state: GridState, requestId: string, error?: string): GridState;
23
+ export declare function cancelRemoteRequest(state: GridState, requestId?: string | undefined): GridState;
24
+ export declare function isActiveRemoteRequest(state: GridState, requestId: string): boolean;
25
+ export declare function createRemoteCacheKey(state: GridState): string;
26
+ export declare function setRemoteCache(state: GridState, remoteCache: RemoteCacheState): GridState;
27
+ export declare function invalidateRemoteCache(state: GridState, key?: string): GridState;
28
+ export declare function acknowledgeRemoteCache(state: GridState, key?: string): GridState;
package/dist/state.js ADDED
@@ -0,0 +1,295 @@
1
+ export function createGridState(state = {}) {
2
+ return {
3
+ columns: state.columns ? [...state.columns] : [],
4
+ sort: state.sort ? [...state.sort] : [],
5
+ filters: state.filters ? [...state.filters] : [],
6
+ aggregation: state.aggregation ? [...state.aggregation] : [],
7
+ rowGrouping: state.rowGrouping
8
+ ? {
9
+ columnIds: [...state.rowGrouping.columnIds],
10
+ collapsedGroupIds: state.rowGrouping.collapsedGroupIds
11
+ ? [...state.rowGrouping.collapsedGroupIds]
12
+ : undefined,
13
+ }
14
+ : undefined,
15
+ pagination: state.pagination ? { ...state.pagination } : undefined,
16
+ cursorPagination: state.cursorPagination ? { ...state.cursorPagination } : undefined,
17
+ remoteRequest: state.remoteRequest ? { ...state.remoteRequest } : undefined,
18
+ remoteCache: state.remoteCache
19
+ ? {
20
+ ...state.remoteCache,
21
+ invalidatedKeys: state.remoteCache.invalidatedKeys
22
+ ? [...state.remoteCache.invalidatedKeys]
23
+ : undefined,
24
+ }
25
+ : undefined,
26
+ selectedRowIds: state.selectedRowIds ? [...state.selectedRowIds] : [],
27
+ };
28
+ }
29
+ export function toggleSort(state, columnId, options = {}) {
30
+ const cycle = options.cycle ?? ["asc", "desc", undefined];
31
+ const currentRules = state.sort ?? [];
32
+ const currentRule = currentRules.find((rule) => rule.columnId === columnId);
33
+ const currentIndex = cycle.findIndex((direction) => direction === currentRule?.direction);
34
+ const nextDirection = cycle[(currentIndex + 1) % cycle.length];
35
+ const remainingRules = options.multi
36
+ ? currentRules.filter((rule) => rule.columnId !== columnId)
37
+ : [];
38
+ return {
39
+ ...state,
40
+ sort: nextDirection
41
+ ? [...remainingRules, { columnId, direction: nextDirection }]
42
+ : remainingRules,
43
+ remoteCache: markRemoteCacheStale(state.remoteCache),
44
+ };
45
+ }
46
+ export function setSort(state, columnId, direction, options = {}) {
47
+ const currentRules = state.sort ?? [];
48
+ const remainingRules = options.multi
49
+ ? currentRules.filter((rule) => rule.columnId !== columnId)
50
+ : [];
51
+ return {
52
+ ...state,
53
+ sort: [...remainingRules, { columnId, direction }],
54
+ remoteCache: markRemoteCacheStale(state.remoteCache),
55
+ };
56
+ }
57
+ export function clearSort(state, columnId) {
58
+ return {
59
+ ...state,
60
+ sort: (state.sort ?? []).filter((rule) => rule.columnId !== columnId),
61
+ remoteCache: markRemoteCacheStale(state.remoteCache),
62
+ };
63
+ }
64
+ export function setFilter(state, filter) {
65
+ const filters = (state.filters ?? []).filter((item) => item.columnId !== filter.columnId);
66
+ return {
67
+ ...state,
68
+ filters: [...filters, filter],
69
+ pagination: resetPageIndex(state.pagination),
70
+ cursorPagination: resetCursor(state.cursorPagination),
71
+ remoteCache: markRemoteCacheStale(state.remoteCache),
72
+ };
73
+ }
74
+ export function clearFilter(state, columnId) {
75
+ return {
76
+ ...state,
77
+ filters: (state.filters ?? []).filter((filter) => filter.columnId !== columnId),
78
+ pagination: resetPageIndex(state.pagination),
79
+ cursorPagination: resetCursor(state.cursorPagination),
80
+ remoteCache: markRemoteCacheStale(state.remoteCache),
81
+ };
82
+ }
83
+ export function setPagination(state, pagination) {
84
+ return {
85
+ ...state,
86
+ pagination: {
87
+ pageIndex: Math.max(0, pagination.pageIndex),
88
+ pageSize: Math.max(1, pagination.pageSize),
89
+ },
90
+ remoteCache: markRemoteCacheStale(state.remoteCache),
91
+ };
92
+ }
93
+ export function setCursorPagination(state, cursorPagination) {
94
+ return {
95
+ ...state,
96
+ cursorPagination: {
97
+ ...cursorPagination,
98
+ pageSize: Math.max(1, cursorPagination.pageSize),
99
+ },
100
+ remoteCache: markRemoteCacheStale(state.remoteCache),
101
+ };
102
+ }
103
+ export function setCursorPage(state, cursor) {
104
+ const cursorPagination = state.cursorPagination ?? {
105
+ pageSize: state.pagination?.pageSize ?? 50,
106
+ };
107
+ return setCursorPagination(state, {
108
+ ...cursorPagination,
109
+ cursor,
110
+ });
111
+ }
112
+ export function setCursorPageSize(state, pageSize) {
113
+ return setCursorPagination(state, {
114
+ ...state.cursorPagination,
115
+ cursor: undefined,
116
+ pageSize,
117
+ });
118
+ }
119
+ export function setAggregation(state, aggregation) {
120
+ return {
121
+ ...state,
122
+ aggregation: [...aggregation],
123
+ remoteCache: markRemoteCacheStale(state.remoteCache),
124
+ };
125
+ }
126
+ export function setRowGrouping(state, rowGrouping) {
127
+ return {
128
+ ...state,
129
+ rowGrouping: rowGrouping
130
+ ? {
131
+ columnIds: [...rowGrouping.columnIds],
132
+ collapsedGroupIds: rowGrouping.collapsedGroupIds
133
+ ? [...rowGrouping.collapsedGroupIds]
134
+ : undefined,
135
+ }
136
+ : undefined,
137
+ remoteCache: markRemoteCacheStale(state.remoteCache),
138
+ };
139
+ }
140
+ export function toggleRowGroupExpanded(state, groupId) {
141
+ const rowGrouping = state.rowGrouping;
142
+ if (!rowGrouping) {
143
+ return state;
144
+ }
145
+ const collapsedGroupIds = new Set(rowGrouping.collapsedGroupIds ?? []);
146
+ if (collapsedGroupIds.has(groupId)) {
147
+ collapsedGroupIds.delete(groupId);
148
+ }
149
+ else {
150
+ collapsedGroupIds.add(groupId);
151
+ }
152
+ return {
153
+ ...state,
154
+ rowGrouping: {
155
+ ...rowGrouping,
156
+ columnIds: [...rowGrouping.columnIds],
157
+ collapsedGroupIds: collapsedGroupIds.size > 0 ? [...collapsedGroupIds] : undefined,
158
+ },
159
+ };
160
+ }
161
+ export function startRemoteRequest(state, requestId) {
162
+ return {
163
+ ...state,
164
+ remoteRequest: {
165
+ requestId,
166
+ sequence: (state.remoteRequest?.sequence ?? 0) + 1,
167
+ status: "loading",
168
+ },
169
+ };
170
+ }
171
+ export function finishRemoteRequest(state, requestId) {
172
+ if (!isActiveRemoteRequest(state, requestId)) {
173
+ return state;
174
+ }
175
+ return setRemoteRequestStatus(state, {
176
+ requestId,
177
+ sequence: state.remoteRequest?.sequence ?? 0,
178
+ status: "success",
179
+ });
180
+ }
181
+ export function failRemoteRequest(state, requestId, error) {
182
+ if (!isActiveRemoteRequest(state, requestId)) {
183
+ return state;
184
+ }
185
+ return setRemoteRequestStatus(state, {
186
+ requestId,
187
+ sequence: state.remoteRequest?.sequence ?? 0,
188
+ status: "error",
189
+ error,
190
+ });
191
+ }
192
+ export function cancelRemoteRequest(state, requestId = state.remoteRequest?.requestId) {
193
+ if (!requestId || !isActiveRemoteRequest(state, requestId)) {
194
+ return state;
195
+ }
196
+ return setRemoteRequestStatus(state, {
197
+ requestId,
198
+ sequence: state.remoteRequest?.sequence ?? 0,
199
+ status: "cancelled",
200
+ });
201
+ }
202
+ export function isActiveRemoteRequest(state, requestId) {
203
+ return state.remoteRequest?.requestId === requestId && state.remoteRequest.status === "loading";
204
+ }
205
+ export function createRemoteCacheKey(state) {
206
+ return JSON.stringify({
207
+ sort: state.sort ?? [],
208
+ filters: state.filters ?? [],
209
+ aggregation: state.aggregation ?? [],
210
+ rowGrouping: state.rowGrouping,
211
+ pagination: state.pagination,
212
+ cursorPagination: state.cursorPagination,
213
+ });
214
+ }
215
+ export function setRemoteCache(state, remoteCache) {
216
+ return {
217
+ ...state,
218
+ remoteCache: normalizeRemoteCache(remoteCache),
219
+ };
220
+ }
221
+ export function invalidateRemoteCache(state, key = state.remoteCache?.key ?? createRemoteCacheKey(state)) {
222
+ const remoteCache = normalizeRemoteCache(state.remoteCache);
223
+ return {
224
+ ...state,
225
+ remoteCache: {
226
+ ...remoteCache,
227
+ key,
228
+ version: remoteCache.version + 1,
229
+ stale: true,
230
+ invalidatedKeys: addUniqueKey(remoteCache.invalidatedKeys, key),
231
+ },
232
+ };
233
+ }
234
+ export function acknowledgeRemoteCache(state, key = state.remoteCache?.key ?? createRemoteCacheKey(state)) {
235
+ const remoteCache = normalizeRemoteCache(state.remoteCache);
236
+ const invalidatedKeys = (remoteCache.invalidatedKeys ?? []).filter((item) => item !== key);
237
+ const nextRemoteCache = normalizeRemoteCache({
238
+ ...remoteCache,
239
+ key,
240
+ stale: invalidatedKeys.length > 0,
241
+ invalidatedKeys: invalidatedKeys.length > 0 ? invalidatedKeys : undefined,
242
+ });
243
+ return {
244
+ ...state,
245
+ remoteCache: nextRemoteCache,
246
+ };
247
+ }
248
+ function resetPageIndex(pagination) {
249
+ if (!pagination) {
250
+ return undefined;
251
+ }
252
+ return {
253
+ ...pagination,
254
+ pageIndex: 0,
255
+ };
256
+ }
257
+ function resetCursor(cursorPagination) {
258
+ if (!cursorPagination) {
259
+ return undefined;
260
+ }
261
+ return {
262
+ ...cursorPagination,
263
+ cursor: undefined,
264
+ };
265
+ }
266
+ function setRemoteRequestStatus(state, remoteRequest) {
267
+ return {
268
+ ...state,
269
+ remoteRequest,
270
+ };
271
+ }
272
+ function markRemoteCacheStale(remoteCache) {
273
+ if (!remoteCache) {
274
+ return undefined;
275
+ }
276
+ return {
277
+ ...normalizeRemoteCache(remoteCache),
278
+ stale: true,
279
+ };
280
+ }
281
+ function normalizeRemoteCache(remoteCache) {
282
+ const { invalidatedKeys: rawInvalidatedKeys, ...rest } = remoteCache ?? {};
283
+ const invalidatedKeys = rawInvalidatedKeys ? [...new Set(rawInvalidatedKeys)] : undefined;
284
+ const nextRemoteCache = {
285
+ ...rest,
286
+ version: Math.max(0, Math.trunc(remoteCache?.version ?? 0)),
287
+ };
288
+ if (invalidatedKeys && invalidatedKeys.length > 0) {
289
+ nextRemoteCache.invalidatedKeys = invalidatedKeys;
290
+ }
291
+ return nextRemoteCache;
292
+ }
293
+ function addUniqueKey(keys, key) {
294
+ return [...new Set([...(keys ?? []), key])];
295
+ }