@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,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
+ }
@@ -1,4 +1,4 @@
1
- // DOM-level tests for <adw-button>'s style classes.
1
+ // DOM-level tests for <gtk-button>'s style classes.
2
2
  //
3
3
  // The element and its NativeScript twin each kept their own attribute→class table,
4
4
  // and the two disagreed: `circular` was here and not there. The table now lives in
@@ -13,7 +13,7 @@ const WEB_ATTRIBUTES = new Set(['flat', 'suggested', 'destructive', 'circular',
13
13
 
14
14
  /** Mount a button carrying the given boolean attributes; return the inner classes. */
15
15
  function mountWithStyles(names: readonly string[]): string[] {
16
- const el = document.createElement('adw-button');
16
+ const el = document.createElement('gtk-button');
17
17
  el.setAttribute('label', 'Click me');
18
18
  for (const name of names) el.setAttribute(name, '');
19
19
  document.body.appendChild(el);
@@ -22,10 +22,10 @@ function mountWithStyles(names: readonly string[]): string[] {
22
22
  }
23
23
 
24
24
  function unmountAll(): void {
25
- for (const el of Array.from(document.querySelectorAll('adw-button'))) el.remove();
25
+ for (const el of Array.from(document.querySelectorAll('gtk-button'))) el.remove();
26
26
  }
27
27
 
28
- export const AdwButtonTest = async () => {
28
+ export const GtkButtonTest = async () => {
29
29
  // Rows naming a class the LONG way (`suggested-action`) are the NativeScript
30
30
  // variant spelling — this element has no such attribute. They are partitioned
31
31
  // out here rather than skipped inside the loop, and the partition is asserted,
@@ -33,7 +33,7 @@ export const AdwButtonTest = async () => {
33
33
  const reachable = BUTTON_STYLE_CLASS_VECTORS.filter((v) => v.names.every((n) => WEB_ATTRIBUTES.has(n)));
34
34
  const unreachable = BUTTON_STYLE_CLASS_VECTORS.filter((v) => !v.names.every((n) => WEB_ATTRIBUTES.has(n)));
35
35
 
36
- await describe('<adw-button> style classes', async () => {
36
+ await describe('<gtk-button> style classes', async () => {
37
37
  for (const { names, classes, rule } of reachable) {
38
38
  await it(`[${names.join(', ')}] → [${classes.join(', ')}] — ${rule}`, () => {
39
39
  expect(mountWithStyles(names)).toStrictEqual([...classes]);
@@ -47,7 +47,7 @@ export const AdwButtonTest = async () => {
47
47
  });
48
48
 
49
49
  await it('a style attribute added later is picked up', () => {
50
- const el = document.createElement('adw-button');
50
+ const el = document.createElement('gtk-button');
51
51
  el.setAttribute('label', 'Send');
52
52
  document.body.appendChild(el);
53
53
  el.setAttribute('suggested', '');
@@ -1,4 +1,4 @@
1
- // DOM-level behaviour tests for <adw-drop-down>, in a real browser via the
1
+ // DOM-level behaviour tests for <gtk-drop-down>, in a real browser via the
2
2
  // @gjsify/adwaita-web browser test axis.
3
3
  //
4
4
  // The SELECTION half is driven by the SAME table the NativeScript renderer asserts
@@ -14,21 +14,21 @@ import { describe, it, expect } from '@gjsify/unit';
14
14
  import { COMBO_SELECTION_VECTORS } from '@gjsify/adwaita-core/conformance';
15
15
  import type { ComboSelectionStep, ComboSelectionVector } from '@gjsify/adwaita-core/conformance';
16
16
 
17
- import type { AdwDropDown } from './elements/adw-drop-down.js';
17
+ import type { GtkDropDown } from './elements/gtk-drop-down.js';
18
18
 
19
- function makeDropDown(): AdwDropDown {
20
- const el = document.createElement('adw-drop-down') as AdwDropDown;
19
+ function makeDropDown(): GtkDropDown {
20
+ const el = document.createElement('gtk-drop-down') as GtkDropDown;
21
21
  document.body.appendChild(el);
22
22
  return el;
23
23
  }
24
24
 
25
25
  /** The text the closed button shows — the rendered `selectedLabel`. */
26
- function labelText(dd: AdwDropDown): string {
26
+ function labelText(dd: GtkDropDown): string {
27
27
  return dd.querySelector('.adw-drop-down-label')?.textContent ?? '';
28
28
  }
29
29
 
30
30
  /** Open the chooser the way a user does. A no-op over an empty model, as the element guards. */
31
- function openChooser(dd: AdwDropDown): void {
31
+ function openChooser(dd: GtkDropDown): void {
32
32
  (dd.querySelector('.adw-drop-down-button') as HTMLButtonElement).click();
33
33
  }
34
34
 
@@ -36,7 +36,7 @@ function openChooser(dd: AdwDropDown): void {
36
36
  * Replay one vector step against the real element — property sets for the
37
37
  * programmatic ops, a popover gesture for the interactive one.
38
38
  */
39
- function applyStep(dd: AdwDropDown, step: ComboSelectionStep): void {
39
+ function applyStep(dd: GtkDropDown, step: ComboSelectionStep): void {
40
40
  switch (step.op) {
41
41
  case 'setOptions':
42
42
  dd.options = step.options;
@@ -78,15 +78,15 @@ function vectorNamed(name: string): ComboSelectionVector {
78
78
  }
79
79
 
80
80
  /** Mount a drop-down and record every `change` detail it dispatches. */
81
- function mountRecording(): { dd: AdwDropDown; changes: unknown[] } {
81
+ function mountRecording(): { dd: GtkDropDown; changes: unknown[] } {
82
82
  const dd = makeDropDown();
83
83
  const changes: unknown[] = [];
84
84
  dd.addEventListener('change', (event) => changes.push((event as CustomEvent).detail));
85
85
  return { dd, changes };
86
86
  }
87
87
 
88
- export const AdwDropDownTest = async () => {
89
- await describe('adw-drop-down selection (libadwaita conformance vectors)', async () => {
88
+ export const GtkDropDownTest = async () => {
89
+ await describe('gtk-drop-down selection (libadwaita conformance vectors)', async () => {
90
90
  for (const vector of COMBO_SELECTION_VECTORS) {
91
91
  if (vector.name === DROP_DOWN_REJECTS) continue;
92
92
 
@@ -129,7 +129,7 @@ export const AdwDropDownTest = async () => {
129
129
  });
130
130
  });
131
131
 
132
- await describe('adw-drop-down options', async () => {
132
+ await describe('gtk-drop-down options', async () => {
133
133
  await it('accepts a string[] (value === label)', async () => {
134
134
  const dd = makeDropDown();
135
135
  dd.options = ['One', 'Two', 'Three'];
@@ -152,7 +152,7 @@ export const AdwDropDownTest = async () => {
152
152
  });
153
153
 
154
154
  await it('parses options from the JSON attribute', async () => {
155
- const dd = document.createElement('adw-drop-down') as AdwDropDown;
155
+ const dd = document.createElement('gtk-drop-down') as GtkDropDown;
156
156
  dd.setAttribute('options', '[{"value":"x","label":"Ex"},{"value":"y","label":"Why"}]');
157
157
  dd.setAttribute('selected', '1');
158
158
  document.body.appendChild(dd);
@@ -170,7 +170,7 @@ export const AdwDropDownTest = async () => {
170
170
  });
171
171
  });
172
172
 
173
- await describe('adw-drop-down selected ↔ value sync', async () => {
173
+ await describe('gtk-drop-down selected ↔ value sync', async () => {
174
174
  await it('selectedValue setter finds the index by value', async () => {
175
175
  const dd = makeDropDown();
176
176
  dd.options = [
@@ -205,7 +205,7 @@ export const AdwDropDownTest = async () => {
205
205
  await it('setting options + selected before connect does not crash + applies on connect', async () => {
206
206
  // The property setters can run BEFORE connectedCallback builds the DOM, where
207
207
  // _updateLabel would touch an undefined label element.
208
- const dd = document.createElement('adw-drop-down') as AdwDropDown;
208
+ const dd = document.createElement('gtk-drop-down') as GtkDropDown;
209
209
  dd.options = ['a', 'b', 'c'];
210
210
  dd.selected = 2;
211
211
  expect(dd.isConnected).toBe(false);
@@ -217,7 +217,7 @@ export const AdwDropDownTest = async () => {
217
217
  });
218
218
  });
219
219
 
220
- await describe('adw-drop-down notify-on-change', async () => {
220
+ await describe('gtk-drop-down notify-on-change', async () => {
221
221
  await it('a programmatic set fires notify::selected but NOT change (DOM <select> semantics)', async () => {
222
222
  const dd = makeDropDown();
223
223
  dd.options = ['a', 'b', 'c'];
@@ -259,7 +259,7 @@ export const AdwDropDownTest = async () => {
259
259
  });
260
260
  });
261
261
 
262
- await describe('adw-drop-down popover behaviour', async () => {
262
+ await describe('gtk-drop-down popover behaviour', async () => {
263
263
  await it('opens on button click and closes on outside pointerdown', async () => {
264
264
  const dd = makeDropDown();
265
265
  dd.options = ['a', 'b'];
@@ -286,7 +286,7 @@ export const AdwDropDownTest = async () => {
286
286
  });
287
287
  });
288
288
 
289
- await describe('adw-drop-down search', async () => {
289
+ await describe('gtk-drop-down search', async () => {
290
290
  await it('renders a search entry and filters the list', async () => {
291
291
  const dd = makeDropDown();
292
292
  dd.options = ['Apple', 'Banana', 'Cherry'];
@@ -1,4 +1,4 @@
1
- // DOM-level tests for <adw-entry>'s length arithmetic.
1
+ // DOM-level tests for <gtk-entry>'s length arithmetic.
2
2
  //
3
3
  // The element had NO max length and no text length, while its NativeScript twin has
4
4
  // composed `@gjsify/adwaita-core`'s since it shipped — so the same consumer got a
@@ -10,22 +10,22 @@
10
10
  import { describe, expect, it } from '@gjsify/unit';
11
11
  import { ENTRY_MAX_LENGTH_VECTORS, ENTRY_TEXT_LENGTH_VECTORS } from '@gjsify/adwaita-core/conformance';
12
12
 
13
- import type { AdwEntry } from './elements/adw-entry.js';
13
+ import type { GtkEntry } from './elements/gtk-entry.js';
14
14
 
15
15
  /** Mount an entry with the given attributes. */
16
- function mountEntry(attrs: Record<string, string> = {}): AdwEntry {
17
- const entry = document.createElement('adw-entry') as AdwEntry;
16
+ function mountEntry(attrs: Record<string, string> = {}): GtkEntry {
17
+ const entry = document.createElement('gtk-entry') as GtkEntry;
18
18
  for (const [name, value] of Object.entries(attrs)) entry.setAttribute(name, value);
19
19
  document.body.appendChild(entry);
20
20
  return entry;
21
21
  }
22
22
 
23
23
  function unmountAll(): void {
24
- for (const entry of Array.from(document.querySelectorAll('adw-entry'))) entry.remove();
24
+ for (const entry of Array.from(document.querySelectorAll('gtk-entry'))) entry.remove();
25
25
  }
26
26
 
27
- export const AdwEntryTest = async () => {
28
- await describe('<adw-entry> text length', async () => {
27
+ export const GtkEntryTest = async () => {
28
+ await describe('<gtk-entry> text length', async () => {
29
29
  for (const { text, length, rule } of ENTRY_TEXT_LENGTH_VECTORS) {
30
30
  await it(`${JSON.stringify(text)} → ${length} — ${rule}`, () => {
31
31
  const entry = mountEntry();
@@ -36,7 +36,7 @@ export const AdwEntryTest = async () => {
36
36
  }
37
37
  });
38
38
 
39
- await describe('<adw-entry> max length', async () => {
39
+ await describe('<gtk-entry> max length', async () => {
40
40
  for (const { text, maxLength, clamped, length, rule } of ENTRY_MAX_LENGTH_VECTORS) {
41
41
  await it(`${JSON.stringify(text)} @ ${maxLength} — ${rule}`, () => {
42
42
  const entry = mountEntry({ maxlength: String(maxLength) });