@gjsify/adwaita-web 0.64.2-next.252 → 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 (293) hide show
  1. package/README.md +10 -80
  2. package/dist/adwaita-web.css +52 -3
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/accessible.d.ts +8 -0
  5. package/lib/types/compute-expand.d.ts +5 -0
  6. package/lib/types/compute-expand.spec.d.ts +1 -0
  7. package/lib/types/elements/adw-about-dialog.d.ts +28 -1
  8. package/lib/types/elements/adw-action-row.d.ts +2 -1
  9. package/lib/types/elements/adw-alert-dialog.d.ts +3 -2
  10. package/lib/types/elements/adw-avatar.d.ts +2 -1
  11. package/lib/types/elements/adw-banner.d.ts +2 -1
  12. package/lib/types/elements/adw-bin.d.ts +2 -1
  13. package/lib/types/elements/adw-bottom-sheet.d.ts +5 -4
  14. package/lib/types/elements/adw-breakpoint-bin.d.ts +2 -1
  15. package/lib/types/elements/adw-button-content.d.ts +2 -1
  16. package/lib/types/elements/adw-button-row.d.ts +2 -1
  17. package/lib/types/elements/adw-card.d.ts +2 -1
  18. package/lib/types/elements/adw-carousel.d.ts +20 -3
  19. package/lib/types/elements/adw-clamp-scrollable.d.ts +2 -1
  20. package/lib/types/elements/adw-clamp.d.ts +2 -1
  21. package/lib/types/elements/adw-combo-row.d.ts +6 -1
  22. package/lib/types/elements/adw-data-grid.d.ts +2 -1
  23. package/lib/types/elements/adw-dialog.d.ts +2 -1
  24. package/lib/types/elements/adw-entry-row.d.ts +2 -1
  25. package/lib/types/elements/adw-expander-row.d.ts +2 -1
  26. package/lib/types/elements/adw-header-bar.d.ts +2 -1
  27. package/lib/types/elements/adw-inline-view-switcher.d.ts +3 -2
  28. package/lib/types/elements/adw-layout-slot.d.ts +2 -1
  29. package/lib/types/elements/adw-multi-layout-view.d.ts +2 -1
  30. package/lib/types/elements/adw-navigation-split-view.d.ts +2 -1
  31. package/lib/types/elements/adw-navigation-view.d.ts +3 -2
  32. package/lib/types/elements/adw-overlay-split-view.d.ts +2 -1
  33. package/lib/types/elements/adw-preferences-dialog.d.ts +5 -4
  34. package/lib/types/elements/adw-preferences-group.d.ts +2 -1
  35. package/lib/types/elements/adw-preferences-row.d.ts +2 -1
  36. package/lib/types/elements/adw-shortcut-label.d.ts +2 -1
  37. package/lib/types/elements/adw-shortcuts-item.d.ts +2 -1
  38. package/lib/types/elements/adw-shortcuts-section.d.ts +2 -1
  39. package/lib/types/elements/adw-sidebar.d.ts +4 -3
  40. package/lib/types/elements/adw-spin-row.d.ts +2 -1
  41. package/lib/types/elements/adw-spinner.d.ts +2 -1
  42. package/lib/types/elements/adw-split-button.d.ts +2 -1
  43. package/lib/types/elements/adw-status-page.d.ts +2 -1
  44. package/lib/types/elements/adw-switch-row.d.ts +4 -1
  45. package/lib/types/elements/adw-tab-bar.d.ts +2 -1
  46. package/lib/types/elements/adw-tab-button.d.ts +2 -1
  47. package/lib/types/elements/adw-tab-overview.d.ts +2 -1
  48. package/lib/types/elements/adw-tab-view.d.ts +3 -2
  49. package/lib/types/elements/adw-toast-overlay.d.ts +2 -1
  50. package/lib/types/elements/adw-toggle-group.d.ts +3 -2
  51. package/lib/types/elements/adw-toolbar-view.d.ts +2 -1
  52. package/lib/types/elements/adw-view-stack.d.ts +3 -1
  53. package/lib/types/elements/adw-view-switcher-bar.d.ts +2 -1
  54. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +2 -1
  55. package/lib/types/elements/adw-view-switcher.d.ts +3 -2
  56. package/lib/types/elements/adw-window-title.d.ts +2 -1
  57. package/lib/types/elements/adw-wrap-box.d.ts +2 -1
  58. package/lib/types/elements/checks.d.ts +16 -1
  59. package/lib/types/elements/gtk-action-bar.d.ts +2 -1
  60. package/lib/types/elements/gtk-aspect-frame.d.ts +2 -1
  61. package/lib/types/elements/gtk-box.d.ts +5 -1
  62. package/lib/types/elements/gtk-button.d.ts +5 -7
  63. package/lib/types/elements/gtk-calendar.d.ts +2 -1
  64. package/lib/types/elements/gtk-center-box.d.ts +2 -1
  65. package/lib/types/elements/gtk-color-dialog-button.d.ts +2 -1
  66. package/lib/types/elements/gtk-drag-icon.d.ts +2 -1
  67. package/lib/types/elements/gtk-drawing-area.d.ts +2 -1
  68. package/lib/types/elements/gtk-drop-down.d.ts +2 -1
  69. package/lib/types/elements/gtk-editable-label.d.ts +2 -1
  70. package/lib/types/elements/gtk-entry.d.ts +2 -1
  71. package/lib/types/elements/gtk-expander.d.ts +2 -1
  72. package/lib/types/elements/gtk-fixed.d.ts +2 -1
  73. package/lib/types/elements/gtk-flow-box-child.d.ts +2 -1
  74. package/lib/types/elements/gtk-flow-box.d.ts +2 -1
  75. package/lib/types/elements/gtk-font-dialog-button.d.ts +2 -1
  76. package/lib/types/elements/gtk-frame.d.ts +2 -1
  77. package/lib/types/elements/gtk-gl-area.d.ts +2 -1
  78. package/lib/types/elements/gtk-graphics-offload.d.ts +2 -1
  79. package/lib/types/elements/gtk-grid.d.ts +2 -1
  80. package/lib/types/elements/gtk-header-bar.d.ts +2 -1
  81. package/lib/types/elements/gtk-image.d.ts +5 -6
  82. package/lib/types/elements/gtk-inscription.d.ts +2 -1
  83. package/lib/types/elements/gtk-label.d.ts +10 -3
  84. package/lib/types/elements/gtk-level-bar.d.ts +2 -1
  85. package/lib/types/elements/gtk-list-box-row.d.ts +2 -1
  86. package/lib/types/elements/gtk-list-box.d.ts +2 -1
  87. package/lib/types/elements/gtk-list-view.d.ts +2 -1
  88. package/lib/types/elements/gtk-media-controls.d.ts +2 -1
  89. package/lib/types/elements/gtk-menu-button.d.ts +2 -1
  90. package/lib/types/elements/gtk-notebook.d.ts +2 -1
  91. package/lib/types/elements/gtk-overlay.d.ts +2 -1
  92. package/lib/types/elements/gtk-paned.d.ts +2 -1
  93. package/lib/types/elements/gtk-picture.d.ts +2 -1
  94. package/lib/types/elements/gtk-popover-bin.d.ts +2 -1
  95. package/lib/types/elements/gtk-popover-menu-bar.d.ts +2 -1
  96. package/lib/types/elements/gtk-popover.d.ts +2 -1
  97. package/lib/types/elements/gtk-progress-bar.d.ts +2 -1
  98. package/lib/types/elements/gtk-revealer.d.ts +2 -1
  99. package/lib/types/elements/gtk-scale-button.d.ts +2 -1
  100. package/lib/types/elements/gtk-scale.d.ts +2 -1
  101. package/lib/types/elements/gtk-scrollbar.d.ts +2 -1
  102. package/lib/types/elements/gtk-scrolled-window.d.ts +2 -1
  103. package/lib/types/elements/gtk-search-bar.d.ts +2 -1
  104. package/lib/types/elements/gtk-separator.d.ts +2 -1
  105. package/lib/types/elements/gtk-spin-button.d.ts +2 -1
  106. package/lib/types/elements/gtk-spinner.d.ts +2 -1
  107. package/lib/types/elements/gtk-stack-page.d.ts +2 -1
  108. package/lib/types/elements/gtk-stack-sidebar.d.ts +2 -1
  109. package/lib/types/elements/gtk-stack-switcher.d.ts +2 -1
  110. package/lib/types/elements/gtk-stack.d.ts +2 -1
  111. package/lib/types/elements/gtk-switch.d.ts +2 -1
  112. package/lib/types/elements/gtk-text-view.d.ts +2 -1
  113. package/lib/types/elements/gtk-text.d.ts +2 -1
  114. package/lib/types/elements/gtk-tree-expander.d.ts +2 -1
  115. package/lib/types/elements/gtk-video.d.ts +2 -1
  116. package/lib/types/elements/gtk-viewport.d.ts +2 -1
  117. package/lib/types/elements/gtk-window-controls.d.ts +2 -1
  118. package/lib/types/elements/gtk-window-handle.d.ts +2 -1
  119. package/lib/types/elements/gtk-window.d.ts +2 -1
  120. package/lib/types/gobject-elements.d.ts +7 -1
  121. package/lib/types/gtksource/gtk-source-view.d.ts +2 -1
  122. package/lib/types/{icon-registry.spec.d.ts → icon-masks.spec.d.ts} +1 -1
  123. package/lib/types/icon-theme.d.ts +15 -35
  124. package/lib/types/index.d.ts +1 -2
  125. package/lib/types/namespace/gdk.d.ts +1 -0
  126. package/lib/types/namespace/gio.d.ts +1 -0
  127. package/lib/types/namespace/glib.d.ts +2 -1
  128. package/lib/types/signals.d.ts +5 -1
  129. package/lib/types/source-view/adw-source-view.d.ts +2 -1
  130. package/lib/types/styles.generated.d.ts +1 -1
  131. package/lib/types/widget-element.d.ts +25 -0
  132. package/lib/types/widget-map.spec.d.ts +1 -0
  133. package/lib/types/widget-mapping.d.ts +7 -0
  134. package/package.json +12 -12
  135. package/scss/_about_dialog.scss +46 -1
  136. package/scss/_checks.scss +5 -2
  137. package/scss/_icon.scss +3 -4
  138. package/scss/_labels.scss +2 -2
  139. package/scss/_overlay_split_view.scss +10 -0
  140. package/scss/_scrolled_window.scss +15 -0
  141. package/scss/_widget.scss +5 -1
  142. package/src/accessible.ts +29 -0
  143. package/src/adw-about-dialog.spec.ts +81 -12
  144. package/src/adw-action-rows.spec.ts +2 -2
  145. package/src/adw-button-content.spec.ts +1 -1
  146. package/src/adw-carousel.spec.ts +49 -1
  147. package/src/capabilities.mjs +1 -0
  148. package/src/checks.spec.ts +51 -1
  149. package/src/compute-expand.spec.ts +186 -0
  150. package/src/compute-expand.ts +134 -0
  151. package/src/construct-vectors.spec.ts +46 -1
  152. package/src/elements/adw-about-dialog.ts +152 -9
  153. package/src/elements/adw-action-row.ts +2 -1
  154. package/src/elements/adw-alert-dialog.ts +3 -2
  155. package/src/elements/adw-avatar.ts +2 -1
  156. package/src/elements/adw-banner.ts +2 -1
  157. package/src/elements/adw-bin.ts +2 -1
  158. package/src/elements/adw-bottom-sheet.ts +5 -4
  159. package/src/elements/adw-breakpoint-bin.ts +2 -1
  160. package/src/elements/adw-button-content.ts +2 -1
  161. package/src/elements/adw-button-row.ts +2 -1
  162. package/src/elements/adw-card.ts +2 -1
  163. package/src/elements/adw-carousel.ts +62 -3
  164. package/src/elements/adw-clamp-scrollable.ts +2 -1
  165. package/src/elements/adw-clamp.ts +2 -1
  166. package/src/elements/adw-combo-row.ts +15 -1
  167. package/src/elements/adw-data-grid.ts +2 -1
  168. package/src/elements/adw-dialog.ts +2 -1
  169. package/src/elements/adw-entry-row.ts +2 -1
  170. package/src/elements/adw-expander-row.ts +2 -1
  171. package/src/elements/adw-header-bar.ts +2 -1
  172. package/src/elements/adw-inline-view-switcher.ts +3 -2
  173. package/src/elements/adw-layout-slot.ts +2 -1
  174. package/src/elements/adw-multi-layout-view.ts +2 -1
  175. package/src/elements/adw-navigation-split-view.ts +2 -1
  176. package/src/elements/adw-navigation-view.ts +3 -2
  177. package/src/elements/adw-overlay-split-view.ts +2 -1
  178. package/src/elements/adw-preferences-dialog.ts +6 -4
  179. package/src/elements/adw-preferences-group.ts +2 -1
  180. package/src/elements/adw-preferences-row.ts +2 -1
  181. package/src/elements/adw-shortcut-label.ts +2 -1
  182. package/src/elements/adw-shortcuts-item.ts +2 -1
  183. package/src/elements/adw-shortcuts-section.ts +2 -1
  184. package/src/elements/adw-sidebar.ts +4 -3
  185. package/src/elements/adw-spin-row.ts +2 -1
  186. package/src/elements/adw-spinner.ts +2 -1
  187. package/src/elements/adw-split-button.ts +2 -1
  188. package/src/elements/adw-status-page.ts +2 -1
  189. package/src/elements/adw-switch-row.ts +10 -1
  190. package/src/elements/adw-tab-bar.ts +2 -1
  191. package/src/elements/adw-tab-button.ts +2 -1
  192. package/src/elements/adw-tab-overview.ts +2 -1
  193. package/src/elements/adw-tab-view.ts +3 -2
  194. package/src/elements/adw-toast-overlay.ts +2 -1
  195. package/src/elements/adw-toggle-group.ts +3 -2
  196. package/src/elements/adw-toolbar-view.ts +2 -1
  197. package/src/elements/adw-view-stack.ts +39 -1
  198. package/src/elements/adw-view-switcher-bar.ts +2 -1
  199. package/src/elements/adw-view-switcher-sidebar.ts +2 -1
  200. package/src/elements/adw-view-switcher.ts +3 -2
  201. package/src/elements/adw-window-title.ts +2 -1
  202. package/src/elements/adw-wrap-box.ts +2 -1
  203. package/src/elements/checks.ts +85 -6
  204. package/src/elements/gtk-action-bar.ts +2 -1
  205. package/src/elements/gtk-aspect-frame.ts +2 -1
  206. package/src/elements/gtk-box.ts +56 -1
  207. package/src/elements/gtk-button.ts +10 -22
  208. package/src/elements/gtk-calendar.ts +2 -1
  209. package/src/elements/gtk-center-box.ts +2 -1
  210. package/src/elements/gtk-color-dialog-button.ts +2 -1
  211. package/src/elements/gtk-drag-icon.ts +2 -1
  212. package/src/elements/gtk-drawing-area.ts +2 -1
  213. package/src/elements/gtk-drop-down.ts +2 -1
  214. package/src/elements/gtk-editable-label.ts +2 -1
  215. package/src/elements/gtk-entry.ts +2 -1
  216. package/src/elements/gtk-expander.ts +2 -1
  217. package/src/elements/gtk-fixed.ts +2 -1
  218. package/src/elements/gtk-flow-box-child.ts +2 -1
  219. package/src/elements/gtk-flow-box.ts +2 -1
  220. package/src/elements/gtk-font-dialog-button.ts +2 -1
  221. package/src/elements/gtk-frame.ts +2 -1
  222. package/src/elements/gtk-gl-area.ts +2 -1
  223. package/src/elements/gtk-graphics-offload.ts +2 -1
  224. package/src/elements/gtk-grid.ts +2 -1
  225. package/src/elements/gtk-header-bar.ts +2 -1
  226. package/src/elements/gtk-image.ts +14 -15
  227. package/src/elements/gtk-inscription.ts +2 -1
  228. package/src/elements/gtk-label.ts +12 -5
  229. package/src/elements/gtk-level-bar.ts +2 -1
  230. package/src/elements/gtk-list-box-row.ts +2 -1
  231. package/src/elements/gtk-list-box.ts +2 -1
  232. package/src/elements/gtk-list-view.ts +2 -1
  233. package/src/elements/gtk-media-controls.ts +2 -1
  234. package/src/elements/gtk-menu-button.ts +2 -1
  235. package/src/elements/gtk-notebook.ts +2 -1
  236. package/src/elements/gtk-overlay.ts +2 -1
  237. package/src/elements/gtk-paned.ts +2 -1
  238. package/src/elements/gtk-picture.ts +2 -1
  239. package/src/elements/gtk-popover-bin.ts +2 -1
  240. package/src/elements/gtk-popover-menu-bar.ts +2 -1
  241. package/src/elements/gtk-popover.ts +2 -1
  242. package/src/elements/gtk-progress-bar.ts +2 -1
  243. package/src/elements/gtk-revealer.ts +2 -1
  244. package/src/elements/gtk-scale-button.ts +2 -1
  245. package/src/elements/gtk-scale.ts +2 -1
  246. package/src/elements/gtk-scrollbar.ts +2 -1
  247. package/src/elements/gtk-scrolled-window.ts +8 -5
  248. package/src/elements/gtk-search-bar.ts +2 -1
  249. package/src/elements/gtk-separator.ts +2 -1
  250. package/src/elements/gtk-spin-button.ts +2 -1
  251. package/src/elements/gtk-spinner.ts +2 -1
  252. package/src/elements/gtk-stack-page.ts +2 -1
  253. package/src/elements/gtk-stack-sidebar.ts +2 -1
  254. package/src/elements/gtk-stack-switcher.ts +2 -1
  255. package/src/elements/gtk-stack.ts +2 -1
  256. package/src/elements/gtk-switch.ts +2 -1
  257. package/src/elements/gtk-text-view.ts +2 -1
  258. package/src/elements/gtk-text.ts +2 -1
  259. package/src/elements/gtk-tree-expander.ts +2 -1
  260. package/src/elements/gtk-video.ts +2 -1
  261. package/src/elements/gtk-viewport.ts +2 -1
  262. package/src/elements/gtk-window-controls.ts +2 -1
  263. package/src/elements/gtk-window-handle.ts +2 -1
  264. package/src/elements/gtk-window.ts +2 -1
  265. package/src/gio.spec.ts +13 -3
  266. package/src/glib.spec.ts +9 -0
  267. package/src/gobject-elements.ts +18 -4
  268. package/src/gtk-label.spec.ts +39 -0
  269. package/src/gtk-scrolled-window.spec.ts +6 -6
  270. package/src/gtk-value-doors.spec.ts +19 -0
  271. package/src/gtk-window.spec.ts +2 -2
  272. package/src/gtksource/gtk-source-view.ts +2 -1
  273. package/src/{icon-registry.spec.ts → icon-masks.spec.ts} +4 -100
  274. package/src/icon-theme.spec.ts +69 -124
  275. package/src/icon-theme.ts +29 -119
  276. package/src/index.ts +3 -7
  277. package/src/namespace/gdk.ts +1 -0
  278. package/src/namespace/gio.ts +8 -0
  279. package/src/namespace/glib.ts +4 -0
  280. package/src/shared-tree-builder.ts +26 -3
  281. package/src/signals.ts +11 -2
  282. package/src/source-view/adw-source-view.ts +2 -1
  283. package/src/split-button.spec.ts +1 -1
  284. package/src/style-manager.spec.ts +13 -0
  285. package/src/style-manager.ts +6 -0
  286. package/src/styles.generated.ts +1 -1
  287. package/src/test.browser.mts +6 -2
  288. package/src/widget-element.ts +75 -0
  289. package/src/widget-map.spec.ts +116 -0
  290. package/src/widget-mapping.ts +100 -0
  291. package/src/widget-visible.spec.ts +44 -0
  292. package/lib/types/icon-registry.d.ts +0 -37
  293. package/src/icon-registry.ts +0 -163
@@ -93,6 +93,7 @@
93
93
 
94
94
  import type { DispatchedSignals } from '../signals.js';
95
95
  import { STACK_PAGE_ATTRIBUTES, pageChildOf } from './gtk-stack-page.js';
96
+ import { WidgetElement } from '../widget-element.js';
96
97
 
97
98
  /** `GtkStackTransitionType`, spelled as the GIR's enum nicks (gtkstack.c:95-121). */
98
99
  export type StackTransitionType =
@@ -226,7 +227,7 @@ export interface GtkStackPageInfo {
226
227
  /** The five `GtkStackPage` string/boolean properties this element reads off a child. */
227
228
  const PAGE_ATTRIBUTES = ['name', 'title', 'icon-name', 'use-underline', 'needs-attention'];
228
229
 
229
- export class GtkStack extends HTMLElement {
230
+ export class GtkStack extends WidgetElement {
230
231
  /** The GTK signals this element dispatches, each with the DOM event it arrives as (ADR 0093). */
231
232
  static readonly signals: DispatchedSignals = {
232
233
  'notify::visible-child': 'notify::visible-child',
@@ -40,8 +40,9 @@
40
40
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
41
41
 
42
42
  import type { DispatchedSignals } from '../signals.js';
43
+ import { WidgetElement } from '../widget-element.js';
43
44
 
44
- export class GtkSwitch extends HTMLElement {
45
+ export class GtkSwitch extends WidgetElement {
45
46
  /** The GTK signals this element dispatches, each with the DOM event it arrives as (ADR 0093). */
46
47
  static readonly signals: DispatchedSignals = {
47
48
  'notify::active': 'notify::active',
@@ -50,6 +50,7 @@
50
50
  import { normalizeLabelJustify, type LabelJustification } from '@gjsify/adwaita-core';
51
51
 
52
52
  import { JUSTIFY_TEXT_ALIGN } from './justification.js';
53
+ import { WidgetElement } from '../widget-element.js';
53
54
 
54
55
  /** `Gtk.WrapMode`'s four nicks, in enum order — Pango's enum, and the DEFAULT is `none`. */
55
56
  const WRAP_MODES = ['none', 'char', 'word', 'word-char'] as const;
@@ -83,7 +84,7 @@ export interface GtkTextBufferSubset {
83
84
  get_text(): string;
84
85
  }
85
86
 
86
- export class GtkTextView extends HTMLElement {
87
+ export class GtkTextView extends WidgetElement {
87
88
  private _area!: HTMLTextAreaElement;
88
89
  private _initialized = false;
89
90
 
@@ -43,8 +43,9 @@
43
43
  // arithmetic composed from @gjsify/adwaita-core.
44
44
 
45
45
  import { ENTRY_ROW_MAX_LENGTH_LIMIT, clampEntryText, entryTextLength } from '@gjsify/adwaita-core';
46
+ import { WidgetElement } from '../widget-element.js';
46
47
 
47
- export class GtkText extends HTMLElement {
48
+ export class GtkText extends WidgetElement {
48
49
  private _input!: HTMLInputElement;
49
50
  private _initialized = false;
50
51
  private _maxLength = 0;
@@ -60,11 +60,12 @@ import {
60
60
 
61
61
  import { createGtkImage } from './gtk-image.js';
62
62
  import { bindSlottedChildren } from '../slotted-children.js';
63
+ import { WidgetElement } from '../widget-element.js';
63
64
 
64
65
  /** `TIMEOUT_EXPAND` — how long a drag hovers before the row opens (gtktreeexpander.c:717). */
65
66
  const TIMEOUT_EXPAND = 500;
66
67
 
67
- export class GtkTreeExpander extends HTMLElement {
68
+ export class GtkTreeExpander extends WidgetElement {
68
69
  private _ornaments: HTMLElement[] = [];
69
70
  private _expandTimer: ReturnType<typeof setTimeout> | null = null;
70
71
  private _initialized = false;
@@ -65,6 +65,7 @@
65
65
  // Reference: refs/libadwaita/src/stylesheet/widgets/_misc.scss:74-81 (the 64/32 osd icon)
66
66
  // Copyright (c) The GTK Team. LGPLv2.1+.
67
67
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
68
+ import { WidgetElement } from '../widget-element.js';
68
69
 
69
70
  /** The four overlay glyphs, in the order `update_overlay_icon` tests them (gtkvideo.c:626-646). */
70
71
  export type VideoOverlayIcon =
@@ -99,7 +100,7 @@ export const READY_ICON = 'media-playback-start-symbolic';
99
100
  /** `gtk_video_reveal_controls`' timeout: 3 s (gtkvideo.c:130). */
100
101
  export const CONTROLS_HIDE_MS = 3000;
101
102
 
102
- export class GtkVideo extends HTMLElement {
103
+ export class GtkVideo extends WidgetElement {
103
104
  private _initialized = false;
104
105
  private _overlayIcon!: HTMLButtonElement;
105
106
  private _controlsRevealer!: HTMLDivElement;
@@ -66,6 +66,7 @@
66
66
  import { clampAdjustmentValue, normalizeAdjustment, type AdwAdjustment } from '@gjsify/adwaita-core';
67
67
 
68
68
  import { bindSlottedChildren } from '../slotted-children.js';
69
+ import { WidgetElement } from '../widget-element.js';
69
70
 
70
71
  /** `viewport_set_adjustment_values`'s two fractions of the visible size. */
71
72
  const STEP_FRACTION = 0.1;
@@ -94,7 +95,7 @@ function axisAdjustment(clip: HTMLElement, axis: Axis): AdwAdjustment {
94
95
  });
95
96
  }
96
97
 
97
- export class GtkViewport extends HTMLElement {
98
+ export class GtkViewport extends WidgetElement {
98
99
  private _observer: ResizeObserver | null = null;
99
100
  private _watch: MutationObserver | null = null;
100
101
 
@@ -66,6 +66,7 @@
66
66
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
67
67
 
68
68
  import { createGtkImage } from './gtk-image.js';
69
+ import { WidgetElement } from '../widget-element.js';
69
70
 
70
71
  /** `Gtk.PackType`, spelled as the GIR's enum nicks (gtkwindowcontrols.c:68). */
71
72
  type PackSide = 'start' | 'end';
@@ -120,7 +121,7 @@ const WINDOW_ATTRIBUTES = [
120
121
  /** `closest` over both window spellings — `Adw.Window` is a `GtkWindow` subclass. */
121
122
  const WINDOW_SELECTOR = 'gtk-window, adw-window';
122
123
 
123
- export class GtkWindowControls extends HTMLElement {
124
+ export class GtkWindowControls extends WidgetElement {
124
125
  private _initialized = false;
125
126
  private _empty = true;
126
127
  /** The frame this controls answers to, or `null` outside one (`:257-263`). */
@@ -47,6 +47,7 @@
47
47
  // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
48
48
 
49
49
  import { bindSlottedChildren } from '../slotted-children.js';
50
+ import { WidgetElement } from '../widget-element.js';
50
51
 
51
52
  /** `GtkTitlebarGesture`'s three gestures, as `perform_titlebar_action` decides them. */
52
53
  export type GtkTitlebarGesture = 'double-click' | 'middle-click' | 'right-click';
@@ -114,7 +115,7 @@ function gestureOf(button: number, presses: number): GtkTitlebarGesture | null {
114
115
  */
115
116
  const DRAG_THRESHOLD = 1;
116
117
 
117
- export class GtkWindowHandle extends HTMLElement {
118
+ export class GtkWindowHandle extends WidgetElement {
118
119
  /** The gesture in progress, as `priv->drag_start_x` / `_y` are in the C. */
119
120
  private _drag: { pointerId: number; x: number; y: number } | null = null;
120
121
 
@@ -108,8 +108,9 @@ import { bindSlottedChildren, type AdwSlot } from '../slotted-children.js';
108
108
  import './gtk-window-controls.js';
109
109
  import { fillsContainingBlock } from './adw-window-features.js';
110
110
  import type { WindowAction } from './gtk-window-controls.js';
111
+ import { WidgetElement } from '../widget-element.js';
111
112
 
112
- export class GtkWindow extends HTMLElement {
113
+ export class GtkWindow extends WidgetElement {
113
114
  private _initialized = false;
114
115
  /** The `titlebar` strip — `protected` so a subclass can place its own strips around it. */
115
116
  protected _titlebar!: HTMLDivElement;
package/src/gio.spec.ts CHANGED
@@ -1,23 +1,33 @@
1
- // The `Gio.SimpleActionGroup` door of adwaita-web, held to the shared vectors (real GJS is their
2
- // oracle, in adwaita-core's `simple-action-group.gjs.spec.ts`). The door is the namespace module itself.
1
+ // The `Gio.SimpleActionGroup` and `Gio.AppInfo` door of adwaita-web, held to the shared vectors (real GJS
2
+ // is their oracle, in adwaita-core's `simple-action-group.gjs.spec.ts` / `gio-app-info.gjs.spec.ts`). The door is the namespace module itself.
3
3
 
4
4
  import {
5
+ GIO_APP_INFO_VECTORS,
5
6
  SIMPLE_ACTION_GROUP_VECTORS,
7
+ driveGioAppInfoVectors,
6
8
  driveSimpleActionGroupVectors,
7
9
  type GioActionsLike,
10
+ type GioAppInfoSubject,
8
11
  } from '@gjsify/adwaita-core/conformance';
9
12
  import { describe, expect, it } from '@gjsify/unit';
10
13
 
14
+ import * as Gdk from './namespace/gdk.js';
11
15
  import * as Gio from './namespace/gio.js';
16
+ import * as GLib from './namespace/glib.js';
12
17
 
13
18
  export const GioActionsTest = async () => {
14
19
  await driveSimpleActionGroupVectors(
15
20
  { name: 'adwaita-web', isOracle: false, Gio: Gio as unknown as GioActionsLike },
16
21
  { describe, it, expect },
17
22
  );
23
+ await driveGioAppInfoVectors(
24
+ { name: 'adwaita-web', isOracle: false, display: true, Gio, GLib, Gdk } as unknown as GioAppInfoSubject,
25
+ { describe, it, expect },
26
+ GIO_APP_INFO_VECTORS,
27
+ );
18
28
  await describe('adwaita-web: Gio door', async () => {
19
29
  await it('has a vector row for every vector', () => {
20
- expect(SIMPLE_ACTION_GROUP_VECTORS.length > 0).toBe(true);
30
+ expect(SIMPLE_ACTION_GROUP_VECTORS.length > 0 && GIO_APP_INFO_VECTORS.length > 0).toBe(true);
21
31
  });
22
32
  });
23
33
  };
package/src/glib.spec.ts CHANGED
@@ -5,10 +5,13 @@
5
5
  import {
6
6
  GLIB_PATH_VECTORS,
7
7
  GLIB_TIMER_VECTORS,
8
+ GLIB_URI_VECTORS,
8
9
  driveGLibPathVectors,
9
10
  driveGLibTimerVectors,
11
+ driveGLibUriVectors,
10
12
  type GLibPathsLike,
11
13
  type GLibTimersLike,
14
+ type GLibUriLike,
12
15
  } from '@gjsify/adwaita-core/conformance';
13
16
  import { describe, expect, it } from '@gjsify/unit';
14
17
 
@@ -36,6 +39,12 @@ export const GLibTest = async () => {
36
39
  await driveGLibPathVectors(
37
40
  { name: 'adwaita-web', isOracle: false, GLib: GLib as unknown as GLibPathsLike },
38
41
  { describe, it, expect },
42
+ GLIB_PATH_VECTORS,
43
+ );
44
+ await driveGLibUriVectors(
45
+ { name: 'adwaita-web', isOracle: false, GLib: GLib as unknown as GLibUriLike },
46
+ { describe, it, expect },
47
+ GLIB_URI_VECTORS,
39
48
  );
40
49
  await describe('adwaita-web: GLib door', async () => {
41
50
  await it('answers the host-bound path questions with the root and no data dirs', () => {
@@ -17,6 +17,7 @@
17
17
  import { attributeOf, propertyOf } from '@gjsify/adwaita-core/tags';
18
18
 
19
19
  import { dispatchedSignalsOf } from './signals.js';
20
+ import { watchMapping } from './widget-mapping.js';
20
21
 
21
22
  type Handler = (emitter: HTMLElement, ...args: unknown[]) => unknown;
22
23
 
@@ -60,7 +61,7 @@ function inheritedDescriptor(el: object, member: string): PropertyDescriptor | u
60
61
  return undefined;
61
62
  }
62
63
 
63
- function notifyElement(el: HTMLElement, name: string): void {
64
+ export function notifyElement(el: HTMLElement, name: string): void {
64
65
  const member = propertyOf(name);
65
66
  el.dispatchEvent(
66
67
  new CustomEvent(eventOf(el, `notify::${name}`), {
@@ -122,7 +123,12 @@ export function listenElement(el: HTMLElement, signal: string, handler: Handler)
122
123
  }
123
124
  };
124
125
  el.addEventListener(event, listener);
125
- return () => el.removeEventListener(event, listener);
126
+ // `map` / `unmap` have no DOM event behind them: the element is watched while one is connected.
127
+ const unwatch = signal === 'map' || signal === 'unmap' ? watchMapping(el) : undefined;
128
+ return () => {
129
+ el.removeEventListener(event, listener);
130
+ unwatch?.();
131
+ };
126
132
  }
127
133
 
128
134
  export function dispatchElement(el: HTMLElement, signal: string, args: readonly unknown[]): void {
@@ -156,9 +162,17 @@ export function installSensitive(el: HTMLElement): void {
156
162
 
157
163
  const VISIBLE_INSTALLED = new WeakSet<Element>();
158
164
 
159
- /** Whether `installVisible` gave `el` its `visible` (an element with its own keeps its own). */
165
+ /** The `visible` getters `WidgetElement` puts on its prototype, so a class's own accessor tells apart. */
166
+ export const WIDGET_VISIBLE_GETTERS = new WeakSet<() => boolean>();
167
+
168
+ /**
169
+ * Whether `el` has the port's `visible` — from `installVisible` or from `WidgetElement`. An
170
+ * element with its own `visible` (`<gtk-stack-page>`) keeps its own and answers false.
171
+ */
160
172
  export function hasInstalledVisible(el: Element): boolean {
161
- return VISIBLE_INSTALLED.has(el);
173
+ if (VISIBLE_INSTALLED.has(el)) return true;
174
+ const getter = inheritedDescriptor(el, 'visible')?.get;
175
+ return getter !== undefined && WIDGET_VISIBLE_GETTERS.has(getter as () => boolean);
162
176
  }
163
177
 
164
178
  /**
@@ -325,6 +325,45 @@ export const GtkLabelTest = async () => {
325
325
  host.remove();
326
326
  });
327
327
 
328
+ // GtkLabel's wrapping MINIMUM is its longest word, not the width it first wrapped
329
+ // at. A pinned `width` made the measured block the label's min-content, so a card
330
+ // around it in a narrower pane (Learn6502's preferences: 343px) grew past the pane.
331
+ await it('lets a wrapped label shrink below the width it first wrapped at', () => {
332
+ const long = 'word '.repeat(60).trim();
333
+ const { el, host } = mount(long);
334
+ host.style.display = 'flex';
335
+ const card = document.createElement('div');
336
+ host.appendChild(card);
337
+ card.appendChild(el);
338
+ el.wrap = true;
339
+ const first = el.querySelector('.adw-label-text')!.getBoundingClientRect().width;
340
+ expect(first > 300).toBe(true);
341
+ host.style.width = '200px';
342
+ expect(card.getBoundingClientRect().width <= 200).toBe(true);
343
+ expect(el.getBoundingClientRect().width <= 200).toBe(true);
344
+ host.remove();
345
+ });
346
+
347
+ // gtk_label_measure: a wrapping label's minimum is its widest word, its natural
348
+ // width the text on one line (capped only by `max-width-chars`).
349
+ await it('gives a wrapped label its widest word as minimum, one line as natural', () => {
350
+ const long = 'word '.repeat(60).trim();
351
+ const { el, host } = mount(long);
352
+ el.wrap = true;
353
+ const word = mount('word');
354
+ const wordWidth = textRect(word.el).width;
355
+ word.host.remove();
356
+ const line = mount(long);
357
+ line.host.style.width = 'max-content';
358
+ const lineWidth = textRect(line.el).width;
359
+ line.host.remove();
360
+ host.style.width = 'min-content';
361
+ expect(el.getBoundingClientRect().width <= Math.ceil(wordWidth) + 1).toBe(true);
362
+ host.style.width = 'max-content';
363
+ expect(Math.abs(el.getBoundingClientRect().width - lineWidth) <= 1).toBe(true);
364
+ host.remove();
365
+ });
366
+
328
367
  await it('is not selectable unless asked, as GtkLabel', () => {
329
368
  const { el, host } = mount('Hi');
330
369
  expect(getComputedStyle(el).userSelect).toBe('none');
@@ -216,24 +216,24 @@ export const GtkScrolledWindowTest = async () => {
216
216
  await fill(el, 10);
217
217
  // No request is made until one of the two asks for it: GTK only measures the
218
218
  // child when `propagate-natural-*` or a NEVER policy does (gtkscrolledwindow.c:1841-1844).
219
- expect(el.viewport.style.minHeight).toBe('');
219
+ expect(el.viewport.style.height).toBe('');
220
220
  // The NATURAL request is the child's `max-content` size, propagated up.
221
221
  el.setAttribute('propagate-natural-height', '');
222
222
  expect(el.propagateNaturalHeight).toBe(true);
223
- expect(el.viewport.style.minHeight).toBe('max-content');
223
+ expect(el.viewport.style.height).toBe('max-content');
224
224
  // A NEVER policy adds the child's MINIMUM request instead — and the natural one
225
225
  // is the larger of the two, so it wins when both are asked for. Both are FALSE in
226
226
  // the pspec, so their ATTRIBUTE is their presence, as `has-frame` is.
227
227
  el.removeAttribute('propagate-natural-height');
228
228
  el.setAttribute('vscrollbar-policy', 'never');
229
- expect(el.viewport.style.minHeight).toBe('min-content');
229
+ expect(el.viewport.style.height).toBe('min-content');
230
230
  // With both asked for on ONE axis the natural wins, and the other axis keeps
231
231
  // its own answer.
232
232
  el.setAttribute('propagate-natural-width', '');
233
- expect(el.viewport.style.minWidth).toBe('max-content');
234
- expect(el.viewport.style.minHeight).toBe('min-content');
233
+ expect(el.viewport.style.width).toBe('max-content');
234
+ expect(el.viewport.style.height).toBe('min-content');
235
235
  el.setAttribute('propagate-natural-height', '');
236
- expect(el.viewport.style.minHeight).toBe('max-content');
236
+ expect(el.viewport.style.height).toBe('max-content');
237
237
  host.remove();
238
238
  });
239
239
  });
@@ -20,8 +20,15 @@
20
20
  import { describe, it, expect } from '@gjsify/unit';
21
21
 
22
22
  import { GtkAdjustment, GtkStringList } from '@gjsify/adwaita-core';
23
+ import {
24
+ ROW_ACCESSOR_VECTORS,
25
+ driveRowAccessorVectors,
26
+ type ComboRowLike,
27
+ type SwitchRowLike,
28
+ } from '@gjsify/adwaita-core/conformance';
23
29
 
24
30
  import type { AdwComboRow } from './elements/adw-combo-row.js';
31
+ import type { AdwSwitchRow } from './elements/adw-switch-row.js';
25
32
  import type { AdwSpinRow } from './elements/adw-spin-row.js';
26
33
  import type { GtkDropDown } from './elements/gtk-drop-down.js';
27
34
 
@@ -101,4 +108,16 @@ export const GtkValueDoorsTest = async () => {
101
108
  expect(row.value).toBe(16);
102
109
  });
103
110
  });
111
+
112
+ await driveRowAccessorVectors(
113
+ {
114
+ name: 'adwaita-web',
115
+ isOracle: false,
116
+ makeComboRow: () => mount<AdwComboRow>('adw-combo-row') as unknown as ComboRowLike,
117
+ makeSwitchRow: () => mount<AdwSwitchRow>('adw-switch-row') as unknown as SwitchRowLike,
118
+ StringList: GtkStringList,
119
+ },
120
+ { describe, it, expect },
121
+ ROW_ACCESSOR_VECTORS,
122
+ );
104
123
  };
@@ -310,11 +310,11 @@ export const GtkWindowTest = async () => {
310
310
  const { el, host } = mount();
311
311
  let message = '';
312
312
  try {
313
- el.connect('map', () => {});
313
+ el.connect('toggled', () => {});
314
314
  } catch (error) {
315
315
  message = (error as Error).message;
316
316
  }
317
- expect(message.includes("'map'")).toBe(true);
317
+ expect(message.includes("'toggled'")).toBe(true);
318
318
  host.remove();
319
319
  });
320
320
 
@@ -20,6 +20,7 @@ import type { Buffer, Gutter } from '@gjsify/gtksource-core';
20
20
  import { EditorSession, GutterSet, STOP_EMISSION, toBoolean, toNumber } from '@gjsify/gtksource-core';
21
21
 
22
22
  import { WebEditorDriver } from './web-editor-driver.js';
23
+ import { WidgetElement } from '../widget-element.js';
23
24
 
24
25
  const STYLE_ID = 'gjsify-gtk-source-view-style';
25
26
 
@@ -130,7 +131,7 @@ const OBSERVED_ATTRIBUTES = [
130
131
  'bottom-margin',
131
132
  ];
132
133
 
133
- export class GtkSourceView extends HTMLElement {
134
+ export class GtkSourceView extends WidgetElement {
134
135
  static get observedAttributes(): string[] {
135
136
  return OBSERVED_ATTRIBUTES;
136
137
  }
@@ -14,17 +14,12 @@
14
14
  // that was never given draws nothing at all.
15
15
  import { describe, expect, it } from '@gjsify/unit';
16
16
 
17
- import { isIconAvailable, registerIcon } from './icon-registry.js';
17
+ import { isIconAvailable } from './icon-theme.js';
18
18
  import type { GtkImage } from './elements/gtk-image.js';
19
19
 
20
20
  /** A name no compiled entry can collide with, for the "not shipped" arm. */
21
21
  const ABSENT = 'gjsify-registry-probe';
22
22
 
23
- /** An Adwaita symbolic SVG, small and distinctive — a filled 8px square in the 16px grid. */
24
- const PROBE_SVG = `<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
25
- <path d="m 4 4 h 8 v 8 h -8 z m 0 0" fill="currentColor"/>
26
- </svg>`;
27
-
28
23
  function mount(iconName: string | null): { el: GtkImage; host: HTMLElement } {
29
24
  const host = document.createElement('div');
30
25
  document.body.appendChild(host);
@@ -55,7 +50,7 @@ export function fallbackMask(): string {
55
50
  return getComputedStyle(document.documentElement).getPropertyValue('--icon-image-missing').trim();
56
51
  }
57
52
 
58
- export const AdwIconRegistryTest = async () => {
53
+ export const AdwIconMasksTest = async () => {
59
54
  await describe('<gtk-image> resolves a name to a real mask', async () => {
60
55
  await it('a compiled name draws its OWN glyph, not the fallback', () => {
61
56
  const { el, host } = mount('go-next');
@@ -136,8 +131,8 @@ export const AdwIconRegistryTest = async () => {
136
131
  });
137
132
  });
138
133
 
139
- await describe('registerIcon — the documented way out of the compiled set', async () => {
140
- await it('reports an unshipped name as unavailable before registration', () => {
134
+ await describe('isIconAvailable', async () => {
135
+ await it('answers for the compiled set and nothing else', () => {
141
136
  expect(isIconAvailable(ABSENT)).toBe(false);
142
137
  // …and a compiled one as available, so the check is not answering `false` to
143
138
  // everything. `image-missing` is the case a fallback-comparison would get wrong.
@@ -145,96 +140,5 @@ export const AdwIconRegistryTest = async () => {
145
140
  expect(isIconAvailable('image-missing')).toBe(true);
146
141
  expect(isIconAvailable('')).toBe(false);
147
142
  });
148
-
149
- await it('makes the name resolve, on an element that is ALREADY mounted', () => {
150
- const { el, host } = mount(ABSENT);
151
- const before = maskOf(el);
152
- expect(before).toBe(fallbackMask());
153
-
154
- registerIcon(ABSENT, PROBE_SVG);
155
-
156
- const after = maskOf(el);
157
- expect(after).not.toBe(before);
158
- expect(after).not.toBe(fallbackMask());
159
- // The glyph really is the SVG that was handed over: `toDataUri` percent-encodes
160
- // it, so the path data survives as `m%204%204`.
161
- expect(after.includes('m%204%204')).toBe(true);
162
- expect(isIconAvailable(ABSENT)).toBe(true);
163
- host.remove();
164
- });
165
-
166
- await it('serves an element mounted AFTER the registration too', () => {
167
- const { el, host } = mount(`${ABSENT}-symbolic`);
168
- // The `-symbolic` suffix is stripped on both sides, so a consumer may spell the
169
- // name either way at either end.
170
- expect(el.resolvedIconName).toBe(ABSENT);
171
- expect(maskOf(el).includes('m%204%204')).toBe(true);
172
- host.remove();
173
- });
174
-
175
- await it('re-registering REPLACES the glyph without a second rule', () => {
176
- const sheet = (document.getElementById('adwaita-web-icon-registry') as HTMLStyleElement).sheet;
177
- const rulesBefore = (sheet as CSSStyleSheet).cssRules.length;
178
-
179
- registerIcon(ABSENT, PROBE_SVG.replace('m 4 4 h 8 v 8 h -8 z', 'm 2 2 h 12 v 12 h -12 z'));
180
-
181
- const { el, host } = mount(ABSENT);
182
- expect(maskOf(el).includes('m%202%202')).toBe(true);
183
- expect((sheet as CSSStyleSheet).cssRules.length).toBe(rulesBefore);
184
- host.remove();
185
- });
186
-
187
- await it('throws on a name that could never be one CSS class', () => {
188
- // Silently registering nothing is the exact failure this area exists to end, and
189
- // unlike a render this is an explicit call with a wrong argument.
190
- expect(() => registerIcon('org.gnome.Builder', PROBE_SVG)).toThrow();
191
- expect(() => registerIcon('a b', PROBE_SVG)).toThrow();
192
- expect(() => registerIcon('', PROBE_SVG)).toThrow();
193
- });
194
-
195
- await it('throws on a payload that is not SVG source, and registers nothing', () => {
196
- // The NAME was checked from the start; the payload was not, and a wrong payload
197
- // is worse than no registration at all: `toDataUri` percent-encodes anything, so
198
- // the mask comes out well-formed and masks NOTHING, the registered class beats
199
- // `:where(.adw-icon)` and switches this PR's fallback off, and `isIconAvailable`
200
- // answers `true`. Measured in Firefox before the guard: `'not an svg at all'`
201
- // gave `url("data:image/svg+xml,not%20an%20svg%20at%20all")` on a box painted 0 %,
202
- // where the unregistered control painted the 30 % image-missing glyph.
203
- const REJECTED = 'gjsify-registry-payload-probe';
204
- expect(() => registerIcon(REJECTED, 'not an svg at all')).toThrow();
205
- expect(() => registerIcon(REJECTED, '')).toThrow();
206
- // The likeliest wrong argument of all: what the custom property HOLDS, handed
207
- // over instead of what it was made from.
208
- expect(() => registerIcon(REJECTED, 'url("data:image/svg+xml,%3Csvg%3E%3C/svg%3E")')).toThrow();
209
- expect(isIconAvailable(REJECTED)).toBe(false);
210
-
211
- const { el, host } = mount(REJECTED);
212
- expect(maskOf(el)).toBe(fallbackMask());
213
- host.remove();
214
- });
215
-
216
- await it('rebuilds its rules after the <style> element is taken away', () => {
217
- // What an SPA head swap or an Astro view transition does. The record of inserted
218
- // rules is module-level and outlives the element it describes, so the early
219
- // return above used to skip the insert forever: the custom property was re-set
220
- // and the rule that consumes it never came back.
221
- const LOST = 'gjsify-registry-sheet-probe';
222
- registerIcon(LOST, PROBE_SVG);
223
- document.getElementById('adwaita-web-icon-registry')?.remove();
224
-
225
- registerIcon(LOST, PROBE_SVG);
226
-
227
- expect(document.getElementById('adwaita-web-icon-registry')).not.toBe(null);
228
- const { el, host } = mount(LOST);
229
- expect(maskOf(el).includes('m%204%204')).toBe(true);
230
- host.remove();
231
-
232
- // …and the names registered BEFORE the swap are on the rebuilt sheet too. Their
233
- // custom properties survived on the document element, so re-issuing only the
234
- // one name being registered would leave every earlier icon on the fallback.
235
- const { el: earlier, host: earlierHost } = mount(ABSENT);
236
- expect(maskOf(earlier)).not.toBe(fallbackMask());
237
- earlierHost.remove();
238
- });
239
143
  });
240
144
  };