@gjsify/adwaita-web 0.64.2-next.252 → 0.64.2-next.255

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 (293) hide show
  1. package/README.md +10 -80
  2. package/dist/adwaita-web.css +52 -3
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/accessible.d.ts +8 -0
  5. package/lib/types/compute-expand.d.ts +5 -0
  6. package/lib/types/compute-expand.spec.d.ts +1 -0
  7. package/lib/types/elements/adw-about-dialog.d.ts +28 -1
  8. package/lib/types/elements/adw-action-row.d.ts +2 -1
  9. package/lib/types/elements/adw-alert-dialog.d.ts +3 -2
  10. package/lib/types/elements/adw-avatar.d.ts +2 -1
  11. package/lib/types/elements/adw-banner.d.ts +2 -1
  12. package/lib/types/elements/adw-bin.d.ts +2 -1
  13. package/lib/types/elements/adw-bottom-sheet.d.ts +5 -4
  14. package/lib/types/elements/adw-breakpoint-bin.d.ts +2 -1
  15. package/lib/types/elements/adw-button-content.d.ts +2 -1
  16. package/lib/types/elements/adw-button-row.d.ts +2 -1
  17. package/lib/types/elements/adw-card.d.ts +2 -1
  18. package/lib/types/elements/adw-carousel.d.ts +20 -3
  19. package/lib/types/elements/adw-clamp-scrollable.d.ts +2 -1
  20. package/lib/types/elements/adw-clamp.d.ts +2 -1
  21. package/lib/types/elements/adw-combo-row.d.ts +6 -1
  22. package/lib/types/elements/adw-data-grid.d.ts +2 -1
  23. package/lib/types/elements/adw-dialog.d.ts +2 -1
  24. package/lib/types/elements/adw-entry-row.d.ts +2 -1
  25. package/lib/types/elements/adw-expander-row.d.ts +2 -1
  26. package/lib/types/elements/adw-header-bar.d.ts +2 -1
  27. package/lib/types/elements/adw-inline-view-switcher.d.ts +3 -2
  28. package/lib/types/elements/adw-layout-slot.d.ts +2 -1
  29. package/lib/types/elements/adw-multi-layout-view.d.ts +2 -1
  30. package/lib/types/elements/adw-navigation-split-view.d.ts +2 -1
  31. package/lib/types/elements/adw-navigation-view.d.ts +3 -2
  32. package/lib/types/elements/adw-overlay-split-view.d.ts +2 -1
  33. package/lib/types/elements/adw-preferences-dialog.d.ts +5 -4
  34. package/lib/types/elements/adw-preferences-group.d.ts +2 -1
  35. package/lib/types/elements/adw-preferences-row.d.ts +2 -1
  36. package/lib/types/elements/adw-shortcut-label.d.ts +2 -1
  37. package/lib/types/elements/adw-shortcuts-item.d.ts +2 -1
  38. package/lib/types/elements/adw-shortcuts-section.d.ts +2 -1
  39. package/lib/types/elements/adw-sidebar.d.ts +4 -3
  40. package/lib/types/elements/adw-spin-row.d.ts +2 -1
  41. package/lib/types/elements/adw-spinner.d.ts +2 -1
  42. package/lib/types/elements/adw-split-button.d.ts +2 -1
  43. package/lib/types/elements/adw-status-page.d.ts +2 -1
  44. package/lib/types/elements/adw-switch-row.d.ts +4 -1
  45. package/lib/types/elements/adw-tab-bar.d.ts +2 -1
  46. package/lib/types/elements/adw-tab-button.d.ts +2 -1
  47. package/lib/types/elements/adw-tab-overview.d.ts +2 -1
  48. package/lib/types/elements/adw-tab-view.d.ts +3 -2
  49. package/lib/types/elements/adw-toast-overlay.d.ts +2 -1
  50. package/lib/types/elements/adw-toggle-group.d.ts +3 -2
  51. package/lib/types/elements/adw-toolbar-view.d.ts +2 -1
  52. package/lib/types/elements/adw-view-stack.d.ts +3 -1
  53. package/lib/types/elements/adw-view-switcher-bar.d.ts +2 -1
  54. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +2 -1
  55. package/lib/types/elements/adw-view-switcher.d.ts +3 -2
  56. package/lib/types/elements/adw-window-title.d.ts +2 -1
  57. package/lib/types/elements/adw-wrap-box.d.ts +2 -1
  58. package/lib/types/elements/checks.d.ts +16 -1
  59. package/lib/types/elements/gtk-action-bar.d.ts +2 -1
  60. package/lib/types/elements/gtk-aspect-frame.d.ts +2 -1
  61. package/lib/types/elements/gtk-box.d.ts +5 -1
  62. package/lib/types/elements/gtk-button.d.ts +5 -7
  63. package/lib/types/elements/gtk-calendar.d.ts +2 -1
  64. package/lib/types/elements/gtk-center-box.d.ts +2 -1
  65. package/lib/types/elements/gtk-color-dialog-button.d.ts +2 -1
  66. package/lib/types/elements/gtk-drag-icon.d.ts +2 -1
  67. package/lib/types/elements/gtk-drawing-area.d.ts +2 -1
  68. package/lib/types/elements/gtk-drop-down.d.ts +2 -1
  69. package/lib/types/elements/gtk-editable-label.d.ts +2 -1
  70. package/lib/types/elements/gtk-entry.d.ts +2 -1
  71. package/lib/types/elements/gtk-expander.d.ts +2 -1
  72. package/lib/types/elements/gtk-fixed.d.ts +2 -1
  73. package/lib/types/elements/gtk-flow-box-child.d.ts +2 -1
  74. package/lib/types/elements/gtk-flow-box.d.ts +2 -1
  75. package/lib/types/elements/gtk-font-dialog-button.d.ts +2 -1
  76. package/lib/types/elements/gtk-frame.d.ts +2 -1
  77. package/lib/types/elements/gtk-gl-area.d.ts +2 -1
  78. package/lib/types/elements/gtk-graphics-offload.d.ts +2 -1
  79. package/lib/types/elements/gtk-grid.d.ts +2 -1
  80. package/lib/types/elements/gtk-header-bar.d.ts +2 -1
  81. package/lib/types/elements/gtk-image.d.ts +5 -6
  82. package/lib/types/elements/gtk-inscription.d.ts +2 -1
  83. package/lib/types/elements/gtk-label.d.ts +10 -3
  84. package/lib/types/elements/gtk-level-bar.d.ts +2 -1
  85. package/lib/types/elements/gtk-list-box-row.d.ts +2 -1
  86. package/lib/types/elements/gtk-list-box.d.ts +2 -1
  87. package/lib/types/elements/gtk-list-view.d.ts +2 -1
  88. package/lib/types/elements/gtk-media-controls.d.ts +2 -1
  89. package/lib/types/elements/gtk-menu-button.d.ts +2 -1
  90. package/lib/types/elements/gtk-notebook.d.ts +2 -1
  91. package/lib/types/elements/gtk-overlay.d.ts +2 -1
  92. package/lib/types/elements/gtk-paned.d.ts +2 -1
  93. package/lib/types/elements/gtk-picture.d.ts +2 -1
  94. package/lib/types/elements/gtk-popover-bin.d.ts +2 -1
  95. package/lib/types/elements/gtk-popover-menu-bar.d.ts +2 -1
  96. package/lib/types/elements/gtk-popover.d.ts +2 -1
  97. package/lib/types/elements/gtk-progress-bar.d.ts +2 -1
  98. package/lib/types/elements/gtk-revealer.d.ts +2 -1
  99. package/lib/types/elements/gtk-scale-button.d.ts +2 -1
  100. package/lib/types/elements/gtk-scale.d.ts +2 -1
  101. package/lib/types/elements/gtk-scrollbar.d.ts +2 -1
  102. package/lib/types/elements/gtk-scrolled-window.d.ts +2 -1
  103. package/lib/types/elements/gtk-search-bar.d.ts +2 -1
  104. package/lib/types/elements/gtk-separator.d.ts +2 -1
  105. package/lib/types/elements/gtk-spin-button.d.ts +2 -1
  106. package/lib/types/elements/gtk-spinner.d.ts +2 -1
  107. package/lib/types/elements/gtk-stack-page.d.ts +2 -1
  108. package/lib/types/elements/gtk-stack-sidebar.d.ts +2 -1
  109. package/lib/types/elements/gtk-stack-switcher.d.ts +2 -1
  110. package/lib/types/elements/gtk-stack.d.ts +2 -1
  111. package/lib/types/elements/gtk-switch.d.ts +2 -1
  112. package/lib/types/elements/gtk-text-view.d.ts +2 -1
  113. package/lib/types/elements/gtk-text.d.ts +2 -1
  114. package/lib/types/elements/gtk-tree-expander.d.ts +2 -1
  115. package/lib/types/elements/gtk-video.d.ts +2 -1
  116. package/lib/types/elements/gtk-viewport.d.ts +2 -1
  117. package/lib/types/elements/gtk-window-controls.d.ts +2 -1
  118. package/lib/types/elements/gtk-window-handle.d.ts +2 -1
  119. package/lib/types/elements/gtk-window.d.ts +2 -1
  120. package/lib/types/gobject-elements.d.ts +7 -1
  121. package/lib/types/gtksource/gtk-source-view.d.ts +2 -1
  122. package/lib/types/{icon-registry.spec.d.ts → icon-masks.spec.d.ts} +1 -1
  123. package/lib/types/icon-theme.d.ts +15 -35
  124. package/lib/types/index.d.ts +1 -2
  125. package/lib/types/namespace/gdk.d.ts +1 -0
  126. package/lib/types/namespace/gio.d.ts +1 -0
  127. package/lib/types/namespace/glib.d.ts +2 -1
  128. package/lib/types/signals.d.ts +5 -1
  129. package/lib/types/source-view/adw-source-view.d.ts +2 -1
  130. package/lib/types/styles.generated.d.ts +1 -1
  131. package/lib/types/widget-element.d.ts +25 -0
  132. package/lib/types/widget-map.spec.d.ts +1 -0
  133. package/lib/types/widget-mapping.d.ts +7 -0
  134. package/package.json +12 -12
  135. package/scss/_about_dialog.scss +46 -1
  136. package/scss/_checks.scss +5 -2
  137. package/scss/_icon.scss +3 -4
  138. package/scss/_labels.scss +2 -2
  139. package/scss/_overlay_split_view.scss +10 -0
  140. package/scss/_scrolled_window.scss +15 -0
  141. package/scss/_widget.scss +5 -1
  142. package/src/accessible.ts +29 -0
  143. package/src/adw-about-dialog.spec.ts +81 -12
  144. package/src/adw-action-rows.spec.ts +2 -2
  145. package/src/adw-button-content.spec.ts +1 -1
  146. package/src/adw-carousel.spec.ts +49 -1
  147. package/src/capabilities.mjs +1 -0
  148. package/src/checks.spec.ts +51 -1
  149. package/src/compute-expand.spec.ts +186 -0
  150. package/src/compute-expand.ts +134 -0
  151. package/src/construct-vectors.spec.ts +46 -1
  152. package/src/elements/adw-about-dialog.ts +152 -9
  153. package/src/elements/adw-action-row.ts +2 -1
  154. package/src/elements/adw-alert-dialog.ts +3 -2
  155. package/src/elements/adw-avatar.ts +2 -1
  156. package/src/elements/adw-banner.ts +2 -1
  157. package/src/elements/adw-bin.ts +2 -1
  158. package/src/elements/adw-bottom-sheet.ts +5 -4
  159. package/src/elements/adw-breakpoint-bin.ts +2 -1
  160. package/src/elements/adw-button-content.ts +2 -1
  161. package/src/elements/adw-button-row.ts +2 -1
  162. package/src/elements/adw-card.ts +2 -1
  163. package/src/elements/adw-carousel.ts +62 -3
  164. package/src/elements/adw-clamp-scrollable.ts +2 -1
  165. package/src/elements/adw-clamp.ts +2 -1
  166. package/src/elements/adw-combo-row.ts +15 -1
  167. package/src/elements/adw-data-grid.ts +2 -1
  168. package/src/elements/adw-dialog.ts +2 -1
  169. package/src/elements/adw-entry-row.ts +2 -1
  170. package/src/elements/adw-expander-row.ts +2 -1
  171. package/src/elements/adw-header-bar.ts +2 -1
  172. package/src/elements/adw-inline-view-switcher.ts +3 -2
  173. package/src/elements/adw-layout-slot.ts +2 -1
  174. package/src/elements/adw-multi-layout-view.ts +2 -1
  175. package/src/elements/adw-navigation-split-view.ts +2 -1
  176. package/src/elements/adw-navigation-view.ts +3 -2
  177. package/src/elements/adw-overlay-split-view.ts +2 -1
  178. package/src/elements/adw-preferences-dialog.ts +6 -4
  179. package/src/elements/adw-preferences-group.ts +2 -1
  180. package/src/elements/adw-preferences-row.ts +2 -1
  181. package/src/elements/adw-shortcut-label.ts +2 -1
  182. package/src/elements/adw-shortcuts-item.ts +2 -1
  183. package/src/elements/adw-shortcuts-section.ts +2 -1
  184. package/src/elements/adw-sidebar.ts +4 -3
  185. package/src/elements/adw-spin-row.ts +2 -1
  186. package/src/elements/adw-spinner.ts +2 -1
  187. package/src/elements/adw-split-button.ts +2 -1
  188. package/src/elements/adw-status-page.ts +2 -1
  189. package/src/elements/adw-switch-row.ts +10 -1
  190. package/src/elements/adw-tab-bar.ts +2 -1
  191. package/src/elements/adw-tab-button.ts +2 -1
  192. package/src/elements/adw-tab-overview.ts +2 -1
  193. package/src/elements/adw-tab-view.ts +3 -2
  194. package/src/elements/adw-toast-overlay.ts +2 -1
  195. package/src/elements/adw-toggle-group.ts +3 -2
  196. package/src/elements/adw-toolbar-view.ts +2 -1
  197. package/src/elements/adw-view-stack.ts +39 -1
  198. package/src/elements/adw-view-switcher-bar.ts +2 -1
  199. package/src/elements/adw-view-switcher-sidebar.ts +2 -1
  200. package/src/elements/adw-view-switcher.ts +3 -2
  201. package/src/elements/adw-window-title.ts +2 -1
  202. package/src/elements/adw-wrap-box.ts +2 -1
  203. package/src/elements/checks.ts +85 -6
  204. package/src/elements/gtk-action-bar.ts +2 -1
  205. package/src/elements/gtk-aspect-frame.ts +2 -1
  206. package/src/elements/gtk-box.ts +56 -1
  207. package/src/elements/gtk-button.ts +10 -22
  208. package/src/elements/gtk-calendar.ts +2 -1
  209. package/src/elements/gtk-center-box.ts +2 -1
  210. package/src/elements/gtk-color-dialog-button.ts +2 -1
  211. package/src/elements/gtk-drag-icon.ts +2 -1
  212. package/src/elements/gtk-drawing-area.ts +2 -1
  213. package/src/elements/gtk-drop-down.ts +2 -1
  214. package/src/elements/gtk-editable-label.ts +2 -1
  215. package/src/elements/gtk-entry.ts +2 -1
  216. package/src/elements/gtk-expander.ts +2 -1
  217. package/src/elements/gtk-fixed.ts +2 -1
  218. package/src/elements/gtk-flow-box-child.ts +2 -1
  219. package/src/elements/gtk-flow-box.ts +2 -1
  220. package/src/elements/gtk-font-dialog-button.ts +2 -1
  221. package/src/elements/gtk-frame.ts +2 -1
  222. package/src/elements/gtk-gl-area.ts +2 -1
  223. package/src/elements/gtk-graphics-offload.ts +2 -1
  224. package/src/elements/gtk-grid.ts +2 -1
  225. package/src/elements/gtk-header-bar.ts +2 -1
  226. package/src/elements/gtk-image.ts +14 -15
  227. package/src/elements/gtk-inscription.ts +2 -1
  228. package/src/elements/gtk-label.ts +12 -5
  229. package/src/elements/gtk-level-bar.ts +2 -1
  230. package/src/elements/gtk-list-box-row.ts +2 -1
  231. package/src/elements/gtk-list-box.ts +2 -1
  232. package/src/elements/gtk-list-view.ts +2 -1
  233. package/src/elements/gtk-media-controls.ts +2 -1
  234. package/src/elements/gtk-menu-button.ts +2 -1
  235. package/src/elements/gtk-notebook.ts +2 -1
  236. package/src/elements/gtk-overlay.ts +2 -1
  237. package/src/elements/gtk-paned.ts +2 -1
  238. package/src/elements/gtk-picture.ts +2 -1
  239. package/src/elements/gtk-popover-bin.ts +2 -1
  240. package/src/elements/gtk-popover-menu-bar.ts +2 -1
  241. package/src/elements/gtk-popover.ts +2 -1
  242. package/src/elements/gtk-progress-bar.ts +2 -1
  243. package/src/elements/gtk-revealer.ts +2 -1
  244. package/src/elements/gtk-scale-button.ts +2 -1
  245. package/src/elements/gtk-scale.ts +2 -1
  246. package/src/elements/gtk-scrollbar.ts +2 -1
  247. package/src/elements/gtk-scrolled-window.ts +8 -5
  248. package/src/elements/gtk-search-bar.ts +2 -1
  249. package/src/elements/gtk-separator.ts +2 -1
  250. package/src/elements/gtk-spin-button.ts +2 -1
  251. package/src/elements/gtk-spinner.ts +2 -1
  252. package/src/elements/gtk-stack-page.ts +2 -1
  253. package/src/elements/gtk-stack-sidebar.ts +2 -1
  254. package/src/elements/gtk-stack-switcher.ts +2 -1
  255. package/src/elements/gtk-stack.ts +2 -1
  256. package/src/elements/gtk-switch.ts +2 -1
  257. package/src/elements/gtk-text-view.ts +2 -1
  258. package/src/elements/gtk-text.ts +2 -1
  259. package/src/elements/gtk-tree-expander.ts +2 -1
  260. package/src/elements/gtk-video.ts +2 -1
  261. package/src/elements/gtk-viewport.ts +2 -1
  262. package/src/elements/gtk-window-controls.ts +2 -1
  263. package/src/elements/gtk-window-handle.ts +2 -1
  264. package/src/elements/gtk-window.ts +2 -1
  265. package/src/gio.spec.ts +13 -3
  266. package/src/glib.spec.ts +9 -0
  267. package/src/gobject-elements.ts +18 -4
  268. package/src/gtk-label.spec.ts +39 -0
  269. package/src/gtk-scrolled-window.spec.ts +6 -6
  270. package/src/gtk-value-doors.spec.ts +19 -0
  271. package/src/gtk-window.spec.ts +2 -2
  272. package/src/gtksource/gtk-source-view.ts +2 -1
  273. package/src/{icon-registry.spec.ts → icon-masks.spec.ts} +4 -100
  274. package/src/icon-theme.spec.ts +69 -124
  275. package/src/icon-theme.ts +29 -119
  276. package/src/index.ts +3 -7
  277. package/src/namespace/gdk.ts +1 -0
  278. package/src/namespace/gio.ts +8 -0
  279. package/src/namespace/glib.ts +4 -0
  280. package/src/shared-tree-builder.ts +26 -3
  281. package/src/signals.ts +11 -2
  282. package/src/source-view/adw-source-view.ts +2 -1
  283. package/src/split-button.spec.ts +1 -1
  284. package/src/style-manager.spec.ts +13 -0
  285. package/src/style-manager.ts +6 -0
  286. package/src/styles.generated.ts +1 -1
  287. package/src/test.browser.mts +6 -2
  288. package/src/widget-element.ts +75 -0
  289. package/src/widget-map.spec.ts +116 -0
  290. package/src/widget-mapping.ts +100 -0
  291. package/src/widget-visible.spec.ts +44 -0
  292. package/lib/types/icon-registry.d.ts +0 -37
  293. package/src/icon-registry.ts +0 -163
@@ -32,6 +32,7 @@
32
32
 
33
33
  import { bindSlottedChildren } from '../slotted-children.js';
34
34
  import { AdwModalSurface } from './modal-surface.js';
35
+ import { WidgetElement } from '../widget-element.js';
35
36
 
36
37
  /** Adaptive presentation of the dialog — mirrors Adw.DialogPresentationMode. */
37
38
  export type AdwDialogPresentationMode = 'auto' | 'floating' | 'bottom-sheet';
@@ -39,7 +40,7 @@ export type AdwDialogPresentationMode = 'auto' | 'floating' | 'bottom-sheet';
39
40
  const DEFAULT_CONTENT_WIDTH = 360;
40
41
  const PRESENTATION_MODES: readonly AdwDialogPresentationMode[] = ['auto', 'floating', 'bottom-sheet'];
41
42
 
42
- export class AdwDialog extends HTMLElement {
43
+ export class AdwDialog extends WidgetElement {
43
44
  private _initialized = false;
44
45
  private _scrimEl!: HTMLDivElement;
45
46
  private _boxEl!: HTMLDivElement;
@@ -41,6 +41,7 @@ import { booleanAttribute } from '../attributes.js';
41
41
  import { applyRowTooltip } from '../row-tooltip.js';
42
42
  import { bindSlottedChildren, type AdwSlottedChildren } from '../slotted-children.js';
43
43
  import { type GtkImage, createGtkImage } from './gtk-image.js';
44
+ import { TooltipElement } from '../widget-element.js';
44
45
 
45
46
  /**
46
47
  * Show/hide a rendered part. `hidden` carries the semantics and is what the conformance
@@ -53,7 +54,7 @@ function setPartVisible(part: HTMLElement, visible: boolean): void {
53
54
  part.style.display = visible ? '' : 'none';
54
55
  }
55
56
 
56
- export class AdwEntryRow extends HTMLElement {
57
+ export class AdwEntryRow extends TooltipElement {
57
58
  /** The headless `update_empty` derivation + apply latch (ADR 0004). */
58
59
  protected readonly _state = new EntryRowState();
59
60
  protected _input!: HTMLInputElement;
@@ -42,8 +42,9 @@ import './gtk-switch.js';
42
42
  import type { GtkSwitch } from './gtk-switch.js';
43
43
  import { type GtkImage, createGtkImage } from './gtk-image.js';
44
44
  import { attachRowActivation } from './row-activation.js';
45
+ import { TooltipElement } from '../widget-element.js';
45
46
 
46
- export class AdwExpanderRow extends HTMLElement {
47
+ export class AdwExpanderRow extends TooltipElement {
47
48
  private _headerEl!: HTMLDivElement;
48
49
  private _titleEl!: HTMLSpanElement;
49
50
  private _subtitleEl!: HTMLSpanElement;
@@ -33,8 +33,9 @@ import { bindSlottedChildren } from '../slotted-children.js';
33
33
  // Registers <adw-window-title>: the derived centre is one, so importing the bar
34
34
  // alone must still define it.
35
35
  import './adw-window-title.js';
36
+ import { WidgetElement } from '../widget-element.js';
36
37
 
37
- export class AdwHeaderBar extends HTMLElement {
38
+ export class AdwHeaderBar extends WidgetElement {
38
39
  private _initialized = false;
39
40
  private _startEl: HTMLDivElement | null = null;
40
41
  private _centerEl: HTMLDivElement | null = null;
@@ -57,9 +57,10 @@ import {
57
57
  } from './view-switcher-dom.js';
58
58
  import { bindSlottedChildren } from '../slotted-children.js';
59
59
  import { attachRovingFocus } from './roving-focus.js';
60
+ import { WidgetElement } from '../widget-element.js';
60
61
 
61
62
  /** A single page. Children of <adw-inline-view-switcher>; consumed at connect time. */
62
- export class AdwViewStackPage extends HTMLElement {
63
+ export class AdwViewStackPage extends WidgetElement {
63
64
  static get observedAttributes() {
64
65
  return ['name', 'title', 'icon-name', 'badge-number', 'needs-attention', 'use-underline'];
65
66
  }
@@ -75,7 +76,7 @@ export class AdwViewStackPage extends HTMLElement {
75
76
  }
76
77
  }
77
78
 
78
- export class AdwInlineViewSwitcher extends HTMLElement {
79
+ export class AdwInlineViewSwitcher extends WidgetElement {
79
80
  /**
80
81
  * The dwell timer, injectable: a property rather than an inline
81
82
  * `new ViewSwitcherState({ scheduler: domViewSwitcherScheduler })`, so a test can
@@ -31,8 +31,9 @@
31
31
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
32
32
 
33
33
  import { AdwMultiLayoutView } from './adw-multi-layout-view.js';
34
+ import { WidgetElement } from '../widget-element.js';
34
35
 
35
- export class AdwLayoutSlot extends HTMLElement {
36
+ export class AdwLayoutSlot extends WidgetElement {
36
37
  private _registered = false;
37
38
 
38
39
  static get observedAttributes() {
@@ -57,6 +57,7 @@
57
57
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
58
58
 
59
59
  import type { AdwLayoutSlot } from './adw-layout-slot.js';
60
+ import { WidgetElement } from '../widget-element.js';
60
61
 
61
62
  /** One layout: the element itself, plus the name `AdwLayout:name` carries. */
62
63
  interface Layout {
@@ -64,7 +65,7 @@ interface Layout {
64
65
  readonly content: Element;
65
66
  }
66
67
 
67
- export class AdwMultiLayoutView extends HTMLElement {
68
+ export class AdwMultiLayoutView extends WidgetElement {
68
69
  /** The C's own tables: layouts in order, children by id, and the current layout. */
69
70
  private _layouts: Layout[] = [];
70
71
  private _children = new Map<string, Element>();
@@ -37,6 +37,7 @@ import {
37
37
 
38
38
  import { bindBreakpointSetter } from '../breakpoints.js';
39
39
  import { bindSlottedChildren } from '../slotted-children.js';
40
+ import { WidgetElement } from '../widget-element.js';
40
41
 
41
42
  /** Detail of the `navigation-push` / `navigation-pop` delegation event. */
42
43
  export interface NavigationDelegateDetail {
@@ -46,7 +47,7 @@ export interface NavigationDelegateDetail {
46
47
  handled: boolean;
47
48
  }
48
49
 
49
- export class AdwNavigationSplitView extends HTMLElement {
50
+ export class AdwNavigationSplitView extends WidgetElement {
50
51
  private _sidebarEl!: HTMLDivElement;
51
52
  private _contentEl!: HTMLDivElement;
52
53
  private _initialized = false;
@@ -57,6 +57,7 @@ import type { AdwNavigationPageProps, NavigationDiagnostic, NavigationStackChang
57
57
  import { bindSlottedChildren } from '../slotted-children.js';
58
58
  import { installElementApi } from '../gobject-elements.js';
59
59
  import type { DispatchedSignals } from '../signals.js';
60
+ import { WidgetElement } from '../widget-element.js';
60
61
 
61
62
  /** The page properties the core owns, read off the element's attributes. */
62
63
  function readPageProps(page: AdwNavigationPage): AdwNavigationPageProps {
@@ -64,7 +65,7 @@ function readPageProps(page: AdwNavigationPage): AdwNavigationPageProps {
64
65
  }
65
66
 
66
67
  /** A single navigation page. Children of <adw-navigation-view>. */
67
- export class AdwNavigationPage extends HTMLElement {
68
+ export class AdwNavigationPage extends WidgetElement {
68
69
  /** Set while the owning view writes an attribute back, so the sync cannot recurse. */
69
70
  private _syncing = false;
70
71
 
@@ -136,7 +137,7 @@ export class AdwNavigationPage extends HTMLElement {
136
137
  }
137
138
  }
138
139
 
139
- export class AdwNavigationView extends HTMLElement {
140
+ export class AdwNavigationView extends WidgetElement {
140
141
  /** The GTK signals this element dispatches, each with the DOM event it arrives as (ADR 0093). */
141
142
  static readonly signals: DispatchedSignals = {
142
143
  pushed: 'pushed',
@@ -28,6 +28,7 @@ import {
28
28
  import { bindBreakpointSetter } from '../breakpoints.js';
29
29
  import type { DispatchedSignals } from '../signals.js';
30
30
  import { bindSlottedChildren } from '../slotted-children.js';
31
+ import { WidgetElement } from '../widget-element.js';
31
32
 
32
33
  /**
33
34
  * The reveal spring, as a CSS-timed animator: libadwaita animates with a spring
@@ -80,7 +81,7 @@ function readTriStateAttr(element: Element, name: string, fallback: boolean): bo
80
81
  return raw !== 'false' && raw !== '0';
81
82
  }
82
83
 
83
- export class AdwOverlaySplitView extends HTMLElement {
84
+ export class AdwOverlaySplitView extends WidgetElement {
84
85
  /** The GTK signals this element dispatches, which is what a `.blp` `bind` of `show-sidebar` follows. */
85
86
  static readonly signals: DispatchedSignals = { 'notify::show-sidebar': 'notify::show-sidebar' };
86
87
 
@@ -52,6 +52,7 @@ import type { PreferencesSearchResult, SearchPreferencesOptions } from '@gjsify/
52
52
  import { searchPreferencesDom } from '../preferences-search.js';
53
53
  import { bindSlottedChildren } from '../slotted-children.js';
54
54
  import { AdwModalSurface } from './modal-surface.js';
55
+ import { WidgetElement } from '../widget-element.js';
55
56
 
56
57
  const DEFAULT_CONTENT_WIDTH = 640;
57
58
 
@@ -63,7 +64,7 @@ const DEFAULT_CONTENT_WIDTH = 640;
63
64
  * / name / use-underline / visible onto the view-stack page, and
64
65
  * `create_search_row_subtitle` needs the title back the moment a second page is visible.
65
66
  */
66
- export class AdwPreferencesPage extends HTMLElement {
67
+ export class AdwPreferencesPage extends WidgetElement {
67
68
  static get observedAttributes() {
68
69
  return ['title', 'icon-name', 'name', 'use-underline', 'open'];
69
70
  }
@@ -100,7 +101,7 @@ export class AdwPreferencesPage extends HTMLElement {
100
101
  }
101
102
  }
102
103
 
103
- export class AdwPreferencesDialog extends HTMLElement {
104
+ export class AdwPreferencesDialog extends WidgetElement {
104
105
  private _initialized = false;
105
106
  private _scrimEl!: HTMLDivElement;
106
107
  private _dialogEl!: HTMLDivElement;
@@ -146,8 +147,9 @@ export class AdwPreferencesDialog extends HTMLElement {
146
147
  this.setAttribute('content-width', String(value));
147
148
  }
148
149
 
149
- /** Reveal the dialog (mirrors Adw.Dialog.present). */
150
- present(): void {
150
+ /** Reveal the dialog (mirrors Adw.Dialog.present). Auto-attaches if disconnected. */
151
+ present(parent?: Element): void {
152
+ if (!this.isConnected) (parent ?? document.body).appendChild(this);
151
153
  this.open = true;
152
154
  }
153
155
 
@@ -25,13 +25,14 @@
25
25
  import { derivePreferencesGroupHeader } from '@gjsify/adwaita-core';
26
26
 
27
27
  import { bindSlottedChildren } from '../slotted-children.js';
28
+ import { WidgetElement } from '../widget-element.js';
28
29
 
29
30
  /** A child that asked to sit in the header rather than in the boxed list. */
30
31
  function isHeaderSuffix(node: Node): boolean {
31
32
  return node instanceof Element && node.getAttribute('slot') === 'header-suffix';
32
33
  }
33
34
 
34
- export class AdwPreferencesGroup extends HTMLElement {
35
+ export class AdwPreferencesGroup extends WidgetElement {
35
36
  private _headerEl!: HTMLDivElement;
36
37
  private _titleEl!: HTMLSpanElement;
37
38
  private _descriptionEl!: HTMLSpanElement;
@@ -47,8 +47,9 @@ import { labelDisplayText, stringIsNotEmpty } from '@gjsify/adwaita-core';
47
47
  import { applyRowTooltip } from '../row-tooltip.js';
48
48
  import { bindEmptySections } from '../empty-sections.js';
49
49
  import { bindSlottedChildren } from '../slotted-children.js';
50
+ import { TooltipElement } from '../widget-element.js';
50
51
 
51
- export class AdwPreferencesRow extends HTMLElement {
52
+ export class AdwPreferencesRow extends TooltipElement {
52
53
  private _titleEl!: HTMLSpanElement;
53
54
  private _contentEl!: HTMLDivElement;
54
55
  private _initialized = false;
@@ -26,8 +26,9 @@
26
26
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
27
27
 
28
28
  import { parseShortcutLabel } from '@gjsify/adwaita-core';
29
+ import { WidgetElement } from '../widget-element.js';
29
30
 
30
- export class AdwShortcutLabel extends HTMLElement {
31
+ export class AdwShortcutLabel extends WidgetElement {
31
32
  private _initialized = false;
32
33
 
33
34
  static get observedAttributes() {
@@ -36,6 +36,7 @@
36
36
  // Reference: refs/libadwaita/src/stylesheet/widgets/_shortcuts-dialog.scss:16-27
37
37
  // Copyright (c) 2025 GNOME Foundation Inc. (libadwaita). LGPLv2.1+
38
38
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
39
+ import { WidgetElement } from '../widget-element.js';
39
40
 
40
41
  /**
41
42
  * `AdwShortcutsItem:direction` is a `GtkTextDirection`, so it carries `none` beside the
@@ -48,7 +49,7 @@ export type AdwShortcutsItemDirection = 'ltr' | 'rtl' | 'none';
48
49
 
49
50
  const DIRECTIONS: readonly AdwShortcutsItemDirection[] = ['ltr', 'rtl', 'none'];
50
51
 
51
- export class AdwShortcutsItem extends HTMLElement {
52
+ export class AdwShortcutsItem extends WidgetElement {
52
53
  private _initialized = false;
53
54
  private _titleEl!: HTMLSpanElement;
54
55
  private _subtitleEl!: HTMLSpanElement;
@@ -27,8 +27,9 @@
27
27
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
28
28
 
29
29
  import { bindSlottedChildren } from '../slotted-children.js';
30
+ import { WidgetElement } from '../widget-element.js';
30
31
 
31
- export class AdwShortcutsSection extends HTMLElement {
32
+ export class AdwShortcutsSection extends WidgetElement {
32
33
  private _initialized = false;
33
34
  private _bodyEl!: HTMLDivElement;
34
35
  private _titleEl!: HTMLElement;
@@ -65,6 +65,7 @@ import {
65
65
  import { createGtkImage } from './gtk-image.js';
66
66
  import { attachRovingFocus } from './roving-focus.js';
67
67
  import { booleanAttribute } from '../attributes.js';
68
+ import { WidgetElement } from '../widget-element.js';
68
69
 
69
70
  // The sidebar consumes its declared children and drops them from the tree, so a later
70
71
  // `setAttribute` on one cannot find its sidebar with `closest()`. These keep the link —
@@ -74,7 +75,7 @@ const itemBindings = new WeakMap<AdwSidebarItem, { sidebar: AdwSidebar; spec: Ad
74
75
  const sectionBindings = new WeakMap<AdwSidebarSection, { sidebar: AdwSidebar; spec: AdwSidebarSectionSpec }>();
75
76
 
76
77
  /** A single sidebar item. Child of <adw-sidebar-section>; consumed at connect time. */
77
- export class AdwSidebarItem extends HTMLElement {
78
+ export class AdwSidebarItem extends WidgetElement {
78
79
  static get observedAttributes() {
79
80
  return [
80
81
  'title',
@@ -144,7 +145,7 @@ export class AdwSidebarItem extends HTMLElement {
144
145
  }
145
146
 
146
147
  /** A titled group of items. Child of <adw-sidebar>; consumed at connect time. */
147
- export class AdwSidebarSection extends HTMLElement {
148
+ export class AdwSidebarSection extends WidgetElement {
148
149
  static get observedAttributes() {
149
150
  return ['title'];
150
151
  }
@@ -158,7 +159,7 @@ export class AdwSidebarSection extends HTMLElement {
158
159
  }
159
160
  }
160
161
 
161
- export class AdwSidebar extends HTMLElement {
162
+ export class AdwSidebar extends WidgetElement {
162
163
  private readonly _state = new SidebarState();
163
164
  private _listEl!: HTMLDivElement;
164
165
  private _rows: { el: HTMLButtonElement; index: number }[] = [];
@@ -42,6 +42,7 @@ import { attributeOf } from '@gjsify/adwaita-core/tags';
42
42
  import { applyRowTooltip } from '../row-tooltip.js';
43
43
  import { bindSlottedChildren } from '../slotted-children.js';
44
44
  import { applyRowLineClamp, parseRowLinesAttribute } from '../row-line-clamp.js';
45
+ import { TooltipElement } from '../widget-element.js';
45
46
 
46
47
  /** `Gtk.Adjustment`'s six properties, as `AdwAdjustmentInput` names them. */
47
48
  const ADJUSTMENT_FIELDS = ['value', 'lower', 'upper', 'stepIncrement', 'pageIncrement', 'pageSize'] as const;
@@ -63,7 +64,7 @@ function authoredAdjustment(node: Node): AdwAdjustmentInput {
63
64
  return input;
64
65
  }
65
66
 
66
- export class AdwSpinRow extends HTMLElement {
67
+ export class AdwSpinRow extends TooltipElement {
67
68
  private _input!: HTMLInputElement;
68
69
  /** The label column — kept for `tooltip-text`, which the browser reads off a PART. */
69
70
  private _textEl!: HTMLDivElement;
@@ -30,6 +30,7 @@ import {
30
30
  spinnerGeometry,
31
31
  spinnerProgressAt,
32
32
  } from '@gjsify/adwaita-core';
33
+ import { WidgetElement } from '../widget-element.js';
33
34
 
34
35
  const SVG_NS = 'http://www.w3.org/2000/svg';
35
36
 
@@ -52,7 +53,7 @@ function startTicking(): void {
52
53
  if (frameHandle === 0 && mapped.size > 0) frameHandle = requestAnimationFrame(tick);
53
54
  }
54
55
 
55
- export class AdwSpinner extends HTMLElement {
56
+ export class AdwSpinner extends WidgetElement {
56
57
  static get observedAttributes() {
57
58
  return ['size'];
58
59
  }
@@ -72,6 +72,7 @@ import './gtk-popover.js';
72
72
  import type { GtkPopover } from './gtk-popover.js';
73
73
 
74
74
  import { type GtkImage, createGtkImage } from './gtk-image.js';
75
+ import { WidgetElement } from '../widget-element.js';
75
76
 
76
77
  const VARIANT_CLASSES: Record<string, string> = {
77
78
  flat: 'flat',
@@ -118,7 +119,7 @@ const POPOVER_POSITIONS = {
118
119
  right: 'end',
119
120
  } as const;
120
121
 
121
- export class AdwSplitButton extends HTMLElement {
122
+ export class AdwSplitButton extends WidgetElement {
122
123
  private readonly _state = new SplitButtonState();
123
124
  private _actionEl!: HTMLButtonElement;
124
125
  private _dropdownEl!: HTMLButtonElement;
@@ -14,8 +14,9 @@ import { stringIsNotEmpty } from '@gjsify/adwaita-core';
14
14
  import { bindEmptySections } from '../empty-sections.js';
15
15
  import { bindSlottedChildren } from '../slotted-children.js';
16
16
  import { type GtkImage, createGtkImage } from './gtk-image.js';
17
+ import { WidgetElement } from '../widget-element.js';
17
18
 
18
- export class AdwStatusPage extends HTMLElement {
19
+ export class AdwStatusPage extends WidgetElement {
19
20
  private _iconEl!: GtkImage;
20
21
  private _titleEl!: HTMLSpanElement;
21
22
  private _descEl!: HTMLSpanElement;
@@ -42,8 +42,9 @@ import { applyRowLineClamp, parseRowLinesAttribute } from '../row-line-clamp.js'
42
42
  import './gtk-switch.js';
43
43
  import { attachRowActivation } from './row-activation.js';
44
44
  import type { GtkSwitch } from './gtk-switch.js';
45
+ import { TooltipElement } from '../widget-element.js';
45
46
 
46
- export class AdwSwitchRow extends HTMLElement {
47
+ export class AdwSwitchRow extends TooltipElement {
47
48
  /** The GTK signals this element dispatches, each with the DOM event it arrives as (ADR 0093). */
48
49
  static readonly signals: DispatchedSignals = { 'notify::active': 'notify::active' };
49
50
 
@@ -76,6 +77,14 @@ export class AdwSwitchRow extends HTMLElement {
76
77
  this.toggleAttribute('active', !!value);
77
78
  }
78
79
 
80
+ get_active(): boolean {
81
+ return this.active;
82
+ }
83
+
84
+ set_active(active: boolean): void {
85
+ this.active = active;
86
+ }
87
+
79
88
  constructor() {
80
89
  super();
81
90
  installElementApi(this);
@@ -79,6 +79,7 @@ import { tabsRevealed } from '@gjsify/adwaita-core';
79
79
  import { bindSlottedChildren } from '../slotted-children.js';
80
80
  import { type TabChip, createTabChip, refreshTabChip, refreshTabChipClose, scrollChipIntoBar } from '../tab-chip.js';
81
81
  import type { AdwTabView } from './adw-tab-view.js';
82
+ import { WidgetElement } from '../widget-element.js';
82
83
 
83
84
  /** `set_view`'s connections: the page list, the selection, and each page's own state. */
84
85
  const VIEW_EVENTS = [
@@ -92,7 +93,7 @@ const VIEW_EVENTS = [
92
93
 
93
94
  /** The CSS classes a chip's own layout reads — the states C puts on the widget. */
94
95
 
95
- export class AdwTabBar extends HTMLElement {
96
+ export class AdwTabBar extends WidgetElement {
96
97
  private _boxEl!: HTMLDivElement;
97
98
  private _startEl!: HTMLDivElement;
98
99
  private _endEl!: HTMLDivElement;
@@ -49,6 +49,7 @@
49
49
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
50
50
 
51
51
  import type { AdwTabView } from './adw-tab-view.js';
52
+ import { WidgetElement } from '../widget-element.js';
52
53
 
53
54
  /** `update_icon`: a label from ten pages up, because two digits do not fit the plate. */
54
55
  const SMALL_LABEL_PAGES = 10;
@@ -57,7 +58,7 @@ const OVERFLOW_PAGES = 100;
57
58
  /** What `set_view` connects to: the page list, the selection and each page's attention. */
58
59
  const VIEW_EVENTS = ['page-attached', 'page-detached', 'page-updated', 'notify::selected-page'] as const;
59
60
 
60
- export class AdwTabButton extends HTMLElement {
61
+ export class AdwTabButton extends WidgetElement {
61
62
  private _button!: HTMLButtonElement;
62
63
  private _binEl!: HTMLSpanElement;
63
64
  private _labelEl!: HTMLSpanElement;
@@ -81,6 +81,7 @@ import { assertMenuRenderable, ADW_MENU_SURFACE_WEB } from '@gjsify/adwaita-core
81
81
 
82
82
  import type { AdwTabView, AdwTabViewPage } from './adw-tab-view.js';
83
83
  import { createGtkImage, type GtkImage } from './gtk-image.js';
84
+ import { WidgetElement } from '../widget-element.js';
84
85
 
85
86
  /** The thumbnail nodes of one page, kept so a re-render edits them in place. */
86
87
  interface Thumbnail {
@@ -98,7 +99,7 @@ interface Thumbnail {
98
99
  attention: HTMLDivElement;
99
100
  }
100
101
 
101
- export class AdwTabOverview extends HTMLElement {
102
+ export class AdwTabOverview extends WidgetElement {
102
103
  private _childEl!: HTMLDivElement;
103
104
  private _overviewEl!: HTMLDivElement;
104
105
  private _headerEl!: HTMLDivElement;
@@ -50,6 +50,7 @@ import type { AdwTabPageSpec, AdwTabPageState, TabViewPagesChange, TabViewSelect
50
50
 
51
51
  import { bindSlottedChildren } from '../slotted-children.js';
52
52
  import { type TabChip, createTabChip, refreshTabChip, refreshTabChipClose, scrollChipIntoBar } from '../tab-chip.js';
53
+ import { WidgetElement } from '../widget-element.js';
53
54
 
54
55
  export type AdwTabViewPage = AdwTabPageState<HTMLElement>;
55
56
 
@@ -73,7 +74,7 @@ const PAGE_ATTRIBUTES = [
73
74
  * moves the children out and discards the element leaves `observedAttributes` with
74
75
  * nothing to act on.
75
76
  */
76
- export class AdwTabPage extends HTMLElement {
77
+ export class AdwTabPage extends WidgetElement {
77
78
  static get observedAttributes() {
78
79
  return PAGE_ATTRIBUTES;
79
80
  }
@@ -106,7 +107,7 @@ export class AdwTabPage extends HTMLElement {
106
107
  }
107
108
  }
108
109
 
109
- export class AdwTabView extends HTMLElement {
110
+ export class AdwTabView extends WidgetElement {
110
111
  private readonly _state = new TabViewState<HTMLElement>({
111
112
  onClosePage: (page) => this._requestClose(page),
112
113
  });
@@ -25,6 +25,7 @@ import { renderPangoMarkup } from '../pango-markup.js';
25
25
  import { bindSlottedChildren } from '../slotted-children.js';
26
26
  import { createGtkImage } from './gtk-image.js';
27
27
  import type { Toast, ToastScheduler, ToastTimerHandle } from '@gjsify/adwaita-core';
28
+ import { WidgetElement } from '../widget-element.js';
28
29
 
29
30
  // The timing seam is re-exported so a consumer can type a custom scheduler for
30
31
  // {@link AdwToastOverlay.scheduler} without depending on the core package.
@@ -43,7 +44,7 @@ const domScheduler: ToastScheduler = {
43
44
  cancel: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),
44
45
  };
45
46
 
46
- export class AdwToastOverlay extends HTMLElement {
47
+ export class AdwToastOverlay extends WidgetElement {
47
48
  private _toasts!: HTMLDivElement;
48
49
  private _initialized = false;
49
50
  /** The headless queue of `adw-toast-overlay.c` (ADR 0004). */
@@ -83,9 +83,10 @@ import { ToggleGroupState, keptToggles, toggleIndexOfName } from '@gjsify/adwait
83
83
  import { booleanAttribute } from '../attributes.js';
84
84
  import { createGtkImage } from './gtk-image.js';
85
85
  import { attachRovingFocus } from './roving-focus.js';
86
+ import { WidgetElement } from '../widget-element.js';
86
87
 
87
88
  /** A single toggle. Children of <adw-toggle-group>; consumed at connect time. */
88
- export class AdwToggle extends HTMLElement {
89
+ export class AdwToggle extends WidgetElement {
89
90
  // `tooltip` joins because `AdwToggle:tooltip` exists upstream (:467) and an
90
91
  // icon-only toggle has no other text — `tooltip` is what NAMES it, so it is not a
91
92
  // decoration. It produces no disabled or hidden button, which is the invariant
@@ -111,7 +112,7 @@ export class AdwToggle extends HTMLElement {
111
112
  }
112
113
  }
113
114
 
114
- export class AdwToggleGroup extends HTMLElement {
115
+ export class AdwToggleGroup extends WidgetElement {
115
116
  private _innerEl!: HTMLDivElement;
116
117
  private _buttons: HTMLButtonElement[] = [];
117
118
  /** The headless segment list + guarded selection state machine (ADR 0004). */
@@ -33,8 +33,9 @@ import {
33
33
  import { bindEmptySections } from '../empty-sections.js';
34
34
  import { AdwScrollShading } from '../scroll-shading.js';
35
35
  import { bindSlottedChildren } from '../slotted-children.js';
36
+ import { WidgetElement } from '../widget-element.js';
36
37
 
37
- export class AdwToolbarView extends HTMLElement {
38
+ export class AdwToolbarView extends WidgetElement {
38
39
  private _topEl!: HTMLDivElement;
39
40
  private _contentEl!: HTMLDivElement;
40
41
  private _bottomEl!: HTMLDivElement;
@@ -51,10 +51,11 @@ import { ViewStackState } from '@gjsify/adwaita-core';
51
51
  import type { AdwViewStackPageInfo as CorePageInfo, ViewStackStateChange } from '@gjsify/adwaita-core';
52
52
 
53
53
  import type { DispatchedSignals } from '../signals.js';
54
+ import { WidgetElement } from '../widget-element.js';
54
55
 
55
56
  export type AdwViewStackPageInfo = CorePageInfo<HTMLElement>;
56
57
 
57
- export class AdwViewStack extends HTMLElement {
58
+ export class AdwViewStack extends WidgetElement {
58
59
  /** The GTK signals this element dispatches, each with the DOM event it arrives as (ADR 0093). */
59
60
  static readonly signals: DispatchedSignals = {
60
61
  'notify::visible-child': 'notify::visible-child',
@@ -73,6 +74,11 @@ export class AdwViewStack extends HTMLElement {
73
74
  // Subscribing touches no attributes and no children, so it is legal in a
74
75
  // custom element constructor — unlike anything DOM-shaped.
75
76
  this._state.subscribe((change) => this._onStateChange(change));
77
+ // A page moved out by plain DOM (`otherBox.append(page)`) is `gtk_widget_unparent`
78
+ // reaching the stack's `remove`: `stack_remove` (adw-view-stack.c:1184-1205) drops
79
+ // the page, so it must not stay in the model or keep the stack's marks elsewhere.
80
+ // Observing the element itself touches no attribute and no child.
81
+ new MutationObserver((records) => this._onChildrenRemoved(records)).observe(this, { childList: true });
76
82
  }
77
83
 
78
84
  get pages(): readonly AdwViewStackPageInfo[] {
@@ -217,6 +223,7 @@ export class AdwViewStack extends HTMLElement {
217
223
  const content = this._state.pages[this._state.indexOfName(name)]?.content;
218
224
  if (!this._state.removePage(name)) return false;
219
225
  content?.remove();
226
+ if (content) clearPageMarks(content);
220
227
  this._applyVisibility();
221
228
  this._reflectName();
222
229
  this._emitItemsChanged();
@@ -271,6 +278,25 @@ export class AdwViewStack extends HTMLElement {
271
278
  );
272
279
  }
273
280
 
281
+ private _onChildrenRemoved(records: MutationRecord[]): void {
282
+ let changed = false;
283
+ for (const record of records) {
284
+ for (const node of record.removedNodes) {
285
+ // Re-appended into this same stack (a reorder) is still a child.
286
+ if (!(node instanceof HTMLElement) || node.parentElement === this) continue;
287
+ const page = this._state.pages.find((p) => p.content === node);
288
+ if (page === undefined) continue;
289
+ this._state.removePage(page.name);
290
+ clearPageMarks(node);
291
+ changed = true;
292
+ }
293
+ }
294
+ if (!changed) return;
295
+ this._applyVisibility();
296
+ this._reflectName();
297
+ this._emitItemsChanged();
298
+ }
299
+
274
300
  private _applyVisibility(): void {
275
301
  const selected = this._state.visibleIndex;
276
302
  this._state.pages.forEach((page, index) => {
@@ -299,3 +325,15 @@ export class AdwViewStack extends HTMLElement {
299
325
  }
300
326
 
301
327
  customElements.define('adw-view-stack', AdwViewStack);
328
+
329
+ /**
330
+ * What the stack wrote on a page's content, taken back once it is no longer a page: the
331
+ * class, the name, `active-view` and the `hidden` that is `gtk_widget_set_child_visible`
332
+ * (adw-view-stack.c:1138) — a child-visible flag the stack owns, which `gtk_widget_unparent`
333
+ * resets, not the widget's own visibility.
334
+ */
335
+ function clearPageMarks(content: HTMLElement): void {
336
+ content.classList.remove('adw-view-stack-child', 'active-view');
337
+ delete content.dataset.name;
338
+ content.hidden = false;
339
+ }
@@ -25,6 +25,7 @@ import type { AdwViewStack } from './adw-view-stack.js';
25
25
  import { applyDescription, applyIndicator, applySwitcherIcon } from './view-switcher-dom.js';
26
26
  import { type GtkImage, createGtkImage } from './gtk-image.js';
27
27
  import { attachRovingFocus } from './roving-focus.js';
28
+ import { WidgetElement } from '../widget-element.js';
28
29
 
29
30
  /** The DOM nodes one bar button owns — the bar paints the derived model onto them. */
30
31
  interface BarButtonNodes {
@@ -34,7 +35,7 @@ interface BarButtonNodes {
34
35
  indicator: HTMLSpanElement;
35
36
  }
36
37
 
37
- export class AdwViewSwitcherBar extends HTMLElement {
38
+ export class AdwViewSwitcherBar extends WidgetElement {
38
39
  private readonly _barState = new ViewSwitcherBarState();
39
40
  private _barEl!: HTMLDivElement;
40
41
  private _nodes: BarButtonNodes[] = [];
@@ -57,8 +57,9 @@ import type { AdwSidebarItemSpec, AdwSidebarSectionSpec, SidebarItemFilter } fro
57
57
  import { bindSlottedChildren } from '../slotted-children.js';
58
58
  import type { AdwSidebar } from './adw-sidebar.js';
59
59
  import type { AdwViewStack } from './adw-view-stack.js';
60
+ import { WidgetElement } from '../widget-element.js';
60
61
 
61
- export class AdwViewSwitcherSidebar extends HTMLElement {
62
+ export class AdwViewSwitcherSidebar extends WidgetElement {
62
63
  private _sidebar!: AdwSidebar;
63
64
  private _placeholderEl!: HTMLDivElement;
64
65
  private _prefixEl!: HTMLDivElement;