@lyeve-labs/ui-kit 0.31.1 → 0.32.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/README.md +9 -9
- package/dist/components/AccordionItem.svelte +1 -1
- package/dist/components/AccountMenu.svelte +2 -2
- package/dist/components/AccountMenu.svelte.d.ts +1 -1
- package/dist/components/Alert.svelte +2 -2
- package/dist/components/Alert.svelte.d.ts +1 -1
- package/dist/components/AppShell.svelte +7 -7
- package/dist/components/AppShell.svelte.d.ts +2 -2
- package/dist/components/AuthShell.svelte +1 -1
- package/dist/components/AuthShell.svelte.d.ts +1 -1
- package/dist/components/Autocomplete.svelte +1 -1
- package/dist/components/Badge.svelte +2 -2
- package/dist/components/Banner.svelte +1 -1
- package/dist/components/Banner.svelte.d.ts +1 -1
- package/dist/components/Button.svelte +5 -5
- package/dist/components/Button.svelte.d.ts +1 -1
- package/dist/components/Card.svelte +2 -2
- package/dist/components/Checkbox.svelte +3 -3
- package/dist/components/CheckoutSteps.svelte +54 -0
- package/dist/components/CheckoutSteps.svelte.d.ts +12 -0
- package/dist/components/Collapsible.svelte +1 -1
- package/dist/components/Collapsible.svelte.d.ts +1 -1
- package/dist/components/CopyField.svelte +2 -2
- package/dist/components/Field.svelte +1 -1
- package/dist/components/Field.svelte.d.ts +1 -1
- package/dist/components/FileInput.svelte +1 -1
- package/dist/components/FormMessage.svelte +4 -4
- package/dist/components/Logo.svelte +1 -1
- package/dist/components/Logo.svelte.d.ts +1 -1
- package/dist/components/MultiSelect.svelte +1 -1
- package/dist/components/PageHeader.svelte +2 -2
- package/dist/components/PageShell.svelte +4 -4
- package/dist/components/PageShell.svelte.d.ts +4 -4
- package/dist/components/Pagination.svelte +2 -2
- package/dist/components/Panel.svelte +1 -1
- package/dist/components/Panel.svelte.d.ts +1 -1
- package/dist/components/PluginCart.svelte +339 -0
- package/dist/components/PluginCart.svelte.d.ts +45 -0
- package/dist/components/Radio.svelte +2 -2
- package/dist/components/SearchInput.svelte +2 -2
- package/dist/components/SegmentedControl.svelte +4 -4
- package/dist/components/SegmentedControl.svelte.d.ts +2 -2
- package/dist/components/Select.svelte +5 -5
- package/dist/components/Select.svelte.d.ts +4 -4
- package/dist/components/SidebarNav.svelte +5 -5
- package/dist/components/Stat.svelte +1 -1
- package/dist/components/Stat.svelte.d.ts +1 -1
- package/dist/components/Table.svelte +4 -4
- package/dist/components/Tabs.svelte +2 -2
- package/dist/components/ThemeToggle.svelte +1 -1
- package/dist/components/TimePicker.svelte +2 -2
- package/dist/components/Toggle.svelte +3 -3
- package/dist/components/Toolbar.svelte +1 -1
- package/dist/components/Toolbar.svelte.d.ts +1 -1
- package/dist/components/TreeView.svelte +1 -1
- package/dist/components/dialog/Dialog.svelte +1 -1
- package/dist/components/dialog/DialogContainer.svelte +1 -1
- package/dist/components/dialog/dialog-manager.svelte.d.ts +3 -3
- package/dist/components/dialog/dialog-manager.svelte.js +7 -7
- package/dist/components/dialog/types.d.ts +3 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +8 -5
- package/dist/internal/calendar.d.ts +1 -1
- package/dist/internal/calendar.js +2 -2
- package/dist/internal/choice.d.ts +6 -6
- package/dist/internal/choice.js +6 -6
- package/dist/internal/copy.svelte.d.ts +2 -2
- package/dist/internal/copy.svelte.js +2 -2
- package/dist/internal/field.d.ts +11 -11
- package/dist/internal/field.js +12 -12
- package/dist/internal/filter.d.ts +3 -3
- package/dist/internal/filter.js +3 -3
- package/dist/internal/href.d.ts +1 -1
- package/dist/internal/href.js +1 -1
- package/dist/internal/layout.d.ts +7 -7
- package/dist/internal/layout.js +7 -7
- package/dist/internal/listbox.svelte.d.ts +1 -1
- package/dist/internal/listbox.svelte.js +3 -3
- package/dist/internal/nav-expansion.svelte.d.ts +1 -1
- package/dist/internal/nav-expansion.svelte.js +2 -2
- package/dist/internal/nav-tree.d.ts +3 -3
- package/dist/internal/nav-tree.js +3 -3
- package/dist/internal/number.d.ts +1 -1
- package/dist/internal/number.js +1 -1
- package/dist/internal/overlay.d.ts +3 -3
- package/dist/internal/overlay.js +3 -3
- package/dist/internal/panel.d.ts +5 -5
- package/dist/internal/panel.js +5 -5
- package/dist/internal/pricing.d.ts +110 -0
- package/dist/internal/pricing.js +77 -0
- package/dist/internal/rollup.d.ts +3 -3
- package/dist/internal/rollup.js +3 -3
- package/dist/internal/scroll-edges.d.ts +4 -4
- package/dist/internal/scroll-edges.js +5 -5
- package/dist/internal/time.d.ts +3 -3
- package/dist/internal/time.js +3 -3
- package/dist/internal/tone.d.ts +3 -3
- package/dist/internal/tone.js +3 -3
- package/dist/internal/touch.d.ts +1 -1
- package/dist/internal/touch.js +1 -1
- package/dist/internal/tree.d.ts +2 -2
- package/dist/internal/tree.js +2 -2
- package/dist/motion.d.ts +3 -3
- package/dist/motion.js +4 -4
- package/dist/stores/toast.svelte.d.ts +1 -1
- package/dist/styles/theme.css +45 -45
- package/dist/utils/cn.d.ts +1 -1
- package/dist/utils/theme.d.ts +6 -6
- package/dist/utils/theme.js +10 -10
- package/package.json +1 -1
- package/src/lib/styles/theme.css +45 -45
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cart's shape and the volume ladder, shared by every surface that sells.
|
|
3
|
+
*
|
|
4
|
+
* Two sites sold the same catalog from two components. One posted the
|
|
5
|
+
* selection to the server and rendered the price that came back, the other
|
|
6
|
+
* computed a total in the browser from a catalog it had fetched, with a
|
|
7
|
+
* hardcoded list behind it for when the fetch failed. They agreed by
|
|
8
|
+
* coincidence, and the second carried a comment recording how thin the
|
|
9
|
+
* coincidence was: the discount has to be truncated rather than rounded, or
|
|
10
|
+
* the quote is a cent deeper than the charge.
|
|
11
|
+
*
|
|
12
|
+
* So nothing here computes a price. The types describe what the sales API
|
|
13
|
+
* returns, and the functions are presentation over the ladder: which rung a
|
|
14
|
+
* selection stands on and how far the next one is. The total always comes
|
|
15
|
+
* from the server, on both sites, because a price computed twice is a price
|
|
16
|
+
* that will disagree once.
|
|
17
|
+
*/
|
|
18
|
+
export function ladderState(brackets, count) {
|
|
19
|
+
const sorted = [...brackets].sort((a, b) => a.plugins - b.plugins);
|
|
20
|
+
const reachedPct = sorted
|
|
21
|
+
.filter((b) => b.plugins <= count)
|
|
22
|
+
.reduce((m, b) => Math.max(m, b.discount_pct), 0);
|
|
23
|
+
const step = sorted.find((b) => b.plugins > count && b.discount_pct > reachedPct);
|
|
24
|
+
let active = -1;
|
|
25
|
+
sorted.forEach((b, i) => {
|
|
26
|
+
if (count >= b.plugins)
|
|
27
|
+
active = i;
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
count,
|
|
31
|
+
reachedPct,
|
|
32
|
+
next: step
|
|
33
|
+
? { plugins: step.plugins, discount_pct: step.discount_pct, more: step.plugins - count }
|
|
34
|
+
: null,
|
|
35
|
+
active,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* How many capabilities the bill will carry.
|
|
40
|
+
*
|
|
41
|
+
* For a new cart that is what is selected. For a change to a live
|
|
42
|
+
* subscription it is what is held as well, because that is the count the
|
|
43
|
+
* server prices the change at. Reading the cart alone put a subscriber on the
|
|
44
|
+
* list-price rung beside a total that had already taken the discount.
|
|
45
|
+
*/
|
|
46
|
+
export function billedCount(opts) {
|
|
47
|
+
const added = new Set(opts.selected);
|
|
48
|
+
if (!opts.change)
|
|
49
|
+
return added.size;
|
|
50
|
+
if (opts.pricedSkus)
|
|
51
|
+
return new Set(opts.pricedSkus).size;
|
|
52
|
+
return new Set([...(opts.held ?? []), ...added]).size;
|
|
53
|
+
}
|
|
54
|
+
/** One row per rung, labeled by the range it covers. */
|
|
55
|
+
export function ladderRows(brackets) {
|
|
56
|
+
const sorted = [...brackets].sort((a, b) => a.plugins - b.plugins);
|
|
57
|
+
return sorted.map((b, i) => {
|
|
58
|
+
const next = sorted[i + 1];
|
|
59
|
+
return { from: b.plugins, to: next ? next.plugins - 1 : null, discount_pct: b.discount_pct };
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Money, for display.
|
|
64
|
+
*
|
|
65
|
+
* The locale is fixed for the reason `number.ts` states: a server and the
|
|
66
|
+
* browser that hydrates its output do not have to report the same one, and a
|
|
67
|
+
* figure that changes under the reader is worse than one that is not local to
|
|
68
|
+
* them.
|
|
69
|
+
*/
|
|
70
|
+
export function formatCents(cents, currency = 'USD') {
|
|
71
|
+
return new Intl.NumberFormat('en-US', {
|
|
72
|
+
style: 'currency',
|
|
73
|
+
currency,
|
|
74
|
+
minimumFractionDigits: 2,
|
|
75
|
+
maximumFractionDigits: 2,
|
|
76
|
+
}).format(cents / 100);
|
|
77
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The tri-state contract behind a permissions matrix and a checkable tree.
|
|
3
3
|
*
|
|
4
|
-
* A parent control does two jobs at once: it
|
|
4
|
+
* A parent control does two jobs at once: it summarizes the rows beneath it,
|
|
5
5
|
* and a click on it writes every one of them. Both surfaces folded that summary
|
|
6
6
|
* with `rows.every(has)`, which is true over an empty array, so a group whose
|
|
7
7
|
* rows were all filtered away or all disabled drew as fully granted and the
|
|
8
|
-
* click that followed meant clear rather than fill.
|
|
8
|
+
* click that followed meant clear rather than fill. Summarizing by count rather
|
|
9
9
|
* than by fold, and separating what may be written from what is counted, is the
|
|
10
10
|
* whole reason this module exists.
|
|
11
11
|
*
|
|
12
|
-
* Not exported from the package entry point
|
|
12
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
13
13
|
*/
|
|
14
14
|
/** What a parent control shows: nothing granted, part granted, all granted. */
|
|
15
15
|
export type TriState = 'none' | 'some' | 'all';
|
package/dist/internal/rollup.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The tri-state contract behind a permissions matrix and a checkable tree.
|
|
3
3
|
*
|
|
4
|
-
* A parent control does two jobs at once: it
|
|
4
|
+
* A parent control does two jobs at once: it summarizes the rows beneath it,
|
|
5
5
|
* and a click on it writes every one of them. Both surfaces folded that summary
|
|
6
6
|
* with `rows.every(has)`, which is true over an empty array, so a group whose
|
|
7
7
|
* rows were all filtered away or all disabled drew as fully granted and the
|
|
8
|
-
* click that followed meant clear rather than fill.
|
|
8
|
+
* click that followed meant clear rather than fill. Summarizing by count rather
|
|
9
9
|
* than by fold, and separating what may be written from what is counted, is the
|
|
10
10
|
* whole reason this module exists.
|
|
11
11
|
*
|
|
12
|
-
* Not exported from the package entry point
|
|
12
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
13
13
|
*/
|
|
14
14
|
/**
|
|
15
15
|
* Rolls a set of rows up to one state.
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
* the tab past the edge is otherwise unannounced. The arithmetic is the same
|
|
7
7
|
* in both and lives here so a third scroller cannot get it subtly different.
|
|
8
8
|
*
|
|
9
|
-
* Not exported from the package entry point
|
|
9
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
10
10
|
*/
|
|
11
11
|
export interface ScrollEdges {
|
|
12
12
|
before: boolean;
|
|
13
13
|
after: boolean;
|
|
14
14
|
}
|
|
15
|
-
/** The three metrics the answer is read from
|
|
15
|
+
/** The three metrics the answer is read from. An element has all of them. */
|
|
16
16
|
export interface ScrollMetrics {
|
|
17
17
|
scrollWidth: number;
|
|
18
18
|
clientWidth: number;
|
|
@@ -22,8 +22,8 @@ export declare function scrollEdges(el: ScrollMetrics): ScrollEdges;
|
|
|
22
22
|
/**
|
|
23
23
|
* The fade itself: a dark gradient on the edge, outside the scroll box so it
|
|
24
24
|
* does not scroll away with the content it describes. Dark rather than a
|
|
25
|
-
* palette
|
|
26
|
-
* a card in another and no surface token is the
|
|
25
|
+
* palette color, because the box sits on the page in one place and inside
|
|
26
|
+
* a card in another and no surface token is the color to fade to. The
|
|
27
27
|
* scrims use black at an alpha for the same reason and it reads in both
|
|
28
28
|
* themes. The direction is logical, so a right-to-left page fades the other
|
|
29
29
|
* way.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* the tab past the edge is otherwise unannounced. The arithmetic is the same
|
|
7
7
|
* in both and lives here so a third scroller cannot get it subtly different.
|
|
8
8
|
*
|
|
9
|
-
* Not exported from the package entry point
|
|
9
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
10
10
|
*/
|
|
11
11
|
export function scrollEdges(el) {
|
|
12
12
|
const slack = el.scrollWidth - el.clientWidth;
|
|
@@ -16,14 +16,14 @@ export function scrollEdges(el) {
|
|
|
16
16
|
return { before: false, after: false };
|
|
17
17
|
// A right-to-left box reports the offset as a negative number, and the two
|
|
18
18
|
// edges are the same two edges either way round.
|
|
19
|
-
const
|
|
20
|
-
return { before:
|
|
19
|
+
const traveled = Math.abs(el.scrollLeft);
|
|
20
|
+
return { before: traveled > 1, after: traveled < slack - 1 };
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* The fade itself: a dark gradient on the edge, outside the scroll box so it
|
|
24
24
|
* does not scroll away with the content it describes. Dark rather than a
|
|
25
|
-
* palette
|
|
26
|
-
* a card in another and no surface token is the
|
|
25
|
+
* palette color, because the box sits on the page in one place and inside
|
|
26
|
+
* a card in another and no surface token is the color to fade to. The
|
|
27
27
|
* scrims use black at an alpha for the same reason and it reads in both
|
|
28
28
|
* themes. The direction is logical, so a right-to-left page fades the other
|
|
29
29
|
* way.
|
package/dist/internal/time.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* rewrites a legal time, and a modulo that turns midnight into hour zero of a
|
|
17
17
|
* clock with no hour zero.
|
|
18
18
|
*
|
|
19
|
-
* Not exported from the package entry point
|
|
19
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
20
20
|
*/
|
|
21
21
|
/** One time, already range checked. `mi` rather than `m` so it cannot read as months. */
|
|
22
22
|
export interface TimeParts {
|
|
@@ -47,7 +47,7 @@ export declare function parseISOTime(s: string | undefined | null): TimeParts |
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function toISOTime(p: TimeParts, seconds: boolean): string;
|
|
49
49
|
/**
|
|
50
|
-
* Steps one segment without carrying into its
|
|
50
|
+
* Steps one segment without carrying into its neighbor. Stepping the minute
|
|
51
51
|
* past 59 wraps to 0 and leaves the hour alone, because a spinner that changes
|
|
52
52
|
* two fields at once is not what the arrow key promised.
|
|
53
53
|
*
|
|
@@ -91,7 +91,7 @@ export declare function to12Hour(h: number): {
|
|
|
91
91
|
meridiem: 'AM' | 'PM';
|
|
92
92
|
};
|
|
93
93
|
/**
|
|
94
|
-
* 12-hour back to 24. 12 AM is hour 0 and 12 PM is hour 12
|
|
94
|
+
* 12-hour back to 24. 12 AM is hour 0 and 12 PM is hour 12. Every other hour is
|
|
95
95
|
* itself in the morning and itself plus twelve in the afternoon.
|
|
96
96
|
*/
|
|
97
97
|
export declare function from12Hour(hour: number, meridiem: 'AM' | 'PM'): number;
|
package/dist/internal/time.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* rewrites a legal time, and a modulo that turns midnight into hour zero of a
|
|
17
17
|
* clock with no hour zero.
|
|
18
18
|
*
|
|
19
|
-
* Not exported from the package entry point
|
|
19
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
20
20
|
*/
|
|
21
21
|
/** Highest legal value plus one, per stepped segment. */
|
|
22
22
|
const SEGMENT_SIZE = {
|
|
@@ -67,7 +67,7 @@ export function toISOTime(p, seconds) {
|
|
|
67
67
|
return seconds ? `${base}:${pad2(p.s)}` : base;
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
|
-
* Steps one segment without carrying into its
|
|
70
|
+
* Steps one segment without carrying into its neighbor. Stepping the minute
|
|
71
71
|
* past 59 wraps to 0 and leaves the hour alone, because a spinner that changes
|
|
72
72
|
* two fields at once is not what the arrow key promised.
|
|
73
73
|
*
|
|
@@ -149,7 +149,7 @@ export function to12Hour(h) {
|
|
|
149
149
|
return { hour: wrapped === 0 ? 12 : wrapped, meridiem: h < 12 ? 'AM' : 'PM' };
|
|
150
150
|
}
|
|
151
151
|
/**
|
|
152
|
-
* 12-hour back to 24. 12 AM is hour 0 and 12 PM is hour 12
|
|
152
|
+
* 12-hour back to 24. 12 AM is hour 0 and 12 PM is hour 12. Every other hour is
|
|
153
153
|
* itself in the morning and itself plus twelve in the afternoon.
|
|
154
154
|
*/
|
|
155
155
|
export function from12Hour(hour, meridiem) {
|
package/dist/internal/tone.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Alert, Banner and the toast store each named their neutral-informational tone
|
|
5
5
|
* `info`, while Badge, Tag, Indicator and Progress named the same brand-cyan
|
|
6
6
|
* tone `brand`. A consumer building a status row had to remember which
|
|
7
|
-
* component wanted which word for the same
|
|
8
|
-
* it names the token the tone actually resolves to
|
|
7
|
+
* component wanted which word for the same color. `brand` is canonical because
|
|
8
|
+
* it names the token the tone actually resolves to. `info` still works and maps
|
|
9
9
|
* onto it, so nothing that already ships has to change.
|
|
10
10
|
*/
|
|
11
11
|
/** Tones a status surface can carry. */
|
|
@@ -20,7 +20,7 @@ export declare function statusTone(tone: StatusToneInput): StatusTone;
|
|
|
20
20
|
* The glyph each status tone draws, as SVG path data on a 24x24 grid.
|
|
21
21
|
*
|
|
22
22
|
* Alert and Toaster drew these as the literal characters ℹ ✓ ! ×, which pick up
|
|
23
|
-
* whatever the user's font does with them
|
|
23
|
+
* whatever the user's font does with them: the check and the cross landed at
|
|
24
24
|
* different optical weights from every other icon in the library, all of which
|
|
25
25
|
* are stroked SVG.
|
|
26
26
|
*/
|
package/dist/internal/tone.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Alert, Banner and the toast store each named their neutral-informational tone
|
|
5
5
|
* `info`, while Badge, Tag, Indicator and Progress named the same brand-cyan
|
|
6
6
|
* tone `brand`. A consumer building a status row had to remember which
|
|
7
|
-
* component wanted which word for the same
|
|
8
|
-
* it names the token the tone actually resolves to
|
|
7
|
+
* component wanted which word for the same color. `brand` is canonical because
|
|
8
|
+
* it names the token the tone actually resolves to. `info` still works and maps
|
|
9
9
|
* onto it, so nothing that already ships has to change.
|
|
10
10
|
*/
|
|
11
11
|
/** Resolves the accepted spelling to the canonical one. */
|
|
@@ -16,7 +16,7 @@ export function statusTone(tone) {
|
|
|
16
16
|
* The glyph each status tone draws, as SVG path data on a 24x24 grid.
|
|
17
17
|
*
|
|
18
18
|
* Alert and Toaster drew these as the literal characters ℹ ✓ ! ×, which pick up
|
|
19
|
-
* whatever the user's font does with them
|
|
19
|
+
* whatever the user's font does with them: the check and the cross landed at
|
|
20
20
|
* different optical weights from every other icon in the library, all of which
|
|
21
21
|
* are stroked SVG.
|
|
22
22
|
*/
|
package/dist/internal/touch.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* value of `--spacing-control` and the `hit-area` utility all live beside the
|
|
8
8
|
* palette so a consumer's build emits them.
|
|
9
9
|
*
|
|
10
|
-
* Not exported from the package entry point
|
|
10
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* The control grows. For a control whose visual may take the finger's size:
|
package/dist/internal/touch.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* value of `--spacing-control` and the `hit-area` utility all live beside the
|
|
8
8
|
* palette so a consumer's build emits them.
|
|
9
9
|
*
|
|
10
|
-
* Not exported from the package entry point
|
|
10
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* The control grows. For a control whose visual may take the finger's size:
|
package/dist/internal/tree.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The shape of a data tree and the arithmetic a checkable one needs.
|
|
3
3
|
*
|
|
4
4
|
* A data tree is not a navigation menu. A menu shows where you can go and one
|
|
5
|
-
* item is current
|
|
5
|
+
* item is current. A tree shows a structure, and a branch in it summarizes
|
|
6
6
|
* everything beneath it while a click on that branch writes every one of them.
|
|
7
7
|
* Those two jobs are the reason this module exists: the summary and the write
|
|
8
8
|
* have to be computed from the same list, or a branch reports a state its own
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* here. That module already holds the case a fold gets wrong, and a second
|
|
13
13
|
* implementation of it would be a second chance to get it wrong.
|
|
14
14
|
*
|
|
15
|
-
* Not exported from the package entry point
|
|
15
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
16
16
|
*/
|
|
17
17
|
import type { Component } from 'svelte';
|
|
18
18
|
import { type TriState } from './rollup.js';
|
package/dist/internal/tree.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The shape of a data tree and the arithmetic a checkable one needs.
|
|
3
3
|
*
|
|
4
4
|
* A data tree is not a navigation menu. A menu shows where you can go and one
|
|
5
|
-
* item is current
|
|
5
|
+
* item is current. A tree shows a structure, and a branch in it summarizes
|
|
6
6
|
* everything beneath it while a click on that branch writes every one of them.
|
|
7
7
|
* Those two jobs are the reason this module exists: the summary and the write
|
|
8
8
|
* have to be computed from the same list, or a branch reports a state its own
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* here. That module already holds the case a fold gets wrong, and a second
|
|
13
13
|
* implementation of it would be a second chance to get it wrong.
|
|
14
14
|
*
|
|
15
|
-
* Not exported from the package entry point
|
|
15
|
+
* Not exported from the package entry point: this is an implementation detail.
|
|
16
16
|
*/
|
|
17
17
|
import { nextState, rollUp, setSubtree } from './rollup.js';
|
|
18
18
|
/**
|
package/dist/motion.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare const FALLBACK: {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* What a preset hands Svelte. The function form is resolved once the element
|
|
21
|
-
* is in the DOM, with the direction the animation is really playing in
|
|
21
|
+
* is in the DOM, with the direction the animation is really playing in. Under
|
|
22
22
|
* `transition:` the directive itself only ever says `both`, so this is the
|
|
23
23
|
* one way a single directive can tune its exit apart from its entrance.
|
|
24
24
|
*/
|
|
@@ -38,7 +38,7 @@ export declare function bezier(x1: number, y1: number, x2: number, y2: number):
|
|
|
38
38
|
export declare function easing(curve: Curve): (x: number) => number;
|
|
39
39
|
/** True when the document asked for no motion, or cannot play any. */
|
|
40
40
|
export declare function still(node: Element): boolean;
|
|
41
|
-
/** A
|
|
41
|
+
/** A centered dialog: rises a little and settles to full size. */
|
|
42
42
|
export declare const dialog: (node: Element) => Motion;
|
|
43
43
|
/** The scrim behind a dialog or drawer, on the same clock as its surface. */
|
|
44
44
|
export declare const scrim: (node: Element) => Motion;
|
|
@@ -55,7 +55,7 @@ export declare const popover: (node: Element) => Motion;
|
|
|
55
55
|
export declare const toast: (node: Element) => Motion;
|
|
56
56
|
/**
|
|
57
57
|
* Siblings closing the gap a removed item leaves, for `animate:`. Svelte's
|
|
58
|
-
* flip measures the move
|
|
58
|
+
* flip measures the move. The kit supplies the clock.
|
|
59
59
|
*/
|
|
60
60
|
export declare function reorder(node: Element, positions: {
|
|
61
61
|
from: DOMRect;
|
package/dist/motion.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* <li animate:motion.reorder>
|
|
7
7
|
*
|
|
8
8
|
* `|global` is not optional. A Svelte transition is local by default and
|
|
9
|
-
* plays only when its own block toggles
|
|
9
|
+
* plays only when its own block toggles. A page that wraps a Modal in its own
|
|
10
10
|
* `{#if}` to reset the form each time removes the whole component, and a
|
|
11
11
|
* local exit never runs. Global plays it on any ancestor change.
|
|
12
12
|
*
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* and a test holds them equal to the tokens.
|
|
23
23
|
*
|
|
24
24
|
* Two cases return no duration at all. A reader who asked for reduced motion
|
|
25
|
-
* gets the state change and none of the travel
|
|
25
|
+
* gets the state change and none of the travel. The reduced-motion block in
|
|
26
26
|
* theme.css cannot reach these, because Svelte drives them through the Web
|
|
27
27
|
* Animations API and not through a stylesheet. And a document with no
|
|
28
28
|
* `Element.animate`, which is every jsdom test, mounts and unmounts at once,
|
|
@@ -143,7 +143,7 @@ function surface(rung, css) {
|
|
|
143
143
|
};
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
|
-
/** A
|
|
146
|
+
/** A centered dialog: rises a little and settles to full size. */
|
|
147
147
|
export const dialog = surface('slow', (t, u) => `opacity: ${t}; transform: translateY(${8 * u}px) scale(${0.96 + 0.04 * t})`);
|
|
148
148
|
/** The scrim behind a dialog or drawer, on the same clock as its surface. */
|
|
149
149
|
export const scrim = surface('slow', (t) => `opacity: ${t}`);
|
|
@@ -161,7 +161,7 @@ export const popover = surface('base', (t, u) => `opacity: ${t}; transform: tran
|
|
|
161
161
|
export const toast = surface('base', (t, u) => `opacity: ${t}; transform: translateY(${8 * u}px) scale(${0.96 + 0.04 * t})`);
|
|
162
162
|
/**
|
|
163
163
|
* Siblings closing the gap a removed item leaves, for `animate:`. Svelte's
|
|
164
|
-
* flip measures the move
|
|
164
|
+
* flip measures the move. The kit supplies the clock.
|
|
165
165
|
*/
|
|
166
166
|
export function reorder(node, positions, _params) {
|
|
167
167
|
if (still(node))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { StatusToneInput } from '../internal/tone.js';
|
|
2
2
|
/**
|
|
3
3
|
* A toast carries the same tone vocabulary as Alert and Banner. `brand` is the
|
|
4
|
-
* canonical name
|
|
4
|
+
* canonical name. `info` is kept because `toast.info(...)` already ships.
|
|
5
5
|
*/
|
|
6
6
|
export type ToastTone = StatusToneInput;
|
|
7
7
|
export interface Toast {
|
package/dist/styles/theme.css
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* @lyeve-labs/ui-kit
|
|
2
|
+
* @lyeve-labs/ui-kit: theme tokens
|
|
3
3
|
*
|
|
4
4
|
* A single CSS file imported once at the top of your app's root stylesheet.
|
|
5
|
-
* Declares two palettes
|
|
5
|
+
* Declares two palettes, Soft Dark (default) and Soft Light, built from
|
|
6
6
|
* the LyEve brand guideline (Ink #0B1422 + Cyan #00D4FF) and exposes them
|
|
7
7
|
* as Tailwind v4 `@theme` tokens.
|
|
8
8
|
*
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
--color-line-strong: #616d80;
|
|
45
45
|
--color-fg: #e6e8ee;
|
|
46
46
|
--color-muted: #9aa1ad;
|
|
47
|
-
/* #525866 failed WCAG AA against surface/ink (~2.5:1)
|
|
47
|
+
/* #525866 failed WCAG AA against surface/ink (~2.5:1). Every caption and
|
|
48
48
|
* metadata label uses faint, so one token fix clears the systemic
|
|
49
49
|
* violation. #8b94a7 sits at ~5.6:1 on surface and ~5.9:1 on ink. */
|
|
50
50
|
--color-faint: #8b94a7;
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
* tokens because the brand ramp above is tuned for text contrast: in the
|
|
62
62
|
* light theme it darkens to #005a77 and brand-light sits below brand, so a
|
|
63
63
|
* mark painted from it inverts its lighting. A logotype is exempt from the
|
|
64
|
-
* contrast floor, so these keep the published
|
|
64
|
+
* contrast floor, so these keep the published colors instead. */
|
|
65
65
|
--color-mark-ink: #ffffff;
|
|
66
66
|
--color-mark-foot: #9aa1ad;
|
|
67
67
|
--color-mark-step: #c5cad3;
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
* cannot work as a foreground on a dark surface.
|
|
80
80
|
*
|
|
81
81
|
* One token serves both roles because it inverts with `ink`. As text on a
|
|
82
|
-
* dark surface #f87171 reads 6.30:1
|
|
82
|
+
* dark surface #f87171 reads 6.30:1. As the fill behind a `text-ink` label
|
|
83
83
|
* on a filled destructive button it reads 6.67:1. The light palette does
|
|
84
84
|
* the same in reverse with a dark red and a near-white ink. */
|
|
85
85
|
--color-danger: #f87171;
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
--radius-xl: 16px;
|
|
93
93
|
--radius-2xl: 24px;
|
|
94
94
|
|
|
95
|
-
/* -- Elevation
|
|
95
|
+
/* -- Elevation: the stacking order of everything that floats --- *
|
|
96
96
|
* Every floating surface in the kit carried a bare z-50, so which
|
|
97
97
|
* one won was decided by document order: a Dropdown opened after a
|
|
98
98
|
* Modal painted over it, and the same two in the other order did
|
|
@@ -123,16 +123,16 @@
|
|
|
123
123
|
--z-index-dropdown: 100; /* a panel anchored to its trigger */
|
|
124
124
|
--z-index-overlay: 200; /* the scrim behind a drawer or modal */
|
|
125
125
|
--z-index-drawer: 300; /* a panel docked to a viewport edge */
|
|
126
|
-
--z-index-modal: 400; /* a
|
|
126
|
+
--z-index-modal: 400; /* a centered dialog, and the stack */
|
|
127
127
|
--z-index-tooltip: 500; /* a label attached to a control */
|
|
128
128
|
--z-index-toast: 600; /* transient status */
|
|
129
129
|
--z-index-skip-link: 700; /* the first tab stop in the document */
|
|
130
130
|
|
|
131
|
-
/* -- Motion
|
|
131
|
+
/* -- Motion: four durations, three curves, one rule for exits -- *
|
|
132
132
|
* Named for what they are used for, so the choice is made by
|
|
133
133
|
* reading the name:
|
|
134
134
|
*
|
|
135
|
-
* fast a state change in place:
|
|
135
|
+
* fast a state change in place: color, opacity, border,
|
|
136
136
|
* shadow, focus
|
|
137
137
|
* base movement in place (a knob, a chevron, a collapse, a
|
|
138
138
|
* tab indicator) and a small surface arriving (menu,
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
* move changing in place
|
|
146
146
|
*
|
|
147
147
|
* An exit runs one rung faster than its entrance and on exit:
|
|
148
|
-
* slow in, base out
|
|
148
|
+
* slow in, base out. Base in, fast out. Entrances and exits move
|
|
149
149
|
* only opacity and transform.
|
|
150
150
|
*
|
|
151
151
|
* Tailwind builds no utility from a --duration-* token: there is
|
|
@@ -161,8 +161,8 @@
|
|
|
161
161
|
* wrote `duration-150` fifty times to say the same thing.
|
|
162
162
|
*
|
|
163
163
|
* The reduced-motion block at the foot of this file overrides
|
|
164
|
-
* every one of them and stays the authority on whether they run
|
|
165
|
-
*
|
|
164
|
+
* every one of them and stays the authority on whether they run.
|
|
165
|
+
* The Svelte presets in motion.ts honor the same preference for
|
|
166
166
|
* the entrances and exits that run outside CSS. */
|
|
167
167
|
--duration-fast: 120ms;
|
|
168
168
|
--duration-base: 200ms;
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
|
|
179
179
|
/* The one entrance that is a CSS animation. A panel inside <details> is
|
|
180
180
|
* shown and removed by the browser, so a Svelte transition never sees it
|
|
181
|
-
* leave
|
|
181
|
+
* leave. It plays this on the way in and nothing on the way out. Every
|
|
182
182
|
* other surface enters and leaves through the presets in motion.ts. */
|
|
183
183
|
--animate-popover-in: popover-in var(--duration-base) var(--ease-enter);
|
|
184
184
|
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
--tracking-h2: -0.02em;
|
|
224
224
|
--tracking-h3: -0.015em;
|
|
225
225
|
|
|
226
|
-
/* -- Typography
|
|
226
|
+
/* -- Typography: console type scale --------------------------- *
|
|
227
227
|
* Token Size Line Where it renders *
|
|
228
228
|
* text-xs 12px 16px labels, table heads, metadata, hints*
|
|
229
229
|
* text-sm 14px 20px body copy and every control *
|
|
@@ -259,7 +259,7 @@
|
|
|
259
259
|
*
|
|
260
260
|
* A step is declared with its leading, because a --text-* token
|
|
261
261
|
* sets font-size and nothing else. Only the six steps the kit
|
|
262
|
-
* actually renders are declared
|
|
262
|
+
* actually renders are declared. The larger ones a marketing
|
|
263
263
|
* page reaches for stay as Tailwind ships them. */
|
|
264
264
|
--text-xs: 0.75rem; /* 12px */
|
|
265
265
|
--text-xs--line-height: calc(1 / 0.75); /* 16px */
|
|
@@ -277,32 +277,32 @@
|
|
|
277
277
|
/* ── Spacing grid · 4px base (semantic shortcuts) ────────────── *
|
|
278
278
|
* Tailwind's default 0.25rem (4px) grid is unchanged. *
|
|
279
279
|
* These tokens add named slots for common component spacing. */
|
|
280
|
-
--spacing-page-x: 1.5rem; /* 24px
|
|
281
|
-
--spacing-page-y: 1.5rem; /* 24px
|
|
282
|
-
* measured renders an asymmetric gutter
|
|
280
|
+
--spacing-page-x: 1.5rem; /* 24px: page horizontal gutter */
|
|
281
|
+
--spacing-page-y: 1.5rem; /* 24px: page vertical gutter. Equal to page-x because no page
|
|
282
|
+
* measured renders an asymmetric gutter. The two names stay
|
|
283
283
|
* separate so one axis can move without dragging the other. */
|
|
284
|
-
--spacing-card: 1.25rem; /* 20px
|
|
285
|
-
* surfaces in use
|
|
286
|
-
--spacing-card-sm: 1rem; /* 16px
|
|
287
|
-
--spacing-section: 2rem; /* 32px
|
|
284
|
+
--spacing-card: 1.25rem; /* 20px: card inner padding. 24px matched none of the card
|
|
285
|
+
* surfaces in use. 20px is their measured mode and Card's own md. */
|
|
286
|
+
--spacing-card-sm: 1rem; /* 16px: compact card padding */
|
|
287
|
+
--spacing-section: 2rem; /* 32px: section gap. 48px matched nothing anywhere. 32px is the
|
|
288
288
|
* gap the pages that set one already use, and PageHeader's own. */
|
|
289
|
-
--spacing-input-x: 0.75rem; /* 12px
|
|
289
|
+
--spacing-input-x: 0.75rem; /* 12px: input horizontal padding */
|
|
290
290
|
--spacing-input-y: 0.5rem; /* 8px - input vertical padding */
|
|
291
|
-
/* 38px
|
|
291
|
+
/* 38px: the height of every single-line control. Stated once so an Input,
|
|
292
292
|
* a Select and a NumberInput sitting in the same row line up. Derived from
|
|
293
293
|
* the 13px/1.25 control text plus input-y padding and a 1px border. Under a
|
|
294
|
-
* coarse pointer it is 44px
|
|
294
|
+
* coarse pointer it is 44px. See the touch-target block below the palette. */
|
|
295
295
|
--spacing-control: 2.375rem;
|
|
296
|
-
--spacing-panel-max: 15rem; /* 240px
|
|
297
|
-
/* 56px
|
|
296
|
+
--spacing-panel-max: 15rem; /* 240px: the scroll cap on a floating option list */
|
|
297
|
+
/* 56px: the app header bar, and the sidebar's brand row above the nav.
|
|
298
298
|
* One token, because the two sit side by side across the top of every
|
|
299
299
|
* authed screen and a 4px disagreement between them reads as a broken
|
|
300
300
|
* seam. Three apps each picked their own height before this existed. */
|
|
301
301
|
--spacing-header: 3.5rem;
|
|
302
|
-
--spacing-nav-indent: 0.875rem; /* 14px
|
|
303
|
-
--spacing-nav-rail: 3.5rem; /* 56px
|
|
304
|
-
--spacing-sidebar: 14rem; /* 224px
|
|
305
|
-
--spacing-stack: 1rem; /* 16px
|
|
302
|
+
--spacing-nav-indent: 0.875rem; /* 14px: one level of sidebar nesting */
|
|
303
|
+
--spacing-nav-rail: 3.5rem; /* 56px: the collapsed icon rail */
|
|
304
|
+
--spacing-sidebar: 14rem; /* 224px: the expanded sidebar */
|
|
305
|
+
--spacing-stack: 1rem; /* 16px: default vertical stack gap */
|
|
306
306
|
--spacing-inline: 0.5rem; /* 8px - default inline gap */
|
|
307
307
|
|
|
308
308
|
/* ── Widths · how much room a surface is allowed to take ───── *
|
|
@@ -317,8 +317,8 @@
|
|
|
317
317
|
* drawers asked for the widest rung there was, which is what a *
|
|
318
318
|
* ladder that stops too early looks like from the outside. */
|
|
319
319
|
--container-page-narrow: 56rem; /* 896px - one column: a form, a settings pane */
|
|
320
|
-
--container-page-default: 72rem; /* 1152px
|
|
321
|
-
--container-page-wide: 96rem; /* 1536px
|
|
320
|
+
--container-page-default: 72rem; /* 1152px: a page of stacked cards */
|
|
321
|
+
--container-page-wide: 96rem; /* 1536px: a data page whose table needs the room */
|
|
322
322
|
|
|
323
323
|
/* One ladder for every surface lifted off the page, so a drawer and
|
|
324
324
|
* a modal opened from the same screen are the same size. Each rung
|
|
@@ -328,7 +328,7 @@
|
|
|
328
328
|
--container-overlay-md: 36rem; /* 576px - up to four fields */
|
|
329
329
|
--container-overlay-lg: 44rem; /* 704px - a form with paired fields */
|
|
330
330
|
--container-overlay-xl: 56rem; /* 896px - a form beside a preview */
|
|
331
|
-
--container-overlay-full: 68rem; /* 1088px
|
|
331
|
+
--container-overlay-full: 68rem; /* 1088px: a table inside a dialog */
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
/*
|
|
@@ -350,13 +350,13 @@
|
|
|
350
350
|
*
|
|
351
351
|
* `hit-area` does not move the visual. A switch, a checkbox, a breadcrumb, a
|
|
352
352
|
* pager button, a close cross and an icon inside an input are drawn small on
|
|
353
|
-
* purpose and grown to 44px would push their
|
|
354
|
-
* draws an invisible box
|
|
353
|
+
* purpose and grown to 44px would push their neighbors around. Each one
|
|
354
|
+
* draws an invisible box centered on itself that is never smaller than the
|
|
355
355
|
* control size, and a tap on the box lands on the control. The element must
|
|
356
356
|
* be positioned (`relative`, or `absolute` where it already is) for the box
|
|
357
|
-
* to
|
|
357
|
+
* to center on it. The utility does not set position itself, because a
|
|
358
358
|
* position it set would fight the `absolute` an input's clear button relies
|
|
359
|
-
* on. Two
|
|
359
|
+
* on. Two neighbors' boxes may overlap. The later one in document order
|
|
360
360
|
* wins the overlap, which is the spacing exception SC 2.5.8 allows for.
|
|
361
361
|
*/
|
|
362
362
|
@custom-variant coarse (@media (pointer: coarse));
|
|
@@ -392,7 +392,7 @@ html[data-theme='light'] {
|
|
|
392
392
|
--color-line-strong: #767d8e;
|
|
393
393
|
--color-fg: #111827;
|
|
394
394
|
--color-muted: #525866;
|
|
395
|
-
/* Every value below is the lightest
|
|
395
|
+
/* Every value below is the lightest color on its own hue that clears
|
|
396
396
|
* 4.5:1 against the worst background the kit actually paints it on. That
|
|
397
397
|
* worst case is rarely the bare canvas: status text and brand chips sit
|
|
398
398
|
* inside a tint of their own token (bg-warn/10 text-warn), and the tint
|
|
@@ -425,7 +425,7 @@ html[data-theme='light'] {
|
|
|
425
425
|
/*
|
|
426
426
|
* A forced-colors scheme repaints the page but not a fill named in hex, so the
|
|
427
427
|
* mark's white column vanished on a white high-contrast canvas. Its neutral
|
|
428
|
-
* faces take the system
|
|
428
|
+
* faces take the system colors there. The cyan faces keep their shape.
|
|
429
429
|
*/
|
|
430
430
|
@media (forced-colors: active) {
|
|
431
431
|
:root,
|
|
@@ -515,8 +515,8 @@ html[data-theme='light'] {
|
|
|
515
515
|
/*
|
|
516
516
|
* Every animation in the kit ran regardless of what the reader asked for:
|
|
517
517
|
* the drawer slid, the toast flew in, the pulse and ping looped forever.
|
|
518
|
-
*
|
|
519
|
-
* added later, which is the only way it stays
|
|
518
|
+
* Honoring the preference once here covers every component, including any
|
|
519
|
+
* added later, which is the only way it stays honored.
|
|
520
520
|
*
|
|
521
521
|
* Durations are not zeroed. An animation that finishes in 1ms still fires its
|
|
522
522
|
* animationend, so components that wait on one keep working.
|
|
@@ -565,12 +565,12 @@ html[data-theme='light'] {
|
|
|
565
565
|
* Every kit component paints from these tokens, so redefining them here
|
|
566
566
|
* turns the whole library monochrome without a single component knowing
|
|
567
567
|
* about paper. Browsers drop backgrounds when printing by default, which
|
|
568
|
-
* left light text on the white the printer supplies
|
|
568
|
+
* left light text on the white the printer supplies. Naming white here means
|
|
569
569
|
* the two agree either way.
|
|
570
570
|
*
|
|
571
571
|
* The status hues collapse to black rather than to a print-safe tint. A
|
|
572
|
-
*
|
|
573
|
-
* and a legible black label beats an unreadable
|
|
572
|
+
* color that carries meaning on screen carries none through a mono printer,
|
|
573
|
+
* and a legible black label beats an unreadable colored one.
|
|
574
574
|
*/
|
|
575
575
|
html,
|
|
576
576
|
html[data-theme='light'] {
|