@gjsify/adwaita-web 0.54.0 → 0.56.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 (479) hide show
  1. package/README.md +8 -0
  2. package/dist/adwaita-web.css +8146 -3011
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/adw-application-window.spec.d.ts +1 -0
  5. package/lib/types/adw-bin.spec.d.ts +1 -0
  6. package/lib/types/adw-breakpoint-bin.spec.d.ts +1 -0
  7. package/lib/types/adw-clamp-scrollable.spec.d.ts +1 -0
  8. package/lib/types/adw-multi-layout-view.spec.d.ts +1 -0
  9. package/lib/types/adw-preferences-row.spec.d.ts +1 -0
  10. package/lib/types/adw-shortcuts.spec.d.ts +1 -0
  11. package/lib/types/adw-status-page.spec.d.ts +1 -0
  12. package/lib/types/adw-tab-bar.spec.d.ts +1 -0
  13. package/lib/types/adw-tab-button.spec.d.ts +1 -0
  14. package/lib/types/adw-tab-overview.spec.d.ts +1 -0
  15. package/lib/types/adw-view-switcher-sidebar.spec.d.ts +1 -0
  16. package/lib/types/adw-window.spec.d.ts +1 -0
  17. package/lib/types/attributes.d.ts +19 -0
  18. package/lib/types/breakpoints.d.ts +14 -3
  19. package/lib/types/construct-vectors.spec.d.ts +1 -0
  20. package/lib/types/elements/adw-action-row.d.ts +4 -0
  21. package/lib/types/elements/adw-application-window.d.ts +27 -0
  22. package/lib/types/elements/adw-bin.d.ts +17 -0
  23. package/lib/types/elements/adw-breakpoint-bin.d.ts +67 -0
  24. package/lib/types/elements/adw-clamp-scrollable.d.ts +38 -0
  25. package/lib/types/elements/adw-combo-row.d.ts +4 -0
  26. package/lib/types/elements/adw-dialog.d.ts +10 -0
  27. package/lib/types/elements/adw-entry-row.d.ts +6 -0
  28. package/lib/types/elements/adw-expander-row.d.ts +2 -0
  29. package/lib/types/elements/adw-header-bar.d.ts +6 -0
  30. package/lib/types/elements/adw-layout-slot.d.ts +19 -0
  31. package/lib/types/elements/adw-multi-layout-view.d.ts +101 -0
  32. package/lib/types/elements/adw-overlay-split-view.d.ts +13 -0
  33. package/lib/types/elements/adw-preferences-row.d.ts +31 -0
  34. package/lib/types/elements/adw-shortcuts-dialog.d.ts +13 -0
  35. package/lib/types/elements/adw-shortcuts-item.d.ts +36 -0
  36. package/lib/types/elements/adw-shortcuts-section.d.ts +14 -0
  37. package/lib/types/elements/adw-sidebar.d.ts +8 -2
  38. package/lib/types/elements/adw-spin-row.d.ts +6 -0
  39. package/lib/types/elements/adw-switch-row.d.ts +7 -0
  40. package/lib/types/elements/adw-tab-bar.d.ts +108 -0
  41. package/lib/types/elements/adw-tab-button.d.ts +32 -0
  42. package/lib/types/elements/adw-tab-overview.d.ts +199 -0
  43. package/lib/types/elements/adw-tab-view.d.ts +19 -23
  44. package/lib/types/elements/adw-toggle-group.d.ts +17 -0
  45. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +84 -0
  46. package/lib/types/elements/adw-window.d.ts +40 -0
  47. package/lib/types/elements/gtk-about-dialog.d.ts +146 -0
  48. package/lib/types/elements/gtk-application-window.d.ts +34 -0
  49. package/lib/types/elements/gtk-aspect-frame.d.ts +27 -0
  50. package/lib/types/elements/gtk-button.d.ts +9 -0
  51. package/lib/types/elements/gtk-calendar.d.ts +159 -0
  52. package/lib/types/elements/gtk-center-box.d.ts +39 -0
  53. package/lib/types/elements/gtk-color-dialog-button.d.ts +69 -0
  54. package/lib/types/elements/gtk-column-view.d.ts +50 -0
  55. package/lib/types/elements/gtk-drag-icon.d.ts +78 -0
  56. package/lib/types/elements/gtk-drawing-area.d.ts +95 -0
  57. package/lib/types/elements/gtk-editable-label.d.ts +33 -0
  58. package/lib/types/elements/gtk-emoji-chooser.d.ts +84 -0
  59. package/lib/types/elements/gtk-entry.d.ts +20 -1
  60. package/lib/types/elements/gtk-expander.d.ts +49 -0
  61. package/lib/types/elements/gtk-fixed.d.ts +13 -0
  62. package/lib/types/elements/gtk-flow-box-child.d.ts +14 -0
  63. package/lib/types/elements/gtk-flow-box.d.ts +87 -0
  64. package/lib/types/elements/gtk-font-dialog-button.d.ts +83 -0
  65. package/lib/types/elements/gtk-frame.d.ts +24 -0
  66. package/lib/types/elements/gtk-gl-area.d.ts +136 -0
  67. package/lib/types/elements/gtk-graphics-offload.d.ts +24 -0
  68. package/lib/types/elements/gtk-grid-view.d.ts +39 -0
  69. package/lib/types/elements/gtk-grid.d.ts +27 -0
  70. package/lib/types/elements/gtk-header-bar.d.ts +60 -0
  71. package/lib/types/elements/gtk-inscription.d.ts +64 -0
  72. package/lib/types/elements/gtk-label.d.ts +3 -0
  73. package/lib/types/elements/gtk-level-bar.d.ts +59 -0
  74. package/lib/types/elements/gtk-link-button.d.ts +29 -0
  75. package/lib/types/elements/gtk-list-box-row.d.ts +54 -0
  76. package/lib/types/elements/gtk-list-box.d.ts +100 -0
  77. package/lib/types/elements/gtk-list-view.d.ts +73 -0
  78. package/lib/types/elements/gtk-media-controls.d.ts +142 -0
  79. package/lib/types/elements/gtk-notebook.d.ts +148 -0
  80. package/lib/types/elements/gtk-overlay.d.ts +22 -0
  81. package/lib/types/elements/gtk-page-setup-unix-dialog.d.ts +87 -0
  82. package/lib/types/elements/gtk-paned.d.ts +121 -0
  83. package/lib/types/elements/gtk-password-entry.d.ts +27 -0
  84. package/lib/types/elements/gtk-picture.d.ts +66 -0
  85. package/lib/types/elements/gtk-popover-bin.d.ts +82 -0
  86. package/lib/types/elements/gtk-popover-menu-bar.d.ts +66 -0
  87. package/lib/types/elements/gtk-popover-menu.d.ts +83 -0
  88. package/lib/types/elements/gtk-popover.d.ts +28 -3
  89. package/lib/types/elements/gtk-print-unix-dialog.d.ts +167 -0
  90. package/lib/types/elements/gtk-revealer.d.ts +55 -0
  91. package/lib/types/elements/gtk-scale-button.d.ts +59 -0
  92. package/lib/types/elements/gtk-scale.d.ts +98 -0
  93. package/lib/types/elements/gtk-scrollbar.d.ts +124 -0
  94. package/lib/types/elements/gtk-scrolled-window.d.ts +129 -0
  95. package/lib/types/elements/gtk-search-bar.d.ts +39 -0
  96. package/lib/types/elements/gtk-search-entry.d.ts +27 -0
  97. package/lib/types/elements/gtk-separator.d.ts +10 -0
  98. package/lib/types/elements/gtk-spin-button.d.ts +94 -0
  99. package/lib/types/elements/gtk-spinner.d.ts +14 -0
  100. package/lib/types/elements/gtk-stack-sidebar.d.ts +43 -0
  101. package/lib/types/elements/gtk-stack-switcher.d.ts +58 -0
  102. package/lib/types/elements/gtk-stack.d.ts +154 -0
  103. package/lib/types/elements/gtk-switch.d.ts +4 -1
  104. package/lib/types/elements/gtk-text-view.d.ts +62 -0
  105. package/lib/types/elements/gtk-text.d.ts +45 -0
  106. package/lib/types/elements/gtk-toggle-button.d.ts +45 -0
  107. package/lib/types/elements/gtk-tree-expander.d.ts +38 -0
  108. package/lib/types/elements/gtk-video.d.ts +97 -0
  109. package/lib/types/elements/gtk-viewport.d.ts +84 -0
  110. package/lib/types/elements/gtk-window-controls.d.ts +80 -0
  111. package/lib/types/elements/gtk-window-handle.d.ts +39 -0
  112. package/lib/types/elements/gtk-window.d.ts +103 -0
  113. package/lib/types/elements/justification.d.ts +2 -0
  114. package/lib/types/elements/popover-menu.d.ts +18 -0
  115. package/lib/types/elements/roving-focus.d.ts +29 -1
  116. package/lib/types/emoji-data.d.ts +38 -0
  117. package/lib/types/font-description.d.ts +96 -0
  118. package/lib/types/gtk-about-dialog.spec.d.ts +1 -0
  119. package/lib/types/gtk-action-bar.spec.d.ts +1 -0
  120. package/lib/types/gtk-application-window.spec.d.ts +1 -0
  121. package/lib/types/gtk-aspect-frame.spec.d.ts +1 -0
  122. package/lib/types/gtk-calendar.spec.d.ts +1 -0
  123. package/lib/types/gtk-center-box.spec.d.ts +1 -0
  124. package/lib/types/gtk-color-dialog-button.spec.d.ts +1 -0
  125. package/lib/types/gtk-column-view.spec.d.ts +1 -0
  126. package/lib/types/gtk-drag-icon.spec.d.ts +1 -0
  127. package/lib/types/gtk-drawing-area.spec.d.ts +1 -0
  128. package/lib/types/gtk-editable-label.spec.d.ts +1 -0
  129. package/lib/types/gtk-emoji-chooser.spec.d.ts +1 -0
  130. package/lib/types/gtk-expander.spec.d.ts +1 -0
  131. package/lib/types/gtk-fixed.spec.d.ts +1 -0
  132. package/lib/types/gtk-flow-box.spec.d.ts +1 -0
  133. package/lib/types/gtk-font-dialog-button.spec.d.ts +1 -0
  134. package/lib/types/gtk-frame.spec.d.ts +1 -0
  135. package/lib/types/gtk-gl-area.spec.d.ts +1 -0
  136. package/lib/types/gtk-graphics-offload.spec.d.ts +1 -0
  137. package/lib/types/gtk-grid-view.spec.d.ts +1 -0
  138. package/lib/types/gtk-grid.spec.d.ts +1 -0
  139. package/lib/types/gtk-header-bar.spec.d.ts +1 -0
  140. package/lib/types/gtk-inscription.spec.d.ts +1 -0
  141. package/lib/types/gtk-level-bar.spec.d.ts +1 -0
  142. package/lib/types/gtk-link-button.spec.d.ts +1 -0
  143. package/lib/types/gtk-list-box.spec.d.ts +1 -0
  144. package/lib/types/gtk-list-view.spec.d.ts +1 -0
  145. package/lib/types/gtk-media-controls.spec.d.ts +1 -0
  146. package/lib/types/gtk-notebook.spec.d.ts +1 -0
  147. package/lib/types/gtk-overlay.spec.d.ts +1 -0
  148. package/lib/types/gtk-paned.spec.d.ts +1 -0
  149. package/lib/types/gtk-password-entry.spec.d.ts +1 -0
  150. package/lib/types/gtk-picture.spec.d.ts +1 -0
  151. package/lib/types/gtk-popover-bin.spec.d.ts +1 -0
  152. package/lib/types/gtk-popover-menu-bar.spec.d.ts +1 -0
  153. package/lib/types/gtk-popover-menu.spec.d.ts +1 -0
  154. package/lib/types/gtk-popover-role.spec.d.ts +1 -0
  155. package/lib/types/gtk-popover.spec.d.ts +1 -0
  156. package/lib/types/gtk-print-dialogs.spec.d.ts +1 -0
  157. package/lib/types/gtk-revealer.spec.d.ts +1 -0
  158. package/lib/types/gtk-scale-button.spec.d.ts +1 -0
  159. package/lib/types/gtk-scale.spec.d.ts +1 -0
  160. package/lib/types/gtk-scrollbar.spec.d.ts +1 -0
  161. package/lib/types/gtk-scrolled-window.spec.d.ts +1 -0
  162. package/lib/types/gtk-search-bar.spec.d.ts +1 -0
  163. package/lib/types/gtk-search-entry.spec.d.ts +1 -0
  164. package/lib/types/gtk-separator.spec.d.ts +1 -0
  165. package/lib/types/gtk-spin-button.spec.d.ts +1 -0
  166. package/lib/types/gtk-spinner.spec.d.ts +1 -0
  167. package/lib/types/gtk-stack-sidebar.spec.d.ts +1 -0
  168. package/lib/types/gtk-stack-switcher.spec.d.ts +1 -0
  169. package/lib/types/gtk-stack.spec.d.ts +1 -0
  170. package/lib/types/gtk-text-view.spec.d.ts +1 -0
  171. package/lib/types/gtk-text.spec.d.ts +1 -0
  172. package/lib/types/gtk-toggle-button.spec.d.ts +1 -0
  173. package/lib/types/gtk-tree-expander.spec.d.ts +1 -0
  174. package/lib/types/gtk-video.spec.d.ts +1 -0
  175. package/lib/types/gtk-viewport.spec.d.ts +1 -0
  176. package/lib/types/gtk-window-controls.spec.d.ts +1 -0
  177. package/lib/types/gtk-window-handle.spec.d.ts +1 -0
  178. package/lib/types/gtk-window.spec.d.ts +1 -0
  179. package/lib/types/index.d.ts +4 -1
  180. package/lib/types/list-view-dom.d.ts +44 -0
  181. package/lib/types/namespace/adw.d.ts +12 -0
  182. package/lib/types/namespace/gtk.d.ts +61 -0
  183. package/lib/types/page-setup.d.ts +100 -0
  184. package/lib/types/row-line-clamp.d.ts +20 -0
  185. package/lib/types/row-tooltip.d.ts +8 -0
  186. package/lib/types/row-tooltip.spec.d.ts +1 -0
  187. package/lib/types/scroll-shading.d.ts +15 -1
  188. package/lib/types/shared-tree-builder.d.ts +75 -17
  189. package/lib/types/shared-tree-mount.spec.d.ts +1 -0
  190. package/lib/types/signals.d.ts +4 -0
  191. package/lib/types/styles.generated.d.ts +1 -1
  192. package/lib/types/tab-chip.d.ts +73 -0
  193. package/lib/types/template-classes.d.ts +11 -0
  194. package/lib/types/widget-size.spec.d.ts +1 -0
  195. package/package.json +12 -8
  196. package/scss/_action_row.scss +41 -17
  197. package/scss/_application_window.scss +26 -0
  198. package/scss/_aspect_frame.scss +25 -0
  199. package/scss/_bin.scss +26 -0
  200. package/scss/_button.scss +45 -0
  201. package/scss/_button_row.scss +5 -0
  202. package/scss/_calendar.scss +176 -0
  203. package/scss/_center_box.scss +25 -0
  204. package/scss/_checks.scss +6 -1
  205. package/scss/_clamp_scrollable.scss +28 -0
  206. package/scss/_color_button.scss +67 -0
  207. package/scss/_column_view.scss +126 -0
  208. package/scss/_drag_icon.scss +55 -0
  209. package/scss/_drawing.scss +85 -0
  210. package/scss/_emoji_chooser.scss +213 -0
  211. package/scss/_entry.scss +13 -5
  212. package/scss/_entry_row.scss +1 -1
  213. package/scss/_expander.scss +113 -0
  214. package/scss/_expander_row.scss +36 -3
  215. package/scss/_fixed.scss +29 -0
  216. package/scss/_flow_box.scss +94 -0
  217. package/scss/_font_button.scss +63 -0
  218. package/scss/_frame.scss +41 -0
  219. package/scss/_grid.scss +19 -0
  220. package/scss/_grid_view.scss +46 -0
  221. package/scss/_gtk_about_dialog.scss +186 -0
  222. package/scss/_headerbar.scss +134 -1
  223. package/scss/_icons.generated.scss +186 -0
  224. package/scss/_inscription.scss +125 -0
  225. package/scss/_level_bar.scss +190 -0
  226. package/scss/_link.scss +82 -0
  227. package/scss/_list_box.scss +88 -0
  228. package/scss/_list_view.scss +96 -0
  229. package/scss/_media_controls.scss +139 -0
  230. package/scss/_overlay.scss +68 -0
  231. package/scss/_paned.scss +130 -0
  232. package/scss/_password_entry.scss +83 -0
  233. package/scss/_picture.scss +80 -0
  234. package/scss/_popover_bin.scss +53 -0
  235. package/scss/_popover_menu_bar.scss +104 -0
  236. package/scss/_preferences_row.scss +60 -0
  237. package/scss/_print_dialogs.scss +328 -0
  238. package/scss/_reset.scss +21 -19
  239. package/scss/_revealer.scss +37 -0
  240. package/scss/_row.scss +36 -5
  241. package/scss/_scale.scss +298 -0
  242. package/scss/_scale_button.scss +167 -0
  243. package/scss/_scrollbar.scss +230 -0
  244. package/scss/_scrolled_window.scss +131 -0
  245. package/scss/_search_bar.scss +118 -0
  246. package/scss/_search_entry.scss +86 -0
  247. package/scss/_separator.scss +44 -0
  248. package/scss/_shortcuts_dialog.scss +100 -0
  249. package/scss/_spin_button.scss +172 -0
  250. package/scss/_spin_row.scss +56 -8
  251. package/scss/_spinner.scss +85 -4
  252. package/scss/_stack.scss +729 -0
  253. package/scss/_status_page.scss +1 -1
  254. package/scss/_switch.scss +13 -5
  255. package/scss/_switch_row.scss +10 -0
  256. package/scss/_tab_bar.scss +317 -0
  257. package/scss/_tab_button.scss +98 -0
  258. package/scss/_tab_overview.scss +483 -0
  259. package/scss/_text.scss +182 -0
  260. package/scss/_theme.scss +1 -1
  261. package/scss/_toggle_group.scss +28 -0
  262. package/scss/_tree_expander.scss +62 -0
  263. package/scss/_variables.scss +1 -1
  264. package/scss/_video.scss +146 -0
  265. package/scss/_view_switcher_sidebar.scss +112 -0
  266. package/scss/_viewport.scss +50 -0
  267. package/scss/_widget.scss +14 -3
  268. package/scss/_window.scss +131 -2
  269. package/scss/_window_handle.scss +20 -0
  270. package/scss/adwaita-skin.scss +109 -0
  271. package/src/adw-action-rows.spec.ts +331 -0
  272. package/src/adw-application-window.spec.ts +118 -0
  273. package/src/adw-bin.spec.ts +75 -0
  274. package/src/adw-breakpoint-bin.spec.ts +324 -0
  275. package/src/adw-clamp-scrollable.spec.ts +189 -0
  276. package/src/adw-header-bar.spec.ts +18 -0
  277. package/src/adw-multi-layout-view.spec.ts +243 -0
  278. package/src/adw-preferences-row.spec.ts +164 -0
  279. package/src/adw-row-state.spec.ts +142 -0
  280. package/src/adw-shortcuts.spec.ts +155 -0
  281. package/src/adw-status-page.spec.ts +124 -0
  282. package/src/adw-tab-bar.spec.ts +287 -0
  283. package/src/adw-tab-button.spec.ts +101 -0
  284. package/src/adw-tab-overview.spec.ts +443 -0
  285. package/src/adw-view-switcher-sidebar.spec.ts +281 -0
  286. package/src/adw-window.spec.ts +129 -0
  287. package/src/attributes.ts +52 -0
  288. package/src/breakpoints.ts +25 -8
  289. package/src/capabilities.d.mts +3 -0
  290. package/src/capabilities.mjs +21 -0
  291. package/src/connect-lifecycle.spec.ts +12 -0
  292. package/src/construct-vectors.spec.ts +175 -0
  293. package/src/elements/adw-action-row.ts +31 -2
  294. package/src/elements/adw-alert-dialog.ts +4 -1
  295. package/src/elements/adw-application-window.ts +154 -0
  296. package/src/elements/adw-bin.ts +101 -0
  297. package/src/elements/adw-breakpoint-bin.ts +287 -0
  298. package/src/elements/adw-button-row.ts +7 -1
  299. package/src/elements/adw-clamp-scrollable.ts +207 -0
  300. package/src/elements/adw-combo-row.ts +26 -1
  301. package/src/elements/adw-dialog.ts +19 -0
  302. package/src/elements/adw-entry-row.ts +22 -12
  303. package/src/elements/adw-expander-row.ts +34 -1
  304. package/src/elements/adw-header-bar.ts +18 -4
  305. package/src/elements/adw-layout-slot.ts +95 -0
  306. package/src/elements/adw-multi-layout-view.ts +326 -0
  307. package/src/elements/adw-overlay-split-view.ts +29 -6
  308. package/src/elements/adw-preferences-row.ts +153 -0
  309. package/src/elements/adw-shortcuts-dialog.ts +52 -0
  310. package/src/elements/adw-shortcuts-item.ts +171 -0
  311. package/src/elements/adw-shortcuts-section.ts +86 -0
  312. package/src/elements/adw-sidebar.ts +74 -7
  313. package/src/elements/adw-spin-row.ts +37 -2
  314. package/src/elements/adw-status-page.ts +10 -2
  315. package/src/elements/adw-switch-row.ts +53 -2
  316. package/src/elements/adw-tab-bar.ts +529 -0
  317. package/src/elements/adw-tab-button.ts +194 -0
  318. package/src/elements/adw-tab-overview.ts +1011 -0
  319. package/src/elements/adw-tab-view.ts +66 -145
  320. package/src/elements/adw-toggle-group.ts +138 -14
  321. package/src/elements/adw-view-stack.ts +18 -0
  322. package/src/elements/adw-view-switcher-sidebar.ts +332 -0
  323. package/src/elements/adw-window.ts +190 -11
  324. package/src/elements/checks.ts +35 -8
  325. package/src/elements/gtk-about-dialog.ts +811 -0
  326. package/src/elements/gtk-application-window.ts +108 -0
  327. package/src/elements/gtk-aspect-frame.ts +160 -0
  328. package/src/elements/gtk-button.ts +12 -0
  329. package/src/elements/gtk-calendar.ts +757 -0
  330. package/src/elements/gtk-center-box.ts +184 -0
  331. package/src/elements/gtk-color-dialog-button.ts +278 -0
  332. package/src/elements/gtk-column-view.ts +320 -0
  333. package/src/elements/gtk-drag-icon.ts +257 -0
  334. package/src/elements/gtk-drawing-area.ts +303 -0
  335. package/src/elements/gtk-editable-label.ts +204 -0
  336. package/src/elements/gtk-emoji-chooser.ts +542 -0
  337. package/src/elements/gtk-entry.ts +39 -5
  338. package/src/elements/gtk-expander.ts +301 -0
  339. package/src/elements/gtk-fixed.ts +99 -0
  340. package/src/elements/gtk-flow-box-child.ts +68 -0
  341. package/src/elements/gtk-flow-box.ts +480 -0
  342. package/src/elements/gtk-font-dialog-button.ts +432 -0
  343. package/src/elements/gtk-frame.ts +174 -0
  344. package/src/elements/gtk-gl-area.ts +476 -0
  345. package/src/elements/gtk-graphics-offload.ts +130 -0
  346. package/src/elements/gtk-grid-view.ts +168 -0
  347. package/src/elements/gtk-grid.ts +127 -0
  348. package/src/elements/gtk-header-bar.ts +273 -0
  349. package/src/elements/gtk-inscription.ts +387 -0
  350. package/src/elements/gtk-label.ts +19 -11
  351. package/src/elements/gtk-level-bar.ts +323 -0
  352. package/src/elements/gtk-link-button.ts +138 -0
  353. package/src/elements/gtk-list-box-row.ts +195 -0
  354. package/src/elements/gtk-list-box.ts +413 -0
  355. package/src/elements/gtk-list-view.ts +370 -0
  356. package/src/elements/gtk-media-controls.ts +509 -0
  357. package/src/elements/gtk-notebook.ts +664 -0
  358. package/src/elements/gtk-overlay.ts +149 -0
  359. package/src/elements/gtk-page-setup-unix-dialog.ts +420 -0
  360. package/src/elements/gtk-paned.ts +597 -0
  361. package/src/elements/gtk-password-entry.ts +170 -0
  362. package/src/elements/gtk-picture.ts +254 -0
  363. package/src/elements/gtk-popover-bin.ts +332 -0
  364. package/src/elements/gtk-popover-menu-bar.ts +355 -0
  365. package/src/elements/gtk-popover-menu.ts +339 -0
  366. package/src/elements/gtk-popover.ts +92 -10
  367. package/src/elements/gtk-print-unix-dialog.ts +989 -0
  368. package/src/elements/gtk-progress-bar.ts +24 -11
  369. package/src/elements/gtk-revealer.ts +406 -0
  370. package/src/elements/gtk-scale-button.ts +358 -0
  371. package/src/elements/gtk-scale.ts +492 -0
  372. package/src/elements/gtk-scrollbar.ts +528 -0
  373. package/src/elements/gtk-scrolled-window.ts +653 -0
  374. package/src/elements/gtk-search-bar.ts +200 -0
  375. package/src/elements/gtk-search-entry.ts +172 -0
  376. package/src/elements/gtk-separator.ts +52 -0
  377. package/src/elements/gtk-spin-button.ts +475 -0
  378. package/src/elements/gtk-spinner.ts +126 -0
  379. package/src/elements/gtk-stack-sidebar.ts +212 -0
  380. package/src/elements/gtk-stack-switcher.ts +279 -0
  381. package/src/elements/gtk-stack.ts +748 -0
  382. package/src/elements/gtk-switch.ts +52 -19
  383. package/src/elements/gtk-text-view.ts +290 -0
  384. package/src/elements/gtk-text.ts +219 -0
  385. package/src/elements/gtk-toggle-button.ts +239 -0
  386. package/src/elements/gtk-tree-expander.ts +243 -0
  387. package/src/elements/gtk-video.ts +423 -0
  388. package/src/elements/gtk-viewport.ts +277 -0
  389. package/src/elements/gtk-window-controls.ts +341 -0
  390. package/src/elements/gtk-window-handle.ts +221 -0
  391. package/src/elements/gtk-window.ts +372 -0
  392. package/src/elements/justification.ts +24 -0
  393. package/src/elements/popover-menu.ts +24 -0
  394. package/src/elements/roving-focus.ts +53 -21
  395. package/src/emoji-data.ts +577 -0
  396. package/src/entry-rows.spec.ts +31 -0
  397. package/src/font-description.ts +238 -0
  398. package/src/gtk-about-dialog.spec.ts +250 -0
  399. package/src/gtk-action-bar.spec.ts +89 -0
  400. package/src/gtk-application-window.spec.ts +107 -0
  401. package/src/gtk-aspect-frame.spec.ts +114 -0
  402. package/src/gtk-calendar.spec.ts +589 -0
  403. package/src/gtk-center-box.spec.ts +125 -0
  404. package/src/gtk-color-dialog-button.spec.ts +141 -0
  405. package/src/gtk-column-view.spec.ts +154 -0
  406. package/src/gtk-drag-icon.spec.ts +190 -0
  407. package/src/gtk-drawing-area.spec.ts +211 -0
  408. package/src/gtk-editable-label.spec.ts +190 -0
  409. package/src/gtk-emoji-chooser.spec.ts +173 -0
  410. package/src/gtk-entry.spec.ts +23 -0
  411. package/src/gtk-expander.spec.ts +170 -0
  412. package/src/gtk-fixed.spec.ts +97 -0
  413. package/src/gtk-flow-box.spec.ts +289 -0
  414. package/src/gtk-font-dialog-button.spec.ts +166 -0
  415. package/src/gtk-frame.spec.ts +119 -0
  416. package/src/gtk-gl-area.spec.ts +361 -0
  417. package/src/gtk-graphics-offload.spec.ts +119 -0
  418. package/src/gtk-grid-view.spec.ts +106 -0
  419. package/src/gtk-grid.spec.ts +122 -0
  420. package/src/gtk-header-bar.spec.ts +202 -0
  421. package/src/gtk-inscription.spec.ts +235 -0
  422. package/src/gtk-level-bar.spec.ts +199 -0
  423. package/src/gtk-link-button.spec.ts +117 -0
  424. package/src/gtk-list-box.spec.ts +422 -0
  425. package/src/gtk-list-view.spec.ts +203 -0
  426. package/src/gtk-media-controls.spec.ts +295 -0
  427. package/src/gtk-notebook.spec.ts +546 -0
  428. package/src/gtk-overlay.spec.ts +141 -0
  429. package/src/gtk-paned.spec.ts +267 -0
  430. package/src/gtk-password-entry.spec.ts +150 -0
  431. package/src/gtk-picture.spec.ts +172 -0
  432. package/src/gtk-popover-bin.spec.ts +229 -0
  433. package/src/gtk-popover-menu-bar.spec.ts +296 -0
  434. package/src/gtk-popover-menu.spec.ts +261 -0
  435. package/src/gtk-popover-role.spec.ts +138 -0
  436. package/src/gtk-popover.spec.ts +264 -0
  437. package/src/gtk-print-dialogs.spec.ts +251 -0
  438. package/src/gtk-revealer.spec.ts +164 -0
  439. package/src/gtk-scale-button.spec.ts +218 -0
  440. package/src/gtk-scale.spec.ts +213 -0
  441. package/src/gtk-scrollbar.spec.ts +244 -0
  442. package/src/gtk-scrolled-window.spec.ts +262 -0
  443. package/src/gtk-search-bar.spec.ts +179 -0
  444. package/src/gtk-search-entry.spec.ts +142 -0
  445. package/src/gtk-separator.spec.ts +74 -0
  446. package/src/gtk-spin-button.spec.ts +186 -0
  447. package/src/gtk-spinner.spec.ts +130 -0
  448. package/src/gtk-stack-sidebar.spec.ts +217 -0
  449. package/src/gtk-stack-switcher.spec.ts +249 -0
  450. package/src/gtk-stack.spec.ts +432 -0
  451. package/src/gtk-text-view.spec.ts +189 -0
  452. package/src/gtk-text.spec.ts +163 -0
  453. package/src/gtk-toggle-button.spec.ts +186 -0
  454. package/src/gtk-tree-expander.spec.ts +201 -0
  455. package/src/gtk-video.spec.ts +240 -0
  456. package/src/gtk-viewport.spec.ts +140 -0
  457. package/src/gtk-window-controls.spec.ts +232 -0
  458. package/src/gtk-window-handle.spec.ts +158 -0
  459. package/src/gtk-window.spec.ts +202 -0
  460. package/src/index.ts +9 -1
  461. package/src/keyboard-operable.spec.ts +77 -9
  462. package/src/list-view-dom.ts +121 -0
  463. package/src/namespace/adw.ts +12 -0
  464. package/src/namespace/gtk.ts +61 -0
  465. package/src/page-setup.ts +222 -0
  466. package/src/row-line-clamp.ts +74 -0
  467. package/src/row-tooltip.spec.ts +313 -0
  468. package/src/row-tooltip.ts +52 -0
  469. package/src/scroll-shading.ts +18 -1
  470. package/src/shared-tree-builder.ts +336 -41
  471. package/src/shared-tree-mount.spec.ts +130 -0
  472. package/src/shared-trees.spec.ts +15 -0
  473. package/src/signals.ts +15 -0
  474. package/src/style-classes.spec.ts +9 -8
  475. package/src/styles.generated.ts +1 -1
  476. package/src/tab-chip.ts +200 -0
  477. package/src/template-classes.ts +45 -0
  478. package/src/test.browser.mts +160 -0
  479. package/src/widget-size.spec.ts +117 -0
@@ -0,0 +1,158 @@
1
+ // DOM-level tests for <gtk-window-handle>: the three titlebar gestures and what they raise.
2
+ // The gestures are the whole widget — it has one property, a `child` slot, and no box of its
3
+ // own — so what is asserted here is the ACTIONS, in the vocabulary
4
+ // `perform_titlebar_action_fallback` uses when a compositor has no opinion.
5
+ import { describe, expect, it } from '@gjsify/unit';
6
+
7
+ import type { GtkWindowHandle } from './elements/gtk-window-handle.js';
8
+
9
+ function mount(): { el: GtkWindowHandle; host: HTMLElement } {
10
+ const host = document.createElement('div');
11
+ host.style.width = '400px';
12
+ host.style.height = '40px';
13
+ document.body.appendChild(host);
14
+ const el = document.createElement('gtk-window-handle') as GtkWindowHandle;
15
+ el.style.display = 'contents';
16
+ const title = document.createElement('gtk-label');
17
+ title.setAttribute('label', 'Untitled');
18
+ el.appendChild(title);
19
+ host.appendChild(el);
20
+ return { el, host };
21
+ }
22
+
23
+ /** Every `event` name dispatched on `el`, with its `detail`. */
24
+ function record(el: HTMLElement, ...events: string[]): Map<string, unknown[]> {
25
+ const seen = new Map<string, unknown[]>();
26
+ for (const name of events) {
27
+ const details: unknown[] = [];
28
+ seen.set(name, details);
29
+ el.addEventListener(name, (e) => details.push((e as CustomEvent).detail));
30
+ }
31
+ return seen;
32
+ }
33
+
34
+ const click = (el: HTMLElement, init: MouseEventInit = {}): void => {
35
+ el.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, ...init }));
36
+ };
37
+
38
+ const pointer = (el: HTMLElement, type: string, init: PointerEventInit = {}): void => {
39
+ el.dispatchEvent(new PointerEvent(type, { bubbles: true, cancelable: true, ...init }));
40
+ };
41
+
42
+ export const GtkWindowHandleTest = async () => {
43
+ await describe('<gtk-window-handle> the titlebar actions', async () => {
44
+ await it('is a generic role and contributes no box of its own', async () => {
45
+ const { el, host } = mount();
46
+ expect(el.getAttribute('role')).toBe('generic');
47
+ // `display: contents` IS `GtkBinLayout`'s "the child takes the whole
48
+ // allocation", and what makes a handle usable as a titlebar strip.
49
+ expect(getComputedStyle(el).display).toBe('contents');
50
+ host.remove();
51
+ });
52
+
53
+ await it('turns a DOUBLE CLICK into toggle-maximize, and a single click into nothing', async () => {
54
+ const { el, host } = mount();
55
+ const seen = record(el, 'titlebar-action', 'window.toggle-maximized');
56
+ click(el, { button: 0, detail: 1 });
57
+ expect(seen.get('titlebar-action')?.length).toBe(0);
58
+ click(el, { button: 0, detail: 2 });
59
+ expect(seen.get('titlebar-action')?.length).toBe(1);
60
+ expect(seen.get('window.toggle-maximized')?.length).toBe(1);
61
+ const detail = seen.get('titlebar-action')?.[0] as {
62
+ action: string;
63
+ gesture: string;
64
+ windowAction: string;
65
+ };
66
+ expect(detail.action).toBe('toggle-maximize');
67
+ expect(detail.gesture).toBe('double-click');
68
+ expect(detail.windowAction).toBe('window.toggle-maximized');
69
+ host.remove();
70
+ });
71
+
72
+ await it('turns a right click into the window menu, as its setting says', async () => {
73
+ const { el, host } = mount();
74
+ const seen = record(el, 'window.menu', 'window-move');
75
+ click(el, { button: 2 });
76
+ expect(seen.get('window.menu')?.length).toBe(1);
77
+ host.remove();
78
+ });
79
+
80
+ await it('reads each gesture off its OWN setting default, and refuses a value GTK does not know', async () => {
81
+ const { el, host } = mount();
82
+ // The three pspecs are not the same (gtksettings.c:868-896): a middle click does
83
+ // NOTHING by default, which is the whole point of there being three settings.
84
+ expect(el.actionFor('double-click')).toBe('toggle-maximize');
85
+ expect(el.actionFor('middle-click')).toBe('none');
86
+ expect(el.actionFor('right-click')).toBe('menu');
87
+ el.setAttribute('double-click-action', 'minimize');
88
+ expect(el.actionFor('double-click')).toBe('minimize');
89
+ const seen = record(el, 'window.minimize');
90
+ click(el, { button: 0, detail: 2 });
91
+ expect(seen.get('window.minimize')?.length).toBe(1);
92
+ // An unknown value is `none`, which is the C's own refusal branch — a typo must
93
+ // not minimize a window.
94
+ el.setAttribute('double-click-action', 'minimise');
95
+ expect(el.actionFor('double-click')).toBe('none');
96
+ const none = record(el, 'window.minimize');
97
+ click(el, { button: 0, detail: 2 });
98
+ expect(none.get('window.minimize')?.length).toBe(0);
99
+ // A maximization VARIANT maximizes: `perform_titlebar_action_fallback` matches
100
+ // `toggle-maximize` by prefix, "treat all maximization variants the same"
101
+ // (gtkwindowhandle.c:311-315).
102
+ el.setAttribute('double-click-action', 'toggle-maximize-fullscreen');
103
+ expect(el.actionFor('double-click')).toBe('toggle-maximize');
104
+ host.remove();
105
+ });
106
+
107
+ await it('reports `none` on titlebar-action all the same, which is the gesture itself', async () => {
108
+ const { el, host } = mount();
109
+ const seen = record(el, 'titlebar-action', 'window.menu');
110
+ // A middle click, which is `none` by default (gtksettings.c:881-883) — the gesture
111
+ // still happened, so it is still reported, and nothing else fires.
112
+ click(el, { button: 1 });
113
+ expect(seen.get('titlebar-action')?.length).toBe(1);
114
+ expect(seen.get('window.menu')?.length).toBe(0);
115
+ // Taken apart before the property is read: `(x?.[0] as T).gesture` would throw
116
+ // a TypeError instead of failing the assertion if the array were empty.
117
+ const middle = seen.get('titlebar-action')?.[0] as { gesture: string } | undefined;
118
+ expect(middle?.gesture).toBe('middle-click');
119
+ el.setAttribute('right-click-action', 'none');
120
+ const right = record(el, 'titlebar-action', 'window.menu');
121
+ click(el, { button: 2 });
122
+ expect(right.get('titlebar-action')?.length).toBe(1);
123
+ expect(right.get('window.menu')?.length).toBe(0);
124
+ host.remove();
125
+ });
126
+ });
127
+
128
+ await describe('<gtk-window-handle> the drag', async () => {
129
+ await it('raises window-move once the pointer passes the drag threshold', async () => {
130
+ const { el, host } = mount();
131
+ const seen = record(el, 'window-move');
132
+ pointer(el, 'pointerdown', { pointerId: 1, clientX: 10, clientY: 20 });
133
+ // Under the threshold nothing has happened, which is `gtk_drag_check_threshold_double`.
134
+ pointer(el, 'pointermove', { pointerId: 1, clientX: 10, clientY: 21 });
135
+ expect(seen.get('window-move')?.length).toBe(0);
136
+ pointer(el, 'pointermove', { pointerId: 1, clientX: 60, clientY: 20 });
137
+ expect(seen.get('window-move')?.length).toBe(1);
138
+ // The sequence is reset afterwards, so the gesture does not repeat.
139
+ pointer(el, 'pointermove', { pointerId: 1, clientX: 90, clientY: 20 });
140
+ expect(seen.get('window-move')?.length).toBe(1);
141
+ host.remove();
142
+ });
143
+
144
+ await it('denies the drag once a multi-click has claimed the sequence', async () => {
145
+ const { el, host } = mount();
146
+ const seen = record(el, 'window-move');
147
+ pointer(el, 'pointerdown', { pointerId: 1, clientX: 10, clientY: 20 });
148
+ pointer(el, 'pointerdown', { pointerId: 1, clientX: 10, clientY: 20 });
149
+ // The second press of a double click: the click gesture claims the sequence and
150
+ // `gtk_event_controller_reset` denies the drag with it (gtkwindowhandle.c:400-406),
151
+ // which is where a browser knows the press count.
152
+ click(el, { button: 0, detail: 2 });
153
+ pointer(el, 'pointermove', { pointerId: 1, clientX: 90, clientY: 20 });
154
+ expect(seen.get('window-move')?.length).toBe(0);
155
+ host.remove();
156
+ });
157
+ });
158
+ };
@@ -0,0 +1,202 @@
1
+ // DOM-level tests for <gtk-window>. A window in a page is a FRAME, and this file holds that
2
+ // honest: the two shapes its titlebar strip can be in (the application's `titlebar` slot, or
3
+ // the server-side decoration a page has to draw for itself), the four properties that decide
4
+ // which frame buttons appear, and the two branches of `gtk_window_close`
5
+ // (gtkwindow.c:1274-1287).
6
+ import { describe, expect, it } from '@gjsify/unit';
7
+
8
+ import type { GtkWindow } from './elements/gtk-window.js';
9
+
10
+ function mount(attrs: Record<string, string> = {}): { el: GtkWindow; host: HTMLElement } {
11
+ const host = document.createElement('div');
12
+ document.body.appendChild(host);
13
+ const el = document.createElement('gtk-window') as GtkWindow;
14
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
15
+ host.appendChild(el);
16
+ return { el, host };
17
+ }
18
+
19
+ function content(el: GtkWindow): HTMLElement {
20
+ return el.querySelector('.adw-gtk-window-content') as HTMLElement;
21
+ }
22
+
23
+ function titlebar(el: GtkWindow): HTMLElement {
24
+ return el.querySelector('.adw-gtk-window-titlebar') as HTMLElement;
25
+ }
26
+
27
+ export const GtkWindowTest = async () => {
28
+ await describe('<gtk-window> structure', async () => {
29
+ await it('is a titlebar strip over a content box', async () => {
30
+ // The two strips `connectedCallback` installs, in `strips()` order.
31
+ const { el, host } = mount();
32
+ expect([...el.children].map((node) => node.className)).toStrictEqual([
33
+ 'adw-gtk-window-titlebar',
34
+ 'adw-gtk-window-content',
35
+ ]);
36
+ expect(titlebar(el).hidden).toBe(false);
37
+ host.remove();
38
+ });
39
+
40
+ await it('answers an unset title as a string and clears it with null', async () => {
41
+ // `HTMLElement.title` is a `string`; a `string | null` getter broke every consumer's
42
+ // type check of the emitted `.d.ts`.
43
+ const { el, host } = mount();
44
+ expect(el.title).toBe('');
45
+ el.title = 'Learn6502';
46
+ expect(el.title).toBe('Learn6502');
47
+ el.title = null;
48
+ expect(el.title).toBe('');
49
+ host.remove();
50
+ });
51
+
52
+ await it('routes every unslotted child into the content box, in document order', async () => {
53
+ const { el, host } = mount();
54
+ const first = document.createElement('span');
55
+ first.textContent = 'a';
56
+ const second = document.createElement('span');
57
+ second.textContent = 'b';
58
+ el.append(first, second);
59
+ await Promise.resolve();
60
+ expect([...content(el).children]).toStrictEqual([first, second]);
61
+ host.remove();
62
+ });
63
+
64
+ await it('a `titlebar` child takes the whole strip, decorations and all', async () => {
65
+ // GTK hands the titlebar the window's decorations; a `Gtk.HeaderBar` brings its
66
+ // own window controls with it.
67
+ const { el, host } = mount();
68
+ const bar = document.createElement('gtk-header-bar');
69
+ // `titlebar` is a PROPERTY on Gtk.Window (gtkwindow.c:1138) and the buildable's
70
+ // single child is something else, so the slot name is how the markup spells it.
71
+ bar.setAttribute('slot', 'titlebar');
72
+ el.appendChild(bar);
73
+ await Promise.resolve();
74
+ await Promise.resolve();
75
+ expect(bar.parentElement).toBe(titlebar(el));
76
+ // The WINDOW's own two are gone, and the bar brings its own pair instead — which is
77
+ // what `show-title-buttons` is for (gtkheaderbar.c:198-249).
78
+ expect([...titlebar(el).children]).toStrictEqual([bar]);
79
+ expect(el.querySelectorAll('gtk-window-controls').length).toBe(2);
80
+ host.remove();
81
+ });
82
+
83
+ await it('with no titlebar it draws the SSD a window manager would have', async () => {
84
+ const { el, host } = mount({ title: 'Documents' });
85
+ expect([...titlebar(el).children].map((node) => node.localName)).toStrictEqual([
86
+ 'gtk-window-controls',
87
+ 'span',
88
+ 'gtk-window-controls',
89
+ ]);
90
+ expect(titlebar(el).querySelector('.adw-gtk-window-title')?.getAttribute('title')).toBe('Documents');
91
+ host.remove();
92
+ });
93
+
94
+ await it('`decorated="false"` HIDES the strip, frame buttons and all', async () => {
95
+ // gtk_window_set_decorated (gtkwindow.c:1014) takes the titlebar OUT OF THE FRAME,
96
+ // which is not the same as discarding it: the window keeps the widget and an
97
+ // undecorating write puts it back. So the strip is hidden, not emptied.
98
+ const { el, host } = mount();
99
+ el.decorated = false;
100
+ expect(titlebar(el).hidden).toBe(true);
101
+ expect(el.querySelector('gtk-window-controls')).not.toBe(null);
102
+ el.decorated = true;
103
+ expect(titlebar(el).hidden).toBe(false);
104
+ host.remove();
105
+ });
106
+ });
107
+
108
+ await describe('<gtk-window> frame properties', async () => {
109
+ await it('`maximized` and `fullscreened` square the frame off', async () => {
110
+ // _window.scss:66-72 — the two states with no corners and no shadow.
111
+ const { el, host } = mount();
112
+ el.maximized = true;
113
+ expect(el.classList.contains('maximized')).toBe(true);
114
+ el.maximized = false;
115
+ el.setAttribute('fullscreened', '');
116
+ expect(el.classList.contains('fullscreen')).toBe(true);
117
+ host.remove();
118
+ });
119
+
120
+ await it('`default-width`/`default-height` size the frame, and an absent one clears it', async () => {
121
+ const { el, host } = mount({ 'default-width': '480', 'default-height': '320' });
122
+ expect(el.style.width).toBe('480px');
123
+ expect(el.style.height).toBe('320px');
124
+ el.removeAttribute('default-width');
125
+ expect(el.style.width).toBe('');
126
+ host.remove();
127
+ });
128
+
129
+ await it("`title` is the window's accessible name", async () => {
130
+ const { el, host } = mount({ title: 'Documents' });
131
+ expect(el.getAttribute('aria-label')).toBe('Documents');
132
+ el.removeAttribute('title');
133
+ expect(el.hasAttribute('aria-label')).toBe(false);
134
+ host.remove();
135
+ });
136
+
137
+ await it('the frame buttons follow `deletable` and `resizable`', async () => {
138
+ // One read each, through the controls the window draws.
139
+ const { el, host } = mount();
140
+ el.deletable = false;
141
+ el.resizable = false;
142
+ await Promise.resolve();
143
+ await Promise.resolve();
144
+ expect(el.querySelector('.adw-window-controls-button.close')).toBe(null);
145
+ expect(el.querySelector('.adw-window-controls-button.maximize')).toBe(null);
146
+ expect(el.querySelector('.adw-window-controls-button.minimize')).not.toBe(null);
147
+ host.remove();
148
+ });
149
+
150
+ await it('the maximize button toggles `maximized` and says so', async () => {
151
+ const { el, host } = mount();
152
+ const button = el.querySelector('.adw-window-controls-button.maximize') as HTMLButtonElement;
153
+ expect(button.getAttribute('aria-label')).toBe('Maximize');
154
+ button.click();
155
+ expect(el.maximized).toBe(true);
156
+ host.remove();
157
+ });
158
+
159
+ await it('notifies once per real change', async () => {
160
+ const { el, host } = mount();
161
+ const events: unknown[] = [];
162
+ el.addEventListener('notify::resizable', (e) => events.push((e as CustomEvent).detail));
163
+ el.resizable = false;
164
+ el.resizable = false;
165
+ expect(events).toStrictEqual([{ resizable: false }]);
166
+ host.remove();
167
+ });
168
+ });
169
+
170
+ await describe('<gtk-window> close', async () => {
171
+ await it("detaches the frame, which is GTK's destroy branch", async () => {
172
+ // gtkwindow.c:1282-1285 — no hide-on-close, so `gtk_window_destroy`.
173
+ const { el, host } = mount();
174
+ let seen = 0;
175
+ el.addEventListener('close-request', () => {
176
+ seen += 1;
177
+ });
178
+ expect(el.close()).toBe(true);
179
+ expect(seen).toBe(1);
180
+ expect(el.isConnected).toBe(false);
181
+ host.remove();
182
+ });
183
+
184
+ await it('hides the frame when `hide-on-close` is set', async () => {
185
+ // gtkwindow.c:945 and the first branch of :1282.
186
+ const { el, host } = mount({ 'hide-on-close': 'true' });
187
+ el.close();
188
+ expect(el.isConnected).toBe(true);
189
+ expect(el.hidden).toBe(true);
190
+ host.remove();
191
+ });
192
+
193
+ await it('a handler that cancels `close-request` takes the whole thing over', async () => {
194
+ // gtkwindow.c:1300-1320 — `g_signal_stop_emission_by_name` on the default handler.
195
+ const { el, host } = mount();
196
+ el.addEventListener('close-request', (e) => e.preventDefault());
197
+ expect(el.close()).toBe(false);
198
+ expect(el.isConnected).toBe(true);
199
+ host.remove();
200
+ });
201
+ });
202
+ };
package/src/index.ts CHANGED
@@ -81,7 +81,8 @@ export type { AdwUndershootEdges } from './scroll-shading.js';
81
81
  // spec itself — has a route to it that is not a `.spec.ts` import; see that file's header
82
82
  // for why `mountSharedTree` and not `buildSharedTree` alone is the instantiation half.
83
83
  export { buildSharedTree, mountSharedTree } from './shared-tree-builder.js';
84
- export type { MountedSharedTree } from './shared-tree-builder.js';
84
+ export type { MountOptions, MountedSharedTree, SizeSource } from './shared-tree-builder.js';
85
+ export { registerTemplateClass } from './template-classes.js';
85
86
 
86
87
  // The stylesheet compiles a chosen SUBSET of `@gjsify/adwaita-icons` (the whole set is
87
88
  // ~1.07 MB of data-URI), so a name outside it draws the `image-missing` fallback. This is
@@ -156,6 +157,13 @@ export { AdwViewSwitcherPage } from './elements/adw-view-switcher.js';
156
157
  export { AdwViewStackPage } from './elements/adw-inline-view-switcher.js';
157
158
  export { AdwSidebarItem, AdwSidebarSection } from './elements/adw-sidebar.js';
158
159
 
160
+ // The two halves of a shortcuts dialog, and the same objection the four above state:
161
+ // `AdwShortcutsSection` and `AdwShortcutsItem` descend from `GObject.Object` (they are
162
+ // `add()`ed to a dialog, not packed into one), so there is no GIR name to export them
163
+ // under. `AdwShortcutsDialog` itself IS a widget and has its namespace member.
164
+ export { AdwShortcutsSection } from './elements/adw-shortcuts-section.js';
165
+ export { AdwShortcutsItem } from './elements/adw-shortcuts-item.js';
166
+
159
167
  // Slot wrappers and a declarative response: on GTK these are `set_content()`,
160
168
  // `set_sheet()` and `add_response()` — calls, not widgets.
161
169
  export { AdwBottomSheetBottomBar, AdwBottomSheetContent, AdwBottomSheetSheet } from './elements/adw-bottom-sheet.js';
@@ -622,18 +622,57 @@ export const AdwKeyboardOperableTest = async () => {
622
622
  // Prose cannot hold that: this line fails the commit that adds it.
623
623
  // `<adw-inline-view-switcher>` has the same gap (status/open-todos/README.md).
624
624
  // `active-name` joined the list without touching the axis: it picks a toggle.
625
- expect([...AdwToggleGroup.observedAttributes]).toStrictEqual(['active', 'active-name', 'flat', 'round']);
625
+ // `sensitive` joined it for the same reason — it gates every button's `disabled`,
626
+ // never the axis. `keyboard-operable.spec.ts` below now pins the roving walk
627
+ // against a disabled toggle, which is what made that attribute safe to add.
628
+ expect([...AdwToggleGroup.observedAttributes]).toStrictEqual([
629
+ 'active',
630
+ 'active-name',
631
+ 'flat',
632
+ 'round',
633
+ 'sensitive',
634
+ ]);
626
635
  });
627
636
 
628
637
  await it('adw-toggle has no state a roving walk would have to skip', async () => {
629
- // `<adw-toggle-group>` passes its buttons to `attachRovingFocus` UNFILTERED,
630
- // which is only safe while no `<adw-toggle>` attribute can produce a disabled
631
- // or hidden button. That is a decision recorded in two comments and a ledger
632
- // entry, and this is the line that fails when it stops being true — the first
633
- // disabled toggle is otherwise a `focus()` the browser refuses, with nothing
634
- // in the walk to step over it. Grow this list and add the filter and its spec
635
- // in the same change (status/open-todos/README.md, `<adw-toggle>` has no `enabled`).
636
- expect([...AdwToggle.observedAttributes]).toStrictEqual(['label', 'icon-name']);
638
+ // `<adw-toggle-group>` FILTERS its buttons for `attachRovingFocus`, which is only
639
+ // necessary once some `<adw-toggle>` attribute can produce a disabled button.
640
+ // `enabled` is that attribute (`AdwToggle:enabled`), so this list is now the
641
+ // record of WHICH attributes can — `hidden` cannot, and no other one can.
642
+ // Grow it and the filter has to grow with it: an unskipped disabled toggle is a
643
+ // `focus()` the browser refuses, with nothing in the walk to step over it. The
644
+ // skip itself is pinned in the case below.
645
+ //
646
+ // `tooltip` is not a counterexample: it sets `title` and `aria-label`, which
647
+ // change neither reachability nor rendering.
648
+ expect([...AdwToggle.observedAttributes]).toStrictEqual(['label', 'icon-name', 'tooltip', 'enabled']);
649
+ });
650
+
651
+ await it('adw-toggle-group arrow skips a disabled toggle', async () => {
652
+ // `AdwToggle:enabled` reached the web element with #1818, and the filter
653
+ // `roving-focus.ts` asks of every caller is the price of it — the same obligation
654
+ // `<adw-sidebar>` already pays ("arrow skips a disabled row", above). A disabled
655
+ // `<button>` cannot take focus, so leaving it in the walk strands the user on a
656
+ // `focus()` the browser refuses.
657
+ withWidget(
658
+ () => {
659
+ const el = document.createElement('adw-toggle-group');
660
+ el.innerHTML =
661
+ '<adw-toggle label="One"></adw-toggle>' +
662
+ '<adw-toggle label="Two" enabled="false"></adw-toggle>' +
663
+ '<adw-toggle label="Three"></adw-toggle>';
664
+ return el;
665
+ },
666
+ (el) => {
667
+ const items = rovingCase('adw-toggle-group').items(el);
668
+ expect(items.length).toBe(3);
669
+ expect((items[1] as HTMLButtonElement).disabled).toBe(true);
670
+
671
+ items[0].focus();
672
+ press(items[0], 'ArrowRight');
673
+ expect(document.activeElement).toBe(items[2]);
674
+ },
675
+ );
637
676
  });
638
677
 
639
678
  await it('adw-toggle-group notifies once per arrow, through the click path', async () => {
@@ -895,6 +934,35 @@ export const AdwKeyboardOperableTest = async () => {
895
934
  host.remove();
896
935
  });
897
936
 
937
+ // `<gtk-editable-label>` is the one GTK widget here whose focus moves WITH its
938
+ // state: the label is focusable and `editing` hands the focus to the entry
939
+ // (gtkeditablelabel.c:614,652), so the tab stop has to move with it or a Tab would
940
+ // reach a control the user cannot see.
941
+ await it('gtk-editable-label moves its tab stop with its state', () => {
942
+ const host = mount('<gtk-editable-label id="k-ed" text="Ada"></gtk-editable-label>');
943
+ const el = document.getElementById('k-ed') as HTMLElement & {
944
+ entry: HTMLInputElement;
945
+ startEditing: () => void;
946
+ stopEditing: (commit?: boolean) => void;
947
+ };
948
+
949
+ expect(el.getAttribute('tabindex')).toBe('0');
950
+ expect(el.entry.tabIndex).toBe(-1);
951
+ el.focus();
952
+ expect(document.activeElement).toBe(el);
953
+
954
+ el.startEditing();
955
+ expect(el.hasAttribute('tabindex')).toBe(false);
956
+ expect(document.activeElement).toBe(el.entry);
957
+
958
+ // …and back: the widget owns the focus once the edit is over, so the next Tab
959
+ // starts from the label rather than from inside a collapsed edit mode.
960
+ el.stopEditing(true);
961
+ expect(el.getAttribute('tabindex')).toBe('0');
962
+ expect(document.activeElement).toBe(el);
963
+ host.remove();
964
+ });
965
+
898
966
  await it('activates on Enter and Space, and lets a child keep its own keys', () => {
899
967
  const host = mount(
900
968
  '<adw-action-row id="k-keys" title="Keys" activatable></adw-action-row>' +
@@ -0,0 +1,121 @@
1
+ // What `<gtk-list-view>`, `<gtk-grid-view>` and `<gtk-column-view>` share in the DOM —
2
+ // the default factory and the rubber band (ADR 0089).
3
+ //
4
+ // The three views derive from `GtkListBase` upstream and share its item manager, its
5
+ // selection function and its rubberband gesture. The SELECTION half of that is portable
6
+ // and lives in `@gjsify/adwaita-core`'s `ListViewState` (ADR 0004); what is left here is
7
+ // genuinely a DOM job — a pointer drag, a rectangle, and the node a factory builds — and
8
+ // is shared for the reason the second copy always is: three elements writing the same
9
+ // hit test is three places for it to be subtly different.
10
+ //
11
+ // Reference: refs/gtk/gtk/gtklistbase.c (the rubberband gesture and its `rubberband` node)
12
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_views.scss:47-50 (`rubberband`)
13
+ // Copyright (c) GNOME contributors (GTK/libadwaita). LGPLv2.1+.
14
+
15
+ import type { AdwListItemContext, AdwListItemFactory } from '@gjsify/adwaita-core';
16
+
17
+ /** The class every row/cell label carries, so one stylesheet rule reaches all three views. */
18
+ export const LIST_ITEM_LABEL_CLASS = 'adw-list-item-label';
19
+
20
+ /**
21
+ * What a view draws for an item when no `factory` was set.
22
+ *
23
+ * GTK HAS NO DEFAULT FACTORY — `gtk_list_view_new (model, NULL)` is legal and draws empty
24
+ * rows, which on a documentation surface is indistinguishable from a broken widget. So
25
+ * the port's default is the factory every upstream example writes by hand: a label bound
26
+ * to the item. Setting `factory` replaces it, and that is the only way to get GTK's own
27
+ * answer back.
28
+ */
29
+ export const defaultListItemFactory: AdwListItemFactory<Node> = (context: AdwListItemContext) => {
30
+ const label = document.createElement('span');
31
+ label.className = LIST_ITEM_LABEL_CLASS;
32
+ label.textContent = context.item.label;
33
+ return label;
34
+ };
35
+
36
+ /** What {@link attachRubberBand} needs to know about the view it bands. */
37
+ export interface AdwRubberBandInit {
38
+ /** The element the pointer listeners sit on. */
39
+ host: HTMLElement;
40
+ /** The positioned box the band is drawn inside — the row container. */
41
+ surface: HTMLElement;
42
+ /** Whether a drag may start right now: `enable-rubberband` AND a multiple selection. */
43
+ enabled: () => boolean;
44
+ /** The row elements, in model order. */
45
+ rows: () => readonly HTMLElement[];
46
+ /** Select every position the band covers, replacing the selection. */
47
+ selectPositions: (positions: readonly number[]) => void;
48
+ }
49
+
50
+ /**
51
+ * Rubberband selection — drag on the view's background to select what the rectangle
52
+ * covers.
53
+ *
54
+ * GTK runs this as a drag gesture on `GtkListBase` and draws a `rubberband` CSS node,
55
+ * which libadwaita styles as an accent border over a 20% accent fill
56
+ * (`_views.scss:47-50`); this builds the same node and lets that rule reach it.
57
+ *
58
+ * THE DRAG MUST START ON THE BACKGROUND. A press that lands on a row is that row's click
59
+ * — GTK's row gesture claims the sequence — so starting a band there would make every
60
+ * click a one-pixel drag and swallow the row's own selection step.
61
+ *
62
+ * The hit test is `getBoundingClientRect` per row against the band, which is the same
63
+ * question GTK answers against its tile areas. It is recomputed per pointermove rather
64
+ * than cached: a row's box can change mid-drag (a scroll, a factory that lays out late),
65
+ * and a cached rectangle would select the wrong rows without anything looking wrong.
66
+ */
67
+ export function attachRubberBand(init: AdwRubberBandInit): void {
68
+ let band: HTMLElement | null = null;
69
+ let origin: { x: number; y: number } | null = null;
70
+ let pointerId: number | null = null;
71
+
72
+ const stop = () => {
73
+ band?.remove();
74
+ band = null;
75
+ origin = null;
76
+ if (pointerId !== null && init.host.hasPointerCapture(pointerId)) {
77
+ init.host.releasePointerCapture(pointerId);
78
+ }
79
+ pointerId = null;
80
+ };
81
+
82
+ init.host.addEventListener('pointerdown', (event) => {
83
+ if (event.button !== 0 || !init.enabled()) return;
84
+ const target = event.target as Node | null;
85
+ if (target !== null && init.rows().some((row) => row === target || row.contains(target))) return;
86
+
87
+ origin = { x: event.clientX, y: event.clientY };
88
+ pointerId = event.pointerId;
89
+ init.host.setPointerCapture(event.pointerId);
90
+ band = document.createElement('div');
91
+ band.className = 'adw-rubberband';
92
+ band.setAttribute('aria-hidden', 'true');
93
+ init.surface.appendChild(band);
94
+ });
95
+
96
+ init.host.addEventListener('pointermove', (event) => {
97
+ if (origin === null || band === null) return;
98
+ const box = init.surface.getBoundingClientRect();
99
+ const left = Math.min(origin.x, event.clientX);
100
+ const top = Math.min(origin.y, event.clientY);
101
+ const width = Math.abs(event.clientX - origin.x);
102
+ const height = Math.abs(event.clientY - origin.y);
103
+ band.style.left = `${left - box.left}px`;
104
+ band.style.top = `${top - box.top}px`;
105
+ band.style.width = `${width}px`;
106
+ band.style.height = `${height}px`;
107
+
108
+ const covered: number[] = [];
109
+ init.rows().forEach((row, position) => {
110
+ const rect = row.getBoundingClientRect();
111
+ const hit =
112
+ rect.right >= left && rect.left <= left + width && rect.bottom >= top && rect.top <= top + height;
113
+ if (hit) covered.push(position);
114
+ });
115
+ init.selectPositions(covered);
116
+ });
117
+
118
+ for (const name of ['pointerup', 'pointercancel', 'lostpointercapture']) {
119
+ init.host.addEventListener(name, stop);
120
+ }
121
+ }