@svelte-lean/table 0.10.0 → 0.12.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.
- package/CHANGELOG.md +16 -0
- package/dist/table/data-table.svelte +45 -5
- package/dist/types.d.ts +10 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @svelte-lean/table
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- dba6ebc: `DataTable` takes `measureKey`: change it when what the cells show changes without the rows changing (a masked value revealed in place, a value a cell fetched itself), and the grid measures every row on the page again when idle, so the column widens instead of the value running over the next column. A column only grows; the first value measures nothing extra.
|
|
8
|
+
|
|
9
|
+
## 0.11.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 84e0055: A paginated `DataTable` loading without rows draws a page of placeholder rows by default (its page size, at most 25) instead of five, so the pager and whatever follows the table stand where they will be once the rows arrive. An unpaginated table still draws five; `skeletonRows` still sets the number.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 8ba61b8: A paginated `DataTable` on a page that no longer exists moves to the last page there is. The model already drew the last page, but the state kept the old index, so a manual table whose last page emptied (its last row approved or deleted) showed "page 23 of 23" while it kept asking the server for page 24 and drew it empty. Once the table is neither `loading` nor `fetching`, `state.pageIndex` now follows and `onStateChange` fires.
|
|
18
|
+
|
|
3
19
|
## 0.10.0
|
|
4
20
|
|
|
5
21
|
No changes in this release.
|
|
@@ -104,7 +104,8 @@
|
|
|
104
104
|
onExpandedRowsChange,
|
|
105
105
|
loading = false,
|
|
106
106
|
fetching = false,
|
|
107
|
-
skeletonRows
|
|
107
|
+
skeletonRows,
|
|
108
|
+
measureKey,
|
|
108
109
|
error,
|
|
109
110
|
onRetry,
|
|
110
111
|
empty,
|
|
@@ -180,6 +181,19 @@
|
|
|
180
181
|
const m = $derived({ ...en, ...messages });
|
|
181
182
|
const cols = $derived(table.visibleColumns);
|
|
182
183
|
const model = $derived(table.model);
|
|
184
|
+
/**
|
|
185
|
+
* A page that no longer exists is left for the last one there is. When the rows of the last
|
|
186
|
+
* page go — a filter elsewhere, the last row on it approved, the total of a manual table
|
|
187
|
+
* shrinking — the model draws the last page that remains, and the state follows it, so a
|
|
188
|
+
* manual table's `onStateChange` asks for that page instead of drawing the empty one it asked
|
|
189
|
+
* for. Not while the table loads or fetches: a page count read before the answer arrives is
|
|
190
|
+
* not the data's.
|
|
191
|
+
*/
|
|
192
|
+
$effect(() => {
|
|
193
|
+
if (loading || fetching || !pagination) return;
|
|
194
|
+
const last = model.pageIndex;
|
|
195
|
+
if (last < s.pageIndex) untrack(() => table.setPage(last));
|
|
196
|
+
});
|
|
183
197
|
/** The expand toggle has a column of its own when asked for and when anything can expand. */
|
|
184
198
|
const expander = $derived(expandColumn && (!!rowDetails || !!getSubRows));
|
|
185
199
|
/** Every column of a full-width row: the leading control columns and the data columns. */
|
|
@@ -510,6 +524,8 @@
|
|
|
510
524
|
const GRID_MAX = 480;
|
|
511
525
|
const GRID_MIN = 48;
|
|
512
526
|
const MEASURE_ROWS = 30;
|
|
527
|
+
/** The most placeholder rows a loading page draws when `skeletonRows` is not given. */
|
|
528
|
+
const MAX_PLACEHOLDERS = 25;
|
|
513
529
|
const grid = $derived(layout === 'grid');
|
|
514
530
|
let measured = $state<Record<string, number>>({});
|
|
515
531
|
function gridWidth(col: Column<T>): number {
|
|
@@ -566,6 +582,22 @@
|
|
|
566
582
|
whenIdle(() => measure(true, first));
|
|
567
583
|
});
|
|
568
584
|
});
|
|
585
|
+
/**
|
|
586
|
+
* A cell's content changed under the same rows (`measureKey`): every row on the page is
|
|
587
|
+
* measured again when idle, so a value revealed in place widens its column instead of
|
|
588
|
+
* running over the next one. Not on the first value: the rows are measured as they come.
|
|
589
|
+
*/
|
|
590
|
+
let lastMeasureKey: unknown = undefined;
|
|
591
|
+
let measureKeySeen = false;
|
|
592
|
+
$effect(() => {
|
|
593
|
+
const key = measureKey;
|
|
594
|
+
if (!grid) return;
|
|
595
|
+
untrack(() => {
|
|
596
|
+
if (measureKeySeen && key !== lastMeasureKey) whenIdle(() => measure(true, true, true));
|
|
597
|
+
measureKeySeen = true;
|
|
598
|
+
lastMeasureKey = key;
|
|
599
|
+
});
|
|
600
|
+
});
|
|
569
601
|
/**
|
|
570
602
|
* What a body row stands, from the first section once its rows are drawn: the sections the
|
|
571
603
|
* browser skips assume it, so the page is about as tall before they are drawn as after.
|
|
@@ -591,15 +623,15 @@
|
|
|
591
623
|
* hidden table inside the root, laid out there with every cell at its max-content width
|
|
592
624
|
* (`data-measuring`), read, and removed. The live rows are neither restyled nor laid out.
|
|
593
625
|
*/
|
|
594
|
-
function measure(whole: boolean, first = true) {
|
|
626
|
+
function measure(whole: boolean, first = true, every = false) {
|
|
595
627
|
const live = viewport?.firstElementChild as HTMLElement | null;
|
|
596
628
|
if (!live || !root) return;
|
|
597
629
|
const leaves = new Set(cols.map((col) => col.id));
|
|
598
630
|
const rows = [...ownRows()];
|
|
599
631
|
// The first rows and the header, and for a whole page twenty rows spread over the rest; a pass
|
|
600
632
|
// over a page whose first rows were measured already (`first` false) takes only the spread.
|
|
601
|
-
const sample = first ? rows.slice(0, MEASURE_ROWS) : [];
|
|
602
|
-
if (whole && rows.length > MEASURE_ROWS) {
|
|
633
|
+
const sample = every ? rows : first ? rows.slice(0, MEASURE_ROWS) : [];
|
|
634
|
+
if (!every && whole && rows.length > MEASURE_ROWS) {
|
|
603
635
|
const step = Math.ceil((rows.length - MEASURE_ROWS) / 20);
|
|
604
636
|
for (let i = MEASURE_ROWS; i < rows.length; i += step) sample.push(rows[i]!);
|
|
605
637
|
}
|
|
@@ -873,9 +905,17 @@
|
|
|
873
905
|
manual && rowCount !== undefined ? rowCount + headerRowCount : undefined
|
|
874
906
|
);
|
|
875
907
|
const pageSizes = $derived([...new Set([...pageSizeOptions, s.pageSize])]);
|
|
908
|
+
/**
|
|
909
|
+
* A paged table loading draws a page of placeholders (at most 25, a screenful and more), so
|
|
910
|
+
* the pager and whatever follows the table stand where they will be once the rows arrive; five
|
|
911
|
+
* stood in for a page of twenty, and everything below moved when it came.
|
|
912
|
+
*/
|
|
913
|
+
const skeletonCount = $derived(
|
|
914
|
+
skeletonRows ?? (pagination && s.pageSize > 0 ? Math.min(s.pageSize, MAX_PLACEHOLDERS) : 5)
|
|
915
|
+
);
|
|
876
916
|
const skeleton = $derived(
|
|
877
917
|
loading && !model.rows.length
|
|
878
|
-
? Array.from({ length: Math.max(0,
|
|
918
|
+
? Array.from({ length: Math.max(0, skeletonCount) }, (_, i) => i)
|
|
879
919
|
: []
|
|
880
920
|
);
|
|
881
921
|
const emptyContext = $derived({
|
package/dist/types.d.ts
CHANGED
|
@@ -268,8 +268,17 @@ export interface TableProps<T> {
|
|
|
268
268
|
onExpandedRowsChange?: (rows: RowId[]) => void;
|
|
269
269
|
loading?: boolean;
|
|
270
270
|
fetching?: boolean;
|
|
271
|
-
/**
|
|
271
|
+
/**
|
|
272
|
+
* Skeleton rows drawn while `loading` and no row is present. Default: the page size, at most
|
|
273
|
+
* 25, when paginated (so nothing below the table moves when the rows arrive); otherwise 5.
|
|
274
|
+
*/
|
|
272
275
|
skeletonRows?: number;
|
|
276
|
+
/**
|
|
277
|
+
* Changes when what the cells show changes without the rows changing — a masked value
|
|
278
|
+
* revealed in place, a value the cell fetched itself. On each change after the first the grid
|
|
279
|
+
* measures every row on the page again, when idle; a column only grows.
|
|
280
|
+
*/
|
|
281
|
+
measureKey?: unknown;
|
|
273
282
|
error?: string;
|
|
274
283
|
onRetry?: () => void;
|
|
275
284
|
empty?: Snippet<[EmptyContext]>;
|