animot-presenter 0.5.13 → 0.5.14
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/AnimotPresenter.svelte +36 -1
- package/dist/cdn/animot-presenter.esm.js +3990 -3978
- package/dist/cdn/animot-presenter.min.js +8 -8
- package/dist/types.d.ts +14 -0
- package/package.json +1 -1
|
@@ -187,6 +187,30 @@
|
|
|
187
187
|
let menuVisible = $state(true);
|
|
188
188
|
let mouseIdleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
189
189
|
|
|
190
|
+
// Single <audio> element for per-slide narration playback. Only used
|
|
191
|
+
// when `project.settings.narrationEnabled` is true. Lazy-allocated so
|
|
192
|
+
// decks without narration don't pay for it.
|
|
193
|
+
let narrationAudio: HTMLAudioElement | null = null;
|
|
194
|
+
function playNarrationForSlide(index: number) {
|
|
195
|
+
if (!project?.settings?.narrationEnabled) return;
|
|
196
|
+
const slide = project?.slides?.[index];
|
|
197
|
+
if (narrationAudio) {
|
|
198
|
+
narrationAudio.pause();
|
|
199
|
+
narrationAudio.currentTime = 0;
|
|
200
|
+
}
|
|
201
|
+
const src = slide?.narration?.src;
|
|
202
|
+
if (!src) return;
|
|
203
|
+
if (!narrationAudio) narrationAudio = new Audio();
|
|
204
|
+
narrationAudio.src = src;
|
|
205
|
+
// First play() may reject under autoplay policy; the player's first
|
|
206
|
+
// user gesture (pressing play / clicking the deck) unlocks the audio
|
|
207
|
+
// context and subsequent slides will work.
|
|
208
|
+
narrationAudio.play().catch(() => {});
|
|
209
|
+
}
|
|
210
|
+
function stopNarration() {
|
|
211
|
+
if (narrationAudio) { narrationAudio.pause(); narrationAudio = null; }
|
|
212
|
+
}
|
|
213
|
+
|
|
190
214
|
const slides = $derived(project?.slides ?? []);
|
|
191
215
|
const currentSlide = $derived(slides[currentSlideIndex]);
|
|
192
216
|
const isCinemaMode = $derived(project?.mode === 'cinema');
|
|
@@ -547,6 +571,12 @@
|
|
|
547
571
|
const targetSlide = slides[targetIndex];
|
|
548
572
|
clearAllTypewriterAnimations();
|
|
549
573
|
cancelMotionPathLoops();
|
|
574
|
+
// Trigger per-slide narration. No-op when `narrationEnabled` is off
|
|
575
|
+
// or the slide has no narration clip. First call may be blocked by
|
|
576
|
+
// the browser's autoplay policy; the deck consumer should suppress
|
|
577
|
+
// `autoplay` when narration is on so the viewer's first nav-click
|
|
578
|
+
// (which gets us here) acts as the unlocking gesture.
|
|
579
|
+
playNarrationForSlide(targetIndex);
|
|
550
580
|
const transition = targetSlide.transition;
|
|
551
581
|
const duration = durationOverride ?? transition.duration;
|
|
552
582
|
transitionDurationMs = duration;
|
|
@@ -1106,6 +1136,11 @@
|
|
|
1106
1136
|
await loadCodeHighlights();
|
|
1107
1137
|
loading = false;
|
|
1108
1138
|
if (currentSlide) setTimeout(() => animateMotionPaths(currentSlide!), 300);
|
|
1139
|
+
// First-slide narration. Browsers may block this until the
|
|
1140
|
+
// viewer interacts; downstream code (e.g. share-link page)
|
|
1141
|
+
// should already disable autoplay when narration is on so the
|
|
1142
|
+
// click that starts the deck doubles as the audio unlock.
|
|
1143
|
+
playNarrationForSlide(currentSlideIndex);
|
|
1109
1144
|
if (autoplay) isAutoplay = true;
|
|
1110
1145
|
} catch (e: any) { error = e.message; loading = false; }
|
|
1111
1146
|
}
|
|
@@ -1123,7 +1158,7 @@
|
|
|
1123
1158
|
});
|
|
1124
1159
|
if (containerEl) resizeObserver.observe(containerEl);
|
|
1125
1160
|
resetMouseIdleTimer();
|
|
1126
|
-
return () => { resizeObserver?.disconnect(); clearAutoplayTimer(); clearAllTypewriterAnimations(); if (mouseIdleTimer) clearTimeout(mouseIdleTimer); };
|
|
1161
|
+
return () => { resizeObserver?.disconnect(); clearAutoplayTimer(); clearAllTypewriterAnimations(); if (mouseIdleTimer) clearTimeout(mouseIdleTimer); stopNarration(); };
|
|
1127
1162
|
});
|
|
1128
1163
|
|
|
1129
1164
|
// Watch for prop changes
|