@bendyline/squisq-react 1.4.2 → 2.0.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.
Files changed (50) hide show
  1. package/README.md +30 -3
  2. package/dist/index.d.ts +177 -28
  3. package/dist/index.js +1330 -611
  4. package/dist/index.js.map +1 -1
  5. package/dist/squisq-player.css +1 -1
  6. package/dist/squisq-player.css.map +1 -1
  7. package/dist/squisq-player.global.js +57 -37
  8. package/dist/squisq-player.global.js.map +1 -1
  9. package/dist/standalone-source.js +1 -1
  10. package/dist/styles/index.css +28 -0
  11. package/package.json +2 -2
  12. package/src/BlockRenderer.tsx +54 -17
  13. package/src/DocControlsSlideshow.tsx +222 -5
  14. package/src/DocPlayer.tsx +367 -183
  15. package/src/DocPlayerWithSidebar.tsx +4 -0
  16. package/src/DocProgressBar.tsx +40 -1
  17. package/src/LinearDocView.tsx +138 -62
  18. package/src/MarkdownRenderer.tsx +40 -97
  19. package/src/MediaClipLayer.tsx +12 -2
  20. package/src/__tests__/BlockRenderer.test.tsx +138 -8
  21. package/src/__tests__/DocControlsSlideshow.test.tsx +94 -1
  22. package/src/__tests__/DocPlayer.test.tsx +505 -0
  23. package/src/__tests__/DocProgressBar.test.tsx +28 -2
  24. package/src/__tests__/LinearDocView.test.tsx +104 -11
  25. package/src/__tests__/MapLayer.test.tsx +63 -0
  26. package/src/__tests__/MarkdownRenderer.test.tsx +16 -5
  27. package/src/__tests__/MediaClipLayer.test.tsx +70 -0
  28. package/src/__tests__/MediaContext.test.tsx +51 -0
  29. package/src/__tests__/PathLayer.test.tsx +12 -1
  30. package/src/__tests__/VideoLayer.test.tsx +94 -0
  31. package/src/__tests__/fillStyle.test.tsx +50 -2
  32. package/src/__tests__/standaloneEntry.test.tsx +103 -0
  33. package/src/__tests__/useAudioSync.test.ts +49 -0
  34. package/src/__tests__/useDocPlayback.transition.test.ts +48 -5
  35. package/src/__tests__/useViewportOrientation.test.ts +22 -0
  36. package/src/hooks/MediaContext.tsx +12 -3
  37. package/src/hooks/useAudioSync.ts +61 -12
  38. package/src/hooks/useDocPlayback.ts +40 -12
  39. package/src/hooks/useViewportOrientation.ts +2 -4
  40. package/src/index.ts +5 -2
  41. package/src/layers/ImageLayer.tsx +106 -1
  42. package/src/layers/MapLayer.tsx +7 -6
  43. package/src/layers/PathLayer.tsx +20 -11
  44. package/src/layers/ShapeLayer.tsx +33 -9
  45. package/src/layers/TextLayer.tsx +4 -3
  46. package/src/layers/TreeLayer.tsx +167 -0
  47. package/src/layers/VideoLayer.tsx +20 -6
  48. package/src/standalone-entry.tsx +91 -14
  49. package/src/styles/doc-animations.css +36 -0
  50. package/src/types.ts +13 -13
package/README.md CHANGED
@@ -70,6 +70,7 @@ Blocks are composed of typed layers rendered as SVG:
70
70
  | `VideoLayer` | Embedded video with playback sync |
71
71
  | `TableLayer` | HTML table embedded via SVG `<foreignObject>` |
72
72
  | `MapLayer` | Tile-based map rendering |
73
+ | `TreeLayer` | Interactive filesystem/outline tree |
73
74
 
74
75
  ## Hooks
75
76
 
@@ -82,24 +83,50 @@ Blocks are composed of typed layers rendered as SVG:
82
83
  | `useAutoSurface` | Live light/dark surface detection via `prefers-color-scheme` |
83
84
  | `useMediaProvider` / `useMediaUrl` | Media URL resolution via `MediaContext` |
84
85
 
86
+ `useDocPlayback` takes configuration as an options object:
87
+
88
+ ```ts
89
+ useDocPlayback(doc, currentTime, { viewport, theme, onSeek });
90
+ ```
91
+
85
92
  ## Standalone Player
86
93
 
87
94
  A self-contained global build is available for non-React environments. It
88
- exposes a `SquisqPlayer` global with `mount`, `mountStatic`, `unmount`, and
89
- `version`:
95
+ exposes a `SquisqPlayer` global with `mount`, `getHandle`, `unmount`, and
96
+ `version`. `mount` returns an instance handle.
97
+
98
+ The former `mountStatic()` shortcut was removed; pass `mode: 'static'` to
99
+ `mount()`. Render methods are instance-scoped and are no longer copied to
100
+ top-level `window.seekTo` / `window.getDuration` properties.
101
+
102
+ Interactive mount:
90
103
 
91
104
  ```html
92
105
  <script src="https://unpkg.com/@bendyline/squisq-react/dist/squisq-player.global.js"></script>
93
106
  <div id="player"></div>
94
107
  <script>
95
108
  // docJson is a Doc (e.g. produced by markdownToDoc and serialized)
96
- SquisqPlayer.mount(document.getElementById('player'), docJson, {
109
+ const root = document.getElementById('player');
110
+ const handle = SquisqPlayer.mount(root, docJson, {
97
111
  mode: 'slideshow', // or 'static' for a scrollable document view
98
112
  basePath: '/',
99
113
  });
114
+
115
+ // In render mode: const api = await handle.renderAPI;
116
+ // The same handle is available later as SquisqPlayer.getHandle(root).
100
117
  </script>
101
118
  ```
102
119
 
120
+ For headless capture, add `renderMode: true`, then await
121
+ `handle.renderAPI` before calling `seekTo()` or reading render metadata.
122
+ TypeScript hosts can import `MountOptions` and `SquisqPlayerHandle` from the
123
+ package root.
124
+
125
+ Set `animationsEnabled: false` on `DocPlayer`, `BlockRenderer`, or standalone
126
+ `mount()` to render authored layer animations and block transitions as static
127
+ content. Embedded video, timed media, captions, audio, and document timing stay
128
+ active; this makes the option suitable for compact MP4 and animated-GIF export.
129
+
103
130
  For build-time embedding, `@bendyline/squisq-react/standalone-source` exports
104
131
  the same bundle as a string constant (`PLAYER_BUNDLE`) — used by
105
132
  `@bendyline/squisq-formats` and the CLI to produce single-file HTML exports.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Block, Doc, Theme, SurfaceScheme, Transition, CaptionTrack, ViewportConfig as ViewportConfig$1, ImageLayer as ImageLayer$1, TextLayer as TextLayer$1, ShapeLayer as ShapeLayer$1, PathLayer as PathLayer$1, VideoLayer as VideoLayer$1, TableLayer as TableLayer$1, MapLayer as MapLayer$1, ScheduledClip, AudioTrack, MediaProvider } from '@bendyline/squisq/schemas';
2
+ import { Block, Doc, Theme, SurfaceScheme, Transition, CaptionTrack, ViewportConfig as ViewportConfig$1, ImageLayer as ImageLayer$1, TextLayer as TextLayer$1, ShapeLayer as ShapeLayer$1, PathLayer as PathLayer$1, VideoLayer as VideoLayer$1, TableLayer as TableLayer$1, TreeLayer as TreeLayer$1, MapLayer as MapLayer$1, ScheduledClip, AudioTrack, MediaProvider } from '@bendyline/squisq/schemas';
3
3
  import { ViewportConfig, ViewportOrientation } from '@bendyline/squisq/doc';
4
4
  export { getAnimationStyle, getTransitionClass } from '@bendyline/squisq/doc';
5
5
  import { MarkdownBlockNode, HtmlPolicy } from '@bendyline/squisq/markdown';
@@ -86,8 +86,12 @@ type ControlsLayout = 'overlay' | 'sidebar' | 'bottom';
86
86
  * `markdownDocToPlainHtml` export produces. No SquisqPlayer, no SVG
87
87
  * cards — just `<h1>`/`<p>`/`<ul>` etc. inside a sandboxed iframe.
88
88
  * Use when you want a WYSIWYG view of the simple HTML export.
89
+ * - `'narrate'` — Teleprompter/performance surface. DocPlayer does not
90
+ * implement this mode; it is owned by the editor package
91
+ * (`@bendyline/squisq-editor-react`), which renders its own
92
+ * voice-paced teleprompter view for it.
89
93
  */
90
- type DisplayMode = 'video' | 'slideshow' | 'linear' | 'page';
94
+ type DisplayMode = 'video' | 'slideshow' | 'linear' | 'page' | 'narrate';
91
95
  /**
92
96
  * Caption display style.
93
97
  *
@@ -117,6 +121,8 @@ interface PlaybackState$1 {
117
121
  isPlaying: boolean;
118
122
  currentTime: number;
119
123
  totalDuration: number;
124
+ /** Whether the managed cover is the visual currently shown. */
125
+ isCoverVisible?: boolean;
120
126
  currentBlockIndex: number;
121
127
  totalBlocks: number;
122
128
  docProgress: number;
@@ -184,15 +190,15 @@ interface RenderChapterInfo {
184
190
  duration: number;
185
191
  }
186
192
  /**
187
- * API surface exposed on `window` in render mode and debug mode.
188
- * Used by Playwright for video export and by ?debug=true for testing.
193
+ * Instance-scoped API created in render mode and debug mode.
194
+ * React hosts receive it via `DocPlayer.onRenderAPIReady`; standalone hosts
195
+ * receive it from their mount handle.
189
196
  *
190
197
  * @example
191
198
  * ```ts
192
- * // In Playwright:
193
- * const w = window as unknown as SquisqWindow;
194
- * await w.seekTo!(5.0);
195
- * const blocks = w.getBlocks!();
199
+ * const handle = SquisqPlayer.getHandle(rootElement);
200
+ * const api = await handle?.renderAPI;
201
+ * await api?.seekTo(5.0);
196
202
  * ```
197
203
  */
198
204
  interface SquisqRenderAPI {
@@ -206,11 +212,6 @@ interface SquisqRenderAPI {
206
212
  hideCover: () => Promise<void>;
207
213
  hasCoverBlock: () => boolean;
208
214
  }
209
- /**
210
- * Window augmented with optional SquisqRenderAPI properties.
211
- * Each property is optional because they're only present in render/debug mode.
212
- */
213
- type SquisqWindow = Window & typeof globalThis & Partial<SquisqRenderAPI>;
214
215
  /** Format time in seconds to MM:SS string */
215
216
  declare function formatTime(seconds: number): string;
216
217
 
@@ -229,8 +230,19 @@ interface DocPlayerProps {
229
230
  markdown?: string;
230
231
  /** Base path for resolving media URLs (default: `'.'`) */
231
232
  basePath?: string;
232
- /** Render mode for video capture (hides controls, exposes seekTo) */
233
+ /** Render mode for video capture (hides controls and creates a render API). */
233
234
  renderMode?: boolean;
235
+ /**
236
+ * Whether to render slide transitions and per-layer animations (default: true).
237
+ * Set to false for static slide changes while preserving timeline and media
238
+ * playback.
239
+ */
240
+ animationsEnabled?: boolean;
241
+ /**
242
+ * Receives this player's instance-scoped render API, and `null` on cleanup.
243
+ * The API is created in render mode and `?debug=true` mode only.
244
+ */
245
+ onRenderAPIReady?: (api: SquisqRenderAPI | null) => void;
234
246
  /** Auto-play when loaded */
235
247
  autoPlay?: boolean;
236
248
  /** Callback when playback ends */
@@ -291,6 +303,12 @@ interface DocPlayerProps {
291
303
  * `doc.startBlock`. Defaults to true for existing documents.
292
304
  */
293
305
  showCoverSlide?: boolean;
306
+ /**
307
+ * Optional controlled cover visibility. Intended for synchronized audience
308
+ * mirrors that follow another DocPlayer's visual cursor. When omitted, the
309
+ * player owns its normal cover lifecycle.
310
+ */
311
+ coverVisible?: boolean;
294
312
  /** Caption display style (default: 'standard').
295
313
  * 'social' shows large centered words with the active word highlighted. */
296
314
  captionStyle?: CaptionStyle;
@@ -301,6 +319,12 @@ interface DocPlayerProps {
301
319
  * `displayMode === 'slideshow'` and not in render/headless mode.
302
320
  */
303
321
  enableSwipe?: boolean;
322
+ /**
323
+ * Listen for playback/navigation shortcuts at the document level instead of
324
+ * requiring this player to hold focus. Intended for a primary preview or
325
+ * standalone presentation; leave disabled when several players share a page.
326
+ */
327
+ globalKeyboardShortcuts?: boolean;
304
328
  }
305
329
  /**
306
330
  * Front-door component: resolves the `doc` / `markdown` props into a Doc
@@ -310,11 +334,80 @@ interface DocPlayerProps {
310
334
  */
311
335
  declare function DocPlayer(props: DocPlayerProps): react_jsx_runtime.JSX.Element;
312
336
 
313
- /** Default viewport dimensions (1080p landscape) - for backwards compatibility */
314
- declare const VIEWPORT: {
315
- width: number;
316
- height: number;
317
- };
337
+ /**
338
+ * Standalone Entry Point — IIFE bundle for self-contained HTML rendering.
339
+ *
340
+ * This file is the entry point for the standalone `squisq-player.iife.js` bundle.
341
+ * It bundles Preact (via preact/compat), squisq core, and all rendering components
342
+ * into a single self-contained script that can be loaded in any HTML page.
343
+ *
344
+ * The bundle exposes a global `SquisqPlayer` object with methods to mount
345
+ * interactive or static document views into any DOM element.
346
+ *
347
+ * Usage (in HTML):
348
+ * <script src="squisq-player.iife.js"></script>
349
+ * <div id="root"></div>
350
+ * <script>
351
+ * const root = document.getElementById('root');
352
+ * const handle = SquisqPlayer.mount(root, docJson, {
353
+ * mode: 'slideshow',
354
+ * images: { 'hero.jpg': 'data:image/jpeg;base64,...' }
355
+ * });
356
+ * // In render mode: const api = await handle.renderAPI;
357
+ * </script>
358
+ */
359
+
360
+ interface MountOptions {
361
+ /** Rendering mode: 'slideshow' (interactive, default) or 'static' (scrollable) */
362
+ mode?: 'slideshow' | 'static';
363
+ /** Base path for resolving relative media URLs */
364
+ basePath?: string;
365
+ /**
366
+ * Map of relative image paths to data URIs or blob URLs.
367
+ * Used in single-HTML exports where images are inlined as base64.
368
+ * Example: { 'hero.jpg': 'data:image/jpeg;base64,...' }
369
+ */
370
+ images?: Record<string, string>;
371
+ /**
372
+ * Map of audio segment names/paths to URLs (data URIs, blob URLs, or relative paths).
373
+ * Used in ZIP exports where audio files are included alongside the HTML.
374
+ */
375
+ audio?: Record<string, string>;
376
+ /** Optional theme override */
377
+ theme?: Theme;
378
+ /** Auto-play on mount (only for slideshow mode, default: false) */
379
+ autoPlay?: boolean;
380
+ /**
381
+ * Capture presentation arrow keys without requiring focus (default: true).
382
+ * Disable when mounting multiple interactive players on the same page.
383
+ */
384
+ globalKeyboardShortcuts?: boolean;
385
+ /**
386
+ * Enable render mode for headless frame capture. The instance API is
387
+ * available through the returned mount handle. Disables controls and
388
+ * auto-play.
389
+ */
390
+ renderMode?: boolean;
391
+ /**
392
+ * Whether to render slide transitions and per-layer animations (default: true).
393
+ * Timed media continues to play when disabled.
394
+ */
395
+ animationsEnabled?: boolean;
396
+ /** Caption style: 'standard' or 'social'. Omit or set to undefined for no captions. */
397
+ captionStyle?: 'standard' | 'social';
398
+ }
399
+ /** Instance handle returned by {@link mount}. */
400
+ interface SquisqPlayerHandle {
401
+ /** DOM element that owns this player instance. */
402
+ readonly element: Element;
403
+ /** Resolves to this instance's render API, or null when render mode is off. */
404
+ readonly renderAPI: Promise<SquisqRenderAPI | null>;
405
+ /** Current render API without waiting for effects to run. */
406
+ getRenderAPI(): SquisqRenderAPI | null;
407
+ /** Unmount this exact player instance. */
408
+ unmount(): void;
409
+ }
410
+
318
411
  /** Viewport configuration type */
319
412
  interface ViewportDimensions {
320
413
  width: number;
@@ -337,8 +430,14 @@ interface BlockRendererProps {
337
430
  viewport?: ViewportDimensions;
338
431
  /** Whether the doc is currently playing (controls video playback) */
339
432
  isPlaying?: boolean;
433
+ /**
434
+ * Whether to render block transitions and layer animations (default: true).
435
+ * Disabling this only removes authored/render-style motion; timed video
436
+ * layers continue to advance normally.
437
+ */
438
+ animationsEnabled?: boolean;
340
439
  }
341
- declare function BlockRenderer({ block, blockTime, basePath, isEntering, isExiting, transition, viewport, isPlaying, }: BlockRendererProps): react_jsx_runtime.JSX.Element;
440
+ declare function BlockRenderer({ block, blockTime, basePath, isEntering, isExiting, transition, viewport, isPlaying, animationsEnabled, }: BlockRendererProps): react_jsx_runtime.JSX.Element;
342
441
 
343
442
  interface CaptionOverlayProps {
344
443
  /** Caption track with timestamped phrases */
@@ -391,11 +490,25 @@ interface DocControlsSidebarProps {
391
490
  }
392
491
  declare function DocControlsSidebar({ state, actions }: DocControlsSidebarProps): react_jsx_runtime.JSX.Element;
393
492
 
493
+ interface SlideshowPickerItem {
494
+ /** Stable identifier for the slide/block. */
495
+ id: string;
496
+ /** Human-facing slide number, or a special label such as "Cover". */
497
+ label: string;
498
+ /** Short description shown in the slide picker. */
499
+ summary: string;
500
+ }
394
501
  interface DocControlsSlideshowProps {
395
502
  state: PlaybackState$1;
396
503
  slideNav: SlideNavActions;
504
+ /** Slides available for direct navigation from the counter popover. */
505
+ slides?: readonly SlideshowPickerItem[];
506
+ /** Controlled open state for hosts that expose their own picker shortcut. */
507
+ pickerOpen?: boolean;
508
+ /** Called whenever the slide picker should open or close. */
509
+ onPickerOpenChange?: (open: boolean) => void;
397
510
  }
398
- declare function DocControlsSlideshow({ state, slideNav }: DocControlsSlideshowProps): react_jsx_runtime.JSX.Element;
511
+ declare function DocControlsSlideshow({ state, slideNav, slides, pickerOpen, onPickerOpenChange, }: DocControlsSlideshowProps): react_jsx_runtime.JSX.Element;
399
512
 
400
513
  interface DocPlayerWithSidebarProps {
401
514
  /** The Doc to play */
@@ -407,6 +520,8 @@ interface DocPlayerWithSidebarProps {
407
520
  onTimeUpdate?: (time: number) => void;
408
521
  /** Optional audio controller (if not provided, uses default HTML5 audio) */
409
522
  audioController?: AudioController;
523
+ /** Whether to render slide transitions and per-layer animations (default: true). */
524
+ animationsEnabled?: boolean;
410
525
  muted?: boolean;
411
526
  captionsEnabled?: boolean;
412
527
  isFullscreen?: boolean;
@@ -423,7 +538,7 @@ interface DocPlayerWithSidebarProps {
423
538
  */
424
539
  theme?: Theme;
425
540
  }
426
- declare function DocPlayerWithSidebar({ doc, basePath, autoPlay, onEnded, onTimeUpdate, audioController, muted, captionsEnabled, isFullscreen, onFullscreenToggle, forceViewport, onPlayingChange, theme, }: DocPlayerWithSidebarProps): react_jsx_runtime.JSX.Element;
541
+ declare function DocPlayerWithSidebar({ doc, basePath, autoPlay, onEnded, onTimeUpdate, audioController, animationsEnabled, muted, captionsEnabled, isFullscreen, onFullscreenToggle, forceViewport, onPlayingChange, theme, }: DocPlayerWithSidebarProps): react_jsx_runtime.JSX.Element;
427
542
 
428
543
  interface DocProgressBarProps {
429
544
  state: PlaybackState$1;
@@ -483,6 +598,8 @@ interface LinearDocViewProps {
483
598
  className?: string;
484
599
  /** Theme to use for rendering (default: DEFAULT_THEME from the theme library) */
485
600
  theme?: Theme;
601
+ /** Whether inline visual cards render their layer animations (default: true). */
602
+ animationsEnabled?: boolean;
486
603
  /**
487
604
  * Optional surface scheme (light / dark paper) overlaid on top of the
488
605
  * theme's colors. Orthogonal to `theme` — a theme picks editorial
@@ -508,6 +625,11 @@ interface LinearDocViewProps {
508
625
  * full-size images would dominate the layout.
509
626
  */
510
627
  imageDisplayMode?: ImageDisplayMode;
628
+ /**
629
+ * Let unmodified Up/Down arrows scroll this view even when it does not
630
+ * currently hold focus. Intended for a primary document preview.
631
+ */
632
+ globalKeyboardShortcuts?: boolean;
511
633
  }
512
634
  type ImageDisplayMode = 'inline' | 'thumbnail';
513
635
  /**
@@ -522,7 +644,7 @@ type ImageDisplayMode = 'inline' | 'thumbnail';
522
644
  * <LinearDocView doc={doc} basePath="/media/" />
523
645
  * ```
524
646
  */
525
- declare function LinearDocView({ doc, markdown, basePath, viewport, className, theme, surface, thinMargins, imageDisplayMode, }: LinearDocViewProps): react_jsx_runtime.JSX.Element;
647
+ declare function LinearDocView({ doc, markdown, basePath, viewport, className, theme, surface, animationsEnabled, thinMargins, imageDisplayMode, globalKeyboardShortcuts, }: LinearDocViewProps): react_jsx_runtime.JSX.Element;
526
648
 
527
649
  interface InlineVideoPlayerProps {
528
650
  /** Source path — resolved through MediaContext when relative. */
@@ -569,8 +691,10 @@ interface ImageLayerProps {
569
691
  };
570
692
  /** Current time relative to block start (for animation timing) */
571
693
  blockTime: number;
694
+ /** Whether authored and responsive image motion should run. */
695
+ animationsEnabled?: boolean;
572
696
  }
573
- declare function ImageLayer({ layer, basePath, viewport, blockTime }: ImageLayerProps): react_jsx_runtime.JSX.Element;
697
+ declare function ImageLayer({ layer, basePath, viewport, blockTime, animationsEnabled, }: ImageLayerProps): react_jsx_runtime.JSX.Element;
574
698
 
575
699
  interface TextLayerProps {
576
700
  layer: TextLayer$1;
@@ -640,6 +764,16 @@ interface TableLayerProps {
640
764
  }
641
765
  declare function TableLayer({ layer, viewport, blockTime }: TableLayerProps): react_jsx_runtime.JSX.Element;
642
766
 
767
+ interface TreeLayerProps {
768
+ layer: TreeLayer$1;
769
+ viewport: {
770
+ width: number;
771
+ height: number;
772
+ };
773
+ blockTime: number;
774
+ }
775
+ declare function TreeLayer({ layer, viewport, blockTime }: TreeLayerProps): react_jsx_runtime.JSX.Element;
776
+
643
777
  interface MapLayerProps {
644
778
  layer: MapLayer$1;
645
779
  /** Base path for resolving relative image URLs */
@@ -660,8 +794,10 @@ interface MediaClipLayerProps {
660
794
  isPlaying: boolean;
661
795
  basePath: string;
662
796
  renderMode?: boolean;
797
+ /** Silence every scheduled clip during live playback. */
798
+ muted?: boolean;
663
799
  }
664
- declare function MediaClipLayer({ schedule, currentTime, isPlaying, basePath, renderMode, }: MediaClipLayerProps): react_jsx_runtime.JSX.Element | null;
800
+ declare function MediaClipLayer({ schedule, currentTime, isPlaying, basePath, renderMode, muted, }: MediaClipLayerProps): react_jsx_runtime.JSX.Element | null;
665
801
 
666
802
  /**
667
803
  * useAudioSync Hook
@@ -677,7 +813,7 @@ declare function MediaClipLayer({ schedule, currentTime, isPlaying, basePath, re
677
813
  * can supply their own AudioController to DocPlayer instead of this hook.
678
814
  */
679
815
 
680
- declare function useAudioSync(audioRef: RefObject<HTMLAudioElement>, audioTrack: AudioTrack | undefined, basePath?: string): AudioController;
816
+ declare function useAudioSync(audioRef: RefObject<HTMLAudioElement>, audioTrack: AudioTrack | undefined, basePath?: string, enabled?: boolean): AudioController;
681
817
 
682
818
  /**
683
819
  * useMediaSchedule
@@ -744,8 +880,21 @@ interface PlaybackActions {
744
880
  prevBlock: () => void;
745
881
  /** Go to specific block by index */
746
882
  goToBlock: (index: number) => void;
883
+ /**
884
+ * Let the identified block enter without remounting the outgoing block.
885
+ * Used when another interaction (such as a swipe) already removed it.
886
+ */
887
+ suppressOutgoingForNextBlock: (blockId: string) => void;
888
+ }
889
+ interface UseDocPlaybackOptions {
890
+ /** Target viewport used to materialize template blocks. */
891
+ viewport?: ViewportConfig;
892
+ /** Active theme used for materialization and transition defaults. */
893
+ theme?: Theme;
894
+ /** Host seek callback used by block navigation actions. */
895
+ onSeek?: (time: number) => void;
747
896
  }
748
- declare function useDocPlayback(script: Doc | null, currentTime: number, viewport?: ViewportConfig, renderMode?: boolean, theme?: Theme): PlaybackState & PlaybackActions;
897
+ declare function useDocPlayback(script: Doc | null, currentTime: number, options?: UseDocPlaybackOptions): PlaybackState & PlaybackActions;
749
898
 
750
899
  /**
751
900
  * useViewportOrientation Hook
@@ -823,4 +972,4 @@ interface JsonViewProps {
823
972
  }
824
973
  declare function JsonView(props: JsonViewProps): react_jsx_runtime.JSX.Element;
825
974
 
826
- export { type AudioActions, type AudioController, type AudioState, type BlockMarker, BlockRenderer, type CaptionMode, CaptionOverlay, type CaptionStyle, type ControlsLayout, type DisplayMode, DocControlsBottom, DocControlsOverlay, DocControlsSidebar, DocControlsSlideshow, DocPlayer, DocPlayerWithSidebar, DocProgressBar, type ImageDisplayMode, ImageLayer, InlineAudioPlayer, type InlineAudioPlayerProps, InlineVideoPlayer, type InlineVideoPlayerProps, JsonView, type JsonViewProps, LinearDocView, type LinearDocViewProps, MapLayer, MarkdownRenderer, MediaClipLayer, type MediaClipLayerProps, MediaContext, type MediaScheduleController, PathLayer, type PlaybackActions$1 as PlaybackActions, type PlaybackState$1 as PlaybackState, type RenderAudioSegmentInfo, type RenderBlockInfo, type RenderCaptionInfo, type RenderChapterInfo, ShapeLayer, type SlideNavActions, SocialCaptionOverlay, type SquisqRenderAPI, type SquisqWindow, TableLayer, TextLayer, VIEWPORT, VideoLayer, formatTime, useAudioSync, useAutoSurface, useDocPlayback, useMediaProvider, useMediaSchedule, useMediaUrl, useViewportOrientation };
975
+ export { type AudioActions, type AudioController, type AudioState, type BlockMarker, BlockRenderer, type CaptionMode, CaptionOverlay, type CaptionStyle, type ControlsLayout, type DisplayMode, DocControlsBottom, DocControlsOverlay, DocControlsSidebar, DocControlsSlideshow, DocPlayer, type DocPlayerProps, DocPlayerWithSidebar, DocProgressBar, type ImageDisplayMode, ImageLayer, InlineAudioPlayer, type InlineAudioPlayerProps, InlineVideoPlayer, type InlineVideoPlayerProps, JsonView, type JsonViewProps, LinearDocView, type LinearDocViewProps, MapLayer, MarkdownRenderer, MediaClipLayer, type MediaClipLayerProps, MediaContext, type MediaScheduleController, type MountOptions, PathLayer, type PlaybackActions$1 as PlaybackActions, type PlaybackState$1 as PlaybackState, type RenderAudioSegmentInfo, type RenderBlockInfo, type RenderCaptionInfo, type RenderChapterInfo, ShapeLayer, type SlideNavActions, SocialCaptionOverlay, type SquisqPlayerHandle, type SquisqRenderAPI, TableLayer, TextLayer, TreeLayer, type UseDocPlaybackOptions, VideoLayer, formatTime, useAudioSync, useAutoSurface, useDocPlayback, useMediaProvider, useMediaSchedule, useMediaUrl, useViewportOrientation };