@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
@@ -27,6 +27,15 @@
27
27
  @use 'labels';
28
28
  // <gtk-box>. Before every widget, which may place its own children in one.
29
29
  @use 'box';
30
+ // The five Gtk layout containers after it, and they are here for ONE reason each: nothing
31
+ // downstream of `box` needs to place children in one, and the frame's 1px border is the
32
+ // only rule libadwaita writes for any of the five (`_misc.scss:4-15`) — so they belong with
33
+ // the primitive they build on rather than in the widget run below.
34
+ @use 'frame';
35
+ @use 'aspect_frame';
36
+ @use 'center_box';
37
+ @use 'grid';
38
+ @use 'fixed';
30
39
  // The REST of libadwaita's documented style-class surface — the widget-
31
40
  // independent half: the surfaces (`.background`, `.view`, `.frame`), `.card` and
32
41
  // the two boxed lists, `.toolbar`, `.spacer`, `.osd`, `.linked`, the app-icon
@@ -37,14 +46,32 @@
37
46
  // documented surface and fails on a class with no rule behind it.
38
47
  @use 'style_classes';
39
48
  @use 'window';
49
+ @use 'application_window';
50
+ // <adw-header-bar>, <gtk-header-bar> AND <gtk-window-controls>, in ONE partial because
51
+ // upstream's `_header-bar.scss` styles `headerbar`, `windowcontrols` and `windowtitle`
52
+ // together — and because a bar's frame buttons ARE its window controls.
40
53
  @use 'headerbar';
41
54
  @use 'action_bar';
42
55
  @use 'window_title';
43
56
  @use 'button';
57
+ // The four button-derived nodes below, in the order of `src/elements/`: each one
58
+ // renders a `.adw-button` of its own, so each rule comes AFTER `button` rather than
59
+ // before it — `button.link`'s transparent background is the whole point of a link and
60
+ // `.adw-button`'s resting fill must not win it on source order.
61
+ @use 'link';
62
+ @use 'scale_button';
63
+ @use 'color_button';
64
+ @use 'font_button';
44
65
  @use 'button_content';
45
66
  // The ONE popover surface. Emitted BEFORE the widgets that host one, so a
46
67
  // consumer's (or a widget's) own higher-specificity rule still wins over it.
47
68
  @use 'popover';
69
+ // <gtk-popover-menu>, <gtk-popover-menu-bar> and <gtk-popover-bin>. All three AFTER
70
+ // `popover`, because every surface they own is `<gtk-popover>`'s and none of them restates
71
+ // it — they add the menubar's item rules and the bin's `.has-open-popup`, and libadwaita
72
+ // puts both in the same file as `popover.menu` for the same reason.
73
+ @use 'popover_menu_bar';
74
+ @use 'popover_bin';
48
75
  @use 'split_button';
49
76
  @use 'menu_button';
50
77
  @use 'drop_down';
@@ -54,14 +81,73 @@
54
81
  // own copy of it until it was lifted out of `adw-switch-row {}`.
55
82
  @use 'switch';
56
83
  @use 'entry';
84
+ @use 'search_entry';
85
+ @use 'password_entry';
86
+ @use 'separator';
87
+ // `<gtk-text>`, `<gtk-text-view>` and `<gtk-editable-label>` — the widgets whose content is
88
+ // text, and the two libadwaita blocks that paint a `text` node.
89
+ @use 'text';
90
+ // `<gtk-search-bar>`, which reads the header-bar tokens rather than the header bar's rules.
91
+ @use 'search_bar';
92
+ // <gtk-drawing-area>, the one widget of the gtk/drawing page that carries a rule of its
93
+ // own. No dependency on anything above it — it styles one canvas — so the order here is
94
+ // placement, not precedence.
95
+ @use 'drawing';
96
+ // The `dnd` node, which libadwaita styles once for the whole widget
97
+ // (`_common.scss:30-32`) and which is otherwise geometry: a drag icon has no parent to lay
98
+ // out in, because it is a GtkRoot with its own surface. No dependency on anything above it.
99
+ @use 'drag_icon';
100
+ // The layout CONTAINERS GTK owns and libadwaita only styles. `_paned` draws the divider as
101
+ // an inset box-shadow on the `separator` node a `GtkPanedHandle` carries, which is a
102
+ // different rule from `<gtk-separator>`'s own fill — so it needs its own partial rather
103
+ // than a class the separator's rule would fight over.
104
+ @use 'overlay';
105
+ @use 'revealer';
106
+ @use 'paned';
107
+ @use 'expander';
57
108
  // The two form-control primitives, in ONE partial because upstream merges them
58
109
  // (there is no `_radio.scss` in libadwaita) — see _checks.scss.
59
110
  @use 'checks';
111
+ @use 'spin_button';
112
+ @use 'scale';
60
113
  @use 'progress_bar';
114
+ // <gtk-level-bar>, next to the progress bar it is easy to confuse with. It has no
115
+ // dependency on anything above it, so the order here is readability, not precedence.
116
+ @use 'level_bar';
117
+ // The three views, in dependency order: `list_view` declares the selectable-row mixin
118
+ // and the rubber band that the other two include.
119
+ @use 'list_view';
120
+ @use 'grid_view';
121
+ @use 'column_view';
122
+ @use 'tree_expander';
123
+ // The media group, in dependency order and nothing else: `picture` fits a replaced
124
+ // element, `inscription` is text measured in characters and lines, `video` lays an
125
+ // overlay out and hosts a `media_controls` inside its revealer, so `media_controls`
126
+ // comes after `video` only in the sense that `video` NAMES it — neither partial reads
127
+ // the other, and the order here is readability, not precedence.
128
+ @use 'picture';
129
+ @use 'inscription';
130
+ @use 'video';
131
+ @use 'media_controls';
132
+ // The two child-holding containers. `list_box` comes first only because it reads like
133
+ // `list_view`; nothing here is a `@use` of the other, and `flow_box` includes the selectable
134
+ // mixin from `list_view` above for the cell's four state colours.
135
+ @use 'list_box';
136
+ @use 'flow_box';
137
+ @use 'calendar';
61
138
  @use 'preferences';
139
+ @use 'preferences_row';
62
140
  @use 'card';
63
141
  @use 'data_grid';
142
+ @use 'bin';
64
143
  @use 'clamp';
144
+ // <gtk-stack> AND <gtk-stack-switcher> AND <gtk-stack-sidebar>, in ONE partial: upstream
145
+ // styles the switcher's buttons out of `_buttons.scss` and the sidebar's rows out of
146
+ // `_sidebars.scss`, so a stack and the two things that switch over it share styles.
147
+ @use 'stack';
148
+ @use 'clamp_scrollable';
149
+ // <adw-spinner> AND <gtk-spinner>, in ONE partial because upstream's
150
+ // `_spinner.scss` styles `spinner` and `image.spinner` in the same file.
65
151
  @use 'spinner';
66
152
  // <adw-shortcut-label>'s keycaps. After `labels`, because a separator inside it
67
153
  // is an ordinary `.dimmed`.
@@ -80,24 +166,47 @@
80
166
  @use 'password_entry_row';
81
167
  @use 'toast';
82
168
  @use 'toolbar_view';
169
+ // The scrolling trio, beside `_scrolling.scss`'s edge indicators: the scrollbar first,
170
+ // because the scrolled window's grid places it, and the viewport before the window, because
171
+ // the window's grid has a cell for it.
172
+ @use 'scrollbar';
173
+ @use 'viewport';
174
+ @use 'scrolled_window';
175
+ @use 'window_handle';
83
176
  @use 'scrolling';
84
177
  @use 'wrap_box';
85
178
  @use 'panes';
86
179
  @use 'overlay_split_view';
87
180
  @use 'navigation_split_view';
88
181
  @use 'carousel';
182
+ // <adw-tab-bar> BEFORE <adw-tab-view>, and only because upstream writes both in ONE file:
183
+ // `tabbar`, `tabbox` and `tab` (_tab-view.scss:1-95). The chip rules here and the merged
184
+ // bar's are the same declarations against the same class names, so whichever partial is
185
+ // emitted second would win on source order for a document that nests one bar in the other.
186
+ @use 'tab_bar';
89
187
  @use 'tab_view';
90
188
  @use 'view_switcher';
91
189
  @use 'inline_view_switcher';
92
190
  @use 'view_stack';
93
191
  @use 'view_switcher_bar';
192
+ @use 'tab_button';
193
+ @use 'tab_overview';
194
+ @use 'view_switcher_sidebar';
94
195
  @use 'navigation_view';
95
196
  @use 'bottom_sheet';
96
197
  @use 'sidebar';
198
+ // GTK's own dialogs: the about window's layout, the emoji chooser's nodes, and the two
199
+ // Unix print dialogs. After `popover` and `entry`, which the emoji chooser hosts.
200
+ @use 'gtk_about_dialog';
201
+ @use 'emoji_chooser';
202
+ @use 'print_dialogs';
97
203
  @use 'about_dialog';
98
204
  @use 'alert_dialog';
99
205
  @use 'preferences_dialog';
100
206
  @use 'dialog';
207
+ // After 'dialog': the shortcuts dialog IS an <adw-dialog> and adds sections and rows
208
+ // inside its content area, so its own rules have to come after the chrome they sit in.
209
+ @use 'shortcuts_dialog';
101
210
  // Last among the widgets: an authored `halign` / `valign` is placement the author asked
102
211
  // for, and an element rule that sets a margin must not win it back on source order.
103
212
  @use 'widget';
@@ -13,6 +13,8 @@
13
13
  // - libadwaita has no activatable opt-out for a button row, and
14
14
  // `<adw-action-row activatable="false">` reads by PRESENCE, so it means the
15
15
  // opposite of what it says.
16
+ // - the row `title-lines`/`subtitle-lines` clamp is observed as RENDERED GEOMETRY, not
17
+ // as computed style (see `renderedLineCount`).
16
18
  import { describe, expect, it } from '@gjsify/unit';
17
19
 
18
20
  import {
@@ -30,6 +32,9 @@ import { isIconAvailable } from './icon-registry.js';
30
32
  import { fallbackMask, maskOf } from './icon-registry.spec.js';
31
33
 
32
34
  import type { AdwActionRow } from './elements/adw-action-row.js';
35
+ import type { AdwComboRow } from './elements/adw-combo-row.js';
36
+ import type { AdwExpanderRow } from './elements/adw-expander-row.js';
37
+ import type { AdwSpinRow } from './elements/adw-spin-row.js';
33
38
  import type { AdwSwitchRow } from './elements/adw-switch-row.js';
34
39
  import type { AdwWindowTitle } from './elements/adw-window-title.js';
35
40
 
@@ -196,6 +201,134 @@ export const AdwActionRowsTest = async () => {
196
201
  });
197
202
  });
198
203
 
204
+ /**
205
+ * The number of lines a row title/subtitle element actually RENDERS, measured from its
206
+ * height divided by one line box's height.
207
+ *
208
+ * NOT the number of rects a `Range` over the element reports. Firefox reports a rect per
209
+ * laid-out line box and `-webkit-line-clamp` truncates the BOX without re-laying out the
210
+ * text, so a label clamped to one line still lists every line it would have taken:
211
+ * measured on a real `adw-switch-row`, `title-lines=1` gave 5 rects for a box that
212
+ * collapsed from 90px to 18px, and an isolated `display:-webkit-box;
213
+ * -webkit-line-clamp:1` probe gave 3 rects / 22px against 3 rects / 66px unclamped —
214
+ * identical rect counts, opposite line counts. Only the HEIGHT moves, so only the height
215
+ * can carry the claim; the rect count was never a line count and no `-webkit-line-clamp`
216
+ * implementation can satisfy `expect(rects.length).toBe(1)`.
217
+ *
218
+ * The step is the FIRST line box, not the computed `line-height`: the stylesheet sets no
219
+ * line-height on these labels, so `getComputedStyle().lineHeight` reads `normal` — which
220
+ * computes to no number at all.
221
+ */
222
+ function renderedLineCount(el: HTMLElement): number {
223
+ const range = document.createRange();
224
+ range.selectNodeContents(el);
225
+ const rects = range.getClientRects();
226
+ const lineBox = rects.length > 0 ? rects[0]!.height : 0;
227
+ if (!(lineBox > 0)) return Number.NaN;
228
+ return Math.round(el.getBoundingClientRect().height / lineBox);
229
+ }
230
+
231
+ // Default (0 = unlimited, the AdwActionRow pspec's sentinel): wraps freely.
232
+ await describe('<adw-action-row> title-lines / subtitle-lines (libadwaita conformance)', async () => {
233
+ await it('title-lines=0 (default) wraps to multiple lines in narrow container', () => {
234
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
235
+ el.setAttribute(
236
+ 'title',
237
+ 'A very long title that should wrap across multiple lines when the container is narrow',
238
+ );
239
+ host.style.width = '200px';
240
+ const lines = renderedLineCount(el.querySelector('.adw-row-title')!);
241
+ expect(lines).toBeGreaterThan(1);
242
+ host.remove();
243
+ });
244
+
245
+ await it('subtitle-lines=0 (default) wraps to multiple lines in narrow container', () => {
246
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
247
+ el.setAttribute(
248
+ 'subtitle',
249
+ 'A very long subtitle that should wrap across multiple lines when the container is narrow',
250
+ );
251
+ host.style.width = '200px';
252
+ const lines = renderedLineCount(el.querySelector('.adw-row-subtitle')!);
253
+ expect(lines).toBeGreaterThan(1);
254
+ host.remove();
255
+ });
256
+
257
+ // title-lines > 0: clamps to N lines
258
+ await it('title-lines=1 clamps to exactly 1 line', () => {
259
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
260
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
261
+ el.setAttribute('title-lines', '1');
262
+ host.style.width = '150px';
263
+ const lines = renderedLineCount(el.querySelector('.adw-row-title')!);
264
+ expect(lines).toBe(1);
265
+ host.remove();
266
+ });
267
+
268
+ await it('subtitle-lines=2 clamps to exactly 2 lines', () => {
269
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
270
+ el.setAttribute('subtitle', 'Subtitle that is long enough to wrap into three lines if allowed');
271
+ el.setAttribute('subtitle-lines', '2');
272
+ host.style.width = '150px';
273
+ const lines = renderedLineCount(el.querySelector('.adw-row-subtitle')!);
274
+ expect(lines).toBe(2);
275
+ host.remove();
276
+ });
277
+
278
+ // Dynamic attribute change
279
+ await it('changing title-lines from 0 to 1 applies clamping visually', () => {
280
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
281
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
282
+ el.setAttribute('title-lines', '0');
283
+ host.style.width = '150px';
284
+ let lines = renderedLineCount(el.querySelector('.adw-row-title')!);
285
+ expect(lines).toBeGreaterThan(1);
286
+
287
+ el.setAttribute('title-lines', '1');
288
+ // Force reflow
289
+ el.getBoundingClientRect();
290
+ lines = renderedLineCount(el.querySelector('.adw-row-title')!);
291
+ expect(lines).toBe(1);
292
+ host.remove();
293
+ });
294
+
295
+ await it('changing title-lines from 1 to 0 removes clamping visually', () => {
296
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
297
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
298
+ el.setAttribute('title-lines', '1');
299
+ host.style.width = '150px';
300
+ let lines = renderedLineCount(el.querySelector('.adw-row-title')!);
301
+ expect(lines).toBe(1);
302
+
303
+ el.setAttribute('title-lines', '0');
304
+ el.getBoundingClientRect();
305
+ lines = renderedLineCount(el.querySelector('.adw-row-title')!);
306
+ expect(lines).toBeGreaterThan(1);
307
+ host.remove();
308
+ });
309
+
310
+ // Invalid/non-numeric values treated as 0 (unlimited) — AdwActionRow pspec range is 0..G_MAXINT
311
+ await it('title-lines="invalid" treated as unlimited (wraps)', () => {
312
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
313
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
314
+ el.setAttribute('title-lines', 'invalid');
315
+ host.style.width = '150px';
316
+ const lines = renderedLineCount(el.querySelector('.adw-row-title')!);
317
+ expect(lines).toBeGreaterThan(1);
318
+ host.remove();
319
+ });
320
+
321
+ await it('subtitle-lines="-1" treated as unlimited (wraps)', () => {
322
+ const { el, host } = mount<AdwActionRow>('adw-action-row');
323
+ el.setAttribute('subtitle', 'Subtitle that is long enough to wrap if allowed');
324
+ el.setAttribute('subtitle-lines', '-1');
325
+ host.style.width = '150px';
326
+ const lines = renderedLineCount(el.querySelector('.adw-row-subtitle')!);
327
+ expect(lines).toBeGreaterThan(1);
328
+ host.remove();
329
+ });
330
+ });
331
+
199
332
  await describe('<adw-switch-row> notify::active (libadwaita conformance vectors)', async () => {
200
333
  for (const vector of SWITCH_ROW_NOTIFY_VECTORS) {
201
334
  await it(`${vector.name} — ${vector.rule}`, () => {
@@ -244,6 +377,152 @@ export const AdwActionRowsTest = async () => {
244
377
  host.remove();
245
378
  });
246
379
  }
380
+
381
+ // title-lines / subtitle-lines tests (same behavior as adw-action-row)
382
+ await it('title-lines=0 (default) wraps to multiple lines in narrow container', () => {
383
+ const { el, host } = mount<AdwSwitchRow>('adw-switch-row');
384
+ el.setAttribute(
385
+ 'title',
386
+ 'A very long title that should wrap across multiple lines when the container is narrow',
387
+ );
388
+ host.style.width = '200px';
389
+ const lines = renderedLineCount(el.querySelector('.adw-row-title')!);
390
+ expect(lines).toBeGreaterThan(1);
391
+ host.remove();
392
+ });
393
+
394
+ await it('subtitle-lines=0 (default) wraps to multiple lines in narrow container', () => {
395
+ const { el, host } = mount<AdwSwitchRow>('adw-switch-row');
396
+ el.setAttribute(
397
+ 'subtitle',
398
+ 'A very long subtitle that should wrap across multiple lines when the container is narrow',
399
+ );
400
+ host.style.width = '200px';
401
+ const lines = renderedLineCount(el.querySelector('.adw-row-subtitle')!);
402
+ expect(lines).toBeGreaterThan(1);
403
+ host.remove();
404
+ });
405
+
406
+ await it('title-lines=1 clamps to exactly 1 line', () => {
407
+ const { el, host } = mount<AdwSwitchRow>('adw-switch-row');
408
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
409
+ el.setAttribute('title-lines', '1');
410
+ host.style.width = '150px';
411
+ const lines = renderedLineCount(el.querySelector('.adw-row-title')!);
412
+ expect(lines).toBe(1);
413
+ host.remove();
414
+ });
415
+
416
+ await it('subtitle-lines=2 clamps to exactly 2 lines', () => {
417
+ const { el, host } = mount<AdwSwitchRow>('adw-switch-row');
418
+ el.setAttribute('subtitle', 'Subtitle that is long enough to wrap into three lines if allowed');
419
+ el.setAttribute('subtitle-lines', '2');
420
+ host.style.width = '150px';
421
+ const lines = renderedLineCount(el.querySelector('.adw-row-subtitle')!);
422
+ expect(lines).toBe(2);
423
+ host.remove();
424
+ });
425
+
426
+ await it('changing title-lines from 0 to 1 applies clamping visually', () => {
427
+ const { el, host } = mount<AdwSwitchRow>('adw-switch-row');
428
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
429
+ el.setAttribute('title-lines', '0');
430
+ host.style.width = '150px';
431
+ let lines = renderedLineCount(el.querySelector('.adw-row-title')!);
432
+ expect(lines).toBeGreaterThan(1);
433
+
434
+ el.setAttribute('title-lines', '1');
435
+ el.getBoundingClientRect();
436
+ lines = renderedLineCount(el.querySelector('.adw-row-title')!);
437
+ expect(lines).toBe(1);
438
+ host.remove();
439
+ });
440
+
441
+ await it('title-lines="invalid" treated as unlimited (wraps)', () => {
442
+ const { el, host } = mount<AdwSwitchRow>('adw-switch-row');
443
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
444
+ el.setAttribute('title-lines', 'invalid');
445
+ host.style.width = '150px';
446
+ const lines = renderedLineCount(el.querySelector('.adw-row-title')!);
447
+ expect(lines).toBeGreaterThan(1);
448
+ host.remove();
449
+ });
450
+ });
451
+
452
+ await describe('<adw-switch-row> prefix slot (inherited add_prefix)', async () => {
453
+ // Routing a live child and then deriving the box's emptiness are TWO observers in
454
+ // a chain: `slotted-children` moves the node into the box, and only that move is
455
+ // what `bindEmptySections` observes. One checkpoint sees the routing, two see the
456
+ // derivation.
457
+ const settleSlot = async () => {
458
+ await Promise.resolve();
459
+ await Promise.resolve();
460
+ };
461
+ await it('routes a DECLARED slot="prefix" child into the prefix box', () => {
462
+ // Adw.SwitchRow IS an AdwActionRow (adw-switch-row.c:50), so `add_prefix`
463
+ // and the box that carries it are inherited, not a web-only addition.
464
+ // The child is authored BEFORE the row reaches the document, which is the
465
+ // install pass rather than the observer.
466
+ const host = document.createElement('div');
467
+ document.body.appendChild(host);
468
+ const row = document.createElement('adw-switch-row') as AdwSwitchRow;
469
+ const icon = document.createElement('span');
470
+ icon.id = 'lead';
471
+ icon.setAttribute('slot', 'prefix');
472
+ row.appendChild(icon);
473
+ host.appendChild(row);
474
+
475
+ expect(icon.parentElement?.className).toBe('adw-switch-row-prefix');
476
+ host.remove();
477
+ });
478
+
479
+ await it('hides the box while it is empty', () => {
480
+ const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
481
+ const box = row.querySelector('.adw-switch-row-prefix') as HTMLElement;
482
+ expect(box.hidden).toBe(true);
483
+ host.remove();
484
+ });
485
+
486
+ await it('routes a prefix appended AFTER connect, and un-hides the box', async () => {
487
+ // The live half: a renderer mounts the row and then appends the icon, which
488
+ // is a MutationObserver callback rather than the install pass — the incident
489
+ // `src/slotted-children.ts` records for 42 elements that snapshotted instead.
490
+ const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
491
+ const box = row.querySelector('.adw-switch-row-prefix') as HTMLElement;
492
+
493
+ const icon = document.createElement('span');
494
+ icon.setAttribute('slot', 'prefix');
495
+ row.appendChild(icon);
496
+ await settleSlot();
497
+
498
+ expect(icon.parentElement).toBe(box);
499
+ expect(box.hidden).toBe(false);
500
+ host.remove();
501
+ });
502
+
503
+ await it('shows it again when the last prefix child leaves', async () => {
504
+ const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
505
+ const icon = document.createElement('span');
506
+ icon.setAttribute('slot', 'prefix');
507
+ row.appendChild(icon);
508
+ await settleSlot();
509
+ const box = row.querySelector('.adw-switch-row-prefix') as HTMLElement;
510
+
511
+ expect(box.hidden).toBe(false);
512
+ icon.remove();
513
+ await Promise.resolve();
514
+ expect(box.hidden).toBe(true);
515
+ host.remove();
516
+ });
517
+
518
+ await it('exposes the box as prefixSection for the imperative spelling', () => {
519
+ const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
520
+ const icon = document.createElement('span');
521
+ row.prefixSection.appendChild(icon);
522
+
523
+ expect(icon.parentElement).toBe(row.prefixSection);
524
+ host.remove();
525
+ });
247
526
  });
248
527
 
249
528
  await describe('<adw-button-row> (libadwaita conformance vectors)', async () => {
@@ -343,4 +622,56 @@ export const AdwActionRowsTest = async () => {
343
622
  host.remove();
344
623
  });
345
624
  });
625
+
626
+ // Line-clamping tests for other row types that inherit title-lines/subtitle-lines
627
+ await describe('<adw-combo-row> title-lines / subtitle-lines', async () => {
628
+ await it('title-lines=0 wraps, title-lines=1 clamps to 1 line', () => {
629
+ const { el, host } = mount<AdwComboRow>('adw-combo-row');
630
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
631
+ el.setAttribute('title-lines', '0');
632
+ host.style.width = '150px';
633
+ let lines = renderedLineCount(el.querySelector('.adw-row-title')!);
634
+ expect(lines).toBeGreaterThan(1);
635
+
636
+ el.setAttribute('title-lines', '1');
637
+ el.getBoundingClientRect();
638
+ lines = renderedLineCount(el.querySelector('.adw-row-title')!);
639
+ expect(lines).toBe(1);
640
+ host.remove();
641
+ });
642
+ });
643
+
644
+ await describe('<adw-spin-row> title-lines / subtitle-lines', async () => {
645
+ await it('title-lines=0 wraps, title-lines=1 clamps to 1 line', () => {
646
+ const { el, host } = mount<AdwSpinRow>('adw-spin-row');
647
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
648
+ el.setAttribute('title-lines', '0');
649
+ host.style.width = '150px';
650
+ let lines = renderedLineCount(el.querySelector('.adw-row-title')!);
651
+ expect(lines).toBeGreaterThan(1);
652
+
653
+ el.setAttribute('title-lines', '1');
654
+ el.getBoundingClientRect();
655
+ lines = renderedLineCount(el.querySelector('.adw-row-title')!);
656
+ expect(lines).toBe(1);
657
+ host.remove();
658
+ });
659
+ });
660
+
661
+ await describe('<adw-expander-row> title-lines / subtitle-lines', async () => {
662
+ await it('title-lines=0 wraps, title-lines=1 clamps to 1 line', () => {
663
+ const { el, host } = mount<AdwExpanderRow>('adw-expander-row');
664
+ el.setAttribute('title', 'Title that is long enough to wrap if allowed');
665
+ el.setAttribute('title-lines', '0');
666
+ host.style.width = '150px';
667
+ let lines = renderedLineCount(el.querySelector('.adw-row-title')!);
668
+ expect(lines).toBeGreaterThan(1);
669
+
670
+ el.setAttribute('title-lines', '1');
671
+ el.getBoundingClientRect();
672
+ lines = renderedLineCount(el.querySelector('.adw-row-title')!);
673
+ expect(lines).toBe(1);
674
+ host.remove();
675
+ });
676
+ });
346
677
  };
@@ -0,0 +1,118 @@
1
+ // DOM-level behaviour tests for <adw-application-window>. Runs in a real browser via the
2
+ // @gjsify/adwaita-web browser test axis (tests/browser Playwright harness). The custom
3
+ // elements are registered by importing the package root in test.browser.mts; these specs
4
+ // create elements via document.createElement and assert their DOM behaviour.
5
+ //
6
+ // The subject is the MENUBAR and the inheritance: `Adw.ApplicationWindow` is
7
+ // `Adw.Window` plus `Gtk.ApplicationWindow:show-menubar`, so the window half is
8
+ // <adw-window>'s spec and only the delta is asserted here.
9
+ import { describe, it, expect } from '@gjsify/unit';
10
+
11
+ import type { AdwApplicationWindow } from './elements/adw-application-window.js';
12
+
13
+ const MENU_MODEL = [
14
+ {
15
+ label: 'File',
16
+ submenu: [
17
+ { label: 'New Window', action: 'app.new-window' },
18
+ { label: 'Quit', action: 'app.quit' },
19
+ ],
20
+ },
21
+ { label: 'Help', action: 'app.help' },
22
+ ];
23
+
24
+ function makeWindow(model: unknown = MENU_MODEL): AdwApplicationWindow {
25
+ const el = document.createElement('adw-application-window') as AdwApplicationWindow;
26
+ el.setAttribute('menu-model', JSON.stringify(model));
27
+ el.innerHTML = '<p>Content</p>';
28
+ document.body.appendChild(el);
29
+ return el;
30
+ }
31
+
32
+ export const AdwApplicationWindowTest = async () => {
33
+ await describe('adw-application-window is an adw-window', async () => {
34
+ await it('places children in the inherited content area', async () => {
35
+ const win = makeWindow();
36
+ expect(win.querySelector('.adw-window-content')?.querySelector('p')?.textContent).toBe('Content');
37
+ win.remove();
38
+ });
39
+
40
+ await it('keeps the inherited size request', async () => {
41
+ const win = makeWindow();
42
+ expect(win.style.width).toBe('360px');
43
+ win.setAttribute('width', '520');
44
+ expect(win.style.width).toBe('520px');
45
+ win.remove();
46
+ });
47
+ });
48
+
49
+ await describe('adw-application-window menubar', async () => {
50
+ await it('draws no bar without show-menubar', async () => {
51
+ const win = makeWindow();
52
+ expect(win.showMenubar).toBe(false);
53
+ expect(win.menubar?.hidden).toBe(true);
54
+ win.remove();
55
+ });
56
+
57
+ await it('draws no bar for an application that installed no menu', async () => {
58
+ // The GTK half of the same rule: a window with no model has no menubar,
59
+ // however the flag reads.
60
+ const win = makeWindow([]);
61
+ win.setAttribute('show-menubar', '');
62
+ expect(win.menubar?.hidden).toBe(true);
63
+ win.remove();
64
+ });
65
+
66
+ await it('a submenu becomes a menu button and a bare item a flat button', async () => {
67
+ const win = makeWindow();
68
+ win.setAttribute('show-menubar', '');
69
+
70
+ expect(win.menubar?.hidden).toBe(false);
71
+ const menuButton = win.menubar?.querySelector('gtk-menu-button');
72
+ expect(menuButton?.getAttribute('menu-title')).toBe('File');
73
+ const help = win.menubar?.querySelector('gtk-button');
74
+ expect(help?.getAttribute('label')).toBe('Help');
75
+ win.remove();
76
+ });
77
+
78
+ await it('the menubar sits above the content, inside the content area', async () => {
79
+ // It is a child of `.adw-window-content` rather than a sibling: the window's
80
+ // own slot binding would re-home a sibling into the content on the next tick.
81
+ const win = makeWindow();
82
+ win.setAttribute('show-menubar', '');
83
+ expect(win.contentArea.firstElementChild).toBe(win.menubar);
84
+ win.remove();
85
+ });
86
+
87
+ await it('the flag alone shows and hides the bar without a rebuild', async () => {
88
+ const win = makeWindow();
89
+ win.setAttribute('show-menubar', '');
90
+ expect(win.menubar?.hidden).toBe(false);
91
+ win.removeAttribute('show-menubar');
92
+ expect(win.menubar?.hidden).toBe(true);
93
+ win.remove();
94
+ });
95
+
96
+ await it('a bare item reports its activation the way every menu surface does', async () => {
97
+ const win = makeWindow();
98
+ win.setAttribute('show-menubar', '');
99
+ const seen: unknown[] = [];
100
+ win.addEventListener('menu-item-activated', (e) => seen.push((e as CustomEvent).detail));
101
+ (win.menubar?.querySelector('gtk-button') as HTMLButtonElement | null)?.click();
102
+ expect(seen).toStrictEqual([{ id: 'Help', label: 'Help', path: [1] }]);
103
+ win.remove();
104
+ });
105
+
106
+ await it('a broken model is dropped rather than thrown', async () => {
107
+ // `parseMenuModel` is total by construction: a typo in markup must not take
108
+ // the window down with it.
109
+ const win = document.createElement('adw-application-window') as AdwApplicationWindow;
110
+ win.setAttribute('menu-model', '{not json');
111
+ win.setAttribute('show-menubar', '');
112
+ document.body.appendChild(win);
113
+ expect(win.menuModel).toStrictEqual([]);
114
+ expect(win.menubar?.hidden).toBe(true);
115
+ win.remove();
116
+ });
117
+ });
118
+ };