@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,141 @@
1
+ // DOM-level tests for <gtk-overlay>. It has no scalar GIR property of its own — `child` is
2
+ // a widget — so what matters here is the SLOT ROUTING that stands in for
3
+ // `set_child` / `add_overlay`, and the `get_child_position` alignment the stylesheet's
4
+ // flex layer reproduces: a child with no `halign` FILLS, one that names an alignment is
5
+ // placed by the generic auto-margin rules, and the `.left` / `.right` / `.top` / `.bottom`
6
+ // classes say which edge each one ended up pinned to.
7
+ import { describe, expect, it } from '@gjsify/unit';
8
+
9
+ import type { GtkOverlay } from './elements/gtk-overlay.js';
10
+
11
+ function mount(children: { tag?: string; attrs?: Record<string, string>; slot?: string }[]): {
12
+ el: GtkOverlay;
13
+ host: HTMLElement;
14
+ } {
15
+ const host = document.createElement('div');
16
+ document.body.appendChild(host);
17
+ host.style.width = '200px';
18
+ host.style.height = '120px';
19
+ const el = document.createElement('gtk-overlay') as GtkOverlay;
20
+ for (const child of children) {
21
+ const node = document.createElement(child.tag ?? 'div');
22
+ for (const [name, value] of Object.entries(child.attrs ?? {})) {
23
+ node.setAttribute(name, value);
24
+ }
25
+ if (child.slot !== undefined) node.setAttribute('slot', child.slot);
26
+ node.style.width = '40px';
27
+ node.style.height = '20px';
28
+ el.appendChild(node);
29
+ }
30
+ host.appendChild(el);
31
+ return { el, host };
32
+ }
33
+
34
+ export const GtkOverlayTest = async () => {
35
+ await describe('<gtk-overlay> placement', async () => {
36
+ await it('routes the bare child to the main slot and slot="overlay" above it', () => {
37
+ const { el, host } = mount([
38
+ { tag: 'div', attrs: { id: 'main' } },
39
+ { tag: 'div', attrs: { id: 'badge' }, slot: 'overlay' },
40
+ ]);
41
+ expect(el.child?.id).toBe('main');
42
+ expect(el.overlayLayer.children.length).toBe(1);
43
+ expect(el.overlayLayer.firstElementChild?.id).toBe('badge');
44
+ // The layer is the `graphene_rect_init (0, 0, width, height)` of
45
+ // `gtk_overlay_snapshot_child`, so it covers the whole overlay.
46
+ const overlay = el.getBoundingClientRect();
47
+ const layer = el.overlayLayer.getBoundingClientRect();
48
+ expect(layer.width).toBe(overlay.width);
49
+ expect(layer.height).toBe(overlay.height);
50
+ host.remove();
51
+ });
52
+
53
+ await it('takes its size from the main child, which is laid out in the host flow', async () => {
54
+ const { el, host } = mount([{ tag: 'div', attrs: { id: 'main' } }]);
55
+ const main = el.child as HTMLElement;
56
+ main.style.height = '70px';
57
+ // `display: contents` is what keeps the child a DIRECT child of the host, so
58
+ // the overlay's own size is the child's.
59
+ expect(getComputedStyle(el.querySelector('.adw-overlay-child') as Element).display).toBe('contents');
60
+ await new Promise((resolve) => requestAnimationFrame(resolve));
61
+ expect(el.getBoundingClientRect().height).toBe(70);
62
+ host.remove();
63
+ });
64
+
65
+ await it('a child that names no alignment FILLS the overlay, as GTK_ALIGN_FILL does', () => {
66
+ const { el, host } = mount([{ tag: 'div' }, { tag: 'div', slot: 'overlay' }]);
67
+ const layer = el.overlayLayer.getBoundingClientRect();
68
+ const badge = el.overlayLayer.firstElementChild as HTMLElement;
69
+ const box = badge.getBoundingClientRect();
70
+ expect(box.width).toBe(layer.width);
71
+ expect(box.height).toBe(layer.height);
72
+ host.remove();
73
+ });
74
+
75
+ await it('an halign/valign places the overlay child and cancels the fill', () => {
76
+ const { el, host } = mount([
77
+ { tag: 'div' },
78
+ { tag: 'div', slot: 'overlay', attrs: { halign: 'end', valign: 'end' } },
79
+ ]);
80
+ const layer = el.overlayLayer.getBoundingClientRect();
81
+ const badge = el.overlayLayer.firstElementChild as HTMLElement;
82
+ const box = badge.getBoundingClientRect();
83
+ expect(box.width).toBe(40);
84
+ expect(box.height).toBe(20);
85
+ // `halign="end"` puts the child's right edge on the layer's right edge — the
86
+ // whole of `alloc->x += width - alloc->width`.
87
+ expect(Math.round(layer.right - box.right)).toBe(0);
88
+ expect(Math.round(layer.bottom - box.bottom)).toBe(0);
89
+ host.remove();
90
+ });
91
+
92
+ await it('the layer does not take input meant for the main child', () => {
93
+ const { el, host } = mount([{ tag: 'div' }, { tag: 'div', slot: 'overlay', attrs: { halign: 'start' } }]);
94
+ expect(getComputedStyle(el.overlayLayer).pointerEvents).toBe('none');
95
+ expect(getComputedStyle(el.overlayLayer.firstElementChild as Element).pointerEvents).toBe('auto');
96
+ host.remove();
97
+ });
98
+ });
99
+
100
+ await describe('<gtk-overlay> edge classes', async () => {
101
+ await it('marks the edges the alignment actually pinned the child to', async () => {
102
+ const { el, host } = mount([
103
+ { tag: 'div' },
104
+ { tag: 'div', slot: 'overlay', attrs: { id: 'tr', halign: 'end', valign: 'end' } },
105
+ ]);
106
+ await new Promise((resolve) => requestAnimationFrame(resolve));
107
+ const badge = el.overlayLayer.firstElementChild as HTMLElement;
108
+ // `gtk_overlay_child_update_style_classes` only marks START and END; FILL and
109
+ // CENTER are pinned to no edge at all.
110
+ expect(badge.classList.contains('right')).toBe(true);
111
+ expect(badge.classList.contains('bottom')).toBe(true);
112
+ expect(badge.classList.contains('left')).toBe(false);
113
+ expect(badge.classList.contains('top')).toBe(false);
114
+ host.remove();
115
+ });
116
+
117
+ await it('follows an alignment rewritten after connect', async () => {
118
+ const { el, host } = mount([{ tag: 'div' }, { tag: 'div', slot: 'overlay', attrs: { halign: 'start' } }]);
119
+ await new Promise((resolve) => requestAnimationFrame(resolve));
120
+ const badge = el.overlayLayer.firstElementChild as HTMLElement;
121
+ expect(badge.classList.contains('left')).toBe(true);
122
+ badge.setAttribute('halign', 'center');
123
+ await new Promise((resolve) => requestAnimationFrame(resolve));
124
+ expect(badge.classList.contains('left')).toBe(false);
125
+ expect(badge.classList.contains('right')).toBe(false);
126
+ host.remove();
127
+ });
128
+
129
+ await it('a child adopted after connect gets its classes too', async () => {
130
+ const { el, host } = mount([{ tag: 'div' }]);
131
+ const late = document.createElement('div');
132
+ late.setAttribute('slot', 'overlay');
133
+ late.setAttribute('valign', 'end');
134
+ el.appendChild(late);
135
+ await new Promise((resolve) => requestAnimationFrame(resolve));
136
+ expect(late.classList.contains('bottom')).toBe(true);
137
+ expect(late.classList.contains('top')).toBe(false);
138
+ host.remove();
139
+ });
140
+ });
141
+ };
@@ -0,0 +1,267 @@
1
+ // DOM-level tests for <gtk-paned>. Two halves, and the split is the point:
2
+ //
3
+ // the ARITHMETIC — `gtk_paned_compute_position` (gtkpaned.c:1092-1146) as a pure function
4
+ // over its inputs, including the `last_allocation` branch that a flex layout cannot reach
5
+ // on its own, so it is pinned here rather than left to the browser;
6
+ //
7
+ // the PLACEMENT — the two slots, GTK's "no separator is drawn if one of the children is
8
+ // missing", the handle's ARIA window-splitter values, `move-handle`'s keys, and the
9
+ // `position` / `position-set` pairing where a write raises a flag the C declares
10
+ // read-only and a write of -1 lowers it again.
11
+ import { describe, expect, it } from '@gjsify/unit';
12
+
13
+ import { computePanedPosition, type GtkPaned, type PanedPositionInput } from './elements/gtk-paned.js';
14
+
15
+ /** The two children every fixture mounts: 100px and 300px of request, as GTK would measure. */
16
+ function input(over: Partial<PanedPositionInput> = {}): PanedPositionInput {
17
+ return {
18
+ allocation: 400,
19
+ startRequest: 100,
20
+ endRequest: 300,
21
+ resizeStart: true,
22
+ resizeEnd: true,
23
+ shrinkStart: true,
24
+ shrinkEnd: true,
25
+ positionSet: false,
26
+ startChildSize: 0,
27
+ lastAllocation: 0,
28
+ ...over,
29
+ };
30
+ }
31
+
32
+ function mount(attrs: Record<string, string> = {}): { el: GtkPaned; host: HTMLElement } {
33
+ const host = document.createElement('div');
34
+ document.body.appendChild(host);
35
+ host.style.width = '400px';
36
+ host.style.height = '120px';
37
+ const el = document.createElement('gtk-paned') as GtkPaned;
38
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
39
+ const start = document.createElement('div');
40
+ start.id = 'start';
41
+ start.style.width = '100px';
42
+ start.style.height = '40px';
43
+ const end = document.createElement('div');
44
+ end.setAttribute('slot', 'end');
45
+ end.id = 'end';
46
+ end.style.width = '300px';
47
+ end.style.height = '40px';
48
+ el.append(start, end);
49
+ host.appendChild(el);
50
+ return { el, host };
51
+ }
52
+
53
+ /** Collect the `detail` of every `event` dispatched on `el`. */
54
+ function record(el: HTMLElement, event: string): unknown[] {
55
+ const details: unknown[] = [];
56
+ el.addEventListener(event, (e) => details.push((e as CustomEvent).detail));
57
+ return details;
58
+ }
59
+
60
+ export const GtkPanedTest = async () => {
61
+ await describe('gtk_paned_compute_position', async () => {
62
+ await it('divides in proportion to the two size requests when both resize', () => {
63
+ // `pos = allocation * ((double)start_child_req / (start_child_req +
64
+ // end_child_req)) + 0.5` — 400 * 100/400 is an exact 100, and the +0.5 floors.
65
+ expect(computePanedPosition(input())).toStrictEqual({ min: 0, max: 400, position: 100 });
66
+ expect(computePanedPosition(input({ startRequest: 300, endRequest: 100 }))).toStrictEqual({
67
+ min: 0,
68
+ max: 400,
69
+ position: 300,
70
+ });
71
+ });
72
+
73
+ await it('halves when neither child has a request, rather than dividing by zero', () => {
74
+ expect(computePanedPosition(input({ startRequest: 0, endRequest: 0 }))).toStrictEqual({
75
+ min: 0,
76
+ max: 400,
77
+ position: 200,
78
+ });
79
+ });
80
+
81
+ await it('gives a non-resizing start child its own request, and a non-resizing end the rest', () => {
82
+ expect(computePanedPosition(input({ resizeStart: false, resizeEnd: true })).position).toBe(100);
83
+ expect(computePanedPosition(input({ resizeStart: true, resizeEnd: false })).position).toBe(100); // MAX (0, 400 - 300)
84
+ });
85
+
86
+ await it('clamps against the shrink flags, and GLib tests the high bound first', () => {
87
+ // `min = shrink_start_child ? 0 : start_child_req` — a start child that may not
88
+ // shrink has a floor of its own request, and `max = MAX (min, max)` inverts
89
+ // whenever the two disagree, which is why this is GLib's CLAMP and not
90
+ // Math.min/Math.max.
91
+ expect(computePanedPosition(input({ shrinkStart: false })).min).toBe(100);
92
+ expect(computePanedPosition(input({ shrinkEnd: false })).max).toBe(100);
93
+ expect(computePanedPosition(input({ shrinkStart: false, shrinkEnd: false }))).toStrictEqual({
94
+ min: 100,
95
+ max: 100,
96
+ position: 100,
97
+ });
98
+ });
99
+
100
+ await it('scales an existing position when the paned grows, and holds it before that', () => {
101
+ // "If the position was set before the initial allocation … just clamp it and
102
+ // leave it": `last_allocation > 0` is false, so the position is taken as it is.
103
+ expect(computePanedPosition(input({ positionSet: true, startChildSize: 220 })).position).toBe(220);
104
+ // Once there IS a previous allocation, the divider keeps its share of it.
105
+ expect(
106
+ computePanedPosition(input({ positionSet: true, startChildSize: 100, lastAllocation: 400 })).position,
107
+ ).toBe(100);
108
+ expect(
109
+ computePanedPosition(
110
+ input({ positionSet: true, startChildSize: 100, lastAllocation: 400, allocation: 800 }),
111
+ ).position,
112
+ ).toBe(200);
113
+ // A non-resizing start child instead takes the whole growth.
114
+ expect(
115
+ computePanedPosition(
116
+ input({
117
+ positionSet: true,
118
+ startChildSize: 100,
119
+ lastAllocation: 400,
120
+ allocation: 800,
121
+ resizeEnd: false,
122
+ }),
123
+ ).position,
124
+ ).toBe(500);
125
+ });
126
+ });
127
+
128
+ await describe('<gtk-paned> placement', async () => {
129
+ await it('routes the bare child to the start pane and slot="end" to the other', () => {
130
+ const { el, host } = mount();
131
+ expect(el.startChild?.id).toBe('start');
132
+ expect(el.endChild?.id).toBe('end');
133
+ expect(el.getAttribute('role')).toBe('group');
134
+ host.remove();
135
+ });
136
+
137
+ await it('draws the divider as the separator node a GtkPanedHandle carries', () => {
138
+ const { el, host } = mount();
139
+ const handle = el.querySelector('.adw-paned-handle') as HTMLElement;
140
+ // `separator` is the handle's CSS NAME (gtkpanedhandle.c:88) and `role` is the
141
+ // ARIA reading of that node; `wide` is what `gtk_paned_set_wide_handle` adds.
142
+ expect(handle.classList.contains('separator')).toBe(true);
143
+ expect(handle.getAttribute('role')).toBe('separator');
144
+ expect(handle.tabIndex).toBe(0);
145
+ expect(handle.classList.contains('wide')).toBe(false);
146
+ expect(getComputedStyle(handle).backgroundColor).toBe('rgba(0, 0, 0, 0)');
147
+ el.wideHandle = true;
148
+ expect(handle.classList.contains('wide')).toBe(true);
149
+ expect(getComputedStyle(handle).minWidth).toBe('5px');
150
+ host.remove();
151
+ });
152
+
153
+ await it('the handle reports the divider as its accessible value', async () => {
154
+ const { el, host } = mount();
155
+ await new Promise((resolve) => requestAnimationFrame(resolve));
156
+ const handle = el.querySelector('.adw-paned-handle') as HTMLElement;
157
+ expect(handle.getAttribute('aria-orientation')).toBe('horizontal');
158
+ expect(handle.getAttribute('aria-valuemin')).toBe('0');
159
+ // GTK's VALUE_MAX is the paned's own width, handle included.
160
+ expect(Number(handle.getAttribute('aria-valuemax'))).toBeGreaterThan(el.position);
161
+ host.remove();
162
+ });
163
+
164
+ await it('draws no separator when one of the children is missing', async () => {
165
+ const host = document.createElement('div');
166
+ document.body.appendChild(host);
167
+ host.style.width = '200px';
168
+ host.style.height = '60px';
169
+ const el = document.createElement('gtk-paned') as GtkPaned;
170
+ const lone = document.createElement('div');
171
+ lone.style.width = '50px';
172
+ lone.style.height = '20px';
173
+ el.appendChild(lone);
174
+ host.appendChild(el);
175
+ await new Promise((resolve) => requestAnimationFrame(resolve));
176
+ // "No separator is drawn if one of the children is missing" (gtkpaned.c:70).
177
+ expect((el.querySelector('.adw-paned-handle') as HTMLElement).hidden).toBe(true);
178
+ host.remove();
179
+ });
180
+ });
181
+
182
+ await describe('<gtk-paned> position', async () => {
183
+ await it('an authored position raises position-set, as a setter would', async () => {
184
+ const { el, host } = mount({ position: '150' });
185
+ await new Promise((resolve) => requestAnimationFrame(resolve));
186
+ expect(el.position).toBe(150);
187
+ expect(el.positionSet).toBe(true);
188
+ host.remove();
189
+ });
190
+
191
+ await it('a write notifies position and position-set once each, a rewrite neither', () => {
192
+ const { el, host } = mount();
193
+ const position = record(el, 'notify::position');
194
+ const positionSet = record(el, 'notify::position-set');
195
+ el.position = 150;
196
+ el.position = 150;
197
+ expect(position.length).toBe(1);
198
+ expect(positionSet).toStrictEqual([{ positionSet: true }]);
199
+ host.remove();
200
+ });
201
+
202
+ await it('a write of -1 puts the divider back to being derived', () => {
203
+ const { el, host } = mount();
204
+ const positionSet = record(el, 'notify::position-set');
205
+ el.position = 150;
206
+ el.position = -1;
207
+ expect(el.positionSet).toBe(false);
208
+ expect(positionSet).toStrictEqual([{ positionSet: true }, { positionSet: false }]);
209
+ host.remove();
210
+ });
211
+
212
+ await it('an unparseable position attribute is not a position at all', async () => {
213
+ const { el, host } = mount({ position: 'halfway' });
214
+ await new Promise((resolve) => requestAnimationFrame(resolve));
215
+ expect(Number.isNaN(el.position)).toBe(false);
216
+ expect(el.positionSet).toBe(false);
217
+ host.remove();
218
+ });
219
+
220
+ await it("writes the divider as the start pane's basis, with no growth", async () => {
221
+ const { el, host } = mount({ position: '150' });
222
+ await new Promise((resolve) => requestAnimationFrame(resolve));
223
+ const start = el.querySelector('.adw-paned-child') as HTMLElement;
224
+ // `start_child_allocation.width = MAX (1, start_child_size)`.
225
+ expect(start.style.flexBasis).toBe('150px');
226
+ expect(start.style.flexGrow).toBe('0');
227
+ host.remove();
228
+ });
229
+ });
230
+
231
+ await describe('<gtk-paned> keyboard', async () => {
232
+ await it("move-handle steps by one and pages by 75, the C's two constants", async () => {
233
+ const { el, host } = mount({ position: '150' });
234
+ await new Promise((resolve) => requestAnimationFrame(resolve));
235
+ const handle = el.querySelector('.adw-paned-handle') as HTMLElement;
236
+ handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
237
+ expect(el.position).toBe(151);
238
+ handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'PageDown', bubbles: true }));
239
+ expect(el.position).toBe(226);
240
+ host.remove();
241
+ });
242
+
243
+ await it('Home and End are GTK_SCROLL_START and GTK_SCROLL_END, so the two bounds', async () => {
244
+ const { el, host } = mount({ position: '150' });
245
+ await new Promise((resolve) => requestAnimationFrame(resolve));
246
+ const handle = el.querySelector('.adw-paned-handle') as HTMLElement;
247
+ handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
248
+ expect(el.position).toBe(el.minPosition);
249
+ handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
250
+ expect(el.position).toBe(el.maxPosition);
251
+ host.remove();
252
+ });
253
+
254
+ await it('Return and Escape are accept-position and cancel-position, dispatched not swallowed', async () => {
255
+ const { el, host } = mount({ position: '150' });
256
+ const accepted = record(el, 'accept-position');
257
+ const cancelled = record(el, 'cancel-position');
258
+ const handle = el.querySelector('.adw-paned-handle') as HTMLElement;
259
+ handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
260
+ handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
261
+ expect(accepted.length).toBe(1);
262
+ expect(cancelled.length).toBe(1);
263
+ expect(el.position).toBe(150);
264
+ host.remove();
265
+ });
266
+ });
267
+ };
@@ -0,0 +1,150 @@
1
+ // DOM-level tests for <gtk-password-entry>. It composes `<gtk-entry>`'s input, so what is
2
+ // under test is the half C adds: masked by default, the peek button off unless
3
+ // `show-peek-icon` is asked for, and the Caps Lock warning shown only while the field has
4
+ // focus AND the text is still masked — the two rules `PasswordEntryRowState` derives.
5
+ import { describe, expect, it } from '@gjsify/unit';
6
+
7
+ import type { GtkPasswordEntry } from './elements/gtk-password-entry.js';
8
+
9
+ function mount(attrs: Record<string, string> = {}): { el: GtkPasswordEntry; host: HTMLElement } {
10
+ const host = document.createElement('div');
11
+ document.body.appendChild(host);
12
+ const el = document.createElement('gtk-password-entry') as GtkPasswordEntry;
13
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
14
+ host.appendChild(el);
15
+ return { el, host };
16
+ }
17
+
18
+ function inner(el: GtkPasswordEntry): HTMLInputElement {
19
+ return el.querySelector('input') as HTMLInputElement;
20
+ }
21
+
22
+ function peek(el: GtkPasswordEntry): HTMLButtonElement {
23
+ return el.querySelector('.adw-password-entry-peek') as HTMLButtonElement;
24
+ }
25
+
26
+ function indicator(el: GtkPasswordEntry): HTMLElement {
27
+ return el.querySelector('.adw-password-entry-caps-lock') as HTMLElement;
28
+ }
29
+
30
+ export const GtkPasswordEntryTest = async () => {
31
+ await describe('<gtk-password-entry> masking', async () => {
32
+ await it('starts masked, with the password input purpose a password field asks for', () => {
33
+ const { el, host } = mount();
34
+ expect(inner(el).type).toBe('password');
35
+ // Read the ATTRIBUTE, not the IDL property: Firefox's form autofill owns the
36
+ // reflected `autocomplete` IDL attribute and answers '' for a field it manages.
37
+ expect(inner(el).getAttribute('autocomplete')).toBe('new-password');
38
+ expect(el.revealed).toBe(false);
39
+ expect(el.hasAttribute('revealed')).toBe(false);
40
+ host.remove();
41
+ });
42
+
43
+ await it('show-peek-icon is off by default and the toggle appears with it', () => {
44
+ const { el, host } = mount();
45
+ expect(peek(el).hidden).toBe(true);
46
+ el.setAttribute('show-peek-icon', '');
47
+ expect(peek(el).hidden).toBe(false);
48
+ host.remove();
49
+ });
50
+
51
+ await it('the peek button reveals, then conceals again, and notifies once each', async () => {
52
+ const { el, host } = mount({ 'show-peek-icon': '' });
53
+ const notified: unknown[] = [];
54
+ el.addEventListener('notify::revealed', (e) => notified.push((e as CustomEvent).detail));
55
+ peek(el).click();
56
+ expect(el.revealed).toBe(true);
57
+ expect(inner(el).type).toBe('text');
58
+ expect(el.hasAttribute('revealed')).toBe(true);
59
+ expect(peek(el).getAttribute('aria-pressed')).toBe('true');
60
+ peek(el).click();
61
+ expect(inner(el).type).toBe('password');
62
+ expect(notified).toStrictEqual([{ revealed: true }, { revealed: false }]);
63
+ host.remove();
64
+ });
65
+
66
+ await it('the peek glyph swaps between reveal and conceal, carrying the libadwaita name', () => {
67
+ const { el, host } = mount({ 'show-peek-icon': '' });
68
+ const icon = peek(el).querySelector('gtk-image') as HTMLElement;
69
+ expect(icon.dataset.iconName).toBe('view-reveal-symbolic');
70
+ expect(icon.classList.contains('adw-icon--view-reveal')).toBe(true);
71
+ el.revealed = true;
72
+ expect(icon.dataset.iconName).toBe('view-conceal-symbolic');
73
+ expect(icon.classList.contains('adw-icon--view-conceal')).toBe(true);
74
+ host.remove();
75
+ });
76
+
77
+ await it('re-setting the same revealed state notifies nothing', () => {
78
+ const { el, host } = mount({ 'show-peek-icon': '' });
79
+ const notified: unknown[] = [];
80
+ el.addEventListener('notify::revealed', (e) => notified.push((e as CustomEvent).detail));
81
+ el.revealed = false;
82
+ el.revealed = false;
83
+ expect(notified.length).toBe(0);
84
+ host.remove();
85
+ });
86
+ });
87
+
88
+ await describe('<gtk-password-entry> caps lock', async () => {
89
+ await it('is off until the keyboard reports it, and never on while unfocused', () => {
90
+ const { el, host } = mount();
91
+ expect(el.capsLockOn).toBe(false);
92
+ expect(indicator(el).hidden).toBe(true);
93
+ el.setCapsLockOn(true);
94
+ expect(el.capsLockOn).toBe(true);
95
+ // `editing && show_indicator` — the focus condition GTK's own
96
+ // `caps_lock_state_changed` has and the core derives.
97
+ expect(indicator(el).hidden).toBe(true);
98
+ inner(el).focus();
99
+ expect(indicator(el).hidden).toBe(false);
100
+ expect(indicator(el).dataset.iconName).toBe('caps-lock-symbolic');
101
+ expect(indicator(el).title).toBe('Caps Lock is on');
102
+ host.remove();
103
+ });
104
+
105
+ await it('peeking retracts the warning in the same turn, as C does', () => {
106
+ const { el, host } = mount({ 'show-peek-icon': '' });
107
+ inner(el).focus();
108
+ el.setCapsLockOn(true);
109
+ expect(indicator(el).hidden).toBe(false);
110
+ el.revealed = true;
111
+ expect(indicator(el).hidden).toBe(true);
112
+ el.revealed = false;
113
+ expect(indicator(el).hidden).toBe(false);
114
+ host.remove();
115
+ });
116
+
117
+ await it('a keyboard event with Caps Lock engaged feeds the derivation', () => {
118
+ const { el, host } = mount();
119
+ // `modifierCapsLock` is a Firefox extension to `KeyboardEventInit` and the only
120
+ // way a dispatched event can report Caps Lock; `getModifierState` is not an init
121
+ // member, so passing it as one is silently dropped.
122
+ inner(el).dispatchEvent(
123
+ new KeyboardEvent('keydown', { key: 'A', bubbles: true, modifierCapsLock: true } as KeyboardEventInit),
124
+ );
125
+ expect(el.capsLockOn).toBe(true);
126
+ inner(el).dispatchEvent(new KeyboardEvent('keyup', { key: 'A', bubbles: true }));
127
+ expect(el.capsLockOn).toBe(false);
128
+ host.remove();
129
+ });
130
+ });
131
+
132
+ await describe('<gtk-password-entry> as an entry', async () => {
133
+ await it('keeps the value, placeholder and disabled behaviour it inherits', () => {
134
+ const { el, host } = mount({ value: 'hunter2', placeholder: 'Password', disabled: '' });
135
+ expect(el.value).toBe('hunter2');
136
+ expect(inner(el).placeholder).toBe('Password');
137
+ expect(inner(el).disabled).toBe(true);
138
+ host.remove();
139
+ });
140
+
141
+ await it('Enter activates, which Gtk.PasswordEntry signals on all forms of Enter', () => {
142
+ const { el, host } = mount();
143
+ let count = 0;
144
+ el.addEventListener('activate', () => (count += 1));
145
+ inner(el).dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }));
146
+ expect(count).toBe(1);
147
+ host.remove();
148
+ });
149
+ });
150
+ };