@xingwangzhe/stalux 1.40.0 → 1.40.1
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 +1 -1
- package/package.json +1 -1
- package/src/scripts/view-transitions.ts +19 -10
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Standalone images written as `` receive a `figure` and
|
|
|
18
18
|
|
|
19
19
|
Code blocks default to the single `dark-plus` theme, with system color-scheme switching and theme selectors disabled. To opt into another theme or switching behavior, explicitly override `themes`, `useDarkModeMediaQuery`, and `themeCssSelector` through `expressiveCode`. This only changes generated code styles and adds no telemetry.
|
|
20
20
|
|
|
21
|
-
Route changes use native CSS View Transitions for one visible semantic heading in the incoming page. The policy covers every theme route category: normal effects take 100–180ms, with short 100–120ms fades on mobile. Entering an article, returning to a list, filtering categories or tags, explicit previous/next article controls, and returning home receive hints that follow reading intent. History traversal restores the existing scroll position; offscreen headings remain out of view. Reduced motion, browser-provided history gestures and same-page anchors add no visible VT animation. Standalone HTML keeps native navigation. See the [1.40.0 transition policy](https://github.com/xingwangzhe/stalux/blob/v1.40.
|
|
21
|
+
Route changes use native CSS View Transitions for one visible semantic heading in the incoming page. The policy covers every theme route category: normal effects take 100–180ms, with short 100–120ms fades on mobile. Entering an article, returning to a list, filtering categories or tags, explicit previous/next article controls, and returning home receive hints that follow reading intent. History traversal restores the existing scroll position; offscreen headings remain out of view. Reduced motion, browser-provided history gestures and same-page anchors add no visible VT animation. Standalone HTML keeps native navigation. See the [1.40.0 transition policy](https://github.com/xingwangzhe/stalux/blob/v1.40.1/docs/view-transitions-1.40.1.md).
|
|
22
22
|
|
|
23
23
|
The sticky header stays at the top while the body grows with long content; the persisted header and footer stay in place during navigation. Text is immediately clear, and the incoming heading is measured once after Astro swaps the document and restores scrolling. Astro continues to own document/font preparation, history, scrolling and page-script lifecycle. Shared motion state settles when the native transition finishes or is canceled. CSS animation duration is reported separately from total navigation time, which includes networking, layout and browser settlement.
|
|
24
24
|
|
package/package.json
CHANGED
|
@@ -94,15 +94,19 @@ function preserveHeaderMetrics(nextDocument: Document): void {
|
|
|
94
94
|
const transitionWindow = window as TransitionWindow;
|
|
95
95
|
if (!transitionWindow.__STALUX_VT_LISTENER__) {
|
|
96
96
|
transitionWindow.__STALUX_VT_LISTENER__ = true;
|
|
97
|
+
let pendingNavigation = 0;
|
|
98
|
+
let swappedNavigation = 0;
|
|
97
99
|
|
|
98
100
|
// A current-page link is not a page replacement. Intercept before Astro's
|
|
99
101
|
// delegated handler, but keep propagation for menu cleanup and click tracking.
|
|
102
|
+
// During preparation, Astro must receive it to cancel an incoming route.
|
|
100
103
|
// Hash changes, explicit reloads, downloads and modified/new-tab clicks keep
|
|
101
104
|
// their native behavior.
|
|
102
105
|
document.addEventListener(
|
|
103
106
|
"click",
|
|
104
107
|
(event) => {
|
|
105
108
|
if (
|
|
109
|
+
pendingNavigation !== 0 ||
|
|
106
110
|
event.defaultPrevented ||
|
|
107
111
|
event.button !== 0 ||
|
|
108
112
|
event.metaKey ||
|
|
@@ -148,6 +152,12 @@ if (!transitionWindow.__STALUX_VT_LISTENER__) {
|
|
|
148
152
|
document.addEventListener("astro:before-preparation", (event) => {
|
|
149
153
|
const navigation = event as unknown as NavigationEvent;
|
|
150
154
|
const current = ++generation;
|
|
155
|
+
pendingNavigation = current;
|
|
156
|
+
const cancelPreparation = () => {
|
|
157
|
+
if (current !== generation) return;
|
|
158
|
+
pendingNavigation = 0;
|
|
159
|
+
clearNavigationState();
|
|
160
|
+
};
|
|
151
161
|
motion?.cancel();
|
|
152
162
|
// Only the incoming heading animates. Drop any prior marker without
|
|
153
163
|
// measuring/capturing a hidden outgoing title or flushing its layout.
|
|
@@ -166,25 +176,21 @@ if (!transitionWindow.__STALUX_VT_LISTENER__) {
|
|
|
166
176
|
});
|
|
167
177
|
pendingBrowserMotion = false;
|
|
168
178
|
setNavigationState(navigation, preset);
|
|
169
|
-
navigation.signal.addEventListener(
|
|
170
|
-
|
|
171
|
-
() => {
|
|
172
|
-
if (current === generation) clearNavigationState();
|
|
173
|
-
},
|
|
174
|
-
{ once: true },
|
|
175
|
-
);
|
|
179
|
+
navigation.signal.addEventListener("abort", cancelPreparation, { once: true });
|
|
180
|
+
if (navigation.signal.aborted) cancelPreparation();
|
|
176
181
|
queueMicrotask(() => {
|
|
177
|
-
if (event.defaultPrevented
|
|
182
|
+
if (event.defaultPrevented) cancelPreparation();
|
|
178
183
|
});
|
|
179
184
|
const loader = navigation.loader;
|
|
180
185
|
navigation.loader = async () => {
|
|
181
186
|
try {
|
|
182
187
|
await loader();
|
|
183
|
-
if (
|
|
188
|
+
if (event.defaultPrevented) cancelPreparation();
|
|
189
|
+
else {
|
|
184
190
|
await prepareNavigationFont(navigation.newDocument, navigation.signal);
|
|
185
191
|
}
|
|
186
192
|
} catch (error) {
|
|
187
|
-
|
|
193
|
+
cancelPreparation();
|
|
188
194
|
throw error;
|
|
189
195
|
}
|
|
190
196
|
};
|
|
@@ -194,6 +200,7 @@ if (!transitionWindow.__STALUX_VT_LISTENER__) {
|
|
|
194
200
|
const navigation = event as unknown as NavigationEvent;
|
|
195
201
|
if (navigation.signal.aborted) return;
|
|
196
202
|
const current = generation;
|
|
203
|
+
swappedNavigation = current;
|
|
197
204
|
preserveHeaderMetrics(navigation.newDocument);
|
|
198
205
|
// Astro replaces the root attributes during swap. Carry state into the
|
|
199
206
|
// new document; CSS keyframes read these data-* attributes to pick their
|
|
@@ -219,6 +226,8 @@ if (!transitionWindow.__STALUX_VT_LISTENER__) {
|
|
|
219
226
|
});
|
|
220
227
|
|
|
221
228
|
document.addEventListener("astro:page-load", () => {
|
|
229
|
+
// A previous route's scripts can finish while a newer loader is pending.
|
|
230
|
+
if (swappedNavigation === generation) pendingNavigation = 0;
|
|
222
231
|
setRouteState(window.location.pathname);
|
|
223
232
|
});
|
|
224
233
|
|