@lavalogic/scoria 0.38.14 → 0.38.16

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.
@@ -115,20 +115,34 @@
115
115
  }
116
116
  const current = tableContext.paginationRepo.paginationState.pageIndex + 1;
117
117
  const last = tableContext.lastPage;
118
+ // Empty / no-results case: render a single "1" button rather than
119
+ // a "0" button. `lastPage` is a 1-indexed count, never 0; a
120
+ // misbehaving data repo that returns 0 would otherwise leak
121
+ // through to a "Previous 0 1 Next" strip (see the page-0
122
+ // regression captured in image 2 of the bug report).
123
+ if (last < 1) {
124
+ pageButtons = [1];
125
+ return;
126
+ }
118
127
  // `pages` accumulates the dedup'd, sorted button set. The minimum
119
128
  // the user always sees between the Previous and Next arrows is the
120
129
  // current page, the next page (when one exists), and the last
121
130
  // page. On top of that we still surface a small window around the
122
- // current page for visual context.
131
+ // current page for visual context. Every value pushed is clamped
132
+ // to `[1, last]` defensively so an out-of-range current page (e.g.
133
+ // a stale `pageIndex` waiting for the next remote reload to
134
+ // settle) cannot resurface a page-0 button.
123
135
  // eslint-disable-next-line svelte/prefer-svelte-reactivity
124
136
  const pages = new Set<number>();
125
137
  const windowStart = Math.max(1, Math.min(current - 2, last - 4));
126
138
  for (let i = windowStart; i < windowStart + 5 && i <= last; i++) {
127
139
  pages.add(i);
128
140
  }
129
- pages.add(current);
130
- if (current + 1 <= last) {
131
- pages.add(current + 1);
141
+ if (current >= 1 && current <= last) {
142
+ pages.add(current);
143
+ if (current + 1 <= last) {
144
+ pages.add(current + 1);
145
+ }
132
146
  }
133
147
  pages.add(last);
134
148
  pageButtons = [...pages].sort((a, b) => a - b);
@@ -131,6 +131,14 @@ export declare class CustomRemoteRepository<TRow extends object> extends TableDa
131
131
  readonly setFilterMode: (id: string, mode: FilterMode | undefined) => void;
132
132
  readonly filterBy: (id: string, value: unknown) => void;
133
133
  readonly resetFilters: () => void;
134
+ /**
135
+ * Reset the current page to page 1 without touching `pageSize`. Used
136
+ * by every filter-mutation entrypoint so a fresh filter never leaves
137
+ * the user stranded on a page index that no longer exists once the
138
+ * remote re-query returns a smaller result set. Mirror of the helper
139
+ * on `BuiltInRemoteRepository`.
140
+ */
141
+ private resetToFirstPage;
134
142
  /** Jumps to the given 1-based page number, clamped at >= 1. */
135
143
  readonly setPage: (page: number) => void;
136
144
  /** Advances to the next page. */
@@ -235,7 +235,7 @@ export class BuiltInRemoteRepository extends TableDataRepository {
235
235
  const transformed = this._applyResponseTransform(raw);
236
236
  this._data = [...transformed.rows];
237
237
  this._totalRows = transformed.totalRows;
238
- this._lastPage = Math.max(0, Math.ceil(transformed.totalRows / this.paginationState.pageSize) - 1);
238
+ this._lastPage = Math.max(1, Math.ceil(transformed.totalRows / this.paginationState.pageSize));
239
239
  }
240
240
  catch (e) {
241
241
  if (e.name === 'AbortError') {
@@ -403,6 +403,7 @@ export class CustomRemoteRepository extends TableDataRepository {
403
403
  else {
404
404
  this._filterModes.set(id, mode);
405
405
  }
406
+ this.resetToFirstPage();
406
407
  void this.reload();
407
408
  };
408
409
  filterBy = (id, value) => {
@@ -423,12 +424,34 @@ export class CustomRemoteRepository extends TableDataRepository {
423
424
  }
424
425
  }
425
426
  this._filtering = next;
427
+ // Any filter change should drop the user back on page 1; otherwise
428
+ // when typing in a filter while on page 2+ the new (smaller) result
429
+ // set leaves the pagination on an out-of-range page index. The user
430
+ // then sees "1 row" in the footer but the body is blank because
431
+ // the request still asks for `page=3` of a 1-page result set.
432
+ this.resetToFirstPage();
426
433
  void this.reload();
427
434
  };
428
435
  resetFilters = () => {
429
436
  this._filtering = [];
437
+ this.resetToFirstPage();
430
438
  void this.reload();
431
439
  };
440
+ /**
441
+ * Reset the current page to page 1 without touching `pageSize`. Used
442
+ * by every filter-mutation entrypoint so a fresh filter never leaves
443
+ * the user stranded on a page index that no longer exists once the
444
+ * remote re-query returns a smaller result set. Mirror of the helper
445
+ * on `BuiltInRemoteRepository`.
446
+ */
447
+ resetToFirstPage() {
448
+ if (this.paginationState.pageIndex !== 0) {
449
+ this.paginationState = {
450
+ ...this.paginationState,
451
+ pageIndex: 0,
452
+ };
453
+ }
454
+ }
432
455
  /** Jumps to the given 1-based page number, clamped at >= 1. */
433
456
  setPage = (page) => {
434
457
  this.paginationState = {
@@ -490,7 +513,7 @@ export class CustomRemoteRepository extends TableDataRepository {
490
513
  }
491
514
  this._data = [...response.rows];
492
515
  this._totalRows = response.totalRows;
493
- this._lastPage = Math.max(0, Math.ceil(response.totalRows / this.paginationState.pageSize) - 1);
516
+ this._lastPage = Math.max(1, Math.ceil(response.totalRows / this.paginationState.pageSize));
494
517
  }
495
518
  catch (e) {
496
519
  if (e.name === 'AbortError') {
@@ -91,9 +91,15 @@ export declare class LocalTableDataRepository<T extends object> extends TableDat
91
91
  /** Clears every active filter value (keeps filter modes intact). */
92
92
  readonly resetFilters: () => void;
93
93
  /**
94
- * Sets the page size and clamps the current page index so the new
95
- * page count covers the current view. Accepts a string so a raw
96
- * `<select>` value can be passed through without parsing first.
94
+ * Sets the page size and resets the page index to 0 (page 1). A
95
+ * page-size change is a "show me the start of the list at this
96
+ * density" action; clamping the previous page index forward instead
97
+ * (e.g. page 5 of size 20 -> page 5 of size 100) leaves the user on
98
+ * an arbitrary window of the new page-sized result, which does not
99
+ * match the user's mental model.
100
+ *
101
+ * Accepts a string so a raw `<select>` value can be passed through
102
+ * without parsing first.
97
103
  */
98
104
  setPageSize: (size: number | string) => void;
99
105
  /** Jumps to the given 1-based page number, clamped to the last page. */
@@ -219,9 +219,15 @@ export class LocalTableDataRepository extends TableDataRepository {
219
219
  this.resetToFirstPage();
220
220
  };
221
221
  /**
222
- * Sets the page size and clamps the current page index so the new
223
- * page count covers the current view. Accepts a string so a raw
224
- * `<select>` value can be passed through without parsing first.
222
+ * Sets the page size and resets the page index to 0 (page 1). A
223
+ * page-size change is a "show me the start of the list at this
224
+ * density" action; clamping the previous page index forward instead
225
+ * (e.g. page 5 of size 20 -> page 5 of size 100) leaves the user on
226
+ * an arbitrary window of the new page-sized result, which does not
227
+ * match the user's mental model.
228
+ *
229
+ * Accepts a string so a raw `<select>` value can be passed through
230
+ * without parsing first.
225
231
  */
226
232
  setPageSize = (size) => {
227
233
  if (typeof size === 'string') {
@@ -231,10 +237,9 @@ export class LocalTableDataRepository extends TableDataRepository {
231
237
  console.warn('page size is nan');
232
238
  return;
233
239
  }
234
- const lastIndex = Math.ceil(this._dataRef.value.length / size) - 1;
235
240
  this.paginationState = {
236
241
  pageSize: size,
237
- pageIndex: Math.max(0, Math.min(this.paginationState.pageIndex, lastIndex)),
242
+ pageIndex: 0,
238
243
  };
239
244
  };
240
245
  /** Jumps to the given 1-based page number, clamped to the last page. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lavalogic/scoria",
3
3
  "description": "Svelte components used for the FloWMS Web Frontend",
4
- "version": "0.38.14",
4
+ "version": "0.38.16",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },