@gjsify/adwaita-web 0.31.0 → 0.33.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 +835 -299
- 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-combo-row.d.ts +10 -0
- 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 +73 -11
- package/lib/types/elements/adw-menu-button.d.ts +6 -6
- package/lib/types/elements/adw-navigation-split-view.d.ts +48 -0
- package/lib/types/elements/adw-navigation-view.d.ts +63 -20
- package/lib/types/elements/adw-overlay-split-view.d.ts +94 -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-spinner.d.ts +23 -0
- 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 +39 -19
- package/lib/types/elements/adw-view-switcher-bar.d.ts +25 -7
- package/lib/types/elements/adw-view-switcher.d.ts +76 -13
- package/lib/types/elements/adw-window-title.d.ts +3 -1
- package/lib/types/elements/adw-wrap-box.d.ts +58 -3
- 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/_combo_row.scss +19 -0
- 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/_navigation_split_view.scss +47 -8
- package/scss/_overlay_split_view.scss +117 -32
- 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 +37 -19
- 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 +63 -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 +65 -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 +176 -0
- package/src/adw-banner.spec.ts +152 -0
- package/src/adw-button-content.spec.ts +207 -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-row-state.spec.ts +49 -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 +341 -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 +400 -0
- package/src/elements/adw-about-dialog.ts +223 -163
- package/src/elements/adw-action-row.ts +131 -11
- 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 +32 -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 +325 -131
- package/src/elements/adw-menu-button.ts +93 -70
- package/src/elements/adw-navigation-split-view.ts +220 -14
- package/src/elements/adw-navigation-view.ts +286 -148
- package/src/elements/adw-overlay-split-view.ts +536 -28
- 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 +168 -9
- 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 +700 -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 +183 -85
- package/src/elements/adw-view-switcher-bar.ts +171 -81
- package/src/elements/adw-view-switcher.ts +328 -117
- package/src/elements/adw-window-title.ts +44 -11
- package/src/elements/adw-wrap-box.ts +329 -78
- 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 +893 -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 +665 -0
|
@@ -1,30 +1,189 @@
|
|
|
1
1
|
// <adw-spinner> — A continuously-spinning loading indicator.
|
|
2
|
-
// Attributes: size (px,
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// Attributes: size (px; the BOX, floored at the measured minimum 16).
|
|
3
|
+
//
|
|
4
|
+
// THE BOX AND THE RING ARE DIFFERENT THINGS. `adw_spinner_measure`
|
|
5
|
+
// (adw-spinner.c:78-81) reports MIN_SIZE as both minimum and natural and has no
|
|
6
|
+
// upper bound — `MAX_SIZE` at :15 is defined and never referenced — while
|
|
7
|
+
// `adw_spinner_snapshot` (:95-99) hands the widget's real width and height to
|
|
8
|
+
// the paintable, which caps only `radius` (adw-spinner-paintable.c:343) and
|
|
9
|
+
// still centres on the box (:349-351). So `size="200"` occupies 200px of layout
|
|
10
|
+
// and draws a 64px ring in the middle. This element used to BE the ring, which
|
|
11
|
+
// is why its suite asserted the opposite of the core's `SPINNER_SIZE_VECTORS`.
|
|
12
|
+
//
|
|
13
|
+
// THE ARC IS NOT A ROTATING QUARTER-CIRCLE. It extends, overlaps, contracts and
|
|
14
|
+
// idles on an ease-in-out-sine while the figure turns; the arithmetic is
|
|
15
|
+
// `@gjsify/adwaita-core`'s `spinnerArc`, shared with the vectors that judge it.
|
|
16
|
+
// Expressing that needs a per-frame value, so this element draws an SVG arc and
|
|
17
|
+
// advances it from one module-level ticker — not one timer per spinner. CSS
|
|
18
|
+
// keyframes cannot express it: a `border-top-color` chase is a fixed 90 degrees,
|
|
19
|
+
// which is what this element drew for its whole life.
|
|
20
|
+
//
|
|
21
|
+
// IT KEEPS SPINNING UNDER REDUCED MOTION. `adw_spinner_paintable_set_widget`
|
|
22
|
+
// calls `adw_animation_set_follow_enable_animations_setting (…, FALSE)` (:537)
|
|
23
|
+
// — deliberately, because a frozen busy indicator reads as a hang. The old
|
|
24
|
+
// `@media (prefers-reduced-motion: reduce) { animation: none }` did exactly that.
|
|
25
|
+
//
|
|
26
|
+
// Reference: refs/libadwaita/src/adw-spinner.c (MIN_SIZE, adw_spinner_measure, the a11y role)
|
|
27
|
+
// Reference: refs/libadwaita/src/adw-spinner-paintable.c (the animation + geometry)
|
|
5
28
|
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
6
29
|
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
7
30
|
|
|
31
|
+
import {
|
|
32
|
+
ADW_SPINNER_STILL_PROGRESS,
|
|
33
|
+
ADW_SPINNER_TRACK_OPACITY,
|
|
34
|
+
resolveSpinnerSize,
|
|
35
|
+
spinnerArc,
|
|
36
|
+
spinnerGeometry,
|
|
37
|
+
spinnerProgressAt,
|
|
38
|
+
} from '@gjsify/adwaita-core';
|
|
39
|
+
|
|
40
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Every mapped spinner, driven by ONE `requestAnimationFrame` loop.
|
|
44
|
+
*
|
|
45
|
+
* The C animates per widget off the frame clock, which costs nothing extra
|
|
46
|
+
* because the clock is already ticking. A browser has no such clock, so the
|
|
47
|
+
* equivalent is one shared rAF: N spinners on a page must not mean N loops, and
|
|
48
|
+
* the loop must not exist at all while none are mapped.
|
|
49
|
+
*/
|
|
50
|
+
const mapped = new Set<AdwSpinner>();
|
|
51
|
+
let frameHandle = 0;
|
|
52
|
+
|
|
53
|
+
function tick(now: number): void {
|
|
54
|
+
for (const spinner of mapped) spinner.drawAt(now);
|
|
55
|
+
frameHandle = mapped.size > 0 ? requestAnimationFrame(tick) : 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function startTicking(): void {
|
|
59
|
+
if (frameHandle === 0 && mapped.size > 0) frameHandle = requestAnimationFrame(tick);
|
|
60
|
+
}
|
|
61
|
+
|
|
8
62
|
export class AdwSpinner extends HTMLElement {
|
|
9
63
|
static get observedAttributes() {
|
|
10
64
|
return ['size'];
|
|
11
65
|
}
|
|
12
66
|
|
|
67
|
+
private _svg: SVGSVGElement | null = null;
|
|
68
|
+
private _track: SVGCircleElement | null = null;
|
|
69
|
+
private _arc: SVGCircleElement | null = null;
|
|
70
|
+
/** Path length of the ring, so the dash arithmetic is done once per resize. */
|
|
71
|
+
private _circumference = 0;
|
|
72
|
+
/** Ring radius in px — the dash lengths are arc-length, i.e. radians × r. */
|
|
73
|
+
private _radius = 0;
|
|
74
|
+
/** The timestamp this spinner was mapped at, so its progress starts at 0. */
|
|
75
|
+
private _origin: number | null = null;
|
|
76
|
+
|
|
13
77
|
connectedCallback() {
|
|
14
|
-
this.
|
|
78
|
+
this._build();
|
|
79
|
+
// `widget_map_cb` (adw-spinner-paintable.c:181-185) plays the animation
|
|
80
|
+
// on MAP, not on construction: an off-screen spinner burns nothing.
|
|
81
|
+
mapped.add(this);
|
|
82
|
+
this._origin = null;
|
|
83
|
+
startTicking();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
disconnectedCallback() {
|
|
87
|
+
mapped.delete(this);
|
|
15
88
|
}
|
|
16
89
|
|
|
17
90
|
attributeChangedCallback() {
|
|
18
91
|
this._sync();
|
|
19
92
|
}
|
|
20
93
|
|
|
21
|
-
|
|
22
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Draw the frame for `now`, in `requestAnimationFrame` timebase.
|
|
96
|
+
*
|
|
97
|
+
* Public because the shared ticker is a module-level function rather than a
|
|
98
|
+
* method — and because a test needs to place the spinner at a known moment
|
|
99
|
+
* without waiting for real frames.
|
|
100
|
+
*/
|
|
101
|
+
drawAt(now: number): void {
|
|
102
|
+
if (this._origin === null) this._origin = now;
|
|
103
|
+
this._paint(spinnerProgressAt(now - this._origin));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private _build(): void {
|
|
107
|
+
if (this._svg) return;
|
|
108
|
+
const svg = document.createElementNS(SVG_NS, 'svg');
|
|
109
|
+
svg.setAttribute('fill', 'none');
|
|
110
|
+
// The ring is decorative; the ROLE is on the host, per adw-spinner.c:124.
|
|
111
|
+
svg.setAttribute('aria-hidden', 'true');
|
|
112
|
+
|
|
113
|
+
const track = document.createElementNS(SVG_NS, 'circle');
|
|
114
|
+
track.setAttribute('stroke', 'currentColor');
|
|
115
|
+
// `CIRCLE_OPACITY` of the WIDGET's colour (adw-spinner-paintable.c:367-369),
|
|
116
|
+
// not a hardcoded grey — so the track follows the text colour everywhere.
|
|
117
|
+
track.setAttribute('stroke-opacity', String(ADW_SPINNER_TRACK_OPACITY));
|
|
118
|
+
|
|
119
|
+
const arc = document.createElementNS(SVG_NS, 'circle');
|
|
120
|
+
arc.setAttribute('stroke', 'currentColor');
|
|
121
|
+
// `GSK_LINE_CAP_ROUND` (adw-spinner-paintable.c:354). The port's
|
|
122
|
+
// `border-top-color` ends were square-cut, visible from 48px up.
|
|
123
|
+
arc.setAttribute('stroke-linecap', 'round');
|
|
124
|
+
|
|
125
|
+
svg.append(track, arc);
|
|
126
|
+
this._svg = svg;
|
|
127
|
+
this._track = track;
|
|
128
|
+
this._arc = arc;
|
|
129
|
+
this.replaceChildren(svg);
|
|
130
|
+
|
|
131
|
+
// `gtk_widget_class_set_accessible_role (…, PROGRESS_BAR)` (adw-spinner.c:124)
|
|
132
|
+
// and `GTK_ACCESSIBLE_STATE_BUSY, TRUE` (:139-141). A repo-wide grep for
|
|
133
|
+
// either found ZERO hits before this: screen readers announced nothing.
|
|
134
|
+
this.setAttribute('role', 'progressbar');
|
|
135
|
+
this.setAttribute('aria-busy', 'true');
|
|
136
|
+
|
|
137
|
+
this._sync();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Re-derive the box, the ring and the stroke from the `size` attribute. */
|
|
141
|
+
private _sync(): void {
|
|
142
|
+
const svg = this._svg;
|
|
143
|
+
const track = this._track;
|
|
144
|
+
const arc = this._arc;
|
|
145
|
+
if (!svg || !track || !arc) return;
|
|
146
|
+
|
|
147
|
+
const size = resolveSpinnerSize(this.getAttribute('size'));
|
|
148
|
+
const { diameter, lineWidth } = spinnerGeometry(size, size);
|
|
149
|
+
// THE BOX: whatever was asked for, floored at the measured minimum.
|
|
23
150
|
this.style.width = `${size}px`;
|
|
24
151
|
this.style.height = `${size}px`;
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
152
|
+
// THE RING: capped at 64, centred by the host's flex box.
|
|
153
|
+
svg.setAttribute('width', String(diameter));
|
|
154
|
+
svg.setAttribute('height', String(diameter));
|
|
155
|
+
svg.setAttribute('viewBox', `0 0 ${diameter} ${diameter}`);
|
|
156
|
+
|
|
157
|
+
// The stroke is centred on the path, so the circle sits half a stroke in
|
|
158
|
+
// — `radius - line_width / 2` (adw-spinner-paintable.c:364).
|
|
159
|
+
const radius = (diameter - lineWidth) / 2;
|
|
160
|
+
this._radius = radius;
|
|
161
|
+
this._circumference = 2 * Math.PI * radius;
|
|
162
|
+
for (const circle of [track, arc]) {
|
|
163
|
+
circle.setAttribute('cx', String(diameter / 2));
|
|
164
|
+
circle.setAttribute('cy', String(diameter / 2));
|
|
165
|
+
circle.setAttribute('r', String(radius));
|
|
166
|
+
circle.setAttribute('stroke-width', String(lineWidth));
|
|
167
|
+
}
|
|
168
|
+
// A resize while unmapped still has to leave a drawable frame behind:
|
|
169
|
+
// the resting pose, which is what a paintable without an animation draws.
|
|
170
|
+
this._paint(this._origin === null ? ADW_SPINNER_STILL_PROGRESS : this._lastProgress);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The progress the last painted frame used, so a resize can repaint it. */
|
|
174
|
+
private _lastProgress = ADW_SPINNER_STILL_PROGRESS;
|
|
175
|
+
|
|
176
|
+
private _paint(progress: number): void {
|
|
177
|
+
const arc = this._arc;
|
|
178
|
+
if (!arc || this._radius <= 0) return;
|
|
179
|
+
this._lastProgress = progress;
|
|
180
|
+
const { end, length } = spinnerArc(progress);
|
|
181
|
+
const drawn = length * this._radius;
|
|
182
|
+
arc.setAttribute('stroke-dasharray', `${drawn} ${Math.max(this._circumference - drawn, 0)}`);
|
|
183
|
+
// An SVG circle's path starts at 3 o'clock and runs clockwise, which is
|
|
184
|
+
// the same origin and direction the C's angles use — so a radian is a
|
|
185
|
+
// path distance and the dash only has to be shifted to `end`.
|
|
186
|
+
arc.setAttribute('stroke-dashoffset', String(-end * this._radius));
|
|
28
187
|
}
|
|
29
188
|
}
|
|
30
189
|
|