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

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 (83) hide show
  1. package/README.md +12 -8
  2. package/dist/adwaita-web.css +39 -9
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/application.d.ts +1 -1
  5. package/lib/types/child-slot.spec.d.ts +1 -0
  6. package/lib/types/container-fill.spec.d.ts +1 -0
  7. package/lib/types/elements/adw-alert-dialog.d.ts +77 -17
  8. package/lib/types/elements/adw-toast-overlay.d.ts +8 -29
  9. package/lib/types/elements/adw-window-features.d.ts +8 -0
  10. package/lib/types/elements/gtk-application-window.d.ts +1 -4
  11. package/lib/types/elements/gtk-emoji-chooser.d.ts +2 -0
  12. package/lib/types/elements/gtk-popover-menu.d.ts +2 -0
  13. package/lib/types/elements/gtk-popover.d.ts +5 -0
  14. package/lib/types/elements/gtk-stack-page.d.ts +28 -0
  15. package/lib/types/elements/gtk-stack.d.ts +11 -0
  16. package/lib/types/elements/gtk-window.d.ts +16 -1
  17. package/lib/types/gobject-elements.d.ts +9 -0
  18. package/lib/types/index.d.ts +2 -2
  19. package/lib/types/learn6502-window.spec.d.ts +1 -0
  20. package/lib/types/namespace/adw.d.ts +1 -1
  21. package/lib/types/namespace/gtk.d.ts +2 -0
  22. package/lib/types/shared-tree-builder.d.ts +31 -0
  23. package/lib/types/styles.generated.d.ts +1 -1
  24. package/lib/types/widget-visible.spec.d.ts +1 -0
  25. package/lib/types/window-maximize.spec.d.ts +1 -0
  26. package/package.json +13 -12
  27. package/scss/_bin.scss +6 -3
  28. package/scss/_overlay.scss +11 -1
  29. package/scss/_reset.scss +1 -1
  30. package/scss/_stack.scss +8 -2
  31. package/scss/_toast.scss +13 -3
  32. package/scss/_window.scss +16 -0
  33. package/src/adw-alert-dialog.spec.ts +71 -5
  34. package/src/adw-bin.spec.ts +4 -3
  35. package/src/adw-header-bar.spec.ts +18 -0
  36. package/src/adw-toast-overlay.spec.ts +68 -24
  37. package/src/application.spec.ts +44 -0
  38. package/src/application.ts +13 -18
  39. package/src/capabilities.mjs +1 -3
  40. package/src/child-slot.spec.ts +71 -0
  41. package/src/construct-vectors.spec.ts +51 -6
  42. package/src/container-fill.spec.ts +70 -0
  43. package/src/elements/adw-alert-dialog.ts +174 -44
  44. package/src/elements/adw-application-window.ts +0 -3
  45. package/src/elements/adw-breakpoint-bin.ts +3 -0
  46. package/src/elements/adw-dialog.ts +3 -1
  47. package/src/elements/adw-header-bar.ts +4 -0
  48. package/src/elements/adw-toast-overlay.ts +35 -69
  49. package/src/elements/adw-window-features.ts +14 -2
  50. package/src/elements/gtk-application-window.ts +3 -8
  51. package/src/elements/gtk-drag-icon.ts +4 -0
  52. package/src/elements/gtk-emoji-chooser.ts +5 -0
  53. package/src/elements/gtk-flow-box-child.ts +3 -1
  54. package/src/elements/gtk-graphics-offload.ts +3 -1
  55. package/src/elements/gtk-list-box-row.ts +3 -1
  56. package/src/elements/gtk-overlay.ts +5 -4
  57. package/src/elements/gtk-paned.ts +7 -1
  58. package/src/elements/gtk-popover-bin.ts +3 -0
  59. package/src/elements/gtk-popover-menu.ts +5 -0
  60. package/src/elements/gtk-popover.ts +12 -0
  61. package/src/elements/gtk-search-bar.ts +5 -5
  62. package/src/elements/gtk-stack-page.ts +111 -0
  63. package/src/elements/gtk-stack.ts +50 -5
  64. package/src/elements/gtk-tree-expander.ts +3 -0
  65. package/src/elements/gtk-viewport.ts +4 -0
  66. package/src/elements/gtk-window-handle.ts +4 -0
  67. package/src/elements/gtk-window.ts +55 -6
  68. package/src/gobject-elements.ts +28 -0
  69. package/src/gtk-stack.spec.ts +170 -0
  70. package/src/index.ts +2 -2
  71. package/src/keyboard-operable.spec.ts +3 -3
  72. package/src/learn6502-window.spec.ts +113 -0
  73. package/src/namespace/adw.ts +1 -1
  74. package/src/namespace/gtk.ts +2 -0
  75. package/src/shared-tree-builder.ts +105 -10
  76. package/src/shared-trees.spec.ts +15 -1
  77. package/src/slotted-children.spec.ts +24 -0
  78. package/src/slotted-children.ts +18 -2
  79. package/src/styles.generated.ts +1 -1
  80. package/src/test.browser.mts +10 -0
  81. package/src/value-lists.spec.ts +3 -3
  82. package/src/widget-visible.spec.ts +104 -0
  83. package/src/window-maximize.spec.ts +93 -0
@@ -83,6 +83,7 @@ import { GtkListViewTest } from './gtk-list-view.spec.js';
83
83
  import { GtkHeaderBarTest } from './gtk-header-bar.spec.js';
84
84
  import { GtkWindowControlsTest } from './gtk-window-controls.spec.js';
85
85
  import { GtkWindowTest } from './gtk-window.spec.js';
86
+ import { WindowMaximizeTest } from './window-maximize.spec.js';
86
87
  import { GtkApplicationWindowTest } from './gtk-application-window.spec.js';
87
88
  import { GtkActionBarTest } from './gtk-action-bar.spec.js';
88
89
  import { GtkSeparatorTest } from './gtk-separator.spec.js';
@@ -93,6 +94,7 @@ import { GtkTreeExpanderTest } from './gtk-tree-expander.spec.js';
93
94
  import { GtkToggleButtonTest } from './gtk-toggle-button.spec.js';
94
95
  import { GtkExpanderTest } from './gtk-expander.spec.js';
95
96
  import { GtkOverlayTest } from './gtk-overlay.spec.js';
97
+ import { ContainerFillTest } from './container-fill.spec.js';
96
98
  import { GtkPanedTest } from './gtk-paned.spec.js';
97
99
  import { GtkRevealerTest } from './gtk-revealer.spec.js';
98
100
  import { GtkScaleTest } from './gtk-scale.spec.js';
@@ -161,6 +163,9 @@ import { AdwValueListsTest } from './value-lists.spec.js';
161
163
  import { AdwBlueprintLayoutTest } from './blueprint-layout.spec.js';
162
164
  import { AdwWidgetSizeTest } from './widget-size.spec.js';
163
165
  import { AdwSharedTreeMountTest } from './shared-tree-mount.spec.js';
166
+ import { AdwWidgetVisibleTest } from './widget-visible.spec.js';
167
+ import { AdwChildSlotTest } from './child-slot.spec.js';
168
+ import { AdwLearn6502WindowTest } from './learn6502-window.spec.js';
164
169
  import { AdwBlueprintMarkupTest } from './blueprint-markup.spec.js';
165
170
  import { AdwTagsTest } from './tags.spec.js';
166
171
  import { AdwFontStackTest } from './font-stack.spec.js';
@@ -183,6 +188,9 @@ run({
183
188
  AdwBlueprintLayoutTest,
184
189
  AdwWidgetSizeTest,
185
190
  AdwSharedTreeMountTest,
191
+ AdwWidgetVisibleTest,
192
+ AdwChildSlotTest,
193
+ AdwLearn6502WindowTest,
186
194
  AdwBlueprintMarkupTest,
187
195
  AdwTagsTest,
188
196
  AdwKeyboardOperableTest,
@@ -219,6 +227,7 @@ run({
219
227
  GtkHeaderBarTest,
220
228
  GtkWindowControlsTest,
221
229
  GtkWindowTest,
230
+ WindowMaximizeTest,
222
231
  GtkApplicationWindowTest,
223
232
  GtkActionBarTest,
224
233
  GtkSeparatorTest,
@@ -234,6 +243,7 @@ run({
234
243
  GtkToggleButtonTest,
235
244
  GtkExpanderTest,
236
245
  GtkOverlayTest,
246
+ ContainerFillTest,
237
247
  GtkPanedTest,
238
248
  GtkRevealerTest,
239
249
  GtkScaleTest,
@@ -63,9 +63,9 @@ export const AdwValueListsTest = async () => {
63
63
  const dialog = root as unknown as AdwAlertDialog;
64
64
  const read = vector.responses.map(({ id }) => ({
65
65
  id,
66
- label: dialog.getResponseLabel(id),
67
- appearance: dialog.getResponseAppearance(id),
68
- enabled: dialog.getResponseEnabled(id),
66
+ label: dialog.get_response_label(id),
67
+ appearance: dialog.get_response_appearance(id),
68
+ enabled: dialog.get_response_enabled(id),
69
69
  }));
70
70
  expect(JSON.stringify(read)).toBe(JSON.stringify(vector.responses));
71
71
  // The buttons the dialog paints, in the order the source wrote them.
@@ -0,0 +1,104 @@
1
+ // `Gtk.Widget:visible` on a built element: an authored `visible: false`, `get_visible()` /
2
+ // `set_visible()`, the property, and a breakpoint setter that writes it and restores it.
3
+ import { describe, expect, it } from '@gjsify/unit';
4
+ import type { SharedTreeNode } from '@gjsify/adwaita-core/conformance';
5
+
6
+ import { mountSharedTree } from './shared-tree-builder.js';
7
+
8
+ function settle(): Promise<void> {
9
+ return new Promise((resolve) => {
10
+ requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
11
+ });
12
+ }
13
+
14
+ type Widget = HTMLElement & { visible: boolean; get_visible(): boolean; set_visible(value: boolean): void };
15
+
16
+ const tree = (width: number, authored: boolean): SharedTreeNode => ({
17
+ tag: 'AdwApplicationWindow',
18
+ props: { 'default-width': width, 'default-height': 400 },
19
+ breakpoints: [
20
+ {
21
+ condition: 'max-width: 599sp',
22
+ setters: [{ object: 'target', property: 'visible', value: false }],
23
+ },
24
+ ],
25
+ children: [
26
+ {
27
+ tag: 'GtkBox',
28
+ slot: 'content',
29
+ children: [{ tag: 'GtkButton', id: 'target', props: authored ? {} : { visible: false } }],
30
+ },
31
+ ],
32
+ });
33
+
34
+ export const AdwWidgetVisibleTest = async () => {
35
+ await describe('adwaita-web: Gtk.Widget:visible on a built element', async () => {
36
+ await it('an authored `visible: false` hides the widget', () => {
37
+ const { root, unmount } = mountSharedTree({
38
+ tag: 'GtkBox',
39
+ children: [{ tag: 'GtkButton', id: 'b', props: { visible: false } }],
40
+ });
41
+ const button = root.querySelector('#b') as Widget;
42
+ expect(button.hidden).toBe(true);
43
+ expect(button.visible).toBe(false);
44
+ expect(button.get_visible()).toBe(false);
45
+ unmount();
46
+ });
47
+
48
+ await it('is visible by default, and an authored `true` shows it', () => {
49
+ const { root, unmount } = mountSharedTree({
50
+ tag: 'GtkBox',
51
+ children: [
52
+ { tag: 'GtkButton', id: 'a' },
53
+ { tag: 'GtkButton', id: 'b', props: { visible: true } },
54
+ ],
55
+ });
56
+ expect((root.querySelector('#a') as Widget).get_visible()).toBe(true);
57
+ expect((root.querySelector('#b') as Widget).hidden).toBe(false);
58
+ unmount();
59
+ });
60
+
61
+ await it('set_visible() and the property round-trip', () => {
62
+ const { root, unmount } = mountSharedTree({
63
+ tag: 'GtkBox',
64
+ children: [{ tag: 'GtkButton', id: 'b' }],
65
+ });
66
+ const button = root.querySelector('#b') as Widget;
67
+ button.set_visible(false);
68
+ expect(button.hidden).toBe(true);
69
+ button.visible = true;
70
+ expect(button.hidden).toBe(false);
71
+ expect(button.get_visible()).toBe(true);
72
+ unmount();
73
+ });
74
+
75
+ await it('a breakpoint setter hides the widget and unapplying restores it', async () => {
76
+ const narrow = mountSharedTree(tree(400, true));
77
+ await settle();
78
+ expect((narrow.root.querySelector('#target') as Widget).visible).toBe(false);
79
+ narrow.unmount();
80
+
81
+ const wide = mountSharedTree(tree(1000, true));
82
+ await settle();
83
+ expect((wide.root.querySelector('#target') as Widget).visible).toBe(true);
84
+ wide.unmount();
85
+ });
86
+
87
+ await it('unapplying a breakpoint restores an authored `false`', async () => {
88
+ const { root, unmount } = mountSharedTree(tree(1000, false));
89
+ await settle();
90
+ expect((root.querySelector('#target') as Widget).visible).toBe(false);
91
+ unmount();
92
+ });
93
+
94
+ await it('<gtk-stack-page> and <adw-sidebar> keep their own `visible`', () => {
95
+ const page = document.createElement('gtk-stack-page') as Widget;
96
+ page.visible = false;
97
+ expect(page.hasAttribute('hidden')).toBe(true);
98
+ const item = document.createElement('adw-sidebar-item') as Widget;
99
+ item.visible = false;
100
+ expect(item.getAttribute('visible')).toBe('false');
101
+ expect(item.hasAttribute('hidden')).toBe(true);
102
+ });
103
+ });
104
+ };
@@ -0,0 +1,93 @@
1
+ // A maximized or fullscreen `Gtk.Window` ignores its default size and fills the work area
2
+ // (gtkwindow.c); on a page that is the frame's containing block. Driven through layout, because
3
+ // the claim is about the box, not about a class name. One body for the three window elements.
4
+ import { describe, expect, it } from '@gjsify/unit';
5
+
6
+ import type { GtkWindow } from './elements/gtk-window.js';
7
+
8
+ const TAGS = ['gtk-window', 'adw-window', 'adw-application-window'] as const;
9
+
10
+ function mount(tag: string, attrs: Record<string, string> = {}): { el: GtkWindow; host: HTMLElement } {
11
+ const host = document.createElement('div');
12
+ host.style.cssText = 'position:relative;width:500px;height:400px';
13
+ document.body.appendChild(host);
14
+ const el = document.createElement(tag) as GtkWindow;
15
+ el.setAttribute('default-width', '360');
16
+ el.setAttribute('default-height', '240');
17
+ for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
18
+ host.appendChild(el);
19
+ return { el, host };
20
+ }
21
+
22
+ function size(el: HTMLElement): string {
23
+ const rect = el.getBoundingClientRect();
24
+ return `${Math.round(rect.width)}x${Math.round(rect.height)}`;
25
+ }
26
+
27
+ export const WindowMaximizeTest = async () => {
28
+ for (const tag of TAGS) {
29
+ await describe(`<${tag}> maximized fills its containing block`, async () => {
30
+ await it('opens at the default size, fills the box maximized, and restores on unmaximize', async () => {
31
+ const { el, host } = mount(tag);
32
+ expect(size(el)).toBe('360x240');
33
+ el.maximize();
34
+ expect(size(el)).toBe('500x400');
35
+ expect(el.style.width).toBe('');
36
+ el.unmaximize();
37
+ expect(size(el)).toBe('360x240');
38
+ host.remove();
39
+ });
40
+
41
+ await it('fills the box through the `maximized` property and `toggle-maximized`', async () => {
42
+ const { el, host } = mount(tag);
43
+ el.maximized = true;
44
+ expect(size(el)).toBe('500x400');
45
+ el.maximized = false;
46
+ expect(size(el)).toBe('360x240');
47
+ el.dispatchEvent(new CustomEvent('window-action', { detail: { action: 'toggle-maximized' } }));
48
+ expect(size(el)).toBe('500x400');
49
+ el.dispatchEvent(new CustomEvent('window-action', { detail: { action: 'toggle-maximized' } }));
50
+ expect(size(el)).toBe('360x240');
51
+ host.remove();
52
+ });
53
+
54
+ await it('fills the box fullscreened and restores on unfullscreen', async () => {
55
+ const { el, host } = mount(tag);
56
+ el.fullscreen();
57
+ expect(el.is_fullscreen()).toBe(true);
58
+ expect(size(el)).toBe('500x400');
59
+ el.unfullscreen();
60
+ expect(size(el)).toBe('360x240');
61
+ host.remove();
62
+ });
63
+
64
+ await it('stays filled until both states are gone', async () => {
65
+ const { el, host } = mount(tag);
66
+ el.maximize();
67
+ el.fullscreen();
68
+ el.unmaximize();
69
+ expect(size(el)).toBe('500x400');
70
+ el.unfullscreen();
71
+ expect(size(el)).toBe('360x240');
72
+ host.remove();
73
+ });
74
+
75
+ await it('fills the box already maximized when it is connected', async () => {
76
+ const { el, host } = mount(tag, { maximized: 'true' });
77
+ expect(size(el)).toBe('500x400');
78
+ host.remove();
79
+ });
80
+ });
81
+ }
82
+
83
+ await describe('<adw-window> maximized keeps its size request as a minimum', async () => {
84
+ await it('does not shrink below width-request/height-request', async () => {
85
+ const { el, host } = mount('adw-window', { 'width-request': '600', 'height-request': '450' });
86
+ el.maximize();
87
+ const [width, height] = size(el).split('x').map(Number);
88
+ expect(width >= 600).toBe(true);
89
+ expect(height >= 450).toBe(true);
90
+ host.remove();
91
+ });
92
+ });
93
+ };