@gjsify/adwaita-web 0.45.0 → 0.46.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.
- package/README.md +8 -6
- package/dist/adwaita-web.css +96 -96
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/elements/adw-entry-row.d.ts +2 -2
- package/lib/types/elements/adw-expander-row.d.ts +1 -1
- package/lib/types/elements/adw-split-button.d.ts +1 -1
- package/lib/types/elements/adw-switch-row.d.ts +1 -1
- package/lib/types/elements/adw-wrap-box.d.ts +1 -1
- package/lib/types/elements/{adw-checks.d.ts → checks.d.ts} +9 -2
- package/lib/types/elements/{adw-button.d.ts → gtk-button.d.ts} +1 -1
- package/lib/types/elements/{adw-drop-down.d.ts → gtk-drop-down.d.ts} +6 -6
- package/lib/types/elements/{adw-entry.d.ts → gtk-entry.d.ts} +1 -1
- package/lib/types/elements/{adw-icon.d.ts → gtk-image.d.ts} +2 -2
- package/lib/types/elements/{adw-menu-button.d.ts → gtk-menu-button.d.ts} +13 -4
- package/lib/types/elements/{adw-popover.d.ts → gtk-popover.d.ts} +9 -9
- package/lib/types/elements/{adw-progress-bar.d.ts → gtk-progress-bar.d.ts} +1 -1
- package/lib/types/elements/{adw-switch.d.ts → gtk-switch.d.ts} +2 -2
- package/lib/types/elements/view-switcher-dom.d.ts +4 -4
- package/lib/types/exported-elements.d.ts +10 -0
- package/lib/types/gtk-button.spec.d.ts +1 -0
- package/lib/types/gtk-drop-down.spec.d.ts +1 -0
- package/lib/types/gtk-entry.spec.d.ts +1 -0
- package/lib/types/gtk-image.spec.d.ts +1 -0
- package/lib/types/gtk-menu-button.spec.d.ts +1 -0
- package/lib/types/gtk-progress-bar.spec.d.ts +1 -0
- package/lib/types/gtk-switch.spec.d.ts +1 -0
- package/lib/types/icon-registry.d.ts +2 -2
- package/lib/types/index.d.ts +13 -51
- package/lib/types/namespace/adw.d.ts +44 -0
- package/lib/types/namespace/gtk.d.ts +9 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/package.json +6 -6
- package/scss/_about_dialog.scss +1 -1
- package/scss/_button.scss +4 -4
- package/scss/_checks.scss +6 -6
- package/scss/_drop_down.scss +3 -3
- package/scss/_entry.scss +3 -3
- package/scss/_expander_row.scss +1 -1
- package/scss/_icon.scss +4 -4
- package/scss/_menu_button.scss +3 -3
- package/scss/_popover.scss +2 -2
- package/scss/_progress_bar.scss +4 -4
- package/scss/_reset.scss +10 -8
- package/scss/_split_button.scss +1 -1
- package/scss/_style_classes.scss +9 -9
- package/scss/_switch.scss +2 -2
- package/scss/_switch_row.scss +1 -1
- package/scss/_toast.scss +1 -1
- package/scss/adwaita-skin.scss +2 -2
- package/src/adw-action-rows.spec.ts +2 -2
- package/src/adw-button-content.spec.ts +1 -1
- package/src/bottom-sheet.spec.ts +2 -2
- package/src/{adw-checks.spec.ts → checks.spec.ts} +11 -11
- package/src/chrome.spec.ts +2 -2
- package/src/connect-lifecycle.spec.ts +10 -7
- package/src/elements/adw-about-dialog.ts +6 -6
- package/src/elements/adw-avatar.ts +4 -4
- package/src/elements/adw-button-content.ts +6 -6
- package/src/elements/adw-button-row.ts +6 -6
- package/src/elements/adw-combo-row.ts +1 -1
- package/src/elements/adw-entry-row.ts +5 -5
- package/src/elements/adw-expander-row.ts +10 -10
- package/src/elements/adw-navigation-view.ts +1 -1
- package/src/elements/adw-password-entry-row.ts +3 -3
- package/src/elements/adw-sidebar.ts +4 -4
- package/src/elements/adw-split-button.ts +14 -14
- package/src/elements/adw-status-page.ts +4 -4
- package/src/elements/adw-switch-row.ts +8 -8
- package/src/elements/adw-tab-view.ts +7 -7
- package/src/elements/adw-toast-overlay.ts +2 -2
- package/src/elements/adw-toggle-group.ts +3 -3
- package/src/elements/adw-view-switcher-bar.ts +3 -3
- package/src/elements/adw-view-switcher.ts +3 -3
- package/src/elements/{adw-checks.ts → checks.ts} +13 -6
- package/src/elements/{adw-button.ts → gtk-button.ts} +6 -6
- package/src/elements/{adw-drop-down.ts → gtk-drop-down.ts} +18 -18
- package/src/elements/{adw-entry.ts → gtk-entry.ts} +4 -4
- package/src/elements/{adw-icon.ts → gtk-image.ts} +5 -5
- package/src/elements/{adw-menu-button.ts → gtk-menu-button.ts} +27 -18
- package/src/elements/{adw-popover.ts → gtk-popover.ts} +18 -18
- package/src/elements/{adw-progress-bar.ts → gtk-progress-bar.ts} +5 -5
- package/src/elements/{adw-switch.ts → gtk-switch.ts} +4 -4
- package/src/elements/view-switcher-dom.ts +5 -5
- package/src/exported-elements.ts +50 -0
- package/src/{adw-button.spec.ts → gtk-button.spec.ts} +6 -6
- package/src/{adw-drop-down.spec.ts → gtk-drop-down.spec.ts} +17 -17
- package/src/{adw-entry.spec.ts → gtk-entry.spec.ts} +8 -8
- package/src/{adw-icon.spec.ts → gtk-image.spec.ts} +21 -21
- package/src/{adw-menu-button.spec.ts → gtk-menu-button.spec.ts} +6 -6
- package/src/{adw-progress-bar.spec.ts → gtk-progress-bar.spec.ts} +12 -12
- package/src/{adw-switch.spec.ts → gtk-switch.spec.ts} +20 -20
- package/src/icon-registry.spec.ts +6 -6
- package/src/icon-registry.ts +6 -6
- package/src/index.ts +64 -63
- package/src/namespace/adw.ts +99 -0
- package/src/namespace/gtk.ts +22 -0
- package/src/preferences-search.ts +1 -1
- package/src/slotted-children.spec.ts +5 -3
- package/src/source-view/adw-source-view.ts +2 -2
- package/src/split-button.spec.ts +5 -5
- package/src/styles.generated.ts +1 -1
- package/src/test.browser.mts +15 -15
- package/lib/types/adw-button.spec.d.ts +0 -1
- package/lib/types/adw-drop-down.spec.d.ts +0 -1
- package/lib/types/adw-entry.spec.d.ts +0 -1
- package/lib/types/adw-icon.spec.d.ts +0 -1
- package/lib/types/adw-menu-button.spec.d.ts +0 -1
- package/lib/types/adw-progress-bar.spec.d.ts +0 -1
- package/lib/types/adw-switch.spec.d.ts +0 -1
- /package/lib/types/{adw-checks.spec.d.ts → checks.spec.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DOM-level tests for <
|
|
1
|
+
// DOM-level tests for <gtk-button>'s style classes.
|
|
2
2
|
//
|
|
3
3
|
// The element and its NativeScript twin each kept their own attribute→class table,
|
|
4
4
|
// and the two disagreed: `circular` was here and not there. The table now lives in
|
|
@@ -13,7 +13,7 @@ const WEB_ATTRIBUTES = new Set(['flat', 'suggested', 'destructive', 'circular',
|
|
|
13
13
|
|
|
14
14
|
/** Mount a button carrying the given boolean attributes; return the inner classes. */
|
|
15
15
|
function mountWithStyles(names: readonly string[]): string[] {
|
|
16
|
-
const el = document.createElement('
|
|
16
|
+
const el = document.createElement('gtk-button');
|
|
17
17
|
el.setAttribute('label', 'Click me');
|
|
18
18
|
for (const name of names) el.setAttribute(name, '');
|
|
19
19
|
document.body.appendChild(el);
|
|
@@ -22,10 +22,10 @@ function mountWithStyles(names: readonly string[]): string[] {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function unmountAll(): void {
|
|
25
|
-
for (const el of Array.from(document.querySelectorAll('
|
|
25
|
+
for (const el of Array.from(document.querySelectorAll('gtk-button'))) el.remove();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const
|
|
28
|
+
export const GtkButtonTest = async () => {
|
|
29
29
|
// Rows naming a class the LONG way (`suggested-action`) are the NativeScript
|
|
30
30
|
// variant spelling — this element has no such attribute. They are partitioned
|
|
31
31
|
// out here rather than skipped inside the loop, and the partition is asserted,
|
|
@@ -33,7 +33,7 @@ export const AdwButtonTest = async () => {
|
|
|
33
33
|
const reachable = BUTTON_STYLE_CLASS_VECTORS.filter((v) => v.names.every((n) => WEB_ATTRIBUTES.has(n)));
|
|
34
34
|
const unreachable = BUTTON_STYLE_CLASS_VECTORS.filter((v) => !v.names.every((n) => WEB_ATTRIBUTES.has(n)));
|
|
35
35
|
|
|
36
|
-
await describe('<
|
|
36
|
+
await describe('<gtk-button> style classes', async () => {
|
|
37
37
|
for (const { names, classes, rule } of reachable) {
|
|
38
38
|
await it(`[${names.join(', ')}] → [${classes.join(', ')}] — ${rule}`, () => {
|
|
39
39
|
expect(mountWithStyles(names)).toStrictEqual([...classes]);
|
|
@@ -47,7 +47,7 @@ export const AdwButtonTest = async () => {
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
await it('a style attribute added later is picked up', () => {
|
|
50
|
-
const el = document.createElement('
|
|
50
|
+
const el = document.createElement('gtk-button');
|
|
51
51
|
el.setAttribute('label', 'Send');
|
|
52
52
|
document.body.appendChild(el);
|
|
53
53
|
el.setAttribute('suggested', '');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DOM-level behaviour tests for <
|
|
1
|
+
// DOM-level behaviour tests for <gtk-drop-down>, in a real browser via the
|
|
2
2
|
// @gjsify/adwaita-web browser test axis.
|
|
3
3
|
//
|
|
4
4
|
// The SELECTION half is driven by the SAME table the NativeScript renderer asserts
|
|
@@ -14,21 +14,21 @@ import { describe, it, expect } from '@gjsify/unit';
|
|
|
14
14
|
import { COMBO_SELECTION_VECTORS } from '@gjsify/adwaita-core/conformance';
|
|
15
15
|
import type { ComboSelectionStep, ComboSelectionVector } from '@gjsify/adwaita-core/conformance';
|
|
16
16
|
|
|
17
|
-
import type {
|
|
17
|
+
import type { GtkDropDown } from './elements/gtk-drop-down.js';
|
|
18
18
|
|
|
19
|
-
function makeDropDown():
|
|
20
|
-
const el = document.createElement('
|
|
19
|
+
function makeDropDown(): GtkDropDown {
|
|
20
|
+
const el = document.createElement('gtk-drop-down') as GtkDropDown;
|
|
21
21
|
document.body.appendChild(el);
|
|
22
22
|
return el;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/** The text the closed button shows — the rendered `selectedLabel`. */
|
|
26
|
-
function labelText(dd:
|
|
26
|
+
function labelText(dd: GtkDropDown): string {
|
|
27
27
|
return dd.querySelector('.adw-drop-down-label')?.textContent ?? '';
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/** Open the chooser the way a user does. A no-op over an empty model, as the element guards. */
|
|
31
|
-
function openChooser(dd:
|
|
31
|
+
function openChooser(dd: GtkDropDown): void {
|
|
32
32
|
(dd.querySelector('.adw-drop-down-button') as HTMLButtonElement).click();
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ function openChooser(dd: AdwDropDown): void {
|
|
|
36
36
|
* Replay one vector step against the real element — property sets for the
|
|
37
37
|
* programmatic ops, a popover gesture for the interactive one.
|
|
38
38
|
*/
|
|
39
|
-
function applyStep(dd:
|
|
39
|
+
function applyStep(dd: GtkDropDown, step: ComboSelectionStep): void {
|
|
40
40
|
switch (step.op) {
|
|
41
41
|
case 'setOptions':
|
|
42
42
|
dd.options = step.options;
|
|
@@ -78,15 +78,15 @@ function vectorNamed(name: string): ComboSelectionVector {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/** Mount a drop-down and record every `change` detail it dispatches. */
|
|
81
|
-
function mountRecording(): { dd:
|
|
81
|
+
function mountRecording(): { dd: GtkDropDown; changes: unknown[] } {
|
|
82
82
|
const dd = makeDropDown();
|
|
83
83
|
const changes: unknown[] = [];
|
|
84
84
|
dd.addEventListener('change', (event) => changes.push((event as CustomEvent).detail));
|
|
85
85
|
return { dd, changes };
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
export const
|
|
89
|
-
await describe('
|
|
88
|
+
export const GtkDropDownTest = async () => {
|
|
89
|
+
await describe('gtk-drop-down selection (libadwaita conformance vectors)', async () => {
|
|
90
90
|
for (const vector of COMBO_SELECTION_VECTORS) {
|
|
91
91
|
if (vector.name === DROP_DOWN_REJECTS) continue;
|
|
92
92
|
|
|
@@ -129,7 +129,7 @@ export const AdwDropDownTest = async () => {
|
|
|
129
129
|
});
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
await describe('
|
|
132
|
+
await describe('gtk-drop-down options', async () => {
|
|
133
133
|
await it('accepts a string[] (value === label)', async () => {
|
|
134
134
|
const dd = makeDropDown();
|
|
135
135
|
dd.options = ['One', 'Two', 'Three'];
|
|
@@ -152,7 +152,7 @@ export const AdwDropDownTest = async () => {
|
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
await it('parses options from the JSON attribute', async () => {
|
|
155
|
-
const dd = document.createElement('
|
|
155
|
+
const dd = document.createElement('gtk-drop-down') as GtkDropDown;
|
|
156
156
|
dd.setAttribute('options', '[{"value":"x","label":"Ex"},{"value":"y","label":"Why"}]');
|
|
157
157
|
dd.setAttribute('selected', '1');
|
|
158
158
|
document.body.appendChild(dd);
|
|
@@ -170,7 +170,7 @@ export const AdwDropDownTest = async () => {
|
|
|
170
170
|
});
|
|
171
171
|
});
|
|
172
172
|
|
|
173
|
-
await describe('
|
|
173
|
+
await describe('gtk-drop-down selected ↔ value sync', async () => {
|
|
174
174
|
await it('selectedValue setter finds the index by value', async () => {
|
|
175
175
|
const dd = makeDropDown();
|
|
176
176
|
dd.options = [
|
|
@@ -205,7 +205,7 @@ export const AdwDropDownTest = async () => {
|
|
|
205
205
|
await it('setting options + selected before connect does not crash + applies on connect', async () => {
|
|
206
206
|
// The property setters can run BEFORE connectedCallback builds the DOM, where
|
|
207
207
|
// _updateLabel would touch an undefined label element.
|
|
208
|
-
const dd = document.createElement('
|
|
208
|
+
const dd = document.createElement('gtk-drop-down') as GtkDropDown;
|
|
209
209
|
dd.options = ['a', 'b', 'c'];
|
|
210
210
|
dd.selected = 2;
|
|
211
211
|
expect(dd.isConnected).toBe(false);
|
|
@@ -217,7 +217,7 @@ export const AdwDropDownTest = async () => {
|
|
|
217
217
|
});
|
|
218
218
|
});
|
|
219
219
|
|
|
220
|
-
await describe('
|
|
220
|
+
await describe('gtk-drop-down notify-on-change', async () => {
|
|
221
221
|
await it('a programmatic set fires notify::selected but NOT change (DOM <select> semantics)', async () => {
|
|
222
222
|
const dd = makeDropDown();
|
|
223
223
|
dd.options = ['a', 'b', 'c'];
|
|
@@ -259,7 +259,7 @@ export const AdwDropDownTest = async () => {
|
|
|
259
259
|
});
|
|
260
260
|
});
|
|
261
261
|
|
|
262
|
-
await describe('
|
|
262
|
+
await describe('gtk-drop-down popover behaviour', async () => {
|
|
263
263
|
await it('opens on button click and closes on outside pointerdown', async () => {
|
|
264
264
|
const dd = makeDropDown();
|
|
265
265
|
dd.options = ['a', 'b'];
|
|
@@ -286,7 +286,7 @@ export const AdwDropDownTest = async () => {
|
|
|
286
286
|
});
|
|
287
287
|
});
|
|
288
288
|
|
|
289
|
-
await describe('
|
|
289
|
+
await describe('gtk-drop-down search', async () => {
|
|
290
290
|
await it('renders a search entry and filters the list', async () => {
|
|
291
291
|
const dd = makeDropDown();
|
|
292
292
|
dd.options = ['Apple', 'Banana', 'Cherry'];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DOM-level tests for <
|
|
1
|
+
// DOM-level tests for <gtk-entry>'s length arithmetic.
|
|
2
2
|
//
|
|
3
3
|
// The element had NO max length and no text length, while its NativeScript twin has
|
|
4
4
|
// composed `@gjsify/adwaita-core`'s since it shipped — so the same consumer got a
|
|
@@ -10,22 +10,22 @@
|
|
|
10
10
|
import { describe, expect, it } from '@gjsify/unit';
|
|
11
11
|
import { ENTRY_MAX_LENGTH_VECTORS, ENTRY_TEXT_LENGTH_VECTORS } from '@gjsify/adwaita-core/conformance';
|
|
12
12
|
|
|
13
|
-
import type {
|
|
13
|
+
import type { GtkEntry } from './elements/gtk-entry.js';
|
|
14
14
|
|
|
15
15
|
/** Mount an entry with the given attributes. */
|
|
16
|
-
function mountEntry(attrs: Record<string, string> = {}):
|
|
17
|
-
const entry = document.createElement('
|
|
16
|
+
function mountEntry(attrs: Record<string, string> = {}): GtkEntry {
|
|
17
|
+
const entry = document.createElement('gtk-entry') as GtkEntry;
|
|
18
18
|
for (const [name, value] of Object.entries(attrs)) entry.setAttribute(name, value);
|
|
19
19
|
document.body.appendChild(entry);
|
|
20
20
|
return entry;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function unmountAll(): void {
|
|
24
|
-
for (const entry of Array.from(document.querySelectorAll('
|
|
24
|
+
for (const entry of Array.from(document.querySelectorAll('gtk-entry'))) entry.remove();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export const
|
|
28
|
-
await describe('<
|
|
27
|
+
export const GtkEntryTest = async () => {
|
|
28
|
+
await describe('<gtk-entry> text length', async () => {
|
|
29
29
|
for (const { text, length, rule } of ENTRY_TEXT_LENGTH_VECTORS) {
|
|
30
30
|
await it(`${JSON.stringify(text)} → ${length} — ${rule}`, () => {
|
|
31
31
|
const entry = mountEntry();
|
|
@@ -36,7 +36,7 @@ export const AdwEntryTest = async () => {
|
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
await describe('<
|
|
39
|
+
await describe('<gtk-entry> max length', async () => {
|
|
40
40
|
for (const { text, maxLength, clamped, length, rule } of ENTRY_MAX_LENGTH_VECTORS) {
|
|
41
41
|
await it(`${JSON.stringify(text)} @ ${maxLength} — ${rule}`, () => {
|
|
42
42
|
const entry = mountEntry({ maxlength: String(maxLength) });
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
// DOM-level tests for <
|
|
1
|
+
// DOM-level tests for <gtk-image>, driven by the SAME `normalizeIconName` vectors the
|
|
2
2
|
// core suite asserts against (`@gjsify/adwaita-core/conformance`).
|
|
3
3
|
//
|
|
4
4
|
// The icon-name class must never be built by hand: a name is only usable once it is
|
|
5
5
|
// known to be a SINGLE CSS token, and hand-built spans skipped that check, so
|
|
6
6
|
// `icon-name="a b"` interpolated a stray second class and shipped it through
|
|
7
|
-
// `<
|
|
7
|
+
// `<gtk-menu-button>` for its own icon and for every JSON menu entry's. The vectors run
|
|
8
8
|
// against the ELEMENT, so hand-building the class again fails naming the input.
|
|
9
9
|
import { describe, expect, it } from '@gjsify/unit';
|
|
10
10
|
|
|
11
11
|
import { VIEW_STACK_ICON_NAME_VECTORS } from '@gjsify/adwaita-core/conformance';
|
|
12
12
|
|
|
13
|
-
import type {
|
|
14
|
-
import type {
|
|
13
|
+
import type { GtkImage } from './elements/gtk-image.js';
|
|
14
|
+
import type { GtkMenuButton } from './elements/gtk-menu-button.js';
|
|
15
15
|
|
|
16
16
|
function mount<T extends HTMLElement>(tag: string): { el: T; host: HTMLElement } {
|
|
17
17
|
const host = document.createElement('div');
|
|
@@ -26,11 +26,11 @@ function extraClasses(el: HTMLElement): string[] {
|
|
|
26
26
|
return [...el.classList].filter((c) => c !== 'adw-icon').sort();
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export const
|
|
30
|
-
await describe('<
|
|
29
|
+
export const GtkImageTest = async () => {
|
|
30
|
+
await describe('<gtk-image> mask class (normalizeIconName vectors)', async () => {
|
|
31
31
|
for (const { icon, normalized, rule } of VIEW_STACK_ICON_NAME_VECTORS) {
|
|
32
32
|
await it(`${JSON.stringify(icon)} → ${JSON.stringify(normalized)} — ${rule}`, () => {
|
|
33
|
-
const { el, host } = mount<
|
|
33
|
+
const { el, host } = mount<GtkImage>('gtk-image');
|
|
34
34
|
el.iconName = icon ?? null;
|
|
35
35
|
|
|
36
36
|
expect(el.resolvedIconName).toBe(normalized);
|
|
@@ -51,15 +51,15 @@ export const AdwIconTest = async () => {
|
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
await describe('<
|
|
54
|
+
await describe('<gtk-image> node contract', async () => {
|
|
55
55
|
await it('is decorative — the accessible name belongs to the host control', () => {
|
|
56
|
-
const { el, host } = mount<
|
|
56
|
+
const { el, host } = mount<GtkImage>('gtk-image');
|
|
57
57
|
expect(el.getAttribute('aria-hidden')).toBe('true');
|
|
58
58
|
host.remove();
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
await it('swaps ONLY the mask class, keeping the caller position classes', () => {
|
|
62
|
-
const { el, host } = mount<
|
|
62
|
+
const { el, host } = mount<GtkImage>('gtk-image');
|
|
63
63
|
el.classList.add('adw-drop-down-arrow', 'start');
|
|
64
64
|
el.iconName = 'go-down';
|
|
65
65
|
expect(extraClasses(el)).toStrictEqual(['adw-drop-down-arrow', 'adw-icon--go-down', 'start']);
|
|
@@ -75,7 +75,7 @@ export const AdwIconTest = async () => {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
await it('sizes the box AND the mask together', () => {
|
|
78
|
-
const { el, host } = mount<
|
|
78
|
+
const { el, host } = mount<GtkImage>('gtk-image');
|
|
79
79
|
el.iconName = 'go-next';
|
|
80
80
|
// Unset: the stylesheet's 16px.
|
|
81
81
|
expect(el.size).toBe(null);
|
|
@@ -97,13 +97,13 @@ export const AdwIconTest = async () => {
|
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
await it('paints in the INHERITED colour, not the boundary reset colour', () => {
|
|
100
|
-
// `.adw-icon` masks with `currentColor` and <
|
|
100
|
+
// `.adw-icon` masks with `currentColor` and <gtk-image> is a custom element, so
|
|
101
101
|
// the ADR-0010 `$adw-components` reset re-roots `color` on it: without
|
|
102
102
|
// `color: inherit` in `_icon.scss` every icon repaints in `--window-fg-color`
|
|
103
103
|
// regardless of the button it sits in.
|
|
104
104
|
const { el: box, host } = mount<HTMLElement>('div');
|
|
105
105
|
box.style.color = 'rgb(255, 0, 0)';
|
|
106
|
-
const icon = document.createElement('
|
|
106
|
+
const icon = document.createElement('gtk-image') as GtkImage;
|
|
107
107
|
icon.iconName = 'go-next';
|
|
108
108
|
box.appendChild(icon);
|
|
109
109
|
expect(getComputedStyle(icon).backgroundColor).toBe('rgb(255, 0, 0)');
|
|
@@ -112,8 +112,8 @@ export const AdwIconTest = async () => {
|
|
|
112
112
|
});
|
|
113
113
|
|
|
114
114
|
await describe('the hand-rolled copies are gone', async () => {
|
|
115
|
-
await it('<
|
|
116
|
-
const { el, host } = mount<
|
|
115
|
+
await it('<gtk-menu-button> no longer injects a stray class from its icon-name', () => {
|
|
116
|
+
const { el, host } = mount<GtkMenuButton>('gtk-menu-button');
|
|
117
117
|
el.setAttribute('icon-name', 'a b');
|
|
118
118
|
const icon = el.querySelector('.adw-icon') as HTMLElement;
|
|
119
119
|
// `adw-icon--a b` would have added a second, unrelated `b` class. What it gets
|
|
@@ -122,8 +122,8 @@ export const AdwIconTest = async () => {
|
|
|
122
122
|
host.remove();
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
await it('<
|
|
126
|
-
const { el, host } = mount<
|
|
125
|
+
await it('<gtk-menu-button> menu entries guard their icons too', () => {
|
|
126
|
+
const { el, host } = mount<GtkMenuButton>('gtk-menu-button');
|
|
127
127
|
el.menuItems = [
|
|
128
128
|
{ label: 'Bad', icon: 'a b' },
|
|
129
129
|
{ label: 'Good', icon: 'view-refresh-symbolic' },
|
|
@@ -142,17 +142,17 @@ export const AdwIconTest = async () => {
|
|
|
142
142
|
host.remove();
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
-
await it('every icon in the package is
|
|
145
|
+
await it('every icon in the package is a <gtk-image>', () => {
|
|
146
146
|
// Asserted structurally: a page of every icon-drawing widget, and no bare span
|
|
147
147
|
// carrying the base class — so a new hand-rolled `<span class="adw-icon …">`
|
|
148
148
|
// fails here even when it guards its own name correctly.
|
|
149
149
|
const { el: page, host } = mount<HTMLElement>('div');
|
|
150
150
|
page.innerHTML = `
|
|
151
|
-
<
|
|
151
|
+
<gtk-button icon="go-next" label="Next"></gtk-button>
|
|
152
152
|
<adw-button-row title="Row" start-icon-name="list-add" end-icon-name="go-next"></adw-button-row>
|
|
153
153
|
<adw-status-page icon="folder" title="Empty"></adw-status-page>
|
|
154
154
|
<adw-split-button label="Save" menu='[{"label":"Save As"}]'></adw-split-button>
|
|
155
|
-
<
|
|
155
|
+
<gtk-drop-down options='["a","b"]'></gtk-drop-down>
|
|
156
156
|
<adw-expander-row title="More" show-enable-switch></adw-expander-row>
|
|
157
157
|
<adw-avatar text="Ada" icon="avatar-default"></adw-avatar>
|
|
158
158
|
<adw-toggle-group><adw-toggle icon-name="view-list"></adw-toggle></adw-toggle-group>
|
|
@@ -160,7 +160,7 @@ export const AdwIconTest = async () => {
|
|
|
160
160
|
const bareSpans = [...host.querySelectorAll('span.adw-icon')];
|
|
161
161
|
expect(bareSpans.length).toBe(0);
|
|
162
162
|
// …and the icons really are there, so the check is not vacuous.
|
|
163
|
-
expect(host.querySelectorAll('
|
|
163
|
+
expect(host.querySelectorAll('gtk-image.adw-icon').length > 5).toBe(true);
|
|
164
164
|
host.remove();
|
|
165
165
|
});
|
|
166
166
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DOM-level tests for <
|
|
1
|
+
// DOM-level tests for <gtk-menu-button>'s `menu` attribute.
|
|
2
2
|
//
|
|
3
3
|
// The element parsed the JSON itself, and the copy was weaker than the core parser
|
|
4
4
|
// the split button next to it already used: it kept `id` and `icon` whatever their
|
|
@@ -11,7 +11,7 @@ import { SPLIT_BUTTON_MENU_PARSE_VECTORS } from '@gjsify/adwaita-core/conformanc
|
|
|
11
11
|
|
|
12
12
|
/** Mount a menu button carrying `menu` as JSON, and return its rendered item labels. */
|
|
13
13
|
function mountWithMenu(json: string): { el: HTMLElement; labels: string[] } {
|
|
14
|
-
const el = document.createElement('
|
|
14
|
+
const el = document.createElement('gtk-menu-button');
|
|
15
15
|
el.setAttribute('menu', json);
|
|
16
16
|
document.body.appendChild(el);
|
|
17
17
|
const labels = Array.from(el.querySelectorAll('.adw-popover button')).map((b) => b.textContent?.trim() ?? '');
|
|
@@ -19,11 +19,11 @@ function mountWithMenu(json: string): { el: HTMLElement; labels: string[] } {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function unmountAll(): void {
|
|
22
|
-
for (const el of Array.from(document.querySelectorAll('
|
|
22
|
+
for (const el of Array.from(document.querySelectorAll('gtk-menu-button'))) el.remove();
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const
|
|
26
|
-
await describe('<
|
|
25
|
+
export const GtkMenuButtonTest = async () => {
|
|
26
|
+
await describe('<gtk-menu-button> menu attribute', async () => {
|
|
27
27
|
for (const { json, entries, rule } of SPLIT_BUTTON_MENU_PARSE_VECTORS) {
|
|
28
28
|
await it(`${rule}`, () => {
|
|
29
29
|
const { labels } = mountWithMenu(json ?? '');
|
|
@@ -33,7 +33,7 @@ export const AdwMenuButtonTest = async () => {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
await it('drops a non-string id instead of leaking a number into the event', () => {
|
|
36
|
-
const el = document.createElement('
|
|
36
|
+
const el = document.createElement('gtk-menu-button');
|
|
37
37
|
el.setAttribute('menu', '[{"label":"Open","id":7}]');
|
|
38
38
|
document.body.appendChild(el);
|
|
39
39
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DOM-level tests for <
|
|
1
|
+
// DOM-level tests for <gtk-progress-bar>.
|
|
2
2
|
//
|
|
3
3
|
// Three things matter more than the attribute round-trips: the CLAMP is GLib's
|
|
4
4
|
// (`glibClamp` from `@gjsify/adwaita-core`, not a local `Math.min/max`); a ZERO fraction
|
|
@@ -9,18 +9,18 @@
|
|
|
9
9
|
|
|
10
10
|
import { describe, expect, it } from '@gjsify/unit';
|
|
11
11
|
|
|
12
|
-
import type {
|
|
12
|
+
import type { GtkProgressBar } from './elements/gtk-progress-bar.js';
|
|
13
13
|
|
|
14
|
-
function mount(): { el:
|
|
14
|
+
function mount(): { el: GtkProgressBar; host: HTMLElement } {
|
|
15
15
|
const host = document.createElement('div');
|
|
16
16
|
document.body.appendChild(host);
|
|
17
|
-
const el = document.createElement('
|
|
17
|
+
const el = document.createElement('gtk-progress-bar') as GtkProgressBar;
|
|
18
18
|
host.appendChild(el);
|
|
19
19
|
return { el, host };
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/** The parts, by the markup contract the stylesheet selects on. */
|
|
23
|
-
function parts(bar:
|
|
23
|
+
function parts(bar: GtkProgressBar): { trough: HTMLElement; progress: HTMLElement; text: HTMLElement } {
|
|
24
24
|
return {
|
|
25
25
|
trough: bar.querySelector('.adw-progress-bar-trough') as HTMLElement,
|
|
26
26
|
progress: bar.querySelector('.adw-progress-bar-progress') as HTMLElement,
|
|
@@ -28,8 +28,8 @@ function parts(bar: AdwProgressBar): { trough: HTMLElement; progress: HTMLElemen
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export const
|
|
32
|
-
await describe('<
|
|
31
|
+
export const GtkProgressBarTest = async () => {
|
|
32
|
+
await describe('<gtk-progress-bar> fraction', async () => {
|
|
33
33
|
await it('starts empty, with the trough flagged so the indicator disappears', () => {
|
|
34
34
|
const { el, host } = mount();
|
|
35
35
|
const { trough, progress } = parts(el);
|
|
@@ -68,7 +68,7 @@ export const AdwProgressBarTest = async () => {
|
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
await describe('<
|
|
71
|
+
await describe('<gtk-progress-bar> indeterminate', async () => {
|
|
72
72
|
await it('pulse() enters the pulsing state and drops aria-valuenow', () => {
|
|
73
73
|
const { el, host } = mount();
|
|
74
74
|
el.fraction = 0.4;
|
|
@@ -98,7 +98,7 @@ export const AdwProgressBarTest = async () => {
|
|
|
98
98
|
});
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
await describe('<
|
|
101
|
+
await describe('<gtk-progress-bar> text', async () => {
|
|
102
102
|
await it('hides the text node until show-text, then shows the percentage', () => {
|
|
103
103
|
const { el, host } = mount();
|
|
104
104
|
expect(parts(el).text.hidden).toBe(true);
|
|
@@ -134,7 +134,7 @@ export const AdwProgressBarTest = async () => {
|
|
|
134
134
|
});
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
await describe('<
|
|
137
|
+
await describe('<gtk-progress-bar> variants', async () => {
|
|
138
138
|
await it('is an 8px trough by default and a 2px hairline with osd', () => {
|
|
139
139
|
// The 8px is libadwaita's (_progress-bar.scss) and the 2px is its
|
|
140
140
|
// `.osd` variant — NOT the vendored web port's 6px, which
|
|
@@ -148,8 +148,8 @@ export const AdwProgressBarTest = async () => {
|
|
|
148
148
|
// transition to be part-way through.
|
|
149
149
|
const host = document.createElement('div');
|
|
150
150
|
document.body.appendChild(host);
|
|
151
|
-
const plain = document.createElement('
|
|
152
|
-
const osd = document.createElement('
|
|
151
|
+
const plain = document.createElement('gtk-progress-bar') as GtkProgressBar;
|
|
152
|
+
const osd = document.createElement('gtk-progress-bar') as GtkProgressBar;
|
|
153
153
|
osd.setAttribute('osd', '');
|
|
154
154
|
host.append(plain, osd);
|
|
155
155
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DOM-level tests for <
|
|
1
|
+
// DOM-level tests for <gtk-switch>, plus the proof that both <adw-switch-row> and
|
|
2
2
|
// <adw-expander-row> still work now that the switch is lifted out of them. Two
|
|
3
3
|
// invariants:
|
|
4
4
|
//
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { describe, expect, it } from '@gjsify/unit';
|
|
13
13
|
|
|
14
14
|
import type { AdwExpanderRow } from './elements/adw-expander-row.js';
|
|
15
|
-
import type {
|
|
15
|
+
import type { GtkSwitch } from './elements/gtk-switch.js';
|
|
16
16
|
import type { AdwSwitchRow } from './elements/adw-switch-row.js';
|
|
17
17
|
|
|
18
18
|
function mount<T extends HTMLElement>(tag: string): { el: T; host: HTMLElement } {
|
|
@@ -31,7 +31,7 @@ function record(el: HTMLElement, event: string): unknown[] {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/** The switch's own parts, by the markup contract the stylesheet selects on. */
|
|
34
|
-
function parts(sw:
|
|
34
|
+
function parts(sw: GtkSwitch): { input: HTMLInputElement; slider: HTMLElement } {
|
|
35
35
|
return {
|
|
36
36
|
input: sw.querySelector('input[type="checkbox"]') as HTMLInputElement,
|
|
37
37
|
slider: sw.querySelector('.adw-switch-slider') as HTMLElement,
|
|
@@ -45,10 +45,10 @@ function measure(sw: HTMLElement): { width: string; height: string; radius: stri
|
|
|
45
45
|
return { width: box.width, height: box.height, radius: slider.borderTopLeftRadius };
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export const
|
|
49
|
-
await describe('<
|
|
48
|
+
export const GtkSwitchTest = async () => {
|
|
49
|
+
await describe('<gtk-switch> state', async () => {
|
|
50
50
|
await it('starts off and builds the input + slider markup', () => {
|
|
51
|
-
const { el, host } = mount<
|
|
51
|
+
const { el, host } = mount<GtkSwitch>('gtk-switch');
|
|
52
52
|
const { input, slider } = parts(el);
|
|
53
53
|
expect(el.active).toBe(false);
|
|
54
54
|
expect(input).toBeTruthy();
|
|
@@ -63,7 +63,7 @@ export const AdwSwitchTest = async () => {
|
|
|
63
63
|
await it('adopts a declarative active attribute without emitting', () => {
|
|
64
64
|
const host = document.createElement('div');
|
|
65
65
|
document.body.appendChild(host);
|
|
66
|
-
const el = document.createElement('
|
|
66
|
+
const el = document.createElement('gtk-switch') as GtkSwitch;
|
|
67
67
|
el.setAttribute('active', '');
|
|
68
68
|
const events = record(el, 'notify::active');
|
|
69
69
|
host.appendChild(el);
|
|
@@ -74,7 +74,7 @@ export const AdwSwitchTest = async () => {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
await it('a programmatic set notifies, and re-setting the same value does not', () => {
|
|
77
|
-
const { el, host } = mount<
|
|
77
|
+
const { el, host } = mount<GtkSwitch>('gtk-switch');
|
|
78
78
|
const events = record(el, 'notify::active');
|
|
79
79
|
el.active = true;
|
|
80
80
|
expect(events).toStrictEqual([{ active: true }]);
|
|
@@ -87,7 +87,7 @@ export const AdwSwitchTest = async () => {
|
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
await it('a click on the track toggles exactly once', () => {
|
|
90
|
-
const { el, host } = mount<
|
|
90
|
+
const { el, host } = mount<GtkSwitch>('gtk-switch');
|
|
91
91
|
const events = record(el, 'notify::active');
|
|
92
92
|
parts(el).slider.click();
|
|
93
93
|
expect(el.active).toBe(true);
|
|
@@ -100,7 +100,7 @@ export const AdwSwitchTest = async () => {
|
|
|
100
100
|
// The checkbox is 0×0, so a pointer never reaches it — but keyboard
|
|
101
101
|
// activation and `input.click()` do, and the track listener must not
|
|
102
102
|
// toggle a second time on the way out.
|
|
103
|
-
const { el, host } = mount<
|
|
103
|
+
const { el, host } = mount<GtkSwitch>('gtk-switch');
|
|
104
104
|
const events = record(el, 'notify::active');
|
|
105
105
|
parts(el).input.click();
|
|
106
106
|
expect(el.active).toBe(true);
|
|
@@ -109,7 +109,7 @@ export const AdwSwitchTest = async () => {
|
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
await it('a disabled switch does not toggle', () => {
|
|
112
|
-
const { el, host } = mount<
|
|
112
|
+
const { el, host } = mount<GtkSwitch>('gtk-switch');
|
|
113
113
|
el.disabled = true;
|
|
114
114
|
const events = record(el, 'notify::active');
|
|
115
115
|
parts(el).slider.click();
|
|
@@ -125,11 +125,11 @@ export const AdwSwitchTest = async () => {
|
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
await describe('<adw-switch-row> still toggles and emits through <
|
|
128
|
+
await describe('<adw-switch-row> still toggles and emits through <gtk-switch>', async () => {
|
|
129
129
|
await it('a programmatic row.active drives the switch and emits once', () => {
|
|
130
130
|
const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
|
|
131
131
|
const events = record(row, 'notify::active');
|
|
132
|
-
const sw = row.querySelector('
|
|
132
|
+
const sw = row.querySelector('gtk-switch') as GtkSwitch;
|
|
133
133
|
expect(sw).toBeTruthy();
|
|
134
134
|
|
|
135
135
|
row.active = true;
|
|
@@ -148,7 +148,7 @@ export const AdwSwitchTest = async () => {
|
|
|
148
148
|
const events = record(row, 'notify::active');
|
|
149
149
|
row.click();
|
|
150
150
|
expect(row.active).toBe(true);
|
|
151
|
-
expect((row.querySelector('
|
|
151
|
+
expect((row.querySelector('gtk-switch') as GtkSwitch).active).toBe(true);
|
|
152
152
|
expect(events.length).toBe(1);
|
|
153
153
|
host.remove();
|
|
154
154
|
});
|
|
@@ -156,7 +156,7 @@ export const AdwSwitchTest = async () => {
|
|
|
156
156
|
await it('a click on the switch toggles the row once, not twice', () => {
|
|
157
157
|
const { el: row, host } = mount<AdwSwitchRow>('adw-switch-row');
|
|
158
158
|
const events = record(row, 'notify::active');
|
|
159
|
-
const sw = row.querySelector('
|
|
159
|
+
const sw = row.querySelector('gtk-switch') as GtkSwitch;
|
|
160
160
|
parts(sw).slider.click();
|
|
161
161
|
expect(row.active).toBe(true);
|
|
162
162
|
expect(events.length).toBe(1);
|
|
@@ -169,7 +169,7 @@ export const AdwSwitchTest = async () => {
|
|
|
169
169
|
const { el: row, host } = mount<AdwExpanderRow>('adw-expander-row');
|
|
170
170
|
row.setAttribute('show-enable-switch', '');
|
|
171
171
|
const events = record(row, 'notify::enable-expansion');
|
|
172
|
-
const sw = row.querySelector('
|
|
172
|
+
const sw = row.querySelector('gtk-switch') as GtkSwitch;
|
|
173
173
|
expect(sw.active).toBe(true); // enable-expansion defaults to true
|
|
174
174
|
|
|
175
175
|
parts(sw).slider.click();
|
|
@@ -191,7 +191,7 @@ export const AdwSwitchTest = async () => {
|
|
|
191
191
|
|
|
192
192
|
row.enableExpansion = false;
|
|
193
193
|
|
|
194
|
-
expect((row.querySelector('
|
|
194
|
+
expect((row.querySelector('gtk-switch') as GtkSwitch).active).toBe(false);
|
|
195
195
|
expect(enableEvents.length).toBe(0);
|
|
196
196
|
// The switch's own notify never escapes the row either.
|
|
197
197
|
expect(activeEvents.length).toBe(0);
|
|
@@ -201,7 +201,7 @@ export const AdwSwitchTest = async () => {
|
|
|
201
201
|
await it('a click on the enable switch does not disclose the row', () => {
|
|
202
202
|
const { el: row, host } = mount<AdwExpanderRow>('adw-expander-row');
|
|
203
203
|
row.setAttribute('show-enable-switch', '');
|
|
204
|
-
const sw = row.querySelector('
|
|
204
|
+
const sw = row.querySelector('gtk-switch') as GtkSwitch;
|
|
205
205
|
|
|
206
206
|
parts(sw).slider.click();
|
|
207
207
|
expect(row.expanded).toBe(false);
|
|
@@ -218,8 +218,8 @@ export const AdwSwitchTest = async () => {
|
|
|
218
218
|
const { el: expander, host: expanderHost } = mount<AdwExpanderRow>('adw-expander-row');
|
|
219
219
|
expander.setAttribute('show-enable-switch', '');
|
|
220
220
|
|
|
221
|
-
const rowBox = measure(row.querySelector('
|
|
222
|
-
const expanderBox = measure(expander.querySelector('
|
|
221
|
+
const rowBox = measure(row.querySelector('gtk-switch') as HTMLElement);
|
|
222
|
+
const expanderBox = measure(expander.querySelector('gtk-switch') as HTMLElement);
|
|
223
223
|
|
|
224
224
|
expect(rowBox).toStrictEqual(expanderBox);
|
|
225
225
|
// Pin the actual numbers too, so "both unstyled" cannot pass as
|