@spaethtech/svelte-ui 0.21.1-dev.111.c0572e9 → 0.21.1-dev.113.5a2e853
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/dist/components/DataTable.svelte +8 -2
- package/dist/data/table/local.d.ts +6 -0
- package/dist/data/table/local.js +5 -1
- package/dist/i18n.d.ts +4 -0
- package/dist/i18n.js +2 -0
- package/docs/components.md +17 -0
- package/package.json +1 -1
|
@@ -148,6 +148,10 @@
|
|
|
148
148
|
const pageCount = $derived(Math.max(1, Math.ceil(total / grid.perPage)));
|
|
149
149
|
// "Settled" = a result came back AND we're not fetching — only then is empty genuinely "No results".
|
|
150
150
|
const settled = $derived(!!result.current && !result.loading);
|
|
151
|
+
// A fetch error → shown in the empty-state row (styled) instead of "No results" / spinner. A string
|
|
152
|
+
// is used as-is, an Error's `.message`, anything else falls back to the localized `loadFailed`.
|
|
153
|
+
const errorText = (e: unknown): string =>
|
|
154
|
+
typeof e === "string" ? e : e instanceof Error ? e.message : i18n.messages.loadFailed;
|
|
151
155
|
$effect(() => {
|
|
152
156
|
grid.loading = result.loading;
|
|
153
157
|
if (result.current) {
|
|
@@ -358,11 +362,13 @@
|
|
|
358
362
|
</div>
|
|
359
363
|
{/if}
|
|
360
364
|
<div class="grow self-center text-center {subtle}">
|
|
361
|
-
{#if
|
|
365
|
+
{#if result.error}
|
|
366
|
+
<span class="[color:var(--ui-color-error)]">{errorText(result.error)}</span>
|
|
367
|
+
{:else if settled}
|
|
362
368
|
{i18n.messages.noResults}.
|
|
363
369
|
{:else}
|
|
364
370
|
<span class="inline-flex items-center gap-2"
|
|
365
|
-
><IconLoading class="w-[1em] h-[1em] animate-spin" />
|
|
371
|
+
><IconLoading class="w-[1em] h-[1em] animate-spin" /> {i18n.messages.loading}</span
|
|
366
372
|
>
|
|
367
373
|
{/if}
|
|
368
374
|
</div>
|
|
@@ -6,6 +6,12 @@ export interface LocalFetchOptions<T> {
|
|
|
6
6
|
caseInsensitive?: boolean;
|
|
7
7
|
/** Instant for resolving `now()` in the query. Called per fetch. Default: `new Date()`. */
|
|
8
8
|
now?: () => Date;
|
|
9
|
+
/** True while `source` is still arriving (an async load not yet resolved). The table shows its
|
|
10
|
+
* Loading row instead of "No results". Called per fetch. Default: `false` (data is ready). */
|
|
11
|
+
loading?: () => boolean;
|
|
12
|
+
/** A load failure. Surfaced in the table's empty-state row (styled as an error) instead of
|
|
13
|
+
* "No results"; if any rows are present they still render. Called per fetch. Default: none. */
|
|
14
|
+
error?: () => string | null | undefined;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Build a `FetchFn` that runs entirely in memory over `source`.
|
package/dist/data/table/local.js
CHANGED
|
@@ -58,6 +58,10 @@ export function localFetch(source, columns, opts = {}) {
|
|
|
58
58
|
const total = filtered.length;
|
|
59
59
|
const start = (state.page - 1) * state.perPage;
|
|
60
60
|
const rows = filtered.slice(start, start + state.perPage);
|
|
61
|
-
return {
|
|
61
|
+
return {
|
|
62
|
+
current: { rows, total },
|
|
63
|
+
loading: opts.loading?.() ?? false,
|
|
64
|
+
error: opts.error?.() ?? undefined,
|
|
65
|
+
};
|
|
62
66
|
};
|
|
63
67
|
}
|
package/dist/i18n.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ export type UiMessages = {
|
|
|
15
15
|
copyToClipboard: Msg;
|
|
16
16
|
done: Msg;
|
|
17
17
|
noResults: Msg;
|
|
18
|
+
/** DataTable empty-state while the source is still arriving. */
|
|
19
|
+
loading: Msg;
|
|
20
|
+
/** DataTable empty-state when the fetch result carries a non-string error. */
|
|
21
|
+
loadFailed: Msg;
|
|
18
22
|
previous: Msg;
|
|
19
23
|
next: Msg;
|
|
20
24
|
first: Msg;
|
package/dist/i18n.js
CHANGED
package/docs/components.md
CHANGED
|
@@ -433,6 +433,23 @@ Config-driven, responsive 12-column data table over a `DataGrid`.
|
|
|
433
433
|
whole cell). The cell is a flex box, so a plain inline `<a>text</a>` is text-width — the rest of the
|
|
434
434
|
cell stays an expand/collapse target. Row-click already ignores clicks on `a`/`button`/`input`/…, so
|
|
435
435
|
a link navigates without toggling expand; don't stretch the anchor with `block`/`w-full`.
|
|
436
|
+
- **Empty-state row (Loading → rows | No results | error)**: with no rows the table renders one
|
|
437
|
+
standard-height row reflecting the fetch result — a **spinner + "Loading…"** while `result.loading`,
|
|
438
|
+
**"No results"** once settled and empty, or the **error** (styled `--ui-color-error`) when
|
|
439
|
+
`result.error` is set (a string as-is, an `Error`'s `.message`, else the localized `loadFailed`). An
|
|
440
|
+
errored result never spins, and the row keeps its height across all three states — so you don't need
|
|
441
|
+
a separate page banner that contradicts a "No results" table. With `localFetch`, drive this by
|
|
442
|
+
passing `loading`/`error` getters (below); a remote `query()` that exposes `.error` gets it for free.
|
|
443
|
+
(`DataGrid.error` is the query-*parse* error surfaced by `<Query>` — a bad filter — which is distinct
|
|
444
|
+
from this fetch/load error.)
|
|
445
|
+
- **`localFetch(rows, columns, opts?)`** options now include **`loading?: () => boolean`** (show the
|
|
446
|
+
Loading row instead of "No results" while the source is still arriving) and **`error?: () => string
|
|
447
|
+
| null | undefined`** (surface a load failure in the empty-state row; rows still render if present).
|
|
448
|
+
State both once beside the data source:
|
|
449
|
+
```ts
|
|
450
|
+
const fetch = localFetch(() => rows, columns, { getValue: valueOf, loading: () => !loaded, error: () => loadError });
|
|
451
|
+
const grid = createGrid({ columns, getRowId: (r) => r.id, fetch });
|
|
452
|
+
```
|
|
436
453
|
|
|
437
454
|
### Query
|
|
438
455
|
|