@gjsify/adwaita-web 0.45.0 → 0.47.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 (110) 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-split-button.d.ts +1 -1
  7. package/lib/types/elements/adw-switch-row.d.ts +1 -1
  8. package/lib/types/elements/adw-wrap-box.d.ts +1 -1
  9. package/lib/types/elements/{adw-checks.d.ts → checks.d.ts} +9 -2
  10. package/lib/types/elements/{adw-button.d.ts → gtk-button.d.ts} +1 -1
  11. package/lib/types/elements/{adw-drop-down.d.ts → gtk-drop-down.d.ts} +6 -6
  12. package/lib/types/elements/{adw-entry.d.ts → gtk-entry.d.ts} +1 -1
  13. package/lib/types/elements/{adw-icon.d.ts → gtk-image.d.ts} +2 -2
  14. package/lib/types/elements/{adw-menu-button.d.ts → gtk-menu-button.d.ts} +13 -4
  15. package/lib/types/elements/{adw-popover.d.ts → gtk-popover.d.ts} +9 -9
  16. package/lib/types/elements/{adw-progress-bar.d.ts → gtk-progress-bar.d.ts} +1 -1
  17. package/lib/types/elements/{adw-switch.d.ts → gtk-switch.d.ts} +2 -2
  18. package/lib/types/elements/view-switcher-dom.d.ts +4 -4
  19. package/lib/types/exported-elements.d.ts +10 -0
  20. package/lib/types/gtk-button.spec.d.ts +1 -0
  21. package/lib/types/gtk-drop-down.spec.d.ts +1 -0
  22. package/lib/types/gtk-entry.spec.d.ts +1 -0
  23. package/lib/types/gtk-image.spec.d.ts +1 -0
  24. package/lib/types/gtk-menu-button.spec.d.ts +1 -0
  25. package/lib/types/gtk-progress-bar.spec.d.ts +1 -0
  26. package/lib/types/gtk-switch.spec.d.ts +1 -0
  27. package/lib/types/icon-registry.d.ts +2 -2
  28. package/lib/types/index.d.ts +13 -51
  29. package/lib/types/namespace/adw.d.ts +44 -0
  30. package/lib/types/namespace/gtk.d.ts +9 -0
  31. package/lib/types/styles.generated.d.ts +1 -1
  32. package/package.json +6 -6
  33. package/scss/_about_dialog.scss +1 -1
  34. package/scss/_button.scss +4 -4
  35. package/scss/_checks.scss +6 -6
  36. package/scss/_drop_down.scss +3 -3
  37. package/scss/_entry.scss +3 -3
  38. package/scss/_expander_row.scss +1 -1
  39. package/scss/_icon.scss +4 -4
  40. package/scss/_menu_button.scss +3 -3
  41. package/scss/_popover.scss +2 -2
  42. package/scss/_progress_bar.scss +4 -4
  43. package/scss/_reset.scss +10 -8
  44. package/scss/_split_button.scss +1 -1
  45. package/scss/_style_classes.scss +9 -9
  46. package/scss/_switch.scss +2 -2
  47. package/scss/_switch_row.scss +1 -1
  48. package/scss/_toast.scss +1 -1
  49. package/scss/adwaita-skin.scss +2 -2
  50. package/src/adw-action-rows.spec.ts +2 -2
  51. package/src/adw-button-content.spec.ts +1 -1
  52. package/src/bottom-sheet.spec.ts +2 -2
  53. package/src/{adw-checks.spec.ts → checks.spec.ts} +11 -11
  54. package/src/chrome.spec.ts +2 -2
  55. package/src/connect-lifecycle.spec.ts +10 -7
  56. package/src/elements/adw-about-dialog.ts +6 -6
  57. package/src/elements/adw-avatar.ts +4 -4
  58. package/src/elements/adw-button-content.ts +6 -6
  59. package/src/elements/adw-button-row.ts +6 -6
  60. package/src/elements/adw-combo-row.ts +1 -1
  61. package/src/elements/adw-entry-row.ts +5 -5
  62. package/src/elements/adw-expander-row.ts +10 -10
  63. package/src/elements/adw-navigation-view.ts +1 -1
  64. package/src/elements/adw-password-entry-row.ts +3 -3
  65. package/src/elements/adw-sidebar.ts +4 -4
  66. package/src/elements/adw-split-button.ts +14 -14
  67. package/src/elements/adw-status-page.ts +4 -4
  68. package/src/elements/adw-switch-row.ts +8 -8
  69. package/src/elements/adw-tab-view.ts +7 -7
  70. package/src/elements/adw-toast-overlay.ts +2 -2
  71. package/src/elements/adw-toggle-group.ts +3 -3
  72. package/src/elements/adw-view-switcher-bar.ts +3 -3
  73. package/src/elements/adw-view-switcher.ts +3 -3
  74. package/src/elements/{adw-checks.ts → checks.ts} +13 -6
  75. package/src/elements/{adw-button.ts → gtk-button.ts} +6 -6
  76. package/src/elements/{adw-drop-down.ts → gtk-drop-down.ts} +18 -18
  77. package/src/elements/{adw-entry.ts → gtk-entry.ts} +4 -4
  78. package/src/elements/{adw-icon.ts → gtk-image.ts} +5 -5
  79. package/src/elements/{adw-menu-button.ts → gtk-menu-button.ts} +27 -18
  80. package/src/elements/{adw-popover.ts → gtk-popover.ts} +18 -18
  81. package/src/elements/{adw-progress-bar.ts → gtk-progress-bar.ts} +5 -5
  82. package/src/elements/{adw-switch.ts → gtk-switch.ts} +4 -4
  83. package/src/elements/view-switcher-dom.ts +5 -5
  84. package/src/exported-elements.ts +50 -0
  85. package/src/{adw-button.spec.ts → gtk-button.spec.ts} +6 -6
  86. package/src/{adw-drop-down.spec.ts → gtk-drop-down.spec.ts} +17 -17
  87. package/src/{adw-entry.spec.ts → gtk-entry.spec.ts} +8 -8
  88. package/src/{adw-icon.spec.ts → gtk-image.spec.ts} +21 -21
  89. package/src/{adw-menu-button.spec.ts → gtk-menu-button.spec.ts} +6 -6
  90. package/src/{adw-progress-bar.spec.ts → gtk-progress-bar.spec.ts} +12 -12
  91. package/src/{adw-switch.spec.ts → gtk-switch.spec.ts} +20 -20
  92. package/src/icon-registry.spec.ts +6 -6
  93. package/src/icon-registry.ts +6 -6
  94. package/src/index.ts +64 -63
  95. package/src/namespace/adw.ts +99 -0
  96. package/src/namespace/gtk.ts +22 -0
  97. package/src/preferences-search.ts +1 -1
  98. package/src/slotted-children.spec.ts +5 -3
  99. package/src/source-view/adw-source-view.ts +2 -2
  100. package/src/split-button.spec.ts +5 -5
  101. package/src/styles.generated.ts +1 -1
  102. package/src/test.browser.mts +15 -15
  103. package/lib/types/adw-button.spec.d.ts +0 -1
  104. package/lib/types/adw-drop-down.spec.d.ts +0 -1
  105. package/lib/types/adw-entry.spec.d.ts +0 -1
  106. package/lib/types/adw-icon.spec.d.ts +0 -1
  107. package/lib/types/adw-menu-button.spec.d.ts +0 -1
  108. package/lib/types/adw-progress-bar.spec.d.ts +0 -1
  109. package/lib/types/adw-switch.spec.d.ts +0 -1
  110. /package/lib/types/{adw-checks.spec.d.ts → checks.spec.d.ts} +0 -0
@@ -54,13 +54,13 @@ import {
54
54
  domViewSwitcherScheduler,
55
55
  readSwitcherPage,
56
56
  } from './view-switcher-dom.js';
57
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
57
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
58
58
  import { attachRovingFocus } from './roving-focus.js';
59
59
 
60
60
  /** The DOM nodes one page owns — the switcher paints the derived model onto them. */
61
61
  interface PageNodes {
62
62
  button: HTMLButtonElement;
63
- icon: AdwIcon;
63
+ icon: GtkImage;
64
64
  label: HTMLSpanElement;
65
65
  indicator: HTMLSpanElement;
66
66
  body: HTMLDivElement;
@@ -271,7 +271,7 @@ export class AdwViewSwitcher extends HTMLElement {
271
271
 
272
272
  // Both children always exist, as in AdwViewSwitcherButton's template — the icon
273
273
  // carries `image-missing` rather than disappearing.
274
- const icon = createAdwIcon(null, 'adw-view-switcher-icon');
274
+ const icon = createGtkImage(null, 'adw-view-switcher-icon');
275
275
 
276
276
  const label = document.createElement('span');
277
277
  label.className = 'adw-view-switcher-label';
@@ -1,4 +1,4 @@
1
- // <adw-checkbox> and <adw-radio> — the two form-control primitives, in ONE module,
1
+ // <gtk-check-button> and <adw-radio> — the two form-control primitives, in ONE module,
2
2
  // for the same reason `scss/_checks.scss` is one partial: upstream merges them
3
3
  // (`refs/libadwaita/src/stylesheet/widgets/_checks.scss` has no `_radio.scss` beside
4
4
  // it), and everything but the corner radius, the glyph and the group is shared.
@@ -35,7 +35,7 @@
35
35
  // disabled — boolean; the control does not respond and is dimmed.
36
36
  // label — the text beside the indicator. When absent, the element's
37
37
  // existing child nodes become the label (so a server-rendered
38
- // `<adw-checkbox>Enable</adw-checkbox>` upgrades intact).
38
+ // `<gtk-check-button>Enable</gtk-check-button>` upgrades intact).
39
39
  // Attributes (<adw-radio> only):
40
40
  // name — the group. Exclusivity is scoped to it, exactly as `name`
41
41
  // scopes `<input type="radio">` — including the empty case:
@@ -68,7 +68,14 @@ import { RadioGroupState, resolveCheckState } from '@gjsify/adwaita-core';
68
68
  */
69
69
  const radioGroups = new RadioGroupState();
70
70
 
71
- /** The markup + state shared by `<adw-checkbox>` and `<adw-radio>`. */
71
+ /**
72
+ * The markup + state shared by `<gtk-check-button>` and `<adw-radio>`.
73
+ *
74
+ * It keeps the `Adw` prefix while the element above it does not, and the split is the
75
+ * same one the stylesheet makes: this class builds `.adw-check-input`,
76
+ * `.adw-check-indicator` and `.adw-check-label`, which are the Adwaita SKIN, and the
77
+ * skin is not what the tag names. It is also not a widget — nothing registers it.
78
+ */
72
79
  abstract class AdwCheckBase extends HTMLElement {
73
80
  protected _input!: HTMLInputElement;
74
81
  protected _indicator!: HTMLSpanElement;
@@ -124,7 +131,7 @@ abstract class AdwCheckBase extends HTMLElement {
124
131
  this._initialized = true;
125
132
 
126
133
  // Captured BEFORE the element takes over its own children, so a server-rendered
127
- // `<adw-checkbox>Enable</adw-checkbox>` keeps its text.
134
+ // `<gtk-check-button>Enable</gtk-check-button>` keeps its text.
128
135
  const authored = [...this.childNodes];
129
136
 
130
137
  this._input = document.createElement('input');
@@ -193,7 +200,7 @@ abstract class AdwCheckBase extends HTMLElement {
193
200
  }
194
201
 
195
202
  /** The Adwaita checkbox — `checkbutton > check` as a custom element. */
196
- export class AdwCheckbox extends AdwCheckBase {
203
+ export class GtkCheckButton extends AdwCheckBase {
197
204
  static get observedAttributes() {
198
205
  return ['checked', 'indeterminate', 'disabled', 'label'];
199
206
  }
@@ -282,5 +289,5 @@ export class AdwRadio extends AdwCheckBase {
282
289
  }
283
290
  }
284
291
 
285
- customElements.define('adw-checkbox', AdwCheckbox);
292
+ customElements.define('gtk-check-button', GtkCheckButton);
286
293
  customElements.define('adw-radio', AdwRadio);
@@ -1,4 +1,4 @@
1
- // <adw-button> — Adwaita button.
1
+ // <gtk-button> — Adwaita button.
2
2
  // Attributes: icon (symbolic name, e.g. "go-previous" / "view-refresh"),
3
3
  // label, tooltip, disabled, and the boolean variant flags
4
4
  // flat / suggested / destructive / circular / pill.
@@ -7,16 +7,16 @@
7
7
  // Reference: refs/libadwaita/src/stylesheet/widgets/_buttons.scss
8
8
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
9
9
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
10
- // icon node is <adw-icon>.
10
+ // icon node is <gtk-image>.
11
11
 
12
12
  import { buttonStyleClasses } from '@gjsify/adwaita-core';
13
13
 
14
- import { createAdwIcon } from './adw-icon.js';
14
+ import { createGtkImage } from './gtk-image.js';
15
15
 
16
16
  /** The boolean attributes that select a style class; the mapping lives in the core. */
17
17
  const STYLE_ATTRIBUTES = ['flat', 'suggested', 'destructive', 'circular', 'pill'] as const;
18
18
 
19
- export class AdwButton extends HTMLElement {
19
+ export class GtkButton extends HTMLElement {
20
20
  private _button!: HTMLButtonElement;
21
21
  private _label = '';
22
22
  private _initialized = false;
@@ -57,7 +57,7 @@ export class AdwButton extends HTMLElement {
57
57
  if (icon && !label) btn.classList.add('icon-only');
58
58
 
59
59
  btn.replaceChildren();
60
- if (icon) btn.appendChild(createAdwIcon(icon));
60
+ if (icon) btn.appendChild(createGtkImage(icon));
61
61
  if (label) btn.appendChild(document.createTextNode(label));
62
62
 
63
63
  const tooltip = this.getAttribute('tooltip');
@@ -74,4 +74,4 @@ export class AdwButton extends HTMLElement {
74
74
  }
75
75
  }
76
76
 
77
- customElements.define('adw-button', AdwButton);
77
+ customElements.define('gtk-button', GtkButton);
@@ -1,4 +1,4 @@
1
- // <adw-drop-down> — A standalone dropdown selector: the web counterpart of
1
+ // <gtk-drop-down> — A standalone dropdown selector: the web counterpart of
2
2
  // Gtk.DropDown. It is a flat Adwaita button showing the current selection (its
3
3
  // label + a `pan-down` chevron) that opens an Adwaita popover list of options;
4
4
  // picking one updates the selection. This is the toolbar/inline control twin of
@@ -12,7 +12,7 @@
12
12
  // Escape and supports arrow-key navigation, Home/End, Enter to pick, and
13
13
  // type-ahead (typing jumps to the next matching option).
14
14
  //
15
- // The popover is `<adw-popover>` and the dismissal/keyboard machine is
15
+ // The popover is `<gtk-popover>` and the dismissal/keyboard machine is
16
16
  // `@gjsify/adwaita-core`'s (ADR 0004). So is the SELECTION: the options list, the
17
17
  // index↔value mapping, the bounds guards and the programmatic-vs-interactive split are
18
18
  // {@link ComboState}, the same state machine `<adw-combo-row>` composes — so both
@@ -47,31 +47,31 @@
47
47
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
48
48
 
49
49
  // SIDE-EFFECT import, deliberately separate from the type import below: it is
50
- // what guarantees `adw-popover` is defined before this module's own
51
- // `customElements.define` can upgrade a server-rendered `<adw-drop-down>` and
52
- // build one. A combined `import { AdwPopover }` would NOT do it — the binding is
50
+ // what guarantees `gtk-popover` is defined before this module's own
51
+ // `customElements.define` can upgrade a server-rendered `<gtk-drop-down>` and
52
+ // build one. A combined `import { GtkPopover }` would NOT do it — the binding is
53
53
  // only ever used in type position here, and this package compiles without
54
54
  // `verbatimModuleSyntax`, so TypeScript would elide the whole statement and take
55
55
  // the registration with it.
56
- import './adw-popover.js';
57
- import type { AdwPopover } from './adw-popover.js';
56
+ import './gtk-popover.js';
57
+ import type { GtkPopover } from './gtk-popover.js';
58
58
 
59
59
  import { ComboState, normalizeComboOptions } from '@gjsify/adwaita-core';
60
60
  import type { AdwComboOption, AdwComboOptionInput } from '@gjsify/adwaita-core';
61
61
 
62
- import { createAdwIcon } from './adw-icon.js';
62
+ import { createGtkImage } from './gtk-image.js';
63
63
 
64
64
  /**
65
65
  * A dropdown option — `value` is the stable id, `label` the shown text. An alias of
66
66
  * core's {@link AdwComboOption}, since the drop-down and the combo row are the same
67
67
  * selection model behind two chromes; still exported so the published name keeps working.
68
68
  */
69
- export type AdwDropDownOption = AdwComboOption;
69
+ export type GtkDropDownOption = AdwComboOption;
70
70
 
71
- export class AdwDropDown extends HTMLElement {
71
+ export class GtkDropDown extends HTMLElement {
72
72
  private _buttonEl!: HTMLButtonElement;
73
73
  private _labelEl!: HTMLSpanElement;
74
- private _popoverEl!: AdwPopover;
74
+ private _popoverEl!: GtkPopover;
75
75
  private _listEl!: HTMLDivElement;
76
76
  private _searchEl: HTMLInputElement | null = null;
77
77
  private _itemButtons: HTMLButtonElement[] = [];
@@ -86,7 +86,7 @@ export class AdwDropDown extends HTMLElement {
86
86
  }
87
87
 
88
88
  /** The options list. Setting it rebuilds the popover and clamps the selection. */
89
- get options(): AdwDropDownOption[] {
89
+ get options(): GtkDropDownOption[] {
90
90
  return this._state.options;
91
91
  }
92
92
 
@@ -97,7 +97,7 @@ export class AdwDropDown extends HTMLElement {
97
97
  if (this._initialized) this._renderAll();
98
98
  }
99
99
 
100
- get items(): AdwDropDownOption[] {
100
+ get items(): GtkDropDownOption[] {
101
101
  return this._state.options;
102
102
  }
103
103
 
@@ -124,7 +124,7 @@ export class AdwDropDown extends HTMLElement {
124
124
  if (index >= 0) this._selectIndex(index);
125
125
  }
126
126
 
127
- get selectedItem(): AdwDropDownOption | null {
127
+ get selectedItem(): GtkDropDownOption | null {
128
128
  return this._state.options[this._state.selectedIndex] ?? null;
129
129
  }
130
130
 
@@ -156,7 +156,7 @@ export class AdwDropDown extends HTMLElement {
156
156
  this._labelEl = document.createElement('span');
157
157
  this._labelEl.className = 'adw-drop-down-label';
158
158
 
159
- this._buttonEl.append(this._labelEl, createAdwIcon('go-down', 'adw-drop-down-arrow'));
159
+ this._buttonEl.append(this._labelEl, createGtkImage('go-down', 'adw-drop-down-arrow'));
160
160
  this._buttonEl.addEventListener('click', () => {
161
161
  if (this.hasAttribute('disabled')) return;
162
162
  if (!this._popoverEl.open && this._state.count === 0) return;
@@ -164,7 +164,7 @@ export class AdwDropDown extends HTMLElement {
164
164
  });
165
165
  this._buttonEl.addEventListener('keydown', (event) => this._onButtonKeyDown(event));
166
166
 
167
- this._popoverEl = document.createElement('adw-popover') as AdwPopover;
167
+ this._popoverEl = document.createElement('gtk-popover') as GtkPopover;
168
168
  this._popoverEl.classList.add('adw-drop-down-popover');
169
169
  this._popoverEl.setAttribute('role', 'listbox');
170
170
  // A dropdown's popover is a `popover.menu` too — `dropdown { popover.menu { … } }`
@@ -208,7 +208,7 @@ export class AdwDropDown extends HTMLElement {
208
208
  }
209
209
  }
210
210
 
211
- private _parseOptionsAttr(): AdwDropDownOption[] {
211
+ private _parseOptionsAttr(): GtkDropDownOption[] {
212
212
  const raw = this.getAttribute('options') ?? this.getAttribute('items');
213
213
  if (!raw) return [];
214
214
  try {
@@ -378,4 +378,4 @@ export class AdwDropDown extends HTMLElement {
378
378
  }
379
379
  }
380
380
 
381
- customElements.define('adw-drop-down', AdwDropDown);
381
+ customElements.define('gtk-drop-down', GtkDropDown);
@@ -1,4 +1,4 @@
1
- // <adw-entry> — Adwaita single-line text entry (e.g. a browser URL bar).
1
+ // <gtk-entry> — Adwaita single-line text entry (e.g. a browser URL bar).
2
2
  // Attributes: value, placeholder, type, disabled, maxlength.
3
3
  // Properties: value (get/set, proxies the inner input), maxLength, textLength.
4
4
  // Events: native `input` bubbles from the inner input; `activate` (CustomEvent)
@@ -6,7 +6,7 @@
6
6
  //
7
7
  // The character arithmetic is HEADLESS and lives in `@gjsify/adwaita-core`
8
8
  // (ADR 0004): `entryTextLength` counts CODE POINTS and `clampEntryText` truncates
9
- // on them. `@gjsify/adwaita-nativescript`'s AdwEntry has composed the same two
9
+ // on them. `@gjsify/adwaita-nativescript`'s GtkEntry has composed the same two
10
10
  // since it shipped; this element counted nothing at all, so the same consumer
11
11
  // got a max length on one renderer and none on the other — and the native
12
12
  // `maxlength` attribute would not have closed the gap, because the browser
@@ -21,7 +21,7 @@
21
21
 
22
22
  import { ENTRY_ROW_MAX_LENGTH_LIMIT, clampEntryText, entryTextLength } from '@gjsify/adwaita-core';
23
23
 
24
- export class AdwEntry extends HTMLElement {
24
+ export class GtkEntry extends HTMLElement {
25
25
  private _input!: HTMLInputElement;
26
26
  private _initialized = false;
27
27
  private _maxLength = 0;
@@ -103,4 +103,4 @@ export class AdwEntry extends HTMLElement {
103
103
  }
104
104
  }
105
105
 
106
- customElements.define('adw-entry', AdwEntry);
106
+ customElements.define('gtk-entry', GtkEntry);
@@ -1,4 +1,4 @@
1
- // <adw-icon> — the symbolic icon node as an element. Every icon in this package is a
1
+ // <gtk-image> — the symbolic icon node as an element. Every icon in this package is a
2
2
  // CSS-masked box whose glyph comes from a generated `.adw-icon--<name>` class and
3
3
  // whose colour is `currentColor`, so it themes with whatever contains it. The name
4
4
  // derivation and its guard live once in `@gjsify/adwaita-core`'s
@@ -46,7 +46,7 @@ export const MASK_CLASS_PREFIX = 'adw-icon--';
46
46
  */
47
47
  export const MISSING_ICON_NAME = 'image-missing';
48
48
 
49
- export class AdwIcon extends HTMLElement {
49
+ export class GtkImage extends HTMLElement {
50
50
  static get observedAttributes() {
51
51
  return ['icon-name', 'size'];
52
52
  }
@@ -141,11 +141,11 @@ export class AdwIcon extends HTMLElement {
141
141
  * Build one icon node. `extraClasses` are the caller's own positioning/context
142
142
  * classes, added alongside the managed `.adw-icon` + mask class, not replacing them.
143
143
  */
144
- export function createAdwIcon(iconName: string | null, ...extraClasses: string[]): AdwIcon {
145
- const icon = document.createElement('adw-icon') as AdwIcon;
144
+ export function createGtkImage(iconName: string | null, ...extraClasses: string[]): GtkImage {
145
+ const icon = document.createElement('gtk-image') as GtkImage;
146
146
  if (iconName !== null) icon.setAttribute('icon-name', iconName);
147
147
  if (extraClasses.length > 0) icon.classList.add(...extraClasses);
148
148
  return icon;
149
149
  }
150
150
 
151
- customElements.define('adw-icon', AdwIcon);
151
+ customElements.define('gtk-image', GtkImage);
@@ -1,11 +1,11 @@
1
- // <adw-menu-button> — the web counterpart of Gtk.MenuButton, which libadwaita styles
1
+ // <gtk-menu-button> — the web counterpart of Gtk.MenuButton, which libadwaita styles
2
2
  // but never subclassed: by default the flat `open-menu-symbolic` app-menu button used
3
3
  // at the end of a header bar. Clicking it toggles an Adwaita-styled popover under the
4
4
  // button, dismissed on an outside click or Escape, with arrow-key navigation.
5
5
  //
6
- // The popover is `<adw-popover>` and the dismissal/keyboard machine is
6
+ // The popover is `<gtk-popover>` and the dismissal/keyboard machine is
7
7
  // `@gjsify/adwaita-core`'s (ADR 0004); this element keeps only what is a menu button:
8
- // the icon, the item model, the title. Icons go through `<adw-icon>`, whose
8
+ // the icon, the item model, the title. Icons go through `<gtk-image>`, whose
9
9
  // `normalizeIconName` guard is what keeps a multi-token `icon-name="a b"` from
10
10
  // shipping a stray CSS class — for the button icon and for every menu entry's.
11
11
  //
@@ -30,19 +30,28 @@ import {
30
30
  import type { AdwMenuEntry, SplitButtonDirection } from '@gjsify/adwaita-core';
31
31
 
32
32
  // SIDE-EFFECT import, deliberately separate from the type import below: it guarantees
33
- // `adw-popover` is defined before this module's `customElements.define` can upgrade a
34
- // server-rendered `<adw-menu-button>` and build one. A combined
35
- // `import { AdwPopover }` would NOT do it — the binding is only used in type position,
33
+ // `gtk-popover` is defined before this module's `customElements.define` can upgrade a
34
+ // server-rendered `<gtk-menu-button>` and build one. A combined
35
+ // `import { GtkPopover }` would NOT do it — the binding is only used in type position,
36
36
  // and this package compiles without `verbatimModuleSyntax`, so TypeScript would elide
37
37
  // the statement and take the registration with it.
38
- import './adw-popover.js';
39
- import type { AdwPopover } from './adw-popover.js';
38
+ import './gtk-popover.js';
39
+ import type { GtkPopover } from './gtk-popover.js';
40
40
 
41
- import { createAdwIcon } from './adw-icon.js';
41
+ import { createGtkImage } from './gtk-image.js';
42
42
 
43
43
  /**
44
- * A menu entry — `@gjsify/adwaita-core`'s {@link AdwMenuEntry}, re-exported under the
45
- * name this element has always used.
44
+ * A menu entry — `@gjsify/adwaita-core`'s {@link AdwMenuEntry} under the name both
45
+ * renderers export it as.
46
+ *
47
+ * IT KEEPS THE `Adw` PREFIX WHILE THE ELEMENT ABOVE IT DOES NOT, and the reason is not
48
+ * "the name it has always used" — ADR 0034 clause 1 just moved every name in this file
49
+ * that had one. It is that this is not a WIDGET name: clause 1 is about the tag, and
50
+ * this is the descriptor a consumer writes menu entries with. `@gjsify/adwaita-
51
+ * nativescript` exports `AdwMenuItem` for the same type, and that port deliberately
52
+ * keeps `Adw` throughout, so renaming this half would give one object two spellings —
53
+ * which is the thing the ADR is removing, not applying. (`GtkDropDownOption` next door
54
+ * DID move: its NativeScript twin exports no such name, so there was nothing to split.)
46
55
  *
47
56
  * It used to be a SECOND declaration of the same shape, and the NativeScript menu
48
57
  * button declared a THIRD that was missing `icon` entirely. One type, so a consumer
@@ -65,9 +74,9 @@ const POPOVER_POSITIONS = {
65
74
  right: 'end',
66
75
  } as const;
67
76
 
68
- export class AdwMenuButton extends HTMLElement {
77
+ export class GtkMenuButton extends HTMLElement {
69
78
  private _buttonEl!: HTMLButtonElement;
70
- private _popoverEl!: AdwPopover;
79
+ private _popoverEl!: GtkPopover;
71
80
  private _items: AdwMenuItem[] = [];
72
81
  private _menuTitle = '';
73
82
  private _initialized = false;
@@ -124,7 +133,7 @@ export class AdwMenuButton extends HTMLElement {
124
133
  this._buttonEl.setAttribute('aria-haspopup', 'menu');
125
134
  this._buttonEl.setAttribute('aria-expanded', 'false');
126
135
 
127
- this._popoverEl = document.createElement('adw-popover') as AdwPopover;
136
+ this._popoverEl = document.createElement('gtk-popover') as GtkPopover;
128
137
  this._popoverEl.classList.add('adw-menu-button-popover');
129
138
  this._popoverEl.setAttribute('role', 'menu');
130
139
  // `gtk_menu_button_set_menu_model` builds a GtkPopoverMenu, whose CSS
@@ -190,7 +199,7 @@ export class AdwMenuButton extends HTMLElement {
190
199
 
191
200
  this._buttonEl.replaceChildren();
192
201
  this._buttonEl.appendChild(
193
- createAdwIcon(this.getAttribute('icon-name') ?? 'open-menu', 'adw-menu-button-icon'),
202
+ createGtkImage(this.getAttribute('icon-name') ?? 'open-menu', 'adw-menu-button-icon'),
194
203
  );
195
204
  this._buttonEl.setAttribute('aria-label', this.getAttribute('menu-title') || 'Menu');
196
205
 
@@ -219,8 +228,8 @@ export class AdwMenuButton extends HTMLElement {
219
228
  // An entry that asked for NO icon gets no icon node — the emptiness of the
220
229
  // declared name, not whether it resolved. Testing `resolvedIconName` dropped
221
230
  // the node for a name that was given and merely undrawable, which is the one
222
- // case a reader needs to SEE; `<adw-icon>` draws `image-missing` there.
223
- const entryIcon = createAdwIcon(entry.icon ?? null, 'adw-menu-button-item-icon');
231
+ // case a reader needs to SEE; `<gtk-image>` draws `image-missing` there.
232
+ const entryIcon = createGtkImage(entry.icon ?? null, 'adw-menu-button-item-icon');
224
233
  if (stringIsNotEmpty(entry.icon)) item.appendChild(entryIcon);
225
234
  const labelEl = document.createElement('span');
226
235
  labelEl.className = 'adw-menu-button-item-label';
@@ -245,4 +254,4 @@ export class AdwMenuButton extends HTMLElement {
245
254
  }
246
255
  }
247
256
 
248
- customElements.define('adw-menu-button', AdwMenuButton);
257
+ customElements.define('gtk-menu-button', GtkMenuButton);
@@ -1,6 +1,6 @@
1
- // <adw-popover> — the elevated surface that pops up next to an anchor, the web
1
+ // <gtk-popover> — the elevated surface that pops up next to an anchor, the web
2
2
  // counterpart of GtkPopover as libadwaita styles it. It is the ONE popover in this
3
- // package: `<adw-menu-button>`, `<adw-drop-down>` and `<adw-split-button>` all use it
3
+ // package: `<gtk-menu-button>`, `<gtk-drop-down>` and `<adw-split-button>` all use it
4
4
  // rather than building their own, which is what keeps the 15px radius, the
5
5
  // three-layer shadow, Escape dismissal and the wrap arithmetic in one place.
6
6
  //
@@ -51,22 +51,22 @@
51
51
  import { PopoverState, resolvePopoverKey } from '@gjsify/adwaita-core';
52
52
 
53
53
  /** Which side of the anchor the surface sits on. */
54
- export type AdwPopoverPosition = 'bottom' | 'top' | 'start' | 'end';
54
+ export type GtkPopoverPosition = 'bottom' | 'top' | 'start' | 'end';
55
55
 
56
56
  /** Which edge of the anchor the surface lines up with. */
57
- export type AdwPopoverAlign = 'start' | 'end';
57
+ export type GtkPopoverAlign = 'start' | 'end';
58
58
 
59
59
  /** The ARIA role of the surface — it decides the row role consumers give their items. */
60
- export type AdwPopoverRole = 'menu' | 'listbox';
60
+ export type GtkPopoverRole = 'menu' | 'listbox';
61
61
 
62
- const POSITIONS: readonly AdwPopoverPosition[] = ['bottom', 'top', 'start', 'end'];
63
- const ALIGNS: readonly AdwPopoverAlign[] = ['start', 'end'];
64
- const ROLES: readonly AdwPopoverRole[] = ['menu', 'listbox'];
62
+ const POSITIONS: readonly GtkPopoverPosition[] = ['bottom', 'top', 'start', 'end'];
63
+ const ALIGNS: readonly GtkPopoverAlign[] = ['start', 'end'];
64
+ const ROLES: readonly GtkPopoverRole[] = ['menu', 'listbox'];
65
65
 
66
66
  /** The row selector keyboard navigation walks. */
67
67
  const ITEM_SELECTOR = '.adw-popover-item';
68
68
 
69
- export class AdwPopover extends HTMLElement {
69
+ export class GtkPopover extends HTMLElement {
70
70
  private readonly _state = new PopoverState();
71
71
  private _anchor: HTMLElement | null = null;
72
72
  private _initialized = false;
@@ -116,27 +116,27 @@ export class AdwPopover extends HTMLElement {
116
116
  this._anchor = value;
117
117
  }
118
118
 
119
- get position(): AdwPopoverPosition {
119
+ get position(): GtkPopoverPosition {
120
120
  const value = this.getAttribute('position');
121
- return POSITIONS.includes(value as AdwPopoverPosition) ? (value as AdwPopoverPosition) : 'bottom';
121
+ return POSITIONS.includes(value as GtkPopoverPosition) ? (value as GtkPopoverPosition) : 'bottom';
122
122
  }
123
123
 
124
- set position(value: AdwPopoverPosition) {
124
+ set position(value: GtkPopoverPosition) {
125
125
  this.setAttribute('position', value);
126
126
  }
127
127
 
128
- get align(): AdwPopoverAlign {
128
+ get align(): GtkPopoverAlign {
129
129
  const value = this.getAttribute('align');
130
- return ALIGNS.includes(value as AdwPopoverAlign) ? (value as AdwPopoverAlign) : 'start';
130
+ return ALIGNS.includes(value as GtkPopoverAlign) ? (value as GtkPopoverAlign) : 'start';
131
131
  }
132
132
 
133
- set align(value: AdwPopoverAlign) {
133
+ set align(value: GtkPopoverAlign) {
134
134
  this.setAttribute('align', value);
135
135
  }
136
136
 
137
- get popoverRole(): AdwPopoverRole {
137
+ get popoverRole(): GtkPopoverRole {
138
138
  const value = this.getAttribute('role');
139
- return ROLES.includes(value as AdwPopoverRole) ? (value as AdwPopoverRole) : 'menu';
139
+ return ROLES.includes(value as GtkPopoverRole) ? (value as GtkPopoverRole) : 'menu';
140
140
  }
141
141
 
142
142
  /** The navigable rows, in DOM order. Hidden rows are skipped — a filtered list navigates what it shows. */
@@ -275,4 +275,4 @@ export class AdwPopover extends HTMLElement {
275
275
  }
276
276
  }
277
277
 
278
- customElements.define('adw-popover', AdwPopover);
278
+ customElements.define('gtk-popover', GtkPopover);
@@ -1,4 +1,4 @@
1
- // <adw-progress-bar> — the DETERMINATE progress indicator, and the partner to
1
+ // <gtk-progress-bar> — the DETERMINATE progress indicator, and the partner to
2
2
  // <adw-spinner>, which only ever covers "busy, no idea how long".
3
3
  //
4
4
  // NO CORE STATE MACHINE: the whole behaviour is `CLAMP(fraction, 0, 1)` plus a pulsing
@@ -9,9 +9,9 @@
9
9
  // `gtk_progress_bar_pulse()`'s step semantics (the `pulse-step` default, how the block
10
10
  // reflects at the ends, whether it resets `fraction`) are NOT reproduced: GtkProgressBar
11
11
  // is a GTK widget, `refs/gtk` is an uninitialized submodule here and libadwaita vendors
12
- // no `adw-progress-bar.c`, so none of it is verifiable. What ships instead is the
12
+ // no `gtk-progress-bar.c`, so none of it is verifiable. What ships instead is the
13
13
  // vendored port's web idiom — a CSS keyframe animation that runs while `pulsing` is set
14
- // — so {@link AdwProgressBar.pulse} ENTERS that state and is idempotent afterwards. The
14
+ // — so {@link GtkProgressBar.pulse} ENTERS that state and is idempotent afterwards. The
15
15
  // default `show-text` label `NN%` is likewise this port's, not GTK's format string.
16
16
  //
17
17
  // `osd` is libadwaita's `.osd` STYLE CLASS: a 2px troughless bar for under a header bar.
@@ -29,7 +29,7 @@
29
29
 
30
30
  import { glibClamp } from '@gjsify/adwaita-core';
31
31
 
32
- export class AdwProgressBar extends HTMLElement {
32
+ export class GtkProgressBar extends HTMLElement {
33
33
  private _trough!: HTMLSpanElement;
34
34
  private _progress!: HTMLSpanElement;
35
35
  private _text!: HTMLSpanElement;
@@ -166,4 +166,4 @@ export class AdwProgressBar extends HTMLElement {
166
166
  }
167
167
  }
168
168
 
169
- customElements.define('adw-progress-bar', AdwProgressBar);
169
+ customElements.define('gtk-progress-bar', GtkProgressBar);
@@ -1,4 +1,4 @@
1
- // <adw-switch> — the Adwaita toggle, as an element. A 44×24 track with a hidden
1
+ // <gtk-switch> — the Adwaita toggle, as an element. A 44×24 track with a hidden
2
2
  // checkbox behind it and a knob that slides on `active`.
3
3
  //
4
4
  // The styles are the UNSCOPED `scss/_switch.scss`, so `.adw-switch` exists outside a
@@ -29,7 +29,7 @@
29
29
  // Copyright (c) 2025 csm (adwaita-web). MIT License.
30
30
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
31
31
 
32
- export class AdwSwitch extends HTMLElement {
32
+ export class GtkSwitch extends HTMLElement {
33
33
  private _input!: HTMLInputElement;
34
34
  private _slider!: HTMLSpanElement;
35
35
  private _initialized = false;
@@ -44,7 +44,7 @@ export class AdwSwitch extends HTMLElement {
44
44
  * `adw_switch_row_init` does `gtk_widget_set_can_focus (self->slider, FALSE)`
45
45
  * (adw-switch-row.c:159) and makes the ROW activatable instead, so a switch row is ONE
46
46
  * tab stop announced as its own title — not a bare checkbox followed by a label that
47
- * cannot be reached. A standalone `<adw-switch>` keeps its checkbox focusable.
47
+ * cannot be reached. A standalone `<gtk-switch>` keeps its checkbox focusable.
48
48
  */
49
49
  get unfocusable(): boolean {
50
50
  return this.hasAttribute('unfocusable');
@@ -125,4 +125,4 @@ export class AdwSwitch extends HTMLElement {
125
125
  }
126
126
  }
127
127
 
128
- customElements.define('adw-switch', AdwSwitch);
128
+ customElements.define('gtk-switch', GtkSwitch);
@@ -20,7 +20,7 @@
20
20
  import { viewSwitcherIconName } from '@gjsify/adwaita-core';
21
21
  import type { AdwViewSwitcherPageInit, ViewSwitcherScheduler, ViewSwitcherTimerHandle } from '@gjsify/adwaita-core';
22
22
 
23
- import { type AdwIcon, createAdwIcon } from './adw-icon.js';
23
+ import { type GtkImage, createGtkImage } from './gtk-image.js';
24
24
 
25
25
  /**
26
26
  * The browser's timer behind the core's scheduler seam. One shared instance rather than
@@ -41,16 +41,16 @@ export const domViewSwitcherScheduler: ViewSwitcherScheduler = {
41
41
  *
42
42
  * The core resolves NULL/empty to `image-missing` (which the stylesheet carries
43
43
  * a real glyph for); the `-symbolic` strip and the CSS-token guard are
44
- * `normalizeIconName`'s, applied by `<adw-icon>` — that strip is this package's
44
+ * `normalizeIconName`'s, applied by `<gtk-image>` — that strip is this package's
45
45
  * own mask-class convention and has no counterpart in C, where the name reaches
46
46
  * `GtkImage` untouched.
47
47
  */
48
- export function createSwitcherIcon(iconName: string, extra: string): AdwIcon {
49
- return createAdwIcon(viewSwitcherIconName(iconName), extra);
48
+ export function createSwitcherIcon(iconName: string, extra: string): GtkImage {
49
+ return createGtkImage(viewSwitcherIconName(iconName), extra);
50
50
  }
51
51
 
52
52
  /** Repaint an existing switcher icon from a page's declared name. */
53
- export function applySwitcherIcon(icon: AdwIcon, iconName: string): void {
53
+ export function applySwitcherIcon(icon: GtkImage, iconName: string): void {
54
54
  icon.iconName = viewSwitcherIconName(iconName);
55
55
  }
56
56
 
@@ -0,0 +1,50 @@
1
+ // Every custom-element constructor this package's barrel exports, however it exports it.
2
+ //
3
+ // THE INCIDENT THIS EXISTS TO PREVENT, in the shape it was caught. Two browser drivers
4
+ // derive their element set from the package rather than from a list — `Object.values` of
5
+ // the module namespace, kept to the functions whose prototype is an `HTMLElement`. That
6
+ // read the widget classes because the barrel re-exported every one of them flat. ADR 0034
7
+ // § Amendment 6 removed those re-exports: the same scan would have gone on passing while
8
+ // its subject shrank to the handful of web-only classes that keep a flat name. Measured
9
+ // on chromium: the narrow scan drops 187 of the package's 4633 browser assertions, and
10
+ // the only thing that noticed was `connect-lifecycle.spec.ts`'s `tags.length > 40`
11
+ // floor. A floor catches the collapse; it does not catch a scan that is merely narrower
12
+ // than it reads, and the next removal will be smaller.
13
+ //
14
+ // So the walk goes ONE LEVEL into the exported objects, which is where `Adw` and `Gtk`
15
+ // put their members. `typeof` is what picks them out and it does not care that they are
16
+ // MODULE namespaces rather than plain objects (`export * as Adw from
17
+ // ./namespace/adw.js`) — a module namespace answers `object` and enumerates under
18
+ // `Object.values` like any other. One level and not a recursion: both barrels are flat
19
+ // by construction, and a deep walk would start reporting whatever a future export
20
+ // happens to hang off itself.
21
+ //
22
+ // It is a module rather than a copy in each spec because the second copy is where a
23
+ // helper gets lifted, and this was already the second copy.
24
+
25
+ /** A constructor the `CustomElementRegistry` could hold — the filter both drivers used. */
26
+ function isElementClass(value: unknown): value is CustomElementConstructor {
27
+ return typeof value === 'function' && value.prototype instanceof HTMLElement;
28
+ }
29
+
30
+ /**
31
+ * The element classes reachable from `barrel`, de-duplicated.
32
+ *
33
+ * De-duplicated because a class can arrive twice: `Adw.CheckBox`-style aliasing is not
34
+ * used today, but a widget that is both a namespace member and a flat web-only export
35
+ * would otherwise be driven twice and counted twice in the floors below the callers.
36
+ *
37
+ * @param barrel the module namespace of `index.ts` (`import * as adwaitaWeb`)
38
+ */
39
+ export function exportedElementClasses(barrel: Record<string, unknown>): CustomElementConstructor[] {
40
+ const found = new Set<CustomElementConstructor>();
41
+ for (const exported of Object.values(barrel)) {
42
+ if (isElementClass(exported)) {
43
+ found.add(exported);
44
+ continue;
45
+ }
46
+ if (typeof exported !== 'object' || exported === null) continue;
47
+ for (const member of Object.values(exported)) if (isElementClass(member)) found.add(member);
48
+ }
49
+ return [...found];
50
+ }