@gjsify/adwaita-web 0.30.0 → 0.32.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/dist/adwaita-web.css +786 -272
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/adw-about-dialog.spec.d.ts +1 -0
- package/lib/types/adw-action-rows.spec.d.ts +1 -0
- package/lib/types/adw-avatar.spec.d.ts +1 -0
- package/lib/types/adw-banner.spec.d.ts +1 -0
- package/lib/types/adw-button-content.spec.d.ts +1 -0
- package/lib/types/adw-carousel.spec.d.ts +1 -0
- package/lib/types/adw-checks.spec.d.ts +1 -0
- package/lib/types/adw-header-bar.spec.d.ts +1 -0
- package/lib/types/adw-icon.spec.d.ts +1 -0
- package/lib/types/adw-progress-bar.spec.d.ts +1 -0
- package/lib/types/adw-sidebar.spec.d.ts +1 -0
- package/lib/types/adw-switch.spec.d.ts +1 -0
- package/lib/types/adw-wrap-box.spec.d.ts +1 -0
- package/lib/types/bottom-sheet.spec.d.ts +1 -0
- package/lib/types/breakpoints.d.ts +22 -0
- package/lib/types/breakpoints.spec.d.ts +1 -0
- package/lib/types/chrome.spec.d.ts +1 -0
- package/lib/types/elements/adw-about-dialog.d.ts +47 -8
- package/lib/types/elements/adw-action-row.d.ts +35 -0
- package/lib/types/elements/adw-avatar.d.ts +11 -0
- package/lib/types/elements/adw-bottom-sheet.d.ts +33 -4
- package/lib/types/elements/adw-button-content.d.ts +12 -0
- package/lib/types/elements/adw-button-row.d.ts +10 -1
- package/lib/types/elements/adw-carousel.d.ts +111 -8
- package/lib/types/elements/adw-checks.d.ts +57 -0
- package/lib/types/elements/adw-clamp.d.ts +4 -1
- package/lib/types/elements/adw-data-grid.d.ts +11 -31
- package/lib/types/elements/adw-drop-down.d.ts +17 -20
- package/lib/types/elements/adw-entry-row.d.ts +93 -3
- package/lib/types/elements/adw-expander-row.d.ts +7 -1
- package/lib/types/elements/adw-header-bar.d.ts +15 -0
- package/lib/types/elements/adw-icon.d.ts +25 -0
- package/lib/types/elements/adw-inline-view-switcher.d.ts +37 -11
- package/lib/types/elements/adw-menu-button.d.ts +6 -6
- package/lib/types/elements/adw-navigation-split-view.d.ts +6 -0
- package/lib/types/elements/adw-navigation-view.d.ts +63 -20
- package/lib/types/elements/adw-overlay-split-view.d.ts +38 -0
- package/lib/types/elements/adw-password-entry-row.d.ts +19 -10
- package/lib/types/elements/adw-popover.d.ts +58 -0
- package/lib/types/elements/adw-preferences-dialog.d.ts +57 -2
- package/lib/types/elements/adw-preferences-group.d.ts +31 -0
- package/lib/types/elements/adw-progress-bar.d.ts +38 -0
- package/lib/types/elements/adw-sidebar.d.ts +37 -5
- package/lib/types/elements/adw-split-button.d.ts +53 -7
- package/lib/types/elements/adw-switch-row.d.ts +11 -2
- package/lib/types/elements/adw-switch.d.ts +15 -0
- package/lib/types/elements/adw-tab-view.d.ts +129 -12
- package/lib/types/elements/adw-toolbar-view.d.ts +5 -0
- package/lib/types/elements/adw-view-stack.d.ts +27 -19
- package/lib/types/elements/adw-view-switcher-bar.d.ts +23 -7
- package/lib/types/elements/adw-view-switcher.d.ts +22 -11
- package/lib/types/elements/adw-window-title.d.ts +3 -1
- package/lib/types/elements/view-switcher-dom.d.ts +44 -0
- package/lib/types/entry-rows.spec.d.ts +1 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/navigation-view.spec.d.ts +1 -0
- package/lib/types/preferences-search.d.ts +20 -0
- package/lib/types/preferences.spec.d.ts +1 -0
- package/lib/types/split-button.spec.d.ts +1 -0
- package/lib/types/split-views.spec.d.ts +1 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/lib/types/tab-view.spec.d.ts +1 -0
- package/lib/types/view-stack.spec.d.ts +1 -0
- package/lib/types/view-switcher.spec.d.ts +1 -0
- package/package.json +6 -6
- package/scss/_banner.scss +13 -0
- package/scss/_bottom_sheet.scss +5 -6
- package/scss/_button.scss +3 -26
- package/scss/_button_content.scss +28 -0
- package/scss/_checks.scss +228 -0
- package/scss/_clamp.scss +9 -3
- package/scss/_data_grid.scss +15 -7
- package/scss/_drop_down.scss +12 -55
- package/scss/_expander_row.scss +5 -50
- package/scss/_icon.scss +51 -0
- package/scss/_icons.generated.scss +6 -0
- package/scss/_inline_view_switcher.scss +34 -0
- package/scss/_labels.scss +135 -0
- package/scss/_menu_button.scss +10 -70
- package/scss/_popover.scss +186 -0
- package/scss/_preferences.scss +29 -0
- package/scss/_preferences_dialog.scss +17 -0
- package/scss/_progress_bar.scss +161 -0
- package/scss/_reset.scss +18 -7
- package/scss/_spinner.scss +7 -3
- package/scss/_split_button.scss +6 -50
- package/scss/_switch.scss +90 -0
- package/scss/_switch_row.scss +6 -52
- package/scss/_tab_view.scss +64 -0
- package/scss/_theme.scss +10 -0
- package/scss/_toolbar_view.scss +74 -0
- package/scss/_variables.scss +34 -0
- package/scss/_view_switcher.scss +40 -0
- package/scss/_view_switcher_bar.scss +37 -0
- package/scss/_wrap_box.scss +56 -6
- package/scss/adwaita-skin.scss +23 -0
- package/src/adw-about-dialog.spec.ts +350 -0
- package/src/adw-action-rows.spec.ts +342 -0
- package/src/adw-avatar.spec.ts +139 -0
- package/src/adw-banner.spec.ts +152 -0
- package/src/adw-button-content.spec.ts +183 -0
- package/src/adw-button-row.spec.ts +12 -6
- package/src/adw-carousel.spec.ts +389 -0
- package/src/adw-checks.spec.ts +368 -0
- package/src/adw-drop-down.spec.ts +123 -0
- package/src/adw-header-bar.spec.ts +83 -0
- package/src/adw-icon.spec.ts +167 -0
- package/src/adw-progress-bar.spec.ts +173 -0
- package/src/adw-sidebar.spec.ts +332 -0
- package/src/adw-switch.spec.ts +242 -0
- package/src/adw-tab-view.spec.ts +12 -3
- package/src/adw-view-switcher-bar.spec.ts +61 -13
- package/src/adw-wrap-box.spec.ts +194 -0
- package/src/bottom-sheet.spec.ts +325 -0
- package/src/breakpoints.spec.ts +147 -0
- package/src/breakpoints.ts +67 -0
- package/src/chrome.spec.ts +301 -0
- package/src/elements/adw-about-dialog.ts +223 -163
- package/src/elements/adw-action-row.ts +120 -10
- package/src/elements/adw-avatar.ts +48 -54
- package/src/elements/adw-banner.ts +46 -10
- package/src/elements/adw-bottom-sheet.ts +145 -60
- package/src/elements/adw-button-content.ts +107 -33
- package/src/elements/adw-button-row.ts +61 -37
- package/src/elements/adw-button.ts +5 -7
- package/src/elements/adw-carousel.ts +467 -105
- package/src/elements/adw-checks.ts +299 -0
- package/src/elements/adw-clamp.ts +80 -10
- package/src/elements/adw-combo-row.ts +15 -7
- package/src/elements/adw-data-grid.ts +43 -91
- package/src/elements/adw-drop-down.ts +117 -128
- package/src/elements/adw-entry-row.ts +404 -36
- package/src/elements/adw-expander-row.ts +61 -29
- package/src/elements/adw-header-bar.ts +31 -6
- package/src/elements/adw-icon.ts +148 -0
- package/src/elements/adw-inline-view-switcher.ts +240 -129
- package/src/elements/adw-menu-button.ts +93 -70
- package/src/elements/adw-navigation-split-view.ts +48 -7
- package/src/elements/adw-navigation-view.ts +286 -148
- package/src/elements/adw-overlay-split-view.ts +164 -14
- package/src/elements/adw-password-entry-row.ts +111 -89
- package/src/elements/adw-popover.ts +283 -0
- package/src/elements/adw-preferences-dialog.ts +120 -21
- package/src/elements/adw-preferences-group.ts +128 -22
- package/src/elements/adw-progress-bar.ts +189 -0
- package/src/elements/adw-sidebar.ts +301 -142
- package/src/elements/adw-spin-row.ts +11 -5
- package/src/elements/adw-spinner.ts +23 -8
- package/src/elements/adw-split-button.ts +371 -92
- package/src/elements/adw-status-page.ts +9 -9
- package/src/elements/adw-switch-row.ts +100 -30
- package/src/elements/adw-switch.ts +129 -0
- package/src/elements/adw-tab-view.ts +682 -129
- package/src/elements/adw-toggle-group.ts +5 -7
- package/src/elements/adw-toolbar-view.ts +84 -21
- package/src/elements/adw-view-stack.ts +162 -85
- package/src/elements/adw-view-switcher-bar.ts +163 -81
- package/src/elements/adw-view-switcher.ts +231 -112
- package/src/elements/adw-window-title.ts +44 -11
- package/src/elements/adw-wrap-box.ts +131 -35
- package/src/elements/view-switcher-dom.ts +108 -0
- package/src/entry-rows.spec.ts +391 -0
- package/src/index.ts +23 -0
- package/src/navigation-view.spec.ts +435 -0
- package/src/preferences-search.ts +135 -0
- package/src/preferences.spec.ts +250 -0
- package/src/source-view/adw-source-view.ts +2 -5
- package/src/split-button.spec.ts +470 -0
- package/src/split-views.spec.ts +309 -0
- package/src/styles.generated.ts +1 -1
- package/src/tab-view.spec.ts +451 -0
- package/src/test.browser.mts +49 -0
- package/src/view-stack.spec.ts +272 -0
- package/src/view-switcher.spec.ts +446 -0
|
@@ -8,6 +8,16 @@ export class AdwHeaderBar extends HTMLElement {
|
|
|
8
8
|
private _startEl: HTMLDivElement | null = null;
|
|
9
9
|
private _centerEl: HTMLDivElement | null = null;
|
|
10
10
|
private _endEl: HTMLDivElement | null = null;
|
|
11
|
+
/**
|
|
12
|
+
* The generated title span, or `null` when a `slot="center"` title-widget
|
|
13
|
+
* took the centre. `Adw.HeaderBar` has the same either/or: setting
|
|
14
|
+
* `title-widget` replaces the derived `AdwWindowTitle` outright.
|
|
15
|
+
*/
|
|
16
|
+
private _titleEl: HTMLSpanElement | null = null;
|
|
17
|
+
|
|
18
|
+
static get observedAttributes() {
|
|
19
|
+
return ['title'];
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
/** The start (left) section container — append buttons/widgets here. */
|
|
13
23
|
get startSection(): HTMLDivElement | null {
|
|
@@ -29,8 +39,6 @@ export class AdwHeaderBar extends HTMLElement {
|
|
|
29
39
|
if (this._initialized) return;
|
|
30
40
|
this._initialized = true;
|
|
31
41
|
|
|
32
|
-
const title = this.getAttribute('title') || '';
|
|
33
|
-
|
|
34
42
|
// Capture any pre-existing slotted children before clearing
|
|
35
43
|
const startChildren = Array.from(this.querySelectorAll(':scope > [slot="start"]'));
|
|
36
44
|
const centerChildren = Array.from(this.querySelectorAll(':scope > [slot="center"]'));
|
|
@@ -48,10 +56,9 @@ export class AdwHeaderBar extends HTMLElement {
|
|
|
48
56
|
if (centerChildren.length > 0) {
|
|
49
57
|
for (const child of centerChildren) this._centerEl.appendChild(child);
|
|
50
58
|
} else {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this._centerEl.appendChild(titleEl);
|
|
59
|
+
this._titleEl = document.createElement('span');
|
|
60
|
+
this._titleEl.className = 'adw-header-bar-title';
|
|
61
|
+
this._centerEl.appendChild(this._titleEl);
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
// End section
|
|
@@ -61,6 +68,24 @@ export class AdwHeaderBar extends HTMLElement {
|
|
|
61
68
|
|
|
62
69
|
// Replace all children atomically
|
|
63
70
|
this.replaceChildren(this._startEl, this._centerEl, this._endEl);
|
|
71
|
+
this._renderTitle();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* `title` used to be read ONCE, in `connectedCallback`, so every later write
|
|
76
|
+
* was a silent no-op — a header bar whose title tracked the open document
|
|
77
|
+
* kept whatever it was created with. `Adw.HeaderBar`'s derived title widget
|
|
78
|
+
* is bound to the property and re-renders on every change.
|
|
79
|
+
*/
|
|
80
|
+
attributeChangedCallback(name: string) {
|
|
81
|
+
if (this._initialized && name === 'title') this._renderTitle();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private _renderTitle() {
|
|
85
|
+
// A `slot="center"` widget replaced the derived title, so there is
|
|
86
|
+
// nothing for the attribute to write to — the same either/or as
|
|
87
|
+
// `Adw.HeaderBar:title-widget`.
|
|
88
|
+
if (this._titleEl) this._titleEl.textContent = this.getAttribute('title') ?? '';
|
|
64
89
|
}
|
|
65
90
|
}
|
|
66
91
|
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// <adw-icon> — the symbolic icon node, as an element instead of a shape you
|
|
2
|
+
// retype. Every icon in this package is a CSS-masked box whose glyph comes from
|
|
3
|
+
// a generated `.adw-icon--<name>` class and whose colour is `currentColor`, so
|
|
4
|
+
// it themes with whatever contains it.
|
|
5
|
+
//
|
|
6
|
+
// WHY IT EXISTS: `<span class="adw-icon adw-icon--<name>" aria-hidden="true">`
|
|
7
|
+
// was built by hand at TWENTY-THREE sites across SEVENTEEN files, NINE of which
|
|
8
|
+
// re-derived the name (`name.replace(/-symbolic$/, '')`) on the spot — one of
|
|
9
|
+
// them unanchored. Exactly ONE site (`<adw-split-button>`) also checked the
|
|
10
|
+
// result was a single CSS token. The others did not, so `icon-name="a b"`
|
|
11
|
+
// interpolated into `class="adw-icon adw-icon--a b"` and shipped a stray `b`
|
|
12
|
+
// class; that was live on `<adw-menu-button>`, for its own icon and for every
|
|
13
|
+
// JSON menu entry's. The derivation now happens once, in
|
|
14
|
+
// `@gjsify/adwaita-core`'s {@link normalizeIconName} (guard included), and the
|
|
15
|
+
// markup happens once, here.
|
|
16
|
+
//
|
|
17
|
+
// Attributes:
|
|
18
|
+
// icon-name — symbolic name, with or without the `-symbolic` suffix. A name
|
|
19
|
+
// that is not a single CSS token (a space, a quote, a
|
|
20
|
+
// reverse-DNS application id) resolves to NO icon rather than to
|
|
21
|
+
// injected markup — see `normalizeIconName`.
|
|
22
|
+
// size — the rendered edge length in px. Absent leaves the stylesheet's
|
|
23
|
+
// 16px in charge; a context that sizes its own icons through CSS
|
|
24
|
+
// (`.adw-about-dialog-icon`, the split button's 14px arrows) keeps
|
|
25
|
+
// doing exactly that and should NOT set this.
|
|
26
|
+
// Properties:
|
|
27
|
+
// iconName — the declared name (get/set; reflects to the attribute).
|
|
28
|
+
// resolvedIconName — what actually reached the mask class ('' = no icon).
|
|
29
|
+
// size — the px size, or null when the stylesheet decides (get/set).
|
|
30
|
+
//
|
|
31
|
+
// THE ELEMENT *IS* THE ICON BOX — it carries `.adw-icon` itself rather than
|
|
32
|
+
// wrapping a span. A wrapper would have inserted a layout node into flex rows,
|
|
33
|
+
// button interiors and absolutely-positioned arrows that were all measured
|
|
34
|
+
// against the icon box directly; carrying the class keeps every existing
|
|
35
|
+
// class-scoped rule (`.adw-drop-down-arrow`, `.adw-tab-icon`, `.adw-row-edit`, …)
|
|
36
|
+
// matching the same node it always matched.
|
|
37
|
+
//
|
|
38
|
+
// Reference: refs/libadwaita/src/stylesheet/_common.scss:34-41 — `.normal-icons`
|
|
39
|
+
// / `.large-icons` set `-gtk-icon-size`; libadwaita has NO `_icon.scss`, the
|
|
40
|
+
// icon is a GtkImage and its size is a GTK property, not a stylesheet rule.
|
|
41
|
+
// Reference: refs/adwaita-web/adwaita-web/scss/_icon.scss — the vendored web
|
|
42
|
+
// port's `.adw-icon` (an inline-flex SVG holder; this package masks instead).
|
|
43
|
+
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
44
|
+
// Copyright (c) 2025 csm (adwaita-web). MIT License.
|
|
45
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the
|
|
46
|
+
// name derivation composed from @gjsify/adwaita-core.
|
|
47
|
+
|
|
48
|
+
import { normalizeIconName } from '@gjsify/adwaita-core';
|
|
49
|
+
|
|
50
|
+
/** The generated mask-class prefix — the one place the `--` spelling appears. */
|
|
51
|
+
const MASK_CLASS_PREFIX = 'adw-icon--';
|
|
52
|
+
|
|
53
|
+
export class AdwIcon extends HTMLElement {
|
|
54
|
+
static get observedAttributes() {
|
|
55
|
+
return ['icon-name', 'size'];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The declared symbolic name, `-symbolic` suffix optional. */
|
|
59
|
+
get iconName(): string {
|
|
60
|
+
return this.getAttribute('icon-name') ?? '';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
set iconName(value: string | null) {
|
|
64
|
+
if (value === null) this.removeAttribute('icon-name');
|
|
65
|
+
else this.setAttribute('icon-name', value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The name that actually reached the mask class — `''` when the icon-name is
|
|
70
|
+
* absent, empty, or not usable as one CSS token. Consumers that need to know
|
|
71
|
+
* whether an icon is being drawn ask this, not the raw attribute.
|
|
72
|
+
*/
|
|
73
|
+
get resolvedIconName(): string {
|
|
74
|
+
return normalizeIconName(this.getAttribute('icon-name'));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** The rendered edge length in px, or `null` when the stylesheet decides. */
|
|
78
|
+
get size(): number | null {
|
|
79
|
+
const declared = Number.parseFloat(this.getAttribute('size') ?? '');
|
|
80
|
+
return Number.isFinite(declared) && declared > 0 ? declared : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
set size(value: number | null) {
|
|
84
|
+
if (value === null) this.removeAttribute('size');
|
|
85
|
+
else this.setAttribute('size', String(value));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
connectedCallback() {
|
|
89
|
+
this._render();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
attributeChangedCallback() {
|
|
93
|
+
this._render();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ── internals ──────────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
private _render(): void {
|
|
99
|
+
this.classList.add('adw-icon');
|
|
100
|
+
|
|
101
|
+
// Swap ONLY the mask class: the callers put their own positioning class
|
|
102
|
+
// on the same node (`adw-drop-down-arrow`, `adw-sidebar-item-arrow`, …),
|
|
103
|
+
// and a `className =` assignment here would take those with it. The list
|
|
104
|
+
// is collected BEFORE removing — `classList` is live, so removing while
|
|
105
|
+
// iterating it would skip the entry after each hit.
|
|
106
|
+
const stale = [...this.classList].filter((existing) => existing.startsWith(MASK_CLASS_PREFIX));
|
|
107
|
+
this.classList.remove(...stale);
|
|
108
|
+
const name = this.resolvedIconName;
|
|
109
|
+
if (name !== '') this.classList.add(`${MASK_CLASS_PREFIX}${name}`);
|
|
110
|
+
|
|
111
|
+
// A masked box has no text, so assistive tech has nothing to announce —
|
|
112
|
+
// the accessible name belongs to the control that HOSTS the icon. Every
|
|
113
|
+
// hand-rolled copy that thought about it said the same thing; the ones
|
|
114
|
+
// that did not were the inconsistency, not the intent.
|
|
115
|
+
this.setAttribute('aria-hidden', 'true');
|
|
116
|
+
|
|
117
|
+
const size = this.size;
|
|
118
|
+
if (size === null) {
|
|
119
|
+
this.style.removeProperty('width');
|
|
120
|
+
this.style.removeProperty('height');
|
|
121
|
+
this.style.removeProperty('mask-size');
|
|
122
|
+
this.style.removeProperty('-webkit-mask-size');
|
|
123
|
+
} else {
|
|
124
|
+
const px = `${size}px`;
|
|
125
|
+
this.style.width = px;
|
|
126
|
+
this.style.height = px;
|
|
127
|
+
// The box and the mask scale together — sizing only the box leaves a
|
|
128
|
+
// 16px glyph floating in the middle of it.
|
|
129
|
+
this.style.setProperty('mask-size', px);
|
|
130
|
+
this.style.setProperty('-webkit-mask-size', px);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Build one icon node: the three lines every caller would otherwise write.
|
|
137
|
+
*
|
|
138
|
+
* `extraClasses` are the caller's own positioning/context classes, added
|
|
139
|
+
* alongside the managed `.adw-icon` + mask class rather than replacing them.
|
|
140
|
+
*/
|
|
141
|
+
export function createAdwIcon(iconName: string | null, ...extraClasses: string[]): AdwIcon {
|
|
142
|
+
const icon = document.createElement('adw-icon') as AdwIcon;
|
|
143
|
+
if (iconName !== null) icon.setAttribute('icon-name', iconName);
|
|
144
|
+
if (extraClasses.length > 0) icon.classList.add(...extraClasses);
|
|
145
|
+
return icon;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
customElements.define('adw-icon', AdwIcon);
|