@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,287 @@
1
+ // <adw-breakpoint-bin> — a bin whose one child rearranges itself at size thresholds.
2
+ // `Adw.BreakpointBin` gives breakpoints a home without a window: it holds a list of
3
+ // `Adw.Breakpoint`s, and on every allocation the LAST one whose condition holds is
4
+ // picked and its setters written. If none holds, the child's original values stand.
5
+ //
6
+ // The picking, the restore order and what a restore restores to are all
7
+ // `@gjsify/adwaita-core`'s `BreakpointBinState` (ADR 0004), driven from real
8
+ // `ResizeObserver` deliveries — the four rules it encodes are quoted at the top of
9
+ // `packages/web/adwaita-core/src/breakpoint-bin.ts`, each with its `file:lines`.
10
+ //
11
+ // WHAT THE ATTRIBUTE CARRIES. `Adw.Breakpoint` is a GObject, not a widget, and
12
+ // `adw_breakpoint_bin_add_breakpoint()` is the whole API — so a browser port needs a
13
+ // MARKUP form and there is no GIR property for one. `breakpoints` is a JSON array of
14
+ // `{ condition, setters: [{ target, property, value }] }`:
15
+ //
16
+ // * `condition` is an Adwaita condition string, parsed by the same grammar as every
17
+ // other breakpoint in this package (`max-width: 720px`).
18
+ // * `target` is a CSS selector for a DESCENDANT. The C says it in the docs —
19
+ // "Breakpoints are only allowed to modify widgets inside the AdwBreakpointBin, but
20
+ // not on the AdwBreakpointBin itself" — and the selector cannot escape the subtree
21
+ // because it is resolved with `querySelector` on this element.
22
+ // * `property` is an ATTRIBUTE name and `value` its value. An attribute is the only
23
+ // thing a browser can write on another custom element portably, and this package's
24
+ // own properties ARE attributes (`<adw-label label>` above).
25
+ // * `originalValue` is read ONCE, when the setter is registered, exactly as
26
+ // `g_object_get_property` is at `adw_breakpoint_add_setter` (adw-breakpoint.c:1627).
27
+ // An attribute the element did not have is restored by REMOVING it.
28
+ //
29
+ // `Adw.BreakpointBin` also measures itself differently once it holds a breakpoint:
30
+ // `adw_breakpoint_bin_measure` forces its MINIMUM to 0 (:388) and
31
+ // `adw_breakpoint_bin_get_request_mode` answers CONSTANT_SIZE (:362). That is the
32
+ // documented rule — "Adding a breakpoint to AdwBreakpointBin will result in it having
33
+ // no minimum size" — and it is why the element sets `min-width`/`min-height` to 0 and
34
+ // `overflow: hidden` (the C's own `gtk_widget_set_overflow(…, GTK_OVERFLOW_HIDDEN)`,
35
+ // :669) while a `breakpoints` attribute is present.
36
+ //
37
+ // Attributes:
38
+ // breakpoints (JSON — the breakpoints to add, in ORDER: a later one beats an earlier
39
+ // one when both match. `current-breakpoint` is reported as the index.)
40
+ //
41
+ // Events:
42
+ // `notify::current-breakpoint` (CustomEvent, bubbles, `detail = { currentBreakpoint }`)
43
+ // when the picked breakpoint changes — mirrors the GObject property of that name,
44
+ // which is read-only and notified on every change (adw-breakpoint-bin.c:477).
45
+ // `breakpoint-unapply` (CustomEvent, bubbles, `detail = { index }`) BEFORE the writes,
46
+ // `breakpoint-apply` (CustomEvent, bubbles, `detail = { index }`) AFTER them — the
47
+ // order of `adw_breakpoint_transition` (adw-breakpoint.c:1793, :1819). A listener on
48
+ // the apply end therefore sees the INCOMING values and one on the unapply end the
49
+ // OUTGOING ones; neither ever sees the restore in between.
50
+ //
51
+ // A11Y: `role="group"`. There is no box of its own: GTK clips overflow and gives the
52
+ // child the allocation, which a light-DOM passthrough already is.
53
+ //
54
+ // NOT PORTED: `adw_breakpoint_bin_set_pass_through()` (:893). It makes `contains()`
55
+ // return FALSE so the bin claims no event of its own (adw-breakpoint-bin.c:327); a
56
+ // browser has no `contains` override for that, and the property is private API besides.
57
+ // `adw_breakpoint_bin_set_natural_size()` (:906) and
58
+ // `adw_breakpoint_bin_set_warnings()` (:853) are the same shape — private helpers with
59
+ // no GIR property, no attribute, and nothing for a page to set.
60
+ //
61
+ // Reference: refs/libadwaita/src/adw-breakpoint-bin.c
62
+ // Reference: refs/libadwaita/src/adw-breakpoint.c (adw_breakpoint_transition)
63
+ // Copyright (c) 2023 Purism SPC (libadwaita). LGPLv2.1+.
64
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
65
+
66
+ import { BreakpointBinState } from '@gjsify/adwaita-core';
67
+ import type { BreakpointSetter } from '@gjsify/adwaita-core';
68
+
69
+ import { observeAdaptiveSize } from '../breakpoints.js';
70
+
71
+ /** One authored setter, as it reads in the `breakpoints` attribute. */
72
+ interface AuthoredSetter {
73
+ readonly target: string;
74
+ readonly property: string;
75
+ readonly value: string;
76
+ }
77
+
78
+ /** One authored breakpoint, as it reads in the `breakpoints` attribute. */
79
+ interface AuthoredBreakpoint {
80
+ readonly condition: string;
81
+ readonly setters: readonly AuthoredSetter[];
82
+ }
83
+
84
+ /** `breaks` parsed, or `[]` for anything that is not an array of breakpoints. */
85
+ function parseBreakpoints(raw: string | null): AuthoredBreakpoint[] {
86
+ if (!raw) return [];
87
+ let parsed: unknown;
88
+ try {
89
+ parsed = JSON.parse(raw);
90
+ } catch {
91
+ // A typo in a condition must not empty the bin: `adw_breakpoint_check_condition`
92
+ // returns FALSE for an unparseable condition (adw-breakpoint.c:1831), so C drops
93
+ // that ONE breakpoint. Silently losing all of them would be a different widget.
94
+ console.error('<adw-breakpoint-bin>: `breakpoints` is not JSON; no breakpoint is applied.');
95
+ return [];
96
+ }
97
+ if (!Array.isArray(parsed)) return [];
98
+ return parsed.flatMap((entry) => {
99
+ if (typeof entry !== 'object' || entry === null) return [];
100
+ const { condition, setters } = entry as Partial<AuthoredBreakpoint>;
101
+ if (typeof condition !== 'string') return [];
102
+ return [{ condition, setters: Array.isArray(setters) ? setters : [] }];
103
+ });
104
+ }
105
+
106
+ export class AdwBreakpointBin extends HTMLElement {
107
+ /** The C's own structure: a list of breakpoints, and at most one picked. */
108
+ private _state = new BreakpointBinState<Element>();
109
+ private _dispose: (() => void) | undefined;
110
+ /**
111
+ * What the last binding applied, carried across every rebind.
112
+ *
113
+ * `BreakpointBinState.inherit` exists for exactly this and its docblock records the
114
+ * measurement: a browser element rebinds on every `connectedCallback`, and a bin that
115
+ * restarts at "none applied" reads the size that LEFT the old breakpoint's range as
116
+ * no change at all and leaves the child holding what the old bin wrote.
117
+ */
118
+ private _applied: number | null = null;
119
+ /** Registration is deferred to the first allocation; see `_observe`. */
120
+ private _pendingSync = false;
121
+ /**
122
+ * What each setter's target held when the setter was FIRST registered, keyed by
123
+ * target + property + value.
124
+ *
125
+ * Carried across a REBIND because a rebind is not a re-registration. Upstream
126
+ * `adw_breakpoint_add_setter` captures the original once, at the call
127
+ * (`g_object_get_property`, adw-breakpoint.c:1627), and the widget outlives every
128
+ * resize; a browser element rebinds on every connect, and re-reading the original
129
+ * then would capture the value the OUTGOING breakpoint had already written — so the
130
+ * restore would write back the applied value and the widget would never recover.
131
+ * Measured: a bin applied at 400px, moved to a 500px parent and widened to 900px
132
+ * kept its narrow label for good.
133
+ *
134
+ * Cleared when the AUTHOR rewrites `breakpoints`, which is a new
135
+ * `add_breakpoint`/`add_setters` sequence and captures new originals.
136
+ */
137
+ private _originals = new Map<string, string | null>();
138
+
139
+ static get observedAttributes() {
140
+ return ['breakpoints'];
141
+ }
142
+
143
+ /** `Adw.BreakpointBin:current-breakpoint` — the picked index, or null. Read-only. */
144
+ get currentBreakpoint(): number | null {
145
+ return this._state.current;
146
+ }
147
+
148
+ /** `adw_breakpoint_bin_get_current_breakpoint()` (:841), under its property name. */
149
+ get currentBreakpointAttribute(): string | null {
150
+ const current = this._state.current;
151
+ return current === null ? null : String(current);
152
+ }
153
+
154
+ /** `Adw.BreakpointBin:child` — the bin has one child, the one every breakpoint writes. */
155
+ get child(): Element | null {
156
+ return this.firstElementChild;
157
+ }
158
+
159
+ connectedCallback() {
160
+ this.setAttribute('role', 'group');
161
+ // A GTK widget is a box and an unknown custom element is `inline`, which measures
162
+ // zero — and a bin measuring zero matches every condition forever. libadwaita
163
+ // ships no rule for this widget, so the box model is set here rather than
164
+ // invented in a partial.
165
+ this.style.display = 'block';
166
+ this._syncSizing();
167
+ // Registration waits for the first allocation: `connectedCallback` of a bin fires
168
+ // while its OWN markup is still being parsed, so `#caption` below it does not
169
+ // exist yet and a setter resolved here would be dropped rather than restored.
170
+ // `ResizeObserver` delivers its first observation after layout, by which time the
171
+ // tree is whole and nothing has been written yet — so the originals are still the
172
+ // ones `adw_breakpoint_add_setter` would have captured.
173
+ this._pendingSync = true;
174
+ this._observe();
175
+ }
176
+
177
+ disconnectedCallback() {
178
+ this._dispose?.();
179
+ this._dispose = undefined;
180
+ }
181
+
182
+ attributeChangedCallback(name?: string) {
183
+ if (name !== 'breakpoints' || !this.isConnected) return;
184
+ // The tree IS whole by the time anything rewrites the attribute, so a change
185
+ // registers immediately rather than one allocation later — and it is a NEW
186
+ // sequence of `add_breakpoint` calls, so the originals are captured afresh.
187
+ this._originals.clear();
188
+ this._syncBreakpoints();
189
+ }
190
+
191
+ /**
192
+ * Rebuild the state from the attribute, keeping the applied breakpoint.
193
+ *
194
+ * The originals are read on the way, because `inherit` restores what the NEW
195
+ * definitions captured: a restore read off a child the outgoing breakpoint already
196
+ * changed would restore it to the applied value, which is no restore at all.
197
+ */
198
+ private _syncBreakpoints(): void {
199
+ this._pendingSync = false;
200
+ const authored = parseBreakpoints(this.getAttribute('breakpoints'));
201
+ this._state = new BreakpointBinState<Element>();
202
+ for (const breakpoint of authored) {
203
+ const setters: BreakpointSetter<Element>[] = [];
204
+ for (const setter of breakpoint.setters) {
205
+ if (typeof setter?.target !== 'string' || typeof setter.property !== 'string') continue;
206
+ const target = this.querySelector(setter.target);
207
+ // An unmatched selector is a setter that would write to nothing; C's
208
+ // `add_setters` needs a live object and refuses one that is not.
209
+ if (target === null) continue;
210
+ const key = `${setter.target}\u0000${setter.property}\u0000${setter.value}`;
211
+ if (!this._originals.has(key)) this._originals.set(key, target.getAttribute(setter.property));
212
+ setters.push({
213
+ object: target,
214
+ property: setter.property,
215
+ value: setter.value,
216
+ originalValue: this._originals.get(key) ?? null,
217
+ });
218
+ }
219
+ this._state.add({ condition: breakpoint.condition, setters });
220
+ }
221
+ this._state.inherit(this._applied);
222
+ this._state.setHasChild(this.child !== null);
223
+ this._write(this._state.current);
224
+ this._syncSizing();
225
+ }
226
+
227
+ /**
228
+ * The size source. `ResizeObserver` delivers an initial observation, so the pick is
229
+ * settled before first paint — the same seam `src/breakpoints.ts` gives every other
230
+ * adaptive element, re-created on every connect so a widget MOVED between parents
231
+ * tracks its conditions again.
232
+ *
233
+ * The CHILD is read here rather than cached, because
234
+ * `adw_breakpoint_bin_size_allocate` tests it on every allocation (:427) and a child
235
+ * appended after connect is then a child.
236
+ */
237
+ private _observe(): void {
238
+ this._dispose?.();
239
+ this._dispose = observeAdaptiveSize(this, (size) => {
240
+ if (this._pendingSync) this._syncBreakpoints();
241
+ this._state.setHasChild(this.child !== null);
242
+ const transition = this._state.evaluate(size);
243
+ if (transition === null) return;
244
+ this._emit(transition.from, 'breakpoint-unapply');
245
+ this._perform(transition.writes);
246
+ this._write(transition.to);
247
+ this._emit(transition.to, 'breakpoint-apply');
248
+ this.dispatchEvent(
249
+ new CustomEvent('notify::current-breakpoint', {
250
+ bubbles: true,
251
+ detail: { currentBreakpoint: this.currentBreakpointAttribute },
252
+ }),
253
+ );
254
+ });
255
+ }
256
+
257
+ private _perform(writes: readonly { object: Element; property: string; value: unknown }[]): void {
258
+ for (const write of writes) {
259
+ // A `null` original is an attribute that was ABSENT, and `removeAttribute`
260
+ // is its restore — the one that makes unapply the exact inverse of apply.
261
+ if (write.value === null) write.object.removeAttribute(write.property);
262
+ else write.object.setAttribute(write.property, String(write.value));
263
+ }
264
+ }
265
+
266
+ private _write(index: number | null): void {
267
+ this._applied = index;
268
+ }
269
+
270
+ private _emit(index: number | null, type: string): void {
271
+ if (index === null) return;
272
+ this.dispatchEvent(new CustomEvent(type, { bubbles: true, detail: { index } }));
273
+ }
274
+
275
+ /** The measure rules of a bin that holds breakpoints (:356, :388, :669). */
276
+ private _syncSizing(): void {
277
+ const adaptive = this._state.length > 0;
278
+ // `display` and the clip are left to the author's stylesheet on purpose: the
279
+ // MINIMUM is the documented rule, and writing `display` from here would fight a
280
+ // host page that lays the bin out in a grid.
281
+ this.style.minWidth = adaptive ? '0px' : '';
282
+ this.style.minHeight = adaptive ? '0px' : '';
283
+ if (adaptive) this.style.overflow = 'hidden';
284
+ }
285
+ }
286
+
287
+ customElements.define('adw-breakpoint-bin', AdwBreakpointBin);
@@ -7,6 +7,9 @@
7
7
  // The label/icon visibility rules are HEADLESS and live in `@gjsify/adwaita-core`
8
8
  // (ADR 0004) as {@link ButtonRowState}; this element keeps only the DOM render half.
9
9
  //
10
+ // Attributes: title, start-icon-name, end-icon-name, tooltip-text
11
+ // (`Gtk.Widget:tooltip-text`).
12
+ //
10
13
  // THERE IS NO `activatable` OPT-OUT, and inventing one would be wrong twice over: the
11
14
  // upstream template hardcodes `activatable=True` and the class docs say "AdwButtonRow is
12
15
  // always activatable", while `<adw-action-row>` in this same package reads `activatable`
@@ -21,6 +24,7 @@
21
24
 
22
25
  import { BUTTON_ROW_ACTIVATABLE, ButtonRowState } from '@gjsify/adwaita-core';
23
26
 
27
+ import { applyRowTooltip } from '../row-tooltip.js';
24
28
  import { type GtkImage, createGtkImage } from './gtk-image.js';
25
29
  import { attachRowActivation } from './row-activation.js';
26
30
 
@@ -34,7 +38,7 @@ export class AdwButtonRow extends HTMLElement {
34
38
  private _initialized = false;
35
39
 
36
40
  static get observedAttributes() {
37
- return ['title', 'start-icon-name', 'end-icon-name'];
41
+ return ['title', 'start-icon-name', 'end-icon-name', 'tooltip-text'];
38
42
  }
39
43
 
40
44
  connectedCallback() {
@@ -81,6 +85,8 @@ export class AdwButtonRow extends HTMLElement {
81
85
 
82
86
  // Unconditional: an AdwButtonRow has no way to not be activatable.
83
87
  this.classList.toggle('activatable', BUTTON_ROW_ACTIVATABLE);
88
+ // The contents box is the whole row here, so it carries the tooltip for all of it.
89
+ applyRowTooltip(this, [this._contentsEl]);
84
90
  }
85
91
 
86
92
  /**
@@ -0,0 +1,207 @@
1
+ // <adw-clamp-scrollable> — the CLAMP whose child scrolls, and the widget
2
+ // `AdwClamp`'s own header points at for anything that must scroll inside a readable
3
+ // width (`adw-clamp-scrollable.c:20-27`: "The primary use case for AdwClampScrollable is
4
+ // clamping Gtk.ListView").
5
+ //
6
+ // SAME ARITHMETIC AS `<adw-clamp>`, both halves of it: the allocation is
7
+ // `clampAllocate` out of `@gjsify/adwaita-core` — `lower`/`max`/`upper`, the
8
+ // ease-out-cubic tightening region and the `small`/`medium`/`large` class stamped on the
9
+ // CHILD — reached through `normalizeClampSize` and the `AdwLengthUnit` conversion
10
+ // `adw-clamp-layout.c:166-171` does per property. The difference is the ORIENTATION and
11
+ // the scrolling.
12
+ //
13
+ // THE ORIENTATION IS THE WIDGET, NOT THE CLAMP'S. `set_orientation` forwards to the
14
+ // layout manager (adw-clamp-scrollable.c:78-92) and the cap lands on the width for a
15
+ // horizontal clamp and on the HEIGHT for a vertical one
16
+ // (`child_size_from_clamp` measures along `self->orientation`). A vertical clamp
17
+ // therefore centres on the block axis here, where `<adw-clamp>` has no axis to pick.
18
+ //
19
+ // THE SCROLLING MOVES FROM THE CHILD TO THE HOST, and that is the one deviation worth
20
+ // naming. In C the child IS the `Gtk.Scrollable`: the widget binds its `hadjustment`,
21
+ // `vadjustment`, `hscroll-policy` and `vscroll-policy` onto it
22
+ // (adw-clamp-scrollable.c:440-455) and a child that is not scrollable is four
23
+ // `gbinding` warnings at exit 0. A DOM element cannot hand its scrolling to a child that
24
+ // does not know it is inside one, so the scrollport is this element (`overflow`) and the
25
+ // child is what gets capped — the same visible contract, one level up. `hscroll-policy`
26
+ // and `vscroll-policy` therefore land on the HOST's overflow, which is where the C's
27
+ // policy ultimately decided whether the child ever scrolled.
28
+ //
29
+ // `hadjustment`/`vadjustment` have no attribute here: they are `Gtk.Adjustment`
30
+ // objects (a widget-valued property on every renderer), and the browser's scroll
31
+ // position is its own `scrollTop`/`scrollLeft`. That is a PORT-ONLY gap against the
32
+ // `Gtk.Scrollable` interface rather than against `AdwClampScrollable`'s own property
33
+ // list, which is why `check-adwaita-element-properties.mjs` has no entry for it.
34
+ //
35
+ // A11Y: no role. `adw_clamp_scrollable_class_init` sets none.
36
+ //
37
+ // Reference: refs/libadwaita/src/adw-clamp-scrollable.c (set_orientation, set_child,
38
+ // the four adjustment bindings, class_init's layout manager + `clamp` node)
39
+ // Reference: refs/libadwaita/src/adw-clamp-layout.c (child_size_from_clamp, allocate)
40
+ // Copyright (c) 2020 Purism SPC / GNOME contributors (libadwaita). LGPLv2.1+.
41
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
42
+
43
+ import {
44
+ ADW_CLAMP_DEFAULTS,
45
+ ADW_CLAMP_SIZE_CLASSES,
46
+ type AdwLengthUnit,
47
+ adwLengthToPx,
48
+ clampAllocate,
49
+ normalizeBoxOrientation,
50
+ normalizeClampSize,
51
+ normalizeLengthUnit,
52
+ type BoxOrientation,
53
+ } from '@gjsify/adwaita-core';
54
+
55
+ import { bindSlottedChildren } from '../slotted-children.js';
56
+
57
+ /** `Gtk.ScrollablePolicy`'s three nicks, in enum order. */
58
+ export type ScrollPolicy = 'automatic' | 'always' | 'never';
59
+
60
+ /** `adw_scrollable_policy_to_overflow` — the policy as the CSS `overflow` keyword. */
61
+ const POLICY_OVERFLOW: Record<ScrollPolicy, string> = {
62
+ automatic: 'auto',
63
+ always: 'scroll',
64
+ never: 'hidden',
65
+ };
66
+
67
+ export class AdwClampScrollable extends HTMLElement {
68
+ private _resize: ResizeObserver | null = null;
69
+ private _mutations: MutationObserver | null = null;
70
+
71
+ static get observedAttributes() {
72
+ return ['maximum-size', 'tightening-threshold', 'unit', 'orientation', 'hscroll-policy', 'vscroll-policy'];
73
+ }
74
+
75
+ /** `AdwClampScrollable:maximum-size` — the cap, in `unit`. Default 600. */
76
+ get maximumSize(): number {
77
+ return normalizeClampSize(this.getAttribute('maximum-size'), ADW_CLAMP_DEFAULTS.maximumSize);
78
+ }
79
+
80
+ set maximumSize(value: number) {
81
+ this.setAttribute('maximum-size', String(value));
82
+ }
83
+
84
+ /** `AdwClampScrollable:tightening-threshold` — where the easing starts. Default 400. */
85
+ get tighteningThreshold(): number {
86
+ return normalizeClampSize(this.getAttribute('tightening-threshold'), ADW_CLAMP_DEFAULTS.tighteningThreshold);
87
+ }
88
+
89
+ set tighteningThreshold(value: number) {
90
+ this.setAttribute('tightening-threshold', String(value));
91
+ }
92
+
93
+ /** `AdwClampScrollable:unit` — the length unit both sizes are written in. Default `sp`. */
94
+ get unit(): AdwLengthUnit {
95
+ return normalizeLengthUnit(this.getAttribute('unit'), 'sp');
96
+ }
97
+
98
+ set unit(value: AdwLengthUnit) {
99
+ this.setAttribute('unit', value);
100
+ }
101
+
102
+ /** `GtkOrientable:orientation`, which this class overrides. Default horizontal. */
103
+ get orientation(): BoxOrientation {
104
+ return normalizeBoxOrientation(this.getAttribute('orientation'));
105
+ }
106
+
107
+ set orientation(value: BoxOrientation) {
108
+ this.setAttribute('orientation', value);
109
+ }
110
+
111
+ connectedCallback() {
112
+ // `AdwClampScrollable:child` is a widget PROPERTY, so a `.blp`'s `child: …`
113
+ // authors `slot="child"`. Every child here is already the content, so only the
114
+ // NAME is enrolled — the reason `adw-clamp.ts` gives for not calling
115
+ // `.install()`.
116
+ bindSlottedChildren(this, [{ name: 'child', into: this }]);
117
+
118
+ // ResizeObserver delivers an initial observation on `observe()`, so the first
119
+ // allocation lands before paint without a seeding pass.
120
+ this._resize = new ResizeObserver(() => this._allocate());
121
+ this._resize.observe(this);
122
+ // A child appended after connect is capped too; without this it keeps whatever
123
+ // width it arrived with.
124
+ this._mutations = new MutationObserver(() => this._allocate());
125
+ this._mutations.observe(this, { childList: true });
126
+
127
+ this._applyOverflow();
128
+ this._allocate();
129
+ }
130
+
131
+ disconnectedCallback() {
132
+ this._resize?.disconnect();
133
+ this._resize = null;
134
+ this._mutations?.disconnect();
135
+ this._mutations = null;
136
+ }
137
+
138
+ attributeChangedCallback() {
139
+ this._applyOverflow();
140
+ this._allocate();
141
+ }
142
+
143
+ /**
144
+ * `Gtk.Scrollable:hscroll-policy` / `vscroll-policy` — the two overrides the class
145
+ * re-declares (adw-clamp-scrollable.c:118-141) and then binds onto the child. They
146
+ * decide here whether this element scrolls at all, which is the question they answer
147
+ * in C.
148
+ */
149
+ private _applyOverflow(): void {
150
+ const horizontal = this.getAttribute('hscroll-policy') as ScrollPolicy | null;
151
+ const vertical = this.getAttribute('vscroll-policy') as ScrollPolicy | null;
152
+ this.style.overflowX = horizontal === null ? 'auto' : (POLICY_OVERFLOW[horizontal] ?? 'auto');
153
+ this.style.overflowY = vertical === null ? 'auto' : (POLICY_OVERFLOW[vertical] ?? 'auto');
154
+ }
155
+
156
+ /**
157
+ * `adw_clamp_layout_allocate`, against the AVAILABLE size on the clamped axis.
158
+ *
159
+ * The cap sits on the CHILD, never here: this element is the scrollport, so a cap on
160
+ * itself would feed its own capped width back into its ResizeObserver — a feedback
161
+ * loop rather than a measurement (the reasoning `<adw-clamp>` carries in full).
162
+ */
163
+ private _allocate(): void {
164
+ const vertical = this.orientation === 'vertical';
165
+ const unit = this.unit;
166
+ const available = vertical ? this.clientHeight : this.clientWidth;
167
+
168
+ // `childMin` is 0, as in `<adw-clamp>`: a child that declares a minimum keeps it
169
+ // (CSS 2.1 §10.4 lets `min-*` beat `max-*`), and one that declares none has a
170
+ // minimum of 0 — the value a synchronous re-measure would arrive at anyway.
171
+ const params = {
172
+ maximumSize: adwLengthToPx(unit, this.maximumSize),
173
+ tighteningThreshold: adwLengthToPx(unit, this.tighteningThreshold),
174
+ childMin: 0,
175
+ childNat: 0,
176
+ };
177
+
178
+ for (const child of Array.from(this.children) as HTMLElement[]) {
179
+ if (available <= 0) {
180
+ // GTK's equivalent is `for_size = -1`: leave the child alone rather than
181
+ // capping it at 0 and collapsing the page.
182
+ child.style.maxWidth = '';
183
+ child.style.maxHeight = '';
184
+ child.style.marginInline = '';
185
+ child.style.marginBlock = '';
186
+ for (const cls of ADW_CLAMP_SIZE_CLASSES) child.classList.remove(cls);
187
+ continue;
188
+ }
189
+
190
+ const { childSize, sizeClass } = clampAllocate(available, params);
191
+ if (vertical) {
192
+ child.style.maxWidth = '';
193
+ child.style.maxHeight = `${childSize}px`;
194
+ child.style.marginInline = '';
195
+ child.style.marginBlock = 'auto';
196
+ } else {
197
+ child.style.maxWidth = `${childSize}px`;
198
+ child.style.maxHeight = '';
199
+ child.style.marginInline = 'auto';
200
+ child.style.marginBlock = '';
201
+ }
202
+ for (const cls of ADW_CLAMP_SIZE_CLASSES) child.classList.toggle(cls, cls === sizeClass);
203
+ }
204
+ }
205
+ }
206
+
207
+ customElements.define('adw-clamp-scrollable', AdwClampScrollable);
@@ -29,6 +29,9 @@
29
29
  // title / subtitle — the text column.
30
30
  // model — JSON array: `["a","b"]` or `[{"value":"a","label":"A"}]`.
31
31
  // selected — the selected index (number).
32
+ // tooltip-text — `Gtk.Widget:tooltip-text` (`src/row-tooltip.ts`).
33
+ // title-lines — clamp title to N lines (0 = unlimited, default)
34
+ // subtitle-lines — clamp subtitle to N lines (0 = unlimited, default)
32
35
  // Properties — the `<gtk-drop-down>` set minus `enableSearch` and `active`, which are that
33
36
  // element's own popover chrome and have no counterpart on a row that opens a native
34
37
  // <select>:
@@ -58,12 +61,16 @@
58
61
  import { ComboState, deriveRowLabels, normalizeComboOptions, parseListModel } from '@gjsify/adwaita-core';
59
62
  import type { AdwComboOption, AdwListItemsChanged, AdwListModelInput } from '@gjsify/adwaita-core';
60
63
 
64
+ import { applyRowTooltip } from '../row-tooltip.js';
61
65
  import { bindSlottedChildren } from '../slotted-children.js';
62
66
  import { stringListSlot } from '../string-list-slot.js';
67
+ import { applyRowLineClamp, parseRowLinesAttribute } from '../row-line-clamp.js';
63
68
 
64
69
  export class AdwComboRow extends HTMLElement {
65
70
  private _select!: HTMLSelectElement;
66
71
  private _valueEl!: HTMLSpanElement;
72
+ /** The label column — kept for `tooltip-text`, which the browser reads off a PART. */
73
+ private _textEl!: HTMLDivElement;
67
74
  private _titleEl!: HTMLSpanElement;
68
75
  private _subtitleEl!: HTMLSpanElement;
69
76
  /** The headless options list + selectedIndex↔selectedValue state machine (ADR 0004). */
@@ -71,7 +78,7 @@ export class AdwComboRow extends HTMLElement {
71
78
  private _initialized = false;
72
79
 
73
80
  static get observedAttributes() {
74
- return ['title', 'subtitle', 'model', 'selected'];
81
+ return ['title', 'subtitle', 'model', 'selected', 'tooltip-text', 'title-lines', 'subtitle-lines'];
75
82
  }
76
83
 
77
84
  /** The list model (`Adw.ComboRow:model`). Setting it splices the <select> and clamps the selection. */
@@ -141,6 +148,7 @@ export class AdwComboRow extends HTMLElement {
141
148
  // survive being attached, and an absent attribute must not blank it.
142
149
  const text = document.createElement('div');
143
150
  text.className = 'adw-row-text';
151
+ this._textEl = text;
144
152
  this._titleEl = document.createElement('span');
145
153
  this._titleEl.className = 'adw-row-title';
146
154
  this._subtitleEl = document.createElement('span');
@@ -283,6 +291,23 @@ export class AdwComboRow extends HTMLElement {
283
291
  this._titleEl.hidden = !labels.titleVisible;
284
292
  this._subtitleEl.textContent = labels.subtitle;
285
293
  this._subtitleEl.hidden = !labels.subtitleVisible;
294
+ // The <select> is stretched over the whole row (`position: absolute; inset: 0`,
295
+ // `_combo_row.scss`), so it is what the pointer actually lands on — the label column
296
+ // has `pointer-events: none`. A tooltip on the label parts alone would therefore
297
+ // never be reached over the title half of the row.
298
+ applyRowTooltip(this, [this._textEl, this._valueEl, this._select]);
299
+ this._applyLineClamping();
300
+ }
301
+
302
+ /** Apply CSS line-clamping based on title-lines/subtitle-lines attributes. */
303
+ private _applyLineClamping(): void {
304
+ applyRowLineClamp({
305
+ titleEl: this._titleEl,
306
+ subtitleEl: this._subtitleEl,
307
+ textContainerEl: this._titleEl.parentElement!,
308
+ getTitleLines: () => parseRowLinesAttribute(this.getAttribute('title-lines')),
309
+ getSubtitleLines: () => parseRowLinesAttribute(this.getAttribute('subtitle-lines')),
310
+ });
286
311
  }
287
312
  }
288
313
 
@@ -19,6 +19,12 @@
19
19
  // Events, all bubbling CustomEvents: `notify::open` (detail `{ open }`), `closed`
20
20
  // (Adw.Dialog::closed), `close-attempt` (Adw.Dialog::close-attempt).
21
21
  //
22
+ // SUBCLASSING: `decorateHeader(header)` is the one hook, and it exists for
23
+ // `<gtk-about-dialog>`, whose headerbar carries a stack switcher in the title position
24
+ // instead of a title (gtkaboutdialog.ui). Chrome, focus, Escape and dismissal stay here,
25
+ // so a subclass that wants a different header adds to this one rather than building a
26
+ // second scrim.
27
+ //
22
28
  // Reference: refs/libadwaita/src/adw-dialog.c (present/close/can-close, Escape, focus)
23
29
  // Reference: refs/libadwaita/src/stylesheet/widgets/_dialogs.scss (floating sheet + bottom sheet)
24
30
  // Copyright (c) 2023-2024 GNOME Foundation Inc. (libadwaita). LGPLv2.1+.
@@ -223,6 +229,17 @@ export class AdwDialog extends HTMLElement {
223
229
  this._modal.dismiss();
224
230
  }
225
231
 
232
+ /**
233
+ * Add to the header bar, called at the end of every render.
234
+ *
235
+ * The hook is for a DIALOG whose header is not a title plus a close button, which is
236
+ * what `<gtk-about-dialog>` needs: `gtkaboutdialog.ui` puts a `GtkStackSwitcher` in
237
+ * the titlebar's title-widget position and no title text at all. An empty body is the
238
+ * default, so every other dialog is unaffected — and the header element is the one
239
+ * the base already owns, so a subclass never reaches into private state to get it.
240
+ */
241
+ protected decorateHeader(_header: HTMLElement): void {}
242
+
226
243
  private _render(): void {
227
244
  this.classList.toggle('open', this.open);
228
245
 
@@ -244,6 +261,8 @@ export class AdwDialog extends HTMLElement {
244
261
  const locked = !this.canClose;
245
262
  this._closeBtn.disabled = locked;
246
263
  this._closeBtn.classList.toggle('locked', locked);
264
+
265
+ this.decorateHeader(this._headerEl);
247
266
  }
248
267
  }
249
268