@gjsify/adwaita-web 0.64.1 → 0.64.2-next.254

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 (335) hide show
  1. package/README.md +22 -88
  2. package/dist/adwaita-web.css +91 -12
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/accessible.d.ts +8 -0
  5. package/lib/types/application.d.ts +1 -1
  6. package/lib/types/child-slot.spec.d.ts +1 -0
  7. package/lib/types/compute-expand.d.ts +5 -0
  8. package/lib/types/compute-expand.spec.d.ts +1 -0
  9. package/lib/types/container-fill.spec.d.ts +1 -0
  10. package/lib/types/elements/adw-about-dialog.d.ts +28 -1
  11. package/lib/types/elements/adw-action-row.d.ts +2 -1
  12. package/lib/types/elements/adw-alert-dialog.d.ts +80 -19
  13. package/lib/types/elements/adw-avatar.d.ts +2 -1
  14. package/lib/types/elements/adw-banner.d.ts +2 -1
  15. package/lib/types/elements/adw-bin.d.ts +2 -1
  16. package/lib/types/elements/adw-bottom-sheet.d.ts +5 -4
  17. package/lib/types/elements/adw-breakpoint-bin.d.ts +2 -1
  18. package/lib/types/elements/adw-button-content.d.ts +2 -1
  19. package/lib/types/elements/adw-button-row.d.ts +2 -1
  20. package/lib/types/elements/adw-card.d.ts +2 -1
  21. package/lib/types/elements/adw-carousel.d.ts +20 -3
  22. package/lib/types/elements/adw-clamp-scrollable.d.ts +2 -1
  23. package/lib/types/elements/adw-clamp.d.ts +2 -1
  24. package/lib/types/elements/adw-combo-row.d.ts +6 -1
  25. package/lib/types/elements/adw-data-grid.d.ts +2 -1
  26. package/lib/types/elements/adw-dialog.d.ts +2 -1
  27. package/lib/types/elements/adw-entry-row.d.ts +2 -1
  28. package/lib/types/elements/adw-expander-row.d.ts +2 -1
  29. package/lib/types/elements/adw-header-bar.d.ts +2 -1
  30. package/lib/types/elements/adw-inline-view-switcher.d.ts +3 -2
  31. package/lib/types/elements/adw-layout-slot.d.ts +2 -1
  32. package/lib/types/elements/adw-multi-layout-view.d.ts +2 -1
  33. package/lib/types/elements/adw-navigation-split-view.d.ts +2 -1
  34. package/lib/types/elements/adw-navigation-view.d.ts +3 -2
  35. package/lib/types/elements/adw-overlay-split-view.d.ts +2 -1
  36. package/lib/types/elements/adw-preferences-dialog.d.ts +5 -4
  37. package/lib/types/elements/adw-preferences-group.d.ts +2 -1
  38. package/lib/types/elements/adw-preferences-row.d.ts +2 -1
  39. package/lib/types/elements/adw-shortcut-label.d.ts +2 -1
  40. package/lib/types/elements/adw-shortcuts-item.d.ts +2 -1
  41. package/lib/types/elements/adw-shortcuts-section.d.ts +2 -1
  42. package/lib/types/elements/adw-sidebar.d.ts +4 -3
  43. package/lib/types/elements/adw-spin-row.d.ts +2 -1
  44. package/lib/types/elements/adw-spinner.d.ts +2 -1
  45. package/lib/types/elements/adw-split-button.d.ts +2 -1
  46. package/lib/types/elements/adw-status-page.d.ts +2 -1
  47. package/lib/types/elements/adw-switch-row.d.ts +4 -1
  48. package/lib/types/elements/adw-tab-bar.d.ts +2 -1
  49. package/lib/types/elements/adw-tab-button.d.ts +2 -1
  50. package/lib/types/elements/adw-tab-overview.d.ts +2 -1
  51. package/lib/types/elements/adw-tab-view.d.ts +3 -2
  52. package/lib/types/elements/adw-toast-overlay.d.ts +10 -30
  53. package/lib/types/elements/adw-toggle-group.d.ts +3 -2
  54. package/lib/types/elements/adw-toolbar-view.d.ts +2 -1
  55. package/lib/types/elements/adw-view-stack.d.ts +3 -1
  56. package/lib/types/elements/adw-view-switcher-bar.d.ts +2 -1
  57. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +2 -1
  58. package/lib/types/elements/adw-view-switcher.d.ts +3 -2
  59. package/lib/types/elements/adw-window-features.d.ts +8 -0
  60. package/lib/types/elements/adw-window-title.d.ts +2 -1
  61. package/lib/types/elements/adw-wrap-box.d.ts +2 -1
  62. package/lib/types/elements/checks.d.ts +16 -1
  63. package/lib/types/elements/gtk-action-bar.d.ts +2 -1
  64. package/lib/types/elements/gtk-application-window.d.ts +1 -4
  65. package/lib/types/elements/gtk-aspect-frame.d.ts +2 -1
  66. package/lib/types/elements/gtk-box.d.ts +5 -1
  67. package/lib/types/elements/gtk-button.d.ts +5 -7
  68. package/lib/types/elements/gtk-calendar.d.ts +2 -1
  69. package/lib/types/elements/gtk-center-box.d.ts +2 -1
  70. package/lib/types/elements/gtk-color-dialog-button.d.ts +2 -1
  71. package/lib/types/elements/gtk-drag-icon.d.ts +2 -1
  72. package/lib/types/elements/gtk-drawing-area.d.ts +2 -1
  73. package/lib/types/elements/gtk-drop-down.d.ts +2 -1
  74. package/lib/types/elements/gtk-editable-label.d.ts +2 -1
  75. package/lib/types/elements/gtk-emoji-chooser.d.ts +2 -0
  76. package/lib/types/elements/gtk-entry.d.ts +2 -1
  77. package/lib/types/elements/gtk-expander.d.ts +2 -1
  78. package/lib/types/elements/gtk-fixed.d.ts +2 -1
  79. package/lib/types/elements/gtk-flow-box-child.d.ts +2 -1
  80. package/lib/types/elements/gtk-flow-box.d.ts +2 -1
  81. package/lib/types/elements/gtk-font-dialog-button.d.ts +2 -1
  82. package/lib/types/elements/gtk-frame.d.ts +2 -1
  83. package/lib/types/elements/gtk-gl-area.d.ts +2 -1
  84. package/lib/types/elements/gtk-graphics-offload.d.ts +2 -1
  85. package/lib/types/elements/gtk-grid.d.ts +2 -1
  86. package/lib/types/elements/gtk-header-bar.d.ts +2 -1
  87. package/lib/types/elements/gtk-image.d.ts +5 -6
  88. package/lib/types/elements/gtk-inscription.d.ts +2 -1
  89. package/lib/types/elements/gtk-label.d.ts +10 -3
  90. package/lib/types/elements/gtk-level-bar.d.ts +2 -1
  91. package/lib/types/elements/gtk-list-box-row.d.ts +2 -1
  92. package/lib/types/elements/gtk-list-box.d.ts +2 -1
  93. package/lib/types/elements/gtk-list-view.d.ts +2 -1
  94. package/lib/types/elements/gtk-media-controls.d.ts +2 -1
  95. package/lib/types/elements/gtk-menu-button.d.ts +2 -1
  96. package/lib/types/elements/gtk-notebook.d.ts +2 -1
  97. package/lib/types/elements/gtk-overlay.d.ts +2 -1
  98. package/lib/types/elements/gtk-paned.d.ts +2 -1
  99. package/lib/types/elements/gtk-picture.d.ts +2 -1
  100. package/lib/types/elements/gtk-popover-bin.d.ts +2 -1
  101. package/lib/types/elements/gtk-popover-menu-bar.d.ts +2 -1
  102. package/lib/types/elements/gtk-popover-menu.d.ts +2 -0
  103. package/lib/types/elements/gtk-popover.d.ts +7 -1
  104. package/lib/types/elements/gtk-progress-bar.d.ts +2 -1
  105. package/lib/types/elements/gtk-revealer.d.ts +2 -1
  106. package/lib/types/elements/gtk-scale-button.d.ts +2 -1
  107. package/lib/types/elements/gtk-scale.d.ts +2 -1
  108. package/lib/types/elements/gtk-scrollbar.d.ts +2 -1
  109. package/lib/types/elements/gtk-scrolled-window.d.ts +2 -1
  110. package/lib/types/elements/gtk-search-bar.d.ts +2 -1
  111. package/lib/types/elements/gtk-separator.d.ts +2 -1
  112. package/lib/types/elements/gtk-spin-button.d.ts +2 -1
  113. package/lib/types/elements/gtk-spinner.d.ts +2 -1
  114. package/lib/types/elements/gtk-stack-page.d.ts +29 -0
  115. package/lib/types/elements/gtk-stack-sidebar.d.ts +2 -1
  116. package/lib/types/elements/gtk-stack-switcher.d.ts +2 -1
  117. package/lib/types/elements/gtk-stack.d.ts +13 -1
  118. package/lib/types/elements/gtk-switch.d.ts +2 -1
  119. package/lib/types/elements/gtk-text-view.d.ts +2 -1
  120. package/lib/types/elements/gtk-text.d.ts +2 -1
  121. package/lib/types/elements/gtk-tree-expander.d.ts +2 -1
  122. package/lib/types/elements/gtk-video.d.ts +2 -1
  123. package/lib/types/elements/gtk-viewport.d.ts +2 -1
  124. package/lib/types/elements/gtk-window-controls.d.ts +2 -1
  125. package/lib/types/elements/gtk-window-handle.d.ts +2 -1
  126. package/lib/types/elements/gtk-window.d.ts +18 -2
  127. package/lib/types/gobject-elements.d.ts +15 -0
  128. package/lib/types/gtksource/gtk-source-view.d.ts +2 -1
  129. package/lib/types/{icon-registry.spec.d.ts → icon-masks.spec.d.ts} +1 -1
  130. package/lib/types/icon-theme.d.ts +15 -35
  131. package/lib/types/index.d.ts +3 -4
  132. package/lib/types/learn6502-window.spec.d.ts +1 -0
  133. package/lib/types/namespace/adw.d.ts +1 -1
  134. package/lib/types/namespace/gdk.d.ts +1 -0
  135. package/lib/types/namespace/gio.d.ts +1 -0
  136. package/lib/types/namespace/glib.d.ts +2 -1
  137. package/lib/types/namespace/gtk.d.ts +2 -0
  138. package/lib/types/shared-tree-builder.d.ts +31 -0
  139. package/lib/types/signals.d.ts +5 -1
  140. package/lib/types/source-view/adw-source-view.d.ts +2 -1
  141. package/lib/types/styles.generated.d.ts +1 -1
  142. package/lib/types/widget-element.d.ts +25 -0
  143. package/lib/types/widget-map.spec.d.ts +1 -0
  144. package/lib/types/widget-mapping.d.ts +7 -0
  145. package/lib/types/widget-visible.spec.d.ts +1 -0
  146. package/lib/types/window-maximize.spec.d.ts +1 -0
  147. package/package.json +13 -12
  148. package/scss/_about_dialog.scss +46 -1
  149. package/scss/_bin.scss +6 -3
  150. package/scss/_checks.scss +5 -2
  151. package/scss/_icon.scss +3 -4
  152. package/scss/_labels.scss +2 -2
  153. package/scss/_overlay.scss +11 -1
  154. package/scss/_overlay_split_view.scss +10 -0
  155. package/scss/_reset.scss +1 -1
  156. package/scss/_scrolled_window.scss +15 -0
  157. package/scss/_stack.scss +8 -2
  158. package/scss/_toast.scss +13 -3
  159. package/scss/_widget.scss +5 -1
  160. package/scss/_window.scss +16 -0
  161. package/src/accessible.ts +29 -0
  162. package/src/adw-about-dialog.spec.ts +81 -12
  163. package/src/adw-action-rows.spec.ts +2 -2
  164. package/src/adw-alert-dialog.spec.ts +71 -5
  165. package/src/adw-bin.spec.ts +4 -3
  166. package/src/adw-button-content.spec.ts +1 -1
  167. package/src/adw-carousel.spec.ts +49 -1
  168. package/src/adw-header-bar.spec.ts +18 -0
  169. package/src/adw-toast-overlay.spec.ts +68 -24
  170. package/src/application.spec.ts +44 -0
  171. package/src/application.ts +13 -18
  172. package/src/capabilities.mjs +2 -3
  173. package/src/checks.spec.ts +51 -1
  174. package/src/child-slot.spec.ts +71 -0
  175. package/src/compute-expand.spec.ts +186 -0
  176. package/src/compute-expand.ts +134 -0
  177. package/src/construct-vectors.spec.ts +97 -7
  178. package/src/container-fill.spec.ts +70 -0
  179. package/src/elements/adw-about-dialog.ts +152 -9
  180. package/src/elements/adw-action-row.ts +2 -1
  181. package/src/elements/adw-alert-dialog.ts +177 -46
  182. package/src/elements/adw-application-window.ts +0 -3
  183. package/src/elements/adw-avatar.ts +2 -1
  184. package/src/elements/adw-banner.ts +2 -1
  185. package/src/elements/adw-bin.ts +2 -1
  186. package/src/elements/adw-bottom-sheet.ts +5 -4
  187. package/src/elements/adw-breakpoint-bin.ts +5 -1
  188. package/src/elements/adw-button-content.ts +2 -1
  189. package/src/elements/adw-button-row.ts +2 -1
  190. package/src/elements/adw-card.ts +2 -1
  191. package/src/elements/adw-carousel.ts +62 -3
  192. package/src/elements/adw-clamp-scrollable.ts +2 -1
  193. package/src/elements/adw-clamp.ts +2 -1
  194. package/src/elements/adw-combo-row.ts +15 -1
  195. package/src/elements/adw-data-grid.ts +2 -1
  196. package/src/elements/adw-dialog.ts +5 -2
  197. package/src/elements/adw-entry-row.ts +2 -1
  198. package/src/elements/adw-expander-row.ts +2 -1
  199. package/src/elements/adw-header-bar.ts +6 -1
  200. package/src/elements/adw-inline-view-switcher.ts +3 -2
  201. package/src/elements/adw-layout-slot.ts +2 -1
  202. package/src/elements/adw-multi-layout-view.ts +2 -1
  203. package/src/elements/adw-navigation-split-view.ts +2 -1
  204. package/src/elements/adw-navigation-view.ts +3 -2
  205. package/src/elements/adw-overlay-split-view.ts +2 -1
  206. package/src/elements/adw-preferences-dialog.ts +6 -4
  207. package/src/elements/adw-preferences-group.ts +2 -1
  208. package/src/elements/adw-preferences-row.ts +2 -1
  209. package/src/elements/adw-shortcut-label.ts +2 -1
  210. package/src/elements/adw-shortcuts-item.ts +2 -1
  211. package/src/elements/adw-shortcuts-section.ts +2 -1
  212. package/src/elements/adw-sidebar.ts +4 -3
  213. package/src/elements/adw-spin-row.ts +2 -1
  214. package/src/elements/adw-spinner.ts +2 -1
  215. package/src/elements/adw-split-button.ts +2 -1
  216. package/src/elements/adw-status-page.ts +2 -1
  217. package/src/elements/adw-switch-row.ts +10 -1
  218. package/src/elements/adw-tab-bar.ts +2 -1
  219. package/src/elements/adw-tab-button.ts +2 -1
  220. package/src/elements/adw-tab-overview.ts +2 -1
  221. package/src/elements/adw-tab-view.ts +3 -2
  222. package/src/elements/adw-toast-overlay.ts +37 -70
  223. package/src/elements/adw-toggle-group.ts +3 -2
  224. package/src/elements/adw-toolbar-view.ts +2 -1
  225. package/src/elements/adw-view-stack.ts +39 -1
  226. package/src/elements/adw-view-switcher-bar.ts +2 -1
  227. package/src/elements/adw-view-switcher-sidebar.ts +2 -1
  228. package/src/elements/adw-view-switcher.ts +3 -2
  229. package/src/elements/adw-window-features.ts +14 -2
  230. package/src/elements/adw-window-title.ts +2 -1
  231. package/src/elements/adw-wrap-box.ts +2 -1
  232. package/src/elements/checks.ts +85 -6
  233. package/src/elements/gtk-action-bar.ts +2 -1
  234. package/src/elements/gtk-application-window.ts +3 -8
  235. package/src/elements/gtk-aspect-frame.ts +2 -1
  236. package/src/elements/gtk-box.ts +56 -1
  237. package/src/elements/gtk-button.ts +10 -22
  238. package/src/elements/gtk-calendar.ts +2 -1
  239. package/src/elements/gtk-center-box.ts +2 -1
  240. package/src/elements/gtk-color-dialog-button.ts +2 -1
  241. package/src/elements/gtk-drag-icon.ts +6 -1
  242. package/src/elements/gtk-drawing-area.ts +2 -1
  243. package/src/elements/gtk-drop-down.ts +2 -1
  244. package/src/elements/gtk-editable-label.ts +2 -1
  245. package/src/elements/gtk-emoji-chooser.ts +5 -0
  246. package/src/elements/gtk-entry.ts +2 -1
  247. package/src/elements/gtk-expander.ts +2 -1
  248. package/src/elements/gtk-fixed.ts +2 -1
  249. package/src/elements/gtk-flow-box-child.ts +5 -2
  250. package/src/elements/gtk-flow-box.ts +2 -1
  251. package/src/elements/gtk-font-dialog-button.ts +2 -1
  252. package/src/elements/gtk-frame.ts +2 -1
  253. package/src/elements/gtk-gl-area.ts +2 -1
  254. package/src/elements/gtk-graphics-offload.ts +5 -2
  255. package/src/elements/gtk-grid.ts +2 -1
  256. package/src/elements/gtk-header-bar.ts +2 -1
  257. package/src/elements/gtk-image.ts +14 -15
  258. package/src/elements/gtk-inscription.ts +2 -1
  259. package/src/elements/gtk-label.ts +12 -5
  260. package/src/elements/gtk-level-bar.ts +2 -1
  261. package/src/elements/gtk-list-box-row.ts +5 -2
  262. package/src/elements/gtk-list-box.ts +2 -1
  263. package/src/elements/gtk-list-view.ts +2 -1
  264. package/src/elements/gtk-media-controls.ts +2 -1
  265. package/src/elements/gtk-menu-button.ts +2 -1
  266. package/src/elements/gtk-notebook.ts +2 -1
  267. package/src/elements/gtk-overlay.ts +7 -5
  268. package/src/elements/gtk-paned.ts +9 -2
  269. package/src/elements/gtk-picture.ts +2 -1
  270. package/src/elements/gtk-popover-bin.ts +5 -1
  271. package/src/elements/gtk-popover-menu-bar.ts +2 -1
  272. package/src/elements/gtk-popover-menu.ts +5 -0
  273. package/src/elements/gtk-popover.ts +14 -1
  274. package/src/elements/gtk-progress-bar.ts +2 -1
  275. package/src/elements/gtk-revealer.ts +2 -1
  276. package/src/elements/gtk-scale-button.ts +2 -1
  277. package/src/elements/gtk-scale.ts +2 -1
  278. package/src/elements/gtk-scrollbar.ts +2 -1
  279. package/src/elements/gtk-scrolled-window.ts +8 -5
  280. package/src/elements/gtk-search-bar.ts +7 -6
  281. package/src/elements/gtk-separator.ts +2 -1
  282. package/src/elements/gtk-spin-button.ts +2 -1
  283. package/src/elements/gtk-spinner.ts +2 -1
  284. package/src/elements/gtk-stack-page.ts +112 -0
  285. package/src/elements/gtk-stack-sidebar.ts +2 -1
  286. package/src/elements/gtk-stack-switcher.ts +2 -1
  287. package/src/elements/gtk-stack.ts +52 -6
  288. package/src/elements/gtk-switch.ts +2 -1
  289. package/src/elements/gtk-text-view.ts +2 -1
  290. package/src/elements/gtk-text.ts +2 -1
  291. package/src/elements/gtk-tree-expander.ts +5 -1
  292. package/src/elements/gtk-video.ts +2 -1
  293. package/src/elements/gtk-viewport.ts +6 -1
  294. package/src/elements/gtk-window-controls.ts +2 -1
  295. package/src/elements/gtk-window-handle.ts +6 -1
  296. package/src/elements/gtk-window.ts +57 -7
  297. package/src/gio.spec.ts +13 -3
  298. package/src/glib.spec.ts +9 -0
  299. package/src/gobject-elements.ts +44 -2
  300. package/src/gtk-label.spec.ts +39 -0
  301. package/src/gtk-scrolled-window.spec.ts +6 -6
  302. package/src/gtk-stack.spec.ts +170 -0
  303. package/src/gtk-value-doors.spec.ts +19 -0
  304. package/src/gtk-window.spec.ts +2 -2
  305. package/src/gtksource/gtk-source-view.ts +2 -1
  306. package/src/{icon-registry.spec.ts → icon-masks.spec.ts} +4 -100
  307. package/src/icon-theme.spec.ts +69 -124
  308. package/src/icon-theme.ts +29 -119
  309. package/src/index.ts +5 -9
  310. package/src/keyboard-operable.spec.ts +3 -3
  311. package/src/learn6502-window.spec.ts +113 -0
  312. package/src/namespace/adw.ts +1 -1
  313. package/src/namespace/gdk.ts +1 -0
  314. package/src/namespace/gio.ts +8 -0
  315. package/src/namespace/glib.ts +4 -0
  316. package/src/namespace/gtk.ts +2 -0
  317. package/src/shared-tree-builder.ts +131 -13
  318. package/src/shared-trees.spec.ts +15 -1
  319. package/src/signals.ts +11 -2
  320. package/src/slotted-children.spec.ts +24 -0
  321. package/src/slotted-children.ts +18 -2
  322. package/src/source-view/adw-source-view.ts +2 -1
  323. package/src/split-button.spec.ts +1 -1
  324. package/src/style-manager.spec.ts +13 -0
  325. package/src/style-manager.ts +6 -0
  326. package/src/styles.generated.ts +1 -1
  327. package/src/test.browser.mts +16 -2
  328. package/src/value-lists.spec.ts +3 -3
  329. package/src/widget-element.ts +75 -0
  330. package/src/widget-map.spec.ts +116 -0
  331. package/src/widget-mapping.ts +100 -0
  332. package/src/widget-visible.spec.ts +148 -0
  333. package/src/window-maximize.spec.ts +93 -0
  334. package/lib/types/icon-registry.d.ts +0 -37
  335. package/src/icon-registry.ts +0 -163
@@ -2,44 +2,35 @@
2
2
  // content and shows transient toast strips (title, optional action button, close
3
3
  // affordance) layered over the bottom of its own bounds.
4
4
  //
5
- // The QUEUE — the one-at-a-time policy, FIFO ordering and auto-dismiss lifecycle —
6
- // is HEADLESS and lives in `@gjsify/adwaita-core` (ADR 0004) as {@link AdwToastQueue};
7
- // this element composes it and keeps only the DOM half: build the strip on `onShow`,
8
- // tear it down on `onHide`, run the enter/exit transitions.
5
+ // A toast is an `Adw.Toast` and goes in through `add_toast(toast)`, exactly as on GTK, so a
6
+ // GNOME app's toast code runs here unchanged. The QUEUE — one toast at a time, priority,
7
+ // re-add, auto-dismiss — is HEADLESS and lives in `@gjsify/adwaita-core` (ADR 0004) as
8
+ // {@link ToastOverlayQueue}; this element keeps only the DOM half: build the strip on
9
+ // `onShow`, tear it down on `onHide`, run the enter/exit transitions.
9
10
  //
10
11
  // Adapted from Adwaita Web UI Framework (https://github.com/mclellac/adwaita-web).
11
12
  // Reference: refs/adwaita-web/adwaita-web/scss/_toast.scss, _toast_overlay.scss
12
- // Reference: refs/libadwaita/src/adw-toast-overlay.c, adw-toast.c (add_toast queues,
13
- // one toast is shown at a time, dismissing advances to the next)
13
+ // Reference: refs/libadwaita/src/adw-toast-overlay.c, adw-toast-widget.c (add_toast queues,
14
+ // one toast is shown at a time, the button emits button-clicked, activates the action and
15
+ // dismisses)
14
16
  // Copyright (c) 2025 csm (adwaita-web). MIT License.
15
17
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
16
- // Modifications: Reimplemented as Web Component for @gjsify/adwaita-web;
17
- // extended addToast() with action button + close button + options API; the
18
+ // Modifications: Reimplemented as Web Component for @gjsify/adwaita-web; the
18
19
  // queue/auto-dismiss state machine composed from @gjsify/adwaita-core.
19
20
 
20
- import { AdwToast, AdwToastQueue } from '@gjsify/adwaita-core';
21
+ import { ToastOverlayQueue } from '@gjsify/adwaita-core';
21
22
 
23
+ import { activateWidgetAction } from '../application.js';
24
+ import { renderPangoMarkup } from '../pango-markup.js';
22
25
  import { bindSlottedChildren } from '../slotted-children.js';
23
26
  import { createGtkImage } from './gtk-image.js';
24
- import type { ToastScheduler, ToastTimerHandle } from '@gjsify/adwaita-core';
27
+ import type { Toast, ToastScheduler, ToastTimerHandle } from '@gjsify/adwaita-core';
28
+ import { WidgetElement } from '../widget-element.js';
25
29
 
26
30
  // The timing seam is re-exported so a consumer can type a custom scheduler for
27
31
  // {@link AdwToastOverlay.scheduler} without depending on the core package.
28
32
  export type { ToastScheduler, ToastTimerHandle } from '@gjsify/adwaita-core';
29
33
 
30
- /** Options for {@link AdwToastOverlay.addToast}, mirroring Adw.Toast's properties. */
31
- export interface AdwToastOptions {
32
- /** Seconds before the toast auto-dismisses; `0` keeps it until dismissed. Mirrors Adw.Toast:timeout (default 5). */
33
- timeout?: number;
34
- /** Label for the action button; omitted/empty means no button. Mirrors Adw.Toast:button-label. */
35
- buttonLabel?: string;
36
- /** Invoked when the action button is pressed. Mirrors the activation of Adw.Toast:action-name. */
37
- onAction?: () => void;
38
- }
39
-
40
- /** Default toast lifetime in SECONDS — this element's public unit (Adw.Toast:timeout). */
41
- const DEFAULT_TIMEOUT_SECONDS = 5;
42
-
43
34
  /**
44
35
  * Fallback budget in ms for the exit transition: must stay at or above the
45
36
  * `.adw-toast.hiding` transition-duration in `_toast.scss` (0.15s today), because it
@@ -53,21 +44,19 @@ const domScheduler: ToastScheduler = {
53
44
  cancel: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),
54
45
  };
55
46
 
56
- export class AdwToastOverlay extends HTMLElement {
47
+ export class AdwToastOverlay extends WidgetElement {
57
48
  private _toasts!: HTMLDivElement;
58
49
  private _initialized = false;
59
- /** The headless one-at-a-time + FIFO + auto-dismiss state machine (ADR 0004). */
60
- private readonly _queue: AdwToastQueue;
50
+ /** The headless queue of `adw-toast-overlay.c` (ADR 0004). */
51
+ private readonly _queue: ToastOverlayQueue;
61
52
  /** The timing source the queue's auto-dismiss runs on — swappable, see {@link scheduler}. */
62
53
  private _scheduler: ToastScheduler = domScheduler;
63
- /** The strip currently mounted for {@link AdwToastQueue.current}, if any. */
54
+ /** The strip currently mounted for {@link ToastOverlayQueue.current}, if any. */
64
55
  private _currentEl: HTMLDivElement | null = null;
65
- /** Per-toast action callbacks (the core toast descriptor carries only the label). */
66
- private readonly _actions = new WeakMap<AdwToast, () => void>();
67
56
 
68
57
  constructor() {
69
58
  super();
70
- this._queue = new AdwToastQueue({
59
+ this._queue = new ToastOverlayQueue({
71
60
  // Indirect through `this._scheduler` so the timing source stays
72
61
  // swappable after construction (the queue takes its scheduler once).
73
62
  scheduler: {
@@ -97,7 +86,7 @@ export class AdwToastOverlay extends HTMLElement {
97
86
  this._toasts = document.createElement('div');
98
87
  this._toasts.className = 'adw-toast-overlay-toasts';
99
88
 
100
- bindSlottedChildren(this, [{ into: content }]).install(content, this._toasts);
89
+ bindSlottedChildren(this, [{ name: 'child', into: content }, { into: content }]).install(content, this._toasts);
101
90
  }
102
91
 
103
92
  /**
@@ -115,7 +104,7 @@ export class AdwToastOverlay extends HTMLElement {
115
104
  }
116
105
 
117
106
  /** The toast currently on screen, or `null` when nothing is shown. */
118
- get currentToast(): AdwToast | null {
107
+ get currentToast(): Toast | null {
119
108
  return this._queue.current;
120
109
  }
121
110
 
@@ -124,45 +113,21 @@ export class AdwToastOverlay extends HTMLElement {
124
113
  return this._queue.pending;
125
114
  }
126
115
 
127
- /**
128
- * Show a toast — the web equivalent of Adw.ToastOverlay.add_toast() with a
129
- * freshly-built Adw.Toast. Only ONE toast is visible at a time; this one shows
130
- * immediately when the slot is free, otherwise it waits its turn.
131
- *
132
- * `options` is either an {@link AdwToastOptions} bag or, as a legacy shorthand, a
133
- * timeout in MILLISECONDS.
134
- */
135
- addToast(title: string, options: number | AdwToastOptions = {}): void {
136
- // Ensure the toast container exists even if addToast() races a not-yet
116
+ /** `adw_toast_overlay_add_toast`: show `toast` now, or queue it by its priority. */
117
+ add_toast(toast: Toast): void {
118
+ // Ensure the toast container exists even if add_toast() races a not-yet
137
119
  // connected element (mirrors Adw.ToastOverlay queuing before realize).
138
120
  if (!this._toasts) this.connectedCallback();
139
-
140
- // Back-compat: the original signature was addToast(title, timeoutMs).
141
- const opts: AdwToastOptions = typeof options === 'number' ? { timeout: options / 1000 } : options;
142
-
143
- // This element's public timeout unit is SECONDS (Adw.Toast:timeout); the
144
- // headless descriptor counts milliseconds.
145
- const toast = new AdwToast(title, {
146
- timeout: (opts.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1000,
147
- buttonLabel: opts.buttonLabel,
148
- });
149
- if (opts.onAction) this._actions.set(toast, opts.onAction);
150
-
151
- this._queue.add(toast);
152
- }
153
-
154
- /** Dismiss the visible toast early; the next queued toast takes its place. */
155
- dismiss(): void {
156
- this._queue.dismiss();
121
+ this._queue.add_toast(toast);
157
122
  }
158
123
 
159
- /** Dismiss the visible toast and discard everything still queued behind it. */
160
- clearToasts(): void {
161
- this._queue.clear();
124
+ /** `adw_toast_overlay_dismiss_all`: dismiss every queued toast, then the visible one. */
125
+ dismiss_all(): void {
126
+ this._queue.dismiss_all();
162
127
  }
163
128
 
164
129
  /** Build + attach the strip for `toast` — the DOM half of the queue's `onShow`. */
165
- private _mountToast(toast: AdwToast): void {
130
+ private _mountToast(toast: Toast): void {
166
131
  const el = document.createElement('div');
167
132
  el.className = 'adw-toast';
168
133
 
@@ -171,18 +136,20 @@ export class AdwToastOverlay extends HTMLElement {
171
136
 
172
137
  const titleEl = document.createElement('span');
173
138
  titleEl.className = 'adw-toast-title';
174
- titleEl.textContent = toast.title;
139
+ if (toast.use_markup) renderPangoMarkup(titleEl, toast.title);
140
+ else titleEl.textContent = toast.title;
175
141
  wrapper.appendChild(titleEl);
176
142
  el.appendChild(wrapper);
177
143
 
178
- if (toast.hasButton) {
144
+ if (toast.button_label) {
179
145
  const button = document.createElement('button');
180
146
  button.type = 'button';
181
147
  button.className = 'adw-toast-action-button';
182
- button.textContent = toast.buttonLabel;
148
+ button.textContent = toast.button_label;
183
149
  button.addEventListener('click', () => {
184
- this._actions.get(toast)?.();
185
- this._queue.dismiss();
150
+ toast.emit('button-clicked');
151
+ if (toast.action_name) activateWidgetAction(this, toast.action_name);
152
+ toast.dismiss();
186
153
  });
187
154
  el.appendChild(button);
188
155
  }
@@ -197,7 +164,7 @@ export class AdwToastOverlay extends HTMLElement {
197
164
  close.className = 'adw-toast-close-button';
198
165
  close.setAttribute('aria-label', 'Close');
199
166
  close.appendChild(createGtkImage('window-close'));
200
- close.addEventListener('click', () => this._queue.dismiss());
167
+ close.addEventListener('click', () => toast.dismiss());
201
168
  el.appendChild(close);
202
169
 
203
170
  this._toasts.appendChild(el);
@@ -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;
@@ -56,6 +56,7 @@ import {
56
56
  } from './view-switcher-dom.js';
57
57
  import { type GtkImage, createGtkImage } from './gtk-image.js';
58
58
  import { attachRovingFocus } from './roving-focus.js';
59
+ import { WidgetElement } from '../widget-element.js';
59
60
 
60
61
  /** The DOM nodes one page owns — the switcher paints the derived model onto them. */
61
62
  interface PageNodes {
@@ -75,9 +76,9 @@ interface PageNodes {
75
76
  * switcher watches them with a `MutationObserver` instead — the DOM stand-in for
76
77
  * the per-page `notify` C rebinds on.
77
78
  */
78
- export class AdwViewSwitcherPage extends HTMLElement {}
79
+ export class AdwViewSwitcherPage extends WidgetElement {}
79
80
 
80
- export class AdwViewSwitcher extends HTMLElement {
81
+ export class AdwViewSwitcher extends WidgetElement {
81
82
  /**
82
83
  * The dwell timer, injectable so a test can hand in a clock and drive
83
84
  * `VIEW_SWITCHER_DRAG_VECTORS` against the real element. Replace it before the
@@ -23,6 +23,15 @@ function requested(host: HTMLElement, name: string, fallback: number): number {
23
23
  return Number.isFinite(value) && value >= 0 ? value : fallback;
24
24
  }
25
25
 
26
+ /**
27
+ * A maximized or fullscreen `Gtk.Window` ignores its default size and fills the monitor's work
28
+ * area (gtkwindow.c: the default size is only the RESTORED size). The page's work area is the
29
+ * frame's containing block, which the skin sizes from these two attributes.
30
+ */
31
+ export function fillsContainingBlock(host: HTMLElement): boolean {
32
+ return ['maximized', 'fullscreened'].some((name) => host.hasAttribute(name) && host.getAttribute(name) !== 'false');
33
+ }
34
+
26
35
  export class AdwWindowFeatures {
27
36
  private _contentEl: HTMLDivElement | null = null;
28
37
  private _breakpoints: AdwBreakpoint[] = [];
@@ -128,13 +137,16 @@ export class AdwWindowFeatures {
128
137
  * size; `width-request`/`height-request` override it). `default-width/height` is only
129
138
  * a default: an authored size is the box, and an absent one leaves the box to the
130
139
  * stylesheet, which fills the viewport — a page has no window manager to pick a size.
140
+ * While maximized or fullscreened the default size is not applied at all: the stylesheet
141
+ * fills the containing block, and the minimum still holds.
131
142
  */
132
143
  applySizeRequest(): void {
133
144
  const host = this._host;
134
145
  host.style.minWidth = `${requested(host, 'width-request', DEFAULT_WIDTH)}px`;
135
146
  host.style.minHeight = `${requested(host, 'height-request', DEFAULT_HEIGHT)}px`;
136
- const width = host.getAttribute('default-width') ?? host.getAttribute('width');
137
- const height = host.getAttribute('default-height') ?? host.getAttribute('height');
147
+ const fills = fillsContainingBlock(host);
148
+ const width = fills ? null : (host.getAttribute('default-width') ?? host.getAttribute('width'));
149
+ const height = fills ? null : (host.getAttribute('default-height') ?? host.getAttribute('height'));
138
150
  if (width) host.style.width = `${width}px`;
139
151
  else host.style.removeProperty('width');
140
152
  if (height) host.style.height = `${height}px`;
@@ -22,8 +22,9 @@
22
22
  // title/subtitle state composed from @gjsify/adwaita-core.
23
23
 
24
24
  import { WindowTitleState } from '@gjsify/adwaita-core';
25
+ import { WidgetElement } from '../widget-element.js';
25
26
 
26
- export class AdwWindowTitle extends HTMLElement {
27
+ export class AdwWindowTitle extends WidgetElement {
27
28
  private _titleEl!: HTMLSpanElement;
28
29
  private _subtitleEl!: HTMLSpanElement;
29
30
  /** The headless title/subtitle pair + change detection (ADR 0004). */
@@ -41,6 +41,7 @@ import {
41
41
  wrapPolicyFlexShrink,
42
42
  type AdwLengthUnit,
43
43
  } from '@gjsify/adwaita-core';
44
+ import { WidgetElement } from '../widget-element.js';
44
45
 
45
46
  /**
46
47
  * The attributes that carry a property, in the order the C installs them.
@@ -80,7 +81,7 @@ function alignToJustifyContent(align: number): string {
80
81
  return 'flex-end';
81
82
  }
82
83
 
83
- export class AdwWrapBox extends HTMLElement {
84
+ export class AdwWrapBox extends WidgetElement {
84
85
  private _initialized = false;
85
86
 
86
87
  static get observedAttributes() {
@@ -37,7 +37,9 @@
37
37
  // · The active member of a group cannot be clicked off: both the gesture handler and
38
38
  // `real_activate` return early when the button is active AND has a group neighbour
39
39
  // (:395-396, :617-622). `<adw-radio>` gets this from `RadioGroupState`, and
40
- // `<gtk-check-button>` cannot reach a group at all here.
40
+ // `<gtk-check-button>` from `group` / `set_group` over the core's `check-group.ts`. A
41
+ // grouped `<gtk-check-button>` draws the round radio (the `radio` attribute) and its
42
+ // input announces `role="radio"`.
41
43
  //
42
44
  // ONE PLACE THIS PORT DIVERGES, DELIBERATELY AND CITED. GTK does NOT clear
43
45
  // `inconsistent` when the user activates the button — `real_activate` only flips
@@ -75,7 +77,8 @@
75
77
  // A11Y: the inner input carries the role (native `checkbox` / `radio`) and an
76
78
  // explicit `aria-checked` derived from {@link resolveCheckState}, so the
77
79
  // indeterminate state announces as `mixed` for BOTH — HTML has a native mixed
78
- // checkbox (`input.indeterminate`) but no mixed radio.
80
+ // checkbox (`input.indeterminate`) but no mixed radio. The host's `aria-label` /
81
+ // `aria-description` (a `.blp`'s `accessibility { }`) are copied onto it too.
79
82
  //
80
83
  // Reference: refs/gtk/gtk/gtkcheckbutton.c:99-112,395-426,617-628,647-714,773-774,849-886,925-974
81
84
  // Reference: refs/libadwaita/src/stylesheet/widgets/_checks.scss
@@ -85,9 +88,18 @@
85
88
  // Copyright (c) 2025 csm (adwaita-web). MIT License.
86
89
  // Modifications: Implemented as Web Components for @gjsify/adwaita-web.
87
90
 
88
- import { RadioGroupState, resolveCheckState } from '@gjsify/adwaita-core';
91
+ import {
92
+ RadioGroupState,
93
+ checkActivationFlips,
94
+ checkGroupNeighbours,
95
+ isRadioCheck,
96
+ resolveCheckState,
97
+ setCheckGroup,
98
+ } from '@gjsify/adwaita-core';
89
99
 
100
+ import { FORWARDED_ARIA, forwardAccessibleName } from '../accessible.js';
90
101
  import type { DispatchedSignals } from '../signals.js';
102
+ import { WidgetElement } from '../widget-element.js';
91
103
 
92
104
  /**
93
105
  * The document's radio groups. ONE registry, as global as a bare
@@ -104,7 +116,7 @@ const radioGroups = new RadioGroupState();
104
116
  * `.adw-check-indicator` and `.adw-check-label`, which are the Adwaita SKIN, and the
105
117
  * skin is not what the tag names. It is also not a widget — nothing registers it.
106
118
  */
107
- abstract class AdwCheckBase extends HTMLElement {
119
+ abstract class AdwCheckBase extends WidgetElement {
108
120
  protected _input!: HTMLInputElement;
109
121
  protected _indicator!: HTMLSpanElement;
110
122
  protected _label!: HTMLSpanElement;
@@ -240,6 +252,7 @@ abstract class AdwCheckBase extends HTMLElement {
240
252
  this._input.setAttribute('aria-checked', state === 'indeterminate' ? 'mixed' : String(state === 'checked'));
241
253
  this._input.disabled = this.disabled;
242
254
  this._label.hidden = this._label.childNodes.length === 0;
255
+ forwardAccessibleName(this, this._input);
243
256
  }
244
257
  }
245
258
 
@@ -252,14 +265,80 @@ export class GtkCheckButton extends AdwCheckBase {
252
265
  };
253
266
 
254
267
  static get observedAttributes() {
255
- return ['checked', 'active', 'indeterminate', 'disabled', 'label'];
268
+ return ['checked', 'active', 'indeterminate', 'disabled', 'label', 'group', ...FORWARDED_ARIA];
256
269
  }
257
270
 
258
271
  protected get inputType(): 'checkbox' {
259
272
  return 'checkbox';
260
273
  }
261
274
 
275
+ /**
276
+ * `Gtk.CheckButton:group`, WRITE-ONLY as in GTK (`G_PARAM_WRITABLE`, gtkcheckbutton.c:665-668):
277
+ * another check button, or its id as a projected `.blp` writes it, or `null` to leave.
278
+ */
279
+ set group(value: GtkCheckButton | string | null) {
280
+ if (typeof value === 'string') {
281
+ this.setAttribute('group', value);
282
+ return;
283
+ }
284
+ this.set_group(value);
285
+ }
286
+
287
+ /** `gtk_check_button_set_group`. */
288
+ set_group(group: GtkCheckButton | null): void {
289
+ setCheckGroup(this, group);
290
+ this.render();
291
+ group?.render();
292
+ }
293
+
294
+ get_active(): boolean {
295
+ return this.checked;
296
+ }
297
+
298
+ set_active(active: boolean): void {
299
+ this.checked = active;
300
+ }
301
+
302
+ attributeChangedCallback(name: string) {
303
+ // `set_active (TRUE)` deactivates every member of the group (gtkcheckbutton.c:955-968).
304
+ if (name === 'checked' && this.checked) {
305
+ for (const other of checkGroupNeighbours(this)) other.checked = false;
306
+ }
307
+ if (name === 'group' && this.isConnected) this._resolveGroup();
308
+ super.attributeChangedCallback(name);
309
+ }
310
+
311
+ protected onConnected(): void {
312
+ this._resolveGroup();
313
+ }
314
+
315
+ /** The `group` attribute names a check button by id, looked up once the tree is in a document. */
316
+ private _resolveGroup(): void {
317
+ const id = this.getAttribute('group');
318
+ if (id === null) return;
319
+ const root = this.getRootNode() as Document | ShadowRoot;
320
+ const found = root.getElementById?.(id) ?? document.getElementById(id);
321
+ if (!(found instanceof GtkCheckButton)) {
322
+ throw new Error(`gtk-check-button group="${id}" names no gtk-check-button in this document`);
323
+ }
324
+ this.set_group(found);
325
+ }
326
+
327
+ protected render(): void {
328
+ if (this._input === undefined) return;
329
+ super.render();
330
+ const radio = isRadioCheck(this);
331
+ this.toggleAttribute('radio', radio);
332
+ if (radio) this._input.setAttribute('role', 'radio');
333
+ else this._input.removeAttribute('role');
334
+ }
335
+
262
336
  protected activate(): void {
337
+ // The active member of a group cannot be activated off (gtkcheckbutton.c:395-396, :617-622).
338
+ if (!checkActivationFlips(this, this.checked)) {
339
+ this.render();
340
+ return;
341
+ }
263
342
  // HTML's pre-click activation steps clear `indeterminate` before the toggle, so a
264
343
  // user can always reach a definite state. GTK does NOT: `gtk_check_button_real_activate`
265
344
  // only flips `active` (gtkcheckbutton.c:617-628) and says turning the inconsistent
@@ -274,7 +353,7 @@ export class AdwRadio extends AdwCheckBase {
274
353
  private _unsubscribe: (() => void) | null = null;
275
354
 
276
355
  static get observedAttributes() {
277
- return ['checked', 'indeterminate', 'disabled', 'label', 'name', 'value'];
356
+ return ['checked', 'indeterminate', 'disabled', 'label', 'name', 'value', ...FORWARDED_ARIA];
278
357
  }
279
358
 
280
359
  protected get inputType(): 'radio' {
@@ -20,8 +20,9 @@
20
20
  // Copyright (c) The GTK Team. LGPLv2.1+.
21
21
 
22
22
  import { bindSlottedChildren } from '../slotted-children.js';
23
+ import { WidgetElement } from '../widget-element.js';
23
24
 
24
- export class GtkActionBar extends HTMLElement {
25
+ export class GtkActionBar extends WidgetElement {
25
26
  private _initialized = false;
26
27
  private _startEl: HTMLDivElement | null = null;
27
28
  private _centerEl: HTMLDivElement | null = null;
@@ -16,7 +16,7 @@
16
16
  //
17
17
  // THE `win.` / `app.` PREFIXES. `GtkApplicationWindow` exports window actions under `win.` and
18
18
  // application-wide ones under `app.` (:48-56), and any `GtkActionable` inside the window can
19
- // activate either. `defineWindowApplication` installs the `Gio.ActionMap` half on the prototype
19
+ // activate either. `installActionMap` installs the `Gio.ActionMap` half on the prototype
20
20
  // (`add_action`, `lookup_action`, `remove_action`, the `win.` registry); the `Gio.ActionGroup`
21
21
  // half stays off because a window's `activate_action` is the widget's. Plain `<gtk-window>` has
22
22
  // no ActionMap. What this element adds over it is that map, the strip and the property that shows it.
@@ -26,17 +26,12 @@
26
26
  // Copyright (c) The GTK Team. LGPLv2.1+.
27
27
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
28
28
 
29
- import type { ActionLike } from '@gjsify/adwaita-core';
30
- import type { GtkApplication } from '../application.js';
29
+ import { installActionMap, type ActionLike } from '@gjsify/adwaita-core';
31
30
  import type { DispatchedSignals } from '../signals.js';
32
31
  import type { AdwSlot } from '../slotted-children.js';
33
32
  import { GtkWindow } from './gtk-window.js';
34
- import { defineWindowApplication } from '../application.js';
35
33
 
36
34
  export class GtkApplicationWindow extends GtkWindow {
37
- /** `Gtk.Window:application`: setting it is `add_window` (ADR 0098), set by `defineWindowApplication`. */
38
- declare application: GtkApplication | null;
39
-
40
35
  /** `Gio.ActionMap.add_action`: installed by `installActionMap`; the action is reachable as `win.<name>`. */
41
36
  declare add_action: (action: ActionLike) => void;
42
37
  /** `Gio.ActionMap.lookup_action`: the window's own action, or `null`. */
@@ -127,4 +122,4 @@ export class GtkApplicationWindow extends GtkWindow {
127
122
 
128
123
  customElements.define('gtk-application-window', GtkApplicationWindow);
129
124
 
130
- defineWindowApplication(GtkApplicationWindow.prototype);
125
+ installActionMap(GtkApplicationWindow.prototype);
@@ -38,6 +38,7 @@
38
38
  import { glibClamp, labelYalignAlignItems } from '@gjsify/adwaita-core';
39
39
 
40
40
  import { bindSlottedChildren } from '../slotted-children.js';
41
+ import { WidgetElement } from '../widget-element.js';
41
42
 
42
43
  /** `Gtk.AspectFrame:ratio`'s pspec range and default (gtkaspectframe.c:124-125, :172-175). */
43
44
  const RATIO_MIN = 0.0001;
@@ -58,7 +59,7 @@ function normalizeRatio(value: string | null): number {
58
59
  return Number.isFinite(parsed) ? glibClamp(parsed, RATIO_MIN, RATIO_MAX) : RATIO_DEFAULT;
59
60
  }
60
61
 
61
- export class GtkAspectFrame extends HTMLElement {
62
+ export class GtkAspectFrame extends WidgetElement {
62
63
  static get observedAttributes() {
63
64
  return ['ratio', 'xalign', 'yalign', 'obey-child'];
64
65
  }