@svadmin/ui 0.34.8 → 0.34.9

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.
@@ -10,6 +10,7 @@
10
10
  type ColumnVisibilityState,
11
11
  type ExpandedState,
12
12
  } from '@tanstack/svelte-table';
13
+ import type { Updater } from '@tanstack/table-core';
13
14
  import {
14
15
  column_getCanSort,
15
16
  column_getIsSorted,
@@ -28,7 +29,7 @@
28
29
  row_getIsExpanded,
29
30
  row_toggleExpanded,
30
31
  cell_getValue,
31
- } from '@tanstack/svelte-table/static-functions';
32
+ } from '@tanstack/table-core/static-functions';
32
33
 
33
34
  import { useList, useDelete, useDeleteMany, getResource, notify } from '@svadmin/core';
34
35
  import type { Pagination as PaginationState, Sort, Filter, FieldDefinition } from '@svadmin/core';
@@ -107,7 +108,7 @@
107
108
  const initPageSize = untrack(() => resource.pageSize ?? (isNaN(storedPageSize) ? 10 : storedPageSize));
108
109
  const initDefaultSort = untrack(() => resource.defaultSort);
109
110
 
110
- let pagination = $state<{ current: number; pageSize: number }>(untrack(() => externalPagination ?? {
111
+ let pagination = $state<PaginationState>(untrack(() => externalPagination ?? {
111
112
  current: urlState.page ?? 1,
112
113
  pageSize: urlState.pageSize ?? initPageSize,
113
114
  }));
@@ -173,6 +174,41 @@
173
174
  return result;
174
175
  });
175
176
 
177
+ function clonePlainValue(value: unknown): unknown {
178
+ if (Array.isArray(value)) return value.map(clonePlainValue);
179
+ if (value && typeof value === 'object') {
180
+ return Object.fromEntries(
181
+ Object.entries(value as Record<string, unknown>).map(([key, entry]) => [key, clonePlainValue(entry)])
182
+ );
183
+ }
184
+ return value;
185
+ }
186
+
187
+ function cloneFilter(filter: Filter): Filter {
188
+ if ('field' in filter) {
189
+ return {
190
+ field: filter.field,
191
+ operator: filter.operator,
192
+ value: clonePlainValue(filter.value),
193
+ };
194
+ }
195
+ return {
196
+ operator: filter.operator,
197
+ value: filter.value.map(cloneFilter),
198
+ };
199
+ }
200
+
201
+ const queryPagination = $derived<PaginationState>({
202
+ current: pagination.current,
203
+ pageSize: pagination.pageSize,
204
+ mode: pagination.mode,
205
+ });
206
+ const querySorters = $derived<Sort[]>(sorters.map(sorter => ({
207
+ field: sorter.field,
208
+ order: sorter.order,
209
+ })));
210
+ const queryFilters = $derived<Filter[]>(activeFilters.map(cloneFilter));
211
+
176
212
  $effect(() => {
177
213
  if (Object.values(filterValues).some(v => v.trim())) {
178
214
  pagination = { ...pagination, current: 1 };
@@ -182,9 +218,9 @@
182
218
  // ─── Data fetching ────────────────────────────────────────────
183
219
  const listResult = useList({
184
220
  get resource() { return resourceName; },
185
- get pagination() { return pagination; },
186
- get sorters() { return sorters; },
187
- get filters() { return activeFilters; },
221
+ get pagination() { return queryPagination; },
222
+ get sorters() { return querySorters; },
223
+ get filters() { return queryFilters; },
188
224
  });
189
225
  const query = listResult;
190
226
  const deleteResult = useDelete({ get resource() { return resourceName; } });
@@ -227,6 +263,68 @@
227
263
  let expanded = $state.raw<ExpandedState>({});
228
264
  let columnOrder = $state<string[]>([]);
229
265
 
266
+ function applyTableUpdater<T>(current: T, updater: Updater<T>): T {
267
+ return typeof updater === 'function' ? (updater as (old: T) => T)(current) : updater;
268
+ }
269
+
270
+ const tableSorting = $derived<SortingState>(sorting.map(sorter => ({
271
+ id: sorter.id,
272
+ desc: sorter.desc,
273
+ })));
274
+ const tableColumnVisibility = $derived<ColumnVisibilityState>({ ...columnVisibility });
275
+ const tableRowSelection = $derived<RowSelectionState>({ ...rowSelection });
276
+ const tableExpanded = $derived<ExpandedState>(expanded === true ? true : { ...expanded });
277
+ const tableColumnOrder = $derived<string[]>([...columnOrder]);
278
+
279
+ const sortingAtom = {
280
+ get: () => tableSorting,
281
+ set: (updater: Updater<SortingState>) => {
282
+ const nextSorting = applyTableUpdater(tableSorting, updater);
283
+ sorting = nextSorting;
284
+
285
+ const nextSorters: Sort[] = nextSorting.map((s) => ({
286
+ field: s.id,
287
+ order: s.desc ? 'desc' as const : 'asc' as const,
288
+ }));
289
+
290
+ if (JSON.stringify(nextSorters) !== JSON.stringify(sorters)) {
291
+ sorters = nextSorters;
292
+ }
293
+
294
+ if ((pagination.current ?? 1) !== 1) {
295
+ pagination = { ...pagination, current: 1 };
296
+ }
297
+ },
298
+ };
299
+
300
+ const columnVisibilityAtom = {
301
+ get: () => tableColumnVisibility,
302
+ set: (updater: Updater<ColumnVisibilityState>) => {
303
+ columnVisibility = applyTableUpdater(tableColumnVisibility, updater);
304
+ },
305
+ };
306
+
307
+ const rowSelectionAtom = {
308
+ get: () => tableRowSelection,
309
+ set: (updater: Updater<RowSelectionState>) => {
310
+ rowSelection = applyTableUpdater(tableRowSelection, updater);
311
+ },
312
+ };
313
+
314
+ const expandedAtom = {
315
+ get: () => tableExpanded,
316
+ set: (updater: Updater<ExpandedState>) => {
317
+ expanded = applyTableUpdater(tableExpanded, updater);
318
+ },
319
+ };
320
+
321
+ const columnOrderAtom = {
322
+ get: () => tableColumnOrder,
323
+ set: (updater: Updater<string[]>) => {
324
+ columnOrder = applyTableUpdater(tableColumnOrder, updater);
325
+ },
326
+ };
327
+
230
328
  // Persist column visibility to localStorage
231
329
  $effect(() => {
232
330
  const storageKey = `svadmin-columns-${resourceName}`;
@@ -297,41 +395,12 @@
297
395
  manualPagination: true,
298
396
  manualSorting: true,
299
397
  getRowId: (row: any) => String(row[primaryKey]),
300
- state: {
301
- get sorting() { return sorting; },
302
- get columnVisibility() { return columnVisibility; },
303
- get rowSelection() { return rowSelection; },
304
- get expanded() { return expanded; },
305
- get columnOrder() { return columnOrder; },
306
- },
307
- onSortingChange: (updater: any) => {
308
- const nextSorting = typeof updater === 'function' ? updater(sorting) : updater;
309
- sorting = nextSorting;
310
-
311
- const nextSorters: Sort[] = nextSorting.map((s: any) => ({
312
- field: s.id,
313
- order: s.desc ? 'desc' as const : 'asc' as const,
314
- }));
315
-
316
- if (JSON.stringify(nextSorters) !== JSON.stringify(sorters)) {
317
- sorters = nextSorters;
318
- }
319
-
320
- if ((pagination.current ?? 1) !== 1) {
321
- pagination = { ...pagination, current: 1 };
322
- }
323
- },
324
- onColumnVisibilityChange: (updater: any) => {
325
- columnVisibility = typeof updater === 'function' ? updater(columnVisibility) : updater;
326
- },
327
- onRowSelectionChange: (updater: any) => {
328
- rowSelection = typeof updater === 'function' ? updater(rowSelection) : updater;
329
- },
330
- onExpandedChange: (updater: any) => {
331
- expanded = typeof updater === 'function' ? updater(expanded) : updater;
332
- },
333
- onColumnOrderChange: (updater: any) => {
334
- columnOrder = typeof updater === 'function' ? updater(columnOrder) : updater;
398
+ atoms: {
399
+ sorting: sortingAtom,
400
+ columnVisibility: columnVisibilityAtom,
401
+ rowSelection: rowSelectionAtom,
402
+ expanded: expandedAtom,
403
+ columnOrder: columnOrderAtom,
335
404
  },
336
405
  get enableRowSelection() { return selectable && (canDelete || batchActions); },
337
406
  get enableExpanding() { return !!expandedRowRender; },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/ui",
3
- "version": "0.34.8",
3
+ "version": "0.34.9",
4
4
  "description": "Pre-built admin UI components — AdminApp, AutoTable, AutoForm, Sidebar, Layout",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -33,7 +33,7 @@
33
33
  "./components/*": "./dist/components/*"
34
34
  },
35
35
  "peerDependencies": {
36
- "@svadmin/core": "^0.25.4",
36
+ "@svadmin/core": "^0.25.5",
37
37
  "@tanstack/svelte-query": "^6.1.29",
38
38
  "highlight.js": "^11.11.1",
39
39
  "isomorphic-dompurify": "^3.7.1",