@gjsify/adwaita-web 0.36.0 → 0.38.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 +504 -34
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/accent.d.ts +28 -0
- package/lib/types/adw-accent.spec.d.ts +2 -0
- 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 +3 -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 +18 -7
- 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/_theme.scss +20 -2
- package/scss/_variables.scss +34 -1
- package/scss/adwaita-skin.scss +12 -0
- package/src/accent.ts +74 -0
- package/src/adw-about-dialog.spec.ts +34 -49
- package/src/adw-accent.spec.ts +105 -0
- 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 +24 -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 +6 -0
- package/src/view-stack.spec.ts +23 -34
- package/src/view-switcher.spec.ts +56 -84
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// <adw-view-stack> — A standalone, named-page CONTENT container: the web
|
|
2
2
|
// counterpart of Adw.ViewStack decoupled from any switcher. It holds a set of
|
|
3
3
|
// named pages and shows exactly one at a time; a paired <adw-view-switcher-bar>
|
|
4
|
-
// (or an adaptive header-bar switcher) binds to it and drives the selection.
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// standalone stack a separate switcher can drive.
|
|
4
|
+
// (or an adaptive header-bar switcher) binds to it and drives the selection. The
|
|
5
|
+
// alternative switchers (<adw-view-switcher>, <adw-inline-view-switcher>) own their
|
|
6
|
+
// own pages instead.
|
|
8
7
|
//
|
|
9
8
|
// The SELECTION itself — the name lookup, the guards on an index change, the
|
|
10
9
|
// first-visible-page auto-pick and which paths notify — is HEADLESS and lives in
|
|
@@ -38,11 +37,10 @@
|
|
|
38
37
|
// page falls back to the next visible one.
|
|
39
38
|
// Events:
|
|
40
39
|
// `notify::visible-child` (CustomEvent, bubbles,
|
|
41
|
-
// detail = { index, name, title, interactive }) whenever the visible page
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// `refresh()`. `interactive` is false for an auto-pick.
|
|
40
|
+
// detail = { index, name, title, interactive }) whenever the visible page changes,
|
|
41
|
+
// INCLUDING the auto-shown first page — `set_visible_child` notifies there too, and
|
|
42
|
+
// a switcher that is not told needs a manual `refresh()`. `interactive` is false
|
|
43
|
+
// for an auto-pick.
|
|
46
44
|
// Reference: refs/libadwaita/src/adw-view-stack.c (AdwViewStack behaviour)
|
|
47
45
|
// Reference: packages/nativescript-bridge/adwaita/src/widgets/adw-view-stack.ts (NS twin)
|
|
48
46
|
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
@@ -51,7 +49,6 @@
|
|
|
51
49
|
import { ViewStackState } from '@gjsify/adwaita-core';
|
|
52
50
|
import type { AdwViewStackPageInfo as CorePageInfo, ViewStackStateChange } from '@gjsify/adwaita-core';
|
|
53
51
|
|
|
54
|
-
/** A page descriptor exposed via `pages` (consumed by a bound switcher bar). */
|
|
55
52
|
export type AdwViewStackPageInfo = CorePageInfo<HTMLElement>;
|
|
56
53
|
|
|
57
54
|
export class AdwViewStack extends HTMLElement {
|
|
@@ -69,7 +66,6 @@ export class AdwViewStack extends HTMLElement {
|
|
|
69
66
|
this._state.subscribe((change) => this._onStateChange(change));
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
/** All pages in declaration/add order. A bound switcher reads this. */
|
|
73
69
|
get pages(): readonly AdwViewStackPageInfo[] {
|
|
74
70
|
return this._state.pages;
|
|
75
71
|
}
|
|
@@ -83,7 +79,6 @@ export class AdwViewStack extends HTMLElement {
|
|
|
83
79
|
this._state.setVisibleIndex(value);
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
/** Name of the visible page, or '' when nothing is selected. */
|
|
87
82
|
get visibleChildName(): string {
|
|
88
83
|
return this._state.visibleName;
|
|
89
84
|
}
|
|
@@ -92,7 +87,6 @@ export class AdwViewStack extends HTMLElement {
|
|
|
92
87
|
this._state.setVisibleName(name);
|
|
93
88
|
}
|
|
94
89
|
|
|
95
|
-
/** The visible page's content element, or null when nothing is selected. */
|
|
96
90
|
get visibleChild(): HTMLElement | null {
|
|
97
91
|
return this._state.visiblePage?.content ?? null;
|
|
98
92
|
}
|
|
@@ -106,21 +100,17 @@ export class AdwViewStack extends HTMLElement {
|
|
|
106
100
|
// otherwise overwrite the author's value with page 0's name.
|
|
107
101
|
const initialName = this.getAttribute('visible-child-name');
|
|
108
102
|
|
|
109
|
-
// Adopt the declared <adw-view-stack-page> children by APPENDING them
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
// children: the buildable adds them one at a time
|
|
116
|
-
// (adw_view_stack_buildable_add_child, adw-view-stack.c:1666-1680) and
|
|
117
|
-
// `adw_view_stack_add` works at any point in the widget's life.
|
|
103
|
+
// Adopt the declared <adw-view-stack-page> children by APPENDING them, never by
|
|
104
|
+
// replacing the page list: a stack built imperatively before it entered the
|
|
105
|
+
// document (`createElement` → `add()` → `body.append()`) would lose every page
|
|
106
|
+
// it had been given. libadwaita has no parse-once phase that can discard
|
|
107
|
+
// children — the buildable adds them one at a time and `adw_view_stack_add`
|
|
108
|
+
// works at any point in the widget's life.
|
|
118
109
|
for (const pageEl of Array.from(this.querySelectorAll(':scope > adw-view-stack-page')) as HTMLElement[]) {
|
|
119
|
-
// A declared page with no `name` is the page named ''
|
|
120
|
-
//
|
|
121
|
-
//
|
|
110
|
+
// A declared page with no `name` is the page named '': C stores the name
|
|
111
|
+
// verbatim, and an invented `page-<index>` would be addressable by a name the
|
|
112
|
+
// author never wrote.
|
|
122
113
|
const name = pageEl.getAttribute('name') ?? '';
|
|
123
|
-
// Wrapping each page's content lets us toggle exactly one.
|
|
124
114
|
const element = document.createElement('div');
|
|
125
115
|
element.className = 'adw-view-stack-child';
|
|
126
116
|
element.dataset.name = name;
|
|
@@ -132,16 +122,15 @@ export class AdwViewStack extends HTMLElement {
|
|
|
132
122
|
icon: pageEl.getAttribute('icon-name'),
|
|
133
123
|
content: element,
|
|
134
124
|
// `hidden` is the DOM spelling of AdwViewStackPage:visible, which
|
|
135
|
-
// gates the auto-pick and refuses selection
|
|
125
|
+
// gates the auto-pick and refuses selection.
|
|
136
126
|
visible: !pageEl.hasAttribute('hidden'),
|
|
137
127
|
});
|
|
138
128
|
this.replaceChild(element, pageEl);
|
|
139
129
|
}
|
|
140
130
|
|
|
141
|
-
// An explicit `visible-child-name` selects the initial page
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
// which the old `initialName ? … : -1` falsy check silently dropped.
|
|
131
|
+
// An explicit `visible-child-name` selects the initial page; only a MISSING
|
|
132
|
+
// attribute falls through to the auto-pick. An empty value is a legal lookup for
|
|
133
|
+
// a page named '' (`g_strcmp0`), so a falsy check here is wrong.
|
|
145
134
|
if (initialName !== null) this._state.setVisibleName(initialName, false);
|
|
146
135
|
this._applyVisibility();
|
|
147
136
|
this._reflectName();
|
|
@@ -159,7 +148,7 @@ export class AdwViewStack extends HTMLElement {
|
|
|
159
148
|
|
|
160
149
|
/**
|
|
161
150
|
* Append a page. It becomes visible when nothing is selected yet, matching
|
|
162
|
-
* `Adw.ViewStack.add()
|
|
151
|
+
* `Adw.ViewStack.add()`, and that auto-pick NOTIFIES.
|
|
163
152
|
*/
|
|
164
153
|
add(content: HTMLElement, name: string, title?: string, icon?: string): AdwViewStackPageInfo {
|
|
165
154
|
content.classList.add('adw-view-stack-child');
|
|
@@ -172,7 +161,6 @@ export class AdwViewStack extends HTMLElement {
|
|
|
172
161
|
return page;
|
|
173
162
|
}
|
|
174
163
|
|
|
175
|
-
/** Convenience alias mirroring Adw.ViewStack.add_titled() (no icon). */
|
|
176
164
|
addTitled(content: HTMLElement, name: string, title: string): AdwViewStackPageInfo {
|
|
177
165
|
return this.add(content, name, title);
|
|
178
166
|
}
|
|
@@ -181,7 +169,7 @@ export class AdwViewStack extends HTMLElement {
|
|
|
181
169
|
* Remove the first page named `name` and detach its content. Returns whether
|
|
182
170
|
* anything was removed. When the removed page was the visible one the stack
|
|
183
171
|
* ends up showing NOTHING and emits no event — `stack_remove` clears
|
|
184
|
-
* `visible_child` without re-picking
|
|
172
|
+
* `visible_child` without re-picking.
|
|
185
173
|
*/
|
|
186
174
|
removePage(name: string): boolean {
|
|
187
175
|
const content = this._state.pages[this._state.indexOfName(name)]?.content;
|
|
@@ -197,28 +185,23 @@ export class AdwViewStack extends HTMLElement {
|
|
|
197
185
|
* Show or hide a page (`AdwViewStackPage:visible`). Returns whether the
|
|
198
186
|
* SELECTION moved: hiding the visible page falls back to the next visible
|
|
199
187
|
* one, and making a page visible while nothing is selected selects it
|
|
200
|
-
* (`update_child_visible
|
|
188
|
+
* (`update_child_visible`).
|
|
201
189
|
*/
|
|
202
190
|
setPageVisible(name: string, visible: boolean): boolean {
|
|
203
191
|
const moved = this._state.setPageVisible(name, visible);
|
|
204
192
|
this._applyVisibility();
|
|
205
193
|
// A visibility flip changes what the pages MODEL reports, which is what
|
|
206
|
-
// `update_bar_revealed` counts
|
|
207
|
-
//
|
|
194
|
+
// `update_bar_revealed` counts — hiding the second-to-last visible page must
|
|
195
|
+
// retract the bar.
|
|
208
196
|
this._emitItemsChanged();
|
|
209
197
|
return moved;
|
|
210
198
|
}
|
|
211
199
|
|
|
212
200
|
/**
|
|
213
|
-
* The pages model's `items-changed
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* (adw-view-switcher-bar.c:340) and `AdwViewSwitcher` rebinds its buttons
|
|
218
|
-
* (adw-view-switcher.c:258-263). Both ports listened only on
|
|
219
|
-
* `notify::visible-child`, so adding a page or hiding a non-selected one
|
|
220
|
-
* left `revealed` — and the button row — stale, with a manual `refresh()`
|
|
221
|
-
* as the documented workaround.
|
|
201
|
+
* The pages model's `items-changed`: `AdwViewSwitcherBar` re-runs
|
|
202
|
+
* `update_bar_revealed` on it and `AdwViewSwitcher` rebinds its buttons. A listener
|
|
203
|
+
* on `notify::visible-child` alone leaves `revealed` and the button row stale when a
|
|
204
|
+
* page is added or a non-selected one hidden.
|
|
222
205
|
*/
|
|
223
206
|
private _emitItemsChanged(): void {
|
|
224
207
|
this.dispatchEvent(new CustomEvent('items-changed', { bubbles: true, detail: { count: this.pages.length } }));
|
|
@@ -253,11 +236,9 @@ export class AdwViewStack extends HTMLElement {
|
|
|
253
236
|
|
|
254
237
|
private _reflectName(): void {
|
|
255
238
|
// With nothing selected there is no name to mirror — C's
|
|
256
|
-
// `adw_view_stack_get_visible_child_name` returns NULL
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
// `if (current && …)` guard meant a stack of nameless pages never
|
|
260
|
-
// reflected its selection at all.
|
|
239
|
+
// `adw_view_stack_get_visible_child_name` returns NULL, and a missing attribute
|
|
240
|
+
// is the DOM spelling of that. An EMPTY name is still a name and IS reflected: a
|
|
241
|
+
// truthiness guard here stops a stack of nameless pages reflecting at all.
|
|
261
242
|
if (this._state.visibleIndex < 0) {
|
|
262
243
|
this.removeAttribute('visible-child-name');
|
|
263
244
|
return;
|
|
@@ -3,33 +3,16 @@
|
|
|
3
3
|
// owns no pages: it reads the bound stack's `pages`, renders one homogeneous
|
|
4
4
|
// button per page, and is two-way synced to the stack's visible child.
|
|
5
5
|
//
|
|
6
|
-
// The derivations are HEADLESS and live in `@gjsify/adwaita-core` (ADR 0004):
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// adw-view-switcher-bar.c:104-126). A bar bound to a one-page stack used to show
|
|
12
|
-
// an empty strip that libadwaita keeps collapsed.
|
|
6
|
+
// The derivations are HEADLESS and live in `@gjsify/adwaita-core` (ADR 0004): the
|
|
7
|
+
// per-button model (`buildViewSwitcherButtons`, so this bar and the header switcher
|
|
8
|
+
// cannot disagree about what a page looks like) and `ViewSwitcherBarState`, which is
|
|
9
|
+
// `reveal` AND MORE THAN ONE VISIBLE PAGE (`update_bar_revealed`) — a bar bound to a
|
|
10
|
+
// one-page stack stays collapsed however loudly the layout asks.
|
|
13
11
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
// C the handlers are bound in `set_stack` and released only in `dispose`
|
|
18
|
-
// (:330-341, :218-221) — realize/unrealize never touch them.
|
|
12
|
+
// `stack` names the <adw-view-stack> to drive by id, like `<label for>`. `revealed` is
|
|
13
|
+
// the LEGACY spelling of the `reveal` request and is still read as one; as a property
|
|
14
|
+
// it is read-only and reports whether the bar is actually shown.
|
|
19
15
|
//
|
|
20
|
-
// Attributes:
|
|
21
|
-
// stack — the id of the <adw-view-stack> to drive (like <label for>).
|
|
22
|
-
// reveal — boolean; the REQUEST (`Adw.ViewSwitcherBar:reveal`, default off).
|
|
23
|
-
// revealed — the legacy spelling of `reveal`, still accepted as the request.
|
|
24
|
-
// Properties:
|
|
25
|
-
// stack — the bound AdwViewStack element (get/set; set also accepts an id).
|
|
26
|
-
// reveal — the request (get/set).
|
|
27
|
-
// revealed — READ-ONLY: whether the bar is actually shown, i.e. the request
|
|
28
|
-
// AND more than one visible page.
|
|
29
|
-
// Methods:
|
|
30
|
-
// setStack(stack) — bind to a stack element (or null); rebuilds the buttons.
|
|
31
|
-
// refresh() — rebuild after pages were added to the bound stack without
|
|
32
|
-
// changing its selection (see the note in `_rebuild`).
|
|
33
16
|
// Reference: refs/libadwaita/src/adw-view-switcher-bar.c (AdwViewSwitcherBar)
|
|
34
17
|
// Reference: refs/libadwaita/src/adw-view-switcher.c (the switcher it embeds)
|
|
35
18
|
// Reference: packages/nativescript-bridge/adwaita/src/widgets/adw-view-switcher-bar.ts (NS twin)
|
|
@@ -91,7 +74,7 @@ export class AdwViewSwitcherBar extends HTMLElement {
|
|
|
91
74
|
|
|
92
75
|
/**
|
|
93
76
|
* Whether the bar is actually shown. READ-ONLY: a one-page stack keeps it
|
|
94
|
-
* collapsed however loudly the layout asks
|
|
77
|
+
* collapsed however loudly the layout asks.
|
|
95
78
|
* Write {@link reveal} to make the request.
|
|
96
79
|
*/
|
|
97
80
|
get revealed(): boolean {
|
|
@@ -108,17 +91,17 @@ export class AdwViewSwitcherBar extends HTMLElement {
|
|
|
108
91
|
}
|
|
109
92
|
this._barState.setReveal(this._readReveal());
|
|
110
93
|
|
|
111
|
-
// Resolve the `stack` id ref now
|
|
112
|
-
//
|
|
113
|
-
//
|
|
94
|
+
// Resolve the `stack` id ref now the element is in the document: the referenced
|
|
95
|
+
// stack is normally earlier in the DOM (content above a bottom bar), so its pages
|
|
96
|
+
// are ready.
|
|
114
97
|
const ref = this.getAttribute('stack');
|
|
115
98
|
if (ref && !this._stack) {
|
|
116
99
|
this.setStack(this._resolveStack(ref));
|
|
117
100
|
return;
|
|
118
101
|
}
|
|
119
|
-
// Re-attaching must re-bind
|
|
120
|
-
//
|
|
121
|
-
//
|
|
102
|
+
// Re-attaching must re-bind, because `disconnectedCallback` released the listener.
|
|
103
|
+
// In C the binding is made in `set_stack`, released in `dispose`, and survives
|
|
104
|
+
// unrealize entirely.
|
|
122
105
|
this._bindStack();
|
|
123
106
|
this._rebuild();
|
|
124
107
|
}
|
|
@@ -147,13 +130,9 @@ export class AdwViewSwitcherBar extends HTMLElement {
|
|
|
147
130
|
}
|
|
148
131
|
|
|
149
132
|
/**
|
|
150
|
-
* Rebuild the buttons by hand
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* way to say so — but no longer the ONLY way: the stack emits
|
|
154
|
-
* `items-changed` now and this bar binds it, which is the mechanism
|
|
155
|
-
* libadwaita uses (adw-view-switcher-bar.c:340,
|
|
156
|
-
* adw-view-switcher.c:258-263).
|
|
133
|
+
* Rebuild the buttons by hand — public API for a consumer that mutated a page in
|
|
134
|
+
* place. Not the only path: the stack emits `items-changed` and this bar binds it,
|
|
135
|
+
* which is the mechanism libadwaita uses.
|
|
157
136
|
*/
|
|
158
137
|
refresh(): void {
|
|
159
138
|
this._rebuild();
|
|
@@ -165,10 +144,9 @@ export class AdwViewSwitcherBar extends HTMLElement {
|
|
|
165
144
|
|
|
166
145
|
private _bindStack(): void {
|
|
167
146
|
this._stack?.addEventListener('notify::visible-child', this._onStackNotify);
|
|
168
|
-
// `update_bar_revealed` runs on the pages model's `items-changed` too
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
// hidden, changes the COUNT the reveal is decided from.
|
|
147
|
+
// `update_bar_revealed` runs on the pages model's `items-changed` too: a page
|
|
148
|
+
// added without moving the selection, or a non-selected page hidden, changes the
|
|
149
|
+
// COUNT the reveal is decided from.
|
|
172
150
|
this._stack?.addEventListener('items-changed', this._onStackNotify);
|
|
173
151
|
}
|
|
174
152
|
|
|
@@ -187,18 +165,16 @@ export class AdwViewSwitcherBar extends HTMLElement {
|
|
|
187
165
|
if (!this._initialized) return;
|
|
188
166
|
|
|
189
167
|
const stackPages = this._stack?.pages ?? [];
|
|
190
|
-
// The page count is half the reveal derivation, so it is fed on every
|
|
191
|
-
//
|
|
192
|
-
// items-changed for exactly this reason (:340-343, :277).
|
|
168
|
+
// The page count is half the reveal derivation, so it is fed on every rebuild —
|
|
169
|
+
// which is why C re-runs `update_bar_revealed` from set_stack and items-changed.
|
|
193
170
|
this._barState.setPages(stackPages);
|
|
194
171
|
|
|
195
172
|
const pages = viewSwitcherPagesFromStack(stackPages);
|
|
196
173
|
const models = buildViewSwitcherButtons(pages, this._stack?.visibleChildIndex ?? -1, 'narrow');
|
|
197
174
|
|
|
198
|
-
// Nodes are recreated only when the page COUNT moves
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
// wholesale replace would drop keyboard focus mid-interaction.
|
|
175
|
+
// Nodes are recreated only when the page COUNT moves: a selection change must not
|
|
176
|
+
// replace the button the user is standing on. `selection_changed_cb` only re-marks
|
|
177
|
+
// the existing buttons, and a wholesale replace drops keyboard focus mid-interaction.
|
|
202
178
|
if (models.length !== this._nodes.length) {
|
|
203
179
|
this._barEl.replaceChildren();
|
|
204
180
|
this._nodes = models.map((model) => this._buildButton(model.pageIndex));
|
|
@@ -3,46 +3,28 @@
|
|
|
3
3
|
// libadwaita keeps separate. Pages are declared as <adw-view-switcher-page>
|
|
4
4
|
// children; their own children become the page body.
|
|
5
5
|
//
|
|
6
|
-
// Everything that decides WHAT to show is HEADLESS
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// `ViewSwitcherState` over the wave-1 `ViewStackState`, so this element and the
|
|
11
|
-
// NativeScript twin share one set of guards and one set of conformance vectors
|
|
12
|
-
// (`@gjsify/adwaita-core/conformance`). This file is the DOM half only.
|
|
6
|
+
// Everything that decides WHAT to show is HEADLESS, in `@gjsify/adwaita-core`
|
|
7
|
+
// (ADR 0004): `ViewSwitcherState` over the wave-1 `ViewStackState`, so this
|
|
8
|
+
// element and the NativeScript twin share one set of guards and one set of
|
|
9
|
+
// conformance vectors. This file is the DOM half only.
|
|
13
10
|
//
|
|
14
|
-
//
|
|
15
|
-
// - a page with
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// `image-missing` (adw-view-switcher-button.c:399-405).
|
|
21
|
-
// - `active="-1"` / `active="99"` were CLAMPED into range, so an out-of-range
|
|
22
|
-
// request silently switched pages; `adw_view_stack_pages_select_item`
|
|
23
|
-
// refuses (adw-view-stack.c:682-684).
|
|
24
|
-
// - `notify::visible-child` fired only for a click, never for a property or
|
|
25
|
-
// attribute set; C notifies on every path (adw-view-stack.c:1038-1039).
|
|
26
|
-
// - `notify::policy` was documented in this header and never dispatched.
|
|
27
|
-
// - the declared pages were harvested with an UNSCOPED querySelectorAll, so a
|
|
28
|
-
// nested switcher inside a page had its pages stolen by the outer one.
|
|
29
|
-
// - the 500 ms drag-hover auto-switch did not exist
|
|
30
|
-
// (adw-view-switcher-button.c:14, :58-96).
|
|
31
|
-
//
|
|
32
|
-
// Attributes:
|
|
33
|
-
// policy — 'wide' | 'narrow' (default 'narrow'). An unrecognised value is
|
|
34
|
-
// REJECTED and leaves the current policy alone, as `g_return_if_fail` does;
|
|
35
|
-
// removing the attribute restores the default.
|
|
36
|
-
// active — zero-based index of the selected PAGE. Out-of-range, negative and
|
|
37
|
-
// fractional values are refused and the attribute is reflected back to the
|
|
11
|
+
// The C rules that are not visible in the DOM code:
|
|
12
|
+
// - a page with NEITHER title NOR icon has no button at all. An EMPTY title is not
|
|
13
|
+
// that case — it keeps its button, hence no `?? ''` flattening of `getAttribute`.
|
|
14
|
+
// - a page with no icon gets `image-missing`, not nothing.
|
|
15
|
+
// - an out-of-range, negative or fractional `active` is REFUSED, not clamped
|
|
16
|
+
// (`adw_view_stack_pages_select_item`), and the attribute is reflected back to the
|
|
38
17
|
// selection that actually holds.
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
18
|
+
// - `notify::visible-child` fires on EVERY path, property and attribute sets
|
|
19
|
+
// included, not only on a click.
|
|
20
|
+
// - a drag hovering a button auto-switches after 500 ms.
|
|
21
|
+
// - `policy` defaults 'narrow'; an unrecognised value is refused and leaves the
|
|
22
|
+
// current policy alone, removing the attribute restores the default.
|
|
23
|
+
//
|
|
24
|
+
// A page's `hidden` attribute is `AdwViewStackPage:visible` inverted. Both events
|
|
25
|
+
// bubble; `notify::visible-child` carries `{ index, name, title, interactive }`, where
|
|
26
|
+
// `interactive` is false for a model-driven change such as the auto-pick.
|
|
27
|
+
//
|
|
46
28
|
// Reference: refs/libadwaita/src/adw-view-switcher.c (AdwViewSwitcher behaviour)
|
|
47
29
|
// Reference: refs/libadwaita/src/adw-view-switcher-button.c (AdwViewSwitcherButton)
|
|
48
30
|
// Reference: refs/libadwaita/src/stylesheet/widgets/_view-switcher.scss
|
|
@@ -86,29 +68,19 @@ interface PageNodes {
|
|
|
86
68
|
/**
|
|
87
69
|
* A single page. Children of `<adw-view-switcher>`; consumed at connect time.
|
|
88
70
|
*
|
|
89
|
-
* Deliberately carries NO `observedAttributes
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* A callback could not fix it either: the switcher consumes these elements at
|
|
96
|
-
* connect and `replaceChildren`s them away, so a detached page has no `closest`
|
|
97
|
-
* to reach its owner through. The switcher watches them with a `MutationObserver`
|
|
98
|
-
* instead, which keeps working after the detach and needs nothing from this class.
|
|
71
|
+
* Deliberately carries NO `observedAttributes` and no `attributeChangedCallback`:
|
|
72
|
+
* the switcher consumes these elements at connect and `replaceChildren`s them
|
|
73
|
+
* away, so a detached page has no `closest` to reach its owner through. The
|
|
74
|
+
* switcher watches them with a `MutationObserver` instead — the DOM stand-in for
|
|
75
|
+
* the per-page `notify` C rebinds on.
|
|
99
76
|
*/
|
|
100
77
|
export class AdwViewSwitcherPage extends HTMLElement {}
|
|
101
78
|
|
|
102
79
|
export class AdwViewSwitcher extends HTMLElement {
|
|
103
80
|
/**
|
|
104
|
-
* The dwell timer, injectable
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* inline, which left NOWHERE to hand a clock in — so
|
|
108
|
-
* `VIEW_SWITCHER_DRAG_VECTORS` was driven by the core suite alone, and the
|
|
109
|
-
* conformance header claimed all three suites drove it. `scheduler` is a
|
|
110
|
-
* property so a test can replace it before the element connects; the DOM one
|
|
111
|
-
* is the default, exactly as before.
|
|
81
|
+
* The dwell timer, injectable so a test can hand in a clock and drive
|
|
82
|
+
* `VIEW_SWITCHER_DRAG_VECTORS` against the real element. Replace it before the
|
|
83
|
+
* element connects.
|
|
112
84
|
*/
|
|
113
85
|
scheduler: ViewSwitcherScheduler = domViewSwitcherScheduler;
|
|
114
86
|
private _stateInstance: ViewSwitcherState | null = null;
|
|
@@ -136,11 +108,8 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
136
108
|
|
|
137
109
|
constructor() {
|
|
138
110
|
super();
|
|
139
|
-
// Subscribing touches no attributes and no children, so it is legal in a
|
|
140
|
-
// custom element constructor — unlike anything DOM-shaped.
|
|
141
111
|
}
|
|
142
112
|
|
|
143
|
-
/** The policy controlling the button layout ('wide' | 'narrow'). */
|
|
144
113
|
get policy(): AdwViewSwitcherPolicy {
|
|
145
114
|
return this._policy;
|
|
146
115
|
}
|
|
@@ -159,7 +128,6 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
159
128
|
this._reflectActive();
|
|
160
129
|
}
|
|
161
130
|
|
|
162
|
-
/** Name of the selected page, `''` when nothing is selected. */
|
|
163
131
|
get visibleChildName(): string {
|
|
164
132
|
return this._state.selectedName;
|
|
165
133
|
}
|
|
@@ -168,7 +136,6 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
168
136
|
this._state.selectName(name);
|
|
169
137
|
}
|
|
170
138
|
|
|
171
|
-
/** The resolved page records a bound layout can read. */
|
|
172
139
|
get pages(): readonly AdwViewSwitcherPageInfo[] {
|
|
173
140
|
return this._state.pages;
|
|
174
141
|
}
|
|
@@ -176,7 +143,7 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
176
143
|
/**
|
|
177
144
|
* Show or hide a page (`AdwViewStackPage:visible`). Returns whether the
|
|
178
145
|
* SELECTION moved — hiding the selected page falls back to the first still
|
|
179
|
-
* visible one
|
|
146
|
+
* visible one.
|
|
180
147
|
*/
|
|
181
148
|
setPageVisible(name: string, visible: boolean): boolean {
|
|
182
149
|
const moved = this._state.setPageVisible(name, visible);
|
|
@@ -186,25 +153,21 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
186
153
|
|
|
187
154
|
connectedCallback() {
|
|
188
155
|
if (this._initialized) {
|
|
189
|
-
// Re-entering a document
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
// slideshow slide, a client-side route change) stopped noticing
|
|
193
|
-
// page attribute changes for good, and did it silently.
|
|
156
|
+
// Re-entering a document: `disconnectedCallback` drops the page observer on
|
|
157
|
+
// the way out, so a switcher that was merely MOVED (a slideshow slide, a
|
|
158
|
+
// route change) has to get it back here or it stops noticing page changes.
|
|
194
159
|
this._watchPages();
|
|
195
160
|
return;
|
|
196
161
|
}
|
|
197
162
|
|
|
198
|
-
// `:scope
|
|
199
|
-
//
|
|
200
|
-
//
|
|
163
|
+
// `:scope >`, not a subtree scan: an unscoped query lets an outer switcher
|
|
164
|
+
// adopt a nested one's pages, since both use the same tag. Pages come from
|
|
165
|
+
// the stack's OWN children in C.
|
|
201
166
|
const declared = Array.from(this.querySelectorAll(':scope > adw-view-switcher-page')) as HTMLElement[];
|
|
202
|
-
// Read
|
|
203
|
-
//
|
|
167
|
+
// Read BEFORE adopting any page: the auto-pick reflects its own index back
|
|
168
|
+
// into this very attribute.
|
|
204
169
|
const declaredActive = this.getAttribute('active');
|
|
205
170
|
|
|
206
|
-
// The single `viewswitcher` node holds the segmented button bar; a
|
|
207
|
-
// sibling content area shows the selected page.
|
|
208
171
|
this._barEl = document.createElement('div');
|
|
209
172
|
this._barEl.className = 'adw-view-switcher-bar';
|
|
210
173
|
this._barEl.setAttribute('role', 'tablist');
|
|
@@ -232,19 +195,18 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
232
195
|
}
|
|
233
196
|
|
|
234
197
|
disconnectedCallback() {
|
|
235
|
-
// A drag that leaves with the element would otherwise switch pages after
|
|
236
|
-
//
|
|
198
|
+
// A drag that leaves with the element would otherwise switch pages after the
|
|
199
|
+
// widget is gone; C drops the source in dispose the same way.
|
|
237
200
|
this._state.cancelDrag();
|
|
238
201
|
this._pageObserver?.disconnect();
|
|
239
202
|
this._pageObserver = undefined;
|
|
240
203
|
}
|
|
241
204
|
|
|
242
205
|
/**
|
|
243
|
-
* Re-read every declared page and push it into the state.
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* the selection where it can, so this is a repaint and not a reset.
|
|
206
|
+
* Re-read every declared page and push it into the state. Driven by the
|
|
207
|
+
* `MutationObserver` in {@link _watchPages}, which is what makes a runtime
|
|
208
|
+
* `badge-number` change reach the button. `setPages` keeps the selection where it
|
|
209
|
+
* can, so this is a repaint and not a reset.
|
|
248
210
|
*/
|
|
249
211
|
refreshPages(): void {
|
|
250
212
|
if (!this._initialized) return;
|
|
@@ -253,18 +215,12 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
253
215
|
}
|
|
254
216
|
|
|
255
217
|
/**
|
|
256
|
-
* Watch the declared pages for attribute changes
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
* the switcher consumes those elements at connect and `replaceChildren`s them
|
|
260
|
-
* out of the tree, so a detached page cannot find its owner — but an observer
|
|
261
|
-
* bound to it keeps firing. This is the DOM's `notify::` on
|
|
262
|
-
* `AdwViewStackPage`, which the C's `update_button` handler binds per page
|
|
263
|
-
* (adw-view-switcher.c:184-193).
|
|
218
|
+
* Watch the declared pages for attribute changes — the DOM's `notify::` on
|
|
219
|
+
* `AdwViewStackPage`, which C's `update_button` binds per page. See
|
|
220
|
+
* {@link AdwViewSwitcherPage} for why an observer and not a callback.
|
|
264
221
|
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* in this element reads the button back inside the setter.
|
|
222
|
+
* MODIFICATION: delivers on a MICROTASK where GTK's notify is synchronous —
|
|
223
|
+
* invisible to a user, and nothing here reads the button back inside a setter.
|
|
268
224
|
*/
|
|
269
225
|
private _watchPages(): void {
|
|
270
226
|
this._pageObserver?.disconnect();
|
|
@@ -299,9 +255,8 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
299
255
|
button.className = 'adw-view-switcher-button';
|
|
300
256
|
button.setAttribute('role', 'tab');
|
|
301
257
|
|
|
302
|
-
// Both children always exist,
|
|
303
|
-
//
|
|
304
|
-
// disappearing (adw-view-switcher-button.ui).
|
|
258
|
+
// Both children always exist, as in AdwViewSwitcherButton's template — the icon
|
|
259
|
+
// carries `image-missing` rather than disappearing.
|
|
305
260
|
const icon = createAdwIcon(null, 'adw-view-switcher-icon');
|
|
306
261
|
|
|
307
262
|
const label = document.createElement('span');
|
|
@@ -315,16 +270,12 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
315
270
|
button.addEventListener('click', () => {
|
|
316
271
|
this._state.setSelected(index);
|
|
317
272
|
});
|
|
318
|
-
// GtkDropControllerMotion's enter/leave, which drive TIMEOUT_EXPAND.
|
|
319
|
-
//
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
// slid from the icon to the label restarted the countdown and the page
|
|
325
|
-
// never switched. C has one `GtkDropControllerMotion` per BUTTON
|
|
326
|
-
// (adw-view-switcher-button.c:79-96), which has no such internal edges —
|
|
327
|
-
// `relatedTarget` containment is that same "did we really leave" test.
|
|
273
|
+
// GtkDropControllerMotion's enter/leave, which drive TIMEOUT_EXPAND. The
|
|
274
|
+
// `relatedTarget` containment test is load-bearing: the button contains an icon
|
|
275
|
+
// and a label, and the DOM fires `dragleave` + `dragenter` when the pointer
|
|
276
|
+
// crosses BETWEEN them. Since `leave` clears the dwell timer and `enter` re-arms
|
|
277
|
+
// a fresh 500 ms, an untested crossing restarts the countdown forever. C's one
|
|
278
|
+
// `GtkDropControllerMotion` per BUTTON has no such internal edges.
|
|
328
279
|
button.addEventListener('dragenter', (event) => {
|
|
329
280
|
if (button.contains((event as DragEvent).relatedTarget as Node | null)) return;
|
|
330
281
|
this._state.dragEnter(index);
|
|
@@ -344,9 +295,9 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
344
295
|
|
|
345
296
|
private _readPolicyAttr(): AdwViewSwitcherPolicy {
|
|
346
297
|
const raw = this.getAttribute('policy');
|
|
347
|
-
// A removed attribute falls back to the C default; an unrecognised value
|
|
348
|
-
//
|
|
349
|
-
//
|
|
298
|
+
// A removed attribute falls back to the C default; an unrecognised value is
|
|
299
|
+
// refused and keeps the current policy, since `adw_view_switcher_set_policy` is
|
|
300
|
+
// reached only through the enum, which rejects garbage.
|
|
350
301
|
if (raw === null) return 'narrow';
|
|
351
302
|
return isViewSwitcherPolicy(raw) ? raw : this._policy;
|
|
352
303
|
}
|
|
@@ -369,8 +320,7 @@ export class AdwViewSwitcher extends HTMLElement {
|
|
|
369
320
|
private _render(): void {
|
|
370
321
|
if (!this._initialized) return;
|
|
371
322
|
|
|
372
|
-
// The single `viewswitcher` node carries the policy style class
|
|
373
|
-
// (adw-view-switcher.c:539-545).
|
|
323
|
+
// The single `viewswitcher` node carries the policy style class.
|
|
374
324
|
for (const policy of VIEW_SWITCHER_POLICIES) this.classList.toggle(policy, policy === this._policy);
|
|
375
325
|
|
|
376
326
|
const models = buildViewSwitcherButtons(this._state.pages, this._state.selected, this._policy);
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
// `@gjsify/adwaita-nativescript` composes the same state, so both ports share one
|
|
10
10
|
// behaviour. Three rules from adw-window-title.c that neither renderer had:
|
|
11
11
|
// - the TITLE label hides when the title is empty (C:207-208; the template even
|
|
12
|
-
// starts it `visible=False
|
|
12
|
+
// starts it `visible=False`). Only the subtitle was
|
|
13
13
|
// ever hidden here, so a header bar with a subtitle and no title reserved a
|
|
14
14
|
// blank title line above it.
|
|
15
|
-
// - setting the value it already has returns early (C:203-204
|
|
16
|
-
// - a real change notifies (C:210
|
|
15
|
+
// - setting the value it already has returns early (C:203-204).
|
|
16
|
+
// - a real change notifies (C:210).
|
|
17
17
|
//
|
|
18
18
|
// Reference: refs/adwaita-web/adwaita-web/docs/widgets/windowtitle.md
|
|
19
19
|
// Reference: refs/libadwaita/src/adw-window-title.c, adw-window-title.ui
|
|
@@ -56,7 +56,7 @@ export class AdwWindowTitle extends HTMLElement {
|
|
|
56
56
|
if (!this._initialized) return;
|
|
57
57
|
const changed = name === 'title' ? this._state.setTitle(value) : this._state.setSubtitle(value);
|
|
58
58
|
// The early-return is the whole point: re-setting the same value paints
|
|
59
|
-
// nothing and notifies nothing (C:203-204
|
|
59
|
+
// nothing and notifies nothing (C:203-204).
|
|
60
60
|
if (!changed) return;
|
|
61
61
|
this._render();
|
|
62
62
|
this.dispatchEvent(
|