@gjsify/adwaita-web 0.64.1 → 0.64.2-next.254

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 (335) hide show
  1. package/README.md +22 -88
  2. package/dist/adwaita-web.css +91 -12
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/accessible.d.ts +8 -0
  5. package/lib/types/application.d.ts +1 -1
  6. package/lib/types/child-slot.spec.d.ts +1 -0
  7. package/lib/types/compute-expand.d.ts +5 -0
  8. package/lib/types/compute-expand.spec.d.ts +1 -0
  9. package/lib/types/container-fill.spec.d.ts +1 -0
  10. package/lib/types/elements/adw-about-dialog.d.ts +28 -1
  11. package/lib/types/elements/adw-action-row.d.ts +2 -1
  12. package/lib/types/elements/adw-alert-dialog.d.ts +80 -19
  13. package/lib/types/elements/adw-avatar.d.ts +2 -1
  14. package/lib/types/elements/adw-banner.d.ts +2 -1
  15. package/lib/types/elements/adw-bin.d.ts +2 -1
  16. package/lib/types/elements/adw-bottom-sheet.d.ts +5 -4
  17. package/lib/types/elements/adw-breakpoint-bin.d.ts +2 -1
  18. package/lib/types/elements/adw-button-content.d.ts +2 -1
  19. package/lib/types/elements/adw-button-row.d.ts +2 -1
  20. package/lib/types/elements/adw-card.d.ts +2 -1
  21. package/lib/types/elements/adw-carousel.d.ts +20 -3
  22. package/lib/types/elements/adw-clamp-scrollable.d.ts +2 -1
  23. package/lib/types/elements/adw-clamp.d.ts +2 -1
  24. package/lib/types/elements/adw-combo-row.d.ts +6 -1
  25. package/lib/types/elements/adw-data-grid.d.ts +2 -1
  26. package/lib/types/elements/adw-dialog.d.ts +2 -1
  27. package/lib/types/elements/adw-entry-row.d.ts +2 -1
  28. package/lib/types/elements/adw-expander-row.d.ts +2 -1
  29. package/lib/types/elements/adw-header-bar.d.ts +2 -1
  30. package/lib/types/elements/adw-inline-view-switcher.d.ts +3 -2
  31. package/lib/types/elements/adw-layout-slot.d.ts +2 -1
  32. package/lib/types/elements/adw-multi-layout-view.d.ts +2 -1
  33. package/lib/types/elements/adw-navigation-split-view.d.ts +2 -1
  34. package/lib/types/elements/adw-navigation-view.d.ts +3 -2
  35. package/lib/types/elements/adw-overlay-split-view.d.ts +2 -1
  36. package/lib/types/elements/adw-preferences-dialog.d.ts +5 -4
  37. package/lib/types/elements/adw-preferences-group.d.ts +2 -1
  38. package/lib/types/elements/adw-preferences-row.d.ts +2 -1
  39. package/lib/types/elements/adw-shortcut-label.d.ts +2 -1
  40. package/lib/types/elements/adw-shortcuts-item.d.ts +2 -1
  41. package/lib/types/elements/adw-shortcuts-section.d.ts +2 -1
  42. package/lib/types/elements/adw-sidebar.d.ts +4 -3
  43. package/lib/types/elements/adw-spin-row.d.ts +2 -1
  44. package/lib/types/elements/adw-spinner.d.ts +2 -1
  45. package/lib/types/elements/adw-split-button.d.ts +2 -1
  46. package/lib/types/elements/adw-status-page.d.ts +2 -1
  47. package/lib/types/elements/adw-switch-row.d.ts +4 -1
  48. package/lib/types/elements/adw-tab-bar.d.ts +2 -1
  49. package/lib/types/elements/adw-tab-button.d.ts +2 -1
  50. package/lib/types/elements/adw-tab-overview.d.ts +2 -1
  51. package/lib/types/elements/adw-tab-view.d.ts +3 -2
  52. package/lib/types/elements/adw-toast-overlay.d.ts +10 -30
  53. package/lib/types/elements/adw-toggle-group.d.ts +3 -2
  54. package/lib/types/elements/adw-toolbar-view.d.ts +2 -1
  55. package/lib/types/elements/adw-view-stack.d.ts +3 -1
  56. package/lib/types/elements/adw-view-switcher-bar.d.ts +2 -1
  57. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +2 -1
  58. package/lib/types/elements/adw-view-switcher.d.ts +3 -2
  59. package/lib/types/elements/adw-window-features.d.ts +8 -0
  60. package/lib/types/elements/adw-window-title.d.ts +2 -1
  61. package/lib/types/elements/adw-wrap-box.d.ts +2 -1
  62. package/lib/types/elements/checks.d.ts +16 -1
  63. package/lib/types/elements/gtk-action-bar.d.ts +2 -1
  64. package/lib/types/elements/gtk-application-window.d.ts +1 -4
  65. package/lib/types/elements/gtk-aspect-frame.d.ts +2 -1
  66. package/lib/types/elements/gtk-box.d.ts +5 -1
  67. package/lib/types/elements/gtk-button.d.ts +5 -7
  68. package/lib/types/elements/gtk-calendar.d.ts +2 -1
  69. package/lib/types/elements/gtk-center-box.d.ts +2 -1
  70. package/lib/types/elements/gtk-color-dialog-button.d.ts +2 -1
  71. package/lib/types/elements/gtk-drag-icon.d.ts +2 -1
  72. package/lib/types/elements/gtk-drawing-area.d.ts +2 -1
  73. package/lib/types/elements/gtk-drop-down.d.ts +2 -1
  74. package/lib/types/elements/gtk-editable-label.d.ts +2 -1
  75. package/lib/types/elements/gtk-emoji-chooser.d.ts +2 -0
  76. package/lib/types/elements/gtk-entry.d.ts +2 -1
  77. package/lib/types/elements/gtk-expander.d.ts +2 -1
  78. package/lib/types/elements/gtk-fixed.d.ts +2 -1
  79. package/lib/types/elements/gtk-flow-box-child.d.ts +2 -1
  80. package/lib/types/elements/gtk-flow-box.d.ts +2 -1
  81. package/lib/types/elements/gtk-font-dialog-button.d.ts +2 -1
  82. package/lib/types/elements/gtk-frame.d.ts +2 -1
  83. package/lib/types/elements/gtk-gl-area.d.ts +2 -1
  84. package/lib/types/elements/gtk-graphics-offload.d.ts +2 -1
  85. package/lib/types/elements/gtk-grid.d.ts +2 -1
  86. package/lib/types/elements/gtk-header-bar.d.ts +2 -1
  87. package/lib/types/elements/gtk-image.d.ts +5 -6
  88. package/lib/types/elements/gtk-inscription.d.ts +2 -1
  89. package/lib/types/elements/gtk-label.d.ts +10 -3
  90. package/lib/types/elements/gtk-level-bar.d.ts +2 -1
  91. package/lib/types/elements/gtk-list-box-row.d.ts +2 -1
  92. package/lib/types/elements/gtk-list-box.d.ts +2 -1
  93. package/lib/types/elements/gtk-list-view.d.ts +2 -1
  94. package/lib/types/elements/gtk-media-controls.d.ts +2 -1
  95. package/lib/types/elements/gtk-menu-button.d.ts +2 -1
  96. package/lib/types/elements/gtk-notebook.d.ts +2 -1
  97. package/lib/types/elements/gtk-overlay.d.ts +2 -1
  98. package/lib/types/elements/gtk-paned.d.ts +2 -1
  99. package/lib/types/elements/gtk-picture.d.ts +2 -1
  100. package/lib/types/elements/gtk-popover-bin.d.ts +2 -1
  101. package/lib/types/elements/gtk-popover-menu-bar.d.ts +2 -1
  102. package/lib/types/elements/gtk-popover-menu.d.ts +2 -0
  103. package/lib/types/elements/gtk-popover.d.ts +7 -1
  104. package/lib/types/elements/gtk-progress-bar.d.ts +2 -1
  105. package/lib/types/elements/gtk-revealer.d.ts +2 -1
  106. package/lib/types/elements/gtk-scale-button.d.ts +2 -1
  107. package/lib/types/elements/gtk-scale.d.ts +2 -1
  108. package/lib/types/elements/gtk-scrollbar.d.ts +2 -1
  109. package/lib/types/elements/gtk-scrolled-window.d.ts +2 -1
  110. package/lib/types/elements/gtk-search-bar.d.ts +2 -1
  111. package/lib/types/elements/gtk-separator.d.ts +2 -1
  112. package/lib/types/elements/gtk-spin-button.d.ts +2 -1
  113. package/lib/types/elements/gtk-spinner.d.ts +2 -1
  114. package/lib/types/elements/gtk-stack-page.d.ts +29 -0
  115. package/lib/types/elements/gtk-stack-sidebar.d.ts +2 -1
  116. package/lib/types/elements/gtk-stack-switcher.d.ts +2 -1
  117. package/lib/types/elements/gtk-stack.d.ts +13 -1
  118. package/lib/types/elements/gtk-switch.d.ts +2 -1
  119. package/lib/types/elements/gtk-text-view.d.ts +2 -1
  120. package/lib/types/elements/gtk-text.d.ts +2 -1
  121. package/lib/types/elements/gtk-tree-expander.d.ts +2 -1
  122. package/lib/types/elements/gtk-video.d.ts +2 -1
  123. package/lib/types/elements/gtk-viewport.d.ts +2 -1
  124. package/lib/types/elements/gtk-window-controls.d.ts +2 -1
  125. package/lib/types/elements/gtk-window-handle.d.ts +2 -1
  126. package/lib/types/elements/gtk-window.d.ts +18 -2
  127. package/lib/types/gobject-elements.d.ts +15 -0
  128. package/lib/types/gtksource/gtk-source-view.d.ts +2 -1
  129. package/lib/types/{icon-registry.spec.d.ts → icon-masks.spec.d.ts} +1 -1
  130. package/lib/types/icon-theme.d.ts +15 -35
  131. package/lib/types/index.d.ts +3 -4
  132. package/lib/types/learn6502-window.spec.d.ts +1 -0
  133. package/lib/types/namespace/adw.d.ts +1 -1
  134. package/lib/types/namespace/gdk.d.ts +1 -0
  135. package/lib/types/namespace/gio.d.ts +1 -0
  136. package/lib/types/namespace/glib.d.ts +2 -1
  137. package/lib/types/namespace/gtk.d.ts +2 -0
  138. package/lib/types/shared-tree-builder.d.ts +31 -0
  139. package/lib/types/signals.d.ts +5 -1
  140. package/lib/types/source-view/adw-source-view.d.ts +2 -1
  141. package/lib/types/styles.generated.d.ts +1 -1
  142. package/lib/types/widget-element.d.ts +25 -0
  143. package/lib/types/widget-map.spec.d.ts +1 -0
  144. package/lib/types/widget-mapping.d.ts +7 -0
  145. package/lib/types/widget-visible.spec.d.ts +1 -0
  146. package/lib/types/window-maximize.spec.d.ts +1 -0
  147. package/package.json +13 -12
  148. package/scss/_about_dialog.scss +46 -1
  149. package/scss/_bin.scss +6 -3
  150. package/scss/_checks.scss +5 -2
  151. package/scss/_icon.scss +3 -4
  152. package/scss/_labels.scss +2 -2
  153. package/scss/_overlay.scss +11 -1
  154. package/scss/_overlay_split_view.scss +10 -0
  155. package/scss/_reset.scss +1 -1
  156. package/scss/_scrolled_window.scss +15 -0
  157. package/scss/_stack.scss +8 -2
  158. package/scss/_toast.scss +13 -3
  159. package/scss/_widget.scss +5 -1
  160. package/scss/_window.scss +16 -0
  161. package/src/accessible.ts +29 -0
  162. package/src/adw-about-dialog.spec.ts +81 -12
  163. package/src/adw-action-rows.spec.ts +2 -2
  164. package/src/adw-alert-dialog.spec.ts +71 -5
  165. package/src/adw-bin.spec.ts +4 -3
  166. package/src/adw-button-content.spec.ts +1 -1
  167. package/src/adw-carousel.spec.ts +49 -1
  168. package/src/adw-header-bar.spec.ts +18 -0
  169. package/src/adw-toast-overlay.spec.ts +68 -24
  170. package/src/application.spec.ts +44 -0
  171. package/src/application.ts +13 -18
  172. package/src/capabilities.mjs +2 -3
  173. package/src/checks.spec.ts +51 -1
  174. package/src/child-slot.spec.ts +71 -0
  175. package/src/compute-expand.spec.ts +186 -0
  176. package/src/compute-expand.ts +134 -0
  177. package/src/construct-vectors.spec.ts +97 -7
  178. package/src/container-fill.spec.ts +70 -0
  179. package/src/elements/adw-about-dialog.ts +152 -9
  180. package/src/elements/adw-action-row.ts +2 -1
  181. package/src/elements/adw-alert-dialog.ts +177 -46
  182. package/src/elements/adw-application-window.ts +0 -3
  183. package/src/elements/adw-avatar.ts +2 -1
  184. package/src/elements/adw-banner.ts +2 -1
  185. package/src/elements/adw-bin.ts +2 -1
  186. package/src/elements/adw-bottom-sheet.ts +5 -4
  187. package/src/elements/adw-breakpoint-bin.ts +5 -1
  188. package/src/elements/adw-button-content.ts +2 -1
  189. package/src/elements/adw-button-row.ts +2 -1
  190. package/src/elements/adw-card.ts +2 -1
  191. package/src/elements/adw-carousel.ts +62 -3
  192. package/src/elements/adw-clamp-scrollable.ts +2 -1
  193. package/src/elements/adw-clamp.ts +2 -1
  194. package/src/elements/adw-combo-row.ts +15 -1
  195. package/src/elements/adw-data-grid.ts +2 -1
  196. package/src/elements/adw-dialog.ts +5 -2
  197. package/src/elements/adw-entry-row.ts +2 -1
  198. package/src/elements/adw-expander-row.ts +2 -1
  199. package/src/elements/adw-header-bar.ts +6 -1
  200. package/src/elements/adw-inline-view-switcher.ts +3 -2
  201. package/src/elements/adw-layout-slot.ts +2 -1
  202. package/src/elements/adw-multi-layout-view.ts +2 -1
  203. package/src/elements/adw-navigation-split-view.ts +2 -1
  204. package/src/elements/adw-navigation-view.ts +3 -2
  205. package/src/elements/adw-overlay-split-view.ts +2 -1
  206. package/src/elements/adw-preferences-dialog.ts +6 -4
  207. package/src/elements/adw-preferences-group.ts +2 -1
  208. package/src/elements/adw-preferences-row.ts +2 -1
  209. package/src/elements/adw-shortcut-label.ts +2 -1
  210. package/src/elements/adw-shortcuts-item.ts +2 -1
  211. package/src/elements/adw-shortcuts-section.ts +2 -1
  212. package/src/elements/adw-sidebar.ts +4 -3
  213. package/src/elements/adw-spin-row.ts +2 -1
  214. package/src/elements/adw-spinner.ts +2 -1
  215. package/src/elements/adw-split-button.ts +2 -1
  216. package/src/elements/adw-status-page.ts +2 -1
  217. package/src/elements/adw-switch-row.ts +10 -1
  218. package/src/elements/adw-tab-bar.ts +2 -1
  219. package/src/elements/adw-tab-button.ts +2 -1
  220. package/src/elements/adw-tab-overview.ts +2 -1
  221. package/src/elements/adw-tab-view.ts +3 -2
  222. package/src/elements/adw-toast-overlay.ts +37 -70
  223. package/src/elements/adw-toggle-group.ts +3 -2
  224. package/src/elements/adw-toolbar-view.ts +2 -1
  225. package/src/elements/adw-view-stack.ts +39 -1
  226. package/src/elements/adw-view-switcher-bar.ts +2 -1
  227. package/src/elements/adw-view-switcher-sidebar.ts +2 -1
  228. package/src/elements/adw-view-switcher.ts +3 -2
  229. package/src/elements/adw-window-features.ts +14 -2
  230. package/src/elements/adw-window-title.ts +2 -1
  231. package/src/elements/adw-wrap-box.ts +2 -1
  232. package/src/elements/checks.ts +85 -6
  233. package/src/elements/gtk-action-bar.ts +2 -1
  234. package/src/elements/gtk-application-window.ts +3 -8
  235. package/src/elements/gtk-aspect-frame.ts +2 -1
  236. package/src/elements/gtk-box.ts +56 -1
  237. package/src/elements/gtk-button.ts +10 -22
  238. package/src/elements/gtk-calendar.ts +2 -1
  239. package/src/elements/gtk-center-box.ts +2 -1
  240. package/src/elements/gtk-color-dialog-button.ts +2 -1
  241. package/src/elements/gtk-drag-icon.ts +6 -1
  242. package/src/elements/gtk-drawing-area.ts +2 -1
  243. package/src/elements/gtk-drop-down.ts +2 -1
  244. package/src/elements/gtk-editable-label.ts +2 -1
  245. package/src/elements/gtk-emoji-chooser.ts +5 -0
  246. package/src/elements/gtk-entry.ts +2 -1
  247. package/src/elements/gtk-expander.ts +2 -1
  248. package/src/elements/gtk-fixed.ts +2 -1
  249. package/src/elements/gtk-flow-box-child.ts +5 -2
  250. package/src/elements/gtk-flow-box.ts +2 -1
  251. package/src/elements/gtk-font-dialog-button.ts +2 -1
  252. package/src/elements/gtk-frame.ts +2 -1
  253. package/src/elements/gtk-gl-area.ts +2 -1
  254. package/src/elements/gtk-graphics-offload.ts +5 -2
  255. package/src/elements/gtk-grid.ts +2 -1
  256. package/src/elements/gtk-header-bar.ts +2 -1
  257. package/src/elements/gtk-image.ts +14 -15
  258. package/src/elements/gtk-inscription.ts +2 -1
  259. package/src/elements/gtk-label.ts +12 -5
  260. package/src/elements/gtk-level-bar.ts +2 -1
  261. package/src/elements/gtk-list-box-row.ts +5 -2
  262. package/src/elements/gtk-list-box.ts +2 -1
  263. package/src/elements/gtk-list-view.ts +2 -1
  264. package/src/elements/gtk-media-controls.ts +2 -1
  265. package/src/elements/gtk-menu-button.ts +2 -1
  266. package/src/elements/gtk-notebook.ts +2 -1
  267. package/src/elements/gtk-overlay.ts +7 -5
  268. package/src/elements/gtk-paned.ts +9 -2
  269. package/src/elements/gtk-picture.ts +2 -1
  270. package/src/elements/gtk-popover-bin.ts +5 -1
  271. package/src/elements/gtk-popover-menu-bar.ts +2 -1
  272. package/src/elements/gtk-popover-menu.ts +5 -0
  273. package/src/elements/gtk-popover.ts +14 -1
  274. package/src/elements/gtk-progress-bar.ts +2 -1
  275. package/src/elements/gtk-revealer.ts +2 -1
  276. package/src/elements/gtk-scale-button.ts +2 -1
  277. package/src/elements/gtk-scale.ts +2 -1
  278. package/src/elements/gtk-scrollbar.ts +2 -1
  279. package/src/elements/gtk-scrolled-window.ts +8 -5
  280. package/src/elements/gtk-search-bar.ts +7 -6
  281. package/src/elements/gtk-separator.ts +2 -1
  282. package/src/elements/gtk-spin-button.ts +2 -1
  283. package/src/elements/gtk-spinner.ts +2 -1
  284. package/src/elements/gtk-stack-page.ts +112 -0
  285. package/src/elements/gtk-stack-sidebar.ts +2 -1
  286. package/src/elements/gtk-stack-switcher.ts +2 -1
  287. package/src/elements/gtk-stack.ts +52 -6
  288. package/src/elements/gtk-switch.ts +2 -1
  289. package/src/elements/gtk-text-view.ts +2 -1
  290. package/src/elements/gtk-text.ts +2 -1
  291. package/src/elements/gtk-tree-expander.ts +5 -1
  292. package/src/elements/gtk-video.ts +2 -1
  293. package/src/elements/gtk-viewport.ts +6 -1
  294. package/src/elements/gtk-window-controls.ts +2 -1
  295. package/src/elements/gtk-window-handle.ts +6 -1
  296. package/src/elements/gtk-window.ts +57 -7
  297. package/src/gio.spec.ts +13 -3
  298. package/src/glib.spec.ts +9 -0
  299. package/src/gobject-elements.ts +44 -2
  300. package/src/gtk-label.spec.ts +39 -0
  301. package/src/gtk-scrolled-window.spec.ts +6 -6
  302. package/src/gtk-stack.spec.ts +170 -0
  303. package/src/gtk-value-doors.spec.ts +19 -0
  304. package/src/gtk-window.spec.ts +2 -2
  305. package/src/gtksource/gtk-source-view.ts +2 -1
  306. package/src/{icon-registry.spec.ts → icon-masks.spec.ts} +4 -100
  307. package/src/icon-theme.spec.ts +69 -124
  308. package/src/icon-theme.ts +29 -119
  309. package/src/index.ts +5 -9
  310. package/src/keyboard-operable.spec.ts +3 -3
  311. package/src/learn6502-window.spec.ts +113 -0
  312. package/src/namespace/adw.ts +1 -1
  313. package/src/namespace/gdk.ts +1 -0
  314. package/src/namespace/gio.ts +8 -0
  315. package/src/namespace/glib.ts +4 -0
  316. package/src/namespace/gtk.ts +2 -0
  317. package/src/shared-tree-builder.ts +131 -13
  318. package/src/shared-trees.spec.ts +15 -1
  319. package/src/signals.ts +11 -2
  320. package/src/slotted-children.spec.ts +24 -0
  321. package/src/slotted-children.ts +18 -2
  322. package/src/source-view/adw-source-view.ts +2 -1
  323. package/src/split-button.spec.ts +1 -1
  324. package/src/style-manager.spec.ts +13 -0
  325. package/src/style-manager.ts +6 -0
  326. package/src/styles.generated.ts +1 -1
  327. package/src/test.browser.mts +16 -2
  328. package/src/value-lists.spec.ts +3 -3
  329. package/src/widget-element.ts +75 -0
  330. package/src/widget-map.spec.ts +116 -0
  331. package/src/widget-mapping.ts +100 -0
  332. package/src/widget-visible.spec.ts +148 -0
  333. package/src/window-maximize.spec.ts +93 -0
  334. package/lib/types/icon-registry.d.ts +0 -37
  335. package/src/icon-registry.ts +0 -163
@@ -28,7 +28,7 @@
28
28
  // into a host `<div>` it was never given.
29
29
  //
30
30
  // Placed flat under `src/`, at parity with this package's other single-purpose modules
31
- // (`accent.ts`, `breakpoints.ts`, `icon-registry.ts`) rather than a new `conformance/` or
31
+ // (`accent.ts`, `breakpoints.ts`, `icon-theme.ts`) rather than a new `conformance/` or
32
32
  // `builder/` directory for one file: unlike `gtk-host`, this package has no existing
33
33
  // `conformance/` home to add to. Exported through the existing barrel, `src/index.ts` — the
34
34
  // package's `exports` map ships only `.`, and a new subpath would buy nothing for a module
@@ -55,7 +55,14 @@ import {
55
55
 
56
56
  import { observeAdaptiveSize } from './breakpoints.js';
57
57
  import { capabilities } from './capabilities.mjs';
58
- import { endpointOf, hasElementApi, installElementApi, installSensitive } from './gobject-elements.js';
58
+ import {
59
+ endpointOf,
60
+ hasElementApi,
61
+ hasInstalledVisible,
62
+ installElementApi,
63
+ installSensitive,
64
+ installVisible,
65
+ } from './gobject-elements.js';
59
66
  import { dispatchedSignalsOf } from './signals.js';
60
67
  import { slottedChildrenOf } from './slotted-children.js';
61
68
  import { isTemplateTag, templateTagFor } from './template-classes.js';
@@ -154,14 +161,93 @@ function isWritable(el: object, member: string): boolean {
154
161
  * upgraded has declared no slots yet, so the refusal below belongs to the mount.
155
162
  */
156
163
  export function buildSharedTree(node: SharedTreeNode, record: BuildRecord = newRecord()): HTMLElement {
164
+ refuseSiblings(node, 'buildSharedTree');
165
+ return buildTree(node, record).root;
166
+ }
167
+
168
+ /** What {@link buildWithSiblings} hands back: the root element and the objects built beside it. */
169
+ export interface BuiltTree {
170
+ /** The element the tree roots at, as {@link buildSharedTree} returns it. */
171
+ root: HTMLElement;
172
+ /**
173
+ * The sibling objects by id — `Adw.AlertDialog unsavedChangesDialog { }` or `$Learn learn { }`
174
+ * written after the template. A sibling is built in the root's id scope (a setter or a bind
175
+ * may name it) but is no child of the root: the code beside the file decides where, or
176
+ * whether, it is placed.
177
+ */
178
+ siblings: ReadonlyMap<string, HTMLElement>;
179
+ /** Every element the tree names by id, siblings included: what `GtkBuilder.get_object` answers for. */
180
+ objects: ReadonlyMap<string, HTMLElement>;
181
+ }
182
+
183
+ /** What {@link buildWithSiblings} takes beside the tree. */
184
+ export interface BuildOptions {
185
+ /** The object a handler NAME is looked up on (ADR 0093 § 3). */
186
+ scope?: Readonly<Record<string, unknown>>;
187
+ /** The size source a `breakpoints` node is driven from. */
188
+ observeSize?: SizeSource;
189
+ }
190
+
191
+ /**
192
+ * A tree with sibling roots (ADR 0093): the root element, and each sibling by id, all DETACHED
193
+ * like {@link buildSharedTree}'s result.
194
+ *
195
+ * {@link buildSharedTree}, {@link mountSharedTree} and {@link buildTemplateTree} refuse such a
196
+ * tree by name, because they return one element and the siblings would be built and then thrown
197
+ * away. A sibling with no id is refused too: nothing could ever ask for it, which is how a
198
+ * dropped object looks finished.
199
+ */
200
+ export function buildWithSiblings(node: SharedTreeNode, options: BuildOptions = {}): BuiltTree {
201
+ const record = newRecord(options.scope, options.observeSize);
202
+ const built = buildTree(node, record);
203
+ // An element declares its slots when it is connected, so a detached tree cannot be checked
204
+ // as it stands. It is connected for the length of the check and handed back detached, as
205
+ // documented: a placement the renderer could not honour is refused here, like
206
+ // `mountSharedTree` refuses it, instead of surfacing as a widget missing from the page.
207
+ const probe = document.createElement('div');
208
+ probe.hidden = true;
209
+ probe.append(built.root, ...built.siblings.values());
210
+ document.body.append(probe);
211
+ try {
212
+ refuseUnknownSlots(record.placed);
213
+ refuseUnheldExtensions(record.extended);
214
+ } catch (error) {
215
+ for (const dispose of record.disposers) dispose();
216
+ throw error;
217
+ } finally {
218
+ probe.remove();
219
+ for (const el of [built.root, ...built.siblings.values()]) el.remove();
220
+ }
221
+ return built;
222
+ }
223
+
224
+ function refuseSiblings(node: SharedTreeNode, door: string): void {
225
+ if ((node.siblings?.length ?? 0) === 0) return;
226
+ throw new Error(
227
+ `\`${node.tag}\` carries ${node.siblings!.length} sibling object(s), and \`${door}\` returns one object ` +
228
+ 'so they would be built and lost. Use `buildWithSiblings`, which hands them back by id.',
229
+ );
230
+ }
231
+
232
+ /** Every node, its siblings in the same id scope, then the binds and breakpoints that name them. */
233
+ function buildTree(node: SharedTreeNode, record: BuildRecord): BuiltTree {
157
234
  // ADR 0093 § 2: the whole tree is checked against the capability table before an element is
158
235
  // created. A refused `layout` is named with its node and the reason the table gives.
159
- assertTreeConstructs('adwaita-web', capabilities, node);
236
+ assertTreeConstructs('adwaita-web', capabilities, node, Object.keys(ARIA_OF));
160
237
  if (node.menus !== undefined) record.menus = node.menus;
161
238
  const root = buildNode(node, record);
239
+ const siblings = new Map<string, HTMLElement>();
240
+ for (const sibling of node.siblings ?? []) {
241
+ if (sibling.id === undefined) {
242
+ throw new Error(
243
+ `the sibling \`${sibling.tag}\` has no id, so nothing could ever ask for it: give it one in the .blp.`,
244
+ );
245
+ }
246
+ siblings.set(sibling.id, buildNode(sibling, record));
247
+ }
162
248
  for (const bind of record.binds) bindProperty(bind, record);
163
249
  for (const host of record.breakpointHosts) bindBreakpoints(host.el, host.node, record);
164
- return root;
250
+ return { root, siblings, objects: new Map(record.ids) };
165
251
  }
166
252
 
167
253
  /** A fresh record, with the scope when the caller has one. */
@@ -344,7 +430,9 @@ export function writeProp(el: HTMLElement, prop: string, value: string | number
344
430
  const member = propertyOf(prop);
345
431
  const expand = GTK_WIDGET_EXPAND.find((name) => name === attr);
346
432
  if (expand !== undefined && typeof value === 'boolean') el.setAttribute(expand, value ? '' : 'false');
347
- else if (isTemplateTag(el.localName) && member in el) {
433
+ else if (attr === 'visible' && typeof value === 'boolean' && hasInstalledVisible(el)) {
434
+ (el as unknown as Record<string, unknown>)[member] = value;
435
+ } else if (isTemplateTag(el.localName) && member in el) {
348
436
  // An application class has no attributeChangedCallback: its properties are GObject properties,
349
437
  // set the way `Gtk.Builder` sets them, after the constructor.
350
438
  (el as unknown as Record<string, unknown>)[member] = value;
@@ -372,9 +460,14 @@ function buildNode(node: SharedTreeNode, record: BuildRecord): HTMLElement {
372
460
  const el = document.createElement(node.extern === true ? templateTagFor(node.tag) : hostTagOf(node.tag));
373
461
  // A template's children talk GObject to the template: `connect`, `emit`, `notify` (ADR 0096).
374
462
  if (record.template !== undefined) installElementApi(el);
463
+ // `Gtk.Widget:visible`, which no element spells: a setter's target and an authored `false` need it.
464
+ installVisible(el);
375
465
  // The id is how the TypeScript beside a `.blp` reaches this element
376
466
  // (`root.querySelector('#…')`), the counterpart of `InternalChildren` on GTK.
377
467
  if (node.id !== undefined) {
468
+ if (record.ids.has(node.id)) {
469
+ throw new Error(`Two nodes of this tree carry the id '${node.id}'; GtkBuilder refuses a duplicate id.`);
470
+ }
378
471
  el.id = node.id;
379
472
  record.ids.set(node.id, el);
380
473
  }
@@ -419,6 +512,29 @@ function writeLook(el: HTMLElement, node: SharedTreeNode, menus?: SharedTreeNode
419
512
  // `.blp`'s `styles ["title-1"]` reached the tree and never the page.
420
513
  if (node.styleClasses !== undefined && node.styleClasses.length > 0) el.classList.add(...node.styleClasses);
421
514
  writeExtensions(el, node);
515
+ writeAccessibility(el, node);
516
+ }
517
+
518
+ /**
519
+ * The `accessibility { }` names this renderer has a door for, and the ARIA attribute each is.
520
+ * The rest (states, relations, `row-index`, …) are refused by name before the build, in
521
+ * {@link assertTreeConstructs}: no element here reads them, so they would be dropped.
522
+ */
523
+ const ARIA_OF: Readonly<Record<string, string>> = {
524
+ label: 'aria-label',
525
+ description: 'aria-description',
526
+ };
527
+
528
+ /**
529
+ * `accessibility { label; description; }` as the host's `aria-label` / `aria-description`.
530
+ * Written after the props, so an element that derives a name from its tooltip sees the
531
+ * authored one first; an element whose role lives on an inner control forwards both
532
+ * (`accessible.ts`). A translatable value is written as its source text, as a prop's is.
533
+ */
534
+ function writeAccessibility(el: HTMLElement, node: SharedTreeNode): void {
535
+ for (const [name, entry] of Object.entries(node.accessibility ?? {})) {
536
+ el.setAttribute(ARIA_OF[name], String(entry.value));
537
+ }
422
538
  }
423
539
 
424
540
  /** The `GtkGridLayoutChild` properties `layout { }` may carry, and the CSS Grid line each one is. */
@@ -492,7 +608,8 @@ export interface BuiltTemplateTree {
492
608
  * belong to the first `connectedCallback`.
493
609
  */
494
610
  export function buildTemplateTree(tree: SharedTreeNode, scope: TemplateScope, host: HTMLElement): BuiltTemplateTree {
495
- assertTreeConstructs('adwaita-web', capabilities, tree);
611
+ refuseSiblings(tree, 'buildTemplateTree');
612
+ assertTreeConstructs('adwaita-web', capabilities, tree, Object.keys(ARIA_OF));
496
613
  const record = newRecord(undefined, undefined, scope);
497
614
  record.menus = tree.menus;
498
615
  if (tree.id !== undefined) record.ids.set(tree.id, host);
@@ -591,9 +708,9 @@ function writeExtensions(el: HTMLElement, node: SharedTreeNode): void {
591
708
 
592
709
  /** The response API an element answers to — `<adw-alert-dialog>`'s, named after libadwaita's. */
593
710
  interface ResponseReader {
594
- getResponseLabel(id: string): string | null;
595
- getResponseAppearance(id: string): string | null;
596
- getResponseEnabled(id: string): boolean;
711
+ get_response_label(id: string): string | null;
712
+ get_response_appearance(id: string): string | null;
713
+ get_response_enabled(id: string): boolean;
597
714
  }
598
715
 
599
716
  /**
@@ -617,10 +734,10 @@ function refuseUnheldExtensions(extended: readonly ExtendedNode[]): void {
617
734
  const reader = el as unknown as Partial<ResponseReader>;
618
735
  for (const response of node.extensions?.responses ?? []) {
619
736
  const held =
620
- typeof reader.getResponseLabel === 'function' &&
621
- reader.getResponseLabel(response.id) === response.label &&
622
- reader.getResponseAppearance?.(response.id) === (response.appearance ?? 'default') &&
623
- reader.getResponseEnabled?.(response.id) === (response.enabled ?? true);
737
+ typeof reader.get_response_label === 'function' &&
738
+ reader.get_response_label(response.id) === response.label &&
739
+ reader.get_response_appearance?.(response.id) === (response.appearance ?? 'default') &&
740
+ reader.get_response_enabled?.(response.id) === (response.enabled ?? true);
624
741
  if (!held) {
625
742
  throw new Error(
626
743
  `<${el.localName}> did not register the response "${response.id}" as authored, so the ` +
@@ -696,6 +813,7 @@ export interface MountOptions {
696
813
  * `buildSharedTree` is for a caller that already has somewhere of its own to attach it.
697
814
  */
698
815
  export function mountSharedTree(node: SharedTreeNode, options: MountOptions = {}): MountedSharedTree {
816
+ refuseSiblings(node, 'mountSharedTree');
699
817
  const { into } = options;
700
818
  const host = into ?? document.createElement('div');
701
819
  const record = newRecord(options.scope, options.observeSize);
@@ -54,7 +54,7 @@ import { ADWAITA_GALLERY_SHARED_TREES } from '../../../../scripts/adwaita-galler
54
54
 
55
55
  import '@gjsify/adwaita-web';
56
56
 
57
- import { mountSharedTree } from './shared-tree-builder.js';
57
+ import { buildWithSiblings, mountSharedTree } from './shared-tree-builder.js';
58
58
 
59
59
  /**
60
60
  * Connect the authored root — these elements build on connect — run, and take it down again.
@@ -364,6 +364,20 @@ export const AdwSharedTreesTest = async () => {
364
364
  ).toThrow('has no slot "middle"');
365
365
  });
366
366
 
367
+ // The detached door refuses it too: a root built and handed back is mounted by the
368
+ // caller, after the builder could still say anything.
369
+ await it('`buildWithSiblings` refuses the same placement, and hands a good tree back detached', () => {
370
+ const bad = { tag: 'AdwToolbarView', children: [{ tag: 'AdwBanner', slot: 'middle' }] };
371
+ expect(() => buildWithSiblings(bad)).toThrow('has no slot "middle"');
372
+ const { root, siblings } = buildWithSiblings({
373
+ tag: 'AdwToolbarView',
374
+ children: [{ tag: 'AdwBanner', slot: 'top' }],
375
+ siblings: [{ tag: 'GtkLabel', id: 'beside' }],
376
+ });
377
+ expect(root.isConnected || siblings.get('beside')!.isConnected).toBe(false);
378
+ expect(root.querySelector('adw-banner') !== null).toBe(true);
379
+ });
380
+
367
381
  // ADR 0092's `layout { }`: a grid child's cell. GTK counts from 0, CSS Grid from 1.
368
382
  await it('`layout { }` places a grid child in its cell, spans defaulting to one', () => {
369
383
  mounted(
package/src/signals.ts CHANGED
@@ -9,7 +9,16 @@
9
9
  /** GTK signal name → the DOM event type the element dispatches it as. */
10
10
  export type DispatchedSignals = Readonly<Record<string, string>>;
11
11
 
12
- /** The signals `el`'s class declares, or none. */
12
+ /**
13
+ * The signals `el`'s class and every class above it declare, or none. A class inherits its
14
+ * base's signals as a GObject class does (`map` / `unmap` are declared once, on
15
+ * `WidgetElement`); where two declare the same name, the more derived class wins.
16
+ */
13
17
  export function dispatchedSignalsOf(el: Element): DispatchedSignals {
14
- return (el.constructor as { signals?: DispatchedSignals }).signals ?? {};
18
+ const chain: DispatchedSignals[] = [];
19
+ for (let klass: unknown = el.constructor; typeof klass === 'function'; klass = Object.getPrototypeOf(klass)) {
20
+ const own = Object.getOwnPropertyDescriptor(klass, 'signals')?.value as DispatchedSignals | undefined;
21
+ if (own !== undefined) chain.unshift(own);
22
+ }
23
+ return Object.assign({}, ...chain) as DispatchedSignals;
15
24
  }
@@ -113,6 +113,30 @@ export const AdwSlottedChildrenTest = async () => {
113
113
  expect(report).toBe('[1]');
114
114
  });
115
115
 
116
+ // The DECLARED twin of the case above. `install()` replaces the host's children with
117
+ // its structure, and a child no slot took used to go with them — gone without a word.
118
+ await it('keeps a declared child no slot takes, and warns that it was not placed', () => {
119
+ const host = document.createElement('div');
120
+ const typo = probe('sied', 'a');
121
+ host.append(document.createTextNode('\n '), typo);
122
+ mounted(host);
123
+ const side = document.createElement('div');
124
+ side.className = 'side';
125
+
126
+ const warned: string[] = [];
127
+ const warn = console.warn;
128
+ console.warn = (...args: unknown[]) => void warned.push(args.join(' '));
129
+ try {
130
+ bindSlottedChildren(host, [{ name: 'side', into: side }]).install(side);
131
+ } finally {
132
+ console.warn = warn;
133
+ }
134
+
135
+ const report = `${placement(host, typo)} | ${warned.join()}`;
136
+ host.remove();
137
+ expect(report).toBe("[1] | 'sied' is not a valid child type of 'div'");
138
+ });
139
+
116
140
  await it('re-adopts a child that was appended, removed and appended again', async () => {
117
141
  const host = mounted(document.createElement('div'));
118
142
  const side = document.createElement('div');
@@ -113,6 +113,12 @@ export interface AdwSlottedChildren {
113
113
  /** Where a bound host's slots can be read back from — see {@link slottedChildrenOf}. */
114
114
  const BOUND = new WeakMap<Element, AdwSlottedChildren>();
115
115
 
116
+ /** An element or a text node with something in it — markup's indentation and comments are not. */
117
+ function isContent(node: Node): boolean {
118
+ if (node instanceof Element) return true;
119
+ return node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim() !== '';
120
+ }
121
+
116
122
  /**
117
123
  * The slot binding `host` installed, if it has one.
118
124
  *
@@ -184,9 +190,19 @@ export function bindSlottedChildren(
184
190
  slots,
185
191
  slotFor,
186
192
  install(...nodes: readonly Node[]) {
187
- for (const node of Array.from(host.childNodes)) route(node);
193
+ const unplaced: Node[] = [];
194
+ for (const node of Array.from(host.childNodes)) {
195
+ if (route(node) !== null || node.parentNode !== host || !isContent(node)) continue;
196
+ // `replaceChildren` below would delete it, and a child the author wrote that
197
+ // vanishes without a word is the silent drop this used to be. It stays beside
198
+ // the structure, as a late child with the same slot does, and says so the
199
+ // way GtkBuilder does (GTK_BUILDER_WARN_INVALID_CHILD_TYPE).
200
+ unplaced.push(node);
201
+ const type = node instanceof Element ? (node.getAttribute('slot') ?? '') : '';
202
+ console.warn(`'${type}' is not a valid child type of '${host.localName}'`);
203
+ }
188
204
  structure = new Set(nodes);
189
- host.replaceChildren(...nodes);
205
+ host.replaceChildren(...nodes, ...unplaced);
190
206
  // Armed AFTER `replaceChildren`, so its own records are never delivered: an
191
207
  // observer armed first would see the whole of `structure` as added nodes and
192
208
  // spend a microtask rejecting them.
@@ -36,13 +36,14 @@ import { adwaitaEditorTheme, adwaitaHighlightStyle, ensureSourceViewStyleInjecte
36
36
  import { formatHexAddress, formatLineNumber, stripSourceWhitespace } from '@gjsify/adwaita-core';
37
37
  import { createGtkImage } from '../elements/gtk-image.js';
38
38
  import { createCopyGlyph } from './copy-glyph.js';
39
+ import { WidgetElement } from '../widget-element.js';
39
40
 
40
41
  /** Parse a boolean attribute: present (any value but "false") ⇒ true. */
41
42
  function boolAttr(value: string | null): boolean {
42
43
  return value !== null && value !== 'false';
43
44
  }
44
45
 
45
- export class AdwSourceView extends HTMLElement {
46
+ export class AdwSourceView extends WidgetElement {
46
47
  private _view?: EditorView;
47
48
  private _editorHost!: HTMLDivElement;
48
49
  private _copyButton!: HTMLButtonElement;
@@ -20,7 +20,7 @@ import {
20
20
  import { ADW_MENU_SURFACE_WEB, flattenMenu, menuRefusals } from '@gjsify/adwaita-core';
21
21
  import type { SplitButtonProperty } from '@gjsify/adwaita-core';
22
22
  import type { AdwSplitButton } from './elements/adw-split-button.js';
23
- import { fallbackMask, maskOf } from './icon-registry.spec.js';
23
+ import { fallbackMask, maskOf } from './icon-masks.spec.js';
24
24
 
25
25
  /** The GObject properties the element re-emits as `notify::*` CustomEvents. */
26
26
  const NOTIFY_PROPERTIES: readonly SplitButtonProperty[] = [
@@ -6,6 +6,7 @@ import { STYLE_MANAGER_VECTORS, driveStyleManagerVectors, type AdwStyleLike } fr
6
6
  import { describe, expect, it } from '@gjsify/unit';
7
7
 
8
8
  import * as Adw from './namespace/adw.js';
9
+ import { webStyleSource } from './style-manager.js';
9
10
 
10
11
  export const StyleManagerTest = async () => {
11
12
  const root = document.documentElement;
@@ -26,6 +27,18 @@ export const StyleManagerTest = async () => {
26
27
  { describe, it, expect },
27
28
  );
28
29
  await describe('adwaita-web: Adw.StyleManager door', async () => {
30
+ await it('system_supports_color_schemes is true where prefers-color-scheme is known', () => {
31
+ expect(Adw.StyleManager.get_default().system_supports_color_schemes).toBe(true);
32
+ });
33
+ await it('a browser that matches neither scheme does not support them', () => {
34
+ const real = globalThis.matchMedia;
35
+ globalThis.matchMedia = ((query: string) => ({ matches: false, media: query })) as never;
36
+ try {
37
+ expect(webStyleSource.supportsColorSchemes?.()).toBe(false);
38
+ } finally {
39
+ globalThis.matchMedia = real;
40
+ }
41
+ });
29
42
  await it('has a vector row for every vector', () => {
30
43
  expect(STYLE_MANAGER_VECTORS.length > 0).toBe(true);
31
44
  });
@@ -2,6 +2,8 @@
2
2
  // on the root outranks `prefers-color-scheme` (ADR 0078, `isAdwaitaDark`). The behaviour is the
3
3
  // core's (`style-manager.ts`); this file is the SOURCE: the root's `class` attribute and the media
4
4
  // query are the two things that can flip it. Without a `document` (SSR) it is light and never changes.
5
+ // The system supports color schemes when the browser knows `prefers-color-scheme`: then one of its
6
+ // two values matches; a browser without the feature matches neither.
5
7
 
6
8
  import { ColorScheme, StyleManagerBase, type StyleSource } from '@gjsify/adwaita-core';
7
9
 
@@ -20,6 +22,10 @@ export const webStyleSource: StyleSource = {
20
22
  observer.disconnect();
21
23
  };
22
24
  },
25
+ supportsColorSchemes() {
26
+ const matches = (query: string) => globalThis.matchMedia?.(query).matches === true;
27
+ return matches('(prefers-color-scheme: dark)') || matches('(prefers-color-scheme: light)');
28
+ },
23
29
  };
24
30
 
25
31
  // FORCE_DARK / FORCE_LIGHT write the same root class an app writes by hand; DEFAULT takes it away.