@anglefeint/astro-theme 0.1.22 → 0.1.23
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/package.json
CHANGED
|
@@ -108,12 +108,22 @@ const enableRedQueen = THEME.EFFECTS.ENABLE_RED_QUEEN;
|
|
|
108
108
|
{heroImage && (
|
|
109
109
|
<div class="hero-shell">
|
|
110
110
|
<div class="hero-pane">
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
<div class="hero-image">
|
|
112
|
+
<div class="hero-stack">
|
|
113
|
+
<div class="hero-base-wrap">
|
|
114
|
+
<Image
|
|
115
|
+
class="hero-base-image"
|
|
116
|
+
src={heroImage}
|
|
117
|
+
alt={title}
|
|
118
|
+
loading="eager"
|
|
119
|
+
decoding="async"
|
|
120
|
+
fetchpriority="high"
|
|
121
|
+
/>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="hero-canvas-wrap" aria-hidden="true">
|
|
124
|
+
<canvas class="hero-canvas" data-hero-src={heroImage.src}></canvas>
|
|
125
|
+
</div>
|
|
115
126
|
</div>
|
|
116
|
-
</div>
|
|
117
127
|
<div class="hero-frame" aria-hidden="true">
|
|
118
128
|
<span>neural monitor</span>
|
|
119
129
|
<span class="hero-frame-dot"></span>
|
|
@@ -15,8 +15,12 @@ export function initHeroCanvas(prefersReducedMotion) {
|
|
|
15
15
|
var heroStart = 0;
|
|
16
16
|
var heroRaf = 0;
|
|
17
17
|
var resizeTimer = 0;
|
|
18
|
+
var prepareTimer = 0;
|
|
19
|
+
var prepareIdleHandle = 0;
|
|
18
20
|
var isInViewport = true;
|
|
19
21
|
var heroObserver = null;
|
|
22
|
+
var heroEffectsPrepared = false;
|
|
23
|
+
var heroEffectsPreparing = false;
|
|
20
24
|
var baseCanvas = document.createElement('canvas');
|
|
21
25
|
var baseCtx = baseCanvas.getContext('2d');
|
|
22
26
|
var pixelCanvas = document.createElement('canvas');
|
|
@@ -251,7 +255,7 @@ export function initHeroCanvas(prefersReducedMotion) {
|
|
|
251
255
|
}
|
|
252
256
|
|
|
253
257
|
function startHeroLoop() {
|
|
254
|
-
if (prefersReducedMotion || document.hidden || !isInViewport || !canvas.img || heroRaf) return;
|
|
258
|
+
if (prefersReducedMotion || document.hidden || !isInViewport || !canvas.img || !heroEffectsPrepared || heroRaf) return;
|
|
255
259
|
heroRaf = requestAnimationFrame(heroRender);
|
|
256
260
|
}
|
|
257
261
|
|
|
@@ -261,17 +265,60 @@ export function initHeroCanvas(prefersReducedMotion) {
|
|
|
261
265
|
heroRaf = 0;
|
|
262
266
|
}
|
|
263
267
|
|
|
268
|
+
function drawStaticFrame(img) {
|
|
269
|
+
var w = canvas.width;
|
|
270
|
+
var h = canvas.height;
|
|
271
|
+
baseCanvas.width = w;
|
|
272
|
+
baseCanvas.height = h;
|
|
273
|
+
drawBase(baseCtx, img, w, h);
|
|
274
|
+
ctx.clearRect(0, 0, w, h);
|
|
275
|
+
ctx.drawImage(baseCanvas, 0, 0);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function scheduleHeroEffectsPrepare() {
|
|
279
|
+
if (prefersReducedMotion || !canvas.img || heroEffectsPrepared || heroEffectsPreparing) return;
|
|
280
|
+
heroEffectsPreparing = true;
|
|
281
|
+
|
|
282
|
+
function runPrepare() {
|
|
283
|
+
prepareTimer = 0;
|
|
284
|
+
prepareIdleHandle = 0;
|
|
285
|
+
if (!canvas.img) {
|
|
286
|
+
heroEffectsPreparing = false;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
buildEdge(canvas.img);
|
|
290
|
+
heroEffectsPrepared = true;
|
|
291
|
+
heroEffectsPreparing = false;
|
|
292
|
+
startHeroLoop();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (typeof window.requestIdleCallback === 'function') {
|
|
296
|
+
prepareIdleHandle = window.requestIdleCallback(runPrepare, { timeout: 1200 });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function afterLoad() {
|
|
301
|
+
prepareTimer = setTimeout(runPrepare, 180);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (document.readyState === 'complete') afterLoad();
|
|
305
|
+
else window.addEventListener('load', afterLoad, { once: true });
|
|
306
|
+
}
|
|
307
|
+
|
|
264
308
|
var img = new Image();
|
|
265
309
|
img.onload = function() {
|
|
266
310
|
canvas.img = img;
|
|
267
311
|
sizeCanvas();
|
|
268
|
-
|
|
312
|
+
drawStaticFrame(img);
|
|
269
313
|
wrap.classList.add('ready');
|
|
270
314
|
if (prefersReducedMotion) {
|
|
271
|
-
ctx.drawImage(baseCanvas, 0, 0);
|
|
272
315
|
return;
|
|
273
316
|
}
|
|
274
|
-
|
|
317
|
+
// Keep first paint static for LCP, then prepare heavy effects when idle.
|
|
318
|
+
scheduleHeroEffectsPrepare();
|
|
319
|
+
};
|
|
320
|
+
img.onerror = function() {
|
|
321
|
+
wrap.classList.add('ready');
|
|
275
322
|
};
|
|
276
323
|
img.src = new URL(src, window.location.href).href;
|
|
277
324
|
|
|
@@ -281,7 +328,8 @@ export function initHeroCanvas(prefersReducedMotion) {
|
|
|
281
328
|
resizeTimer = setTimeout(function() {
|
|
282
329
|
resizeTimer = 0;
|
|
283
330
|
sizeCanvas();
|
|
284
|
-
|
|
331
|
+
drawStaticFrame(canvas.img);
|
|
332
|
+
if (heroEffectsPrepared) buildEdge(canvas.img);
|
|
285
333
|
}, 180);
|
|
286
334
|
}, { passive: true });
|
|
287
335
|
|
|
@@ -309,6 +357,10 @@ export function initHeroCanvas(prefersReducedMotion) {
|
|
|
309
357
|
window.addEventListener('beforeunload', function() {
|
|
310
358
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
311
359
|
stopHeroLoop();
|
|
360
|
+
if (prepareTimer) clearTimeout(prepareTimer);
|
|
361
|
+
if (prepareIdleHandle && typeof window.cancelIdleCallback === 'function') {
|
|
362
|
+
window.cancelIdleCallback(prepareIdleHandle);
|
|
363
|
+
}
|
|
312
364
|
if (heroObserver) heroObserver.disconnect();
|
|
313
365
|
}, { once: true });
|
|
314
366
|
}
|
|
@@ -8,7 +8,7 @@ export function initRedQueenTv(prefersReducedMotion) {
|
|
|
8
8
|
var source2 = stage.getAttribute('data-rq-src2') || '';
|
|
9
9
|
if (!source) return;
|
|
10
10
|
|
|
11
|
-
var OPEN_DELAY_MS =
|
|
11
|
+
var OPEN_DELAY_MS = 2000;
|
|
12
12
|
var COLLAPSE_DELAY_MS = 260;
|
|
13
13
|
var FRAME_MS = 33;
|
|
14
14
|
var FALLBACK_STEP_MS = 650;
|
|
@@ -24,6 +24,10 @@ export function initRedQueenTv(prefersReducedMotion) {
|
|
|
24
24
|
var revealTimer = 0;
|
|
25
25
|
var preloadTimeoutTimer = 0;
|
|
26
26
|
var preloadRetryTimers = new Set();
|
|
27
|
+
var autoDelayTimer = 0;
|
|
28
|
+
var autoIdleHandle = 0;
|
|
29
|
+
var autoLoadHandler = null;
|
|
30
|
+
var autoStarted = false;
|
|
27
31
|
|
|
28
32
|
var start = 0;
|
|
29
33
|
var width = 320;
|
|
@@ -105,6 +109,21 @@ export function initRedQueenTv(prefersReducedMotion) {
|
|
|
105
109
|
preloadRetryTimers.clear();
|
|
106
110
|
}
|
|
107
111
|
|
|
112
|
+
function clearAutoStartTimers() {
|
|
113
|
+
if (autoDelayTimer) {
|
|
114
|
+
clearTimeout(autoDelayTimer);
|
|
115
|
+
autoDelayTimer = 0;
|
|
116
|
+
}
|
|
117
|
+
if (autoIdleHandle && typeof window.cancelIdleCallback === 'function') {
|
|
118
|
+
window.cancelIdleCallback(autoIdleHandle);
|
|
119
|
+
autoIdleHandle = 0;
|
|
120
|
+
}
|
|
121
|
+
if (autoLoadHandler) {
|
|
122
|
+
window.removeEventListener('load', autoLoadHandler);
|
|
123
|
+
autoLoadHandler = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
108
127
|
function scheduleSequence(fn, delay) {
|
|
109
128
|
clearSequenceTimer();
|
|
110
129
|
sequenceTimer = setTimeout(function runTask() {
|
|
@@ -283,6 +302,7 @@ export function initRedQueenTv(prefersReducedMotion) {
|
|
|
283
302
|
forceStaticUntil = 0;
|
|
284
303
|
clearSequenceTimer();
|
|
285
304
|
clearPreloadTimers();
|
|
305
|
+
clearAutoStartTimers();
|
|
286
306
|
if (revealTimer) {
|
|
287
307
|
clearTimeout(revealTimer);
|
|
288
308
|
revealTimer = 0;
|
|
@@ -535,22 +555,53 @@ export function initRedQueenTv(prefersReducedMotion) {
|
|
|
535
555
|
}
|
|
536
556
|
|
|
537
557
|
function queueAutoPlay() {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
558
|
+
var readyByDelay = false;
|
|
559
|
+
var readyByLoad = document.readyState === 'complete';
|
|
560
|
+
var readyByIdle = false;
|
|
561
|
+
|
|
562
|
+
function tryAutoStart() {
|
|
563
|
+
if (autoStarted || !readyByDelay || !readyByLoad || !readyByIdle) return;
|
|
564
|
+
if (document.hidden) {
|
|
565
|
+
pendingAutoPlay = true;
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
autoStarted = true;
|
|
569
|
+
clearAutoStartTimers();
|
|
570
|
+
startPlayback();
|
|
547
571
|
}
|
|
548
572
|
|
|
549
|
-
|
|
550
|
-
|
|
573
|
+
autoDelayTimer = setTimeout(function() {
|
|
574
|
+
autoDelayTimer = 0;
|
|
575
|
+
readyByDelay = true;
|
|
576
|
+
tryAutoStart();
|
|
577
|
+
}, OPEN_DELAY_MS);
|
|
578
|
+
|
|
579
|
+
if (!readyByLoad) {
|
|
580
|
+
autoLoadHandler = function() {
|
|
581
|
+
readyByLoad = true;
|
|
582
|
+
autoLoadHandler = null;
|
|
583
|
+
tryAutoStart();
|
|
584
|
+
};
|
|
585
|
+
window.addEventListener('load', autoLoadHandler, { once: true });
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (typeof window.requestIdleCallback === 'function') {
|
|
589
|
+
autoIdleHandle = window.requestIdleCallback(function() {
|
|
590
|
+
autoIdleHandle = 0;
|
|
591
|
+
readyByIdle = true;
|
|
592
|
+
tryAutoStart();
|
|
593
|
+
}, { timeout: 1500 });
|
|
594
|
+
} else {
|
|
595
|
+
setTimeout(function() {
|
|
596
|
+
readyByIdle = true;
|
|
597
|
+
tryAutoStart();
|
|
598
|
+
}, 600);
|
|
599
|
+
}
|
|
551
600
|
}
|
|
552
601
|
|
|
553
602
|
toggle.addEventListener('click', function() {
|
|
603
|
+
autoStarted = true;
|
|
604
|
+
clearAutoStartTimers();
|
|
554
605
|
startPlayback();
|
|
555
606
|
});
|
|
556
607
|
|
|
@@ -14,11 +14,48 @@ function prefersReducedMotionEnabled() {
|
|
|
14
14
|
|
|
15
15
|
export function initBlogpostEffects() {
|
|
16
16
|
var prefersReducedMotion = prefersReducedMotionEnabled();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
var networkStarted = false;
|
|
18
|
+
var redQueenStarted = false;
|
|
19
|
+
|
|
20
|
+
function startNetworkCanvas() {
|
|
21
|
+
if (networkStarted) return;
|
|
22
|
+
networkStarted = true;
|
|
23
|
+
initNetworkCanvas(prefersReducedMotion);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function startRedQueenTv() {
|
|
27
|
+
if (redQueenStarted) return;
|
|
28
|
+
if (!document.querySelector('.rq-tv-stage')) return;
|
|
29
|
+
redQueenStarted = true;
|
|
21
30
|
initRedQueenTv(prefersReducedMotion);
|
|
22
31
|
}
|
|
32
|
+
|
|
33
|
+
function scheduleDeferredStarts() {
|
|
34
|
+
function fallbackSchedule() {
|
|
35
|
+
function runAfterLoad() {
|
|
36
|
+
setTimeout(startNetworkCanvas, 120);
|
|
37
|
+
setTimeout(startRedQueenTv, 460);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (document.readyState === 'complete') runAfterLoad();
|
|
41
|
+
else window.addEventListener('load', runAfterLoad, { once: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (typeof window.requestIdleCallback !== 'function') {
|
|
45
|
+
fallbackSchedule();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
window.requestIdleCallback(function() {
|
|
50
|
+
startNetworkCanvas();
|
|
51
|
+
window.requestIdleCallback(function() {
|
|
52
|
+
startRedQueenTv();
|
|
53
|
+
}, { timeout: 2200 });
|
|
54
|
+
}, { timeout: 1200 });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
initReadProgressAndBackToTop(prefersReducedMotion);
|
|
58
|
+
initHeroCanvas(prefersReducedMotion);
|
|
23
59
|
initPostInteractions(prefersReducedMotion);
|
|
60
|
+
scheduleDeferredStarts();
|
|
24
61
|
}
|
package/src/styles/blog-post.css
CHANGED
|
@@ -27,16 +27,27 @@
|
|
|
27
27
|
0 24px 48px rgba(8, 18, 30, 0.68),
|
|
28
28
|
0 0 34px rgba(8, 18, 30, 0.64);
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
.hero-stack {
|
|
31
|
+
position: relative;
|
|
32
|
+
aspect-ratio: 1020 / 510;
|
|
33
|
+
background: #0a1218;
|
|
34
|
+
}
|
|
35
|
+
.hero-base-wrap {
|
|
36
|
+
position: absolute;
|
|
37
|
+
inset: 0;
|
|
38
|
+
z-index: 0;
|
|
39
|
+
}
|
|
40
|
+
.hero-base-image {
|
|
41
|
+
width: 100%;
|
|
42
|
+
height: 100%;
|
|
43
|
+
object-fit: cover;
|
|
44
|
+
display: block;
|
|
45
|
+
}
|
|
46
|
+
.hero-canvas-wrap {
|
|
47
|
+
position: absolute;
|
|
48
|
+
inset: 0;
|
|
49
|
+
z-index: 1;
|
|
50
|
+
opacity: 0;
|
|
40
51
|
transition: opacity 260ms ease;
|
|
41
52
|
}
|
|
42
53
|
.hero-canvas-wrap.ready { opacity: 1; }
|