@gjsify/adwaita-web 0.53.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/dist/adwaita-web.css +8070 -3037
  2. package/dist/adwaita-web.css.map +1 -1
  3. package/lib/types/adw-application-window.spec.d.ts +1 -0
  4. package/lib/types/adw-bin.spec.d.ts +1 -0
  5. package/lib/types/adw-breakpoint-bin.spec.d.ts +1 -0
  6. package/lib/types/adw-clamp-scrollable.spec.d.ts +1 -0
  7. package/lib/types/adw-multi-layout-view.spec.d.ts +1 -0
  8. package/lib/types/adw-preferences-row.spec.d.ts +1 -0
  9. package/lib/types/adw-shortcuts.spec.d.ts +1 -0
  10. package/lib/types/adw-tab-bar.spec.d.ts +1 -0
  11. package/lib/types/adw-tab-button.spec.d.ts +1 -0
  12. package/lib/types/adw-tab-overview.spec.d.ts +1 -0
  13. package/lib/types/adw-view-switcher-sidebar.spec.d.ts +1 -0
  14. package/lib/types/adw-window.spec.d.ts +1 -0
  15. package/lib/types/breakpoints.d.ts +14 -3
  16. package/lib/types/construct-vectors.spec.d.ts +1 -0
  17. package/lib/types/elements/adw-application-window.d.ts +27 -0
  18. package/lib/types/elements/adw-bin.d.ts +17 -0
  19. package/lib/types/elements/adw-breakpoint-bin.d.ts +67 -0
  20. package/lib/types/elements/adw-clamp-scrollable.d.ts +38 -0
  21. package/lib/types/elements/adw-dialog.d.ts +10 -0
  22. package/lib/types/elements/adw-layout-slot.d.ts +19 -0
  23. package/lib/types/elements/adw-multi-layout-view.d.ts +101 -0
  24. package/lib/types/elements/adw-preferences-row.d.ts +31 -0
  25. package/lib/types/elements/adw-shortcuts-dialog.d.ts +13 -0
  26. package/lib/types/elements/adw-shortcuts-item.d.ts +36 -0
  27. package/lib/types/elements/adw-shortcuts-section.d.ts +14 -0
  28. package/lib/types/elements/adw-sidebar.d.ts +5 -0
  29. package/lib/types/elements/adw-switch-row.d.ts +3 -0
  30. package/lib/types/elements/adw-tab-bar.d.ts +108 -0
  31. package/lib/types/elements/adw-tab-button.d.ts +32 -0
  32. package/lib/types/elements/adw-tab-overview.d.ts +199 -0
  33. package/lib/types/elements/adw-tab-view.d.ts +19 -23
  34. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +84 -0
  35. package/lib/types/elements/adw-window.d.ts +40 -0
  36. package/lib/types/elements/gtk-about-dialog.d.ts +146 -0
  37. package/lib/types/elements/gtk-application-window.d.ts +34 -0
  38. package/lib/types/elements/gtk-aspect-frame.d.ts +27 -0
  39. package/lib/types/elements/gtk-button.d.ts +9 -0
  40. package/lib/types/elements/gtk-calendar.d.ts +159 -0
  41. package/lib/types/elements/gtk-center-box.d.ts +39 -0
  42. package/lib/types/elements/gtk-color-dialog-button.d.ts +69 -0
  43. package/lib/types/elements/gtk-column-view.d.ts +50 -0
  44. package/lib/types/elements/gtk-drag-icon.d.ts +78 -0
  45. package/lib/types/elements/gtk-drawing-area.d.ts +95 -0
  46. package/lib/types/elements/gtk-editable-label.d.ts +33 -0
  47. package/lib/types/elements/gtk-emoji-chooser.d.ts +84 -0
  48. package/lib/types/elements/gtk-entry.d.ts +20 -1
  49. package/lib/types/elements/gtk-expander.d.ts +49 -0
  50. package/lib/types/elements/gtk-fixed.d.ts +13 -0
  51. package/lib/types/elements/gtk-flow-box-child.d.ts +14 -0
  52. package/lib/types/elements/gtk-flow-box.d.ts +87 -0
  53. package/lib/types/elements/gtk-font-dialog-button.d.ts +83 -0
  54. package/lib/types/elements/gtk-frame.d.ts +24 -0
  55. package/lib/types/elements/gtk-gl-area.d.ts +136 -0
  56. package/lib/types/elements/gtk-graphics-offload.d.ts +24 -0
  57. package/lib/types/elements/gtk-grid-view.d.ts +39 -0
  58. package/lib/types/elements/gtk-grid.d.ts +27 -0
  59. package/lib/types/elements/gtk-header-bar.d.ts +60 -0
  60. package/lib/types/elements/gtk-inscription.d.ts +64 -0
  61. package/lib/types/elements/gtk-label.d.ts +3 -0
  62. package/lib/types/elements/gtk-level-bar.d.ts +59 -0
  63. package/lib/types/elements/gtk-link-button.d.ts +29 -0
  64. package/lib/types/elements/gtk-list-box-row.d.ts +54 -0
  65. package/lib/types/elements/gtk-list-box.d.ts +100 -0
  66. package/lib/types/elements/gtk-list-view.d.ts +73 -0
  67. package/lib/types/elements/gtk-media-controls.d.ts +142 -0
  68. package/lib/types/elements/gtk-notebook.d.ts +148 -0
  69. package/lib/types/elements/gtk-overlay.d.ts +22 -0
  70. package/lib/types/elements/gtk-page-setup-unix-dialog.d.ts +87 -0
  71. package/lib/types/elements/gtk-paned.d.ts +121 -0
  72. package/lib/types/elements/gtk-password-entry.d.ts +27 -0
  73. package/lib/types/elements/gtk-picture.d.ts +66 -0
  74. package/lib/types/elements/gtk-popover-bin.d.ts +82 -0
  75. package/lib/types/elements/gtk-popover-menu-bar.d.ts +66 -0
  76. package/lib/types/elements/gtk-popover-menu.d.ts +83 -0
  77. package/lib/types/elements/gtk-popover.d.ts +28 -3
  78. package/lib/types/elements/gtk-print-unix-dialog.d.ts +167 -0
  79. package/lib/types/elements/gtk-revealer.d.ts +55 -0
  80. package/lib/types/elements/gtk-scale-button.d.ts +59 -0
  81. package/lib/types/elements/gtk-scale.d.ts +98 -0
  82. package/lib/types/elements/gtk-scrollbar.d.ts +124 -0
  83. package/lib/types/elements/gtk-scrolled-window.d.ts +121 -0
  84. package/lib/types/elements/gtk-search-bar.d.ts +39 -0
  85. package/lib/types/elements/gtk-search-entry.d.ts +27 -0
  86. package/lib/types/elements/gtk-separator.d.ts +10 -0
  87. package/lib/types/elements/gtk-spin-button.d.ts +94 -0
  88. package/lib/types/elements/gtk-spinner.d.ts +14 -0
  89. package/lib/types/elements/gtk-stack-sidebar.d.ts +43 -0
  90. package/lib/types/elements/gtk-stack-switcher.d.ts +58 -0
  91. package/lib/types/elements/gtk-stack.d.ts +154 -0
  92. package/lib/types/elements/gtk-switch.d.ts +4 -1
  93. package/lib/types/elements/gtk-text-view.d.ts +62 -0
  94. package/lib/types/elements/gtk-text.d.ts +45 -0
  95. package/lib/types/elements/gtk-toggle-button.d.ts +45 -0
  96. package/lib/types/elements/gtk-tree-expander.d.ts +38 -0
  97. package/lib/types/elements/gtk-video.d.ts +97 -0
  98. package/lib/types/elements/gtk-viewport.d.ts +84 -0
  99. package/lib/types/elements/gtk-window-controls.d.ts +80 -0
  100. package/lib/types/elements/gtk-window-handle.d.ts +39 -0
  101. package/lib/types/elements/gtk-window.d.ts +97 -0
  102. package/lib/types/elements/justification.d.ts +2 -0
  103. package/lib/types/elements/popover-menu.d.ts +18 -0
  104. package/lib/types/elements/roving-focus.d.ts +29 -1
  105. package/lib/types/emoji-data.d.ts +38 -0
  106. package/lib/types/font-description.d.ts +96 -0
  107. package/lib/types/gtk-about-dialog.spec.d.ts +1 -0
  108. package/lib/types/gtk-action-bar.spec.d.ts +1 -0
  109. package/lib/types/gtk-application-window.spec.d.ts +1 -0
  110. package/lib/types/gtk-aspect-frame.spec.d.ts +1 -0
  111. package/lib/types/gtk-calendar.spec.d.ts +1 -0
  112. package/lib/types/gtk-center-box.spec.d.ts +1 -0
  113. package/lib/types/gtk-color-dialog-button.spec.d.ts +1 -0
  114. package/lib/types/gtk-column-view.spec.d.ts +1 -0
  115. package/lib/types/gtk-drag-icon.spec.d.ts +1 -0
  116. package/lib/types/gtk-drawing-area.spec.d.ts +1 -0
  117. package/lib/types/gtk-editable-label.spec.d.ts +1 -0
  118. package/lib/types/gtk-emoji-chooser.spec.d.ts +1 -0
  119. package/lib/types/gtk-expander.spec.d.ts +1 -0
  120. package/lib/types/gtk-fixed.spec.d.ts +1 -0
  121. package/lib/types/gtk-flow-box.spec.d.ts +1 -0
  122. package/lib/types/gtk-font-dialog-button.spec.d.ts +1 -0
  123. package/lib/types/gtk-frame.spec.d.ts +1 -0
  124. package/lib/types/gtk-gl-area.spec.d.ts +1 -0
  125. package/lib/types/gtk-graphics-offload.spec.d.ts +1 -0
  126. package/lib/types/gtk-grid-view.spec.d.ts +1 -0
  127. package/lib/types/gtk-grid.spec.d.ts +1 -0
  128. package/lib/types/gtk-header-bar.spec.d.ts +1 -0
  129. package/lib/types/gtk-inscription.spec.d.ts +1 -0
  130. package/lib/types/gtk-level-bar.spec.d.ts +1 -0
  131. package/lib/types/gtk-link-button.spec.d.ts +1 -0
  132. package/lib/types/gtk-list-box.spec.d.ts +1 -0
  133. package/lib/types/gtk-list-view.spec.d.ts +1 -0
  134. package/lib/types/gtk-media-controls.spec.d.ts +1 -0
  135. package/lib/types/gtk-notebook.spec.d.ts +1 -0
  136. package/lib/types/gtk-overlay.spec.d.ts +1 -0
  137. package/lib/types/gtk-paned.spec.d.ts +1 -0
  138. package/lib/types/gtk-password-entry.spec.d.ts +1 -0
  139. package/lib/types/gtk-picture.spec.d.ts +1 -0
  140. package/lib/types/gtk-popover-bin.spec.d.ts +1 -0
  141. package/lib/types/gtk-popover-menu-bar.spec.d.ts +1 -0
  142. package/lib/types/gtk-popover-menu.spec.d.ts +1 -0
  143. package/lib/types/gtk-popover-role.spec.d.ts +1 -0
  144. package/lib/types/gtk-popover.spec.d.ts +1 -0
  145. package/lib/types/gtk-print-dialogs.spec.d.ts +1 -0
  146. package/lib/types/gtk-revealer.spec.d.ts +1 -0
  147. package/lib/types/gtk-scale-button.spec.d.ts +1 -0
  148. package/lib/types/gtk-scale.spec.d.ts +1 -0
  149. package/lib/types/gtk-scrollbar.spec.d.ts +1 -0
  150. package/lib/types/gtk-scrolled-window.spec.d.ts +1 -0
  151. package/lib/types/gtk-search-bar.spec.d.ts +1 -0
  152. package/lib/types/gtk-search-entry.spec.d.ts +1 -0
  153. package/lib/types/gtk-separator.spec.d.ts +1 -0
  154. package/lib/types/gtk-spin-button.spec.d.ts +1 -0
  155. package/lib/types/gtk-spinner.spec.d.ts +1 -0
  156. package/lib/types/gtk-stack-sidebar.spec.d.ts +1 -0
  157. package/lib/types/gtk-stack-switcher.spec.d.ts +1 -0
  158. package/lib/types/gtk-stack.spec.d.ts +1 -0
  159. package/lib/types/gtk-text-view.spec.d.ts +1 -0
  160. package/lib/types/gtk-text.spec.d.ts +1 -0
  161. package/lib/types/gtk-toggle-button.spec.d.ts +1 -0
  162. package/lib/types/gtk-tree-expander.spec.d.ts +1 -0
  163. package/lib/types/gtk-video.spec.d.ts +1 -0
  164. package/lib/types/gtk-viewport.spec.d.ts +1 -0
  165. package/lib/types/gtk-window-controls.spec.d.ts +1 -0
  166. package/lib/types/gtk-window-handle.spec.d.ts +1 -0
  167. package/lib/types/gtk-window.spec.d.ts +1 -0
  168. package/lib/types/index.d.ts +4 -1
  169. package/lib/types/list-view-dom.d.ts +44 -0
  170. package/lib/types/namespace/adw.d.ts +12 -0
  171. package/lib/types/namespace/gtk.d.ts +61 -0
  172. package/lib/types/page-setup.d.ts +100 -0
  173. package/lib/types/scroll-shading.d.ts +15 -1
  174. package/lib/types/shared-tree-builder.d.ts +30 -2
  175. package/lib/types/signals.d.ts +4 -0
  176. package/lib/types/styles.generated.d.ts +1 -1
  177. package/lib/types/tab-chip.d.ts +73 -0
  178. package/lib/types/template-classes.d.ts +11 -0
  179. package/package.json +12 -8
  180. package/scss/_action_row.scss +2 -2
  181. package/scss/_application_window.scss +26 -0
  182. package/scss/_aspect_frame.scss +25 -0
  183. package/scss/_bin.scss +26 -0
  184. package/scss/_button.scss +45 -0
  185. package/scss/_calendar.scss +176 -0
  186. package/scss/_center_box.scss +25 -0
  187. package/scss/_checks.scss +6 -1
  188. package/scss/_clamp_scrollable.scss +28 -0
  189. package/scss/_color_button.scss +67 -0
  190. package/scss/_column_view.scss +126 -0
  191. package/scss/_drag_icon.scss +55 -0
  192. package/scss/_drawing.scss +85 -0
  193. package/scss/_emoji_chooser.scss +213 -0
  194. package/scss/_entry.scss +13 -5
  195. package/scss/_entry_row.scss +1 -1
  196. package/scss/_expander.scss +113 -0
  197. package/scss/_fixed.scss +29 -0
  198. package/scss/_flow_box.scss +94 -0
  199. package/scss/_font_button.scss +63 -0
  200. package/scss/_frame.scss +41 -0
  201. package/scss/_grid.scss +19 -0
  202. package/scss/_grid_view.scss +46 -0
  203. package/scss/_gtk_about_dialog.scss +186 -0
  204. package/scss/_headerbar.scss +132 -0
  205. package/scss/_icons.generated.scss +186 -0
  206. package/scss/_inscription.scss +125 -0
  207. package/scss/_level_bar.scss +190 -0
  208. package/scss/_link.scss +82 -0
  209. package/scss/_list_box.scss +88 -0
  210. package/scss/_list_view.scss +96 -0
  211. package/scss/_media_controls.scss +139 -0
  212. package/scss/_overlay.scss +68 -0
  213. package/scss/_paned.scss +130 -0
  214. package/scss/_password_entry.scss +83 -0
  215. package/scss/_picture.scss +80 -0
  216. package/scss/_popover_bin.scss +53 -0
  217. package/scss/_popover_menu_bar.scss +104 -0
  218. package/scss/_preferences_row.scss +51 -0
  219. package/scss/_print_dialogs.scss +328 -0
  220. package/scss/_reset.scss +21 -19
  221. package/scss/_revealer.scss +37 -0
  222. package/scss/_row.scss +20 -5
  223. package/scss/_scale.scss +298 -0
  224. package/scss/_scale_button.scss +167 -0
  225. package/scss/_scrollbar.scss +230 -0
  226. package/scss/_scrolled_window.scss +131 -0
  227. package/scss/_search_bar.scss +118 -0
  228. package/scss/_search_entry.scss +86 -0
  229. package/scss/_separator.scss +44 -0
  230. package/scss/_shortcuts_dialog.scss +100 -0
  231. package/scss/_spin_button.scss +172 -0
  232. package/scss/_spin_row.scss +56 -8
  233. package/scss/_spinner.scss +85 -4
  234. package/scss/_stack.scss +729 -0
  235. package/scss/_switch.scss +13 -5
  236. package/scss/_switch_row.scss +10 -0
  237. package/scss/_tab_bar.scss +317 -0
  238. package/scss/_tab_button.scss +98 -0
  239. package/scss/_tab_overview.scss +483 -0
  240. package/scss/_text.scss +182 -0
  241. package/scss/_theme.scss +1 -1
  242. package/scss/_tree_expander.scss +62 -0
  243. package/scss/_variables.scss +43 -21
  244. package/scss/_video.scss +146 -0
  245. package/scss/_view_switcher_sidebar.scss +112 -0
  246. package/scss/_viewport.scss +50 -0
  247. package/scss/_window.scss +118 -1
  248. package/scss/_window_handle.scss +20 -0
  249. package/scss/adwaita-skin.scss +109 -0
  250. package/src/adw-action-rows.spec.ts +76 -0
  251. package/src/adw-application-window.spec.ts +118 -0
  252. package/src/adw-bin.spec.ts +75 -0
  253. package/src/adw-breakpoint-bin.spec.ts +324 -0
  254. package/src/adw-clamp-scrollable.spec.ts +189 -0
  255. package/src/adw-multi-layout-view.spec.ts +243 -0
  256. package/src/adw-preferences-row.spec.ts +164 -0
  257. package/src/adw-row-state.spec.ts +142 -0
  258. package/src/adw-shortcuts.spec.ts +155 -0
  259. package/src/adw-tab-bar.spec.ts +287 -0
  260. package/src/adw-tab-button.spec.ts +101 -0
  261. package/src/adw-tab-overview.spec.ts +443 -0
  262. package/src/adw-view-switcher-sidebar.spec.ts +281 -0
  263. package/src/adw-window.spec.ts +129 -0
  264. package/src/breakpoints.ts +25 -8
  265. package/src/capabilities.d.mts +3 -0
  266. package/src/capabilities.mjs +18 -0
  267. package/src/connect-lifecycle.spec.ts +12 -0
  268. package/src/construct-vectors.spec.ts +175 -0
  269. package/src/elements/adw-application-window.ts +154 -0
  270. package/src/elements/adw-bin.ts +101 -0
  271. package/src/elements/adw-breakpoint-bin.ts +287 -0
  272. package/src/elements/adw-clamp-scrollable.ts +207 -0
  273. package/src/elements/adw-dialog.ts +19 -0
  274. package/src/elements/adw-layout-slot.ts +95 -0
  275. package/src/elements/adw-multi-layout-view.ts +326 -0
  276. package/src/elements/adw-preferences-row.ts +150 -0
  277. package/src/elements/adw-shortcuts-dialog.ts +52 -0
  278. package/src/elements/adw-shortcuts-item.ts +171 -0
  279. package/src/elements/adw-shortcuts-section.ts +86 -0
  280. package/src/elements/adw-sidebar.ts +42 -3
  281. package/src/elements/adw-switch-row.ts +28 -1
  282. package/src/elements/adw-tab-bar.ts +529 -0
  283. package/src/elements/adw-tab-button.ts +194 -0
  284. package/src/elements/adw-tab-overview.ts +1011 -0
  285. package/src/elements/adw-tab-view.ts +66 -145
  286. package/src/elements/adw-toggle-group.ts +20 -5
  287. package/src/elements/adw-view-stack.ts +18 -0
  288. package/src/elements/adw-view-switcher-sidebar.ts +332 -0
  289. package/src/elements/adw-window.ts +185 -11
  290. package/src/elements/checks.ts +35 -8
  291. package/src/elements/gtk-about-dialog.ts +811 -0
  292. package/src/elements/gtk-application-window.ts +108 -0
  293. package/src/elements/gtk-aspect-frame.ts +160 -0
  294. package/src/elements/gtk-button.ts +12 -0
  295. package/src/elements/gtk-calendar.ts +757 -0
  296. package/src/elements/gtk-center-box.ts +184 -0
  297. package/src/elements/gtk-color-dialog-button.ts +278 -0
  298. package/src/elements/gtk-column-view.ts +320 -0
  299. package/src/elements/gtk-drag-icon.ts +257 -0
  300. package/src/elements/gtk-drawing-area.ts +303 -0
  301. package/src/elements/gtk-editable-label.ts +204 -0
  302. package/src/elements/gtk-emoji-chooser.ts +542 -0
  303. package/src/elements/gtk-entry.ts +39 -5
  304. package/src/elements/gtk-expander.ts +301 -0
  305. package/src/elements/gtk-fixed.ts +99 -0
  306. package/src/elements/gtk-flow-box-child.ts +68 -0
  307. package/src/elements/gtk-flow-box.ts +480 -0
  308. package/src/elements/gtk-font-dialog-button.ts +432 -0
  309. package/src/elements/gtk-frame.ts +174 -0
  310. package/src/elements/gtk-gl-area.ts +476 -0
  311. package/src/elements/gtk-graphics-offload.ts +130 -0
  312. package/src/elements/gtk-grid-view.ts +168 -0
  313. package/src/elements/gtk-grid.ts +127 -0
  314. package/src/elements/gtk-header-bar.ts +273 -0
  315. package/src/elements/gtk-inscription.ts +387 -0
  316. package/src/elements/gtk-label.ts +19 -11
  317. package/src/elements/gtk-level-bar.ts +323 -0
  318. package/src/elements/gtk-link-button.ts +138 -0
  319. package/src/elements/gtk-list-box-row.ts +195 -0
  320. package/src/elements/gtk-list-box.ts +413 -0
  321. package/src/elements/gtk-list-view.ts +370 -0
  322. package/src/elements/gtk-media-controls.ts +509 -0
  323. package/src/elements/gtk-notebook.ts +664 -0
  324. package/src/elements/gtk-overlay.ts +149 -0
  325. package/src/elements/gtk-page-setup-unix-dialog.ts +420 -0
  326. package/src/elements/gtk-paned.ts +597 -0
  327. package/src/elements/gtk-password-entry.ts +170 -0
  328. package/src/elements/gtk-picture.ts +254 -0
  329. package/src/elements/gtk-popover-bin.ts +332 -0
  330. package/src/elements/gtk-popover-menu-bar.ts +355 -0
  331. package/src/elements/gtk-popover-menu.ts +339 -0
  332. package/src/elements/gtk-popover.ts +92 -10
  333. package/src/elements/gtk-print-unix-dialog.ts +989 -0
  334. package/src/elements/gtk-progress-bar.ts +24 -11
  335. package/src/elements/gtk-revealer.ts +406 -0
  336. package/src/elements/gtk-scale-button.ts +358 -0
  337. package/src/elements/gtk-scale.ts +492 -0
  338. package/src/elements/gtk-scrollbar.ts +528 -0
  339. package/src/elements/gtk-scrolled-window.ts +642 -0
  340. package/src/elements/gtk-search-bar.ts +200 -0
  341. package/src/elements/gtk-search-entry.ts +172 -0
  342. package/src/elements/gtk-separator.ts +52 -0
  343. package/src/elements/gtk-spin-button.ts +475 -0
  344. package/src/elements/gtk-spinner.ts +126 -0
  345. package/src/elements/gtk-stack-sidebar.ts +212 -0
  346. package/src/elements/gtk-stack-switcher.ts +279 -0
  347. package/src/elements/gtk-stack.ts +748 -0
  348. package/src/elements/gtk-switch.ts +52 -19
  349. package/src/elements/gtk-text-view.ts +290 -0
  350. package/src/elements/gtk-text.ts +219 -0
  351. package/src/elements/gtk-toggle-button.ts +239 -0
  352. package/src/elements/gtk-tree-expander.ts +243 -0
  353. package/src/elements/gtk-video.ts +423 -0
  354. package/src/elements/gtk-viewport.ts +277 -0
  355. package/src/elements/gtk-window-controls.ts +341 -0
  356. package/src/elements/gtk-window-handle.ts +221 -0
  357. package/src/elements/gtk-window.ts +366 -0
  358. package/src/elements/justification.ts +24 -0
  359. package/src/elements/popover-menu.ts +24 -0
  360. package/src/elements/roving-focus.ts +53 -21
  361. package/src/emoji-data.ts +577 -0
  362. package/src/entry-rows.spec.ts +31 -0
  363. package/src/font-description.ts +238 -0
  364. package/src/gtk-about-dialog.spec.ts +250 -0
  365. package/src/gtk-action-bar.spec.ts +89 -0
  366. package/src/gtk-application-window.spec.ts +107 -0
  367. package/src/gtk-aspect-frame.spec.ts +114 -0
  368. package/src/gtk-calendar.spec.ts +589 -0
  369. package/src/gtk-center-box.spec.ts +125 -0
  370. package/src/gtk-color-dialog-button.spec.ts +141 -0
  371. package/src/gtk-column-view.spec.ts +154 -0
  372. package/src/gtk-drag-icon.spec.ts +190 -0
  373. package/src/gtk-drawing-area.spec.ts +211 -0
  374. package/src/gtk-editable-label.spec.ts +190 -0
  375. package/src/gtk-emoji-chooser.spec.ts +173 -0
  376. package/src/gtk-entry.spec.ts +23 -0
  377. package/src/gtk-expander.spec.ts +170 -0
  378. package/src/gtk-fixed.spec.ts +97 -0
  379. package/src/gtk-flow-box.spec.ts +289 -0
  380. package/src/gtk-font-dialog-button.spec.ts +166 -0
  381. package/src/gtk-frame.spec.ts +119 -0
  382. package/src/gtk-gl-area.spec.ts +361 -0
  383. package/src/gtk-graphics-offload.spec.ts +119 -0
  384. package/src/gtk-grid-view.spec.ts +106 -0
  385. package/src/gtk-grid.spec.ts +122 -0
  386. package/src/gtk-header-bar.spec.ts +202 -0
  387. package/src/gtk-inscription.spec.ts +235 -0
  388. package/src/gtk-level-bar.spec.ts +199 -0
  389. package/src/gtk-link-button.spec.ts +117 -0
  390. package/src/gtk-list-box.spec.ts +422 -0
  391. package/src/gtk-list-view.spec.ts +203 -0
  392. package/src/gtk-media-controls.spec.ts +295 -0
  393. package/src/gtk-notebook.spec.ts +546 -0
  394. package/src/gtk-overlay.spec.ts +141 -0
  395. package/src/gtk-paned.spec.ts +267 -0
  396. package/src/gtk-password-entry.spec.ts +150 -0
  397. package/src/gtk-picture.spec.ts +172 -0
  398. package/src/gtk-popover-bin.spec.ts +229 -0
  399. package/src/gtk-popover-menu-bar.spec.ts +296 -0
  400. package/src/gtk-popover-menu.spec.ts +261 -0
  401. package/src/gtk-popover-role.spec.ts +138 -0
  402. package/src/gtk-popover.spec.ts +264 -0
  403. package/src/gtk-print-dialogs.spec.ts +251 -0
  404. package/src/gtk-revealer.spec.ts +164 -0
  405. package/src/gtk-scale-button.spec.ts +218 -0
  406. package/src/gtk-scale.spec.ts +213 -0
  407. package/src/gtk-scrollbar.spec.ts +244 -0
  408. package/src/gtk-scrolled-window.spec.ts +262 -0
  409. package/src/gtk-search-bar.spec.ts +179 -0
  410. package/src/gtk-search-entry.spec.ts +142 -0
  411. package/src/gtk-separator.spec.ts +74 -0
  412. package/src/gtk-spin-button.spec.ts +186 -0
  413. package/src/gtk-spinner.spec.ts +130 -0
  414. package/src/gtk-stack-sidebar.spec.ts +217 -0
  415. package/src/gtk-stack-switcher.spec.ts +249 -0
  416. package/src/gtk-stack.spec.ts +432 -0
  417. package/src/gtk-text-view.spec.ts +189 -0
  418. package/src/gtk-text.spec.ts +163 -0
  419. package/src/gtk-toggle-button.spec.ts +186 -0
  420. package/src/gtk-tree-expander.spec.ts +201 -0
  421. package/src/gtk-video.spec.ts +240 -0
  422. package/src/gtk-viewport.spec.ts +140 -0
  423. package/src/gtk-window-controls.spec.ts +232 -0
  424. package/src/gtk-window-handle.spec.ts +158 -0
  425. package/src/gtk-window.spec.ts +190 -0
  426. package/src/index.ts +9 -1
  427. package/src/keyboard-operable.spec.ts +33 -1
  428. package/src/list-view-dom.ts +121 -0
  429. package/src/namespace/adw.ts +12 -0
  430. package/src/namespace/gtk.ts +61 -0
  431. package/src/page-setup.ts +222 -0
  432. package/src/scroll-shading.ts +18 -1
  433. package/src/shared-tree-builder.ts +263 -21
  434. package/src/signals.ts +15 -0
  435. package/src/source-view/theme.ts +11 -5
  436. package/src/style-classes.spec.ts +9 -8
  437. package/src/styles.generated.ts +1 -1
  438. package/src/tab-chip.ts +200 -0
  439. package/src/template-classes.ts +45 -0
  440. package/src/test.browser.mts +152 -0
@@ -0,0 +1,212 @@
1
+ // <gtk-stack-sidebar> — a vertical list of a <gtk-stack>'s pages, the sidebar
2
+ // counterpart of <gtk-stack-switcher>. It is the older of the two: the switcher
3
+ // is a row of buttons, this is a listbox of rows, and both bind to a stack's
4
+ // `pages` selection model the same way.
5
+ //
6
+ // IT OWNS NO PAGES. C binds the stack through `set_stack`, reads its `pages`
7
+ // model and builds one `GtkListBoxRow` per page (gtkstacksidebar.c:422-448,
8
+ // :252-275). `stack` here is an id reference, like `<label for>`, because a
9
+ // browser attribute cannot carry a widget — the same spelling
10
+ // `<adw-view-switcher-bar>` uses.
11
+ //
12
+ // WHAT A ROW SHOWS, transcribed from `update_row` (gtkstacksidebar.c:175-197):
13
+ // a LABEL and nothing else — `update_row` reads `title`, `needs-attention` and
14
+ // `visible` but never `icon-name`, so a page with an icon and no title gets no
15
+ // row text at all. The row is visible when the page is visible AND the title is
16
+ // non-NULL (`:186`), which is the one place this and the switcher differ: the
17
+ // switcher also accepts an icon there (gtkstackswitcher.c:200), the sidebar does
18
+ // not. `needs-attention` puts the `.needs-attention` class on the ROW (`:188-191`).
19
+ //
20
+ // The list carries C's own style classes: `.navigation-sidebar` on the LIST and
21
+ // `.sidebar` on the widget (gtkstacksidebar.c:155, :163), and the list's
22
+ // accessible label is the translated "Sidebar" (`:157-159`).
23
+ //
24
+ // THE TWO-WAY BINDING. A selected row selects its page
25
+ // (`gtk_stack_sidebar_row_selected`, gtkstacksidebar.c:130-143) and the stack's
26
+ // side is `selection_changed_cb`, which selects or unselects the rows in the
27
+ // changed range (`:317-338`). A selection change does NOT rebuild — an
28
+ // `items-changed` does (`:307-311`) — so the rows survive a page change and keep
29
+ // keyboard focus.
30
+ //
31
+ // A11Y: the list is a `listbox` and each row a `link`, which is what a
32
+ // navigable sidebar is; C's row carries `GTK_ACCESSIBLE_RELATION_LABELLED_BY`
33
+ // the label (`:262-266`) and the list's own label is "Sidebar".
34
+ //
35
+ // Events: `notify::stack` (CustomEvent, bubbles, detail `{ stack }`).
36
+ //
37
+ // Reference: refs/gtk/gtk/gtkstacksidebar.c
38
+ // Copyright (c) The GTK Team. LGPLv2.1+.
39
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
40
+
41
+ import type { GtkStack } from './gtk-stack.js';
42
+
43
+ /** The `GtkStackPageInfo` half this element reads — it never looks inside `child`. */
44
+ interface SidebarPage {
45
+ name: string;
46
+ title: string | null;
47
+ needsAttention: boolean;
48
+ visible: boolean;
49
+ child: HTMLElement;
50
+ }
51
+
52
+ export class GtkStackSidebar extends HTMLElement {
53
+ private _stack: GtkStack | null = null;
54
+ private _list!: HTMLDivElement;
55
+ private _initialized = false;
56
+ private _rows: HTMLButtonElement[] = [];
57
+ private readonly _onStackChange = (): void => this._rebuild();
58
+
59
+ static get observedAttributes() {
60
+ return ['stack'];
61
+ }
62
+
63
+ /** `Gtk.StackSidebar:stack` — the stack this sidebar drives, or null. */
64
+ get stack(): GtkStack | null {
65
+ return this._stack;
66
+ }
67
+
68
+ set stack(value: GtkStack | string | null) {
69
+ this.setStack(typeof value === 'string' ? this._resolve(value) : value);
70
+ }
71
+
72
+ /** Rebuild the rows by hand, for a consumer that mutated a page in place. */
73
+ refresh(): void {
74
+ this._rebuild();
75
+ }
76
+
77
+ connectedCallback() {
78
+ if (this._initialized) {
79
+ this._bindStack();
80
+ this._rebuild();
81
+ return;
82
+ }
83
+ this._initialized = true;
84
+ this._list = document.createElement('div');
85
+ this._list.className = 'adw-stack-sidebar-list navigation-sidebar';
86
+ this._list.setAttribute('role', 'listbox');
87
+ // The translated "Sidebar" of gtkstacksidebar.c:157-159.
88
+ this._list.setAttribute('aria-label', 'Sidebar');
89
+ this.replaceChildren(this._list);
90
+ // `.sidebar` is on the widget itself (gtkstacksidebar.c:163).
91
+ this.classList.add('sidebar');
92
+
93
+ const ref = this.getAttribute('stack');
94
+ if (ref) {
95
+ this.setStack(this._resolve(ref));
96
+ return;
97
+ }
98
+ this._rebuild();
99
+ }
100
+
101
+ disconnectedCallback() {
102
+ this._unbindStack();
103
+ }
104
+
105
+ attributeChangedCallback(name: string, _old: string | null, value: string | null) {
106
+ if (!this._initialized || name !== 'stack') return;
107
+ this.setStack(value === null ? null : this._resolve(value));
108
+ }
109
+
110
+ /** Bind to a stack element (or null). Unbinds the previous one, as `set_stack` does. */
111
+ setStack(stack: GtkStack | null): void {
112
+ if (stack === this._stack) return;
113
+ this._unbindStack();
114
+ this._stack = stack;
115
+ this._bindStack();
116
+ this._rebuild();
117
+ this.dispatchEvent(new CustomEvent('notify::stack', { bubbles: true, detail: { stack: this._stack } }));
118
+ }
119
+
120
+ private _resolve(id: string | null): GtkStack | null {
121
+ if (!id) return null;
122
+ return (document.getElementById(id) as GtkStack | null) ?? null;
123
+ }
124
+
125
+ private _bindStack(): void {
126
+ this._stack?.addEventListener('items-changed', this._onStackChange);
127
+ this._stack?.addEventListener('selection-changed', this._onStackChange);
128
+ this._stack?.addEventListener('page-updated', this._onStackChange);
129
+ }
130
+
131
+ private _unbindStack(): void {
132
+ this._stack?.removeEventListener('items-changed', this._onStackChange);
133
+ this._stack?.removeEventListener('selection-changed', this._onStackChange);
134
+ this._stack?.removeEventListener('page-updated', this._onStackChange);
135
+ }
136
+
137
+ private _pages(): SidebarPage[] {
138
+ const stack = this._stack as (GtkStack & { pages?: SidebarPage[] }) | null;
139
+ return stack?.pages ?? [];
140
+ }
141
+
142
+ /**
143
+ * `update_row`'s visibility rule (gtkstacksidebar.c:186): the page is visible AND
144
+ * carries a title. There is no icon fallback — `update_row` never reads `icon-name`,
145
+ * which is the one rule where this sidebar and the switcher disagree.
146
+ */
147
+ private _visible(page: SidebarPage): boolean {
148
+ return page.visible && page.title !== null;
149
+ }
150
+
151
+ private _selectedIndex(): number {
152
+ const pages = this._pages();
153
+ const name = this._stack?.visibleChildName ?? null;
154
+ return name === null ? -1 : pages.findIndex((page) => page.name === name);
155
+ }
156
+
157
+ /**
158
+ * An `items-changed` rebuilds the list wholesale (gtkstacksidebar.c:307-311) and a
159
+ * `selection-changed` does not (:317-338), so the rows are recreated ONLY when the
160
+ * page COUNT moves.
161
+ */
162
+ private _rebuild(): void {
163
+ if (!this._initialized) return;
164
+ const pages = this._pages();
165
+ if (pages.length !== this._rows.length) {
166
+ this._list.replaceChildren();
167
+ this._rows = pages.map(() => this._buildRow());
168
+ this._list.append(...this._rows);
169
+ }
170
+ const selected = this._selectedIndex();
171
+ pages.forEach((page, index) => {
172
+ const row = this._rows[index];
173
+ if (!row) return;
174
+ const label = row.querySelector('.adw-stack-sidebar-title');
175
+ if (label) label.textContent = page.title ?? '';
176
+ row.hidden = !this._visible(page);
177
+ row.classList.toggle('needs-attention', page.needsAttention);
178
+ row.classList.toggle('selected', index === selected);
179
+ row.setAttribute('aria-selected', String(index === selected));
180
+ });
181
+ }
182
+
183
+ private _buildRow(): HTMLButtonElement {
184
+ const row = document.createElement('button');
185
+ row.type = 'button';
186
+ row.className = 'adw-stack-sidebar-row';
187
+ // A navigable sidebar row is a LINK, which is what a `GtkListBoxRow` with an
188
+ // activatable child presents as; the label is what names it (gtkstacksidebar.c:262).
189
+ row.setAttribute('role', 'link');
190
+ const label = document.createElement('span');
191
+ label.className = 'adw-stack-sidebar-title';
192
+ row.appendChild(label);
193
+ row.addEventListener('click', () => this._onRowActivated(row));
194
+ return row;
195
+ }
196
+
197
+ /**
198
+ * `gtk_stack_sidebar_row_selected` (gtkstacksidebar.c:130-143): a selected row
199
+ * selects its page. An UNSELECTION is not driven from here — the model is the
200
+ * authority, exactly as in the switcher.
201
+ */
202
+ private _onRowActivated(row: HTMLButtonElement): void {
203
+ const index = this._rows.findIndex((candidate) => candidate === row);
204
+ if (index === -1) return;
205
+ const page = this._pages()[index];
206
+ if (!page) return;
207
+ if (this._stack?.isSelected(page.child)) return;
208
+ this._stack?.setVisibleChild(page.child);
209
+ }
210
+ }
211
+
212
+ customElements.define('gtk-stack-sidebar', GtkStackSidebar);
@@ -0,0 +1,279 @@
1
+ // <gtk-stack-switcher> — a row of linked toggle buttons, one per page of a
2
+ // <gtk-stack>, that switches between them. It is the tab strip `Adw.TabView`
3
+ // supersedes, and the widget `Adw.ViewSwitcher` wraps.
4
+ //
5
+ // IT OWNS NO PAGES. C binds the stack through `set_stack`, reads its `pages`
6
+ // selection model and builds one `GtkToggleButton` per page
7
+ // (gtkstackswitcher.c:428-445, :268-275). `stack` here is an id reference, like
8
+ // `<label for>`, because a browser attribute cannot carry a widget — the same
9
+ // spelling `<adw-view-switcher-bar>` already uses.
10
+ //
11
+ // WHAT A BUTTON SHOWS, transcribed from `rebuild_child` + `update_button`
12
+ // (gtkstackswitcher.c:137-207):
13
+ // icon-name set → an icon child, and the SWITCHER takes the title as its
14
+ // tooltip (:146-147). The button wears `image-button`.
15
+ // title set → a label child with `use_underline` (:161-166), the
16
+ // tooltip is CLEARED (:168), and the button wears
17
+ // `text-button`.
18
+ // neither → NO child at all, and the button is hidden: a row is
19
+ // visible when the page is visible AND carries a title or an
20
+ // icon (`:200`).
21
+ // `needs-attention` puts the `.needs-attention` class on the button (:203-206).
22
+ //
23
+ // THE TWO-WAY BINDING. A button's activation selects the page
24
+ // (`on_button_toggled`, gtkstackswitcher.c:113-133) — and DEACTIVATION is undone
25
+ // from the model, so a user cannot deselect the current page by clicking it
26
+ // (:126-131). The stack's side is `selection_changed_cb`, which re-marks the
27
+ // buttons in the changed range (:359-381) and never rebuilds them, which is why
28
+ // this element keeps its button nodes across a selection change and only rebuilds
29
+ // them on `items-changed` (:347-355).
30
+ //
31
+ // A11Y: each button is `role="tab"` with `aria-selected`, the role C installs on
32
+ // the toggle (gtkstackswitcher.c:279), and the row is a `tablist` — the C side is
33
+ // a GtkBoxLayout of toggles with no list role of its own.
34
+ //
35
+ // `stack` is READ-ONLY from the browser's side in the sense that C has it, but the
36
+ // property is writable there and so it is here: `setStack()` rebinds and
37
+ // `stack="<id>"` names a stack in markup. `set_stack` on the SAME stack is a
38
+ // no-op that does not notify (gtkstackswitcher.c:430-432).
39
+ //
40
+ // Events: `notify::stack` and `notify::orientation` (CustomEvent, bubbles,
41
+ // detail `{ <prop>: value }`).
42
+ //
43
+ // Reference: refs/gtk/gtk/gtkstackswitcher.c
44
+ // Copyright (c) The GTK Team. LGPLv2.1+.
45
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
46
+
47
+ import { normalizeBoxOrientation, type BoxOrientation } from '@gjsify/adwaita-core';
48
+
49
+ import type { GtkStack } from './gtk-stack.js';
50
+
51
+ /** The `GtkStackPageInfo` half this element reads — it never looks inside `child`. */
52
+ interface SwitcherPage {
53
+ name: string;
54
+ title: string | null;
55
+ iconName: string | null;
56
+ needsAttention: boolean;
57
+ visible: boolean;
58
+ child: HTMLElement;
59
+ }
60
+
61
+ /** One button and the nodes it paints, kept across selection changes. */
62
+ interface SwitcherButton {
63
+ button: HTMLButtonElement;
64
+ label: HTMLSpanElement;
65
+ icon: HTMLElement;
66
+ }
67
+
68
+ export class GtkStackSwitcher extends HTMLElement {
69
+ private _stack: GtkStack | null = null;
70
+ private _initialized = false;
71
+ private _nodes: SwitcherButton[] = [];
72
+ private readonly _onStackChange = (): void => this._rebuild();
73
+
74
+ static get observedAttributes() {
75
+ return ['stack', 'orientation'];
76
+ }
77
+
78
+ /** `Gtk.StackSwitcher:stack` — the stack this switcher drives, or null. */
79
+ get stack(): GtkStack | null {
80
+ return this._stack;
81
+ }
82
+
83
+ set stack(value: GtkStack | string | null) {
84
+ this.setStack(typeof value === 'string' ? this._resolve(value) : value);
85
+ }
86
+
87
+ /** `GtkOrientable:orientation` (gtkstackswitcher.c:47). */
88
+ get orientation(): BoxOrientation {
89
+ return normalizeBoxOrientation(this.getAttribute('orientation'));
90
+ }
91
+
92
+ set orientation(v: BoxOrientation) {
93
+ if (this.getAttribute('orientation') === v) return;
94
+ this.setAttribute('orientation', v);
95
+ }
96
+
97
+ /**
98
+ * Rebuild the buttons by hand, for a consumer that mutated a page in place. Not
99
+ * the only path: the stack emits `page-updated` and `items-changed`, and this
100
+ * element binds both, which is the mechanism C uses (`:311-321`, `:347-355`).
101
+ */
102
+ refresh(): void {
103
+ this._rebuild();
104
+ }
105
+
106
+ connectedCallback() {
107
+ if (this._initialized) {
108
+ this._bindStack();
109
+ this._rebuild();
110
+ return;
111
+ }
112
+ this._initialized = true;
113
+ this.setAttribute('role', 'tablist');
114
+ // `.linked` is what C puts on the switcher itself (gtkstackswitcher.c:49-57),
115
+ // and the stylesheet reads it to join the buttons into one control.
116
+ this.classList.add('linked');
117
+ // Resolve the id reference now the element is in the document.
118
+ const ref = this.getAttribute('stack');
119
+ if (ref) {
120
+ this.setStack(this._resolve(ref));
121
+ return;
122
+ }
123
+ this._rebuild();
124
+ }
125
+
126
+ disconnectedCallback() {
127
+ this._unbindStack();
128
+ }
129
+
130
+ attributeChangedCallback(name: string, _old: string | null, value: string | null) {
131
+ if (!this._initialized) return;
132
+ if (name === 'orientation') {
133
+ // `gtk_stack_switcher_set_orientation` re-lays-out the box, so the buttons
134
+ // are kept and the STYLESHEET turns them (gtkstackswitcher.c:500-513).
135
+ this._render();
136
+ this.dispatchEvent(
137
+ new CustomEvent('notify::orientation', { bubbles: true, detail: { orientation: this.orientation } }),
138
+ );
139
+ return;
140
+ }
141
+ this.setStack(value === null ? null : this._resolve(value));
142
+ }
143
+
144
+ /** Bind to a stack element (or null). Unbinds the previous one, as `set_stack` does. */
145
+ setStack(stack: GtkStack | null): void {
146
+ if (stack === this._stack) return;
147
+ this._unbindStack();
148
+ this._stack = stack;
149
+ this._bindStack();
150
+ this._rebuild();
151
+ this.dispatchEvent(new CustomEvent('notify::stack', { bubbles: true, detail: { stack: this._stack } }));
152
+ }
153
+
154
+ private _resolve(id: string | null): GtkStack | null {
155
+ if (!id) return null;
156
+ return (document.getElementById(id) as GtkStack | null) ?? null;
157
+ }
158
+
159
+ private _bindStack(): void {
160
+ this._stack?.addEventListener('items-changed', this._onStackChange);
161
+ this._stack?.addEventListener('selection-changed', this._onStackChange);
162
+ this._stack?.addEventListener('page-updated', this._onStackChange);
163
+ }
164
+
165
+ private _unbindStack(): void {
166
+ this._stack?.removeEventListener('items-changed', this._onStackChange);
167
+ this._stack?.removeEventListener('selection-changed', this._onStackChange);
168
+ this._stack?.removeEventListener('page-updated', this._onStackChange);
169
+ }
170
+
171
+ /**
172
+ * A button is visible when its page is visible AND the page carries a title or an
173
+ * icon (gtkstackswitcher.c:200). `visible` false must hide the row, and an absent
174
+ * title with no icon leaves the button childless — `rebuild_child` builds nothing
175
+ * for it (`:158-176`).
176
+ */
177
+ private _visible(page: SwitcherPage): boolean {
178
+ return page.visible && (page.title !== null || page.iconName !== null);
179
+ }
180
+
181
+ /**
182
+ * The pages, in the order the stack holds them. A stack that is not upgraded has no
183
+ * `pages` getter, which is why it is read defensively.
184
+ */
185
+ private _pages(): SwitcherPage[] {
186
+ const stack = this._stack as (GtkStack & { pages?: SwitcherPage[] }) | null;
187
+ return stack?.pages ?? [];
188
+ }
189
+
190
+ /** Which page the stack has selected, by position, `-1` for none. */
191
+ private _selectedIndex(): number {
192
+ const pages = this._pages();
193
+ const name = this._stack?.visibleChildName ?? null;
194
+ return name === null ? -1 : pages.findIndex((page) => page.name === name);
195
+ }
196
+
197
+ /**
198
+ * `items_changed_cb` rebuilds everything (gtkstackswitcher.c:347-355) and a
199
+ * `selection_changed_cb` does not — so the nodes are recreated ONLY when the page
200
+ * COUNT moves, and a selection change re-marks them in place (:359-381). Replacing
201
+ * a button mid-interaction would also drop keyboard focus.
202
+ */
203
+ private _rebuild(): void {
204
+ if (!this._initialized) return;
205
+ const pages = this._pages();
206
+ if (pages.length !== this._nodes.length) {
207
+ this.replaceChildren();
208
+ this._nodes = pages.map(() => this._buildButton());
209
+ this.append(...this._nodes.map((nodes) => nodes.button));
210
+ }
211
+ const selected = this._selectedIndex();
212
+ pages.forEach((page, index) => {
213
+ const nodes = this._nodes[index];
214
+ if (!nodes) return;
215
+ nodes.button.hidden = !this._visible(page);
216
+ nodes.button.classList.toggle('active', index === selected);
217
+ nodes.button.setAttribute('aria-selected', String(index === selected));
218
+ nodes.button.classList.toggle('needs-attention', page.needsAttention);
219
+
220
+ // `rebuild_child`'s two branches (gtkstackswitcher.c:139-176): an icon wins
221
+ // and the button becomes `image-button`; a title alone makes it a
222
+ // `text-button` with a label child; neither leaves it empty.
223
+ const hasIcon = page.iconName !== null;
224
+ const hasTitle = page.title !== null;
225
+ nodes.icon.hidden = !hasIcon;
226
+ nodes.label.hidden = !hasTitle;
227
+ nodes.label.textContent = page.title ?? '';
228
+ nodes.button.dataset.buttonMode = hasIcon ? (hasTitle ? 'both' : 'icon') : 'text';
229
+ if (hasIcon) {
230
+ nodes.icon.setAttribute('icon-name', page.iconName as string);
231
+ // The tooltip goes on the SWITCHER, not the button (gtkstackswitcher.c:146).
232
+ this.title = page.title ?? '';
233
+ } else {
234
+ nodes.icon.removeAttribute('icon-name');
235
+ // A title-only button CLEARS it (gtkstackswitcher.c:168).
236
+ this.removeAttribute('title');
237
+ }
238
+ });
239
+ this._render();
240
+ }
241
+
242
+ private _buildButton(): SwitcherButton {
243
+ const button = document.createElement('button');
244
+ button.type = 'button';
245
+ button.className = 'adw-stack-switcher-button';
246
+ button.setAttribute('role', 'tab');
247
+ const icon = document.createElement('span');
248
+ icon.className = 'adw-stack-switcher-icon';
249
+ icon.setAttribute('aria-hidden', 'true');
250
+ const label = document.createElement('span');
251
+ label.className = 'adw-stack-switcher-title';
252
+ button.append(icon, label);
253
+ // `on_button_toggled` (gtkstackswitcher.c:113-133): an activation selects the
254
+ // page, and a DEACTIVATION is taken back from the stack — so the current page
255
+ // cannot be deselected by clicking its own button.
256
+ button.addEventListener('click', () => this._onToggled(button));
257
+ return { button, label, icon };
258
+ }
259
+
260
+ private _onToggled(button: HTMLButtonElement): void {
261
+ const index = this._nodes.findIndex((nodes) => nodes.button === button);
262
+ if (index === -1) return;
263
+ const page = this._pages()[index];
264
+ if (!page) return;
265
+ if (this._stack?.isSelected(page.child)) return;
266
+ this._stack?.setVisibleChild(page.child);
267
+ }
268
+
269
+ /**
270
+ * The orientation attribute is the GIR property's own spelling (gtkstackswitcher.c:47)
271
+ * and the stylesheet selects on it directly, so there is nothing to mirror onto a
272
+ * second attribute; this hook exists so the render pass has one entry point.
273
+ */
274
+ private _render(): void {
275
+ this.setAttribute('aria-orientation', this.orientation);
276
+ }
277
+ }
278
+
279
+ customElements.define('gtk-stack-switcher', GtkStackSwitcher);