animot-presenter 0.5.16 → 0.5.18

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 CHANGED
@@ -358,9 +358,24 @@ export class DemoComponent implements AfterViewInit {
358
358
  | `keyboard` | `boolean` | `true` | Enable arrow key navigation |
359
359
  | `duration` | `number` | — | Override all transition durations (ms) |
360
360
  | `start-slide` | `number` | `0` | Initial slide index |
361
+ | `mute-narration` | `boolean` | `false` | Force-disable per-slide voice narration regardless of the project's `settings.narrationEnabled`. Use on previews / gallery cards where audio would be intrusive. |
361
362
 
362
363
  **Note:** `data` can only be set via JavaScript property, not as an HTML attribute.
363
364
 
365
+ ### Per-slide voice narration
366
+
367
+ Projects with `settings.narrationEnabled: true` and per-slide `narration` clips
368
+ play voice-over alongside slide changes. Narration is bound to the deck's play
369
+ state — pressing the play button starts narration, pause stops it. To disable
370
+ narration on a specific embed regardless of the project's setting, set
371
+ `mute-narration`.
372
+
373
+ Recommended pattern for share-link / hero usage with narration: omit `autoplay`
374
+ (the deck loads paused) so the viewer's first click on Play doubles as the
375
+ gesture browsers require to unlock audio. Embedded gallery / preview surfaces
376
+ where audio would be intrusive should pass `mute-narration` and keep
377
+ `autoplay`.
378
+
364
379
  ## Events
365
380
 
366
381
  | Event | Detail | Description |
@@ -155,7 +155,7 @@
155
155
  let {
156
156
  src, data, autoplay = false, loop = false, controls = true, arrows = false,
157
157
  progress: showProgress = true, keyboard = true, duration: durationOverride,
158
- startSlide = 0, class: className = '', onslidechange, oncomplete
158
+ startSlide = 0, muteNarration = false, class: className = '', onslidechange, oncomplete
159
159
  }: AnimotPresenterProps = $props();
160
160
 
161
161
  // State
@@ -199,6 +199,7 @@
199
199
  // the user's click on the play control is itself the unlocking gesture.
200
200
  let narrationAudio: HTMLAudioElement | null = null;
201
201
  function playNarrationForSlide(index: number) {
202
+ if (muteNarration) return;
202
203
  if (!project?.settings?.narrationEnabled) return;
203
204
  const slide = project?.slides?.[index];
204
205
  if (narrationAudio) {
@@ -558,6 +559,12 @@
558
559
  currentSlideIndex = 0;
559
560
  isTransitioning = false;
560
561
 
562
+ // Restart narration on loop. Setting `currentSlideIndex = 0` above
563
+ // is a no-op for single-slide decks (was already 0) so the play-state
564
+ // effect doesn't re-fire on its own. Calling explicitly here covers
565
+ // both single- and multi-slide loops uniformly.
566
+ if (isAutoplay) playNarrationForSlide(0);
567
+
561
568
  for (const element of firstSlide.canvas.elements) {
562
569
  if (element.type === 'text') {
563
570
  const textEl = element as TextElement;
@@ -578,10 +585,12 @@
578
585
  const targetSlide = slides[targetIndex];
579
586
  clearAllTypewriterAnimations();
580
587
  cancelMotionPathLoops();
581
- // Trigger per-slide narration only while the deck is actively
582
- // playing. Manual nav while paused stays silent — narration is
583
- // bound to the play button, not to every interaction.
584
- if (isAutoplay) playNarrationForSlide(targetIndex);
588
+ // Manual arrow nav and the autoplay timer are both forms of "user
589
+ // is moving forward in the deck"both should swap narration to
590
+ // the new slide. The pause button is what stops audio. Without
591
+ // this, clicking an arrow while paused would render the new slide
592
+ // silently, which feels broken.
593
+ playNarrationForSlide(targetIndex);
585
594
  const transition = targetSlide.transition;
586
595
  const duration = durationOverride ?? transition.duration;
587
596
  transitionDurationMs = duration;