@gjsify/adwaita-web 0.44.0 → 0.46.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.
Files changed (114) hide show
  1. package/README.md +8 -6
  2. package/dist/adwaita-web.css +96 -96
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/elements/adw-entry-row.d.ts +2 -2
  5. package/lib/types/elements/adw-expander-row.d.ts +1 -1
  6. package/lib/types/elements/adw-header-bar.d.ts +16 -8
  7. package/lib/types/elements/adw-split-button.d.ts +1 -1
  8. package/lib/types/elements/adw-switch-row.d.ts +1 -1
  9. package/lib/types/elements/adw-wrap-box.d.ts +1 -1
  10. package/lib/types/elements/{adw-checks.d.ts → checks.d.ts} +9 -2
  11. package/lib/types/elements/{adw-button.d.ts → gtk-button.d.ts} +1 -1
  12. package/lib/types/elements/{adw-drop-down.d.ts → gtk-drop-down.d.ts} +6 -6
  13. package/lib/types/elements/{adw-entry.d.ts → gtk-entry.d.ts} +1 -1
  14. package/lib/types/elements/{adw-icon.d.ts → gtk-image.d.ts} +2 -2
  15. package/lib/types/elements/{adw-menu-button.d.ts → gtk-menu-button.d.ts} +13 -4
  16. package/lib/types/elements/{adw-popover.d.ts → gtk-popover.d.ts} +9 -9
  17. package/lib/types/elements/{adw-progress-bar.d.ts → gtk-progress-bar.d.ts} +1 -1
  18. package/lib/types/elements/{adw-switch.d.ts → gtk-switch.d.ts} +2 -2
  19. package/lib/types/elements/view-switcher-dom.d.ts +4 -4
  20. package/lib/types/exported-elements.d.ts +10 -0
  21. package/lib/types/gtk-button.spec.d.ts +1 -0
  22. package/lib/types/gtk-drop-down.spec.d.ts +1 -0
  23. package/lib/types/gtk-entry.spec.d.ts +1 -0
  24. package/lib/types/gtk-image.spec.d.ts +1 -0
  25. package/lib/types/gtk-menu-button.spec.d.ts +1 -0
  26. package/lib/types/gtk-progress-bar.spec.d.ts +1 -0
  27. package/lib/types/gtk-switch.spec.d.ts +1 -0
  28. package/lib/types/icon-registry.d.ts +2 -2
  29. package/lib/types/index.d.ts +13 -51
  30. package/lib/types/namespace/adw.d.ts +44 -0
  31. package/lib/types/namespace/gtk.d.ts +9 -0
  32. package/lib/types/styles.generated.d.ts +1 -1
  33. package/package.json +9 -6
  34. package/scss/_about_dialog.scss +1 -1
  35. package/scss/_button.scss +4 -4
  36. package/scss/_checks.scss +6 -6
  37. package/scss/_drop_down.scss +3 -3
  38. package/scss/_entry.scss +3 -3
  39. package/scss/_expander_row.scss +1 -1
  40. package/scss/_icon.scss +4 -4
  41. package/scss/_menu_button.scss +3 -3
  42. package/scss/_popover.scss +2 -2
  43. package/scss/_progress_bar.scss +4 -4
  44. package/scss/_reset.scss +10 -8
  45. package/scss/_split_button.scss +1 -1
  46. package/scss/_style_classes.scss +9 -9
  47. package/scss/_switch.scss +2 -2
  48. package/scss/_switch_row.scss +1 -1
  49. package/scss/_toast.scss +1 -1
  50. package/scss/adwaita-skin.scss +2 -2
  51. package/src/adw-action-rows.spec.ts +2 -2
  52. package/src/adw-button-content.spec.ts +1 -1
  53. package/src/adw-header-bar.spec.ts +9 -4
  54. package/src/adw-tab-view.spec.ts +71 -0
  55. package/src/bottom-sheet.spec.ts +2 -2
  56. package/src/{adw-checks.spec.ts → checks.spec.ts} +11 -11
  57. package/src/chrome.spec.ts +2 -2
  58. package/src/connect-lifecycle.spec.ts +10 -7
  59. package/src/elements/adw-about-dialog.ts +6 -6
  60. package/src/elements/adw-avatar.ts +4 -4
  61. package/src/elements/adw-button-content.ts +6 -6
  62. package/src/elements/adw-button-row.ts +6 -6
  63. package/src/elements/adw-combo-row.ts +1 -1
  64. package/src/elements/adw-entry-row.ts +5 -5
  65. package/src/elements/adw-expander-row.ts +10 -10
  66. package/src/elements/adw-header-bar.ts +34 -13
  67. package/src/elements/adw-navigation-view.ts +24 -4
  68. package/src/elements/adw-password-entry-row.ts +3 -3
  69. package/src/elements/adw-sidebar.ts +4 -4
  70. package/src/elements/adw-split-button.ts +14 -14
  71. package/src/elements/adw-status-page.ts +4 -4
  72. package/src/elements/adw-switch-row.ts +8 -8
  73. package/src/elements/adw-tab-view.ts +32 -10
  74. package/src/elements/adw-toast-overlay.ts +2 -2
  75. package/src/elements/adw-toggle-group.ts +3 -3
  76. package/src/elements/adw-view-switcher-bar.ts +3 -3
  77. package/src/elements/adw-view-switcher.ts +3 -3
  78. package/src/elements/{adw-checks.ts → checks.ts} +13 -6
  79. package/src/elements/{adw-button.ts → gtk-button.ts} +6 -6
  80. package/src/elements/{adw-drop-down.ts → gtk-drop-down.ts} +18 -18
  81. package/src/elements/{adw-entry.ts → gtk-entry.ts} +4 -4
  82. package/src/elements/{adw-icon.ts → gtk-image.ts} +5 -5
  83. package/src/elements/{adw-menu-button.ts → gtk-menu-button.ts} +27 -18
  84. package/src/elements/{adw-popover.ts → gtk-popover.ts} +18 -18
  85. package/src/elements/{adw-progress-bar.ts → gtk-progress-bar.ts} +5 -5
  86. package/src/elements/{adw-switch.ts → gtk-switch.ts} +4 -4
  87. package/src/elements/view-switcher-dom.ts +5 -5
  88. package/src/exported-elements.ts +50 -0
  89. package/src/{adw-button.spec.ts → gtk-button.spec.ts} +6 -6
  90. package/src/{adw-drop-down.spec.ts → gtk-drop-down.spec.ts} +17 -17
  91. package/src/{adw-entry.spec.ts → gtk-entry.spec.ts} +8 -8
  92. package/src/{adw-icon.spec.ts → gtk-image.spec.ts} +21 -21
  93. package/src/{adw-menu-button.spec.ts → gtk-menu-button.spec.ts} +6 -6
  94. package/src/{adw-progress-bar.spec.ts → gtk-progress-bar.spec.ts} +12 -12
  95. package/src/{adw-switch.spec.ts → gtk-switch.spec.ts} +20 -20
  96. package/src/icon-registry.spec.ts +6 -6
  97. package/src/icon-registry.ts +6 -6
  98. package/src/index.ts +64 -63
  99. package/src/namespace/adw.ts +99 -0
  100. package/src/namespace/gtk.ts +22 -0
  101. package/src/preferences-search.ts +1 -1
  102. package/src/slotted-children.spec.ts +5 -3
  103. package/src/source-view/adw-source-view.ts +2 -2
  104. package/src/split-button.spec.ts +5 -5
  105. package/src/styles.generated.ts +1 -1
  106. package/src/test.browser.mts +15 -15
  107. package/lib/types/adw-button.spec.d.ts +0 -1
  108. package/lib/types/adw-drop-down.spec.d.ts +0 -1
  109. package/lib/types/adw-entry.spec.d.ts +0 -1
  110. package/lib/types/adw-icon.spec.d.ts +0 -1
  111. package/lib/types/adw-menu-button.spec.d.ts +0 -1
  112. package/lib/types/adw-progress-bar.spec.d.ts +0 -1
  113. package/lib/types/adw-switch.spec.d.ts +0 -1
  114. /package/lib/types/{adw-checks.spec.d.ts → checks.spec.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- // DOM-level tests for <adw-checkbox> and <adw-radio>, plus the browser side of
1
+ // DOM-level tests for <gtk-check-button> and <adw-radio>, plus the browser side of
2
2
  // the `RADIO_GROUP_VECTORS` conformance table.
3
3
  //
4
4
  // The browser's native radio exclusivity is NOT enough: `<input type="radio" name="g">`
@@ -14,7 +14,7 @@
14
14
  import { describe, expect, it } from '@gjsify/unit';
15
15
  import { RADIO_GROUP_VECTORS } from '@gjsify/adwaita-core/conformance';
16
16
 
17
- import type { AdwCheckbox, AdwRadio } from './elements/adw-checks.js';
17
+ import type { GtkCheckButton, AdwRadio } from './elements/checks.js';
18
18
 
19
19
  function host(): HTMLElement {
20
20
  const el = document.createElement('div');
@@ -22,9 +22,9 @@ function host(): HTMLElement {
22
22
  return el;
23
23
  }
24
24
 
25
- function mountCheckbox(): { el: AdwCheckbox; parent: HTMLElement } {
25
+ function mountCheckbox(): { el: GtkCheckButton; parent: HTMLElement } {
26
26
  const parent = host();
27
- const el = document.createElement('adw-checkbox') as AdwCheckbox;
27
+ const el = document.createElement('gtk-check-button') as GtkCheckButton;
28
28
  parent.appendChild(el);
29
29
  return { el, parent };
30
30
  }
@@ -51,7 +51,7 @@ function glyph(check: HTMLElement): string {
51
51
  }
52
52
 
53
53
  export const AdwChecksTest = async () => {
54
- await describe('<adw-checkbox> state', async () => {
54
+ await describe('<gtk-check-button> state', async () => {
55
55
  await it('builds the input + indicator + label markup', () => {
56
56
  const { el, parent } = mountCheckbox();
57
57
  const { input, indicator, label } = parts(el);
@@ -69,13 +69,13 @@ export const AdwChecksTest = async () => {
69
69
 
70
70
  await it('adopts authored child nodes as the label, and the attribute wins', () => {
71
71
  const parent = host();
72
- const authored = document.createElement('adw-checkbox') as AdwCheckbox;
72
+ const authored = document.createElement('gtk-check-button') as GtkCheckButton;
73
73
  authored.textContent = 'Enable';
74
74
  parent.appendChild(authored);
75
75
  expect(parts(authored).label.textContent).toBe('Enable');
76
76
  expect(parts(authored).label.hidden).toBe(false);
77
77
 
78
- const labelled = document.createElement('adw-checkbox') as AdwCheckbox;
78
+ const labelled = document.createElement('gtk-check-button') as GtkCheckButton;
79
79
  labelled.setAttribute('label', 'From the attribute');
80
80
  labelled.textContent = 'ignored';
81
81
  parent.appendChild(labelled);
@@ -133,7 +133,7 @@ export const AdwChecksTest = async () => {
133
133
  });
134
134
  });
135
135
 
136
- await describe('<adw-checkbox> indeterminate', async () => {
136
+ await describe('<gtk-check-button> indeterminate', async () => {
137
137
  await it('announces as mixed and outranks checked', () => {
138
138
  const { el, parent } = mountCheckbox();
139
139
  el.checked = true;
@@ -152,7 +152,7 @@ export const AdwChecksTest = async () => {
152
152
  // three states proves the cascade, not just that a mask exists.
153
153
  const parent = host();
154
154
  const make = (attrs: string[]) => {
155
- const el = document.createElement('adw-checkbox') as AdwCheckbox;
155
+ const el = document.createElement('gtk-check-button') as GtkCheckButton;
156
156
  for (const attr of attrs) el.setAttribute(attr, '');
157
157
  parent.appendChild(el);
158
158
  return el;
@@ -181,7 +181,7 @@ export const AdwChecksTest = async () => {
181
181
  await describe('check and radio share one stylesheet', async () => {
182
182
  await it('both draw the 14px + 3px indicator, differing only in the radius', () => {
183
183
  const parent = host();
184
- const check = document.createElement('adw-checkbox') as AdwCheckbox;
184
+ const check = document.createElement('gtk-check-button') as GtkCheckButton;
185
185
  const radio = document.createElement('adw-radio') as AdwRadio;
186
186
  parent.append(check, radio);
187
187
 
@@ -219,7 +219,7 @@ export const AdwChecksTest = async () => {
219
219
  radio.setAttribute('name', 'fill-checked');
220
220
  radio.setAttribute('value', 'x');
221
221
  radio.setAttribute('checked', '');
222
- const check = document.createElement('adw-checkbox') as AdwCheckbox;
222
+ const check = document.createElement('gtk-check-button') as GtkCheckButton;
223
223
  check.setAttribute('checked', '');
224
224
  parent.append(plain, radio, check);
225
225
 
@@ -153,7 +153,7 @@ const ROOT_ACTION_PREVIEW = `
153
153
  <adw-window-title slot="center" title="Contacts"></adw-window-title>
154
154
  </adw-header-bar>
155
155
  <div style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">
156
- <adw-button label="Open contact" pill suggested></adw-button>
156
+ <gtk-button label="Open contact" pill suggested></gtk-button>
157
157
  </div>
158
158
  </adw-toolbar-view>`;
159
159
 
@@ -530,7 +530,7 @@ export const AdwChromeTest = async () => {
530
530
  const host = mountPreview(ROOT_ACTION_PREVIEW);
531
531
  await settle();
532
532
  const area = host.querySelector('.adw-toolbar-view-content') as HTMLElement;
533
- const button = host.querySelector('adw-button') as HTMLElement;
533
+ const button = host.querySelector('gtk-button') as HTMLElement;
534
534
 
535
535
  expect(heightOf(area.firstElementChild)).toBe(heightOf(area));
536
536
  // A pill button that grew to the pane's height would be the fill applied
@@ -24,10 +24,14 @@
24
24
  import { describe, expect, it } from '@gjsify/unit';
25
25
 
26
26
  import * as adwaitaWeb from './index.js';
27
+ // Not a bare `Object.values` walk: since ADR 0034 § Amendment 6 the widget classes are
28
+ // members of the exported `Adw`/`Gtk` objects, so a top-level scan reaches only the
29
+ // web-only stragglers while reading as if it swept the package.
30
+ import { exportedElementClasses } from './exported-elements.js';
27
31
 
28
32
  /**
29
33
  * Elements that cannot RENDER a child, however the DOM lets you append one. A container
30
- * getter returning one of these is an imperative handle (`<adw-entry>.input`, for
34
+ * getter returning one of these is an imperative handle (`<gtk-entry>.input`, for
31
35
  * focus and selection), not an append point, and appending to it measures 0 forever.
32
36
  * The HTML void-element set, not a per-widget ledger — a new container still enrols
33
37
  * itself; only a new void element in the spec would need a line here.
@@ -85,9 +89,8 @@ function reveal(el: HTMLElement): void {
85
89
  function registeredElements(): { tags: string[]; unregistered: string[] } {
86
90
  const tags: string[] = [];
87
91
  const unregistered: string[] = [];
88
- for (const exported of Object.values(adwaitaWeb)) {
89
- if (typeof exported !== 'function' || !(exported.prototype instanceof HTMLElement)) continue;
90
- const tag = customElements.getName(exported as CustomElementConstructor);
92
+ for (const exported of exportedElementClasses(adwaitaWeb)) {
93
+ const tag = customElements.getName(exported);
91
94
  if (tag === null) unregistered.push(exported.name);
92
95
  else tags.push(tag);
93
96
  }
@@ -101,7 +104,7 @@ function registeredElements(): { tags: string[]; unregistered: string[] } {
101
104
  * Each half earns its place. No setter, because a container you append into is not one
102
105
  * you replace by assignment — that is what separates `topBar` from `anchor` and
103
106
  * `activatableWidget`. Contained, because the handle has to be part of THIS widget's
104
- * own subtree — `<adw-popover>.anchor` defaults to `parentElement` and is not. And a
107
+ * own subtree — `<gtk-popover>.anchor` defaults to `parentElement` and is not. And a
105
108
  * value that is not an element at all (`items`, `groups`, a `null` slot on an empty
106
109
  * widget) is nothing to append to.
107
110
  *
@@ -326,9 +329,9 @@ export const AdwConnectLifecycleTest = async () => {
326
329
  });
327
330
  }
328
331
 
329
- await it('<adw-popover> still dismisses on an outside click after a move', async () => {
332
+ await it('<gtk-popover> still dismisses on an outside click after a move', async () => {
330
333
  const first = visibleHost();
331
- const popover = document.createElement('adw-popover');
334
+ const popover = document.createElement('gtk-popover');
332
335
  first.appendChild(popover);
333
336
  (popover as HTMLElement & { popup(): void }).popup();
334
337
 
@@ -55,7 +55,7 @@
55
55
  // Reference: refs/adwaita-web/adwaita-web/scss/_about_dialog.scss (web layout)
56
56
  // Copyright (c) 2022-2024 GNOME Foundation Inc. / Purism SPC (libadwaita). LGPLv2.1+.
57
57
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
58
- // icon nodes are <adw-icon>; the derivations live in @gjsify/adwaita-core.
58
+ // icon nodes are <gtk-image>; the derivations live in @gjsify/adwaita-core.
59
59
 
60
60
  import {
61
61
  ADW_ABOUT_DIALOG_LABELS,
@@ -67,7 +67,7 @@ import {
67
67
  stripMnemonic,
68
68
  } from '@gjsify/adwaita-core';
69
69
 
70
- import { createAdwIcon } from './adw-icon.js';
70
+ import { createGtkImage } from './gtk-image.js';
71
71
  import { AdwModalSurface } from './modal-surface.js';
72
72
 
73
73
  /** A template label with its mnemonic marker removed — this renderer has no accelerator layer. */
@@ -440,7 +440,7 @@ export class AdwAboutDialog extends HTMLElement {
440
440
  // `image-missing` rather than three stray classes; that is also what GTK draws for
441
441
  // it on a machine without the app installed.
442
442
  if (visibility.appIcon) {
443
- body.appendChild(createAdwIcon(this.applicationIcon, 'adw-about-dialog-icon'));
443
+ body.appendChild(createGtkImage(this.applicationIcon, 'adw-about-dialog-icon'));
444
444
  }
445
445
 
446
446
  // No fallback: an unset name means no label.
@@ -518,7 +518,7 @@ export class AdwAboutDialog extends HTMLElement {
518
518
  row.setAttribute('title', title);
519
519
  row.setAttribute('activatable', '');
520
520
 
521
- const chevron = createAdwIcon('go-next', 'adw-about-dialog-chevron');
521
+ const chevron = createGtkImage('go-next', 'adw-about-dialog-chevron');
522
522
  chevron.setAttribute('slot', 'suffix');
523
523
  row.appendChild(chevron);
524
524
 
@@ -569,7 +569,7 @@ export class AdwAboutDialog extends HTMLElement {
569
569
  row.setAttribute('activatable', '');
570
570
  row.classList.add('adw-about-dialog-link-row');
571
571
 
572
- const chevron = createAdwIcon('go-next', 'adw-about-dialog-chevron');
572
+ const chevron = createGtkImage('go-next', 'adw-about-dialog-chevron');
573
573
  chevron.setAttribute('slot', 'suffix');
574
574
  row.appendChild(chevron);
575
575
 
@@ -603,7 +603,7 @@ export class AdwAboutDialog extends HTMLElement {
603
603
  const uri = person.uri ?? '';
604
604
  row.setAttribute('activatable', '');
605
605
  row.classList.add('adw-about-dialog-link-row');
606
- const chevron = createAdwIcon('go-next', 'adw-about-dialog-chevron');
606
+ const chevron = createGtkImage('go-next', 'adw-about-dialog-chevron');
607
607
  chevron.setAttribute('slot', 'suffix');
608
608
  row.appendChild(chevron);
609
609
  row.addEventListener('activated', () => this._activateLink(uri));
@@ -7,7 +7,7 @@
7
7
  // Reference: refs/adwaita-web/adwaita-web/scss/_avatar.scss
8
8
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
9
9
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
10
- // fallback icon node is <adw-icon>.
10
+ // fallback icon node is <gtk-image>.
11
11
  //
12
12
  // The two derivations — initials from the name, and the palette colour the name hashes to
13
13
  // — are HEADLESS and live in `@gjsify/adwaita-core` (ADR 0004) as {@link avatarInitials} /
@@ -21,11 +21,11 @@
21
21
 
22
22
  import { avatarColor, avatarFontSize, avatarInitials, avatarMaxFontSize, avatarMode } from '@gjsify/adwaita-core';
23
23
 
24
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
24
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
25
25
 
26
26
  export class AdwAvatar extends HTMLElement {
27
27
  private _textEl!: HTMLSpanElement;
28
- private _iconEl!: AdwIcon;
28
+ private _iconEl!: GtkImage;
29
29
  private _imageEl!: HTMLImageElement;
30
30
  private _initialized = false;
31
31
 
@@ -40,7 +40,7 @@ export class AdwAvatar extends HTMLElement {
40
40
  this._textEl = document.createElement('span');
41
41
  this._textEl.className = 'adw-avatar-text';
42
42
 
43
- this._iconEl = createAdwIcon(null, 'adw-avatar-icon');
43
+ this._iconEl = createGtkImage(null, 'adw-avatar-icon');
44
44
 
45
45
  this._imageEl = document.createElement('img');
46
46
  this._imageEl.className = 'adw-avatar-custom-image';
@@ -20,15 +20,15 @@
20
20
  // (image-text-button · the splitbutton override · buttoncontent)
21
21
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
22
22
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
23
- // icon node is <adw-icon>.
23
+ // icon node is <gtk-image>.
24
24
 
25
25
  import { BUTTON_CONTENT_STYLE_CLASS, buttonContentIconName, buttonContentLabelText } from '@gjsify/adwaita-core';
26
26
 
27
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
27
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
28
28
 
29
29
  /**
30
30
  * What `gtk_widget_get_ancestor (…, GTK_TYPE_BUTTON)` looks like in the DOM: a native
31
- * `<button>`, or anything wearing the Adwaita button class — `<adw-button>` renders an
31
+ * `<button>`, or anything wearing the Adwaita button class — `<gtk-button>` renders an
32
32
  * inner button with it, and the stories put it on plain ones.
33
33
  */
34
34
  const BUTTON_SELECTOR = 'button, .adw-button';
@@ -38,7 +38,7 @@ const SPLIT_BUTTON_SELECTOR = 'adw-split-button, .adw-split-button';
38
38
 
39
39
  export class AdwButtonContent extends HTMLElement {
40
40
  private _boxEl!: HTMLDivElement;
41
- private _iconEl!: AdwIcon;
41
+ private _iconEl!: GtkImage;
42
42
  private _labelEl!: HTMLSpanElement;
43
43
  private _initialized = false;
44
44
  /** The node currently carrying `image-text-button`, so unroot can find it. */
@@ -57,9 +57,9 @@ export class AdwButtonContent extends HTMLElement {
57
57
  this._boxEl.className = 'adw-button-content-box';
58
58
 
59
59
  // The image node is GTK_ACCESSIBLE_ROLE_PRESENTATION in libadwaita: decorative,
60
- // with the label carrying the accessible name — what `<adw-icon>`'s own
60
+ // with the label carrying the accessible name — what `<gtk-image>`'s own
61
61
  // `aria-hidden` already says.
62
- this._iconEl = createAdwIcon(null);
62
+ this._iconEl = createGtkImage(null);
63
63
 
64
64
  this._labelEl = document.createElement('span');
65
65
  this._labelEl.className = 'adw-button-content-label';
@@ -21,13 +21,13 @@
21
21
 
22
22
  import { BUTTON_ROW_ACTIVATABLE, ButtonRowState } from '@gjsify/adwaita-core';
23
23
 
24
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
24
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
25
25
  import { attachRowActivation } from './row-activation.js';
26
26
 
27
27
  export class AdwButtonRow extends HTMLElement {
28
28
  private _contentsEl!: HTMLDivElement;
29
- private _startIconEl!: AdwIcon;
30
- private _endIconEl!: AdwIcon;
29
+ private _startIconEl!: GtkImage;
30
+ private _endIconEl!: GtkImage;
31
31
  private _titleEl!: HTMLSpanElement;
32
32
  /** The headless title + start/end icon state (ADR 0004). */
33
33
  private readonly _state = new ButtonRowState();
@@ -43,12 +43,12 @@ export class AdwButtonRow extends HTMLElement {
43
43
  this._contentsEl = document.createElement('div');
44
44
  this._contentsEl.className = 'adw-button-row-contents';
45
45
 
46
- this._startIconEl = createAdwIcon(null, 'start');
46
+ this._startIconEl = createGtkImage(null, 'start');
47
47
 
48
48
  this._titleEl = document.createElement('span');
49
49
  this._titleEl.className = 'adw-button-row-title';
50
50
 
51
- this._endIconEl = createAdwIcon(null, 'end');
51
+ this._endIconEl = createGtkImage(null, 'end');
52
52
 
53
53
  this._contentsEl.append(this._startIconEl, this._titleEl, this._endIconEl);
54
54
  this.replaceChildren(this._contentsEl);
@@ -89,7 +89,7 @@ export class AdwButtonRow extends HTMLElement {
89
89
  * The `start` / `end` position class is set once at construction — it is
90
90
  * where the node sits, not what it draws — so only the name changes here.
91
91
  */
92
- private _paintIcon(el: AdwIcon, iconName: string, visible: boolean) {
92
+ private _paintIcon(el: GtkImage, iconName: string, visible: boolean) {
93
93
  el.iconName = visible ? iconName : null;
94
94
  el.hidden = !visible;
95
95
  }
@@ -43,7 +43,7 @@ export class AdwComboRow extends HTMLElement {
43
43
  const items: string[] = JSON.parse(this.getAttribute('items') || '[]');
44
44
  // Seed the headless state BEFORE subscribing, so building the initial DOM below is
45
45
  // not driven by a change notification. The string→descriptor mapping is core's, so
46
- // this row and `<adw-drop-down>` accept one option vocabulary.
46
+ // this row and `<gtk-drop-down>` accept one option vocabulary.
47
47
  this._state.setOptions(normalizeComboOptions(items));
48
48
  this._state.setSelectedIndex(parseInt(this.getAttribute('selected') || '0', 10));
49
49
  const selectedIdx = this._state.selectedIndex;
@@ -27,7 +27,7 @@
27
27
  // Reference: refs/libadwaita/src/stylesheet/widgets/_entries.scss
28
28
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
29
29
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
30
- // edit icon node is <adw-icon>.
30
+ // edit icon node is <gtk-image>.
31
31
 
32
32
  import {
33
33
  ENTRY_ROW_APPLY_ICON_NAME,
@@ -38,7 +38,7 @@ import {
38
38
  } from '@gjsify/adwaita-core';
39
39
 
40
40
  import { bindSlottedChildren, type AdwSlottedChildren } from '../slotted-children.js';
41
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
41
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
42
42
 
43
43
  /**
44
44
  * Show/hide a rendered part. `hidden` carries the semantics and is what the conformance
@@ -66,7 +66,7 @@ export class AdwEntryRow extends HTMLElement {
66
66
  protected _title!: HTMLSpanElement;
67
67
  /** The `editable-area` gizmo: both titles plus the input. */
68
68
  protected _area!: HTMLDivElement;
69
- protected _editIcon!: AdwIcon;
69
+ protected _editIcon!: GtkImage;
70
70
  protected _indicator!: HTMLSpanElement;
71
71
  protected _applyButton!: HTMLButtonElement;
72
72
  protected _prefixes!: HTMLDivElement;
@@ -326,11 +326,11 @@ export class AdwEntryRow extends HTMLElement {
326
326
  // The libadwaita name travels in `data-icon-name`; the drawn glyph is
327
327
  // the curated @gjsify/adwaita-icons spelling of the same symbolic, which
328
328
  // is a different string (`adw-entry-edit-symbolic` vs `document-edit`).
329
- this._editIcon = createAdwIcon('document-edit', 'adw-row-edit', `${prefix}-edit`);
329
+ this._editIcon = createGtkImage('document-edit', 'adw-row-edit', `${prefix}-edit`);
330
330
  this._editIcon.dataset.iconName = ENTRY_ROW_EDIT_ICON_NAME;
331
331
 
332
332
  // Author-supplied light-DOM children are KEPT and stay LIVE: `replaceChildren` used
333
- // to discard them silently, so `<adw-entry-row><adw-button>Go</adw-button>` rendered
333
+ // to discard them silently, so `<adw-entry-row><gtk-button>Go</gtk-button>` rendered
334
334
  // without its button, and the snapshot that fixed that was still a one-shot read — a
335
335
  // suffix appended after connect sat outside the affordance box. ELEMENTS only, on
336
336
  // both paths: GtkBuildable also only ever adopts widgets, and keeping stray
@@ -17,7 +17,7 @@
17
17
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
18
18
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
19
19
  // disclosure state machine composed from @gjsify/adwaita-core, the enable
20
- // switch from <adw-switch> and the chevron from <adw-icon>.
20
+ // switch from <gtk-switch> and the chevron from <gtk-image>.
21
21
 
22
22
  import { ExpanderState, deriveRowLabels } from '@gjsify/adwaita-core';
23
23
 
@@ -25,22 +25,22 @@ import { bindEmptySections } from '../empty-sections.js';
25
25
  import { bindSlottedChildren } from '../slotted-children.js';
26
26
 
27
27
  // SIDE-EFFECT import, deliberately separate from the type import below: it guarantees
28
- // `adw-switch` is defined before this module's `customElements.define` can upgrade a
28
+ // `gtk-switch` is defined before this module's `customElements.define` can upgrade a
29
29
  // server-rendered `<adw-expander-row>` and build one. A combined
30
- // `import { AdwSwitch }` would NOT do it — the binding is only used in type position,
30
+ // `import { GtkSwitch }` would NOT do it — the binding is only used in type position,
31
31
  // and this package compiles without `verbatimModuleSyntax`, so TypeScript would elide
32
32
  // the statement and take the registration with it.
33
- import './adw-switch.js';
34
- import type { AdwSwitch } from './adw-switch.js';
35
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
33
+ import './gtk-switch.js';
34
+ import type { GtkSwitch } from './gtk-switch.js';
35
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
36
36
  import { attachRowActivation } from './row-activation.js';
37
37
 
38
38
  export class AdwExpanderRow extends HTMLElement {
39
39
  private _headerEl!: HTMLDivElement;
40
40
  private _titleEl!: HTMLSpanElement;
41
41
  private _subtitleEl!: HTMLSpanElement;
42
- private _enableSwitch!: AdwSwitch;
43
- private _chevronEl!: AdwIcon;
42
+ private _enableSwitch!: GtkSwitch;
43
+ private _chevronEl!: GtkImage;
44
44
  private _contentEl!: HTMLDivElement;
45
45
  private _prefixEl!: HTMLDivElement;
46
46
  private _suffixEl!: HTMLDivElement;
@@ -118,11 +118,11 @@ export class AdwExpanderRow extends HTMLElement {
118
118
  textEl.append(this._titleEl, this._subtitleEl);
119
119
 
120
120
  // Clicking the enable switch does NOT toggle the disclosure.
121
- this._enableSwitch = document.createElement('adw-switch') as AdwSwitch;
121
+ this._enableSwitch = document.createElement('gtk-switch') as GtkSwitch;
122
122
  this._enableSwitch.classList.add('adw-expander-row-enable-switch');
123
123
  this._enableSwitch.active = this.enableExpansion;
124
124
 
125
- this._chevronEl = createAdwIcon('go-down', 'adw-expander-row-chevron');
125
+ this._chevronEl = createGtkImage('go-down', 'adw-expander-row-chevron');
126
126
 
127
127
  this._prefixEl = document.createElement('div');
128
128
  this._prefixEl.className = 'adw-expander-row-prefix';
@@ -1,8 +1,20 @@
1
1
  // <adw-header-bar> — Adwaita header bar with centered title and start/end button slots.
2
2
  //
3
- // The derived centre is an `<adw-window-title>`, which is what `Adw.HeaderBar`
4
- // itself puts there (`adw-header-bar.c`: the title widget it creates when none is
5
- // given IS an `AdwWindowTitle`). It used to be a bare span with
3
+ // The derived centre is an `<adw-window-title>`. That is a DIVERGENCE, and the comment
4
+ // here used to claim the opposite — that `Adw.HeaderBar` puts one there. Measured
5
+ // against the source: `construct_title_label` (adw-header-bar.c:512) builds a plain
6
+ // `gtk_label_new (NULL)` with the `title` class, `single-line-mode` and
7
+ // `ellipsize=END`, and `Adw.HeaderBar` has NO `title` property at all — `update_title`
8
+ // (:475) resolves one from the navigation page, then the dialog, then the root window,
9
+ // then `g_get_application_name`, then `g_get_prgname`. An app that wants a subtitle
10
+ // there sets an `AdwWindowTitle` as its title-widget.
11
+ //
12
+ // The divergence is kept: a declarative surface wants `title=` / `subtitle=` attributes
13
+ // rather than a widget handoff, and both renderers already use them. It is recorded as
14
+ // `HeaderBarRenderState.derivedSubtitle` in `@gjsify/adwaita-core`, so it is a named
15
+ // difference instead of a mistaken claim of fidelity.
16
+ //
17
+ // It used to be a bare span with
6
18
  // `textContent = title ?? ''`, and that span carried none of the three rules the
7
19
  // window title already held in `@gjsify/adwaita-core`: an EMPTY title still
8
20
  // reserved a blank line, re-setting the same value repainted, and there was no
@@ -29,8 +41,10 @@ export class AdwHeaderBar extends HTMLElement {
29
41
  private _endEl: HTMLDivElement | null = null;
30
42
  /**
31
43
  * The derived `<adw-window-title>`, or `null` when a `slot="center"`
32
- * title-widget took the centre. `Adw.HeaderBar` has the same either/or:
33
- * setting `title-widget` replaces the derived `AdwWindowTitle` outright.
44
+ * title-widget took the centre. `Adw.HeaderBar` has the same either/or —
45
+ * `adw_header_bar_set_title_widget` empties the centre bin before installing
46
+ * (adw-header-bar.c:1201) — over a derived `GtkLabel`, not an `AdwWindowTitle`;
47
+ * see the divergence at the top of this file.
34
48
  */
35
49
  private _titleEl: HTMLElement | null = null;
36
50
 
@@ -86,8 +100,9 @@ export class AdwHeaderBar extends HTMLElement {
86
100
  ).install(this._startEl, this._centerEl, this._endEl);
87
101
 
88
102
  // Derived only when the centre is still free — the same either/or as
89
- // `Adw.HeaderBar`, which builds an `AdwWindowTitle` exactly while no title-widget
90
- // was given.
103
+ // `Adw.HeaderBar`, which runs `construct_title_label` exactly while no
104
+ // title-widget holds the centre (adw-header-bar.c:1211). What it builds there is
105
+ // a `GtkLabel`; this is the documented `<adw-window-title>` divergence.
91
106
  if (this._centerEl.childElementCount === 0) {
92
107
  this._titleEl = document.createElement('adw-window-title');
93
108
  this._titleEl.className = 'adw-header-bar-title';
@@ -99,18 +114,24 @@ export class AdwHeaderBar extends HTMLElement {
99
114
  /**
100
115
  * `title` used to be read ONCE, in `connectedCallback`, so every later write
101
116
  * was a silent no-op — a header bar whose title tracked the open document
102
- * kept whatever it was created with. `Adw.HeaderBar`'s derived title widget
103
- * is bound to the property and re-renders on every change.
117
+ * kept whatever it was created with. `Adw.HeaderBar` never reads its title once
118
+ * either: it has no `title` property at all, and re-runs `update_title`
119
+ * (adw-header-bar.c:475) on every ancestor change that could move the answer.
104
120
  */
105
121
  attributeChangedCallback() {
106
122
  if (this._initialized) this._renderTitle();
107
123
  }
108
124
 
109
125
  /**
110
- * Give the centre up to a title-widget. `adw_header_bar_set_title_widget` destroys the
111
- * derived `AdwWindowTitle` rather than stacking the two, so the late case has to remove
112
- * it too — a bar showing both would be a shape neither GTK nor the declared markup can
113
- * produce.
126
+ * Give the centre up to a title-widget. `adw_header_bar_set_title_widget` empties the
127
+ * centre bin and drops its derived label (adw-header-bar.c:1201, :1209) rather than
128
+ * stacking the two, so the late case has to remove ours too — a bar showing both would
129
+ * be a shape neither GTK nor the declared markup can produce.
130
+ *
131
+ * NOT SYMMETRIC HERE, AND KNOWN: C rebuilds the label the moment the title-widget goes
132
+ * away (:1211); nothing in this element brings the derived centre back, so a bar that
133
+ * gave it up has given it up for good. `HeaderBarState` in `@gjsify/adwaita-core` holds
134
+ * the rebuild, and this element adopting it is the rewiring tracked in #1343.
114
135
  */
115
136
  private _dropDerivedTitle() {
116
137
  this._titleEl?.remove();
@@ -100,8 +100,20 @@ export class AdwNavigationPage extends HTMLElement {
100
100
  // back-button derivation read the CORE's copy — so a runtime change has to
101
101
  // be pushed into it. Without this the back button only ever reflected the
102
102
  // `can-pop` value it had at the last stack mutation.
103
- const view = this.closest('adw-navigation-view') as AdwNavigationView | null;
104
- view?.syncPageProperty(this, name, previous);
103
+ //
104
+ // `instanceof` rather than a cast plus `?.`: the two failures the `?.`
105
+ // conflated are different. A MISSING ancestor is one; an ancestor that IS
106
+ // there but is still an ordinary HTMLElement, because its own definition has
107
+ // not upgraded it yet, is the other, and the cast asserted it away. Measured
108
+ // on `dist/test.browser.mjs` against declared markup parsed before the module
109
+ // loaded: `syncPageProperty is not a function`, once per observed attribute
110
+ // per declared page. Dropping the notification for an un-upgraded view loses
111
+ // nothing — such a view has not registered this page, `syncPageProperty`
112
+ // already returns on `!isRegistered`, and `connectedCallback` reads the
113
+ // properties back out of the element through `readPageProps`.
114
+ const view = this.closest('adw-navigation-view');
115
+ if (!(view instanceof AdwNavigationView)) return;
116
+ view.syncPageProperty(this, name, previous);
105
117
  }
106
118
 
107
119
  revertAttribute(name: string, value: string | null): void {
@@ -445,7 +457,7 @@ export class AdwNavigationView extends HTMLElement {
445
457
  const start = (headerBar as { startSection?: HTMLElement | null }).startSection ?? null;
446
458
  if (!start) return;
447
459
 
448
- const back = document.createElement('adw-button');
460
+ const back = document.createElement('gtk-button');
449
461
  back.classList.add('adw-navigation-back-button');
450
462
  back.setAttribute('icon', 'go-previous');
451
463
  back.setAttribute('flat', '');
@@ -464,5 +476,13 @@ export class AdwNavigationView extends HTMLElement {
464
476
  }
465
477
  }
466
478
 
467
- customElements.define('adw-navigation-page', AdwNavigationPage);
479
+ // The VIEW first, and the order carries weight: `define` upgrades every matching
480
+ // element already in the document, immediately, so these two calls are a sequence and
481
+ // not a pair. Registering the page first upgraded every declared
482
+ // `<adw-navigation-page>` while its `<adw-navigation-view>` parent was still an
483
+ // ordinary HTMLElement, and `AdwNavigationPage.attributeChangedCallback` reaches for
484
+ // that parent. Parent before child keeps the window shut; the `instanceof` guard in
485
+ // the callback is what holds when something outside this file reopens it.
486
+ // `scripts/check-adwaita-upgrade-order.mjs` holds the order itself.
468
487
  customElements.define('adw-navigation-view', AdwNavigationView);
488
+ customElements.define('adw-navigation-page', AdwNavigationPage);
@@ -22,7 +22,7 @@
22
22
 
23
23
  import { PasswordEntryRowState, type PasswordEntryRowRenderState } from '@gjsify/adwaita-core';
24
24
 
25
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
25
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
26
26
 
27
27
  import { AdwEntryRow } from './adw-entry-row.js';
28
28
 
@@ -30,7 +30,7 @@ export class AdwPasswordEntryRow extends AdwEntryRow {
30
30
  /** The headless peek + caps-lock derivation, composing the parent row's state. */
31
31
  private readonly _password = new PasswordEntryRowState(this._state);
32
32
  private _toggle!: HTMLButtonElement;
33
- private _toggleIcon!: AdwIcon;
33
+ private _toggleIcon!: GtkImage;
34
34
 
35
35
  static get observedAttributes(): string[] {
36
36
  return [...AdwEntryRow.observedAttributes, 'revealed'];
@@ -73,7 +73,7 @@ export class AdwPasswordEntryRow extends AdwEntryRow {
73
73
  this._toggle = document.createElement('button');
74
74
  this._toggle.type = 'button';
75
75
  this._toggle.className = `adw-button flat circular icon-only ${this._classPrefix}-toggle`;
76
- this._toggleIcon = createAdwIcon(null);
76
+ this._toggleIcon = createGtkImage(null);
77
77
  this._toggle.append(this._toggleIcon);
78
78
  this._toggle.addEventListener('click', () => this._password.togglePeek());
79
79
  // Installed through add_suffix as C does, so it is the FIRST suffix and a
@@ -43,7 +43,7 @@
43
43
  // Reference: refs/libadwaita/src/stylesheet/widgets/_sidebars.scss (.navigation-sidebar, sidebar)
44
44
  // Copyright (c) 2025 GNOME Foundation Inc. (libadwaita). LGPLv2.1+.
45
45
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
46
- // icon nodes are <adw-icon>.
46
+ // icon nodes are <gtk-image>.
47
47
 
48
48
  import {
49
49
  ADW_SIDEBAR_NO_SELECTION,
@@ -56,7 +56,7 @@ import {
56
56
  type SidebarSelectionChange,
57
57
  } from '@gjsify/adwaita-core';
58
58
 
59
- import { createAdwIcon } from './adw-icon.js';
59
+ import { createGtkImage } from './gtk-image.js';
60
60
  import { attachRovingFocus } from './roving-focus.js';
61
61
 
62
62
  // The sidebar consumes its declared children and drops them from the tree, so a later
@@ -348,7 +348,7 @@ export class AdwSidebar extends HTMLElement {
348
348
  row.hidden = item.visible === false;
349
349
  row.disabled = item.enabled === false;
350
350
 
351
- const iconEl = createAdwIcon(item.iconName ?? null, 'adw-sidebar-item-icon');
351
+ const iconEl = createGtkImage(item.iconName ?? null, 'adw-sidebar-item-icon');
352
352
  iconEl.hidden = !flat.iconVisible;
353
353
  row.appendChild(iconEl);
354
354
 
@@ -371,7 +371,7 @@ export class AdwSidebar extends HTMLElement {
371
371
 
372
372
  // Page mode adds a trailing chevron on every row, the way the boxed-list
373
373
  // AdwActionRow carries a `go-next-symbolic` arrow.
374
- row.appendChild(createAdwIcon('go-next', 'adw-sidebar-item-arrow'));
374
+ row.appendChild(createGtkImage('go-next', 'adw-sidebar-item-arrow'));
375
375
 
376
376
  row.addEventListener('click', () => this._activate(flat.index));
377
377