@gjsify/adwaita-web 0.54.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/dist/adwaita-web.css +8066 -3033
  2. package/dist/adwaita-web.css.map +1 -1
  3. package/lib/types/adw-application-window.spec.d.ts +1 -0
  4. package/lib/types/adw-bin.spec.d.ts +1 -0
  5. package/lib/types/adw-breakpoint-bin.spec.d.ts +1 -0
  6. package/lib/types/adw-clamp-scrollable.spec.d.ts +1 -0
  7. package/lib/types/adw-multi-layout-view.spec.d.ts +1 -0
  8. package/lib/types/adw-preferences-row.spec.d.ts +1 -0
  9. package/lib/types/adw-shortcuts.spec.d.ts +1 -0
  10. package/lib/types/adw-tab-bar.spec.d.ts +1 -0
  11. package/lib/types/adw-tab-button.spec.d.ts +1 -0
  12. package/lib/types/adw-tab-overview.spec.d.ts +1 -0
  13. package/lib/types/adw-view-switcher-sidebar.spec.d.ts +1 -0
  14. package/lib/types/adw-window.spec.d.ts +1 -0
  15. package/lib/types/breakpoints.d.ts +14 -3
  16. package/lib/types/construct-vectors.spec.d.ts +1 -0
  17. package/lib/types/elements/adw-application-window.d.ts +27 -0
  18. package/lib/types/elements/adw-bin.d.ts +17 -0
  19. package/lib/types/elements/adw-breakpoint-bin.d.ts +67 -0
  20. package/lib/types/elements/adw-clamp-scrollable.d.ts +38 -0
  21. package/lib/types/elements/adw-dialog.d.ts +10 -0
  22. package/lib/types/elements/adw-layout-slot.d.ts +19 -0
  23. package/lib/types/elements/adw-multi-layout-view.d.ts +101 -0
  24. package/lib/types/elements/adw-preferences-row.d.ts +31 -0
  25. package/lib/types/elements/adw-shortcuts-dialog.d.ts +13 -0
  26. package/lib/types/elements/adw-shortcuts-item.d.ts +36 -0
  27. package/lib/types/elements/adw-shortcuts-section.d.ts +14 -0
  28. package/lib/types/elements/adw-sidebar.d.ts +5 -0
  29. package/lib/types/elements/adw-switch-row.d.ts +3 -0
  30. package/lib/types/elements/adw-tab-bar.d.ts +108 -0
  31. package/lib/types/elements/adw-tab-button.d.ts +32 -0
  32. package/lib/types/elements/adw-tab-overview.d.ts +199 -0
  33. package/lib/types/elements/adw-tab-view.d.ts +19 -23
  34. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +84 -0
  35. package/lib/types/elements/adw-window.d.ts +40 -0
  36. package/lib/types/elements/gtk-about-dialog.d.ts +146 -0
  37. package/lib/types/elements/gtk-application-window.d.ts +34 -0
  38. package/lib/types/elements/gtk-aspect-frame.d.ts +27 -0
  39. package/lib/types/elements/gtk-button.d.ts +9 -0
  40. package/lib/types/elements/gtk-calendar.d.ts +159 -0
  41. package/lib/types/elements/gtk-center-box.d.ts +39 -0
  42. package/lib/types/elements/gtk-color-dialog-button.d.ts +69 -0
  43. package/lib/types/elements/gtk-column-view.d.ts +50 -0
  44. package/lib/types/elements/gtk-drag-icon.d.ts +78 -0
  45. package/lib/types/elements/gtk-drawing-area.d.ts +95 -0
  46. package/lib/types/elements/gtk-editable-label.d.ts +33 -0
  47. package/lib/types/elements/gtk-emoji-chooser.d.ts +84 -0
  48. package/lib/types/elements/gtk-entry.d.ts +20 -1
  49. package/lib/types/elements/gtk-expander.d.ts +49 -0
  50. package/lib/types/elements/gtk-fixed.d.ts +13 -0
  51. package/lib/types/elements/gtk-flow-box-child.d.ts +14 -0
  52. package/lib/types/elements/gtk-flow-box.d.ts +87 -0
  53. package/lib/types/elements/gtk-font-dialog-button.d.ts +83 -0
  54. package/lib/types/elements/gtk-frame.d.ts +24 -0
  55. package/lib/types/elements/gtk-gl-area.d.ts +136 -0
  56. package/lib/types/elements/gtk-graphics-offload.d.ts +24 -0
  57. package/lib/types/elements/gtk-grid-view.d.ts +39 -0
  58. package/lib/types/elements/gtk-grid.d.ts +27 -0
  59. package/lib/types/elements/gtk-header-bar.d.ts +60 -0
  60. package/lib/types/elements/gtk-inscription.d.ts +64 -0
  61. package/lib/types/elements/gtk-label.d.ts +3 -0
  62. package/lib/types/elements/gtk-level-bar.d.ts +59 -0
  63. package/lib/types/elements/gtk-link-button.d.ts +29 -0
  64. package/lib/types/elements/gtk-list-box-row.d.ts +54 -0
  65. package/lib/types/elements/gtk-list-box.d.ts +100 -0
  66. package/lib/types/elements/gtk-list-view.d.ts +73 -0
  67. package/lib/types/elements/gtk-media-controls.d.ts +142 -0
  68. package/lib/types/elements/gtk-notebook.d.ts +148 -0
  69. package/lib/types/elements/gtk-overlay.d.ts +22 -0
  70. package/lib/types/elements/gtk-page-setup-unix-dialog.d.ts +87 -0
  71. package/lib/types/elements/gtk-paned.d.ts +121 -0
  72. package/lib/types/elements/gtk-password-entry.d.ts +27 -0
  73. package/lib/types/elements/gtk-picture.d.ts +66 -0
  74. package/lib/types/elements/gtk-popover-bin.d.ts +82 -0
  75. package/lib/types/elements/gtk-popover-menu-bar.d.ts +66 -0
  76. package/lib/types/elements/gtk-popover-menu.d.ts +83 -0
  77. package/lib/types/elements/gtk-popover.d.ts +28 -3
  78. package/lib/types/elements/gtk-print-unix-dialog.d.ts +167 -0
  79. package/lib/types/elements/gtk-revealer.d.ts +55 -0
  80. package/lib/types/elements/gtk-scale-button.d.ts +59 -0
  81. package/lib/types/elements/gtk-scale.d.ts +98 -0
  82. package/lib/types/elements/gtk-scrollbar.d.ts +124 -0
  83. package/lib/types/elements/gtk-scrolled-window.d.ts +121 -0
  84. package/lib/types/elements/gtk-search-bar.d.ts +39 -0
  85. package/lib/types/elements/gtk-search-entry.d.ts +27 -0
  86. package/lib/types/elements/gtk-separator.d.ts +10 -0
  87. package/lib/types/elements/gtk-spin-button.d.ts +94 -0
  88. package/lib/types/elements/gtk-spinner.d.ts +14 -0
  89. package/lib/types/elements/gtk-stack-sidebar.d.ts +43 -0
  90. package/lib/types/elements/gtk-stack-switcher.d.ts +58 -0
  91. package/lib/types/elements/gtk-stack.d.ts +154 -0
  92. package/lib/types/elements/gtk-switch.d.ts +4 -1
  93. package/lib/types/elements/gtk-text-view.d.ts +62 -0
  94. package/lib/types/elements/gtk-text.d.ts +45 -0
  95. package/lib/types/elements/gtk-toggle-button.d.ts +45 -0
  96. package/lib/types/elements/gtk-tree-expander.d.ts +38 -0
  97. package/lib/types/elements/gtk-video.d.ts +97 -0
  98. package/lib/types/elements/gtk-viewport.d.ts +84 -0
  99. package/lib/types/elements/gtk-window-controls.d.ts +80 -0
  100. package/lib/types/elements/gtk-window-handle.d.ts +39 -0
  101. package/lib/types/elements/gtk-window.d.ts +97 -0
  102. package/lib/types/elements/justification.d.ts +2 -0
  103. package/lib/types/elements/popover-menu.d.ts +18 -0
  104. package/lib/types/elements/roving-focus.d.ts +29 -1
  105. package/lib/types/emoji-data.d.ts +38 -0
  106. package/lib/types/font-description.d.ts +96 -0
  107. package/lib/types/gtk-about-dialog.spec.d.ts +1 -0
  108. package/lib/types/gtk-action-bar.spec.d.ts +1 -0
  109. package/lib/types/gtk-application-window.spec.d.ts +1 -0
  110. package/lib/types/gtk-aspect-frame.spec.d.ts +1 -0
  111. package/lib/types/gtk-calendar.spec.d.ts +1 -0
  112. package/lib/types/gtk-center-box.spec.d.ts +1 -0
  113. package/lib/types/gtk-color-dialog-button.spec.d.ts +1 -0
  114. package/lib/types/gtk-column-view.spec.d.ts +1 -0
  115. package/lib/types/gtk-drag-icon.spec.d.ts +1 -0
  116. package/lib/types/gtk-drawing-area.spec.d.ts +1 -0
  117. package/lib/types/gtk-editable-label.spec.d.ts +1 -0
  118. package/lib/types/gtk-emoji-chooser.spec.d.ts +1 -0
  119. package/lib/types/gtk-expander.spec.d.ts +1 -0
  120. package/lib/types/gtk-fixed.spec.d.ts +1 -0
  121. package/lib/types/gtk-flow-box.spec.d.ts +1 -0
  122. package/lib/types/gtk-font-dialog-button.spec.d.ts +1 -0
  123. package/lib/types/gtk-frame.spec.d.ts +1 -0
  124. package/lib/types/gtk-gl-area.spec.d.ts +1 -0
  125. package/lib/types/gtk-graphics-offload.spec.d.ts +1 -0
  126. package/lib/types/gtk-grid-view.spec.d.ts +1 -0
  127. package/lib/types/gtk-grid.spec.d.ts +1 -0
  128. package/lib/types/gtk-header-bar.spec.d.ts +1 -0
  129. package/lib/types/gtk-inscription.spec.d.ts +1 -0
  130. package/lib/types/gtk-level-bar.spec.d.ts +1 -0
  131. package/lib/types/gtk-link-button.spec.d.ts +1 -0
  132. package/lib/types/gtk-list-box.spec.d.ts +1 -0
  133. package/lib/types/gtk-list-view.spec.d.ts +1 -0
  134. package/lib/types/gtk-media-controls.spec.d.ts +1 -0
  135. package/lib/types/gtk-notebook.spec.d.ts +1 -0
  136. package/lib/types/gtk-overlay.spec.d.ts +1 -0
  137. package/lib/types/gtk-paned.spec.d.ts +1 -0
  138. package/lib/types/gtk-password-entry.spec.d.ts +1 -0
  139. package/lib/types/gtk-picture.spec.d.ts +1 -0
  140. package/lib/types/gtk-popover-bin.spec.d.ts +1 -0
  141. package/lib/types/gtk-popover-menu-bar.spec.d.ts +1 -0
  142. package/lib/types/gtk-popover-menu.spec.d.ts +1 -0
  143. package/lib/types/gtk-popover-role.spec.d.ts +1 -0
  144. package/lib/types/gtk-popover.spec.d.ts +1 -0
  145. package/lib/types/gtk-print-dialogs.spec.d.ts +1 -0
  146. package/lib/types/gtk-revealer.spec.d.ts +1 -0
  147. package/lib/types/gtk-scale-button.spec.d.ts +1 -0
  148. package/lib/types/gtk-scale.spec.d.ts +1 -0
  149. package/lib/types/gtk-scrollbar.spec.d.ts +1 -0
  150. package/lib/types/gtk-scrolled-window.spec.d.ts +1 -0
  151. package/lib/types/gtk-search-bar.spec.d.ts +1 -0
  152. package/lib/types/gtk-search-entry.spec.d.ts +1 -0
  153. package/lib/types/gtk-separator.spec.d.ts +1 -0
  154. package/lib/types/gtk-spin-button.spec.d.ts +1 -0
  155. package/lib/types/gtk-spinner.spec.d.ts +1 -0
  156. package/lib/types/gtk-stack-sidebar.spec.d.ts +1 -0
  157. package/lib/types/gtk-stack-switcher.spec.d.ts +1 -0
  158. package/lib/types/gtk-stack.spec.d.ts +1 -0
  159. package/lib/types/gtk-text-view.spec.d.ts +1 -0
  160. package/lib/types/gtk-text.spec.d.ts +1 -0
  161. package/lib/types/gtk-toggle-button.spec.d.ts +1 -0
  162. package/lib/types/gtk-tree-expander.spec.d.ts +1 -0
  163. package/lib/types/gtk-video.spec.d.ts +1 -0
  164. package/lib/types/gtk-viewport.spec.d.ts +1 -0
  165. package/lib/types/gtk-window-controls.spec.d.ts +1 -0
  166. package/lib/types/gtk-window-handle.spec.d.ts +1 -0
  167. package/lib/types/gtk-window.spec.d.ts +1 -0
  168. package/lib/types/index.d.ts +4 -1
  169. package/lib/types/list-view-dom.d.ts +44 -0
  170. package/lib/types/namespace/adw.d.ts +12 -0
  171. package/lib/types/namespace/gtk.d.ts +61 -0
  172. package/lib/types/page-setup.d.ts +100 -0
  173. package/lib/types/scroll-shading.d.ts +15 -1
  174. package/lib/types/shared-tree-builder.d.ts +30 -2
  175. package/lib/types/signals.d.ts +4 -0
  176. package/lib/types/styles.generated.d.ts +1 -1
  177. package/lib/types/tab-chip.d.ts +73 -0
  178. package/lib/types/template-classes.d.ts +11 -0
  179. package/package.json +12 -8
  180. package/scss/_action_row.scss +2 -2
  181. package/scss/_application_window.scss +26 -0
  182. package/scss/_aspect_frame.scss +25 -0
  183. package/scss/_bin.scss +26 -0
  184. package/scss/_button.scss +45 -0
  185. package/scss/_calendar.scss +176 -0
  186. package/scss/_center_box.scss +25 -0
  187. package/scss/_checks.scss +6 -1
  188. package/scss/_clamp_scrollable.scss +28 -0
  189. package/scss/_color_button.scss +67 -0
  190. package/scss/_column_view.scss +126 -0
  191. package/scss/_drag_icon.scss +55 -0
  192. package/scss/_drawing.scss +85 -0
  193. package/scss/_emoji_chooser.scss +213 -0
  194. package/scss/_entry.scss +13 -5
  195. package/scss/_entry_row.scss +1 -1
  196. package/scss/_expander.scss +113 -0
  197. package/scss/_fixed.scss +29 -0
  198. package/scss/_flow_box.scss +94 -0
  199. package/scss/_font_button.scss +63 -0
  200. package/scss/_frame.scss +41 -0
  201. package/scss/_grid.scss +19 -0
  202. package/scss/_grid_view.scss +46 -0
  203. package/scss/_gtk_about_dialog.scss +186 -0
  204. package/scss/_headerbar.scss +132 -0
  205. package/scss/_icons.generated.scss +186 -0
  206. package/scss/_inscription.scss +125 -0
  207. package/scss/_level_bar.scss +190 -0
  208. package/scss/_link.scss +82 -0
  209. package/scss/_list_box.scss +88 -0
  210. package/scss/_list_view.scss +96 -0
  211. package/scss/_media_controls.scss +139 -0
  212. package/scss/_overlay.scss +68 -0
  213. package/scss/_paned.scss +130 -0
  214. package/scss/_password_entry.scss +83 -0
  215. package/scss/_picture.scss +80 -0
  216. package/scss/_popover_bin.scss +53 -0
  217. package/scss/_popover_menu_bar.scss +104 -0
  218. package/scss/_preferences_row.scss +51 -0
  219. package/scss/_print_dialogs.scss +328 -0
  220. package/scss/_reset.scss +21 -19
  221. package/scss/_revealer.scss +37 -0
  222. package/scss/_row.scss +20 -5
  223. package/scss/_scale.scss +298 -0
  224. package/scss/_scale_button.scss +167 -0
  225. package/scss/_scrollbar.scss +230 -0
  226. package/scss/_scrolled_window.scss +131 -0
  227. package/scss/_search_bar.scss +118 -0
  228. package/scss/_search_entry.scss +86 -0
  229. package/scss/_separator.scss +44 -0
  230. package/scss/_shortcuts_dialog.scss +100 -0
  231. package/scss/_spin_button.scss +172 -0
  232. package/scss/_spin_row.scss +56 -8
  233. package/scss/_spinner.scss +85 -4
  234. package/scss/_stack.scss +729 -0
  235. package/scss/_switch.scss +13 -5
  236. package/scss/_switch_row.scss +10 -0
  237. package/scss/_tab_bar.scss +317 -0
  238. package/scss/_tab_button.scss +98 -0
  239. package/scss/_tab_overview.scss +483 -0
  240. package/scss/_text.scss +182 -0
  241. package/scss/_theme.scss +1 -1
  242. package/scss/_tree_expander.scss +62 -0
  243. package/scss/_variables.scss +1 -1
  244. package/scss/_video.scss +146 -0
  245. package/scss/_view_switcher_sidebar.scss +112 -0
  246. package/scss/_viewport.scss +50 -0
  247. package/scss/_window.scss +118 -1
  248. package/scss/_window_handle.scss +20 -0
  249. package/scss/adwaita-skin.scss +109 -0
  250. package/src/adw-action-rows.spec.ts +76 -0
  251. package/src/adw-application-window.spec.ts +118 -0
  252. package/src/adw-bin.spec.ts +75 -0
  253. package/src/adw-breakpoint-bin.spec.ts +324 -0
  254. package/src/adw-clamp-scrollable.spec.ts +189 -0
  255. package/src/adw-multi-layout-view.spec.ts +243 -0
  256. package/src/adw-preferences-row.spec.ts +164 -0
  257. package/src/adw-row-state.spec.ts +142 -0
  258. package/src/adw-shortcuts.spec.ts +155 -0
  259. package/src/adw-tab-bar.spec.ts +287 -0
  260. package/src/adw-tab-button.spec.ts +101 -0
  261. package/src/adw-tab-overview.spec.ts +443 -0
  262. package/src/adw-view-switcher-sidebar.spec.ts +281 -0
  263. package/src/adw-window.spec.ts +129 -0
  264. package/src/breakpoints.ts +25 -8
  265. package/src/capabilities.d.mts +3 -0
  266. package/src/capabilities.mjs +18 -0
  267. package/src/connect-lifecycle.spec.ts +12 -0
  268. package/src/construct-vectors.spec.ts +175 -0
  269. package/src/elements/adw-application-window.ts +154 -0
  270. package/src/elements/adw-bin.ts +101 -0
  271. package/src/elements/adw-breakpoint-bin.ts +287 -0
  272. package/src/elements/adw-clamp-scrollable.ts +207 -0
  273. package/src/elements/adw-dialog.ts +19 -0
  274. package/src/elements/adw-layout-slot.ts +95 -0
  275. package/src/elements/adw-multi-layout-view.ts +326 -0
  276. package/src/elements/adw-preferences-row.ts +150 -0
  277. package/src/elements/adw-shortcuts-dialog.ts +52 -0
  278. package/src/elements/adw-shortcuts-item.ts +171 -0
  279. package/src/elements/adw-shortcuts-section.ts +86 -0
  280. package/src/elements/adw-sidebar.ts +42 -3
  281. package/src/elements/adw-switch-row.ts +28 -1
  282. package/src/elements/adw-tab-bar.ts +529 -0
  283. package/src/elements/adw-tab-button.ts +194 -0
  284. package/src/elements/adw-tab-overview.ts +1011 -0
  285. package/src/elements/adw-tab-view.ts +66 -145
  286. package/src/elements/adw-toggle-group.ts +20 -5
  287. package/src/elements/adw-view-stack.ts +18 -0
  288. package/src/elements/adw-view-switcher-sidebar.ts +332 -0
  289. package/src/elements/adw-window.ts +185 -11
  290. package/src/elements/checks.ts +35 -8
  291. package/src/elements/gtk-about-dialog.ts +811 -0
  292. package/src/elements/gtk-application-window.ts +108 -0
  293. package/src/elements/gtk-aspect-frame.ts +160 -0
  294. package/src/elements/gtk-button.ts +12 -0
  295. package/src/elements/gtk-calendar.ts +757 -0
  296. package/src/elements/gtk-center-box.ts +184 -0
  297. package/src/elements/gtk-color-dialog-button.ts +278 -0
  298. package/src/elements/gtk-column-view.ts +320 -0
  299. package/src/elements/gtk-drag-icon.ts +257 -0
  300. package/src/elements/gtk-drawing-area.ts +303 -0
  301. package/src/elements/gtk-editable-label.ts +204 -0
  302. package/src/elements/gtk-emoji-chooser.ts +542 -0
  303. package/src/elements/gtk-entry.ts +39 -5
  304. package/src/elements/gtk-expander.ts +301 -0
  305. package/src/elements/gtk-fixed.ts +99 -0
  306. package/src/elements/gtk-flow-box-child.ts +68 -0
  307. package/src/elements/gtk-flow-box.ts +480 -0
  308. package/src/elements/gtk-font-dialog-button.ts +432 -0
  309. package/src/elements/gtk-frame.ts +174 -0
  310. package/src/elements/gtk-gl-area.ts +476 -0
  311. package/src/elements/gtk-graphics-offload.ts +130 -0
  312. package/src/elements/gtk-grid-view.ts +168 -0
  313. package/src/elements/gtk-grid.ts +127 -0
  314. package/src/elements/gtk-header-bar.ts +273 -0
  315. package/src/elements/gtk-inscription.ts +387 -0
  316. package/src/elements/gtk-label.ts +19 -11
  317. package/src/elements/gtk-level-bar.ts +323 -0
  318. package/src/elements/gtk-link-button.ts +138 -0
  319. package/src/elements/gtk-list-box-row.ts +195 -0
  320. package/src/elements/gtk-list-box.ts +413 -0
  321. package/src/elements/gtk-list-view.ts +370 -0
  322. package/src/elements/gtk-media-controls.ts +509 -0
  323. package/src/elements/gtk-notebook.ts +664 -0
  324. package/src/elements/gtk-overlay.ts +149 -0
  325. package/src/elements/gtk-page-setup-unix-dialog.ts +420 -0
  326. package/src/elements/gtk-paned.ts +597 -0
  327. package/src/elements/gtk-password-entry.ts +170 -0
  328. package/src/elements/gtk-picture.ts +254 -0
  329. package/src/elements/gtk-popover-bin.ts +332 -0
  330. package/src/elements/gtk-popover-menu-bar.ts +355 -0
  331. package/src/elements/gtk-popover-menu.ts +339 -0
  332. package/src/elements/gtk-popover.ts +92 -10
  333. package/src/elements/gtk-print-unix-dialog.ts +989 -0
  334. package/src/elements/gtk-progress-bar.ts +24 -11
  335. package/src/elements/gtk-revealer.ts +406 -0
  336. package/src/elements/gtk-scale-button.ts +358 -0
  337. package/src/elements/gtk-scale.ts +492 -0
  338. package/src/elements/gtk-scrollbar.ts +528 -0
  339. package/src/elements/gtk-scrolled-window.ts +642 -0
  340. package/src/elements/gtk-search-bar.ts +200 -0
  341. package/src/elements/gtk-search-entry.ts +172 -0
  342. package/src/elements/gtk-separator.ts +52 -0
  343. package/src/elements/gtk-spin-button.ts +475 -0
  344. package/src/elements/gtk-spinner.ts +126 -0
  345. package/src/elements/gtk-stack-sidebar.ts +212 -0
  346. package/src/elements/gtk-stack-switcher.ts +279 -0
  347. package/src/elements/gtk-stack.ts +748 -0
  348. package/src/elements/gtk-switch.ts +52 -19
  349. package/src/elements/gtk-text-view.ts +290 -0
  350. package/src/elements/gtk-text.ts +219 -0
  351. package/src/elements/gtk-toggle-button.ts +239 -0
  352. package/src/elements/gtk-tree-expander.ts +243 -0
  353. package/src/elements/gtk-video.ts +423 -0
  354. package/src/elements/gtk-viewport.ts +277 -0
  355. package/src/elements/gtk-window-controls.ts +341 -0
  356. package/src/elements/gtk-window-handle.ts +221 -0
  357. package/src/elements/gtk-window.ts +366 -0
  358. package/src/elements/justification.ts +24 -0
  359. package/src/elements/popover-menu.ts +24 -0
  360. package/src/elements/roving-focus.ts +53 -21
  361. package/src/emoji-data.ts +577 -0
  362. package/src/entry-rows.spec.ts +31 -0
  363. package/src/font-description.ts +238 -0
  364. package/src/gtk-about-dialog.spec.ts +250 -0
  365. package/src/gtk-action-bar.spec.ts +89 -0
  366. package/src/gtk-application-window.spec.ts +107 -0
  367. package/src/gtk-aspect-frame.spec.ts +114 -0
  368. package/src/gtk-calendar.spec.ts +589 -0
  369. package/src/gtk-center-box.spec.ts +125 -0
  370. package/src/gtk-color-dialog-button.spec.ts +141 -0
  371. package/src/gtk-column-view.spec.ts +154 -0
  372. package/src/gtk-drag-icon.spec.ts +190 -0
  373. package/src/gtk-drawing-area.spec.ts +211 -0
  374. package/src/gtk-editable-label.spec.ts +190 -0
  375. package/src/gtk-emoji-chooser.spec.ts +173 -0
  376. package/src/gtk-entry.spec.ts +23 -0
  377. package/src/gtk-expander.spec.ts +170 -0
  378. package/src/gtk-fixed.spec.ts +97 -0
  379. package/src/gtk-flow-box.spec.ts +289 -0
  380. package/src/gtk-font-dialog-button.spec.ts +166 -0
  381. package/src/gtk-frame.spec.ts +119 -0
  382. package/src/gtk-gl-area.spec.ts +361 -0
  383. package/src/gtk-graphics-offload.spec.ts +119 -0
  384. package/src/gtk-grid-view.spec.ts +106 -0
  385. package/src/gtk-grid.spec.ts +122 -0
  386. package/src/gtk-header-bar.spec.ts +202 -0
  387. package/src/gtk-inscription.spec.ts +235 -0
  388. package/src/gtk-level-bar.spec.ts +199 -0
  389. package/src/gtk-link-button.spec.ts +117 -0
  390. package/src/gtk-list-box.spec.ts +422 -0
  391. package/src/gtk-list-view.spec.ts +203 -0
  392. package/src/gtk-media-controls.spec.ts +295 -0
  393. package/src/gtk-notebook.spec.ts +546 -0
  394. package/src/gtk-overlay.spec.ts +141 -0
  395. package/src/gtk-paned.spec.ts +267 -0
  396. package/src/gtk-password-entry.spec.ts +150 -0
  397. package/src/gtk-picture.spec.ts +172 -0
  398. package/src/gtk-popover-bin.spec.ts +229 -0
  399. package/src/gtk-popover-menu-bar.spec.ts +296 -0
  400. package/src/gtk-popover-menu.spec.ts +261 -0
  401. package/src/gtk-popover-role.spec.ts +138 -0
  402. package/src/gtk-popover.spec.ts +264 -0
  403. package/src/gtk-print-dialogs.spec.ts +251 -0
  404. package/src/gtk-revealer.spec.ts +164 -0
  405. package/src/gtk-scale-button.spec.ts +218 -0
  406. package/src/gtk-scale.spec.ts +213 -0
  407. package/src/gtk-scrollbar.spec.ts +244 -0
  408. package/src/gtk-scrolled-window.spec.ts +262 -0
  409. package/src/gtk-search-bar.spec.ts +179 -0
  410. package/src/gtk-search-entry.spec.ts +142 -0
  411. package/src/gtk-separator.spec.ts +74 -0
  412. package/src/gtk-spin-button.spec.ts +186 -0
  413. package/src/gtk-spinner.spec.ts +130 -0
  414. package/src/gtk-stack-sidebar.spec.ts +217 -0
  415. package/src/gtk-stack-switcher.spec.ts +249 -0
  416. package/src/gtk-stack.spec.ts +432 -0
  417. package/src/gtk-text-view.spec.ts +189 -0
  418. package/src/gtk-text.spec.ts +163 -0
  419. package/src/gtk-toggle-button.spec.ts +186 -0
  420. package/src/gtk-tree-expander.spec.ts +201 -0
  421. package/src/gtk-video.spec.ts +240 -0
  422. package/src/gtk-viewport.spec.ts +140 -0
  423. package/src/gtk-window-controls.spec.ts +232 -0
  424. package/src/gtk-window-handle.spec.ts +158 -0
  425. package/src/gtk-window.spec.ts +190 -0
  426. package/src/index.ts +9 -1
  427. package/src/keyboard-operable.spec.ts +33 -1
  428. package/src/list-view-dom.ts +121 -0
  429. package/src/namespace/adw.ts +12 -0
  430. package/src/namespace/gtk.ts +61 -0
  431. package/src/page-setup.ts +222 -0
  432. package/src/scroll-shading.ts +18 -1
  433. package/src/shared-tree-builder.ts +263 -21
  434. package/src/signals.ts +15 -0
  435. package/src/style-classes.spec.ts +9 -8
  436. package/src/styles.generated.ts +1 -1
  437. package/src/tab-chip.ts +200 -0
  438. package/src/template-classes.ts +45 -0
  439. package/src/test.browser.mts +152 -0
@@ -0,0 +1,432 @@
1
+ // <gtk-font-dialog-button> — a button that shows a font and opens a chooser for it. GTK's
2
+ // is a `GtkWidget` holding a plain `GtkButton` whose CHILD is a box of the family label
3
+ // and a size box made of a separator and the size label (gtkfontdialogbutton.c:118-152),
4
+ // with the CSS node `fontbutton > button.font`.
5
+ //
6
+ // THE LABEL IS GTK'S, PORTED WHOLE. `update_font_info` (:649-687) is three rules and all
7
+ // three are visible:
8
+ //
9
+ // · the family label is the family NAME at `level: family`, and `family face` above it
10
+ // — with `C_("font", "None")` standing in for a family that was never set;
11
+ // · the size label is `%2.4g` of the size, `px` appended when the size is absolute
12
+ // (:669-673), and it is only computed at `level` FONT or above;
13
+ // · the size BOX — the separator and that label — is visible at `level` FONT and above
14
+ // and gone below it, so a family chooser shows one word where a font chooser shows
15
+ // two.
16
+ //
17
+ // `use-font` and `use-size` are `apply_use_font` (:689-720): the family label is drawn in
18
+ // the selected font or not at all, and `use-size` decides whether the SIZE is drawn in it
19
+ // too — `PANGO_FONT_MASK_SIZE` is unset when it is not. `font-features` and `language`
20
+ // ride along with it, and CSS takes both in the syntax Pango writes them, so neither needs
21
+ // a translation.
22
+ //
23
+ // THE FACE IS THE PART A BROWSER CANNOT LOOK UP. `update_font_data` (:601-647) walks
24
+ // Pango's font map for the family and then its faces, comparing each face's description
25
+ // with `font_description_style_equal` to find the one that matches, and the label prints
26
+ // its face name. A page has no font map: `document.fonts` is the faces the DOCUMENT
27
+ // declares, and `FontFaceSet.check()` is the only question a browser will answer about a
28
+ // description — "can this combination render at all". So the face here is that answer, and
29
+ // a combination the page cannot render has no face name, exactly as a family Pango has no
30
+ // face for has none.
31
+ //
32
+ // THE CHOOSER, then. Presenting a `GtkFontDialog` is GTK's job and the browser has no
33
+ // font API to do it with, so this element's dialog is a popover over the combinations
34
+ // `document.fonts.check()` accepts for the families the document declares — the (weight,
35
+ // slant) grid a family really exposes — plus whatever the button already holds. What
36
+ // choosing one writes is GTK's, per level: a FAMILY pick builds a fresh description
37
+ // carrying the family alone (:449-458), a FACE pick carries the family and its style
38
+ // (:480-490), and a FONT or FEATURES pick carries the whole thing (:500-510).
39
+ //
40
+ // The sensitivity rule is the colour button's, from the same C shape
41
+ // (gtkfontdialogbutton.c:433-439): `dialog != NULL && cancellable == NULL`, so the button
42
+ // is dead until a dialog is set — from markup with the `dialog` attribute, from code with
43
+ // the `dialog` property.
44
+ //
45
+ // A11Y: GTK's role is GROUP (:426). The size label carries the size as text, because that
46
+ // is what the C puts there; `aria-haspopup` marks the button, matching the C's
47
+ // HAS_POPUP (:154-157).
48
+ //
49
+ // Reference: refs/gtk/gtk/gtkfontdialogbutton.c (font_desc, level, use_font, use_size,
50
+ // update_font_info, apply_use_font, the sensitivity rule, the chosen handlers)
51
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_linked.scss:7 (`fontbutton > button`)
52
+ // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
53
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
54
+
55
+ import {
56
+ PANGO_FONT_DESCRIPTION_DEFAULT,
57
+ cssFontFeatureTags,
58
+ cssFontParts,
59
+ cssFontShorthand,
60
+ fontDescriptionEqual,
61
+ formatFontDescription,
62
+ formatFontSize,
63
+ parseFontDescription,
64
+ type PangoFontDescription,
65
+ } from '../font-description.js';
66
+
67
+ // SIDE-EFFECT imports, for the reason `gtk-menu-button.ts` carries one: the popover
68
+ // binding is used in type position only, so a combined `import { GtkPopover }` would be
69
+ // elided by TypeScript and take the registration with it.
70
+ import './gtk-popover.js';
71
+ import type { GtkPopover } from './gtk-popover.js';
72
+
73
+ import './gtk-separator.js';
74
+
75
+ /** `GtkFontLevel`'s four values, under the nicks a string property carries. */
76
+ export type FontLevel = 'family' | 'face' | 'font' | 'features';
77
+
78
+ const LEVELS: readonly FontLevel[] = ['family', 'face', 'font', 'features'];
79
+
80
+ /** `GtkFontDialog`'s own parameters; `font-map` has no browser counterpart and is absent. */
81
+ export interface FontDialogParameters {
82
+ /** Whether the chooser is modal. Default `TRUE`, as in the GIR. */
83
+ modal?: boolean;
84
+ /** The chooser's title. Default `null`. */
85
+ title?: string | null;
86
+ /** The language font features are resolved against. Default `null`. */
87
+ language?: string | null;
88
+ /** Whether only scalable fonts are offered. */
89
+ filter?: number;
90
+ }
91
+
92
+ /**
93
+ * The (weight, slant) grid a font family exposes — the four faces a family really
94
+ * declares, and the four `FontFaceSet.check()` can answer for. Pango's ladder has twelve
95
+ * weights; a browser page cannot ask which of them a family has beyond whether it renders
96
+ * them, and a chooser listing nine unverified weights per family is worse than one listing
97
+ * the four it can see.
98
+ */
99
+ const FACE_GRID: readonly { weight: number; slant: PangoFontDescription['slant'] }[] = [
100
+ { weight: 400, slant: 'normal' },
101
+ { weight: 700, slant: 'normal' },
102
+ { weight: 400, slant: 'italic' },
103
+ { weight: 700, slant: 'italic' },
104
+ ];
105
+
106
+ export class GtkFontDialogButton extends HTMLElement {
107
+ private _buttonEl!: HTMLButtonElement;
108
+ private _labelEl!: HTMLSpanElement;
109
+ private _sizeBoxEl!: HTMLSpanElement;
110
+ private _sizeLabelEl!: HTMLSpanElement;
111
+ private _dockEl!: GtkPopover;
112
+ private _selectEl!: HTMLSelectElement;
113
+ private _desc: PangoFontDescription = { ...PANGO_FONT_DESCRIPTION_DEFAULT };
114
+ private _dialog: FontDialogParameters | null = null;
115
+ private _features = '';
116
+ private _language: string | null = null;
117
+ private _pending = false;
118
+ private _initialized = false;
119
+
120
+ static get observedAttributes() {
121
+ return ['font-desc', 'font-features', 'language', 'level', 'use-font', 'use-size', 'dialog', 'disabled'];
122
+ }
123
+
124
+ /** `GtkFontDialogButton:font-desc` — the selected font, as a plain value. */
125
+ get fontDesc(): PangoFontDescription {
126
+ return { ...this._desc };
127
+ }
128
+
129
+ set fontDesc(value: PangoFontDescription | string) {
130
+ const next = typeof value === 'string' ? parseFontDescription(value) : value;
131
+ // `set_font_desc` returns early when `pango_font_description_equal` holds
132
+ // (:869-871), and `font-desc` is `G_PARAM_EXPLICIT_NOTIFY`.
133
+ if (fontDescriptionEqual(next, this._desc)) return;
134
+ this._desc = { ...next };
135
+ this._render();
136
+ this.dispatchEvent(
137
+ new CustomEvent('notify::font-desc', { bubbles: true, detail: { fontDesc: this.fontDesc } }),
138
+ );
139
+ }
140
+
141
+ /** `GtkFontDialogButton:font-features` — Pango's comma-separated feature list. */
142
+ get fontFeatures(): string {
143
+ return this._features;
144
+ }
145
+
146
+ set fontFeatures(value: string) {
147
+ if (this._features === value) return; // `g_strcmp0` guard (:922-923)
148
+ this._features = value;
149
+ this._render();
150
+ this.dispatchEvent(new CustomEvent('notify::font-features', { bubbles: true, detail: { value } }));
151
+ }
152
+
153
+ /** `GtkFontDialogButton:language` — the language font features resolve against. */
154
+ get language(): string | null {
155
+ return this._language;
156
+ }
157
+
158
+ set language(value: string | null) {
159
+ if (this._language === value) return; // `self->language == language` (:979-980)
160
+ this._language = value;
161
+ this._render();
162
+ this.dispatchEvent(new CustomEvent('notify::language', { bubbles: true, detail: { value } }));
163
+ }
164
+
165
+ /** `GtkFontDialogButton:level` — how much of the font the chooser offers. */
166
+ get level(): FontLevel {
167
+ const value = this.getAttribute('level');
168
+ return LEVELS.find((level) => level === value) ?? 'font';
169
+ }
170
+
171
+ set level(value: FontLevel) {
172
+ this.setAttribute('level', value);
173
+ }
174
+
175
+ /** `GtkFontDialogButton:use-font` — draw the family label in the selected font. */
176
+ get useFont(): boolean {
177
+ return this.hasAttribute('use-font');
178
+ }
179
+
180
+ set useFont(value: boolean) {
181
+ this.toggleAttribute('use-font', !!value);
182
+ }
183
+
184
+ /** `GtkFontDialogButton:use-size` — draw the selected SIZE in the label too. */
185
+ get useSize(): boolean {
186
+ return this.hasAttribute('use-size');
187
+ }
188
+
189
+ set useSize(value: boolean) {
190
+ this.toggleAttribute('use-size', !!value);
191
+ }
192
+
193
+ /** `GtkFontDialogButton:dialog` — the chooser this button opens, or `null` for none. */
194
+ get dialog(): FontDialogParameters | null {
195
+ return this._dialog;
196
+ }
197
+
198
+ set dialog(value: FontDialogParameters | null) {
199
+ if (this._dialog === value) return;
200
+ this._dialog = value;
201
+ this._renderSensitivity();
202
+ this.dispatchEvent(new CustomEvent('notify::dialog', { bubbles: true, detail: { dialog: value } }));
203
+ }
204
+
205
+ connectedCallback() {
206
+ if (this._initialized) return;
207
+ this._initialized = true;
208
+ this.setAttribute('role', 'group');
209
+
210
+ this._labelEl = document.createElement('span');
211
+ this._labelEl.className = 'font-button-label';
212
+ this._sizeLabelEl = document.createElement('span');
213
+ this._sizeLabelEl.className = 'font-button-size-label';
214
+ const separator = document.createElement('gtk-separator');
215
+ separator.setAttribute('orientation', 'vertical');
216
+ this._sizeBoxEl = document.createElement('span');
217
+ this._sizeBoxEl.className = 'font-button-size';
218
+ this._sizeBoxEl.append(separator, this._sizeLabelEl);
219
+
220
+ this._buttonEl = document.createElement('button');
221
+ this._buttonEl.type = 'button';
222
+ // `gtk_widget_add_css_class (self->button, "font")` (:152).
223
+ this._buttonEl.className = 'adw-button font';
224
+ this._buttonEl.setAttribute('aria-haspopup', 'dialog');
225
+ this._buttonEl.append(this._labelEl, this._sizeBoxEl);
226
+
227
+ this._selectEl = document.createElement('select');
228
+ this._selectEl.className = 'font-button-chooser';
229
+ this._selectEl.addEventListener('change', () => this._choose());
230
+
231
+ this._dockEl = document.createElement('gtk-popover') as GtkPopover;
232
+ this._dockEl.classList.add('font-button-popover');
233
+ this._dockEl.replaceChildren(this._selectEl);
234
+ this._dockEl.anchor = this._buttonEl;
235
+
236
+ this.replaceChildren(this._buttonEl, this._dockEl);
237
+
238
+ this._buttonEl.addEventListener('click', () => this.activate());
239
+ this._dockEl.subscribe((open) => {
240
+ if (!open) this._pending = false;
241
+ this._renderSensitivity();
242
+ });
243
+
244
+ // The attribute doors, applied once the tree exists.
245
+ if (this.hasAttribute('dialog')) this.dialog = {};
246
+ for (const attribute of ['font-desc', 'font-features', 'language'] as const) {
247
+ const authored = this.getAttribute(attribute);
248
+ if (authored === null) continue;
249
+ if (attribute === 'font-desc') this.fontDesc = authored;
250
+ else if (attribute === 'font-features') this.fontFeatures = authored;
251
+ else this.language = authored;
252
+ }
253
+ this._render();
254
+ }
255
+
256
+ attributeChangedCallback(name?: string) {
257
+ if (!this._initialized) return;
258
+ switch (name) {
259
+ case 'font-desc': {
260
+ const authored = this.getAttribute('font-desc');
261
+ if (authored !== null) this.fontDesc = authored;
262
+ return;
263
+ }
264
+ case 'font-features':
265
+ this.fontFeatures = this.getAttribute('font-features') ?? '';
266
+ return;
267
+ case 'language':
268
+ this.language = this.getAttribute('language');
269
+ return;
270
+ case 'dialog':
271
+ this.dialog = this.hasAttribute('dialog') ? (this._dialog ?? {}) : null;
272
+ return;
273
+ case 'disabled':
274
+ this._renderSensitivity();
275
+ return;
276
+ default:
277
+ this._render();
278
+ }
279
+ }
280
+
281
+ /**
282
+ * The `::activate` action signal (:405-418), bound to `gtk_widget_activate (self->button)`
283
+ * (:540-546): activating the widget and pressing the button are the same thing, and
284
+ * both present the chooser.
285
+ */
286
+ activate(): void {
287
+ this.dispatchEvent(new CustomEvent('activate', { bubbles: true }));
288
+ this._openChooser();
289
+ }
290
+
291
+ /** `button_clicked` (:548-585), with the level deciding which C handler would answer. */
292
+ private _openChooser(): void {
293
+ if (this._dialog === null || this._pending) return;
294
+ this._pending = true;
295
+ this._renderSensitivity();
296
+ this._selectEl.replaceChildren(...this._options());
297
+ this._dockEl.popup();
298
+ }
299
+
300
+ /**
301
+ * The combinations this page can actually render, plus the one already held.
302
+ *
303
+ * `FontFaceSet.check()` is the browser's font map in one call, and it is a QUESTION
304
+ * ABOUT A DESCRIPTION, which is exactly the shape of Pango's face walk: the family is
305
+ * the outer loop, the face the inner one, and a combination that does not render is
306
+ * the face the family does not have.
307
+ */
308
+ private _options(): HTMLOptionElement[] {
309
+ const families = new Set<string>();
310
+ for (const face of document.fonts) if (face.family) families.add(face.family);
311
+ if (this._desc.family !== '') families.add(this._desc.family);
312
+
313
+ const options: HTMLOptionElement[] = [];
314
+ const seen = new Set<string>();
315
+ const add = (description: PangoFontDescription) => {
316
+ const key = formatFontDescription(description);
317
+ if (seen.has(key)) return;
318
+ seen.add(key);
319
+ const option = document.createElement('option');
320
+ option.value = key;
321
+ option.textContent = key;
322
+ options.push(option);
323
+ };
324
+ add(this._desc);
325
+ for (const family of [...families].sort()) {
326
+ for (const { weight, slant } of FACE_GRID) {
327
+ const candidate: PangoFontDescription = { ...this._desc, family, weight, slant };
328
+ if (!document.fonts.check(cssFontShorthand(candidate, true))) continue;
329
+ add(candidate);
330
+ }
331
+ }
332
+ return options;
333
+ }
334
+
335
+ /** The four `*_chosen` handlers (:441-538), by level. */
336
+ private _choose(): void {
337
+ const chosen = parseFontDescription(this._selectEl.value);
338
+ const level = this.level;
339
+ if (level === 'family') {
340
+ // `family_chosen`: a fresh description carrying the family and nothing else.
341
+ this.fontDesc = { ...PANGO_FONT_DESCRIPTION_DEFAULT, family: chosen.family };
342
+ } else if (level === 'face') {
343
+ // `face_chosen`: `pango_font_face_describe`, which is family + this face.
344
+ this.fontDesc = { ...chosen, size: this._desc.size, absolute: this._desc.absolute };
345
+ } else {
346
+ // `font_chosen` and `font_and_features_chosen`: the whole description.
347
+ this.fontDesc = chosen;
348
+ }
349
+ this._pending = false;
350
+ this._dockEl.popdown();
351
+ this._renderSensitivity();
352
+ }
353
+
354
+ /** `update_button_sensitivity` (:433-439), as the colour button's is (:380-391). */
355
+ private _renderSensitivity(): void {
356
+ const sensitive = this._dialog !== null && !this.hasAttribute('disabled');
357
+ this._buttonEl.disabled = !sensitive;
358
+ this._buttonEl.classList.toggle('disabled', !sensitive);
359
+ }
360
+
361
+ /** `update_font_info` (:649-687) plus `apply_use_font` (:689-720). */
362
+ private _render(): void {
363
+ if (!this._initialized) return;
364
+ const level = this.level;
365
+ const face = this._faceName();
366
+ // `fam_name` is `C_("font", "None")` when no family was ever set (:653-656), and the
367
+ // label is the family alone at level FAMILY and `family face` above it (:658-665).
368
+ // The C concatenates with a space whether or not the face is there, so the two are
369
+ // joined as parts here and a regular face leaves no trailing space.
370
+ const parts = [this._desc.family === '' ? 'None' : this._desc.family];
371
+ if (level !== 'family' && face !== '') parts.push(face);
372
+ this._labelEl.textContent = parts.join(' ');
373
+
374
+ // The size box is visible from FONT up, and the size is only computed there.
375
+ this._sizeBoxEl.hidden = level === 'family' || level === 'face';
376
+ if (!this._sizeBoxEl.hidden) {
377
+ this._sizeLabelEl.textContent = formatFontSize(this._desc.size, this._desc.absolute);
378
+ }
379
+
380
+ // `apply_use_font` sets or CLEARS the whole attribute list, and it is the four
381
+ // longhands rather than the `font` shorthand: a shorthand is all-or-nothing, so one
382
+ // value the browser rejects would discard the family with it.
383
+ const style = this._labelEl.style;
384
+ if (this.useFont) {
385
+ const parts = cssFontParts(this._desc, this.useSize);
386
+ style.fontFamily = parts.fontFamily;
387
+ style.fontWeight = parts.fontWeight;
388
+ style.fontStyle = parts.fontStyle;
389
+ style.fontStretch = parts.fontStretch;
390
+ // An unset size means "do not set it", which is what `PANGO_FONT_MASK_SIZE`
391
+ // cleared means — so the longhand is emptied rather than given a default.
392
+ style.fontSize = parts.fontSize;
393
+ // Tag by tag: a `font-feature-settings` value is dropped whole when any tag in
394
+ // it is unknown (measured in Firefox), so one rejection must not cost the rest.
395
+ style.fontFeatureSettings = '';
396
+ for (const tag of cssFontFeatureTags(this._features)) {
397
+ style.fontFeatureSettings = tag;
398
+ if (style.fontFeatureSettings === '') continue; // rejected: leave it unset
399
+ break;
400
+ }
401
+ this._labelEl.lang = this._language ?? this._dialog?.language ?? '';
402
+ } else {
403
+ style.fontFamily = '';
404
+ style.fontWeight = '';
405
+ style.fontStyle = '';
406
+ style.fontStretch = '';
407
+ style.fontSize = '';
408
+ style.fontFeatureSettings = '';
409
+ this._labelEl.lang = '';
410
+ }
411
+ this._renderSensitivity();
412
+ }
413
+
414
+ /**
415
+ * `font_description_style_equal` against the faces the page declares — the stand-in for
416
+ * the font-map walk `update_font_data` performs, and the name it prints when there is
417
+ * one.
418
+ */
419
+ private _faceName(): string {
420
+ const style = cssFontShorthand(this._desc, true);
421
+ if (this._desc.family === '' || !document.fonts.check(style)) return '';
422
+ const words: string[] = [];
423
+ if (this._desc.slant === 'italic') words.push('Italic');
424
+ else if (this._desc.slant === 'oblique') words.push('Oblique');
425
+ if (this._desc.weight !== 400) words.push(this._desc.weight >= 700 ? 'Bold' : 'Light');
426
+ if (this._desc.width === 'condensed') words.push('Condensed');
427
+ else if (this._desc.width === 'expanded') words.push('Expanded');
428
+ return words.join(' ');
429
+ }
430
+ }
431
+
432
+ customElements.define('gtk-font-dialog-button', GtkFontDialogButton);
@@ -0,0 +1,174 @@
1
+ // <gtk-frame> — Gtk.Frame: a decorative border with a label embedded in its top edge.
2
+ //
3
+ // GTK puts the label WIDGET and the child in the same box: the label takes the whole
4
+ // width line above the child and the child gets what is left
5
+ // (gtkframe.c:554-580, `compute_child_allocation`), which is a flex column. The label is
6
+ // NOT stretched — it is measured, clipped to the frame's width and placed at
7
+ // `(width - label_width) * label_xalign` (gtkframe.c:519-553), which is `align-self` on
8
+ // the label and nothing else. `label-xalign` is mirrored in RTL by GTK itself
9
+ // (gtkframe.c:530-533); `flex-start` is direction-aware already, so the mirroring is the
10
+ // browser's rather than a second rule.
11
+ //
12
+ // `label` is the STRING GtkFrame carries, and `gtk_frame_set_label()` turns it into a
13
+ // `Gtk.Label` (gtkframe.c:349-358) — so the element builds that label itself and unparents
14
+ // it when the string goes away, exactly as `set_label_widget(NULL)` does. An authored
15
+ // `label-widget` slot WINS over the string, which is the order GTK's two setters leave it
16
+ // in whenever the widget is set last (gtkframe.c:424-444 replaces one with the other).
17
+ //
18
+ // `gtk_frame_init` sets `GTK_OVERFLOW_HIDDEN` (gtkframe.c:246), and the GIR doc says the
19
+ // frame CLIPS its child — so the border can round the child's corners, at the cost of
20
+ // cutting its shadows off. `overflow: hidden` is that, in `_frame.scss`.
21
+ //
22
+ // A11Y: `role="group"`, GtkFrame's own accessible role (gtkframe.c:209). GTK also wires
23
+ // LABELLED_BY from the frame to its child (gtkframe.c:389-398); the browser form of that
24
+ // is the child's `aria-labelledby`, which belongs to whoever authors the child.
25
+ //
26
+ // Reference: refs/gtk/gtk/gtkframe.c:170-209, :245-257, :519-580
27
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_misc.scss:4-15
28
+ // Copyright (c) The GTK Team. LGPLv2.1+.
29
+ // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
30
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
31
+
32
+ import { glibClamp, labelYalignAlignItems } from '@gjsify/adwaita-core';
33
+
34
+ import { bindSlottedChildren } from '../slotted-children.js';
35
+
36
+ /** `Gtk.Frame:label-xalign`'s pspec default (gtkframe.c:180-183, and `:253`). */
37
+ const LABEL_XALIGN_DEFAULT = 0;
38
+
39
+ /** The float `label_xalign` is held in: clamped to the pspec's 0…1, unparseable is the default. */
40
+ function normalizeLabelXalign(value: string | null): number {
41
+ const parsed = Number.parseFloat(value ?? '');
42
+ return Number.isFinite(parsed) ? glibClamp(parsed, 0, 1) : LABEL_XALIGN_DEFAULT;
43
+ }
44
+
45
+ export class GtkFrame extends HTMLElement {
46
+ private _mutations: MutationObserver | null = null;
47
+
48
+ static get observedAttributes() {
49
+ return ['label', 'label-xalign'];
50
+ }
51
+
52
+ /** The element's own `<gtk-label>`, built from `label` — null while no string is set. */
53
+ private _labelEl: HTMLElement | null = null;
54
+
55
+ /** True while {@link _sync} writes `label` onto that widget, so its notify does not escape. */
56
+ private _writingLabel = false;
57
+
58
+ /** `Gtk.Frame:label` — the frame's label text, or null when it carries no label. */
59
+ get label(): string | null {
60
+ return this.getAttribute('label');
61
+ }
62
+
63
+ set label(value: string | null) {
64
+ if (value === null) this.removeAttribute('label');
65
+ else this.setAttribute('label', value);
66
+ }
67
+
68
+ /**
69
+ * `Gtk.Frame:label-xalign` — where the label sits across the frame's width.
70
+ * `0` (the pspec default) puts it at the start, `1` at the end, `0.5` centred.
71
+ */
72
+ get labelXalign(): number {
73
+ return normalizeLabelXalign(this.getAttribute('label-xalign'));
74
+ }
75
+
76
+ set labelXalign(value: number) {
77
+ this.setAttribute('label-xalign', String(value));
78
+ }
79
+
80
+ /** The child in GTK's `label-widget` slot — the widget drawn in place of the text. */
81
+ get labelWidget(): HTMLElement | null {
82
+ const named = this.querySelector<HTMLElement>('[slot="label-widget"]');
83
+ if (named !== null) return named;
84
+ // A label that has been unparented is not this frame's label any more, and GTK's
85
+ // getter reads the SLOT (gtkframe.c:412-420) rather than the string it came from.
86
+ return this._labelEl?.parentNode === this ? this._labelEl : null;
87
+ }
88
+
89
+ set labelWidget(value: HTMLElement | null) {
90
+ const current = this.querySelector('[slot="label-widget"]');
91
+ if (current !== null) {
92
+ current.removeAttribute('slot');
93
+ // `gtk_frame_set_label_widget` UNPARENTS whatever it replaces (gtkframe.c:424-437).
94
+ current.remove();
95
+ }
96
+ if (value === null) return;
97
+ value.setAttribute('slot', 'label-widget');
98
+ // FIRST, because GTK stacks the label above the child (gtkframe.c:558-563).
99
+ this.prepend(value);
100
+ this._sync();
101
+ }
102
+
103
+ connectedCallback() {
104
+ // The two NAMES, so an authored tree may address them; nothing is ROUTED, because
105
+ // the label is GTK's FIRST child either way and the child is everything else. The
106
+ // string label is built here and cannot arrive through a slot.
107
+ bindSlottedChildren(this, [
108
+ { name: 'child', into: this },
109
+ { name: 'label-widget', into: this },
110
+ ]);
111
+ // The label is an ELEMENT the element owns, and an author who replaces the frame's
112
+ // children — `frame.innerHTML = …`, which is how a renderer re-renders a subtree —
113
+ // takes it with them. One observer puts it back, the same "evaluated once at connect
114
+ // time" repair `<adw-clamp>` makes for its children's widths.
115
+ this._mutations = new MutationObserver(() => this._sync());
116
+ this._mutations.observe(this, { childList: true });
117
+ this.setAttribute('role', 'group');
118
+ this._sync();
119
+ }
120
+
121
+ disconnectedCallback() {
122
+ this._mutations?.disconnect();
123
+ this._mutations = null;
124
+ }
125
+
126
+ attributeChangedCallback(name: string, old: string | null, value: string | null) {
127
+ this._sync();
128
+ if (!this.isConnected) return;
129
+ const next = name === 'label-xalign' ? String(normalizeLabelXalign(value)) : value;
130
+ const before = name === 'label-xalign' ? String(normalizeLabelXalign(old)) : old;
131
+ if (next === before) return;
132
+ this.dispatchEvent(new CustomEvent(`notify::${name}`, { bubbles: true, detail: { [name]: next } }));
133
+ }
134
+
135
+ private _sync(): void {
136
+ // An authored `label-widget` and the string are mutually exclusive in GTK: the last
137
+ // setter unparents the other (gtkframe.c:424-444). Markup states both at once, so
138
+ // the widget wins and the string is the fallback — stated here because the reverse
139
+ // would silently drop an author's child.
140
+ const authored = this.querySelector<HTMLElement>('[slot="label-widget"]');
141
+ const wanted = this.getAttribute('label');
142
+ if (authored === null && wanted !== null) {
143
+ if (this._labelEl === null) {
144
+ this._labelEl = document.createElement('gtk-label');
145
+ // The label WIDGET is the frame's own, built from the `label` STRING, and GTK
146
+ // notifies on the FRAME alone (gtkframe.c:519-537) — there is no label widget
147
+ // an author reaches through `gtk_frame_set_label()`. Its own `notify::label`
148
+ // bubbles by default, so a listener on the frame saw the same change twice:
149
+ // once from the child and once from the frame. Suppressed ONLY for a write
150
+ // this method made, so a listener on the label widget itself still hears an
151
+ // author who sets `label` on it directly.
152
+ this._labelEl.addEventListener('notify::label', (event) => {
153
+ if (this._writingLabel) event.stopPropagation();
154
+ });
155
+ }
156
+ this._writingLabel = true;
157
+ this._labelEl.setAttribute('label', wanted);
158
+ this._writingLabel = false;
159
+ // FIRST, because GTK stacks the label above the child (gtkframe.c:558-563).
160
+ if (this._labelEl.parentNode !== this) this.prepend(this._labelEl);
161
+ } else if (this._labelEl?.parentNode === this) {
162
+ this._labelEl.remove();
163
+ }
164
+
165
+ const label = this.labelWidget;
166
+ // `flex: none` and the 4px inset are the widget's own, in `_frame.scss`; only the
167
+ // placement is per-instance, so it is the only thing written here.
168
+ if (label === null) return;
169
+ label.classList.add('adw-frame-label');
170
+ label.style.alignSelf = labelYalignAlignItems(this.labelXalign);
171
+ }
172
+ }
173
+
174
+ customElements.define('gtk-frame', GtkFrame);