@gjsify/adwaita-web 0.10.0 → 0.12.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 +5 -5
- package/dist/adwaita-web.css +2742 -263
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/elements/adw-about-dialog.d.ts +77 -0
- package/lib/types/elements/adw-action-row.d.ts +15 -0
- package/lib/types/elements/adw-alert-dialog.d.ts +80 -0
- package/lib/types/elements/adw-avatar.d.ts +9 -0
- package/lib/types/elements/adw-banner.d.ts +9 -0
- package/lib/types/elements/adw-bottom-sheet.d.ts +35 -0
- package/lib/types/elements/adw-button-content.d.ts +10 -0
- package/lib/types/elements/adw-button-row.d.ts +11 -0
- package/lib/types/elements/adw-button.d.ts +11 -0
- package/lib/types/elements/adw-carousel.d.ts +64 -0
- package/lib/types/elements/adw-clamp.d.ts +6 -0
- package/lib/types/elements/adw-combo-row.d.ts +3 -0
- package/lib/types/elements/adw-entry-row.d.ts +10 -0
- package/lib/types/elements/adw-entry.d.ts +11 -0
- package/lib/types/elements/adw-expander-row.d.ts +26 -0
- package/lib/types/elements/adw-header-bar.d.ts +4 -0
- package/lib/types/elements/adw-inline-view-switcher.d.ts +30 -0
- package/lib/types/elements/adw-navigation-split-view.d.ts +15 -0
- package/lib/types/elements/adw-navigation-view.d.ts +66 -0
- package/lib/types/elements/adw-password-entry-row.d.ts +16 -0
- package/lib/types/elements/adw-preferences-dialog.d.ts +36 -0
- package/lib/types/elements/adw-preferences-group.d.ts +8 -0
- package/lib/types/elements/adw-sidebar.d.ts +29 -0
- package/lib/types/elements/adw-spin-row.d.ts +3 -0
- package/lib/types/elements/adw-spinner.d.ts +6 -0
- package/lib/types/elements/adw-split-button.d.ts +18 -0
- package/lib/types/elements/adw-status-page.d.ts +11 -0
- package/lib/types/elements/adw-switch-row.d.ts +3 -0
- package/lib/types/elements/adw-tab-view.d.ts +24 -0
- package/lib/types/elements/adw-toast-overlay.d.ts +19 -4
- package/lib/types/elements/adw-toggle-group.d.ts +19 -0
- package/lib/types/elements/adw-toolbar-view.d.ts +13 -0
- package/lib/types/elements/adw-view-switcher.d.ts +29 -0
- package/lib/types/elements/adw-window-title.d.ts +9 -0
- package/lib/types/elements/adw-wrap-box.d.ts +13 -0
- package/lib/types/index.d.ts +29 -0
- package/lib/types/styles.generated.d.ts +1 -0
- package/package.json +5 -5
- package/scss/_about_dialog.scss +257 -0
- package/scss/_action_row.scss +65 -0
- package/scss/_alert_dialog.scss +151 -0
- package/scss/_avatar.scss +31 -0
- package/scss/_banner.scss +46 -0
- package/scss/_bottom_sheet.scss +113 -0
- package/scss/_button.scss +168 -0
- package/scss/_button_content.scss +48 -0
- package/scss/_button_row.scss +100 -0
- package/scss/_carousel.scss +130 -0
- package/scss/_clamp.scss +11 -0
- package/scss/_entry.scss +49 -0
- package/scss/_entry_row.scss +54 -0
- package/scss/_expander_row.scss +150 -0
- package/scss/_headerbar.scss +1 -1
- package/scss/_inline_view_switcher.scss +174 -0
- package/scss/_navigation_split_view.scss +48 -0
- package/scss/_navigation_view.scss +80 -0
- package/scss/_overlay_split_view.scss +19 -0
- package/scss/_password_entry_row.scss +67 -0
- package/scss/_preferences.scss +26 -3
- package/scss/_preferences_dialog.scss +154 -0
- package/scss/_row.scss +31 -0
- package/scss/_sidebar.scss +213 -0
- package/scss/_spin_row.scss +0 -1
- package/scss/_spinner.scss +28 -0
- package/scss/_split_button.scss +222 -0
- package/scss/_status_page.scss +40 -0
- package/scss/_switch_row.scss +0 -1
- package/scss/_tab_view.scss +193 -0
- package/scss/_theme.scss +12 -0
- package/scss/_toast.scss +122 -12
- package/scss/_toggle_group.scss +124 -0
- package/scss/_toolbar_view.scss +31 -0
- package/scss/_variables.scss +19 -0
- package/scss/_view_switcher.scss +133 -0
- package/scss/_window_title.scss +33 -0
- package/scss/_wrap_box.scss +20 -0
- package/scss/adwaita-skin.scss +38 -0
- package/src/elements/adw-about-dialog.ts +629 -0
- package/src/elements/adw-action-row.ts +82 -0
- package/src/elements/adw-alert-dialog.ts +385 -0
- package/src/elements/adw-avatar.ts +108 -0
- package/src/elements/adw-banner.ts +57 -0
- package/src/elements/adw-bottom-sheet.ts +205 -0
- package/src/elements/adw-button-content.ts +69 -0
- package/src/elements/adw-button-row.ts +75 -0
- package/src/elements/adw-button.ts +81 -0
- package/src/elements/adw-carousel.ts +321 -0
- package/src/elements/adw-clamp.ts +28 -0
- package/src/elements/adw-combo-row.ts +32 -20
- package/src/elements/adw-entry-row.ts +69 -0
- package/src/elements/adw-entry.ts +61 -0
- package/src/elements/adw-expander-row.ts +167 -0
- package/src/elements/adw-header-bar.ts +21 -8
- package/src/elements/adw-inline-view-switcher.ts +222 -0
- package/src/elements/adw-navigation-split-view.ts +89 -0
- package/src/elements/adw-navigation-view.ts +344 -0
- package/src/elements/adw-password-entry-row.ts +121 -0
- package/src/elements/adw-preferences-dialog.ts +240 -0
- package/src/elements/adw-preferences-group.ts +79 -12
- package/src/elements/adw-sidebar.ts +238 -0
- package/src/elements/adw-spin-row.ts +28 -14
- package/src/elements/adw-spinner.ts +31 -0
- package/src/elements/adw-split-button.ts +206 -0
- package/src/elements/adw-status-page.ts +66 -0
- package/src/elements/adw-switch-row.ts +29 -23
- package/src/elements/adw-tab-view.ts +184 -0
- package/src/elements/adw-toast-overlay.ts +98 -19
- package/src/elements/adw-toggle-group.ts +126 -0
- package/src/elements/adw-toolbar-view.ts +60 -0
- package/src/elements/adw-view-switcher.ts +200 -0
- package/src/elements/adw-window-title.ts +48 -0
- package/src/elements/adw-wrap-box.ts +139 -0
- package/src/index.js +1 -1
- package/src/index.ts +46 -3
- package/src/styles.generated.js +2976 -0
- package/src/styles2.generated.js +2976 -0
- package/style.css.d.ts +17 -4
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// <adw-view-switcher> — An adaptive, tab-style switcher driving a set of named
|
|
2
|
+
// pages (the web counterpart of Adw.ViewSwitcher paired with an Adw.ViewStack).
|
|
3
|
+
// Pages are declared as <adw-view-switcher-page> children with `name`, `title`
|
|
4
|
+
// and `icon-name` attributes; their own children become the page body. The
|
|
5
|
+
// switcher renders one toggle button per page (always icon + label) and shows
|
|
6
|
+
// exactly one page at a time, exactly like libadwaita's single `viewswitcher`
|
|
7
|
+
// CSS node with the `.wide` / `.narrow` policy style classes.
|
|
8
|
+
// - wide: icon and label side by side (horizontal button layout)
|
|
9
|
+
// - narrow: icon stacked above the label (vertical button layout)
|
|
10
|
+
// Attributes:
|
|
11
|
+
// policy — 'wide' | 'narrow' (default 'narrow', matching libadwaita's default).
|
|
12
|
+
// active — zero-based index of the selected page (default 0).
|
|
13
|
+
// Events:
|
|
14
|
+
// `notify::visible-child` (CustomEvent, bubbles, detail = { name, index }) when
|
|
15
|
+
// the selected page changes — mirrors Adw.ViewStack's `visible-child-name`.
|
|
16
|
+
// `notify::policy` (CustomEvent, bubbles, detail = { policy }) when the policy
|
|
17
|
+
// changes — mirrors the Adw.ViewSwitcher `policy` GObject property.
|
|
18
|
+
// Reference: refs/libadwaita/src/adw-view-switcher.c (AdwViewSwitcher behaviour)
|
|
19
|
+
// Reference: refs/libadwaita/src/stylesheet/widgets/_view-switcher.scss
|
|
20
|
+
// Reference: refs/adwaita-web/adwaita-web/scss/_viewswitcher.scss
|
|
21
|
+
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
22
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
23
|
+
|
|
24
|
+
type Policy = 'wide' | 'narrow';
|
|
25
|
+
|
|
26
|
+
interface PageInfo {
|
|
27
|
+
name: string;
|
|
28
|
+
title: string;
|
|
29
|
+
icon: string;
|
|
30
|
+
body: HTMLElement;
|
|
31
|
+
button: HTMLButtonElement;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** A single page. Children of <adw-view-switcher>; consumed at connect time. */
|
|
35
|
+
export class AdwViewSwitcherPage extends HTMLElement {
|
|
36
|
+
static get observedAttributes() {
|
|
37
|
+
return ['name', 'title', 'icon-name'];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class AdwViewSwitcher extends HTMLElement {
|
|
42
|
+
private _barEl!: HTMLDivElement;
|
|
43
|
+
private _contentEl!: HTMLDivElement;
|
|
44
|
+
private _pages: PageInfo[] = [];
|
|
45
|
+
private _active = 0;
|
|
46
|
+
private _policy: Policy = 'narrow';
|
|
47
|
+
private _initialized = false;
|
|
48
|
+
|
|
49
|
+
static get observedAttributes() {
|
|
50
|
+
return ['policy', 'active'];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The policy controlling the button layout ('wide' | 'narrow'). */
|
|
54
|
+
get policy(): Policy {
|
|
55
|
+
return this._policy;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
set policy(value: Policy) {
|
|
59
|
+
this.setAttribute('policy', value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Zero-based index of the active page. */
|
|
63
|
+
get active(): number {
|
|
64
|
+
return this._active;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
set active(value: number) {
|
|
68
|
+
this.setAttribute('active', String(value));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The name of the currently visible page, or null when there are none. */
|
|
72
|
+
get visibleChildName(): string | null {
|
|
73
|
+
return this._pages[this._active]?.name ?? null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
connectedCallback() {
|
|
77
|
+
if (this._initialized) return;
|
|
78
|
+
this._initialized = true;
|
|
79
|
+
|
|
80
|
+
// Snapshot the declared <adw-view-switcher-page> children before we take
|
|
81
|
+
// over the subtree — their name / title / icon-name + their own child
|
|
82
|
+
// nodes become the rendered tabs and page bodies.
|
|
83
|
+
const declaredPages = Array.from(this.querySelectorAll('adw-view-switcher-page')) as AdwViewSwitcherPage[];
|
|
84
|
+
|
|
85
|
+
// The single `viewswitcher` node holds the segmented button bar; a sibling
|
|
86
|
+
// content area shows the active page (the web stand-in for the paired
|
|
87
|
+
// Adw.ViewStack the switcher would otherwise drive).
|
|
88
|
+
this._barEl = document.createElement('div');
|
|
89
|
+
this._barEl.className = 'adw-view-switcher-bar';
|
|
90
|
+
this._barEl.setAttribute('role', 'tablist');
|
|
91
|
+
|
|
92
|
+
this._contentEl = document.createElement('div');
|
|
93
|
+
this._contentEl.className = 'adw-view-switcher-content';
|
|
94
|
+
|
|
95
|
+
this._pages = declaredPages.map((pageEl, index) => {
|
|
96
|
+
const name = pageEl.getAttribute('name') ?? `page-${index}`;
|
|
97
|
+
const title = pageEl.getAttribute('title') ?? '';
|
|
98
|
+
const icon = (pageEl.getAttribute('icon-name') ?? '').replace(/-symbolic$/, '');
|
|
99
|
+
|
|
100
|
+
const button = document.createElement('button');
|
|
101
|
+
button.type = 'button';
|
|
102
|
+
button.className = 'adw-view-switcher-button';
|
|
103
|
+
button.setAttribute('role', 'tab');
|
|
104
|
+
|
|
105
|
+
const iconEl = document.createElement('span');
|
|
106
|
+
iconEl.className = `adw-icon${icon ? ` adw-icon--${icon}` : ''}`;
|
|
107
|
+
iconEl.setAttribute('aria-hidden', 'true'); // decorative (mask-image only)
|
|
108
|
+
iconEl.hidden = icon.length === 0;
|
|
109
|
+
|
|
110
|
+
const labelEl = document.createElement('span');
|
|
111
|
+
labelEl.className = 'adw-view-switcher-label';
|
|
112
|
+
labelEl.textContent = title;
|
|
113
|
+
labelEl.hidden = title.length === 0;
|
|
114
|
+
|
|
115
|
+
button.append(iconEl, labelEl);
|
|
116
|
+
// An icon-only tab has no visible text — give it an accessible name.
|
|
117
|
+
if (icon && !title) button.setAttribute('aria-label', icon);
|
|
118
|
+
|
|
119
|
+
button.addEventListener('click', () => this._selectIndex(index));
|
|
120
|
+
|
|
121
|
+
const body = document.createElement('div');
|
|
122
|
+
body.className = 'adw-view-switcher-page';
|
|
123
|
+
body.dataset.name = name;
|
|
124
|
+
for (const child of Array.from(pageEl.childNodes)) body.appendChild(child);
|
|
125
|
+
|
|
126
|
+
return { name, title, icon, body, button };
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
this._barEl.append(...this._pages.map((p) => p.button));
|
|
130
|
+
this._contentEl.append(...this._pages.map((p) => p.body));
|
|
131
|
+
this.replaceChildren(this._barEl, this._contentEl);
|
|
132
|
+
|
|
133
|
+
this._policy = this._readPolicyAttr();
|
|
134
|
+
this._active = this._readActiveAttr();
|
|
135
|
+
this._render();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
attributeChangedCallback(name: string) {
|
|
139
|
+
if (!this._initialized) return;
|
|
140
|
+
if (name === 'policy') {
|
|
141
|
+
const next = this._readPolicyAttr();
|
|
142
|
+
if (next !== this._policy) {
|
|
143
|
+
this._policy = next;
|
|
144
|
+
this._render();
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (name === 'active') {
|
|
149
|
+
const next = this._readActiveAttr();
|
|
150
|
+
if (next !== this._active) {
|
|
151
|
+
this._active = next;
|
|
152
|
+
this._render();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private _readPolicyAttr(): Policy {
|
|
158
|
+
return this.getAttribute('policy') === 'wide' ? 'wide' : 'narrow';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private _readActiveAttr(): number {
|
|
162
|
+
const raw = Number.parseInt(this.getAttribute('active') ?? '0', 10);
|
|
163
|
+
if (Number.isNaN(raw)) return 0;
|
|
164
|
+
const max = Math.max(0, this._pages.length - 1);
|
|
165
|
+
return Math.min(Math.max(raw, 0), max);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private _selectIndex(index: number): void {
|
|
169
|
+
if (index === this._active) return;
|
|
170
|
+
this._active = index;
|
|
171
|
+
// Keep the attribute in sync without re-entering the guarded callback
|
|
172
|
+
// (value already matches, so attributeChangedCallback no-ops).
|
|
173
|
+
this.setAttribute('active', String(index));
|
|
174
|
+
this._render();
|
|
175
|
+
const page = this._pages[index];
|
|
176
|
+
this.dispatchEvent(
|
|
177
|
+
new CustomEvent('notify::visible-child', {
|
|
178
|
+
bubbles: true,
|
|
179
|
+
detail: { name: page?.name ?? null, index },
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private _render(): void {
|
|
185
|
+
// Single `viewswitcher` node carries the `.wide` / `.narrow` policy class.
|
|
186
|
+
this.classList.toggle('wide', this._policy === 'wide');
|
|
187
|
+
this.classList.toggle('narrow', this._policy === 'narrow');
|
|
188
|
+
|
|
189
|
+
this._pages.forEach((page, index) => {
|
|
190
|
+
const isActive = index === this._active;
|
|
191
|
+
page.button.classList.toggle('active', isActive);
|
|
192
|
+
page.button.setAttribute('aria-selected', String(isActive));
|
|
193
|
+
page.button.tabIndex = isActive ? 0 : -1;
|
|
194
|
+
page.body.classList.toggle('active-view', isActive);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
customElements.define('adw-view-switcher-page', AdwViewSwitcherPage);
|
|
200
|
+
customElements.define('adw-view-switcher', AdwViewSwitcher);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// <adw-window-title> — A composite title + subtitle for a header bar.
|
|
2
|
+
// Attributes: title, subtitle.
|
|
3
|
+
// Mirrors Adw.WindowTitle: two centered, ellipsized labels stacked vertically;
|
|
4
|
+
// the subtitle is hidden when empty.
|
|
5
|
+
// Reference: refs/adwaita-web/adwaita-web/docs/widgets/windowtitle.md
|
|
6
|
+
// Reference: refs/libadwaita (Adw.WindowTitle)
|
|
7
|
+
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
8
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
9
|
+
|
|
10
|
+
export class AdwWindowTitle extends HTMLElement {
|
|
11
|
+
private _titleEl!: HTMLSpanElement;
|
|
12
|
+
private _subtitleEl!: HTMLSpanElement;
|
|
13
|
+
private _initialized = false;
|
|
14
|
+
|
|
15
|
+
static get observedAttributes() {
|
|
16
|
+
return ['title', 'subtitle'];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
connectedCallback() {
|
|
20
|
+
if (this._initialized) return;
|
|
21
|
+
this._initialized = true;
|
|
22
|
+
|
|
23
|
+
this._titleEl = document.createElement('span');
|
|
24
|
+
this._titleEl.className = 'adw-window-title-title';
|
|
25
|
+
|
|
26
|
+
this._subtitleEl = document.createElement('span');
|
|
27
|
+
this._subtitleEl.className = 'adw-window-title-subtitle';
|
|
28
|
+
|
|
29
|
+
this.replaceChildren(this._titleEl, this._subtitleEl);
|
|
30
|
+
this._render();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
attributeChangedCallback() {
|
|
34
|
+
if (this._initialized) this._render();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private _render() {
|
|
38
|
+
const title = this.getAttribute('title') ?? '';
|
|
39
|
+
const subtitle = this.getAttribute('subtitle') ?? '';
|
|
40
|
+
this._titleEl.textContent = title;
|
|
41
|
+
this._subtitleEl.textContent = subtitle;
|
|
42
|
+
// Hide the subtitle slot entirely when empty so the title stays
|
|
43
|
+
// vertically centered (matches Adw.WindowTitle).
|
|
44
|
+
this._subtitleEl.hidden = subtitle.length === 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
customElements.define('adw-window-title', AdwWindowTitle);
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// <adw-wrap-box> — A box-like container that lays its children out in a line and
|
|
2
|
+
// wraps them onto new lines when they run out of room (the web analog of
|
|
3
|
+
// flexbox `flex-wrap: wrap` with a gap). Mirrors Adw.WrapBox.
|
|
4
|
+
// Attributes:
|
|
5
|
+
// child-spacing (px, default 0) — spacing between children on the same line
|
|
6
|
+
// → CSS column-gap
|
|
7
|
+
// line-spacing (px, default 0) — spacing between lines → CSS row-gap
|
|
8
|
+
// orientation ("horizontal" | "vertical", default "horizontal") — the main
|
|
9
|
+
// axis children are packed along
|
|
10
|
+
// align (0..1, default 0) — alignment of children within each line
|
|
11
|
+
// (cross axis); 0 = start, 0.5 = center, 1 = end
|
|
12
|
+
// justify ("none" | "fill" | "spread", default "none") — whether/how
|
|
13
|
+
// each line is stretched to fill the widget
|
|
14
|
+
// justify-last-line (boolean) — also justify the last (incomplete) line
|
|
15
|
+
// line-homogeneous (boolean) — make every line take the same amount of space
|
|
16
|
+
// pack-direction ("start-to-end" | "end-to-start", default "start-to-end") —
|
|
17
|
+
// direction children are packed within a line
|
|
18
|
+
// wrap-reverse (boolean) — reverse the wrap direction (lines wrap upwards)
|
|
19
|
+
// Events: notify::child-spacing, notify::line-spacing (CustomEvent, bubbles —
|
|
20
|
+
// mirrors GObject signal naming).
|
|
21
|
+
// Reference: refs/libadwaita/src/adw-wrap-box.c / adw-wrap-layout.c (Adw.WrapBox)
|
|
22
|
+
// Reference: refs/adwaita-web/adwaita-web/scss/_wrap_box.scss
|
|
23
|
+
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
24
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
25
|
+
|
|
26
|
+
/** Adw.JustifyMode → flexbox justify-content. */
|
|
27
|
+
const JUSTIFY_MAP: Record<string, string> = {
|
|
28
|
+
none: 'flex-start',
|
|
29
|
+
fill: 'space-between',
|
|
30
|
+
spread: 'space-between',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export class AdwWrapBox extends HTMLElement {
|
|
34
|
+
private _initialized = false;
|
|
35
|
+
|
|
36
|
+
static get observedAttributes() {
|
|
37
|
+
return [
|
|
38
|
+
'child-spacing',
|
|
39
|
+
'line-spacing',
|
|
40
|
+
'orientation',
|
|
41
|
+
'align',
|
|
42
|
+
'justify',
|
|
43
|
+
'justify-last-line',
|
|
44
|
+
'line-homogeneous',
|
|
45
|
+
'pack-direction',
|
|
46
|
+
'wrap-reverse',
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Spacing between children on the same line, in px (CSS column-gap). */
|
|
51
|
+
get childSpacing(): number {
|
|
52
|
+
return parseFloat(this.getAttribute('child-spacing') || '0');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
set childSpacing(value: number) {
|
|
56
|
+
this.setAttribute('child-spacing', String(value));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Spacing between lines, in px (CSS row-gap). */
|
|
60
|
+
get lineSpacing(): number {
|
|
61
|
+
return parseFloat(this.getAttribute('line-spacing') || '0');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
set lineSpacing(value: number) {
|
|
65
|
+
this.setAttribute('line-spacing', String(value));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
connectedCallback() {
|
|
69
|
+
if (this._initialized) return;
|
|
70
|
+
this._initialized = true;
|
|
71
|
+
this._sync();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
attributeChangedCallback(name: string, old: string | null, value: string | null) {
|
|
75
|
+
if (!this._initialized) return;
|
|
76
|
+
this._sync();
|
|
77
|
+
if (old === value) return;
|
|
78
|
+
if (name === 'child-spacing') {
|
|
79
|
+
this.dispatchEvent(
|
|
80
|
+
new CustomEvent('notify::child-spacing', {
|
|
81
|
+
bubbles: true,
|
|
82
|
+
detail: { childSpacing: this.childSpacing },
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
} else if (name === 'line-spacing') {
|
|
86
|
+
this.dispatchEvent(
|
|
87
|
+
new CustomEvent('notify::line-spacing', {
|
|
88
|
+
bubbles: true,
|
|
89
|
+
detail: { lineSpacing: this.lineSpacing },
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private _sync() {
|
|
96
|
+
const style = this.style;
|
|
97
|
+
const vertical = this.getAttribute('orientation') === 'vertical';
|
|
98
|
+
const reverseWrap = this.hasAttribute('wrap-reverse');
|
|
99
|
+
const packEndToStart = this.getAttribute('pack-direction') === 'end-to-start';
|
|
100
|
+
|
|
101
|
+
// Main axis is the packing direction; lines wrap along the cross axis.
|
|
102
|
+
const direction = vertical ? 'column' : 'row';
|
|
103
|
+
const reversed = packEndToStart ? `${direction}-reverse` : direction;
|
|
104
|
+
style.flexDirection = reversed;
|
|
105
|
+
style.flexWrap = reverseWrap ? 'wrap-reverse' : 'wrap';
|
|
106
|
+
|
|
107
|
+
// child-spacing is along the line (main axis), line-spacing is between
|
|
108
|
+
// lines (cross axis). For a horizontal box that maps to column-gap /
|
|
109
|
+
// row-gap respectively; the mapping flips for a vertical box.
|
|
110
|
+
const childGap = `${this.childSpacing}px`;
|
|
111
|
+
const lineGap = `${this.lineSpacing}px`;
|
|
112
|
+
if (vertical) {
|
|
113
|
+
style.rowGap = childGap;
|
|
114
|
+
style.columnGap = lineGap;
|
|
115
|
+
} else {
|
|
116
|
+
style.columnGap = childGap;
|
|
117
|
+
style.rowGap = lineGap;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// justify-content stretches each complete line along the main axis; the
|
|
121
|
+
// last (incomplete) line is only stretched when justify-last-line is set.
|
|
122
|
+
const justify = this.getAttribute('justify') ?? 'none';
|
|
123
|
+
style.justifyContent = JUSTIFY_MAP[justify] ?? 'flex-start';
|
|
124
|
+
|
|
125
|
+
// align (0..1) positions children within each line on the cross axis.
|
|
126
|
+
// It is only honoured when the line is not justified.
|
|
127
|
+
const align = Math.max(0, Math.min(1, parseFloat(this.getAttribute('align') || '0')));
|
|
128
|
+
let crossAlign = 'flex-start';
|
|
129
|
+
if (align >= 0.75) crossAlign = 'flex-end';
|
|
130
|
+
else if (align >= 0.25) crossAlign = 'center';
|
|
131
|
+
style.alignItems = crossAlign;
|
|
132
|
+
|
|
133
|
+
// line-homogeneous makes every line take the same amount of space, which
|
|
134
|
+
// flexbox approximates by stretching the lines across the cross axis.
|
|
135
|
+
style.alignContent = this.hasAttribute('line-homogeneous') ? 'stretch' : 'flex-start';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
customElements.define('adw-wrap-box', AdwWrapBox);
|
package/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AdwCard as
|
|
1
|
+
import{e}from"./styles2.generated.js";import{AdwAvatar as t}from"./elements/adw-avatar2.js";import{AdwBanner as n}from"./elements/adw-banner2.js";import{AdwCard as r}from"./elements/adw-card2.js";import{AdwClamp as i}from"./elements/adw-clamp2.js";import{AdwSpinner as a}from"./elements/adw-spinner2.js";import{AdwStatusPage as o}from"./elements/adw-status-page2.js";import{AdwWindow as s}from"./elements/adw-window2.js";import{AdwHeaderBar as c}from"./elements/adw-header-bar2.js";import{AdwWindowTitle as l}from"./elements/adw-window-title2.js";import{AdwButton as u}from"./elements/adw-button2.js";import{AdwButtonContent as d}from"./elements/adw-button-content2.js";import{AdwSplitButton as f}from"./elements/adw-split-button2.js";import{AdwToggle as p,AdwToggleGroup as m}from"./elements/adw-toggle-group2.js";import{AdwEntry as h}from"./elements/adw-entry2.js";import{AdwPreferencesGroup as g}from"./elements/adw-preferences-group2.js";import{AdwActionRow as _}from"./elements/adw-action-row2.js";import{AdwEntryRow as v}from"./elements/adw-entry-row2.js";import{AdwSwitchRow as y}from"./elements/adw-switch-row2.js";import{AdwComboRow as b}from"./elements/adw-combo-row2.js";import{AdwSpinRow as x}from"./elements/adw-spin-row2.js";import{AdwButtonRow as S}from"./elements/adw-button-row2.js";import{AdwExpanderRow as C}from"./elements/adw-expander-row2.js";import{AdwPasswordEntryRow as w}from"./elements/adw-password-entry-row2.js";import{AdwToastOverlay as T}from"./elements/adw-toast-overlay2.js";import{AdwToolbarView as E}from"./elements/adw-toolbar-view2.js";import{AdwWrapBox as D}from"./elements/adw-wrap-box2.js";import{AdwOverlaySplitView as O}from"./elements/adw-overlay-split-view2.js";import{AdwNavigationSplitView as k}from"./elements/adw-navigation-split-view2.js";import{AdwCarousel as A,AdwCarouselIndicatorDots as j,AdwCarouselIndicatorLines as M}from"./elements/adw-carousel2.js";import{AdwTabPage as N,AdwTabView as P}from"./elements/adw-tab-view2.js";import{AdwViewSwitcher as F,AdwViewSwitcherPage as I}from"./elements/adw-view-switcher2.js";import{AdwInlineViewSwitcher as L,AdwViewStackPage as R}from"./elements/adw-inline-view-switcher2.js";import{AdwNavigationPage as z,AdwNavigationView as B}from"./elements/adw-navigation-view2.js";import{AdwBottomSheet as V,AdwBottomSheetContent as H,AdwBottomSheetSheet as U}from"./elements/adw-bottom-sheet2.js";import{AdwSidebar as W,AdwSidebarItem as G,AdwSidebarSection as K}from"./elements/adw-sidebar2.js";import{AdwAboutDialog as q}from"./elements/adw-about-dialog2.js";import{AdwAlertDialog as J,AdwAlertResponse as Y}from"./elements/adw-alert-dialog2.js";import{AdwPreferencesDialog as X,AdwPreferencesPage as Z}from"./elements/adw-preferences-dialog2.js";import"@gjsify/adwaita-fonts";if(typeof document<`u`&&!document.getElementById(`adwaita-web-style`)){let t=document.createElement(`style`);t.id=`adwaita-web-style`,t.textContent=e,document.head.appendChild(t)}export{q as AdwAboutDialog,_ as AdwActionRow,J as AdwAlertDialog,Y as AdwAlertResponse,t as AdwAvatar,n as AdwBanner,V as AdwBottomSheet,H as AdwBottomSheetContent,U as AdwBottomSheetSheet,u as AdwButton,d as AdwButtonContent,S as AdwButtonRow,r as AdwCard,A as AdwCarousel,j as AdwCarouselIndicatorDots,M as AdwCarouselIndicatorLines,i as AdwClamp,b as AdwComboRow,h as AdwEntry,v as AdwEntryRow,C as AdwExpanderRow,c as AdwHeaderBar,L as AdwInlineViewSwitcher,z as AdwNavigationPage,k as AdwNavigationSplitView,B as AdwNavigationView,O as AdwOverlaySplitView,w as AdwPasswordEntryRow,X as AdwPreferencesDialog,g as AdwPreferencesGroup,Z as AdwPreferencesPage,W as AdwSidebar,G as AdwSidebarItem,K as AdwSidebarSection,x as AdwSpinRow,a as AdwSpinner,f as AdwSplitButton,o as AdwStatusPage,y as AdwSwitchRow,N as AdwTabPage,P as AdwTabView,T as AdwToastOverlay,p as AdwToggle,m as AdwToggleGroup,E as AdwToolbarView,R as AdwViewStackPage,F as AdwViewSwitcher,I as AdwViewSwitcherPage,s as AdwWindow,l as AdwWindowTitle,D as AdwWrapBox};
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,61 @@
|
|
|
1
1
|
// @gjsify/adwaita-web — Adwaita/Libadwaita web components for browser targets.
|
|
2
|
-
// Importing this module registers all custom elements
|
|
3
|
-
// stylesheet
|
|
4
|
-
//
|
|
2
|
+
// Importing this module registers all custom elements AND self-applies the
|
|
3
|
+
// compiled stylesheet — no separate CSS import is needed. The compiled CSS is
|
|
4
|
+
// still exported at `@gjsify/adwaita-web/style.css` (e.g. for a <link>) and the
|
|
5
|
+
// SCSS partials at `@gjsify/adwaita-web/scss/...` for custom theming.
|
|
5
6
|
// Reference: refs/libadwaita (colors/sizing), refs/adwaita-web (component patterns).
|
|
6
7
|
|
|
7
8
|
import '@gjsify/adwaita-fonts'; // Registers @font-face (fontsource pattern)
|
|
9
|
+
import { ADWAITA_WEB_CSS } from './styles.generated.js';
|
|
10
|
+
|
|
11
|
+
// Self-apply the compiled stylesheet on import. This makes `import
|
|
12
|
+
// '@gjsify/adwaita-web'` enough to style the components under ANY bundler —
|
|
13
|
+
// a separate `import '@gjsify/adwaita-web/style.css'` is a no-op under a gjsify
|
|
14
|
+
// `--app browser` build (css-as-string yields a string a side-effect import
|
|
15
|
+
// discards), which used to leave consumers unstyled. Idempotent + browser-only.
|
|
16
|
+
if (typeof document !== 'undefined' && !document.getElementById('adwaita-web-style')) {
|
|
17
|
+
const style = document.createElement('style');
|
|
18
|
+
style.id = 'adwaita-web-style';
|
|
19
|
+
style.textContent = ADWAITA_WEB_CSS;
|
|
20
|
+
document.head.appendChild(style);
|
|
21
|
+
}
|
|
8
22
|
|
|
9
23
|
// Register custom elements (side-effect imports)
|
|
24
|
+
export { AdwAvatar } from './elements/adw-avatar.js';
|
|
25
|
+
export { AdwBanner } from './elements/adw-banner.js';
|
|
10
26
|
export { AdwCard } from './elements/adw-card.js';
|
|
27
|
+
export { AdwClamp } from './elements/adw-clamp.js';
|
|
28
|
+
export { AdwSpinner } from './elements/adw-spinner.js';
|
|
29
|
+
export { AdwStatusPage } from './elements/adw-status-page.js';
|
|
11
30
|
export { AdwWindow } from './elements/adw-window.js';
|
|
12
31
|
export { AdwHeaderBar } from './elements/adw-header-bar.js';
|
|
32
|
+
export { AdwWindowTitle } from './elements/adw-window-title.js';
|
|
33
|
+
export { AdwButton } from './elements/adw-button.js';
|
|
34
|
+
export { AdwButtonContent } from './elements/adw-button-content.js';
|
|
35
|
+
export { AdwSplitButton } from './elements/adw-split-button.js';
|
|
36
|
+
export { AdwToggle, AdwToggleGroup } from './elements/adw-toggle-group.js';
|
|
37
|
+
export { AdwEntry } from './elements/adw-entry.js';
|
|
13
38
|
export { AdwPreferencesGroup } from './elements/adw-preferences-group.js';
|
|
39
|
+
export { AdwActionRow } from './elements/adw-action-row.js';
|
|
40
|
+
export { AdwEntryRow } from './elements/adw-entry-row.js';
|
|
14
41
|
export { AdwSwitchRow } from './elements/adw-switch-row.js';
|
|
15
42
|
export { AdwComboRow } from './elements/adw-combo-row.js';
|
|
16
43
|
export { AdwSpinRow } from './elements/adw-spin-row.js';
|
|
44
|
+
export { AdwButtonRow } from './elements/adw-button-row.js';
|
|
45
|
+
export { AdwExpanderRow } from './elements/adw-expander-row.js';
|
|
46
|
+
export { AdwPasswordEntryRow } from './elements/adw-password-entry-row.js';
|
|
17
47
|
export { AdwToastOverlay } from './elements/adw-toast-overlay.js';
|
|
48
|
+
export { AdwToolbarView } from './elements/adw-toolbar-view.js';
|
|
49
|
+
export { AdwWrapBox } from './elements/adw-wrap-box.js';
|
|
18
50
|
export { AdwOverlaySplitView } from './elements/adw-overlay-split-view.js';
|
|
51
|
+
export { AdwNavigationSplitView } from './elements/adw-navigation-split-view.js';
|
|
52
|
+
export { AdwCarousel, AdwCarouselIndicatorDots, AdwCarouselIndicatorLines } from './elements/adw-carousel.js';
|
|
53
|
+
export { AdwTabPage, AdwTabView } from './elements/adw-tab-view.js';
|
|
54
|
+
export { AdwViewSwitcher, AdwViewSwitcherPage } from './elements/adw-view-switcher.js';
|
|
55
|
+
export { AdwInlineViewSwitcher, AdwViewStackPage } from './elements/adw-inline-view-switcher.js';
|
|
56
|
+
export { AdwNavigationPage, AdwNavigationView } from './elements/adw-navigation-view.js';
|
|
57
|
+
export { AdwBottomSheet, AdwBottomSheetContent, AdwBottomSheetSheet } from './elements/adw-bottom-sheet.js';
|
|
58
|
+
export { AdwSidebar, AdwSidebarItem, AdwSidebarSection } from './elements/adw-sidebar.js';
|
|
59
|
+
export { AdwAboutDialog } from './elements/adw-about-dialog.js';
|
|
60
|
+
export { AdwAlertDialog, AdwAlertResponse } from './elements/adw-alert-dialog.js';
|
|
61
|
+
export { AdwPreferencesDialog, AdwPreferencesPage } from './elements/adw-preferences-dialog.js';
|