@gjsify/adwaita-web 0.36.0 → 0.37.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/dist/adwaita-web.css +433 -33
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/adw-shortcut-label.spec.d.ts +2 -0
- package/lib/types/breakpoints.d.ts +10 -12
- package/lib/types/elements/adw-about-dialog.d.ts +19 -36
- package/lib/types/elements/adw-action-row.d.ts +9 -12
- package/lib/types/elements/adw-alert-dialog.d.ts +0 -12
- package/lib/types/elements/adw-avatar.d.ts +1 -0
- package/lib/types/elements/adw-bottom-sheet.d.ts +7 -12
- package/lib/types/elements/adw-button-content.d.ts +3 -4
- package/lib/types/elements/adw-button-row.d.ts +1 -1
- package/lib/types/elements/adw-carousel.d.ts +28 -49
- package/lib/types/elements/adw-checks.d.ts +2 -8
- package/lib/types/elements/adw-combo-row.d.ts +6 -6
- package/lib/types/elements/adw-data-grid.d.ts +5 -10
- package/lib/types/elements/adw-drop-down.d.ts +3 -11
- package/lib/types/elements/adw-entry-row.d.ts +20 -23
- package/lib/types/elements/adw-icon.d.ts +2 -4
- package/lib/types/elements/adw-inline-view-switcher.d.ts +18 -31
- package/lib/types/elements/adw-navigation-split-view.d.ts +7 -12
- package/lib/types/elements/adw-navigation-view.d.ts +2 -10
- package/lib/types/elements/adw-overlay-split-view.d.ts +28 -52
- package/lib/types/elements/adw-password-entry-row.d.ts +4 -5
- package/lib/types/elements/adw-popover.d.ts +2 -7
- package/lib/types/elements/adw-preferences-dialog.d.ts +21 -34
- package/lib/types/elements/adw-preferences-group.d.ts +12 -14
- package/lib/types/elements/adw-progress-bar.d.ts +3 -4
- package/lib/types/elements/adw-shortcut-label.d.ts +20 -0
- package/lib/types/elements/adw-sidebar.d.ts +5 -10
- package/lib/types/elements/adw-spinner.d.ts +3 -5
- package/lib/types/elements/adw-split-button.d.ts +6 -16
- package/lib/types/elements/adw-switch-row.d.ts +3 -3
- package/lib/types/elements/adw-tab-view.d.ts +16 -26
- package/lib/types/elements/adw-toast-overlay.d.ts +8 -13
- package/lib/types/elements/adw-view-stack.d.ts +7 -17
- package/lib/types/elements/adw-view-switcher-bar.d.ts +4 -8
- package/lib/types/elements/adw-view-switcher.d.ts +18 -38
- package/lib/types/elements/adw-wrap-box.d.ts +7 -17
- package/lib/types/elements/view-switcher-dom.d.ts +10 -13
- package/lib/types/index.d.ts +1 -0
- package/lib/types/source-view/hex.d.ts +7 -13
- package/lib/types/style-classes.spec.d.ts +11 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/package.json +6 -6
- package/scss/_about_dialog.scss +3 -2
- package/scss/_action_row.scss +33 -0
- package/scss/_avatar.scss +12 -0
- package/scss/_button.scss +44 -22
- package/scss/_card.scss +11 -8
- package/scss/_checks.scss +2 -4
- package/scss/_dialog.scss +3 -2
- package/scss/_headerbar.scss +23 -0
- package/scss/_popover.scss +8 -4
- package/scss/_preferences.scss +7 -7
- package/scss/_progress_bar.scss +9 -6
- package/scss/_reset.scss +1 -1
- package/scss/_shortcut_label.scss +80 -0
- package/scss/_sidebar.scss +57 -0
- package/scss/_status_page.scss +20 -0
- package/scss/_style_classes.scss +407 -0
- package/scss/_switch.scss +4 -3
- package/scss/_variables.scss +25 -0
- package/scss/adwaita-skin.scss +12 -0
- package/src/adw-about-dialog.spec.ts +34 -49
- package/src/adw-action-rows.spec.ts +25 -33
- package/src/adw-avatar.spec.ts +51 -20
- package/src/adw-banner.spec.ts +5 -8
- package/src/adw-button-content.spec.ts +9 -12
- package/src/adw-button-row.spec.ts +2 -4
- package/src/adw-carousel.spec.ts +40 -53
- package/src/adw-checks.spec.ts +36 -47
- package/src/adw-drop-down.spec.ts +25 -32
- package/src/adw-header-bar.spec.ts +5 -7
- package/src/adw-icon.spec.ts +23 -32
- package/src/adw-progress-bar.spec.ts +10 -12
- package/src/adw-row-state.spec.ts +9 -10
- package/src/adw-shortcut-label.spec.ts +112 -0
- package/src/adw-sidebar.spec.ts +17 -24
- package/src/adw-switch.spec.ts +11 -17
- package/src/adw-tab-view.spec.ts +7 -10
- package/src/adw-toast-overlay.spec.ts +7 -11
- package/src/adw-view-switcher-bar.spec.ts +10 -14
- package/src/adw-wrap-box.spec.ts +25 -36
- package/src/bottom-sheet.spec.ts +30 -36
- package/src/breakpoints.ts +15 -18
- package/src/chrome.spec.ts +13 -21
- package/src/elements/adw-about-dialog.ts +71 -114
- package/src/elements/adw-action-row.ts +22 -37
- package/src/elements/adw-alert-dialog.ts +25 -50
- package/src/elements/adw-avatar.ts +40 -15
- package/src/elements/adw-banner.ts +14 -18
- package/src/elements/adw-bottom-sheet.ts +31 -52
- package/src/elements/adw-button-content.ts +30 -37
- package/src/elements/adw-button-row.ts +14 -24
- package/src/elements/adw-carousel.ts +87 -148
- package/src/elements/adw-checks.ts +43 -56
- package/src/elements/adw-clamp.ts +8 -9
- package/src/elements/adw-combo-row.ts +17 -25
- package/src/elements/adw-data-grid.ts +26 -38
- package/src/elements/adw-dialog.ts +25 -56
- package/src/elements/adw-drop-down.ts +31 -51
- package/src/elements/adw-entry-row.ts +39 -46
- package/src/elements/adw-expander-row.ts +30 -53
- package/src/elements/adw-icon.ts +30 -53
- package/src/elements/adw-inline-view-switcher.ts +38 -67
- package/src/elements/adw-menu-button.ts +28 -58
- package/src/elements/adw-navigation-split-view.ts +35 -47
- package/src/elements/adw-navigation-view.ts +12 -28
- package/src/elements/adw-overlay-split-view.ts +100 -175
- package/src/elements/adw-password-entry-row.ts +18 -28
- package/src/elements/adw-popover.ts +28 -44
- package/src/elements/adw-preferences-dialog.ts +41 -66
- package/src/elements/adw-preferences-group.ts +33 -46
- package/src/elements/adw-progress-bar.ts +27 -47
- package/src/elements/adw-shortcut-label.ts +138 -0
- package/src/elements/adw-sidebar.ts +31 -39
- package/src/elements/adw-spin-row.ts +7 -14
- package/src/elements/adw-spinner.ts +31 -43
- package/src/elements/adw-split-button.ts +45 -75
- package/src/elements/adw-switch-row.ts +29 -46
- package/src/elements/adw-switch.ts +28 -47
- package/src/elements/adw-tab-view.ts +62 -103
- package/src/elements/adw-toast-overlay.ts +28 -35
- package/src/elements/adw-toggle-group.ts +9 -16
- package/src/elements/adw-view-stack.ts +32 -51
- package/src/elements/adw-view-switcher-bar.ts +26 -50
- package/src/elements/adw-view-switcher.ts +60 -110
- package/src/elements/adw-window-title.ts +4 -4
- package/src/elements/adw-wrap-box.ts +33 -59
- package/src/elements/view-switcher-dom.ts +15 -22
- package/src/entry-rows.spec.ts +18 -24
- package/src/index.ts +13 -15
- package/src/navigation-view.spec.ts +7 -10
- package/src/preferences-search.ts +11 -15
- package/src/preferences.spec.ts +13 -15
- package/src/source-view/adw-source-view.ts +6 -19
- package/src/source-view/hex.ts +7 -13
- package/src/split-button.spec.ts +32 -44
- package/src/split-views.spec.ts +83 -149
- package/src/style-classes.spec.ts +181 -0
- package/src/style-isolation.spec.ts +3 -6
- package/src/styles.generated.ts +1 -1
- package/src/tab-view.spec.ts +26 -35
- package/src/test.browser.mts +4 -0
- package/src/view-stack.spec.ts +23 -34
- package/src/view-switcher.spec.ts +56 -84
|
@@ -4,56 +4,37 @@
|
|
|
4
4
|
// headerbar-colored strip, with the selected chip raised onto the view
|
|
5
5
|
// background.
|
|
6
6
|
//
|
|
7
|
-
// The MODEL is HEADLESS
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// DOM half only: it turns declared markup into pages, builds and MOVES tab
|
|
11
|
-
// chips, toggles visibility, reflects the selection to an attribute, re-emits
|
|
12
|
-
// changes as DOM events, and maps key chords onto the state machine.
|
|
7
|
+
// The MODEL is HEADLESS, in `@gjsify/adwaita-core`'s {@link TabViewState}
|
|
8
|
+
// (ADR 0004), shared with the NativeScript twin and specced by
|
|
9
|
+
// `@gjsify/adwaita-core/conformance`. This element is the DOM half only.
|
|
13
10
|
//
|
|
14
|
-
//
|
|
15
|
-
// -
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// -
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
11
|
+
// The C rules that are not visible in the DOM code:
|
|
12
|
+
// - closing defaults to closing a non-pinned page and DENYING a pinned one
|
|
13
|
+
// (`close_page_cb`).
|
|
14
|
+
// - an out-of-range `selected` is IGNORED, not clamped, and every path notifies,
|
|
15
|
+
// property sets included.
|
|
16
|
+
// - the bar stays up for a single PINNED tab.
|
|
17
|
+
// - the close affordance follows `tabCloseVisible` (three terms plus a pinned
|
|
18
|
+
// gate), and titles/tooltips/icons/loading stay live.
|
|
19
|
+
//
|
|
20
|
+
// Pages are declared as <adw-tab-page> children — the element itself becomes the
|
|
21
|
+
// panel, so its attributes stay live — or added imperatively. The roving tabindex
|
|
22
|
+
// must keep moving: under `role=tablist` a frozen one leaves every inactive tab
|
|
23
|
+
// keyboard-unreachable.
|
|
24
|
+
//
|
|
25
|
+
// MODIFICATION: Adw.TabBar defaults `autohide` TRUE (`DEFAULT_TAB_AUTOHIDE`); an
|
|
26
|
+
// HTML boolean attribute cannot express a TRUE default, so `autohide` is opt-in
|
|
27
|
+
// here. `no-close` is web-specific, for static tab sets such as documentation
|
|
28
|
+
// command tabs.
|
|
29
|
+
//
|
|
30
|
+
// Events (all CustomEvent, all bubbling): `notify::selected-page`
|
|
31
|
+
// (`{ selected, selectedId, previousId, interactive }`); `close-page`
|
|
32
|
+
// (`{ index, id }`), CANCELABLE and one per close ATTEMPT, where
|
|
33
|
+
// `preventDefault()` holds the page open until `closePageFinish(id, confirm)`;
|
|
34
|
+
// and `page-attached` / `page-detached` / `page-reordered` / `page-pinned` /
|
|
35
|
+
// `page-updated` (`{ id, position, previousPosition }`), one per page-list change
|
|
36
|
+
// so a bound tab bar can move ONE chip instead of rebuilding.
|
|
34
37
|
//
|
|
35
|
-
// Pages are declared as <adw-tab-page> children (the element itself becomes the
|
|
36
|
-
// page panel, so its attributes stay live) or added imperatively.
|
|
37
|
-
// Attributes:
|
|
38
|
-
// selected — zero-based index of the visible page; out-of-range is IGNORED.
|
|
39
|
-
// autohide — hide the tab bar when it has nothing to show. NB Adw.TabBar
|
|
40
|
-
// defaults this to TRUE (`DEFAULT_TAB_AUTOHIDE`); an HTML boolean attribute
|
|
41
|
-
// cannot, so this stays opt-in — a deliberate, citable inversion.
|
|
42
|
-
// expand-tabs — tabs stretch to fill the bar evenly (Adw.TabBar `expand-tabs`).
|
|
43
|
-
// no-close — render no close affordance; web-specific escape hatch for
|
|
44
|
-
// static tab sets such as documentation command tabs.
|
|
45
|
-
// <adw-tab-page> attributes: page-id, title, tooltip, icon, indicator-icon,
|
|
46
|
-
// loading, needs-attention, pinned.
|
|
47
|
-
// Events:
|
|
48
|
-
// `notify::selected-page` (CustomEvent, bubbles,
|
|
49
|
-
// detail = { selected, selectedId, previousId, interactive }).
|
|
50
|
-
// `close-page` (CustomEvent, bubbles, CANCELABLE,
|
|
51
|
-
// detail = { index, id }) — one per close ATTEMPT. `preventDefault()` holds
|
|
52
|
-
// the page open until `closePageFinish(id, confirm)`.
|
|
53
|
-
// `page-attached` / `page-detached` / `page-reordered` / `page-pinned` /
|
|
54
|
-
// `page-updated` (CustomEvent, bubbles,
|
|
55
|
-
// detail = { id, position, previousPosition }) — one per page-list change,
|
|
56
|
-
// so a bound tab bar can move ONE chip instead of rebuilding.
|
|
57
38
|
// Reference: refs/libadwaita/src/adw-tab-view.c (AdwTabView behaviour)
|
|
58
39
|
// Reference: refs/libadwaita/src/adw-tab-bar.c (AdwTabBar autohide)
|
|
59
40
|
// Reference: refs/libadwaita/src/adw-tab.c (AdwTab chip)
|
|
@@ -69,20 +50,18 @@ import type { AdwTabPageSpec, AdwTabPageState, TabViewPagesChange, TabViewSelect
|
|
|
69
50
|
|
|
70
51
|
import { type AdwIcon, createAdwIcon } from './adw-icon.js';
|
|
71
52
|
|
|
72
|
-
/** A page descriptor as `pages` exposes it. */
|
|
73
53
|
export type AdwTabViewPage = AdwTabPageState<HTMLElement>;
|
|
74
54
|
|
|
75
|
-
/** The page spec the imperative insertion methods take. */
|
|
76
55
|
export type AdwTabViewPageSpec = AdwTabPageSpec<HTMLElement>;
|
|
77
56
|
|
|
78
57
|
/** The live `<adw-tab-page>` properties, each mapped onto a state setter. */
|
|
79
58
|
const PAGE_ATTRIBUTES = ['title', 'tooltip', 'icon', 'indicator-icon', 'loading', 'needs-attention', 'pinned'];
|
|
80
59
|
|
|
81
60
|
/**
|
|
82
|
-
* A single page. Declared as a child of <adw-tab-view>; the element itself
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
61
|
+
* A single page. Declared as a child of <adw-tab-view>; the element itself becomes the
|
|
62
|
+
* page panel, so its attributes keep driving the tab after connect — a renderer that
|
|
63
|
+
* moves the children out and discards the element leaves `observedAttributes` with
|
|
64
|
+
* nothing to act on.
|
|
86
65
|
*/
|
|
87
66
|
export class AdwTabPage extends HTMLElement {
|
|
88
67
|
static get observedAttributes() {
|
|
@@ -136,8 +115,6 @@ export class AdwTabView extends HTMLElement {
|
|
|
136
115
|
this._state.subscribe((change) => this._onSelectionChange(change));
|
|
137
116
|
}
|
|
138
117
|
|
|
139
|
-
// --- Declarative surface ------------------------------------------------
|
|
140
|
-
|
|
141
118
|
/** Zero-based index of the visible page, `-1` when the view is empty. */
|
|
142
119
|
get selected(): number {
|
|
143
120
|
return this._state.selectedIndex;
|
|
@@ -160,7 +137,6 @@ export class AdwTabView extends HTMLElement {
|
|
|
160
137
|
else this.removeAttribute('autohide');
|
|
161
138
|
}
|
|
162
139
|
|
|
163
|
-
/** Whether tabs stretch to fill the bar evenly (Adw.TabBar `expand-tabs`). */
|
|
164
140
|
get expandTabs(): boolean {
|
|
165
141
|
return this.hasAttribute('expand-tabs');
|
|
166
142
|
}
|
|
@@ -250,17 +226,14 @@ export class AdwTabView extends HTMLElement {
|
|
|
250
226
|
|
|
251
227
|
// --- Model surface (thin delegations to TabViewState) --------------------
|
|
252
228
|
|
|
253
|
-
/** All pages in order. */
|
|
254
229
|
get pages(): readonly AdwTabViewPage[] {
|
|
255
230
|
return this._state.pages;
|
|
256
231
|
}
|
|
257
232
|
|
|
258
|
-
/** Number of pages. */
|
|
259
233
|
get nPages(): number {
|
|
260
234
|
return this._state.nPages;
|
|
261
235
|
}
|
|
262
236
|
|
|
263
|
-
/** Length of the pinned prefix. */
|
|
264
237
|
get nPinnedPages(): number {
|
|
265
238
|
return this._state.nPinnedPages;
|
|
266
239
|
}
|
|
@@ -275,7 +248,6 @@ export class AdwTabView extends HTMLElement {
|
|
|
275
248
|
return this._state.selectedIndex;
|
|
276
249
|
}
|
|
277
250
|
|
|
278
|
-
/** The selected page's panel element, or `null`. */
|
|
279
251
|
get selectedContent(): HTMLElement | null {
|
|
280
252
|
return this._state.selectedPage?.content ?? null;
|
|
281
253
|
}
|
|
@@ -426,8 +398,6 @@ export class AdwTabView extends HTMLElement {
|
|
|
426
398
|
return this._state.diagnostics;
|
|
427
399
|
}
|
|
428
400
|
|
|
429
|
-
// --- Adoption -----------------------------------------------------------
|
|
430
|
-
|
|
431
401
|
private _adoptDeclaredPage(pageEl: AdwTabPage): void {
|
|
432
402
|
// The declared element IS the panel — attributes stay live on it, which
|
|
433
403
|
// is what makes `<adw-tab-page title>` observable at all.
|
|
@@ -461,8 +431,6 @@ export class AdwTabView extends HTMLElement {
|
|
|
461
431
|
return `tab-${this._generatedIds}`;
|
|
462
432
|
}
|
|
463
433
|
|
|
464
|
-
// --- Rendering ----------------------------------------------------------
|
|
465
|
-
|
|
466
434
|
private _onPagesChange(change: TabViewPagesChange): void {
|
|
467
435
|
switch (change.kind) {
|
|
468
436
|
case 'attached': {
|
|
@@ -507,19 +475,16 @@ export class AdwTabView extends HTMLElement {
|
|
|
507
475
|
tab.setAttribute('role', 'tab');
|
|
508
476
|
tab.dataset.pageId = page.id;
|
|
509
477
|
|
|
510
|
-
// Decorative mask-image nodes — <adw-icon> carries the convention
|
|
511
|
-
//
|
|
512
|
-
//
|
|
478
|
+
// Decorative mask-image nodes — <adw-icon> carries the convention, including the
|
|
479
|
+
// `-symbolic` strip, which is ours and not C's: there the name reaches
|
|
480
|
+
// `GtkImage` untouched.
|
|
513
481
|
const icon = createAdwIcon(null, 'adw-tab-icon');
|
|
514
482
|
tab.appendChild(icon);
|
|
515
483
|
|
|
516
|
-
// `AdwTabPage:loading` swaps the icon image for an `AdwSpinnerPaintable`
|
|
517
|
-
//
|
|
518
|
-
// adw-
|
|
519
|
-
//
|
|
520
|
-
// the border, the grey and the 0.8s under a comment claiming it was
|
|
521
|
-
// "not a second copy of them", and it inherited every spinner defect
|
|
522
|
-
// independently.
|
|
484
|
+
// `AdwTabPage:loading` swaps the icon image for an `AdwSpinnerPaintable` — the
|
|
485
|
+
// SAME paintable `Adw.Spinner` uses (`update_icons`). So this is a real
|
|
486
|
+
// `<adw-spinner>` in the icon's slot, not a ring drawn again in CSS: a CSS copy
|
|
487
|
+
// inherits every spinner defect independently.
|
|
523
488
|
const spinner = document.createElement('adw-spinner');
|
|
524
489
|
spinner.className = 'adw-tab-spinner';
|
|
525
490
|
spinner.setAttribute('size', '16');
|
|
@@ -532,9 +497,10 @@ export class AdwTabView extends HTMLElement {
|
|
|
532
497
|
|
|
533
498
|
tab.appendChild(createAdwIcon(null, 'adw-tab-indicator'));
|
|
534
499
|
|
|
535
|
-
// Close affordance — a small flat button drawn with a CSS "×" glyph
|
|
536
|
-
//
|
|
537
|
-
//
|
|
500
|
+
// Close affordance — a small flat button drawn with a CSS "×" glyph, because
|
|
501
|
+
// `window-close` has no mask class: it is not in the ICONS map in
|
|
502
|
+
// `scripts/build-scss.mjs` that generates them. `can-focus=False` in C, so it
|
|
503
|
+
// stays out of the tab order here too.
|
|
538
504
|
const close = document.createElement('button');
|
|
539
505
|
close.type = 'button';
|
|
540
506
|
close.className = 'adw-tab-close';
|
|
@@ -567,7 +533,6 @@ export class AdwTabView extends HTMLElement {
|
|
|
567
533
|
this._refreshTab(page.id);
|
|
568
534
|
}
|
|
569
535
|
|
|
570
|
-
/** Remove-then-insert, the same shape the model's own reorder has. */
|
|
571
536
|
private _moveTab(id: string, position: number): void {
|
|
572
537
|
const tab = this._tabs.get(id);
|
|
573
538
|
if (tab) {
|
|
@@ -588,10 +553,9 @@ export class AdwTabView extends HTMLElement {
|
|
|
588
553
|
|
|
589
554
|
const label = tab.querySelector('.adw-tab-title') as HTMLElement | null;
|
|
590
555
|
if (label) label.textContent = page.title;
|
|
591
|
-
// The tooltip is Pango MARKUP when the page sets one of its own
|
|
592
|
-
//
|
|
593
|
-
//
|
|
594
|
-
// — a renderer that interpreted it would be executing page-supplied markup.
|
|
556
|
+
// The tooltip is Pango MARKUP when the page sets one of its own. The DOM `title`
|
|
557
|
+
// attribute is a TEXT sink, so the markup is shown verbatim rather than pushed
|
|
558
|
+
// through an HTML sink — interpreting it would execute page-supplied markup.
|
|
595
559
|
tab.title = tabTooltip(page);
|
|
596
560
|
tab.classList.toggle('pinned', page.pinned);
|
|
597
561
|
tab.classList.toggle('needs-attention', page.needsAttention);
|
|
@@ -618,10 +582,10 @@ export class AdwTabView extends HTMLElement {
|
|
|
618
582
|
}
|
|
619
583
|
|
|
620
584
|
/**
|
|
621
|
-
* `tabCloseVisible
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
585
|
+
* `tabCloseVisible`, with its pinned gate. `dragging` is constantly false — tab
|
|
586
|
+
* drag-and-drop is compositor work and is not modelled — and `fullyVisible` is
|
|
587
|
+
* measured against the bar's scroll window, which is what the C term means for a
|
|
588
|
+
* horizontally scrolled bar.
|
|
625
589
|
*/
|
|
626
590
|
private _refreshCloseVisibility(id: string): void {
|
|
627
591
|
const page = this._state.getPage(id);
|
|
@@ -700,23 +664,18 @@ export class AdwTabView extends HTMLElement {
|
|
|
700
664
|
|
|
701
665
|
private _applySelectedAttribute(value: string): void {
|
|
702
666
|
const index = Number.parseInt(value, 10);
|
|
703
|
-
// An unparseable value is IGNORED rather than treated as 0
|
|
704
|
-
//
|
|
705
|
-
// first page
|
|
706
|
-
// (adw-tab-view.c:2145, :4126-4134).
|
|
667
|
+
// An unparseable value is IGNORED rather than treated as 0, and an out-of-range
|
|
668
|
+
// one is refused rather than clamped: libadwaita refuses both, so
|
|
669
|
+
// `selected="oops"` must not select the first page nor `selected="99"` the last.
|
|
707
670
|
if (Number.isNaN(index)) return;
|
|
708
671
|
this._state.selectNthPage(index);
|
|
709
672
|
}
|
|
710
673
|
|
|
711
|
-
// --- Keyboard -----------------------------------------------------------
|
|
712
|
-
|
|
713
674
|
/**
|
|
714
|
-
* The `Adw.TabView` shortcut table (`init_shortcuts
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* separates them in `select_page_cb` (:2017-2041). Alt+0 is page index 9,
|
|
719
|
-
* because pages count from 0 (:2149-2150).
|
|
675
|
+
* The `Adw.TabView` shortcut table (`init_shortcuts`), plus the ArrowLeft/ArrowRight
|
|
676
|
+
* movement `role=tablist` promises. Ctrl+Tab WRAPS and Ctrl+Page-Up/Down does not —
|
|
677
|
+
* the same `last` flag that separates them in `select_page_cb`. Alt+0 is page index
|
|
678
|
+
* 9, because pages count from 0.
|
|
720
679
|
*/
|
|
721
680
|
private _onKeyDown(event: KeyboardEvent): void {
|
|
722
681
|
const inBar = event.target instanceof Node && this._barEl.contains(event.target);
|
|
@@ -758,10 +717,10 @@ export class AdwTabView extends HTMLElement {
|
|
|
758
717
|
}
|
|
759
718
|
|
|
760
719
|
/**
|
|
761
|
-
* The `close-page` seam. A CANCELABLE DOM event is the idiomatic spelling of
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
*
|
|
720
|
+
* The `close-page` seam. A CANCELABLE DOM event is the idiomatic spelling of the C
|
|
721
|
+
* signal's return value: letting it through takes libadwaita's default (`!pinned`),
|
|
722
|
+
* and `preventDefault()` defers the close until the app calls
|
|
723
|
+
* {@link closePageFinish}.
|
|
765
724
|
*/
|
|
766
725
|
private _requestClose(page: AdwTabViewPage): boolean | 'defer' {
|
|
767
726
|
const proceed = this.dispatchEvent(
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
// <adw-toast-overlay> —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// optional action button and a close affordance) layered over the bottom of its
|
|
5
|
-
// own bounds.
|
|
1
|
+
// <adw-toast-overlay> — the web counterpart of Adw.ToastOverlay: wraps arbitrary
|
|
2
|
+
// content and shows transient toast strips (title, optional action button, close
|
|
3
|
+
// affordance) layered over the bottom of its own bounds.
|
|
6
4
|
//
|
|
7
|
-
// The QUEUE —
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// `onHide`, and the enter/exit CSS transitions. `@gjsify/adwaita-nativescript`
|
|
12
|
-
// composes the same core queue, so both ports share one behaviour.
|
|
5
|
+
// The QUEUE — the one-at-a-time policy, FIFO ordering and auto-dismiss lifecycle —
|
|
6
|
+
// is HEADLESS and lives in `@gjsify/adwaita-core` (ADR 0004) as {@link AdwToastQueue};
|
|
7
|
+
// this element composes it and keeps only the DOM half: build the strip on `onShow`,
|
|
8
|
+
// tear it down on `onHide`, run the enter/exit transitions.
|
|
13
9
|
//
|
|
14
10
|
// Adapted from Adwaita Web UI Framework (https://github.com/mclellac/adwaita-web).
|
|
15
11
|
// Reference: refs/adwaita-web/adwaita-web/scss/_toast.scss, _toast_overlay.scss
|
|
@@ -41,7 +37,11 @@ export interface AdwToastOptions {
|
|
|
41
37
|
/** Default toast lifetime in SECONDS — this element's public unit (Adw.Toast:timeout). */
|
|
42
38
|
const DEFAULT_TIMEOUT_SECONDS = 5;
|
|
43
39
|
|
|
44
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Fallback budget in ms for the exit transition: must stay at or above the
|
|
42
|
+
* `.adw-toast.hiding` transition-duration in `_toast.scss` (0.15s today), because it
|
|
43
|
+
* only fires when `transitionend` does not.
|
|
44
|
+
*/
|
|
45
45
|
const TOAST_EXIT_MS = 300;
|
|
46
46
|
|
|
47
47
|
/** The default timing seam: the browser's own timers. */
|
|
@@ -73,9 +73,9 @@ export class AdwToastOverlay extends HTMLElement {
|
|
|
73
73
|
},
|
|
74
74
|
onShow: (toast) => this._mountToast(toast),
|
|
75
75
|
// The core queue fires `onHide` BEFORE it shifts the next toast in, so
|
|
76
|
-
// `pending > 0` here means another toast takes this slot immediately:
|
|
77
|
-
//
|
|
78
|
-
//
|
|
76
|
+
// `pending > 0` here means another toast takes this slot immediately: detach
|
|
77
|
+
// without the exit transition, keeping exactly one strip in the DOM. A last
|
|
78
|
+
// toast fades out instead.
|
|
79
79
|
onHide: () => this._unmountToast(this._queue.pending > 0),
|
|
80
80
|
});
|
|
81
81
|
}
|
|
@@ -84,8 +84,8 @@ export class AdwToastOverlay extends HTMLElement {
|
|
|
84
84
|
if (this._initialized) return;
|
|
85
85
|
this._initialized = true;
|
|
86
86
|
|
|
87
|
-
//
|
|
88
|
-
//
|
|
87
|
+
// The declared children become the wrapped content (Adw.ToastOverlay:child);
|
|
88
|
+
// the toast container is layered over the bottom edge.
|
|
89
89
|
const content = document.createElement('div');
|
|
90
90
|
content.className = 'adw-toast-overlay-content';
|
|
91
91
|
for (const child of Array.from(this.childNodes)) content.appendChild(child);
|
|
@@ -121,16 +121,12 @@ export class AdwToastOverlay extends HTMLElement {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
|
-
* Show a toast
|
|
125
|
-
*
|
|
124
|
+
* Show a toast — the web equivalent of Adw.ToastOverlay.add_toast() with a
|
|
125
|
+
* freshly-built Adw.Toast. Only ONE toast is visible at a time; this one shows
|
|
126
|
+
* immediately when the slot is free, otherwise it waits its turn.
|
|
126
127
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* toasts already queued.
|
|
130
|
-
*
|
|
131
|
-
* @param title The text to display.
|
|
132
|
-
* @param options Either a timeout in milliseconds (legacy shorthand) or an
|
|
133
|
-
* {@link AdwToastOptions} bag (title text already supplied here).
|
|
128
|
+
* `options` is either an {@link AdwToastOptions} bag or, as a legacy shorthand, a
|
|
129
|
+
* timeout in MILLISECONDS.
|
|
134
130
|
*/
|
|
135
131
|
addToast(title: string, options: number | AdwToastOptions = {}): void {
|
|
136
132
|
// Ensure the toast container exists even if addToast() races a not-yet
|
|
@@ -187,8 +183,7 @@ export class AdwToastOverlay extends HTMLElement {
|
|
|
187
183
|
el.appendChild(button);
|
|
188
184
|
}
|
|
189
185
|
|
|
190
|
-
// Close affordance
|
|
191
|
-
// curated @gjsify/adwaita-icons set), mirroring adw-tab-view's .adw-tab-close.
|
|
186
|
+
// Close affordance: a CSS-drawn "×", as in adw-tab-view's close button.
|
|
192
187
|
const close = document.createElement('button');
|
|
193
188
|
close.type = 'button';
|
|
194
189
|
close.className = 'adw-toast-close-button';
|
|
@@ -206,10 +201,9 @@ export class AdwToastOverlay extends HTMLElement {
|
|
|
206
201
|
}
|
|
207
202
|
|
|
208
203
|
/**
|
|
209
|
-
* Detach the mounted strip — the DOM half of the queue's `onHide`.
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* about to take this slot (keeps exactly one strip mounted).
|
|
204
|
+
* Detach the mounted strip — the DOM half of the queue's `onHide`. `immediate`
|
|
205
|
+
* skips the exit transition because the next queued toast is about to take this
|
|
206
|
+
* slot, which is what keeps exactly one strip mounted.
|
|
213
207
|
*/
|
|
214
208
|
private _unmountToast(immediate: boolean): void {
|
|
215
209
|
const el = this._currentEl;
|
|
@@ -224,9 +218,8 @@ export class AdwToastOverlay extends HTMLElement {
|
|
|
224
218
|
el.classList.remove('visible');
|
|
225
219
|
el.classList.add('hiding');
|
|
226
220
|
el.addEventListener('transitionend', () => el.remove(), { once: true });
|
|
227
|
-
// Fallback
|
|
228
|
-
//
|
|
229
|
-
// when a fake clock is installed.
|
|
221
|
+
// Fallback for when transitionend does not fire (reduced motion). Routed through
|
|
222
|
+
// the injected scheduler so the lifecycle stays deterministic under a fake clock.
|
|
230
223
|
this._scheduler.schedule(() => {
|
|
231
224
|
if (el.parentNode) el.remove();
|
|
232
225
|
}, TOAST_EXIT_MS);
|
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
// <adw-toggle-group> —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// Attributes: active (zero-based index of the active toggle, default 0), and the
|
|
7
|
-
// style flags flat / round (mirroring the Adw.ToggleGroup `.flat` / `.round`
|
|
8
|
-
// style classes).
|
|
9
|
-
// Events: `notify::active` (CustomEvent, bubbles, `detail = { active }`) when the
|
|
10
|
-
// active toggle changes — mirrors the Adw.ToggleGroup `active` GObject property.
|
|
1
|
+
// <adw-toggle-group> — the web counterpart of Adw.ToggleGroup: a linked set of toggle
|
|
2
|
+
// buttons where exactly one is active. Toggles are `<adw-toggle>` children carrying
|
|
3
|
+
// `label` and/or `icon-name`, and the `flat` / `round` attributes mirror the upstream
|
|
4
|
+
// `.flat` / `.round` style classes. `notify::active` (CustomEvent, bubbles, detail
|
|
5
|
+
// `{ active }`) mirrors the `active` GObject property.
|
|
11
6
|
//
|
|
12
|
-
// The SELECTION state machine (the segment list plus the guarded, no-op-on-same
|
|
13
|
-
//
|
|
14
|
-
// {@link ToggleGroupState}; this element
|
|
15
|
-
//
|
|
16
|
-
// the `notify::active` event. `@gjsify/adwaita-nativescript` composes the same
|
|
17
|
-
// state machine, so both ports share one behaviour.
|
|
7
|
+
// The SELECTION state machine (the segment list plus the guarded, no-op-on-same active
|
|
8
|
+
// index) is HEADLESS and lives in `@gjsify/adwaita-core` (ADR 0004) as
|
|
9
|
+
// {@link ToggleGroupState}; this element keeps only the DOM half — the buttons, the active
|
|
10
|
+
// pill / `aria-pressed` reflection and the event.
|
|
18
11
|
//
|
|
19
12
|
// Reference: refs/libadwaita/src/adw-toggle-group.c (AdwToggleGroup behaviour)
|
|
20
13
|
// Reference: refs/libadwaita/src/stylesheet/widgets/_toggle-group.scss
|