@lyeve-labs/ui-kit 0.19.0 → 0.21.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.
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { safeHref } from '../internal/href.js';
|
|
3
|
+
import { formatCount } from '../internal/number.js';
|
|
3
4
|
|
|
4
5
|
interface Base {
|
|
5
6
|
page: number;
|
|
@@ -21,6 +22,31 @@
|
|
|
21
22
|
* back.
|
|
22
23
|
*/
|
|
23
24
|
hasNext?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* How many rows the page on screen actually holds.
|
|
27
|
+
*
|
|
28
|
+
* Only an uncounted list needs it, and only for the sentence: without a
|
|
29
|
+
* total the component knows where the page starts but not where it ends,
|
|
30
|
+
* because the last page is short and nothing here says how short. Given it,
|
|
31
|
+
* the summary states a range instead of naming the page.
|
|
32
|
+
*
|
|
33
|
+
* It is the row count of what was rendered, not a page size. A caller that
|
|
34
|
+
* asked for 50 and received 12 passes 12.
|
|
35
|
+
*/
|
|
36
|
+
count?: number;
|
|
37
|
+
/**
|
|
38
|
+
* What the list holds, in the plural: 'files', 'jobs', 'webhooks'.
|
|
39
|
+
*
|
|
40
|
+
* The summary names it, because a console that stacks three lists under one
|
|
41
|
+
* page title prints '51 to 100' three times and says of what nowhere. Left
|
|
42
|
+
* out, the summary reads exactly as it did before this existed.
|
|
43
|
+
*
|
|
44
|
+
* Plural at every size, including a list of one. The noun labels the
|
|
45
|
+
* collection here rather than agreeing with a figure in the sentence, the
|
|
46
|
+
* same way the column header above it does, and a singular form would have
|
|
47
|
+
* to pick which of the three figures governs it.
|
|
48
|
+
*/
|
|
49
|
+
noun?: string;
|
|
24
50
|
class?: string;
|
|
25
51
|
}
|
|
26
52
|
|
|
@@ -47,6 +73,8 @@
|
|
|
47
73
|
total = undefined,
|
|
48
74
|
perPage = 20,
|
|
49
75
|
hasNext = false,
|
|
76
|
+
count = undefined,
|
|
77
|
+
noun = '',
|
|
50
78
|
class: cls = '',
|
|
51
79
|
onchange,
|
|
52
80
|
href,
|
|
@@ -64,6 +92,15 @@
|
|
|
64
92
|
let from = $derived(Math.min((safePage - 1) * perPage + 1, safeTotal));
|
|
65
93
|
let to = $derived(Math.min(safePage * perPage, safeTotal));
|
|
66
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The rows on screen, when the caller states them. Zero and a negative are
|
|
97
|
+
* both "nothing to describe": a page of no rows has no range, and the summary
|
|
98
|
+
* falls back to naming the page rather than printing an inverted one.
|
|
99
|
+
*/
|
|
100
|
+
let safeCount = $derived(
|
|
101
|
+
typeof count === 'number' && isFinite(count) && count > 0 ? Math.floor(count) : undefined,
|
|
102
|
+
);
|
|
103
|
+
|
|
67
104
|
let canPrev = $derived(safePage > 1);
|
|
68
105
|
let canNext = $derived(counted ? safePage < totalPages : hasNext);
|
|
69
106
|
let hasControls = $derived(counted ? totalPages > 1 : canPrev || canNext);
|
|
@@ -102,20 +139,40 @@
|
|
|
102
139
|
|
|
103
140
|
let nums = $derived(counted ? pageNumbers(safePage, totalPages) : []);
|
|
104
141
|
|
|
142
|
+
/**
|
|
143
|
+
* The noun as it will be read.
|
|
144
|
+
*
|
|
145
|
+
* Trimmed, and empty means absent: a caller composing the word from data can
|
|
146
|
+
* hand over ' ' as easily as 'files', and a summary that opens with a stray
|
|
147
|
+
* space is worse than one that names nothing.
|
|
148
|
+
*/
|
|
149
|
+
let label = $derived(noun.trim());
|
|
150
|
+
|
|
105
151
|
/**
|
|
106
152
|
* The count, when there is one to state.
|
|
107
153
|
*
|
|
108
154
|
* An uncounted list says which page it is on and nothing else. It cannot say
|
|
109
155
|
* "1 to 20 of 400" without the total, and it cannot say "1 to 20" either: the
|
|
110
|
-
* last page is short and this component is never told how short.
|
|
156
|
+
* last page is short and this component is never told how short. It still
|
|
157
|
+
* groups the page number: `href` mode puts that number in the URL, so a link
|
|
158
|
+
* or a reader can land on page 5,000 without stepping there.
|
|
159
|
+
*
|
|
160
|
+
* Every figure is grouped, because a pager sits under a table that groups its
|
|
161
|
+
* own figures and the pager is where the largest number on the screen is.
|
|
111
162
|
*/
|
|
112
|
-
let summary = $derived(
|
|
113
|
-
counted
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
163
|
+
let summary = $derived.by(() => {
|
|
164
|
+
if (!counted) {
|
|
165
|
+
if (safeCount !== undefined) {
|
|
166
|
+
const start = (safePage - 1) * perPage + 1;
|
|
167
|
+
const span = `${formatCount(start)} to ${formatCount(start + safeCount - 1)}`;
|
|
168
|
+
return label ? `${label} ${span}` : span;
|
|
169
|
+
}
|
|
170
|
+
return label ? `${label}, page ${formatCount(safePage)}` : `Page ${formatCount(safePage)}`;
|
|
171
|
+
}
|
|
172
|
+
if (safeTotal === 0) return label ? `No ${label}` : 'No results';
|
|
173
|
+
const range = `${formatCount(from)} to ${formatCount(to)} of ${formatCount(safeTotal)}`;
|
|
174
|
+
return label ? `${label} ${range}` : range;
|
|
175
|
+
});
|
|
119
176
|
|
|
120
177
|
/** The target of a control, sanitized, or nothing when the step is unavailable. */
|
|
121
178
|
function linkTo(target: number, enabled: boolean): string | undefined {
|
|
@@ -18,6 +18,31 @@ interface Base {
|
|
|
18
18
|
* back.
|
|
19
19
|
*/
|
|
20
20
|
hasNext?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* How many rows the page on screen actually holds.
|
|
23
|
+
*
|
|
24
|
+
* Only an uncounted list needs it, and only for the sentence: without a
|
|
25
|
+
* total the component knows where the page starts but not where it ends,
|
|
26
|
+
* because the last page is short and nothing here says how short. Given it,
|
|
27
|
+
* the summary states a range instead of naming the page.
|
|
28
|
+
*
|
|
29
|
+
* It is the row count of what was rendered, not a page size. A caller that
|
|
30
|
+
* asked for 50 and received 12 passes 12.
|
|
31
|
+
*/
|
|
32
|
+
count?: number;
|
|
33
|
+
/**
|
|
34
|
+
* What the list holds, in the plural: 'files', 'jobs', 'webhooks'.
|
|
35
|
+
*
|
|
36
|
+
* The summary names it, because a console that stacks three lists under one
|
|
37
|
+
* page title prints '51 to 100' three times and says of what nowhere. Left
|
|
38
|
+
* out, the summary reads exactly as it did before this existed.
|
|
39
|
+
*
|
|
40
|
+
* Plural at every size, including a list of one. The noun labels the
|
|
41
|
+
* collection here rather than agreeing with a figure in the sentence, the
|
|
42
|
+
* same way the column header above it does, and a singular form would have
|
|
43
|
+
* to pick which of the three figures governs it.
|
|
44
|
+
*/
|
|
45
|
+
noun?: string;
|
|
21
46
|
class?: string;
|
|
22
47
|
}
|
|
23
48
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -89,4 +89,4 @@ export type { ConfirmOptions } from './components/dialog/dialog-manager.svelte.j
|
|
|
89
89
|
export type { DialogOptions, DialogEntry, DialogSize } from './components/dialog/types.js';
|
|
90
90
|
export { cn, type ClassValue } from './utils/cn.js';
|
|
91
91
|
export { getTheme, getThemePreference, nextThemePreference, resolveTheme, setTheme, setThemePreference, systemTheme, themeBootScript, toggleTheme, watchSystemTheme, THEME_PREFERENCES, type Theme, type ThemePreference, } from './utils/theme.js';
|
|
92
|
-
export declare const VERSION = "0.
|
|
92
|
+
export declare const VERSION = "0.21.0";
|
package/dist/index.js
CHANGED
|
@@ -96,4 +96,4 @@ export { getTheme, getThemePreference, nextThemePreference, resolveTheme, setThe
|
|
|
96
96
|
// ── Version ────────────────────────────────────────────────────────────────
|
|
97
97
|
// Generated from package.json by `pnpm version:sync`. Bump package.json, never
|
|
98
98
|
// this line; the build and the test suite fail when the two disagree.
|
|
99
|
-
export const VERSION = '0.
|
|
99
|
+
export const VERSION = '0.21.0';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Digit grouping for a figure a reader is meant to take in at a glance.
|
|
3
|
+
*
|
|
4
|
+
* The locale is fixed rather than the runtime's. `toLocaleString()` with no
|
|
5
|
+
* argument formats by whatever locale the environment reports, and the server
|
|
6
|
+
* that renders a page and the browser that hydrates it do not have to report
|
|
7
|
+
* the same one: the same figure then arrives as `4,210` in the HTML and as
|
|
8
|
+
* `4.210` or `4210` after hydration, which is a mismatch the framework warns
|
|
9
|
+
* about and a number the reader watches change under them. A component library
|
|
10
|
+
* has no way to know which locale a host has configured either, so the
|
|
11
|
+
* separator has to be a decision the kit makes once.
|
|
12
|
+
*
|
|
13
|
+
* `en-US` because that is the language every string in the kit is written in,
|
|
14
|
+
* and an English sentence carrying a German separator is the worse of the two
|
|
15
|
+
* inconsistencies.
|
|
16
|
+
*
|
|
17
|
+
* Not exported from the package entry point - this is an implementation detail.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* A count, grouped in threes.
|
|
21
|
+
*
|
|
22
|
+
* A value that is not a finite number reads as zero rather than reaching the
|
|
23
|
+
* formatter, which spells infinity as a glyph no summary line should carry and
|
|
24
|
+
* NaN as a word no reader can act on.
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatCount(n: number): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Digit grouping for a figure a reader is meant to take in at a glance.
|
|
3
|
+
*
|
|
4
|
+
* The locale is fixed rather than the runtime's. `toLocaleString()` with no
|
|
5
|
+
* argument formats by whatever locale the environment reports, and the server
|
|
6
|
+
* that renders a page and the browser that hydrates it do not have to report
|
|
7
|
+
* the same one: the same figure then arrives as `4,210` in the HTML and as
|
|
8
|
+
* `4.210` or `4210` after hydration, which is a mismatch the framework warns
|
|
9
|
+
* about and a number the reader watches change under them. A component library
|
|
10
|
+
* has no way to know which locale a host has configured either, so the
|
|
11
|
+
* separator has to be a decision the kit makes once.
|
|
12
|
+
*
|
|
13
|
+
* `en-US` because that is the language every string in the kit is written in,
|
|
14
|
+
* and an English sentence carrying a German separator is the worse of the two
|
|
15
|
+
* inconsistencies.
|
|
16
|
+
*
|
|
17
|
+
* Not exported from the package entry point - this is an implementation detail.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Built at module load, not per call.
|
|
21
|
+
*
|
|
22
|
+
* Constructing an `Intl` formatter is the expensive half of using one, and a
|
|
23
|
+
* pager re-renders on every keystroke that filters the list behind it.
|
|
24
|
+
*/
|
|
25
|
+
const GROUPED = new Intl.NumberFormat('en-US');
|
|
26
|
+
/**
|
|
27
|
+
* A count, grouped in threes.
|
|
28
|
+
*
|
|
29
|
+
* A value that is not a finite number reads as zero rather than reaching the
|
|
30
|
+
* formatter, which spells infinity as a glyph no summary line should carry and
|
|
31
|
+
* NaN as a word no reader can act on.
|
|
32
|
+
*/
|
|
33
|
+
export function formatCount(n) {
|
|
34
|
+
return Number.isFinite(n) ? GROUPED.format(n) : '0';
|
|
35
|
+
}
|
package/package.json
CHANGED