@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,17 +1,17 @@
1
- // DOM-level tests for <adw-icon>, driven by the SAME `normalizeIconName` vectors the
1
+ // DOM-level tests for <gtk-image>, driven by the SAME `normalizeIconName` vectors the
2
2
  // core suite asserts against (`@gjsify/adwaita-core/conformance`).
3
3
  //
4
4
  // The icon-name class must never be built by hand: a name is only usable once it is
5
5
  // known to be a SINGLE CSS token, and hand-built spans skipped that check, so
6
6
  // `icon-name="a b"` interpolated a stray second class and shipped it through
7
- // `<adw-menu-button>` for its own icon and for every JSON menu entry's. The vectors run
7
+ // `<gtk-menu-button>` for its own icon and for every JSON menu entry's. The vectors run
8
8
  // against the ELEMENT, so hand-building the class again fails naming the input.
9
9
  import { describe, expect, it } from '@gjsify/unit';
10
10
 
11
11
  import { VIEW_STACK_ICON_NAME_VECTORS } from '@gjsify/adwaita-core/conformance';
12
12
 
13
- import type { AdwIcon } from './elements/adw-icon.js';
14
- import type { AdwMenuButton } from './elements/adw-menu-button.js';
13
+ import type { GtkImage } from './elements/gtk-image.js';
14
+ import type { GtkMenuButton } from './elements/gtk-menu-button.js';
15
15
 
16
16
  function mount<T extends HTMLElement>(tag: string): { el: T; host: HTMLElement } {
17
17
  const host = document.createElement('div');
@@ -26,11 +26,11 @@ function extraClasses(el: HTMLElement): string[] {
26
26
  return [...el.classList].filter((c) => c !== 'adw-icon').sort();
27
27
  }
28
28
 
29
- export const AdwIconTest = async () => {
30
- await describe('<adw-icon> mask class (normalizeIconName vectors)', async () => {
29
+ export const GtkImageTest = async () => {
30
+ await describe('<gtk-image> mask class (normalizeIconName vectors)', async () => {
31
31
  for (const { icon, normalized, rule } of VIEW_STACK_ICON_NAME_VECTORS) {
32
32
  await it(`${JSON.stringify(icon)} → ${JSON.stringify(normalized)} — ${rule}`, () => {
33
- const { el, host } = mount<AdwIcon>('adw-icon');
33
+ const { el, host } = mount<GtkImage>('gtk-image');
34
34
  el.iconName = icon ?? null;
35
35
 
36
36
  expect(el.resolvedIconName).toBe(normalized);
@@ -51,15 +51,15 @@ export const AdwIconTest = async () => {
51
51
  }
52
52
  });
53
53
 
54
- await describe('<adw-icon> node contract', async () => {
54
+ await describe('<gtk-image> node contract', async () => {
55
55
  await it('is decorative — the accessible name belongs to the host control', () => {
56
- const { el, host } = mount<AdwIcon>('adw-icon');
56
+ const { el, host } = mount<GtkImage>('gtk-image');
57
57
  expect(el.getAttribute('aria-hidden')).toBe('true');
58
58
  host.remove();
59
59
  });
60
60
 
61
61
  await it('swaps ONLY the mask class, keeping the caller position classes', () => {
62
- const { el, host } = mount<AdwIcon>('adw-icon');
62
+ const { el, host } = mount<GtkImage>('gtk-image');
63
63
  el.classList.add('adw-drop-down-arrow', 'start');
64
64
  el.iconName = 'go-down';
65
65
  expect(extraClasses(el)).toStrictEqual(['adw-drop-down-arrow', 'adw-icon--go-down', 'start']);
@@ -75,7 +75,7 @@ export const AdwIconTest = async () => {
75
75
  });
76
76
 
77
77
  await it('sizes the box AND the mask together', () => {
78
- const { el, host } = mount<AdwIcon>('adw-icon');
78
+ const { el, host } = mount<GtkImage>('gtk-image');
79
79
  el.iconName = 'go-next';
80
80
  // Unset: the stylesheet's 16px.
81
81
  expect(el.size).toBe(null);
@@ -97,13 +97,13 @@ export const AdwIconTest = async () => {
97
97
  });
98
98
 
99
99
  await it('paints in the INHERITED colour, not the boundary reset colour', () => {
100
- // `.adw-icon` masks with `currentColor` and <adw-icon> is a custom element, so
100
+ // `.adw-icon` masks with `currentColor` and <gtk-image> is a custom element, so
101
101
  // the ADR-0010 `$adw-components` reset re-roots `color` on it: without
102
102
  // `color: inherit` in `_icon.scss` every icon repaints in `--window-fg-color`
103
103
  // regardless of the button it sits in.
104
104
  const { el: box, host } = mount<HTMLElement>('div');
105
105
  box.style.color = 'rgb(255, 0, 0)';
106
- const icon = document.createElement('adw-icon') as AdwIcon;
106
+ const icon = document.createElement('gtk-image') as GtkImage;
107
107
  icon.iconName = 'go-next';
108
108
  box.appendChild(icon);
109
109
  expect(getComputedStyle(icon).backgroundColor).toBe('rgb(255, 0, 0)');
@@ -112,8 +112,8 @@ export const AdwIconTest = async () => {
112
112
  });
113
113
 
114
114
  await describe('the hand-rolled copies are gone', async () => {
115
- await it('<adw-menu-button> no longer injects a stray class from its icon-name', () => {
116
- const { el, host } = mount<AdwMenuButton>('adw-menu-button');
115
+ await it('<gtk-menu-button> no longer injects a stray class from its icon-name', () => {
116
+ const { el, host } = mount<GtkMenuButton>('gtk-menu-button');
117
117
  el.setAttribute('icon-name', 'a b');
118
118
  const icon = el.querySelector('.adw-icon') as HTMLElement;
119
119
  // `adw-icon--a b` would have added a second, unrelated `b` class. What it gets
@@ -122,8 +122,8 @@ export const AdwIconTest = async () => {
122
122
  host.remove();
123
123
  });
124
124
 
125
- await it('<adw-menu-button> menu entries guard their icons too', () => {
126
- const { el, host } = mount<AdwMenuButton>('adw-menu-button');
125
+ await it('<gtk-menu-button> menu entries guard their icons too', () => {
126
+ const { el, host } = mount<GtkMenuButton>('gtk-menu-button');
127
127
  el.menuItems = [
128
128
  { label: 'Bad', icon: 'a b' },
129
129
  { label: 'Good', icon: 'view-refresh-symbolic' },
@@ -142,17 +142,17 @@ export const AdwIconTest = async () => {
142
142
  host.remove();
143
143
  });
144
144
 
145
- await it('every icon in the package is an <adw-icon>', () => {
145
+ await it('every icon in the package is a <gtk-image>', () => {
146
146
  // Asserted structurally: a page of every icon-drawing widget, and no bare span
147
147
  // carrying the base class — so a new hand-rolled `<span class="adw-icon …">`
148
148
  // fails here even when it guards its own name correctly.
149
149
  const { el: page, host } = mount<HTMLElement>('div');
150
150
  page.innerHTML = `
151
- <adw-button icon="go-next" label="Next"></adw-button>
151
+ <gtk-button icon="go-next" label="Next"></gtk-button>
152
152
  <adw-button-row title="Row" start-icon-name="list-add" end-icon-name="go-next"></adw-button-row>
153
153
  <adw-status-page icon="folder" title="Empty"></adw-status-page>
154
154
  <adw-split-button label="Save" menu='[{"label":"Save As"}]'></adw-split-button>
155
- <adw-drop-down options='["a","b"]'></adw-drop-down>
155
+ <gtk-drop-down options='["a","b"]'></gtk-drop-down>
156
156
  <adw-expander-row title="More" show-enable-switch></adw-expander-row>
157
157
  <adw-avatar text="Ada" icon="avatar-default"></adw-avatar>
158
158
  <adw-toggle-group><adw-toggle icon-name="view-list"></adw-toggle></adw-toggle-group>
@@ -160,7 +160,7 @@ export const AdwIconTest = async () => {
160
160
  const bareSpans = [...host.querySelectorAll('span.adw-icon')];
161
161
  expect(bareSpans.length).toBe(0);
162
162
  // …and the icons really are there, so the check is not vacuous.
163
- expect(host.querySelectorAll('adw-icon.adw-icon').length > 5).toBe(true);
163
+ expect(host.querySelectorAll('gtk-image.adw-icon').length > 5).toBe(true);
164
164
  host.remove();
165
165
  });
166
166
  });
@@ -1,4 +1,4 @@
1
- // DOM-level tests for <adw-menu-button>'s `menu` attribute.
1
+ // DOM-level tests for <gtk-menu-button>'s `menu` attribute.
2
2
  //
3
3
  // The element parsed the JSON itself, and the copy was weaker than the core parser
4
4
  // the split button next to it already used: it kept `id` and `icon` whatever their
@@ -11,7 +11,7 @@ import { SPLIT_BUTTON_MENU_PARSE_VECTORS } from '@gjsify/adwaita-core/conformanc
11
11
 
12
12
  /** Mount a menu button carrying `menu` as JSON, and return its rendered item labels. */
13
13
  function mountWithMenu(json: string): { el: HTMLElement; labels: string[] } {
14
- const el = document.createElement('adw-menu-button');
14
+ const el = document.createElement('gtk-menu-button');
15
15
  el.setAttribute('menu', json);
16
16
  document.body.appendChild(el);
17
17
  const labels = Array.from(el.querySelectorAll('.adw-popover button')).map((b) => b.textContent?.trim() ?? '');
@@ -19,11 +19,11 @@ function mountWithMenu(json: string): { el: HTMLElement; labels: string[] } {
19
19
  }
20
20
 
21
21
  function unmountAll(): void {
22
- for (const el of Array.from(document.querySelectorAll('adw-menu-button'))) el.remove();
22
+ for (const el of Array.from(document.querySelectorAll('gtk-menu-button'))) el.remove();
23
23
  }
24
24
 
25
- export const AdwMenuButtonTest = async () => {
26
- await describe('<adw-menu-button> menu attribute', async () => {
25
+ export const GtkMenuButtonTest = async () => {
26
+ await describe('<gtk-menu-button> menu attribute', async () => {
27
27
  for (const { json, entries, rule } of SPLIT_BUTTON_MENU_PARSE_VECTORS) {
28
28
  await it(`${rule}`, () => {
29
29
  const { labels } = mountWithMenu(json ?? '');
@@ -33,7 +33,7 @@ export const AdwMenuButtonTest = async () => {
33
33
  }
34
34
 
35
35
  await it('drops a non-string id instead of leaking a number into the event', () => {
36
- const el = document.createElement('adw-menu-button');
36
+ const el = document.createElement('gtk-menu-button');
37
37
  el.setAttribute('menu', '[{"label":"Open","id":7}]');
38
38
  document.body.appendChild(el);
39
39
 
@@ -1,4 +1,4 @@
1
- // DOM-level tests for <adw-progress-bar>.
1
+ // DOM-level tests for <gtk-progress-bar>.
2
2
  //
3
3
  // Three things matter more than the attribute round-trips: the CLAMP is GLib's
4
4
  // (`glibClamp` from `@gjsify/adwaita-core`, not a local `Math.min/max`); a ZERO fraction
@@ -9,18 +9,18 @@
9
9
 
10
10
  import { describe, expect, it } from '@gjsify/unit';
11
11
 
12
- import type { AdwProgressBar } from './elements/adw-progress-bar.js';
12
+ import type { GtkProgressBar } from './elements/gtk-progress-bar.js';
13
13
 
14
- function mount(): { el: AdwProgressBar; host: HTMLElement } {
14
+ function mount(): { el: GtkProgressBar; host: HTMLElement } {
15
15
  const host = document.createElement('div');
16
16
  document.body.appendChild(host);
17
- const el = document.createElement('adw-progress-bar') as AdwProgressBar;
17
+ const el = document.createElement('gtk-progress-bar') as GtkProgressBar;
18
18
  host.appendChild(el);
19
19
  return { el, host };
20
20
  }
21
21
 
22
22
  /** The parts, by the markup contract the stylesheet selects on. */
23
- function parts(bar: AdwProgressBar): { trough: HTMLElement; progress: HTMLElement; text: HTMLElement } {
23
+ function parts(bar: GtkProgressBar): { trough: HTMLElement; progress: HTMLElement; text: HTMLElement } {
24
24
  return {
25
25
  trough: bar.querySelector('.adw-progress-bar-trough') as HTMLElement,
26
26
  progress: bar.querySelector('.adw-progress-bar-progress') as HTMLElement,
@@ -28,8 +28,8 @@ function parts(bar: AdwProgressBar): { trough: HTMLElement; progress: HTMLElemen
28
28
  };
29
29
  }
30
30
 
31
- export const AdwProgressBarTest = async () => {
32
- await describe('<adw-progress-bar> fraction', async () => {
31
+ export const GtkProgressBarTest = async () => {
32
+ await describe('<gtk-progress-bar> fraction', async () => {
33
33
  await it('starts empty, with the trough flagged so the indicator disappears', () => {
34
34
  const { el, host } = mount();
35
35
  const { trough, progress } = parts(el);
@@ -68,7 +68,7 @@ export const AdwProgressBarTest = async () => {
68
68
  });
69
69
  });
70
70
 
71
- await describe('<adw-progress-bar> indeterminate', async () => {
71
+ await describe('<gtk-progress-bar> indeterminate', async () => {
72
72
  await it('pulse() enters the pulsing state and drops aria-valuenow', () => {
73
73
  const { el, host } = mount();
74
74
  el.fraction = 0.4;
@@ -98,7 +98,7 @@ export const AdwProgressBarTest = async () => {
98
98
  });
99
99
  });
100
100
 
101
- await describe('<adw-progress-bar> text', async () => {
101
+ await describe('<gtk-progress-bar> text', async () => {
102
102
  await it('hides the text node until show-text, then shows the percentage', () => {
103
103
  const { el, host } = mount();
104
104
  expect(parts(el).text.hidden).toBe(true);
@@ -134,7 +134,7 @@ export const AdwProgressBarTest = async () => {
134
134
  });
135
135
  });
136
136
 
137
- await describe('<adw-progress-bar> variants', async () => {
137
+ await describe('<gtk-progress-bar> variants', async () => {
138
138
  await it('is an 8px trough by default and a 2px hairline with osd', () => {
139
139
  // The 8px is libadwaita's (_progress-bar.scss) and the 2px is its
140
140
  // `.osd` variant — NOT the vendored web port's 6px, which
@@ -148,8 +148,8 @@ export const AdwProgressBarTest = async () => {
148
148
  // transition to be part-way through.
149
149
  const host = document.createElement('div');
150
150
  document.body.appendChild(host);
151
- const plain = document.createElement('adw-progress-bar') as AdwProgressBar;
152
- const osd = document.createElement('adw-progress-bar') as AdwProgressBar;
151
+ const plain = document.createElement('gtk-progress-bar') as GtkProgressBar;
152
+ const osd = document.createElement('gtk-progress-bar') as GtkProgressBar;
153
153
  osd.setAttribute('osd', '');
154
154
  host.append(plain, osd);
155
155
 
@@ -1,4 +1,4 @@
1
- // DOM-level tests for <adw-switch>, plus the proof that both <adw-switch-row> and
1
+ // DOM-level tests for <gtk-switch>, plus the proof that both <adw-switch-row> and
2
2
  // <adw-expander-row> still work now that the switch is lifted out of them. Two
3
3
  // invariants:
4
4
  //
@@ -12,7 +12,7 @@
12
12
  import { describe, expect, it } from '@gjsify/unit';
13
13
 
14
14
  import type { AdwExpanderRow } from './elements/adw-expander-row.js';
15
- import type { AdwSwitch } from './elements/adw-switch.js';
15
+ import type { GtkSwitch } from './elements/gtk-switch.js';
16
16
  import type { AdwSwitchRow } from './elements/adw-switch-row.js';
17
17
 
18
18
  function mount<T extends HTMLElement>(tag: string): { el: T; host: HTMLElement } {
@@ -31,7 +31,7 @@ function record(el: HTMLElement, event: string): unknown[] {
31
31
  }
32
32
 
33
33
  /** The switch's own parts, by the markup contract the stylesheet selects on. */
34
- function parts(sw: AdwSwitch): { input: HTMLInputElement; slider: HTMLElement } {
34
+ function parts(sw: GtkSwitch): { input: HTMLInputElement; slider: HTMLElement } {
35
35
  return {
36
36
  input: sw.querySelector('input[type="checkbox"]') as HTMLInputElement,
37
37
  slider: sw.querySelector('.adw-switch-slider') as HTMLElement,
@@ -45,10 +45,10 @@ function measure(sw: HTMLElement): { width: string; height: string; radius: stri
45
45
  return { width: box.width, height: box.height, radius: slider.borderTopLeftRadius };
46
46
  }
47
47
 
48
- export const AdwSwitchTest = async () => {
49
- await describe('<adw-switch> state', async () => {
48
+ export const GtkSwitchTest = async () => {
49
+ await describe('<gtk-switch> state', async () => {
50
50
  await it('starts off and builds the input + slider markup', () => {
51
- const { el, host } = mount<AdwSwitch>('adw-switch');
51
+ const { el, host } = mount<GtkSwitch>('gtk-switch');
52
52
  const { input, slider } = parts(el);
53
53
  expect(el.active).toBe(false);
54
54
  expect(input).toBeTruthy();
@@ -63,7 +63,7 @@ export const AdwSwitchTest = async () => {
63
63
  await it('adopts a declarative active attribute without emitting', () => {
64
64
  const host = document.createElement('div');
65
65
  document.body.appendChild(host);
66
- const el = document.createElement('adw-switch') as AdwSwitch;
66
+ const el = document.createElement('gtk-switch') as GtkSwitch;
67
67
  el.setAttribute('active', '');
68
68
  const events = record(el, 'notify::active');
69
69
  host.appendChild(el);
@@ -74,7 +74,7 @@ export const AdwSwitchTest = async () => {
74
74
  });
75
75
 
76
76
  await it('a programmatic set notifies, and re-setting the same value does not', () => {
77
- const { el, host } = mount<AdwSwitch>('adw-switch');
77
+ const { el, host } = mount<GtkSwitch>('gtk-switch');
78
78
  const events = record(el, 'notify::active');
79
79
  el.active = true;
80
80
  expect(events).toStrictEqual([{ active: true }]);
@@ -87,7 +87,7 @@ export const AdwSwitchTest = async () => {
87
87
  });
88
88
 
89
89
  await it('a click on the track toggles exactly once', () => {
90
- const { el, host } = mount<AdwSwitch>('adw-switch');
90
+ const { el, host } = mount<GtkSwitch>('gtk-switch');
91
91
  const events = record(el, 'notify::active');
92
92
  parts(el).slider.click();
93
93
  expect(el.active).toBe(true);
@@ -100,7 +100,7 @@ export const AdwSwitchTest = async () => {
100
100
  // The checkbox is 0×0, so a pointer never reaches it — but keyboard
101
101
  // activation and `input.click()` do, and the track listener must not
102
102
  // toggle a second time on the way out.
103
- const { el, host } = mount<AdwSwitch>('adw-switch');
103
+ const { el, host } = mount<GtkSwitch>('gtk-switch');
104
104
  const events = record(el, 'notify::active');
105
105
  parts(el).input.click();
106
106
  expect(el.active).toBe(true);
@@ -109,7 +109,7 @@ export const AdwSwitchTest = async () => {
109
109
  });
110
110
 
111
111
  await it('a disabled switch does not toggle', () => {
112
- const { el, host } = mount<AdwSwitch>('adw-switch');
112
+ const { el, host } = mount<GtkSwitch>('gtk-switch');
113
113
  el.disabled = true;
114
114
  const events = record(el, 'notify::active');
115
115
  parts(el).slider.click();
@@ -125,11 +125,11 @@ export const AdwSwitchTest = async () => {
125
125
  });
126
126
  });
127
127
 
128
- await describe('<adw-switch-row> still toggles and emits through <adw-switch>', async () => {
128
+ await describe('<adw-switch-row> still toggles and emits through <gtk-switch>', async () => {
129
129
  await it('a programmatic row.active drives the switch and emits once', () => {
130
130
  const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
131
131
  const events = record(row, 'notify::active');
132
- const sw = row.querySelector('adw-switch') as AdwSwitch;
132
+ const sw = row.querySelector('gtk-switch') as GtkSwitch;
133
133
  expect(sw).toBeTruthy();
134
134
 
135
135
  row.active = true;
@@ -148,7 +148,7 @@ export const AdwSwitchTest = async () => {
148
148
  const events = record(row, 'notify::active');
149
149
  row.click();
150
150
  expect(row.active).toBe(true);
151
- expect((row.querySelector('adw-switch') as AdwSwitch).active).toBe(true);
151
+ expect((row.querySelector('gtk-switch') as GtkSwitch).active).toBe(true);
152
152
  expect(events.length).toBe(1);
153
153
  host.remove();
154
154
  });
@@ -156,7 +156,7 @@ export const AdwSwitchTest = async () => {
156
156
  await it('a click on the switch toggles the row once, not twice', () => {
157
157
  const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
158
158
  const events = record(row, 'notify::active');
159
- const sw = row.querySelector('adw-switch') as AdwSwitch;
159
+ const sw = row.querySelector('gtk-switch') as GtkSwitch;
160
160
  parts(sw).slider.click();
161
161
  expect(row.active).toBe(true);
162
162
  expect(events.length).toBe(1);
@@ -169,7 +169,7 @@ export const AdwSwitchTest = async () => {
169
169
  const { el: row, host } = mount<AdwExpanderRow>('adw-expander-row');
170
170
  row.setAttribute('show-enable-switch', '');
171
171
  const events = record(row, 'notify::enable-expansion');
172
- const sw = row.querySelector('adw-switch') as AdwSwitch;
172
+ const sw = row.querySelector('gtk-switch') as GtkSwitch;
173
173
  expect(sw.active).toBe(true); // enable-expansion defaults to true
174
174
 
175
175
  parts(sw).slider.click();
@@ -191,7 +191,7 @@ export const AdwSwitchTest = async () => {
191
191
 
192
192
  row.enableExpansion = false;
193
193
 
194
- expect((row.querySelector('adw-switch') as AdwSwitch).active).toBe(false);
194
+ expect((row.querySelector('gtk-switch') as GtkSwitch).active).toBe(false);
195
195
  expect(enableEvents.length).toBe(0);
196
196
  // The switch's own notify never escapes the row either.
197
197
  expect(activeEvents.length).toBe(0);
@@ -201,7 +201,7 @@ export const AdwSwitchTest = async () => {
201
201
  await it('a click on the enable switch does not disclose the row', () => {
202
202
  const { el: row, host } = mount<AdwExpanderRow>('adw-expander-row');
203
203
  row.setAttribute('show-enable-switch', '');
204
- const sw = row.querySelector('adw-switch') as AdwSwitch;
204
+ const sw = row.querySelector('gtk-switch') as GtkSwitch;
205
205
 
206
206
  parts(sw).slider.click();
207
207
  expect(row.expanded).toBe(false);
@@ -218,8 +218,8 @@ export const AdwSwitchTest = async () => {
218
218
  const { el: expander, host: expanderHost } = mount<AdwExpanderRow>('adw-expander-row');
219
219
  expander.setAttribute('show-enable-switch', '');
220
220
 
221
- const rowBox = measure(row.querySelector('adw-switch') as HTMLElement);
222
- const expanderBox = measure(expander.querySelector('adw-switch') as HTMLElement);
221
+ const rowBox = measure(row.querySelector('gtk-switch') as HTMLElement);
222
+ const expanderBox = measure(expander.querySelector('gtk-switch') as HTMLElement);
223
223
 
224
224
  expect(rowBox).toStrictEqual(expanderBox);
225
225
  // Pin the actual numbers too, so "both unstyled" cannot pass as
@@ -1,4 +1,4 @@
1
- // What an icon actually DRAWS — the assertion `adw-icon.spec.ts` did not make.
1
+ // What an icon actually DRAWS — the assertion `gtk-image.spec.ts` did not make.
2
2
  //
3
3
  // THE INCIDENT. `_icon.scss` set `background-color: currentColor` plus mask sizing and no
4
4
  // `mask-image`, so a name outside the compiled `.adw-icon--<name>` set painted a solid 16px
@@ -15,7 +15,7 @@
15
15
  import { describe, expect, it } from '@gjsify/unit';
16
16
 
17
17
  import { isIconAvailable, registerIcon } from './icon-registry.js';
18
- import type { AdwIcon } from './elements/adw-icon.js';
18
+ import type { GtkImage } from './elements/gtk-image.js';
19
19
 
20
20
  /** A name no compiled entry can collide with, for the "not shipped" arm. */
21
21
  const ABSENT = 'gjsify-registry-probe';
@@ -25,10 +25,10 @@ const PROBE_SVG = `<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="ht
25
25
  <path d="m 4 4 h 8 v 8 h -8 z m 0 0" fill="currentColor"/>
26
26
  </svg>`;
27
27
 
28
- function mount(iconName: string | null): { el: AdwIcon; host: HTMLElement } {
28
+ function mount(iconName: string | null): { el: GtkImage; host: HTMLElement } {
29
29
  const host = document.createElement('div');
30
30
  document.body.appendChild(host);
31
- const el = document.createElement('adw-icon') as AdwIcon;
31
+ const el = document.createElement('gtk-image') as GtkImage;
32
32
  if (iconName !== null) el.iconName = iconName;
33
33
  host.appendChild(el);
34
34
  return { el, host };
@@ -56,7 +56,7 @@ export function fallbackMask(): string {
56
56
  }
57
57
 
58
58
  export const AdwIconRegistryTest = async () => {
59
- await describe('<adw-icon> resolves a name to a real mask', async () => {
59
+ await describe('<gtk-image> resolves a name to a real mask', async () => {
60
60
  await it('a compiled name draws its OWN glyph, not the fallback', () => {
61
61
  const { el, host } = mount('go-next');
62
62
  const mask = maskOf(el);
@@ -111,7 +111,7 @@ export const AdwIconRegistryTest = async () => {
111
111
 
112
112
  await describe('a name carried by STATE still resolves', async () => {
113
113
  await it("the password row's peek toggle draws both of its glyphs", () => {
114
- // These two reach `<adw-icon>.iconName` as `state.peekIconName`, a property of
114
+ // These two reach `<gtk-image>.iconName` as `state.peekIconName`, a property of
115
115
  // the core's `PasswordEntryRowState`, so no literal spells them at the point of
116
116
  // use. `check-adwaita-icon-masks.mjs` reads their DECLARATIONS
117
117
  // (`PASSWORD_REVEAL_ICON_NAME`), which proves the map entry exists — never that
@@ -10,16 +10,16 @@
10
10
  // That is this module. `registerIcon` writes the SAME pair the generator writes — the
11
11
  // custom property on the document element, the mask class into a stylesheet this module
12
12
  // owns — so a registered icon is indistinguishable from a compiled one at every later
13
- // point: `<adw-icon icon-name="…">`, a hand-written `class="adw-icon adw-icon--…"`, a
13
+ // point: `<gtk-image icon-name="…">`, a hand-written `class="adw-icon adw-icon--…"`, a
14
14
  // widget attribute, `var(--icon-…)` in the consumer's own CSS.
15
15
  //
16
16
  // import { registerIcon } from '@gjsify/adwaita-web';
17
17
  // import { dialogErrorSymbolic } from '@gjsify/adwaita-icons/status';
18
18
  //
19
19
  // registerIcon('dialog-error-symbolic', dialogErrorSymbolic);
20
- // // …then anywhere: <adw-icon icon-name="dialog-error-symbolic"></adw-icon>
20
+ // // …then anywhere: <gtk-image icon-name="dialog-error-symbolic"></gtk-image>
21
21
  //
22
- // Register BEFORE the icon is mounted where you can. An `<adw-icon>` already in the
22
+ // Register BEFORE the icon is mounted where you can. A `<gtk-image>` already in the
23
23
  // document draws the `image-missing` fallback (see `_icon.scss`) until the registration
24
24
  // lands; the CSS is live, so it corrects itself on the next style recalculation with no
25
25
  // re-render, but there is a visible frame in between.
@@ -30,7 +30,7 @@
30
30
  import { normalizeIconName } from '@gjsify/adwaita-core';
31
31
  import { toDataUri } from '@gjsify/adwaita-icons/utils';
32
32
 
33
- import { MASK_CLASS_PREFIX } from './elements/adw-icon.js';
33
+ import { MASK_CLASS_PREFIX } from './elements/gtk-image.js';
34
34
 
35
35
  /** Marks the one `<style>` element this module owns, so a reload reuses it. */
36
36
  const REGISTRY_STYLE_ID = 'adwaita-web-icon-registry';
@@ -96,8 +96,8 @@ function svgRootOf(source: string): Element {
96
96
  * BOTH arguments are checked and a wrong one THROWS rather than registering nothing: unlike
97
97
  * a render, this is an explicit call with a wrong argument, and silently doing nothing is
98
98
  * the failure mode this whole area exists to end. The name is normalized exactly as
99
- * `<adw-icon icon-name>` normalizes it — a single `-symbolic` suffix comes off, and the rest
100
- * must be one CSS token; the SVG has to parse to an `<svg>` root. `<adw-icon>` draws
99
+ * `<gtk-image icon-name>` normalizes it — a single `-symbolic` suffix comes off, and the rest
100
+ * must be one CSS token; the SVG has to parse to an `<svg>` root. `<gtk-image>` draws
101
101
  * `image-missing` for the same unusable name instead — there it came from markup, and
102
102
  * taking the page down over a typo is not proportionate.
103
103
  *
package/src/index.ts CHANGED
@@ -63,8 +63,42 @@ export type { AdwUndershootEdges } from './scroll-shading.js';
63
63
  // `icon-registry.ts` for the full recipe.
64
64
  export { isIconAvailable, registerIcon } from './icon-registry.js';
65
65
 
66
- export { AdwAvatar } from './elements/adw-avatar.js';
67
- export { AdwBanner } from './elements/adw-banner.js';
66
+ // THE WIDGET CLASSES ARE REACHABLE ONLY AS `Adw.<Name>` / `Gtk.<Name>` (ADR 0034
67
+ // clause 2 + § Amendment 6). The namespace used to be the LAST line in the file, under a
68
+ // run of `export { AdwActionRow } …` re-exports it duplicated one for one; those are
69
+ // gone, and with them the second spelling. `<adw-action-row>` and `<gtk-entry>` are
70
+ // unchanged — this was never about the tags.
71
+ //
72
+ // IT IS ALSO WHAT PULLS THE ELEMENT MODULES IN, so importing this barrel still
73
+ // registers everything. The old order comment ("exported before the widgets that build
74
+ // them") described a sequence that is not load-bearing and never was: every host
75
+ // imports its prerequisite itself (`import './gtk-switch.js'` in the switch rows,
76
+ // `createGtkImage` from `./gtk-image.js` in every widget that draws an icon), so the
77
+ // module graph fixes the order whatever a barrel does. The order that IS load-bearing
78
+ // is the one inside a single module, and `scripts/check-adwaita-upgrade-order.mjs`
79
+ // holds that.
80
+ //
81
+ // `export * as`, NOT an object literal, and that is a bundler constraint rather than a
82
+ // preference: a module namespace carries the TYPE meaning of every name in it, so
83
+ // `as Adw.HeaderBar` works with no second list of instance types — and the merge that
84
+ // would have produced those types (`export const Adw` beside `export namespace Adw`) is
85
+ // a PARSE_ERROR in rolldown's oxc parser even though `tsc` accepts it. The reasoning is
86
+ // in `namespace/adw.ts`.
87
+ export * as Adw from './namespace/adw.js';
88
+ export * as Gtk from './namespace/gtk.js';
89
+
90
+ // WHAT DID NOT MOVE INTO THE NAMESPACE, and the rule that decides it. A member exists
91
+ // for an element whose GIR tag names a real widget; `WEB_ELEMENT_ALIGNMENT` declares the
92
+ // rest `webOnly`, meaning no widget in the reference vocabulary stands behind it, so
93
+ // there is no GIR name to export it under and inventing one would be held against
94
+ // nothing but prose (ADR 0034 § 5). Those classes therefore keep their flat name, and
95
+ // that is not a second spelling: it is their only one.
96
+ //
97
+ // Everything else below is not a widget class at all — a factory, a helper, or a type —
98
+ // and a type has no namespace member to move to.
99
+
100
+ // Two elements with no GTK counterpart: `.adw-card` is a style class here and a styled
101
+ // container on GTK, and the grid is presentational where GTK would use a plain Gtk.Grid.
68
102
  export { AdwCard } from './elements/adw-card.js';
69
103
  export { AdwDataGrid } from './elements/adw-data-grid.js';
70
104
  export type {
@@ -73,66 +107,33 @@ export type {
73
107
  AdwDataGridRow,
74
108
  AdwDataGridRowVariant,
75
109
  } from './elements/adw-data-grid.js';
76
- export { AdwClamp } from './elements/adw-clamp.js';
77
- export { AdwSpinner } from './elements/adw-spinner.js';
78
- export { AdwStatusPage } from './elements/adw-status-page.js';
79
- export { AdwWindow } from './elements/adw-window.js';
80
- export { AdwHeaderBar } from './elements/adw-header-bar.js';
81
- export { AdwWindowTitle } from './elements/adw-window-title.js';
82
- export { AdwButton } from './elements/adw-button.js';
83
- export { AdwButtonContent } from './elements/adw-button-content.js';
84
- // The ONE symbolic-icon node and the ONE toggle, exported before the widgets that build
85
- // them so the barrel's definition order matches theirs. Each host ALSO imports them
86
- // directly, which is what actually guarantees the tags are defined before a
87
- // server-rendered host upgrades.
88
- export { AdwIcon, createAdwIcon } from './elements/adw-icon.js';
89
- export { AdwSwitch } from './elements/adw-switch.js';
90
- // The two form-control primitives. ONE module, because upstream merges their
91
- // stylesheet (`_checks.scss`; there is no `_radio.scss` in libadwaita) and
92
- // everything but the corner radius, the glyph and the group is shared.
93
- export { AdwCheckbox, AdwRadio } from './elements/adw-checks.js';
94
- // The determinate progress indicator — <adw-spinner> covers only the indeterminate case.
95
- export { AdwProgressBar } from './elements/adw-progress-bar.js';
96
- // A keyboard shortcut, drawn as keycaps. The accelerator GRAMMAR lives in
97
- // @gjsify/adwaita-core; this element only builds the nodes.
98
- export { AdwShortcutLabel } from './elements/adw-shortcut-label.js';
99
- // The ONE popover surface, exported before its three hosts for the same reason as
100
- // <adw-icon> above.
101
- export { AdwPopover } from './elements/adw-popover.js';
102
- export type { AdwPopoverAlign, AdwPopoverPosition, AdwPopoverRole } from './elements/adw-popover.js';
103
- export { AdwSplitButton } from './elements/adw-split-button.js';
104
- export { AdwToggle, AdwToggleGroup } from './elements/adw-toggle-group.js';
105
- export { AdwEntry } from './elements/adw-entry.js';
106
- export { AdwPreferencesGroup } from './elements/adw-preferences-group.js';
107
- export { AdwActionRow } from './elements/adw-action-row.js';
108
- export { AdwEntryRow } from './elements/adw-entry-row.js';
109
- export { AdwSwitchRow } from './elements/adw-switch-row.js';
110
- export { AdwComboRow } from './elements/adw-combo-row.js';
111
- export { AdwSpinRow } from './elements/adw-spin-row.js';
112
- export { AdwButtonRow } from './elements/adw-button-row.js';
113
- export { AdwExpanderRow } from './elements/adw-expander-row.js';
114
- export { AdwPasswordEntryRow } from './elements/adw-password-entry-row.js';
115
- export { AdwToastOverlay } from './elements/adw-toast-overlay.js';
116
- export { AdwToolbarView } from './elements/adw-toolbar-view.js';
117
- export { AdwWrapBox } from './elements/adw-wrap-box.js';
118
- export { AdwOverlaySplitView } from './elements/adw-overlay-split-view.js';
119
- export { AdwNavigationSplitView } from './elements/adw-navigation-split-view.js';
120
- export { AdwCarousel, AdwCarouselIndicatorDots, AdwCarouselIndicatorLines } from './elements/adw-carousel.js';
121
- export { AdwTabPage, AdwTabView } from './elements/adw-tab-view.js';
122
- export { AdwViewSwitcher, AdwViewSwitcherPage } from './elements/adw-view-switcher.js';
123
- export { AdwInlineViewSwitcher, AdwViewStackPage } from './elements/adw-inline-view-switcher.js';
124
- export { AdwViewStack } from './elements/adw-view-stack.js';
110
+
111
+ // The symbolic-icon FACTORY. `Gtk.Image` is the element; this builds one without a tag,
112
+ // which the icon-drawing element modules use internally and a consumer with its own
113
+ // chrome needs.
114
+ export { createGtkImage } from './elements/gtk-image.js';
115
+
116
+ // GTK4 has no radio TYPE — a radio is a GtkCheckButton with its `group` set — so
117
+ // `Gtk.CheckButton` is the plain form and the grouped one has only this name.
118
+ export { AdwRadio } from './elements/checks.js';
119
+
120
+ // The declarative children of four composites. Each descends from `GObject.Object` and
121
+ // not `GtkWidget` on GTK, so the table of concrete widgets has no row for them; the day
122
+ // it grows one, its member appears in `namespace.ts` by itself.
123
+ export { AdwTabPage } from './elements/adw-tab-view.js';
124
+ export { AdwViewSwitcherPage } from './elements/adw-view-switcher.js';
125
+ export { AdwViewStackPage } from './elements/adw-inline-view-switcher.js';
126
+ export { AdwSidebarItem, AdwSidebarSection } from './elements/adw-sidebar.js';
127
+
128
+ // Slot wrappers and a declarative response: on GTK these are `set_content()`,
129
+ // `set_sheet()` and `add_response()` — calls, not widgets.
130
+ export { AdwBottomSheetContent, AdwBottomSheetSheet } from './elements/adw-bottom-sheet.js';
131
+ export { AdwAlertResponse } from './elements/adw-alert-dialog.js';
132
+
133
+ // Supporting types — the option bags, enums and unions the widgets above take and
134
+ // return. Not widgets, so clause 2 has nothing to say about them.
135
+ export type { GtkPopoverAlign, GtkPopoverPosition, GtkPopoverRole } from './elements/gtk-popover.js';
125
136
  export type { AdwViewStackPageInfo } from './elements/adw-view-stack.js';
126
- export { AdwViewSwitcherBar } from './elements/adw-view-switcher-bar.js';
127
- export { AdwMenuButton } from './elements/adw-menu-button.js';
128
- export type { AdwMenuItem } from './elements/adw-menu-button.js';
129
- export { AdwDropDown } from './elements/adw-drop-down.js';
130
- export type { AdwDropDownOption } from './elements/adw-drop-down.js';
131
- export { AdwNavigationPage, AdwNavigationView } from './elements/adw-navigation-view.js';
132
- export { AdwBottomSheet, AdwBottomSheetContent, AdwBottomSheetSheet } from './elements/adw-bottom-sheet.js';
133
- export { AdwSidebar, AdwSidebarItem, AdwSidebarSection } from './elements/adw-sidebar.js';
134
- export { AdwAboutDialog } from './elements/adw-about-dialog.js';
135
- export { AdwAlertDialog, AdwAlertResponse } from './elements/adw-alert-dialog.js';
136
- export { AdwPreferencesDialog, AdwPreferencesPage } from './elements/adw-preferences-dialog.js';
137
- export { AdwDialog } from './elements/adw-dialog.js';
137
+ export type { AdwMenuItem } from './elements/gtk-menu-button.js';
138
+ export type { GtkDropDownOption } from './elements/gtk-drop-down.js';
138
139
  export type { AdwDialogPresentationMode } from './elements/adw-dialog.js';