@gjsify/adwaita-web 0.59.1 → 0.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +11 -0
  2. package/dist/adwaita-web.css +4 -0
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/elements/gtk-button.d.ts +13 -0
  5. package/lib/types/elements/gtk-drop-down.d.ts +4 -0
  6. package/lib/types/elements/gtk-label.d.ts +4 -0
  7. package/lib/types/elements/gtk-text-view.d.ts +15 -0
  8. package/lib/types/file-chooser-host.d.ts +55 -0
  9. package/lib/types/file-chooser.spec.d.ts +1 -0
  10. package/lib/types/gtk-platform.spec.d.ts +1 -0
  11. package/lib/types/namespace/adw.d.ts +1 -0
  12. package/lib/types/namespace/gdk.d.ts +2 -0
  13. package/lib/types/namespace/gio.d.ts +3 -0
  14. package/lib/types/namespace/glib.d.ts +1 -0
  15. package/lib/types/namespace/gtk-enums.d.ts +22 -0
  16. package/lib/types/namespace/gtk-platform.d.ts +13 -0
  17. package/lib/types/namespace/gtk.d.ts +4 -1
  18. package/lib/types/platform-host.d.ts +2 -0
  19. package/lib/types/registered-styles.d.ts +2 -0
  20. package/lib/types/style-manager.d.ts +7 -0
  21. package/lib/types/styles.generated.d.ts +1 -1
  22. package/lib/types/template-classes.d.ts +2 -0
  23. package/lib/types/widget-members.spec.d.ts +1 -0
  24. package/package.json +23 -10
  25. package/scss/_viewport.scss +9 -0
  26. package/src/capabilities.mjs +1 -4
  27. package/src/construct-vectors.spec.ts +10 -1
  28. package/src/elements/gtk-button.ts +34 -0
  29. package/src/elements/gtk-drop-down.ts +10 -0
  30. package/src/elements/gtk-label.ts +10 -0
  31. package/src/elements/gtk-text-view.ts +40 -0
  32. package/src/file-chooser-host.ts +421 -0
  33. package/src/file-chooser.spec.ts +376 -0
  34. package/src/gobject-door.ts +15 -2
  35. package/src/gobject-elements.ts +4 -0
  36. package/src/gtk-drop-down.spec.ts +11 -0
  37. package/src/gtk-label.spec.ts +12 -0
  38. package/src/gtk-platform.spec.ts +19 -0
  39. package/src/gtk-text-view.spec.ts +22 -0
  40. package/src/namespace/adw.ts +1 -0
  41. package/src/namespace/gdk.ts +18 -1
  42. package/src/namespace/gio.ts +20 -2
  43. package/src/namespace/glib.ts +6 -1
  44. package/src/namespace/gtk-enums.ts +7 -2
  45. package/src/namespace/gtk-platform.ts +16 -0
  46. package/src/namespace/gtk.ts +12 -1
  47. package/src/platform-host.ts +88 -0
  48. package/src/registered-styles.ts +73 -0
  49. package/src/shared-tree-builder.ts +46 -2
  50. package/src/shared-trees.spec.ts +36 -0
  51. package/src/style-manager.ts +10 -1
  52. package/src/styles.generated.ts +1 -1
  53. package/src/template-classes.ts +6 -0
  54. package/src/test.browser.mts +6 -0
  55. package/src/widget-members.spec.ts +147 -0
@@ -26,6 +26,12 @@ export function registerTemplateClass(name: string, tag: string): void {
26
26
  registry.set(name, tag);
27
27
  }
28
28
 
29
+ /** Whether `tag` is an element an application class registered, whose properties are GObject properties. */
30
+ export function isTemplateTag(tag: string): boolean {
31
+ for (const known of registry.values()) if (known === tag) return true;
32
+ return false;
33
+ }
34
+
29
35
  /** The tag `name` was registered under, or a refusal that names what is missing. */
30
36
  export function templateTagFor(name: string): string {
31
37
  const tag = registry.get(name);
@@ -142,7 +142,10 @@ import { AdwConstructVectorsTest } from './construct-vectors.spec.js';
142
142
  import { GObjectDoorTest } from './gobject-door.spec.js';
143
143
  import { ApplicationTest } from './application.spec.js';
144
144
  import { GdkTest } from './gdk.spec.js';
145
+ import { FileChooserTest } from './file-chooser.spec.js';
146
+ import { WidgetMembersTest } from './widget-members.spec.js';
145
147
  import { GLibTest } from './glib.spec.js';
148
+ import { GtkPlatformTest } from './gtk-platform.spec.js';
146
149
  import { StyleManagerTest } from './style-manager.spec.js';
147
150
  import { GioActionsTest } from './gio.spec.js';
148
151
  import { MenuActionsTest } from './menu-actions.spec.js';
@@ -162,7 +165,10 @@ run({
162
165
  GObjectDoorTest,
163
166
  ApplicationTest,
164
167
  GdkTest,
168
+ FileChooserTest,
169
+ WidgetMembersTest,
165
170
  GLibTest,
171
+ GtkPlatformTest,
166
172
  StyleManagerTest,
167
173
  GioActionsTest,
168
174
  MenuActionsTest,
@@ -0,0 +1,147 @@
1
+ // `Gtk.Widget` members a registered class gets from the port: direction, tree links and
2
+ // `insert_action_group`. GTK's own answers (gtkwidget.c) are the oracle.
3
+
4
+ import { describe, expect, it } from '@gjsify/unit';
5
+
6
+ import * as GObject from './namespace/gobject.js';
7
+ import * as Gio from './namespace/gio.js';
8
+ import { writeProp } from './shared-tree-builder.js';
9
+ import { registerTemplateClass } from './template-classes.js';
10
+
11
+ interface WidgetLike extends HTMLElement {
12
+ set_direction(direction: number): void;
13
+ get_direction(): number;
14
+ get_first_child(): Element | null;
15
+ get_last_child(): Element | null;
16
+ get_next_sibling(): Element | null;
17
+ get_prev_sibling(): Element | null;
18
+ get_parent(): Element | null;
19
+ insert_action_group(name: string, group: unknown): void;
20
+ }
21
+
22
+ const make = (name: string): WidgetLike =>
23
+ new (GObject.registerClass({ GTypeName: name }, class extends HTMLElement {}) as unknown as new () => WidgetLike)();
24
+
25
+ export const WidgetMembersTest = async () => {
26
+ await describe('Gtk.Widget members on a registered class', async () => {
27
+ await it('is LTR until set_direction, and reads back what it was given', () => {
28
+ const widget = make('WidgetMembersDirection');
29
+ expect(widget.get_direction()).toBe(1);
30
+ widget.set_direction(2);
31
+ expect(widget.get_direction()).toBe(2);
32
+ document.body.append(widget);
33
+ expect(widget.dir).toBe('rtl');
34
+ widget.set_direction(0);
35
+ expect(widget.hasAttribute('dir')).toBe(false);
36
+ widget.remove();
37
+ });
38
+
39
+ await it('is set in the constructor of an element that createElement builds, which may take no attribute', () => {
40
+ class Pinned extends HTMLElement {
41
+ constructor() {
42
+ super();
43
+ (this as unknown as WidgetLike).set_direction(1);
44
+ }
45
+ }
46
+ GObject.registerClass({ GTypeName: 'WidgetMembersCtor' }, Pinned);
47
+ const widget = document.createElement('gjsify-widget-members-ctor') as WidgetLike;
48
+ document.body.append(widget);
49
+ expect(widget.dir).toBe('ltr');
50
+ widget.remove();
51
+ });
52
+
53
+ await it('rejects a direction that is not a Gtk.TextDirection', () => {
54
+ const widget = make('WidgetMembersBadDirection');
55
+ expect(() => widget.set_direction(7)).toThrow();
56
+ });
57
+
58
+ await it('walks the element tree with the GTK link names', () => {
59
+ const parent = make('WidgetMembersParent');
60
+ const a = document.createElement('div');
61
+ const b = document.createElement('div');
62
+ parent.append(a, b);
63
+ expect(parent.get_first_child()).toBe(a);
64
+ expect(parent.get_last_child()).toBe(b);
65
+ expect(a.nextElementSibling).toBe(b);
66
+ expect(parent.get_next_sibling()).toBe(null);
67
+ expect(parent.get_prev_sibling()).toBe(null);
68
+ expect(parent.get_parent()).toBe(null);
69
+ });
70
+
71
+ await it('adds, tests and removes a CSS class with the GTK names', () => {
72
+ const widget = make('WidgetMembersCss') as unknown as {
73
+ add_css_class(c: string): void;
74
+ remove_css_class(c: string): void;
75
+ has_css_class(c: string): boolean;
76
+ };
77
+ widget.add_css_class('dim-label');
78
+ expect(widget.has_css_class('dim-label')).toBe(true);
79
+ widget.remove_css_class('dim-label');
80
+ expect(widget.has_css_class('dim-label')).toBe(false);
81
+ });
82
+
83
+ await it('takes an action group and drops it again with null', () => {
84
+ const widget = make('WidgetMembersActions');
85
+ const group = new Gio.SimpleActionGroup();
86
+ widget.insert_action_group('source-view', group);
87
+ widget.insert_action_group('source-view', null);
88
+ });
89
+ });
90
+
91
+ await describe('the stylesheet of a registered class', async () => {
92
+ await it('gets the rules its base tag has, for every selector that names the base', () => {
93
+ class StyleBase extends HTMLElement {}
94
+ customElements.define('widget-style-base', StyleBase);
95
+ const sheet = document.createElement('style');
96
+ sheet.textContent =
97
+ 'widget-style-base { display: block; padding-left: 7px; }' +
98
+ 'widget-style-base > :only-child { block-size: 100%; }' +
99
+ 'widget-style-other, widget-style-base { margin-left: 3px; }' +
100
+ '@media (min-width: 1px) { widget-style-base { margin-right: 5px; } }';
101
+ document.head.append(sheet);
102
+ GObject.registerClass({ GTypeName: 'WidgetStyleSub' }, class extends StyleBase {});
103
+ const widget = document.createElement('gjsify-widget-style-sub');
104
+ document.body.append(widget);
105
+ const style = getComputedStyle(widget);
106
+ expect(style.display).toBe('block');
107
+ expect(style.paddingLeft).toBe('7px');
108
+ expect(style.marginLeft).toBe('3px');
109
+ expect(style.marginRight).toBe('5px');
110
+ widget.remove();
111
+ sheet.remove();
112
+ });
113
+
114
+ await it('takes an authored template property as a GObject property, not an attribute', () => {
115
+ class Props extends HTMLElement {
116
+ seen: unknown[] = [];
117
+ set lineNumbers(value: boolean) {
118
+ this.seen.push(value);
119
+ }
120
+ set lineNumberStart(value: number) {
121
+ this.seen.push(value);
122
+ }
123
+ }
124
+ GObject.registerClass({ GTypeName: 'WidgetMembersProps' }, Props);
125
+ registerTemplateClass('WidgetMembersProps', 'gjsify-widget-members-props');
126
+ const widget = document.createElement('gjsify-widget-members-props') as Props;
127
+ writeProp(widget, 'line-numbers', true);
128
+ writeProp(widget, 'line-number-start', 1536);
129
+ expect(widget.seen).toStrictEqual([true, 1536]);
130
+ expect(widget.hasAttribute('line-numbers')).toBe(false);
131
+ });
132
+
133
+ await it('reaches the DOM when a class writes icon_name or tooltip_text on a button', () => {
134
+ const button = document.createElement('gtk-button') as HTMLElement & {
135
+ icon_name: string;
136
+ tooltip_text: string;
137
+ };
138
+ document.body.append(button);
139
+ button.icon_name = 'edit-copy-symbolic';
140
+ button.tooltip_text = 'Copy';
141
+ expect(button.getAttribute('icon-name')).toBe('edit-copy-symbolic');
142
+ expect(button.querySelector('button')?.title).toBe('Copy');
143
+ expect(button.querySelector('gtk-image') !== null).toBe(true);
144
+ button.remove();
145
+ });
146
+ });
147
+ };