@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,125 @@
1
+ // DOM-level tests for <gtk-center-box>: the three slots are read off each child's `slot=`
2
+ // (so the markup order is not the layout's), `shrink-center-last` becomes the flex WEIGHTS
3
+ // that reproduce GTK's order, and `baseline-position` only moves the children when authored.
4
+ import { describe, expect, it } from '@gjsify/unit';
5
+
6
+ import type { GtkCenterBox } from './elements/gtk-center-box.js';
7
+
8
+ const SLOT_CHILD = (role: string, text: string): HTMLElement => {
9
+ const el = document.createElement('gtk-label');
10
+ el.setAttribute('slot', role);
11
+ el.setAttribute('label', text);
12
+ return el;
13
+ };
14
+
15
+ function mount(attrs: Record<string, string> = {}): { el: GtkCenterBox; host: HTMLElement } {
16
+ const host = document.createElement('div');
17
+ host.style.width = '300px';
18
+ document.body.appendChild(host);
19
+ const el = document.createElement('gtk-center-box') as GtkCenterBox;
20
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
21
+ el.append(
22
+ SLOT_CHILD('start-widget', 'Start'),
23
+ SLOT_CHILD('center-widget', 'Centre'),
24
+ SLOT_CHILD('end-widget', 'End'),
25
+ );
26
+ host.appendChild(el);
27
+ return { el, host };
28
+ }
29
+
30
+ /** The `flex-shrink` the element wrote on each of the three slots. */
31
+ const weights = (el: GtkCenterBox): Record<string, string> => ({
32
+ start: (el.startWidget as HTMLElement).style.flexShrink,
33
+ center: (el.centerWidget as HTMLElement).style.flexShrink,
34
+ end: (el.endWidget as HTMLElement).style.flexShrink,
35
+ });
36
+
37
+ export const GtkCenterBoxTest = async () => {
38
+ await describe('<gtk-center-box> slots', async () => {
39
+ await it('reads the three widgets off their slot names', () => {
40
+ const { el, host } = mount();
41
+ expect(el.startWidget?.getAttribute('label')).toBe('Start');
42
+ expect(el.centerWidget?.getAttribute('label')).toBe('Centre');
43
+ expect(el.endWidget?.getAttribute('label')).toBe('End');
44
+ expect(el.getAttribute('role')).toBe('generic');
45
+ host.remove();
46
+ });
47
+
48
+ await it('a child assigned through the property takes that slot', () => {
49
+ const { el, host } = mount();
50
+ const late = document.createElement('gtk-label');
51
+ late.setAttribute('label', 'Late');
52
+ el.endWidget = late;
53
+ expect(el.endWidget).toBe(late);
54
+ expect(el.endWidget?.style.flexShrink).toBe('100');
55
+ host.remove();
56
+ });
57
+
58
+ await it('the children sit at the start, the middle and the end of the box', () => {
59
+ const { el, host } = mount();
60
+ const box = el.getBoundingClientRect();
61
+ expect(Math.round((el.startWidget as HTMLElement).getBoundingClientRect().left - box.left)).toBe(0);
62
+ expect(Math.round(box.right - (el.endWidget as HTMLElement).getBoundingClientRect().right)).toBe(0);
63
+ host.remove();
64
+ });
65
+ });
66
+
67
+ await describe('<gtk-center-box> shrink-center-last', async () => {
68
+ await it('is TRUE by default, and the centre then carries the small weight', () => {
69
+ const { el, host } = mount();
70
+ expect(el.shrinkCenterLast).toBe(true);
71
+ // The START and END children are the ones that shrink FIRST, so they get the
72
+ // large weight (gtkcenterlayout.c:150-158 with the default TRUE).
73
+ expect(weights(el)).toStrictEqual({ start: '100', center: '1', end: '100' });
74
+ host.remove();
75
+ });
76
+
77
+ await it('flips the weights when the attribute says the centre shrinks first', () => {
78
+ const { el, host } = mount({ 'shrink-center-last': 'false' });
79
+ expect(el.shrinkCenterLast).toBe(false);
80
+ expect(weights(el)).toStrictEqual({ start: '1', center: '100', end: '1' });
81
+ host.remove();
82
+ });
83
+
84
+ await it('an unknown nick is the default, and writing the value already held notifies nothing', () => {
85
+ const { el, host } = mount();
86
+ const notified: unknown[] = [];
87
+ el.addEventListener('notify::shrink-center-last', (e) => notified.push((e as CustomEvent).detail));
88
+ // The pspec default is TRUE, and the setter compares against it
89
+ // (gtkcenterbox.c:596-602), so writing TRUE back is not a change — while the
90
+ // write that IS one notifies exactly once.
91
+ el.shrinkCenterLast = true;
92
+ expect(el.shrinkCenterLast).toBe(true);
93
+ expect(notified).toStrictEqual([]);
94
+ el.shrinkCenterLast = false;
95
+ expect(el.getAttribute('shrink-center-last')).toBe('false');
96
+ el.shrinkCenterLast = false;
97
+ expect(notified).toStrictEqual([{ 'shrink-center-last': false }]);
98
+ host.remove();
99
+ });
100
+ });
101
+
102
+ await describe('<gtk-center-box> baseline-position', async () => {
103
+ await it('is the centre position by default and leaves the stylesheet to stretch', () => {
104
+ const { el, host } = mount();
105
+ expect(el.baselinePosition).toBe('center');
106
+ // Nothing inline: the default position must not change the default look, and the
107
+ // stylesheet's `align-items: stretch` is what a box of FILL children draws.
108
+ expect(el.style.alignItems).toBe('');
109
+ expect(getComputedStyle(el).alignItems).toBe('stretch');
110
+ host.remove();
111
+ });
112
+
113
+ await it('the three nicks move the children in the extra space', () => {
114
+ const { el, host } = mount({ 'baseline-position': 'top' });
115
+ expect(el.baselinePosition).toBe('top');
116
+ expect(el.style.alignItems).toBe('flex-start');
117
+ el.baselinePosition = 'bottom';
118
+ expect(el.style.alignItems).toBe('flex-end');
119
+ el.setAttribute('baseline-position', 'middle');
120
+ expect(el.baselinePosition).toBe('center');
121
+ expect(el.style.alignItems).toBe('center');
122
+ host.remove();
123
+ });
124
+ });
125
+ };
@@ -0,0 +1,141 @@
1
+ // DOM-level tests for <gtk-color-dialog-button>. The ported rules are GTK's: the button is
2
+ // INSENSITIVE until a dialog is set, `set_rgba` refuses a write of the colour it already
3
+ // holds, and the swatch's accessible name is the channel percentages — with the Alpha
4
+ // clause only while the colour is translucent.
5
+ import { describe, expect, it } from '@gjsify/unit';
6
+
7
+ import type { GtkColorDialogButton } from './elements/gtk-color-dialog-button.js';
8
+
9
+ function mount(attrs: Record<string, string> = {}): {
10
+ el: GtkColorDialogButton;
11
+ host: HTMLElement;
12
+ button: HTMLButtonElement;
13
+ input: HTMLInputElement;
14
+ } {
15
+ const host = document.createElement('div');
16
+ document.body.appendChild(host);
17
+ const el = document.createElement('gtk-color-dialog-button') as GtkColorDialogButton;
18
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
19
+ host.appendChild(el);
20
+ const button = el.querySelector('button') as HTMLButtonElement;
21
+ const input = el.querySelector('input') as HTMLInputElement;
22
+ // The chooser is a native `<input type="color">`; opening it for real would block the
23
+ // suite, so the click on it is what stands in for the platform picker.
24
+ input.click = () => {};
25
+ return { el, host, button, input };
26
+ }
27
+
28
+ export const GtkColorDialogButtonTest = async () => {
29
+ await describe('<gtk-color-dialog-button> sensitivity', async () => {
30
+ await it('is insensitive until a dialog is set — the first half of the C’s rule', () => {
31
+ const { el, host, button } = mount();
32
+ expect(button.disabled).toBe(true);
33
+ el.dialog = {};
34
+ expect(button.disabled).toBe(false);
35
+ el.dialog = null;
36
+ expect(button.disabled).toBe(true);
37
+ host.remove();
38
+ });
39
+
40
+ await it('a dialog written in markup counts as one', () => {
41
+ const { host, button } = mount({ dialog: '' });
42
+ expect(button.disabled).toBe(false);
43
+ host.remove();
44
+ });
45
+
46
+ await it('the disabled attribute is the author’s own switch, beside the dialog gate', () => {
47
+ const { el, host, button } = mount({ dialog: '' });
48
+ el.setAttribute('disabled', '');
49
+ expect(button.disabled).toBe(true);
50
+ el.removeAttribute('disabled');
51
+ expect(button.disabled).toBe(false);
52
+ host.remove();
53
+ });
54
+ });
55
+
56
+ await describe('<gtk-color-dialog-button> rgba', async () => {
57
+ await it('opens on the colour init gives it, not on black', () => {
58
+ const { el, host } = mount();
59
+ expect(el.rgba.red).toBe(0.75);
60
+ expect(el.rgba.green).toBe(0.25);
61
+ expect(el.rgba.blue).toBe(0.25);
62
+ expect(el.rgba.alpha).toBe(1);
63
+ host.remove();
64
+ });
65
+
66
+ await it('reads every CSS colour the browser knows, because CSSOM parses it', () => {
67
+ const { el, host } = mount({ rgba: '#3584e4' });
68
+ expect(el.rgba.red).toBeCloseTo(53 / 255, 4);
69
+ expect(el.rgba.green).toBeCloseTo(132 / 255, 4);
70
+ expect(el.rgba.blue).toBeCloseTo(228 / 255, 4);
71
+ el.setAttribute('rgba', 'rgba(255, 0, 0, 0.5)');
72
+ expect(el.rgba.alpha).toBe(0.5);
73
+ el.setAttribute('rgba', 'not-a-colour');
74
+ expect(el.rgba.red).toBeCloseTo(1, 4);
75
+ host.remove();
76
+ });
77
+
78
+ await it('a write of the colour already held changes nothing and notifies nothing', () => {
79
+ const { el, host } = mount({ rgba: '#ff0000' });
80
+ const notified: unknown[] = [];
81
+ el.addEventListener('notify::rgba', (e) => notified.push((e as CustomEvent).detail));
82
+ el.rgba = '#ff0000';
83
+ expect(notified.length).toBe(0);
84
+ el.rgba = { red: 0, green: 0, blue: 1, alpha: 1 };
85
+ expect(notified.length).toBe(1);
86
+ host.remove();
87
+ });
88
+ });
89
+
90
+ await describe('<gtk-color-dialog-button> accessible name', async () => {
91
+ await it('is the channel percentages, with Alpha only while translucent', () => {
92
+ const { el, host, button } = mount();
93
+ expect(button.getAttribute('aria-label')).toBe('Red 75%, Green 25%, Blue 25%');
94
+ el.rgba = 'rgba(255, 0, 0, 0.5)';
95
+ expect(button.getAttribute('aria-label')).toBe('Red 100%, Green 0%, Blue 0%, Alpha 50%');
96
+ host.remove();
97
+ });
98
+
99
+ await it('rounds half up, the way scale_round does', () => {
100
+ const { el, host, button } = mount();
101
+ // 0.255 is exactly the case a truncating round gets wrong.
102
+ el.rgba = { red: 0.255, green: 0.754, blue: 0.5, alpha: 1 };
103
+ expect(button.getAttribute('aria-label')).toBe('Red 26%, Green 75%, Blue 50%');
104
+ host.remove();
105
+ });
106
+ });
107
+
108
+ await describe('<gtk-color-dialog-button> chooser', async () => {
109
+ await it('a chosen colour lands on the button, and the alpha it already had survives', () => {
110
+ const { el, host, input } = mount({ dialog: '', rgba: '#ff0000' });
111
+ el.rgba = 'rgba(255, 0, 0, 0.25)';
112
+ el.activate();
113
+ expect(input.value).toBe('#ff0000');
114
+ input.value = '#0000ff';
115
+ input.dispatchEvent(new Event('change'));
116
+ expect(el.rgba.blue).toBe(1);
117
+ expect(el.rgba.alpha).toBe(0.25);
118
+ host.remove();
119
+ });
120
+
121
+ await it('is a group with a popup button, as GTK marks it', () => {
122
+ const { host, button } = mount({ dialog: '' });
123
+ expect(host.ownerDocument.activeElement).not.toBe(button);
124
+ expect(button.getAttribute('aria-haspopup')).toBe('dialog');
125
+ expect(host.firstElementChild?.getAttribute('role')).toBe('group');
126
+ host.remove();
127
+ });
128
+ });
129
+
130
+ await describe('<gtk-color-dialog-button> look', async () => {
131
+ await it('paints the swatch with the colour, and marks a translucent one', () => {
132
+ const { el, host } = mount({ rgba: '#3584e4' });
133
+ const swatch = el.querySelector('.color-button-swatch') as HTMLElement;
134
+ expect(getComputedStyle(swatch).backgroundColor).toBe('rgb(53, 132, 228)');
135
+ expect(swatch.dataset.translucent).toBe('false');
136
+ el.rgba = 'rgba(53, 132, 228, 0.5)';
137
+ expect(swatch.dataset.translucent).toBe('true');
138
+ host.remove();
139
+ });
140
+ });
141
+ };
@@ -0,0 +1,154 @@
1
+ // DOM-level tests for <gtk-column-view>: the header, one cell per visible column, the
2
+ // per-column factory, and the sort state a header click produces. The rows, the model and
3
+ // the selection are <gtk-list-view>'s and are asserted there; what is checked here is
4
+ // that they still arrive through the subclass.
5
+ import { describe, expect, it } from '@gjsify/unit';
6
+
7
+ import { COLUMN_VIEW_SORT_VECTORS } from '@gjsify/adwaita-core/conformance';
8
+
9
+ import type { GtkColumnView } from './elements/gtk-column-view.js';
10
+
11
+ const COLUMNS =
12
+ '[{"key":"label","id":"name","title":"Name","sortable":true},{"key":"value","id":"code","title":"Code"}]';
13
+
14
+ function mount(attrs: Record<string, string> = {}): { el: GtkColumnView; host: HTMLElement } {
15
+ const host = document.createElement('div');
16
+ document.body.appendChild(host);
17
+ const el = document.createElement('gtk-column-view') as GtkColumnView;
18
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
19
+ host.appendChild(el);
20
+ return { el, host };
21
+ }
22
+
23
+ const headers = (el: GtkColumnView): HTMLElement[] => [
24
+ ...el.querySelectorAll<HTMLElement>('.adw-column-view-header-cell'),
25
+ ];
26
+ const rows = (el: GtkColumnView): HTMLElement[] => [...el.querySelectorAll<HTMLElement>('.adw-column-view-row')];
27
+ const cellsOf = (row: HTMLElement): string[] =>
28
+ [...row.querySelectorAll<HTMLElement>('.adw-column-view-cell')].map((cell) => cell.textContent ?? '');
29
+
30
+ const MODEL = '[{"value":"de","label":"German"},{"value":"fr","label":"French"}]';
31
+
32
+ export const GtkColumnViewTest = async () => {
33
+ await describe('<gtk-column-view> header and cells', async () => {
34
+ await it('draws one header button per column and one cell per column per row', () => {
35
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
36
+ expect(headers(el).map((button) => button.textContent?.trim())).toStrictEqual(['Name', 'Code']);
37
+ expect(rows(el).length).toBe(2);
38
+ expect(cellsOf(rows(el)[0]!)).toStrictEqual(['German', 'de']);
39
+ expect(cellsOf(rows(el)[1]!)).toStrictEqual(['French', 'fr']);
40
+ host.remove();
41
+ });
42
+
43
+ await it('announces itself as a grid of rows, headers and cells', () => {
44
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
45
+ expect(el.getAttribute('role')).toBe('grid');
46
+ expect(headers(el)[0]!.getAttribute('role')).toBe('columnheader');
47
+ expect(rows(el)[0]!.getAttribute('role')).toBe('row');
48
+ expect(rows(el)[0]!.querySelector('.adw-column-view-cell')?.getAttribute('role')).toBe('gridcell');
49
+ host.remove();
50
+ });
51
+
52
+ await it('leaves an invisible column out of both the header and the rows', () => {
53
+ const { el, host } = mount({ model: MODEL });
54
+ el.columns = [
55
+ { key: 'label', id: 'name', title: 'Name' },
56
+ { key: 'value', id: 'code', title: 'Code', visible: false },
57
+ ];
58
+ expect(headers(el).length).toBe(1);
59
+ expect(cellsOf(rows(el)[0]!)).toStrictEqual(['German']);
60
+ host.remove();
61
+ });
62
+
63
+ await it('gives the header and every row the same track list', () => {
64
+ const { el, host } = mount({ model: MODEL });
65
+ el.columns = [
66
+ { key: 'label', id: 'name', fixedWidth: 120 },
67
+ { key: 'value', id: 'code', expand: true },
68
+ ];
69
+ const header = el.querySelector<HTMLElement>('.adw-column-view-header')!;
70
+ expect(header.style.gridTemplateColumns).toBe('120px 1fr');
71
+ expect(rows(el)[0]!.style.gridTemplateColumns).toBe('120px 1fr');
72
+ host.remove();
73
+ });
74
+
75
+ await it('draws a column with a factory instead of its portable field', () => {
76
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
77
+ el.columnFactories = {
78
+ code: (context) => {
79
+ const node = document.createElement('code');
80
+ node.textContent = context.item.value.toUpperCase();
81
+ return node;
82
+ },
83
+ };
84
+ expect(cellsOf(rows(el)[0]!)).toStrictEqual(['German', 'DE']);
85
+ host.remove();
86
+ });
87
+ });
88
+
89
+ await describe('<gtk-column-view> drives the sort vectors with real header clicks', async () => {
90
+ for (const vector of COLUMN_VIEW_SORT_VECTORS) {
91
+ await it(vector.rule, () => {
92
+ const { el, host } = mount({ model: MODEL });
93
+ el.columns = [
94
+ { key: 'label', id: 'name', title: 'Name', sortable: true },
95
+ { key: 'value', id: 'code', title: 'Code', sortable: vector.sortable },
96
+ ];
97
+ el.sorter = vector.current;
98
+ headers(el)
99
+ .find((button) => button.dataset.columnId === vector.column)!
100
+ .click();
101
+ expect(el.sorter).toStrictEqual(vector.next);
102
+ host.remove();
103
+ });
104
+ }
105
+ });
106
+
107
+ await describe('<gtk-column-view> sorting', async () => {
108
+ await it('sorts ascending on the first click and inverts on the second', () => {
109
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
110
+ const seen: (string | null)[] = [];
111
+ el.addEventListener('notify::sorter', (event) => {
112
+ const sorter = (event as CustomEvent).detail.sorter as { column: string; descending: boolean } | null;
113
+ seen.push(sorter === null ? null : `${sorter.column}/${sorter.descending}`);
114
+ });
115
+ headers(el)[0]!.click();
116
+ expect(el.sorter).toStrictEqual({ column: 'name', descending: false });
117
+ expect(headers(el)[0]!.getAttribute('aria-sort')).toBe('ascending');
118
+ headers(el)[0]!.click();
119
+ expect(el.sorter).toStrictEqual({ column: 'name', descending: true });
120
+ expect(headers(el)[0]!.getAttribute('aria-sort')).toBe('descending');
121
+ expect(seen).toStrictEqual(['name/false', 'name/true']);
122
+ host.remove();
123
+ });
124
+
125
+ await it('does not sort by a column that declares no sorter', () => {
126
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
127
+ headers(el)[1]!.click();
128
+ expect(el.sorter).toBe(null);
129
+ expect(headers(el)[1]!.hasAttribute('aria-sort')).toBe(false);
130
+ host.remove();
131
+ });
132
+
133
+ await it('REORDERS nothing by itself, the way gtk_column_view_get_sorter does not', () => {
134
+ // The view publishes the sort and the consumer re-assigns the model; a view
135
+ // that reordered its own rows would fight whatever model the consumer holds.
136
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
137
+ headers(el)[0]!.click();
138
+ expect(rows(el).map((row) => cellsOf(row)[0])).toStrictEqual(['German', 'French']);
139
+ host.remove();
140
+ });
141
+ });
142
+
143
+ await describe('<gtk-column-view> separators', async () => {
144
+ await it('colours the cell borders only while show-column-separators is set', () => {
145
+ const { el, host } = mount({ columns: COLUMNS, model: MODEL });
146
+ expect(el.classList.contains('column-separators')).toBe(false);
147
+ el.showColumnSeparators = true;
148
+ expect(el.classList.contains('column-separators')).toBe(true);
149
+ el.showRowSeparators = true;
150
+ expect(el.classList.contains('separators')).toBe(true);
151
+ host.remove();
152
+ });
153
+ });
154
+ };
@@ -0,0 +1,190 @@
1
+ // DOM-level tests for <gtk-drag-icon>. A drag icon exists only WHILE a drag is in flight and
2
+ // GTK destroys it with the drag, so what a test can reach is the whole lifecycle: the child
3
+ // the icon carries, the per-drag cache `getForDrag` is, the icon following the pointer, and
4
+ // the hide that stands in for the destroy.
5
+ import { describe, expect, it } from '@gjsify/unit';
6
+
7
+ import { GtkDragIcon } from './elements/gtk-drag-icon.js';
8
+
9
+ function mount(child?: string): { el: GtkDragIcon; host: HTMLElement } {
10
+ const host = document.createElement('div');
11
+ document.body.appendChild(host);
12
+ const el = document.createElement('gtk-drag-icon') as GtkDragIcon;
13
+ if (child !== undefined) el.innerHTML = child;
14
+ host.appendChild(el);
15
+ return { el, host };
16
+ }
17
+
18
+ /** A drag event of its own: `getForDrag` keys on the `dataTransfer`, so each one is new. */
19
+ function dragEvent(x = 0, y = 0, type = 'dragstart'): DragEvent {
20
+ const event = new DragEvent(type, { clientX: x, clientY: y });
21
+ // `DataTransfer` is not in the event dictionary's constructor options in every engine,
22
+ // and the icon's own code reads it defensively; a test must not depend on that.
23
+ Object.defineProperty(event, 'dataTransfer', { value: new DataTransfer() });
24
+ return event;
25
+ }
26
+
27
+ export const GtkDragIconTest = async () => {
28
+ await describe('<gtk-drag-icon> child', async () => {
29
+ await it('is null until it is given one', () => {
30
+ const { el, host } = mount();
31
+ expect(el.child).toBe(null);
32
+ host.remove();
33
+ });
34
+
35
+ await it('takes the child it is set, in light DOM, and keeps only that one', () => {
36
+ // :478-485 — `gtk_widget_unparent (self->child)` then `gtk_widget_set_parent`
37
+ // on the new one, so the old child LEAVES rather than being duplicated.
38
+ const { el, host } = mount();
39
+ const first = document.createElement('gtk-label');
40
+ const second = document.createElement('gtk-image');
41
+ el.child = first;
42
+ expect(el.child).toBe(first);
43
+ el.child = second;
44
+ expect(el.child).toBe(second);
45
+ expect(el.children.length).toBe(1);
46
+ expect(first.isConnected).toBe(false);
47
+ host.remove();
48
+ });
49
+
50
+ await it('reads a child declared in markup without a call', () => {
51
+ // The getter is the light-DOM child, which is what makes the declared form work.
52
+ const { el, host } = mount('<gtk-label label="A drag icon can be markup"></gtk-label>');
53
+ expect(el.child?.tagName).toBe('GTK-LABEL');
54
+ host.remove();
55
+ });
56
+
57
+ await it('notifies once per real change and never for an echo', () => {
58
+ // :475 — `if (self->child == child) return;` — and `G_PARAM_EXPLICIT_NOTIFY`,
59
+ // so the one notify at :489 is the only signal this class emits.
60
+ const { el, host } = mount();
61
+ const detail: unknown[] = [];
62
+ el.addEventListener('notify::child', (event) => detail.push((event as CustomEvent).detail['child']));
63
+ const child = document.createElement('gtk-label');
64
+ el.child = child;
65
+ el.child = child;
66
+ el.child = null;
67
+ expect(detail).toStrictEqual([child, null]);
68
+ host.remove();
69
+ });
70
+ });
71
+
72
+ await describe('<gtk-drag-icon> the drag', async () => {
73
+ await it('is hidden and idle until a drag begins', () => {
74
+ // `gtk_drag_icon_get_for_drag` (:400-421) creates the icon and shows it only
75
+ // once a child is set, which in a browser is the drag itself.
76
+ const { el, host } = mount('<gtk-label label="x"></gtk-label>');
77
+ expect(el.dragging).toBe(false);
78
+ expect(el.hidden).toBe(false);
79
+ el.endDrag();
80
+ expect(el.hidden).toBe(true);
81
+ host.remove();
82
+ });
83
+
84
+ await it('follows the pointer once a drag is in flight', () => {
85
+ // `gtk_drag_icon_move_resize` (:138-150) is the whole of "moves with the
86
+ // pointer", and the hotspot is (0, 0) — see the header for why.
87
+ const { el, host } = mount('<gtk-label label="drag me"></gtk-label>');
88
+ el.beginDrag(dragEvent(40, 12));
89
+ expect(el.dragging).toBe(true);
90
+ expect(el.hidden).toBe(false);
91
+ expect(el.style.transform).toBe('translate3d(40px, 12px, 0px)');
92
+ document.dispatchEvent(new DragEvent('dragover', { clientX: 41, clientY: 13 }));
93
+ expect(el.style.transform).toBe('translate3d(41px, 13px, 0px)');
94
+ el.endDrag();
95
+ expect(el.dragging).toBe(false);
96
+ expect(el.hidden).toBe(true);
97
+ host.remove();
98
+ });
99
+
100
+ await it('stops following when the drag ends', () => {
101
+ const { el, host } = mount('<gtk-label label="drag me"></gtk-label>');
102
+ el.beginDrag(dragEvent(4, 4));
103
+ document.dispatchEvent(new DragEvent('dragover', { clientX: 90, clientY: 90 }));
104
+ document.dispatchEvent(new DragEvent('dragend', {}));
105
+ expect(el.dragging).toBe(false);
106
+ expect(el.hidden).toBe(true);
107
+ const before = el.style.transform;
108
+ document.dispatchEvent(new DragEvent('dragover', { clientX: 120, clientY: 120 }));
109
+ expect(el.style.transform).toBe(before);
110
+ host.remove();
111
+ });
112
+ });
113
+
114
+ await describe('GtkDragIcon.getForDrag', async () => {
115
+ await it('gives one icon per drag and the same one twice', () => {
116
+ // `g_object_get_qdata (G_OBJECT (drag), drag_icon_quark)` (:408-419): the icon
117
+ // is cached ON THE DRAG, so a second call for the same drag is the same widget.
118
+ const event = dragEvent();
119
+ const icon = GtkDragIcon.getForDrag(event);
120
+ expect(GtkDragIcon.getForDrag(event)).toBe(icon);
121
+ // No declared icon is free in this state, so the second drag is a new node.
122
+ const other = GtkDragIcon.getForDrag(dragEvent());
123
+ expect(other).not.toBe(icon);
124
+ for (const el of [icon, other]) {
125
+ el.endDrag();
126
+ el.remove();
127
+ }
128
+ });
129
+
130
+ await it('reuses a declared <gtk-drag-icon> instead of adding another', () => {
131
+ const declared = document.createElement('gtk-drag-icon');
132
+ document.body.appendChild(declared);
133
+ const icon = GtkDragIcon.getForDrag(dragEvent());
134
+ expect(icon).toBe(declared);
135
+ expect(document.querySelectorAll('gtk-drag-icon').length).toBe(1);
136
+ icon.endDrag();
137
+ declared.remove();
138
+ });
139
+
140
+ await it('gives a drag whose declared icon is busy a node of its own', () => {
141
+ // One icon per drag is the C's contract, so a declared icon already following
142
+ // a pointer belongs to that drag — the reuse is for the ONE drag markup names.
143
+ const declared = document.createElement('gtk-drag-icon');
144
+ document.body.appendChild(declared);
145
+ const first = GtkDragIcon.getForDrag(dragEvent());
146
+ expect(first).toBe(declared);
147
+ const second = GtkDragIcon.getForDrag(dragEvent());
148
+ expect(second).not.toBe(declared);
149
+ expect(second.dragging).toBe(true);
150
+ // The busy icon is left to its own drag: it still follows that pointer.
151
+ expect(first.dragging).toBe(true);
152
+ for (const el of [first, second]) el.endDrag();
153
+ for (const el of document.querySelectorAll('gtk-drag-icon')) el.remove();
154
+ });
155
+
156
+ await it('detaches the platform drag image so only the mirror shows', () => {
157
+ // The browser's own ghost is asked away with a 1×1 transparent image; where a
158
+ // browser refuses that, the platform ghost shows as well — the header says so.
159
+ const icon = GtkDragIcon.getForDrag(dragEvent(3, 4));
160
+ expect(icon.style.transform).toBe('translate3d(3px, 4px, 0px)');
161
+ icon.endDrag();
162
+ for (const el of document.querySelectorAll('gtk-drag-icon')) el.remove();
163
+ });
164
+ });
165
+
166
+ await describe('GtkDragIcon.createWidgetForValue', async () => {
167
+ await it('builds a label for a string', () => {
168
+ // :531-534 — `G_VALUE_HOLDS (value, G_TYPE_STRING)` → `gtk_label_new`.
169
+ const widget = GtkDragIcon.createWidgetForValue('Report.odt');
170
+ expect(widget?.tagName).toBe('GTK-LABEL');
171
+ expect(widget?.getAttribute('label')).toBe('Report.odt');
172
+ });
173
+
174
+ await it('builds a swatch carrying the colour for an RGBA', () => {
175
+ // :544-553 — a `GtkColorSwatch` with can-drag and can-drop FALSE, so for a drag
176
+ // icon it is nothing but the colour. The div is this package's swatch.
177
+ const widget = GtkDragIcon.createWidgetForValue({ red: 1, green: 0, blue: 0, alpha: 0.5 });
178
+ expect(widget?.className).toBe('adw-drag-icon-swatch');
179
+ // The alpha is half, so every engine keeps the `rgba()` form a swatch needs to
180
+ // read as translucent; at alpha 1 Firefox serializes it back to `rgb()`.
181
+ expect((widget as HTMLElement | null)?.style.backgroundColor).toBe('rgba(255, 0, 0, 0.5)');
182
+ });
183
+
184
+ await it('returns null for a value it cannot make a widget for', () => {
185
+ // :603-605 — and the four types between :535-602 have no browser answer, which
186
+ // the header names: no icon query for a file, no painted selection for a buffer.
187
+ expect(GtkDragIcon.createWidgetForValue(null)).toBe(null);
188
+ });
189
+ });
190
+ };