@gjsify/adwaita-web 0.64.1-next.243 → 0.64.1-next.245

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.
@@ -30,6 +30,7 @@ export declare class AdwActionRow extends HTMLElement {
30
30
  set activatableWidget(widget: HTMLElement | null);
31
31
  /** Whether a click activates this row — `GtkListBoxRow:activatable`. */
32
32
  get activatable(): boolean;
33
+ constructor();
33
34
  connectedCallback(): void;
34
35
  /** Copy the declarative attributes into the headless state. */
35
36
  private _adoptAttributes;
@@ -71,6 +71,7 @@ export declare class AdwBottomSheet extends HTMLElement {
71
71
  * a swipe, and the drag handle never closes anything (`resolveBottomSheetClose`).
72
72
  */
73
73
  requestClose(source: BottomSheetCloseSource): BottomSheetCloseOutcome;
74
+ constructor();
74
75
  connectedCallback(): void;
75
76
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
76
77
  /** The programmatic open/close — `AdwBottomSheet:open`, ungated by `can-close`. */
@@ -41,6 +41,7 @@ export declare class AdwNavigationView extends HTMLElement {
41
41
  get canGoBack(): boolean;
42
42
  /** The back button's tooltip — the previous page's title, or null when there is no button. */
43
43
  get backButtonTooltip(): string | null;
44
+ constructor();
44
45
  connectedCallback(): void;
45
46
  attributeChangedCallback(name: string): void;
46
47
  /**
@@ -17,6 +17,7 @@ export declare class AdwSwitchRow extends HTMLElement {
17
17
  get prefixSection(): HTMLDivElement;
18
18
  get active(): boolean;
19
19
  set active(value: boolean);
20
+ constructor();
20
21
  connectedCallback(): void;
21
22
  attributeChangedCallback(name: string): void;
22
23
  /**
@@ -72,6 +72,7 @@ export { GtkToggleButton as ToggleButton } from '../elements/gtk-toggle-button.j
72
72
  export { GtkTreeExpander as TreeExpander } from '../elements/gtk-tree-expander.js';
73
73
  export { GtkVideo as Video } from '../elements/gtk-video.js';
74
74
  export { GtkWindow as Window } from '../elements/gtk-window.js';
75
+ export type { WindowCommon } from '@gjsify/adwaita-core';
75
76
  export { GtkWindowControls as WindowControls } from '../elements/gtk-window-controls.js';
76
77
  export { GtkViewport as Viewport } from '../elements/gtk-viewport.js';
77
78
  export { GtkWindowHandle as WindowHandle } from '../elements/gtk-window-handle.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/adwaita-web",
3
- "version": "0.64.1-next.243",
3
+ "version": "0.64.1-next.245",
4
4
  "description": "Adwaita/Libadwaita web components for browser targets",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -58,14 +58,14 @@
58
58
  "@codemirror/language": "^6.12.4",
59
59
  "@codemirror/state": "^6.7.0",
60
60
  "@codemirror/view": "^6.43.4",
61
- "@gjsify/adwaita-core": "0.64.1-next.243",
62
- "@gjsify/adwaita-fonts": "0.64.1-next.243",
63
- "@gjsify/adwaita-icons": "0.64.1-next.243",
64
- "@gjsify/gtksource-core": "0.64.1-next.243",
61
+ "@gjsify/adwaita-core": "0.64.1-next.245",
62
+ "@gjsify/adwaita-fonts": "0.64.1-next.245",
63
+ "@gjsify/adwaita-icons": "0.64.1-next.245",
64
+ "@gjsify/gtksource-core": "0.64.1-next.245",
65
65
  "@lezer/highlight": "^1.2.3"
66
66
  },
67
67
  "peerDependencies": {
68
- "@gjsify/app-settings": "0.64.1-next.243"
68
+ "@gjsify/app-settings": "0.64.1-next.245"
69
69
  },
70
70
  "peerDependenciesMeta": {
71
71
  "@gjsify/app-settings": {
@@ -73,11 +73,11 @@
73
73
  }
74
74
  },
75
75
  "devDependencies": {
76
- "@gjsify/app-settings": "0.64.1-next.243",
77
- "@gjsify/blueprint": "0.64.1-next.243",
78
- "@gjsify/cli": "0.64.1-next.243",
79
- "@gjsify/unit": "0.64.1-next.243",
80
- "@gjsify/vite-plugin-blueprint": "0.64.1-next.243",
76
+ "@gjsify/app-settings": "0.64.1-next.245",
77
+ "@gjsify/blueprint": "0.64.1-next.245",
78
+ "@gjsify/cli": "0.64.1-next.245",
79
+ "@gjsify/unit": "0.64.1-next.245",
80
+ "@gjsify/vite-plugin-blueprint": "0.64.1-next.245",
81
81
  "sass": "^1.101.0",
82
82
  "typescript": "^6.0.3"
83
83
  },
@@ -115,5 +115,5 @@
115
115
  "url": "https://github.com/gjsify/gjsify/issues"
116
116
  },
117
117
  "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/web/adwaita-web#readme",
118
- "gitHead": "f88c7b1074d454e211094963a9f4dc7d0982bf32"
118
+ "gitHead": "9a6ca179c1a74477f23791c5b8f6d5a7bffaee61"
119
119
  }
@@ -54,6 +54,10 @@ export const AdwWindowTest = async () => {
54
54
  });
55
55
 
56
56
  await it('keeps 360×200 as a minimum and fills the viewport without an authored size', async () => {
57
+ // The window fills its containing block, which is the viewport only once the
58
+ // browser's default 8px body margin is gone (an app resets it, the test page does not).
59
+ const margin = document.body.style.margin;
60
+ document.body.style.margin = '0';
57
61
  const win = makeWindow();
58
62
  expect(win.style.minWidth).toBe('360px');
59
63
  expect(win.style.minHeight).toBe('200px');
@@ -62,6 +66,7 @@ export const AdwWindowTest = async () => {
62
66
  expect(Math.round(win.getBoundingClientRect().width)).toBe(document.documentElement.clientWidth);
63
67
  expect(Math.round(win.getBoundingClientRect().height)).toBe(window.innerHeight);
64
68
  win.remove();
69
+ document.body.style.margin = margin;
65
70
  });
66
71
 
67
72
  await it('width-request/height-request override the minimum; gtk-window has none', async () => {
@@ -117,6 +122,8 @@ export const AdwWindowTest = async () => {
117
122
 
118
123
  win.remove();
119
124
  document.body.appendChild(win);
125
+ // 360 is a MINIMUM, so a 200px box needs the request lowered as well.
126
+ win.setAttribute('width-request', '100');
120
127
  win.setAttribute('width', '200');
121
128
  await settle();
122
129
 
@@ -53,8 +53,6 @@ const subject: ApplicationSubject = {
53
53
 
54
54
  export const ApplicationTest = async () => {
55
55
  await driveApplicationVectors(subject, { describe, it, expect });
56
- // The page is shared with every other suite: a window left in it moves their layout.
57
- for (const element of made.splice(0)) element.remove();
58
56
 
59
57
  await describe('adwaita-web: Application (ADR 0098 § 3)', async () => {
60
58
  await it('has a vector for every unlocked vfunc', () => {
@@ -102,7 +100,9 @@ export const ApplicationTest = async () => {
102
100
  app.connect('activate', () => app.quit());
103
101
  await app.runAsync([]);
104
102
  expect(window.isConnected).toBe(false);
105
- made.length = 0;
103
+ made.splice(made.indexOf(window), 1);
106
104
  });
107
105
  });
106
+ // The page is shared with every other suite: a window left in it moves their layout.
107
+ for (const element of made.splice(0)) element.remove();
108
108
  };
@@ -27,6 +27,7 @@ import { ActionRowState } from '@gjsify/adwaita-core';
27
27
  import { bindEmptySections } from '../empty-sections.js';
28
28
  import { applyRowTooltip } from '../row-tooltip.js';
29
29
  import { bindSlottedChildren } from '../slotted-children.js';
30
+ import { installElementApi } from '../gobject-elements.js';
30
31
  import type { DispatchedSignals } from '../signals.js';
31
32
  import { type AdwRowActivation, attachRowActivation } from './row-activation.js';
32
33
  import { applyRowLineClamp, parseRowLinesAttribute } from '../row-line-clamp.js';
@@ -97,6 +98,11 @@ export class AdwActionRow extends HTMLElement {
97
98
  return this._state.activatable;
98
99
  }
99
100
 
101
+ constructor() {
102
+ super();
103
+ installElementApi(this);
104
+ }
105
+
100
106
  connectedCallback() {
101
107
  if (this._initialized) {
102
108
  // Re-entering a document: `disconnectedCallback` dropped the sensitivity
@@ -64,6 +64,7 @@ import type {
64
64
  } from '@gjsify/adwaita-core';
65
65
 
66
66
  import { bindSlottedChildren, type AdwSlot } from '../slotted-children.js';
67
+ import { installElementApi } from '../gobject-elements.js';
67
68
  import type { DispatchedSignals } from '../signals.js';
68
69
 
69
70
  /** The persistent content. Child of <adw-bottom-sheet>; consumed at connect time. */
@@ -209,6 +210,11 @@ export class AdwBottomSheet extends HTMLElement {
209
210
  return outcome;
210
211
  }
211
212
 
213
+ constructor() {
214
+ super();
215
+ installElementApi(this);
216
+ }
217
+
212
218
  connectedCallback() {
213
219
  if (this._initialized) return;
214
220
  this._initialized = true;
@@ -55,6 +55,7 @@ import { BACK_BUTTON_FALLBACK_TOOLTIP, NavigationViewState, describeNavigationDi
55
55
  import type { AdwNavigationPageProps, NavigationDiagnostic, NavigationStackChange } from '@gjsify/adwaita-core';
56
56
 
57
57
  import { bindSlottedChildren } from '../slotted-children.js';
58
+ import { installElementApi } from '../gobject-elements.js';
58
59
  import type { DispatchedSignals } from '../signals.js';
59
60
 
60
61
  /** The page properties the core owns, read off the element's attributes. */
@@ -215,6 +216,11 @@ export class AdwNavigationView extends HTMLElement {
215
216
  return this._state.backButtonTooltip();
216
217
  }
217
218
 
219
+ constructor() {
220
+ super();
221
+ installElementApi(this);
222
+ }
223
+
218
224
  connectedCallback() {
219
225
  if (this._initialized) return;
220
226
  this._initialized = true;
@@ -29,6 +29,7 @@ import { SwitchRowState, deriveRowLabels } from '@gjsify/adwaita-core';
29
29
  import { bindEmptySections } from '../empty-sections.js';
30
30
  import { applyRowTooltip } from '../row-tooltip.js';
31
31
  import { bindSlottedChildren } from '../slotted-children.js';
32
+ import { installElementApi } from '../gobject-elements.js';
32
33
  import type { DispatchedSignals } from '../signals.js';
33
34
  import { applyRowLineClamp, parseRowLinesAttribute } from '../row-line-clamp.js';
34
35
 
@@ -75,6 +76,11 @@ export class AdwSwitchRow extends HTMLElement {
75
76
  this.toggleAttribute('active', !!value);
76
77
  }
77
78
 
79
+ constructor() {
80
+ super();
81
+ installElementApi(this);
82
+ }
83
+
78
84
  connectedCallback() {
79
85
  if (this._initialized) return;
80
86
  this._initialized = true;
@@ -280,7 +280,7 @@ export class GtkWindowControls extends HTMLElement {
280
280
  if (token === 'maximize') {
281
281
  if (!sovereign || !this._windowFlag(window, 'resizable')) return null;
282
282
  // :347-350 — the glyph and the label follow the window's state, not the token.
283
- const maximized = window.hasAttribute('maximized');
283
+ const maximized = window.hasAttribute('maximized') && window.getAttribute('maximized') !== 'false';
284
284
  return this._controlButton(
285
285
  maximized
286
286
  ? { ...TOKEN_BUTTONS.maximize, icon: RESTORE_ICON_NAME, label: RESTORE_LABEL }
@@ -281,7 +281,7 @@ export class GtkWindow extends HTMLElement {
281
281
  }
282
282
 
283
283
  private _offByDefault(name: string): boolean {
284
- return this.hasAttribute(name);
284
+ return this.hasAttribute(name) && this.getAttribute(name) !== 'false';
285
285
  }
286
286
 
287
287
  connectedCallback() {
@@ -22,6 +22,7 @@ import {
22
22
  dialogFailedError,
23
23
  dismissedError,
24
24
  fileFilterAccepts,
25
+ GLibError,
25
26
  registerFileChooserDriver,
26
27
  type FileChooserDriver,
27
28
  type FileChooserHandle,
@@ -207,6 +208,7 @@ function isAbort(error: unknown): boolean {
207
208
 
208
209
  /** The `Gtk.DialogError` a platform rejection becomes: `AbortError` is the user closing the picker. */
209
210
  function dialogRejection(error: unknown) {
211
+ if (error instanceof GLibError) return error;
210
212
  if (isAbort(error)) return dismissedError();
211
213
  const e = error as { name?: string; message?: string } | null;
212
214
  if (e && typeof e.message === 'string') return dialogFailedError(`${e.name ?? 'Error'}: ${e.message}`);
@@ -316,11 +316,9 @@ export const FileChooserTest = async () => {
316
316
  const { env, subject } = opfsSubject(dir);
317
317
  subject.script({ basename: 'd.txt' });
318
318
  await withEnv(env, async () => {
319
- const save = new Gtk.FileDialog({ initial_name: 'd.txt' }).save as unknown as (
320
- p: unknown,
321
- c: unknown,
322
- ) => Promise<{ replace_contents_async: unknown }>;
323
- await save(null, null);
319
+ const dialog = new Gtk.FileDialog({ initial_name: 'd.txt' });
320
+ // Called on the dialog: a detached `save` has no `this`, which is not what is under test.
321
+ await (dialog.save as unknown as (p: unknown, c: unknown) => Promise<unknown>)(null, null);
324
322
  });
325
323
  } finally {
326
324
  document.createElement = original;
@@ -124,7 +124,9 @@ export const GtkFontDialogButtonTest = async () => {
124
124
  expect(label.style.fontFamily).toBe('');
125
125
  el.useFont = true;
126
126
  expect(label.style.fontWeight).toBe('700');
127
- expect(label.style.fontFamily).toBe('"Cantarell"');
127
+ // Engines differ on serializing a quoted single-identifier family: Firefox keeps
128
+ // the quotes, Chromium drops them. The family name is what matters.
129
+ expect(label.style.fontFamily.replace(/"/g, '')).toBe('Cantarell');
128
130
  // `use-size` is false, so `PANGO_FONT_MASK_SIZE` was cleared and there is no size.
129
131
  expect(label.style.fontSize).toBe('');
130
132
  el.useSize = true;
@@ -185,6 +185,9 @@ export const GtkScrolledWindowTest = async () => {
185
185
  // An unknown nick is the pspec's `automatic`, not a silent never.
186
186
  el.setAttribute('vscrollbar-policy', 'sideways');
187
187
  expect(el.vscrollbarPolicy).toBe('automatic');
188
+ // AUTOMATIC decides from the adjustment, and the viewport was just held at its
189
+ // minimum by NEVER: the re-measure that lifts it is a ResizeObserver delivery.
190
+ await settle();
188
191
  expect(bars(el).vertical.hidden).toBe(false);
189
192
  host.remove();
190
193
  });
@@ -96,6 +96,8 @@ export { GtkToggleButton as ToggleButton } from '../elements/gtk-toggle-button.j
96
96
  export { GtkTreeExpander as TreeExpander } from '../elements/gtk-tree-expander.js';
97
97
  export { GtkVideo as Video } from '../elements/gtk-video.js';
98
98
  export { GtkWindow as Window } from '../elements/gtk-window.js';
99
+ // ADR 0098 Amendment 4: the `Gtk.Window` subset both ports and GJS share, for code that runs on all three.
100
+ export type { WindowCommon } from '@gjsify/adwaita-core';
99
101
  export { GtkWindowControls as WindowControls } from '../elements/gtk-window-controls.js';
100
102
  export { GtkViewport as Viewport } from '../elements/gtk-viewport.js';
101
103
  export { GtkWindowHandle as WindowHandle } from '../elements/gtk-window-handle.js';
@@ -433,8 +433,8 @@ export const AdwNavigationViewTest = async () => {
433
433
  await describe('<adw-navigation-view> GJS-spelled API and declared signals', async () => {
434
434
  await it('push_by_tag and get_visible_page_tag follow the camelCase members', () => {
435
435
  const { adapter, view, host, page } = mountView();
436
- adapter.add(page('root'));
437
- adapter.add(page('detail'));
436
+ adapter.add(page('root'), { tag: 'root' });
437
+ adapter.add(page('detail'), { tag: 'detail' });
438
438
  expect(view.push_by_tag('detail')).toBe(true);
439
439
  expect(view.get_visible_page_tag()).toBe('detail');
440
440
  host.remove();
@@ -442,8 +442,8 @@ export const AdwNavigationViewTest = async () => {
442
442
 
443
443
  await it('connects `pushed` and `notify::visible-page`', () => {
444
444
  const { adapter, view, host, page } = mountView();
445
- adapter.add(page('root'));
446
- adapter.add(page('detail'));
445
+ adapter.add(page('root'), { tag: 'root' });
446
+ adapter.add(page('detail'), { tag: 'detail' });
447
447
  const api = view as unknown as { connect(s: string, h: () => void): number };
448
448
  let pushed = 0;
449
449
  let visible = 0;