@bendyline/squisq-react 0.1.2
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/index.d.ts +563 -0
- package/dist/index.js +3180 -0
- package/dist/index.js.map +1 -0
- package/dist/squisq-player.css +2 -0
- package/dist/squisq-player.css.map +1 -0
- package/dist/squisq-player.global.js +6 -0
- package/dist/squisq-player.global.js.map +1 -0
- package/dist/standalone-source.d.ts +2 -0
- package/dist/standalone-source.js +2 -0
- package/package.json +69 -0
- package/src/BlockRenderer.tsx +146 -0
- package/src/CaptionOverlay.tsx +86 -0
- package/src/DocControlsBottom.tsx +103 -0
- package/src/DocControlsOverlay.tsx +178 -0
- package/src/DocControlsSidebar.tsx +107 -0
- package/src/DocControlsSlideshow.tsx +132 -0
- package/src/DocPlayer.tsx +1005 -0
- package/src/DocPlayerWithSidebar.tsx +138 -0
- package/src/DocProgressBar.tsx +200 -0
- package/src/LinearDocView.tsx +313 -0
- package/src/MarkdownRenderer.tsx +360 -0
- package/src/__tests__/BlockRenderer.test.tsx +105 -0
- package/src/__tests__/DocControlsSlideshow.test.tsx +127 -0
- package/src/__tests__/LinearDocView.test.tsx +180 -0
- package/src/__tests__/MarkdownRenderer.test.tsx +234 -0
- package/src/__tests__/exports.test.ts +55 -0
- package/src/hooks/AudioProvider.ts +114 -0
- package/src/hooks/MediaContext.tsx +81 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useAudioSync.ts +390 -0
- package/src/hooks/useDocPlayback.ts +251 -0
- package/src/hooks/useViewportOrientation.ts +117 -0
- package/src/index.ts +46 -0
- package/src/layers/ImageLayer.tsx +182 -0
- package/src/layers/MapLayer.tsx +184 -0
- package/src/layers/ShapeLayer.tsx +107 -0
- package/src/layers/TextLayer.tsx +197 -0
- package/src/layers/VideoLayer.tsx +150 -0
- package/src/layers/index.ts +5 -0
- package/src/standalone-entry.tsx +228 -0
- package/src/styles/doc-animations.css +458 -0
- package/src/types.ts +152 -0
- package/src/utils/animationUtils.ts +13 -0
- package/src/utils/layerUtils.ts +42 -0
- package/src/utils/mapTileUtils.ts +375 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { Block, Doc, Theme, CaptionTrack, ViewportConfig as ViewportConfig$1, ImageLayer as ImageLayer$1, TextLayer as TextLayer$1, ShapeLayer as ShapeLayer$1, VideoLayer as VideoLayer$1, MapLayer as MapLayer$1, AudioTrack, MediaProvider } from '@bendyline/squisq/schemas';
|
|
3
|
+
import { ViewportConfig, ViewportOrientation } from '@bendyline/squisq/doc';
|
|
4
|
+
export { getAnimationStyle, getTransitionClass } from '@bendyline/squisq/doc';
|
|
5
|
+
import { MarkdownBlockNode } from '@bendyline/squisq/markdown';
|
|
6
|
+
import * as react from 'react';
|
|
7
|
+
import { RefObject } from 'react';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* AudioProvider - Abstraction for audio playback in DocPlayer
|
|
11
|
+
*
|
|
12
|
+
* This module defines an interface for audio playback operations that can have
|
|
13
|
+
* different implementations depending on the runtime environment:
|
|
14
|
+
*
|
|
15
|
+
* - Site/Browser: Uses HTML5 Audio element directly
|
|
16
|
+
* - EFB/MSFS: Routes through CompanionAPI to Electron app
|
|
17
|
+
*
|
|
18
|
+
* The DocPlayer uses this abstraction instead of directly manipulating audio,
|
|
19
|
+
* allowing the same component code to work in both environments.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
interface AudioState {
|
|
23
|
+
/** Current time in overall timeline (seconds) */
|
|
24
|
+
currentTime: number;
|
|
25
|
+
/** Whether audio is currently playing */
|
|
26
|
+
isPlaying: boolean;
|
|
27
|
+
/** Index of current audio segment */
|
|
28
|
+
currentSegment: number;
|
|
29
|
+
/** Total duration of all segments */
|
|
30
|
+
totalDuration: number;
|
|
31
|
+
/** Whether audio has finished */
|
|
32
|
+
isEnded: boolean;
|
|
33
|
+
/** Whether audio is loaded and ready to play */
|
|
34
|
+
isReady: boolean;
|
|
35
|
+
/** Whether the audio backend is available/connected */
|
|
36
|
+
isAvailable: boolean;
|
|
37
|
+
/** Message to show when not available */
|
|
38
|
+
unavailableMessage?: string;
|
|
39
|
+
}
|
|
40
|
+
interface AudioActions {
|
|
41
|
+
/** Start or resume playback */
|
|
42
|
+
play: () => Promise<void>;
|
|
43
|
+
/** Pause playback */
|
|
44
|
+
pause: () => Promise<void>;
|
|
45
|
+
/** Toggle play/pause */
|
|
46
|
+
toggle: () => Promise<void>;
|
|
47
|
+
/** Seek to specific time in timeline */
|
|
48
|
+
seekTo: (time: number) => Promise<void>;
|
|
49
|
+
/** Skip to specific segment */
|
|
50
|
+
skipToSegment: (index: number) => Promise<void>;
|
|
51
|
+
/** Restart from beginning */
|
|
52
|
+
restart: () => Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
type AudioProvider = AudioState & AudioActions;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Doc Player Control Types
|
|
58
|
+
*
|
|
59
|
+
* Shared type definitions for doc player controls across different
|
|
60
|
+
* layout modes (overlay, sidebar, bottom). These interfaces allow
|
|
61
|
+
* control components to be decoupled from the core DocPlayer.
|
|
62
|
+
*
|
|
63
|
+
* Related Files:
|
|
64
|
+
* - DocPlayer.tsx — Core player component
|
|
65
|
+
* - DocProgressBar.tsx — Extracted progress bar
|
|
66
|
+
* - DocControlsOverlay.tsx — Overlay controls (default)
|
|
67
|
+
* - DocControlsSidebar.tsx — Vertical sidebar controls
|
|
68
|
+
* - DocControlsBottom.tsx — Horizontal bottom strip controls
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/** Layout mode for doc player controls */
|
|
72
|
+
type ControlsLayout = 'overlay' | 'sidebar' | 'bottom';
|
|
73
|
+
/**
|
|
74
|
+
* Display mode for DocPlayer.
|
|
75
|
+
*
|
|
76
|
+
* - `'video'` — Traditional video-style playback with play/pause, scrub bar,
|
|
77
|
+
* and time-based auto-advance. Default mode.
|
|
78
|
+
* - `'slideshow'` — PowerPoint-style presentation with prev/next navigation.
|
|
79
|
+
* Blocks are treated as static slides that only change on user click.
|
|
80
|
+
* No auto-advance, no scrub bar.
|
|
81
|
+
* - `'linear'` — Long-scrolling document view. Renders the full markdown as
|
|
82
|
+
* readable HTML with template-annotated sections shown as inline SVG cards.
|
|
83
|
+
* No audio, no timeline, no controls — just a scrollable page.
|
|
84
|
+
*/
|
|
85
|
+
type DisplayMode = 'video' | 'slideshow' | 'linear';
|
|
86
|
+
/** Slide navigation actions for slideshow display mode */
|
|
87
|
+
interface SlideNavActions {
|
|
88
|
+
/** Navigate to the next slide */
|
|
89
|
+
nextSlide: () => void;
|
|
90
|
+
/** Navigate to the previous slide */
|
|
91
|
+
prevSlide: () => void;
|
|
92
|
+
/** Navigate to a specific slide by index (0-based) */
|
|
93
|
+
goToSlide: (index: number) => void;
|
|
94
|
+
}
|
|
95
|
+
/** Playback state exposed to external control components */
|
|
96
|
+
interface PlaybackState$1 {
|
|
97
|
+
isPlaying: boolean;
|
|
98
|
+
currentTime: number;
|
|
99
|
+
totalDuration: number;
|
|
100
|
+
currentBlockIndex: number;
|
|
101
|
+
totalBlocks: number;
|
|
102
|
+
docProgress: number;
|
|
103
|
+
hasCaptions: boolean;
|
|
104
|
+
captionsEnabled: boolean;
|
|
105
|
+
isFullscreen?: boolean;
|
|
106
|
+
/** Current audio segment index (0-based) */
|
|
107
|
+
currentSegmentIndex: number;
|
|
108
|
+
/** Current audio segment name (e.g., 'intro', 'history') */
|
|
109
|
+
currentSegmentName: string | null;
|
|
110
|
+
/** Current block data (for extracting image info, etc.) */
|
|
111
|
+
currentBlock: Block | null;
|
|
112
|
+
}
|
|
113
|
+
/** Playback actions exposed to external control components */
|
|
114
|
+
interface PlaybackActions$1 {
|
|
115
|
+
toggle: () => void;
|
|
116
|
+
restart: () => void;
|
|
117
|
+
seekTo: (time: number) => void;
|
|
118
|
+
setCaptionsEnabled: (enabled: boolean) => void;
|
|
119
|
+
toggleFullscreen?: () => void;
|
|
120
|
+
}
|
|
121
|
+
/** Block marker data for the progress bar */
|
|
122
|
+
interface BlockMarker {
|
|
123
|
+
block: Block;
|
|
124
|
+
index: number;
|
|
125
|
+
position: number;
|
|
126
|
+
title: string;
|
|
127
|
+
/** True if this block is the first in a new audio segment (section boundary) */
|
|
128
|
+
isSectionStart: boolean;
|
|
129
|
+
}
|
|
130
|
+
/** Block metadata returned by SquisqRenderAPI.getBlocks() */
|
|
131
|
+
interface RenderBlockInfo {
|
|
132
|
+
id: string;
|
|
133
|
+
template: string;
|
|
134
|
+
startTime: number;
|
|
135
|
+
duration: number;
|
|
136
|
+
}
|
|
137
|
+
/** Audio segment info returned by SquisqRenderAPI.getAudioSegments() */
|
|
138
|
+
interface RenderAudioSegmentInfo {
|
|
139
|
+
src: string;
|
|
140
|
+
name: string;
|
|
141
|
+
duration: number;
|
|
142
|
+
startTime: number;
|
|
143
|
+
}
|
|
144
|
+
/** Caption phrase info returned by SquisqRenderAPI.getCaptions() */
|
|
145
|
+
interface RenderCaptionInfo {
|
|
146
|
+
text: string;
|
|
147
|
+
startTime: number;
|
|
148
|
+
endTime: number;
|
|
149
|
+
}
|
|
150
|
+
/** Chapter marker returned by SquisqRenderAPI.getChapters() */
|
|
151
|
+
interface RenderChapterInfo {
|
|
152
|
+
title: string;
|
|
153
|
+
startTime: number;
|
|
154
|
+
duration: number;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* API surface exposed on `window` in render mode and debug mode.
|
|
158
|
+
* Used by Playwright for video export and by ?debug=true for testing.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* // In Playwright:
|
|
163
|
+
* const w = window as unknown as SquisqWindow;
|
|
164
|
+
* await w.seekTo!(5.0);
|
|
165
|
+
* const blocks = w.getBlocks!();
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
interface SquisqRenderAPI {
|
|
169
|
+
seekTo: (time: number) => Promise<void>;
|
|
170
|
+
getDuration: () => number;
|
|
171
|
+
getBlocks: () => RenderBlockInfo[];
|
|
172
|
+
getAudioSegments: () => RenderAudioSegmentInfo[];
|
|
173
|
+
getCaptions: () => RenderCaptionInfo[];
|
|
174
|
+
getChapters: () => RenderChapterInfo[];
|
|
175
|
+
showCover: () => Promise<void>;
|
|
176
|
+
hideCover: () => Promise<void>;
|
|
177
|
+
hasCoverBlock: () => boolean;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Window augmented with optional SquisqRenderAPI properties.
|
|
181
|
+
* Each property is optional because they're only present in render/debug mode.
|
|
182
|
+
*/
|
|
183
|
+
type SquisqWindow = Window & typeof globalThis & Partial<SquisqRenderAPI>;
|
|
184
|
+
/** Format time in seconds to MM:SS string */
|
|
185
|
+
declare function formatTime(seconds: number): string;
|
|
186
|
+
|
|
187
|
+
interface DocPlayerProps {
|
|
188
|
+
/** Doc script to play */
|
|
189
|
+
script: Doc;
|
|
190
|
+
/** Base path for resolving media URLs */
|
|
191
|
+
basePath: string;
|
|
192
|
+
/** Render mode for video capture (hides controls, exposes seekTo) */
|
|
193
|
+
renderMode?: boolean;
|
|
194
|
+
/** Auto-play when loaded */
|
|
195
|
+
autoPlay?: boolean;
|
|
196
|
+
/** Callback when playback ends */
|
|
197
|
+
onEnded?: () => void;
|
|
198
|
+
/** Callback for time updates */
|
|
199
|
+
onTimeUpdate?: (time: number) => void;
|
|
200
|
+
/** Optional audio provider (if not provided, uses default HTML5 audio) */
|
|
201
|
+
audioProvider?: AudioProvider;
|
|
202
|
+
/** Show built-in controls (default: true). Set to false for custom controls. */
|
|
203
|
+
showControls?: boolean;
|
|
204
|
+
/** Show only the progress bar/scrubber at bottom (no other controls).
|
|
205
|
+
* Only takes effect when showControls is false. Allows external controls
|
|
206
|
+
* while keeping the scrubber in-video. */
|
|
207
|
+
showScrubber?: boolean;
|
|
208
|
+
/** Mute audio (default: false) */
|
|
209
|
+
muted?: boolean;
|
|
210
|
+
/** Enable captions (default: true) */
|
|
211
|
+
captionsEnabled?: boolean;
|
|
212
|
+
/** Callback when captions enabled state is toggled */
|
|
213
|
+
onCaptionsToggle?: (enabled: boolean) => void;
|
|
214
|
+
/** Callback for playback state changes (for external controls) */
|
|
215
|
+
onPlaybackStateChange?: (state: PlaybackState$1) => void;
|
|
216
|
+
/** Callback when playback controls are ready (for external controls) */
|
|
217
|
+
onControlsReady?: (controls: PlaybackActions$1 & {
|
|
218
|
+
play: () => void;
|
|
219
|
+
pause: () => void;
|
|
220
|
+
}) => void;
|
|
221
|
+
/** Whether the player is currently in fullscreen mode */
|
|
222
|
+
isFullscreen?: boolean;
|
|
223
|
+
/** Callback to toggle fullscreen mode */
|
|
224
|
+
onFullscreenToggle?: () => void;
|
|
225
|
+
/** Callback when block markers are computed (for external progress bars) */
|
|
226
|
+
onBlockMarkers?: (markers: BlockMarker[]) => void;
|
|
227
|
+
/** Force a specific viewport preset, bypassing window-based orientation detection.
|
|
228
|
+
* Used when the player is rendered in a constrained container (e.g., map overlay panel)
|
|
229
|
+
* whose shape differs from the window's. */
|
|
230
|
+
forceViewport?: ViewportConfig;
|
|
231
|
+
/** Theme to use for rendering (default: DEFAULT_THEME from the theme library) */
|
|
232
|
+
theme?: Theme;
|
|
233
|
+
/**
|
|
234
|
+
* Display mode for the player.
|
|
235
|
+
* - `'video'` (default) — Traditional video playback with play/pause, scrub bar, auto-advance.
|
|
236
|
+
* - `'slideshow'` — PowerPoint-style with prev/next buttons. Blocks are static slides
|
|
237
|
+
* that only change on user click. No auto-advance, no scrub bar.
|
|
238
|
+
* - `'linear'` — Long-scrolling document view. Renders markdown as readable HTML with
|
|
239
|
+
* template-annotated sections as inline SVG cards. No audio, no timeline.
|
|
240
|
+
*/
|
|
241
|
+
displayMode?: DisplayMode;
|
|
242
|
+
}
|
|
243
|
+
declare function DocPlayer({ script, basePath, renderMode, autoPlay, onEnded, onTimeUpdate, audioProvider: externalAudioProvider, showControls, showScrubber, muted, captionsEnabled: captionsEnabledProp, onCaptionsToggle, onPlaybackStateChange, onControlsReady, isFullscreen, onFullscreenToggle, onBlockMarkers, forceViewport, displayMode, theme, }: DocPlayerProps): react_jsx_runtime.JSX.Element;
|
|
244
|
+
|
|
245
|
+
/** Default viewport dimensions (1080p landscape) - for backwards compatibility */
|
|
246
|
+
declare const VIEWPORT: {
|
|
247
|
+
width: number;
|
|
248
|
+
height: number;
|
|
249
|
+
};
|
|
250
|
+
/** Viewport configuration type */
|
|
251
|
+
interface ViewportDimensions {
|
|
252
|
+
width: number;
|
|
253
|
+
height: number;
|
|
254
|
+
}
|
|
255
|
+
interface BlockRendererProps {
|
|
256
|
+
/** The block to render */
|
|
257
|
+
block: Block;
|
|
258
|
+
/** Current time relative to block start (seconds) */
|
|
259
|
+
blockTime: number;
|
|
260
|
+
/** Base path for resolving media URLs */
|
|
261
|
+
basePath: string;
|
|
262
|
+
/** Whether this block is entering (for transition) */
|
|
263
|
+
isEntering?: boolean;
|
|
264
|
+
/** Whether this block is exiting (for transition) */
|
|
265
|
+
isExiting?: boolean;
|
|
266
|
+
/** Viewport dimensions (defaults to 1920x1080 landscape) */
|
|
267
|
+
viewport?: ViewportDimensions;
|
|
268
|
+
/** Whether the doc is currently playing (controls video playback) */
|
|
269
|
+
isPlaying?: boolean;
|
|
270
|
+
}
|
|
271
|
+
declare function BlockRenderer({ block, blockTime, basePath, isEntering, isExiting, viewport, isPlaying, }: BlockRendererProps): react_jsx_runtime.JSX.Element;
|
|
272
|
+
|
|
273
|
+
interface CaptionOverlayProps {
|
|
274
|
+
/** Caption track with timestamped phrases */
|
|
275
|
+
captions: CaptionTrack | undefined;
|
|
276
|
+
/** Current playback time in seconds */
|
|
277
|
+
currentTime: number;
|
|
278
|
+
/** Whether captions are enabled */
|
|
279
|
+
enabled?: boolean;
|
|
280
|
+
/** Font size in pixels (default: 16) */
|
|
281
|
+
fontSize?: number;
|
|
282
|
+
}
|
|
283
|
+
declare function CaptionOverlay({ captions, currentTime, enabled, fontSize, }: CaptionOverlayProps): react_jsx_runtime.JSX.Element;
|
|
284
|
+
|
|
285
|
+
interface DocControlsOverlayProps {
|
|
286
|
+
state: PlaybackState$1;
|
|
287
|
+
actions: PlaybackActions$1;
|
|
288
|
+
blockMarkers: BlockMarker[];
|
|
289
|
+
expandedBlocks: Block[];
|
|
290
|
+
getBlockTitle?: (block: Block) => string;
|
|
291
|
+
}
|
|
292
|
+
declare function DocControlsOverlay({ state, actions, blockMarkers, expandedBlocks, getBlockTitle, }: DocControlsOverlayProps): react_jsx_runtime.JSX.Element;
|
|
293
|
+
|
|
294
|
+
interface DocControlsBottomProps {
|
|
295
|
+
state: PlaybackState$1;
|
|
296
|
+
actions: PlaybackActions$1;
|
|
297
|
+
blockMarkers: BlockMarker[];
|
|
298
|
+
expandedBlocks: Block[];
|
|
299
|
+
getBlockTitle?: (block: Block) => string;
|
|
300
|
+
}
|
|
301
|
+
declare function DocControlsBottom({ state, actions, blockMarkers, expandedBlocks, getBlockTitle, }: DocControlsBottomProps): react_jsx_runtime.JSX.Element;
|
|
302
|
+
|
|
303
|
+
interface DocControlsSidebarProps {
|
|
304
|
+
state: PlaybackState$1;
|
|
305
|
+
actions: PlaybackActions$1;
|
|
306
|
+
}
|
|
307
|
+
declare function DocControlsSidebar({ state, actions }: DocControlsSidebarProps): react_jsx_runtime.JSX.Element;
|
|
308
|
+
|
|
309
|
+
interface DocControlsSlideshowProps {
|
|
310
|
+
state: PlaybackState$1;
|
|
311
|
+
slideNav: SlideNavActions;
|
|
312
|
+
}
|
|
313
|
+
declare function DocControlsSlideshow({ state, slideNav }: DocControlsSlideshowProps): react_jsx_runtime.JSX.Element;
|
|
314
|
+
|
|
315
|
+
interface DocPlayerWithSidebarProps {
|
|
316
|
+
script: Doc;
|
|
317
|
+
basePath: string;
|
|
318
|
+
autoPlay?: boolean;
|
|
319
|
+
onEnded?: () => void;
|
|
320
|
+
onTimeUpdate?: (time: number) => void;
|
|
321
|
+
audioProvider?: AudioProvider;
|
|
322
|
+
muted?: boolean;
|
|
323
|
+
captionsEnabled?: boolean;
|
|
324
|
+
isFullscreen?: boolean;
|
|
325
|
+
onFullscreenToggle?: () => void;
|
|
326
|
+
/** Force a specific viewport preset, bypassing window-based orientation detection. */
|
|
327
|
+
forceViewport?: ViewportConfig$1;
|
|
328
|
+
/** Called when playing state changes */
|
|
329
|
+
onPlayingChange?: (isPlaying: boolean) => void;
|
|
330
|
+
}
|
|
331
|
+
declare function DocPlayerWithSidebar({ script, basePath, autoPlay, onEnded, onTimeUpdate, audioProvider, muted, captionsEnabled, isFullscreen, onFullscreenToggle, forceViewport, onPlayingChange, }: DocPlayerWithSidebarProps): react_jsx_runtime.JSX.Element;
|
|
332
|
+
|
|
333
|
+
interface DocProgressBarProps {
|
|
334
|
+
state: PlaybackState$1;
|
|
335
|
+
actions: PlaybackActions$1;
|
|
336
|
+
blockMarkers: BlockMarker[];
|
|
337
|
+
/** All expanded blocks for hover lookup */
|
|
338
|
+
expandedBlocks: Block[];
|
|
339
|
+
/** Optional: get block title for hover tooltip */
|
|
340
|
+
getBlockTitle?: (block: Block) => string;
|
|
341
|
+
}
|
|
342
|
+
declare function DocProgressBar({ state, actions, blockMarkers, expandedBlocks, getBlockTitle, }: DocProgressBarProps): react_jsx_runtime.JSX.Element;
|
|
343
|
+
|
|
344
|
+
interface MarkdownRendererProps {
|
|
345
|
+
/** Block-level AST nodes to render */
|
|
346
|
+
nodes: MarkdownBlockNode[];
|
|
347
|
+
/** Optional CSS class for the wrapper element */
|
|
348
|
+
className?: string;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Renders MarkdownBlockNode[] AST as React HTML elements.
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```tsx
|
|
355
|
+
* <MarkdownRenderer nodes={block.contents} />
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
declare function MarkdownRenderer({ nodes, className }: MarkdownRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
359
|
+
|
|
360
|
+
interface LinearDocViewProps {
|
|
361
|
+
/** The Doc to render */
|
|
362
|
+
doc: Doc;
|
|
363
|
+
/** Base path for resolving media URLs (images, etc.) */
|
|
364
|
+
basePath?: string;
|
|
365
|
+
/** Viewport config for SVG card rendering (default: landscape) */
|
|
366
|
+
viewport?: ViewportConfig$1;
|
|
367
|
+
/** Optional CSS class for the outer container */
|
|
368
|
+
className?: string;
|
|
369
|
+
/** Theme to use for rendering (default: DEFAULT_THEME from the theme library) */
|
|
370
|
+
theme?: Theme;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Renders a Doc as a long-scrolling, readable document.
|
|
374
|
+
*
|
|
375
|
+
* Non-annotated blocks are rendered as HTML text (headings, paragraphs,
|
|
376
|
+
* lists, etc.) via MarkdownRenderer. Template-annotated blocks are
|
|
377
|
+
* rendered as inline SVG visual cards via BlockRenderer.
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* ```tsx
|
|
381
|
+
* <LinearDocView doc={doc} basePath="/media/" />
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
declare function LinearDocView({ doc, basePath, viewport, className, theme, }: LinearDocViewProps): react_jsx_runtime.JSX.Element;
|
|
385
|
+
|
|
386
|
+
interface ImageLayerProps {
|
|
387
|
+
layer: ImageLayer$1;
|
|
388
|
+
/** Base path for resolving relative image URLs */
|
|
389
|
+
basePath: string;
|
|
390
|
+
/** Viewport dimensions for percentage calculations */
|
|
391
|
+
viewport: {
|
|
392
|
+
width: number;
|
|
393
|
+
height: number;
|
|
394
|
+
};
|
|
395
|
+
/** Current time relative to block start (for animation timing) */
|
|
396
|
+
blockTime: number;
|
|
397
|
+
}
|
|
398
|
+
declare function ImageLayer({ layer, basePath, viewport, blockTime }: ImageLayerProps): react_jsx_runtime.JSX.Element;
|
|
399
|
+
|
|
400
|
+
interface TextLayerProps {
|
|
401
|
+
layer: TextLayer$1;
|
|
402
|
+
/** Viewport dimensions for percentage calculations */
|
|
403
|
+
viewport: {
|
|
404
|
+
width: number;
|
|
405
|
+
height: number;
|
|
406
|
+
};
|
|
407
|
+
/** Current time relative to block start */
|
|
408
|
+
blockTime: number;
|
|
409
|
+
}
|
|
410
|
+
declare function TextLayer({ layer, viewport, blockTime }: TextLayerProps): react_jsx_runtime.JSX.Element;
|
|
411
|
+
|
|
412
|
+
interface ShapeLayerProps {
|
|
413
|
+
layer: ShapeLayer$1;
|
|
414
|
+
/** Viewport dimensions for percentage calculations */
|
|
415
|
+
viewport: {
|
|
416
|
+
width: number;
|
|
417
|
+
height: number;
|
|
418
|
+
};
|
|
419
|
+
/** Current time relative to block start */
|
|
420
|
+
blockTime: number;
|
|
421
|
+
}
|
|
422
|
+
declare function ShapeLayer({ layer, viewport, blockTime }: ShapeLayerProps): react_jsx_runtime.JSX.Element;
|
|
423
|
+
|
|
424
|
+
interface VideoLayerProps {
|
|
425
|
+
layer: VideoLayer$1;
|
|
426
|
+
/** Base path for resolving relative video URLs */
|
|
427
|
+
basePath: string;
|
|
428
|
+
/** Viewport dimensions for percentage calculations */
|
|
429
|
+
viewport: {
|
|
430
|
+
width: number;
|
|
431
|
+
height: number;
|
|
432
|
+
};
|
|
433
|
+
/** Current time relative to block start (for playback sync) */
|
|
434
|
+
blockTime: number;
|
|
435
|
+
/** Whether the doc is currently playing */
|
|
436
|
+
isPlaying?: boolean;
|
|
437
|
+
}
|
|
438
|
+
declare function VideoLayer({ layer, basePath, viewport, blockTime: _blockTime, isPlaying, }: VideoLayerProps): react_jsx_runtime.JSX.Element;
|
|
439
|
+
|
|
440
|
+
interface MapLayerProps {
|
|
441
|
+
layer: MapLayer$1;
|
|
442
|
+
/** Base path for resolving relative image URLs */
|
|
443
|
+
basePath: string;
|
|
444
|
+
/** Viewport dimensions for percentage calculations */
|
|
445
|
+
viewport: {
|
|
446
|
+
width: number;
|
|
447
|
+
height: number;
|
|
448
|
+
};
|
|
449
|
+
/** Current time relative to block start (for animation timing) */
|
|
450
|
+
blockTime: number;
|
|
451
|
+
}
|
|
452
|
+
declare function MapLayer({ layer, basePath, viewport, blockTime }: MapLayerProps): react_jsx_runtime.JSX.Element;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* useAudioSync Hook
|
|
456
|
+
*
|
|
457
|
+
* Synchronizes playback state with an audio element. Provides current
|
|
458
|
+
* playback time, playing state, and methods to control audio playback.
|
|
459
|
+
*
|
|
460
|
+
* Handles multiple audio segments (MP3 files) by tracking which segment
|
|
461
|
+
* is currently playing and calculating the overall timeline position.
|
|
462
|
+
*
|
|
463
|
+
* This is the HTML5 Audio implementation of the AudioProvider interface.
|
|
464
|
+
* For EFB/MSFS environments, use useCompanionAudioSync instead.
|
|
465
|
+
*/
|
|
466
|
+
|
|
467
|
+
declare function useAudioSync(audioRef: RefObject<HTMLAudioElement>, audioTrack: AudioTrack | undefined, basePath?: string): AudioProvider;
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* useDocPlayback Hook
|
|
471
|
+
*
|
|
472
|
+
* Manages the playback state for a visual doc, including which block
|
|
473
|
+
* is currently active, transition states, and synchronization with audio.
|
|
474
|
+
*
|
|
475
|
+
* This hook provides:
|
|
476
|
+
* - Current block determination based on time
|
|
477
|
+
* - Transition tracking (entering/exiting blocks)
|
|
478
|
+
* - Manual navigation (next/prev block)
|
|
479
|
+
* - Time-based seeking
|
|
480
|
+
* - Automatic expansion of template blocks
|
|
481
|
+
*/
|
|
482
|
+
|
|
483
|
+
interface PlaybackState {
|
|
484
|
+
/** Currently visible block */
|
|
485
|
+
currentBlock: Block | null;
|
|
486
|
+
/** Index of current block */
|
|
487
|
+
currentBlockIndex: number;
|
|
488
|
+
/** Previous block (for transitions) */
|
|
489
|
+
previousBlock: Block | null;
|
|
490
|
+
/** Whether current block is entering */
|
|
491
|
+
isEntering: boolean;
|
|
492
|
+
/** Whether previous block is exiting */
|
|
493
|
+
isExiting: boolean;
|
|
494
|
+
/** Time relative to current block start */
|
|
495
|
+
blockTime: number;
|
|
496
|
+
/** Progress through current block (0-1) */
|
|
497
|
+
blockProgress: number;
|
|
498
|
+
/** Overall progress through doc (0-1) */
|
|
499
|
+
docProgress: number;
|
|
500
|
+
/** Expanded blocks (templates converted to full blocks with layers) */
|
|
501
|
+
blocks: Block[];
|
|
502
|
+
}
|
|
503
|
+
interface PlaybackActions {
|
|
504
|
+
/** Go to next block */
|
|
505
|
+
nextBlock: () => void;
|
|
506
|
+
/** Go to previous block */
|
|
507
|
+
prevBlock: () => void;
|
|
508
|
+
/** Go to specific block by index */
|
|
509
|
+
goToBlock: (index: number) => void;
|
|
510
|
+
}
|
|
511
|
+
declare function useDocPlayback(script: Doc | null, currentTime: number, viewport?: ViewportConfig, renderMode?: boolean, theme?: Theme): PlaybackState & PlaybackActions;
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* useViewportOrientation Hook
|
|
515
|
+
*
|
|
516
|
+
* Detects the current viewport orientation and returns the appropriate
|
|
517
|
+
* VIEWPORT_PRESET for rendering docs. Automatically updates when
|
|
518
|
+
* the window is resized.
|
|
519
|
+
*
|
|
520
|
+
* Thresholds:
|
|
521
|
+
* - Portrait: height > width * 1.2 (significantly taller than wide)
|
|
522
|
+
* - Square: width and height within 20% of each other
|
|
523
|
+
* - Landscape: width > height * 1.2 (significantly wider than tall)
|
|
524
|
+
*/
|
|
525
|
+
|
|
526
|
+
interface UseViewportOrientationResult {
|
|
527
|
+
/** Current viewport preset configuration */
|
|
528
|
+
viewport: ViewportConfig;
|
|
529
|
+
/** Current orientation name */
|
|
530
|
+
orientation: ViewportOrientation;
|
|
531
|
+
/** Current window dimensions */
|
|
532
|
+
windowSize: {
|
|
533
|
+
width: number;
|
|
534
|
+
height: number;
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Hook to detect viewport orientation and return appropriate preset.
|
|
539
|
+
* Updates automatically when window is resized.
|
|
540
|
+
*/
|
|
541
|
+
declare function useViewportOrientation(): UseViewportOrientationResult;
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* React context holding the current MediaProvider (or null if none provided).
|
|
545
|
+
*/
|
|
546
|
+
declare const MediaContext: react.Context<MediaProvider | null>;
|
|
547
|
+
/**
|
|
548
|
+
* Hook to access the current MediaProvider from context.
|
|
549
|
+
* Returns null if no provider is set.
|
|
550
|
+
*/
|
|
551
|
+
declare function useMediaProvider(): MediaProvider | null;
|
|
552
|
+
/**
|
|
553
|
+
* Hook to resolve a media URL via the MediaProvider (if available),
|
|
554
|
+
* falling back to basePath-based resolution.
|
|
555
|
+
*
|
|
556
|
+
* Returns the resolved URL string. Updates when the provider or path changes.
|
|
557
|
+
*
|
|
558
|
+
* @param relativePath - Relative media path from the document (e.g., 'hero.jpg')
|
|
559
|
+
* @param basePath - Fallback base path for URL construction
|
|
560
|
+
*/
|
|
561
|
+
declare function useMediaUrl(relativePath: string, basePath: string): string;
|
|
562
|
+
|
|
563
|
+
export { type AudioActions, type AudioProvider, type AudioState, type BlockMarker, BlockRenderer, CaptionOverlay, type ControlsLayout, type DisplayMode, DocControlsBottom, DocControlsOverlay, DocControlsSidebar, DocControlsSlideshow, DocPlayer, DocPlayerWithSidebar, DocProgressBar, ImageLayer, LinearDocView, MapLayer, MarkdownRenderer, MediaContext, type PlaybackActions$1 as PlaybackActions, type PlaybackState$1 as PlaybackState, type RenderAudioSegmentInfo, type RenderBlockInfo, type RenderCaptionInfo, type RenderChapterInfo, ShapeLayer, type SlideNavActions, type SquisqRenderAPI, type SquisqWindow, TextLayer, VIEWPORT, VideoLayer, formatTime, useAudioSync, useDocPlayback, useMediaProvider, useMediaUrl, useViewportOrientation };
|