@bendyline/squisq-react 0.1.3 → 1.0.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.
Files changed (139) hide show
  1. package/dist/BlockRenderer.d.ts +37 -0
  2. package/dist/BlockRenderer.d.ts.map +1 -0
  3. package/dist/BlockRenderer.js +51 -0
  4. package/dist/BlockRenderer.js.map +1 -0
  5. package/dist/CaptionOverlay.d.ts +24 -0
  6. package/dist/CaptionOverlay.d.ts.map +1 -0
  7. package/dist/CaptionOverlay.js +40 -0
  8. package/dist/CaptionOverlay.js.map +1 -0
  9. package/dist/DocControlsBottom.d.ts +28 -0
  10. package/dist/DocControlsBottom.d.ts.map +1 -0
  11. package/dist/DocControlsBottom.js +23 -0
  12. package/dist/DocControlsBottom.js.map +1 -0
  13. package/dist/DocControlsOverlay.d.ts +28 -0
  14. package/dist/DocControlsOverlay.d.ts.map +1 -0
  15. package/dist/DocControlsOverlay.js +75 -0
  16. package/dist/DocControlsOverlay.js.map +1 -0
  17. package/dist/DocControlsSidebar.d.ts +27 -0
  18. package/dist/DocControlsSidebar.d.ts.map +1 -0
  19. package/dist/DocControlsSidebar.js +6 -0
  20. package/dist/DocControlsSidebar.js.map +1 -0
  21. package/dist/DocControlsSlideshow.d.ts +20 -0
  22. package/dist/DocControlsSlideshow.d.ts.map +1 -0
  23. package/dist/DocControlsSlideshow.js +69 -0
  24. package/dist/DocControlsSlideshow.js.map +1 -0
  25. package/dist/DocPlayer.d.ts +87 -0
  26. package/dist/DocPlayer.d.ts.map +1 -0
  27. package/dist/DocPlayer.js +604 -0
  28. package/dist/DocPlayer.js.map +1 -0
  29. package/dist/DocPlayerWithSidebar.d.ts +41 -0
  30. package/dist/DocPlayerWithSidebar.d.ts.map +1 -0
  31. package/dist/DocPlayerWithSidebar.js +68 -0
  32. package/dist/DocPlayerWithSidebar.js.map +1 -0
  33. package/dist/DocProgressBar.d.ts +31 -0
  34. package/dist/DocProgressBar.d.ts.map +1 -0
  35. package/dist/DocProgressBar.js +122 -0
  36. package/dist/DocProgressBar.js.map +1 -0
  37. package/dist/LinearDocView.d.ts +47 -0
  38. package/dist/LinearDocView.d.ts.map +1 -0
  39. package/dist/LinearDocView.js +184 -0
  40. package/dist/LinearDocView.js.map +1 -0
  41. package/dist/MarkdownRenderer.d.ts +32 -0
  42. package/dist/MarkdownRenderer.d.ts.map +1 -0
  43. package/dist/MarkdownRenderer.js +133 -0
  44. package/dist/MarkdownRenderer.js.map +1 -0
  45. package/dist/__tests__/BlockRenderer.test.d.ts +2 -0
  46. package/dist/__tests__/BlockRenderer.test.d.ts.map +1 -0
  47. package/dist/__tests__/BlockRenderer.test.js +82 -0
  48. package/dist/__tests__/BlockRenderer.test.js.map +1 -0
  49. package/dist/__tests__/DocControlsSlideshow.test.d.ts +2 -0
  50. package/dist/__tests__/DocControlsSlideshow.test.d.ts.map +1 -0
  51. package/dist/__tests__/DocControlsSlideshow.test.js +88 -0
  52. package/dist/__tests__/DocControlsSlideshow.test.js.map +1 -0
  53. package/dist/__tests__/LinearDocView.test.d.ts +2 -0
  54. package/dist/__tests__/LinearDocView.test.d.ts.map +1 -0
  55. package/dist/__tests__/LinearDocView.test.js +160 -0
  56. package/dist/__tests__/LinearDocView.test.js.map +1 -0
  57. package/dist/__tests__/MarkdownRenderer.test.d.ts +2 -0
  58. package/dist/__tests__/MarkdownRenderer.test.d.ts.map +1 -0
  59. package/dist/__tests__/MarkdownRenderer.test.js +208 -0
  60. package/dist/__tests__/MarkdownRenderer.test.js.map +1 -0
  61. package/dist/__tests__/exports.test.d.ts +2 -0
  62. package/dist/__tests__/exports.test.d.ts.map +1 -0
  63. package/dist/__tests__/exports.test.js +48 -0
  64. package/dist/__tests__/exports.test.js.map +1 -0
  65. package/dist/hooks/AudioProvider.d.ts +71 -0
  66. package/dist/hooks/AudioProvider.d.ts.map +1 -0
  67. package/dist/hooks/AudioProvider.js +52 -0
  68. package/dist/hooks/AudioProvider.js.map +1 -0
  69. package/dist/hooks/MediaContext.d.ts +35 -0
  70. package/dist/hooks/MediaContext.d.ts.map +1 -0
  71. package/dist/hooks/MediaContext.js +66 -0
  72. package/dist/hooks/MediaContext.js.map +1 -0
  73. package/dist/hooks/index.d.ts +6 -0
  74. package/dist/hooks/index.d.ts.map +1 -0
  75. package/dist/hooks/index.js +5 -0
  76. package/dist/hooks/index.js.map +1 -0
  77. package/dist/hooks/useAudioSync.d.ts +18 -0
  78. package/dist/hooks/useAudioSync.d.ts.map +1 -0
  79. package/dist/hooks/useAudioSync.js +338 -0
  80. package/dist/hooks/useAudioSync.js.map +1 -0
  81. package/dist/hooks/useDocPlayback.d.ts +47 -0
  82. package/dist/hooks/useDocPlayback.d.ts.map +1 -0
  83. package/dist/hooks/useDocPlayback.js +176 -0
  84. package/dist/hooks/useDocPlayback.js.map +1 -0
  85. package/dist/hooks/useViewportOrientation.d.ts +31 -0
  86. package/dist/hooks/useViewportOrientation.d.ts.map +1 -0
  87. package/dist/hooks/useViewportOrientation.js +92 -0
  88. package/dist/hooks/useViewportOrientation.js.map +1 -0
  89. package/dist/index.d.ts +25 -563
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +26 -3179
  92. package/dist/index.js.map +1 -1
  93. package/dist/layers/ImageLayer.d.ts +23 -0
  94. package/dist/layers/ImageLayer.d.ts.map +1 -0
  95. package/dist/layers/ImageLayer.js +104 -0
  96. package/dist/layers/ImageLayer.js.map +1 -0
  97. package/dist/layers/MapLayer.d.ts +29 -0
  98. package/dist/layers/MapLayer.d.ts.map +1 -0
  99. package/dist/layers/MapLayer.js +97 -0
  100. package/dist/layers/MapLayer.js.map +1 -0
  101. package/dist/layers/ShapeLayer.d.ts +20 -0
  102. package/dist/layers/ShapeLayer.d.ts.map +1 -0
  103. package/dist/layers/ShapeLayer.js +35 -0
  104. package/dist/layers/ShapeLayer.js.map +1 -0
  105. package/dist/layers/TextLayer.d.ts +23 -0
  106. package/dist/layers/TextLayer.d.ts.map +1 -0
  107. package/dist/layers/TextLayer.js +126 -0
  108. package/dist/layers/TextLayer.js.map +1 -0
  109. package/dist/layers/VideoLayer.d.ts +40 -0
  110. package/dist/layers/VideoLayer.d.ts.map +1 -0
  111. package/dist/layers/VideoLayer.js +105 -0
  112. package/dist/layers/VideoLayer.js.map +1 -0
  113. package/dist/layers/index.d.ts +6 -0
  114. package/dist/layers/index.d.ts.map +1 -0
  115. package/dist/layers/index.js +6 -0
  116. package/dist/layers/index.js.map +1 -0
  117. package/dist/squisq-player.global.js +1 -1
  118. package/dist/standalone-entry.d.ts +61 -0
  119. package/dist/standalone-entry.d.ts.map +1 -0
  120. package/dist/standalone-entry.js +169 -0
  121. package/dist/standalone-entry.js.map +1 -0
  122. package/dist/standalone-source.js +1 -1
  123. package/dist/types.d.ts +131 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +21 -0
  126. package/dist/types.js.map +1 -0
  127. package/dist/utils/animationUtils.d.ts +8 -0
  128. package/dist/utils/animationUtils.d.ts.map +1 -0
  129. package/dist/utils/animationUtils.js +8 -0
  130. package/dist/utils/animationUtils.js.map +1 -0
  131. package/dist/utils/layerUtils.d.ts +17 -0
  132. package/dist/utils/layerUtils.d.ts.map +1 -0
  133. package/dist/utils/layerUtils.js +37 -0
  134. package/dist/utils/layerUtils.js.map +1 -0
  135. package/dist/utils/mapTileUtils.d.ts +105 -0
  136. package/dist/utils/mapTileUtils.d.ts.map +1 -0
  137. package/dist/utils/mapTileUtils.js +268 -0
  138. package/dist/utils/mapTileUtils.js.map +1 -0
  139. package/package.json +3 -4
@@ -0,0 +1,338 @@
1
+ /**
2
+ * useAudioSync Hook
3
+ *
4
+ * Synchronizes playback state with an audio element. Provides current
5
+ * playback time, playing state, and methods to control audio playback.
6
+ *
7
+ * Handles multiple audio segments (MP3 files) by tracking which segment
8
+ * is currently playing and calculating the overall timeline position.
9
+ *
10
+ * This is the HTML5 Audio implementation of the AudioProvider interface.
11
+ * For EFB/MSFS environments, use useCompanionAudioSync instead.
12
+ */
13
+ import { useState, useEffect, useRef, useCallback } from 'react';
14
+ export function useAudioSync(audioRef, audioTrack, basePath = '') {
15
+ const [currentTime, setCurrentTime] = useState(0);
16
+ const [isPlaying, setIsPlaying] = useState(false);
17
+ const [currentSegment, setCurrentSegment] = useState(0);
18
+ const [isEnded, setIsEnded] = useState(false);
19
+ const [isAudioReady, setIsAudioReady] = useState(false);
20
+ const [totalDuration, setTotalDuration] = useState(0);
21
+ // Calculate segment start times
22
+ const segmentStarts = useRef([]);
23
+ // Pending seek time (used when switching segments)
24
+ const pendingSeekTime = useRef(null);
25
+ const shouldPlayAfterLoad = useRef(false);
26
+ // Preloaded audio blob URLs (for seeking without range request support)
27
+ const blobUrls = useRef(new Map());
28
+ const loadingPromises = useRef(new Map());
29
+ // Fallback timer: when audio.play() is blocked (e.g., autoplay policy),
30
+ // advance currentTime synthetically so blocks still progress without audio.
31
+ const fallbackMode = useRef(false);
32
+ useEffect(() => {
33
+ if (!audioTrack?.segments) {
34
+ return;
35
+ }
36
+ let time = 0;
37
+ segmentStarts.current = audioTrack.segments.map((seg) => {
38
+ const start = time;
39
+ time += seg.duration;
40
+ return start;
41
+ });
42
+ setTotalDuration(time);
43
+ }, [audioTrack]);
44
+ // Preload audio file as blob (enables seeking without range request support)
45
+ const preloadAudio = useCallback(async (src) => {
46
+ const audioUrl = basePath ? `${basePath}/${src}` : src;
47
+ // Return cached blob URL if available
48
+ if (blobUrls.current.has(src)) {
49
+ return blobUrls.current.get(src);
50
+ }
51
+ // Return existing loading promise if in progress
52
+ if (loadingPromises.current.has(src)) {
53
+ return loadingPromises.current.get(src);
54
+ }
55
+ // Start loading
56
+ const loadPromise = (async () => {
57
+ try {
58
+ const response = await fetch(audioUrl);
59
+ if (!response.ok)
60
+ throw new Error(`HTTP ${response.status}`);
61
+ const blob = await response.blob();
62
+ const blobUrl = URL.createObjectURL(blob);
63
+ blobUrls.current.set(src, blobUrl);
64
+ return blobUrl;
65
+ }
66
+ catch {
67
+ // Fall back to direct URL if blob loading fails
68
+ return audioUrl;
69
+ }
70
+ finally {
71
+ loadingPromises.current.delete(src);
72
+ }
73
+ })();
74
+ loadingPromises.current.set(src, loadPromise);
75
+ return loadPromise;
76
+ }, [basePath]);
77
+ // Preload all audio segments on mount
78
+ useEffect(() => {
79
+ if (!audioTrack?.segments)
80
+ return;
81
+ // Preload all segments in parallel
82
+ audioTrack.segments.forEach((segment) => {
83
+ preloadAudio(segment.src);
84
+ });
85
+ // Cleanup blob URLs on unmount
86
+ const currentBlobUrls = blobUrls.current;
87
+ return () => {
88
+ currentBlobUrls.forEach((url) => {
89
+ URL.revokeObjectURL(url);
90
+ });
91
+ currentBlobUrls.clear();
92
+ };
93
+ }, [audioTrack, preloadAudio]);
94
+ // Handle audio time updates
95
+ useEffect(() => {
96
+ const audio = audioRef.current;
97
+ if (!audio)
98
+ return;
99
+ const handleTimeUpdate = () => {
100
+ // Calculate overall timeline position
101
+ const segmentStart = segmentStarts.current[currentSegment] || 0;
102
+ const overallTime = segmentStart + audio.currentTime;
103
+ setCurrentTime(overallTime);
104
+ };
105
+ const handlePlay = () => {
106
+ fallbackMode.current = false;
107
+ setIsPlaying(true);
108
+ };
109
+ const handlePause = () => setIsPlaying(false);
110
+ const handleError = () => {
111
+ // Audio source failed to load (e.g., 404 in CI or missing files).
112
+ // Set ready so the UI can still render controls and progress.
113
+ setIsAudioReady(true);
114
+ };
115
+ const handleEnded = () => {
116
+ // Move to next segment or end
117
+ if (audioTrack && currentSegment < audioTrack.segments.length - 1) {
118
+ // Auto-advance to next segment
119
+ // Set shouldPlayAfterLoad so the next segment auto-plays after loading
120
+ shouldPlayAfterLoad.current = true;
121
+ setCurrentSegment((prev) => prev + 1);
122
+ }
123
+ else {
124
+ setIsEnded(true);
125
+ setIsPlaying(false);
126
+ }
127
+ };
128
+ audio.addEventListener('timeupdate', handleTimeUpdate);
129
+ audio.addEventListener('play', handlePlay);
130
+ audio.addEventListener('pause', handlePause);
131
+ audio.addEventListener('ended', handleEnded);
132
+ audio.addEventListener('error', handleError);
133
+ return () => {
134
+ audio.removeEventListener('timeupdate', handleTimeUpdate);
135
+ audio.removeEventListener('play', handlePlay);
136
+ audio.removeEventListener('pause', handlePause);
137
+ audio.removeEventListener('ended', handleEnded);
138
+ audio.removeEventListener('error', handleError);
139
+ };
140
+ }, [audioRef, currentSegment, audioTrack]);
141
+ // Load new segment when currentSegment changes
142
+ useEffect(() => {
143
+ const audio = audioRef.current;
144
+ if (!audio || !audioTrack?.segments)
145
+ return;
146
+ const segment = audioTrack.segments[currentSegment];
147
+ if (!segment)
148
+ return;
149
+ // Apply pending seek and play state
150
+ const applyPendingSeek = () => {
151
+ if (pendingSeekTime.current !== null) {
152
+ const segmentStart = segmentStarts.current[currentSegment] || 0;
153
+ const segmentTime = pendingSeekTime.current - segmentStart;
154
+ audio.currentTime = Math.max(0, segmentTime);
155
+ setCurrentTime(pendingSeekTime.current);
156
+ pendingSeekTime.current = null;
157
+ }
158
+ if (shouldPlayAfterLoad.current) {
159
+ audio.play().catch(() => { });
160
+ shouldPlayAfterLoad.current = false;
161
+ }
162
+ };
163
+ // Check if we're already on this source (avoid unnecessary reload)
164
+ // For blob URLs, check by segment src key
165
+ const currentSrc = audio.src;
166
+ const cachedBlobUrl = blobUrls.current.get(segment.src);
167
+ const isSameSource = currentSrc && (currentSrc === cachedBlobUrl || currentSrc.endsWith(segment.src));
168
+ if (!isSameSource) {
169
+ // Need to load new source - use preloaded blob URL
170
+ const loadAndPlay = async () => {
171
+ const blobUrl = await preloadAudio(segment.src);
172
+ const handleCanPlay = () => {
173
+ setIsAudioReady(true);
174
+ applyPendingSeek();
175
+ audio.removeEventListener('canplay', handleCanPlay);
176
+ };
177
+ audio.addEventListener('canplay', handleCanPlay);
178
+ audio.src = blobUrl;
179
+ audio.load();
180
+ // If audio is already ready (blob is instant), canplay might not fire
181
+ // Check after a microtask to see if it's ready
182
+ await Promise.resolve();
183
+ if (audio.readyState >= 3) {
184
+ audio.removeEventListener('canplay', handleCanPlay);
185
+ setIsAudioReady(true);
186
+ applyPendingSeek();
187
+ }
188
+ };
189
+ loadAndPlay();
190
+ }
191
+ else {
192
+ // Same source - apply seek directly
193
+ applyPendingSeek();
194
+ }
195
+ }, [audioRef, currentSegment, audioTrack, preloadAudio]);
196
+ const play = useCallback(() => {
197
+ const audio = audioRef.current;
198
+ if (audio) {
199
+ if (isEnded) {
200
+ // Restart from beginning
201
+ setCurrentSegment(0);
202
+ setIsEnded(false);
203
+ }
204
+ audio
205
+ .play()
206
+ .then(() => {
207
+ fallbackMode.current = false;
208
+ })
209
+ .catch(() => {
210
+ // Audio playback failed (e.g., autoplay policy or 404).
211
+ // Enable fallback timer so blocks progress without audio.
212
+ fallbackMode.current = true;
213
+ setIsPlaying(true);
214
+ });
215
+ }
216
+ }, [audioRef, isEnded]);
217
+ const pause = useCallback(() => {
218
+ const audio = audioRef.current;
219
+ if (audio) {
220
+ audio.pause();
221
+ }
222
+ // Also set state directly for cases where audio isn't loaded
223
+ // (pause event won't fire if audio has no valid source)
224
+ setIsPlaying(false);
225
+ }, [audioRef]);
226
+ const toggle = useCallback(() => {
227
+ const audio = audioRef.current;
228
+ if (!audio)
229
+ return;
230
+ // Use component state instead of audio.paused to handle cases where
231
+ // audio source isn't loaded (audio.paused is always true without a source)
232
+ if (!isPlaying) {
233
+ play();
234
+ }
235
+ else {
236
+ pause();
237
+ }
238
+ }, [audioRef, isPlaying, play, pause]);
239
+ const seekTo = useCallback((time) => {
240
+ const audio = audioRef.current;
241
+ if (!audio || !audioTrack?.segments)
242
+ return;
243
+ // Clamp time to valid range
244
+ const clampedTime = Math.max(0, Math.min(time, totalDuration));
245
+ // Find which segment this time falls into
246
+ let segmentIndex = 0;
247
+ let segmentStart = 0;
248
+ for (let i = 0; i < audioTrack.segments.length; i++) {
249
+ const segEnd = segmentStart + audioTrack.segments[i].duration;
250
+ if (clampedTime < segEnd) {
251
+ segmentIndex = i;
252
+ break;
253
+ }
254
+ segmentStart = segEnd;
255
+ // Handle edge case: time exactly at end goes to last segment
256
+ if (i === audioTrack.segments.length - 1) {
257
+ segmentIndex = i;
258
+ }
259
+ }
260
+ const wasPlaying = !audio.paused;
261
+ setIsEnded(false);
262
+ // Check if we need to switch segments
263
+ if (segmentIndex !== currentSegment) {
264
+ // Store pending seek time - will be applied after segment loads
265
+ pendingSeekTime.current = clampedTime;
266
+ shouldPlayAfterLoad.current = wasPlaying;
267
+ setCurrentSegment(segmentIndex);
268
+ }
269
+ else {
270
+ // Same segment - seek directly
271
+ const segmentTime = clampedTime - segmentStart;
272
+ audio.currentTime = Math.max(0, segmentTime);
273
+ setCurrentTime(clampedTime);
274
+ }
275
+ }, [audioRef, audioTrack, currentSegment, totalDuration]);
276
+ const skipToSegment = useCallback((index) => {
277
+ if (!audioTrack?.segments || index < 0 || index >= audioTrack.segments.length) {
278
+ return;
279
+ }
280
+ setCurrentSegment(index);
281
+ setIsEnded(false);
282
+ }, [audioTrack]);
283
+ // Restart from beginning
284
+ const restart = useCallback(async () => {
285
+ seekTo(0);
286
+ // Small delay to ensure seek completes before playing
287
+ await new Promise((resolve) => setTimeout(resolve, 50));
288
+ play();
289
+ }, [seekTo, play]);
290
+ // Fallback timer: advance currentTime synthetically when audio.play() was blocked
291
+ // (e.g., autoplay policy or missing audio). Blocks progress at real-time pace
292
+ // without sound. Stops when audio actually starts playing or playback is paused.
293
+ useEffect(() => {
294
+ if (!isPlaying || !fallbackMode.current || !totalDuration)
295
+ return;
296
+ let lastTime = performance.now();
297
+ let raf;
298
+ const tick = (now) => {
299
+ // Audio started playing for real — stop the fallback
300
+ if (!fallbackMode.current)
301
+ return;
302
+ const dt = (now - lastTime) / 1000;
303
+ lastTime = now;
304
+ setCurrentTime((prev) => {
305
+ const next = prev + dt;
306
+ if (next >= totalDuration) {
307
+ fallbackMode.current = false;
308
+ setIsEnded(true);
309
+ setIsPlaying(false);
310
+ return totalDuration;
311
+ }
312
+ return next;
313
+ });
314
+ raf = requestAnimationFrame(tick);
315
+ };
316
+ raf = requestAnimationFrame(tick);
317
+ return () => cancelAnimationFrame(raf);
318
+ }, [isPlaying, totalDuration]);
319
+ return {
320
+ // State
321
+ currentTime,
322
+ isPlaying,
323
+ currentSegment,
324
+ totalDuration,
325
+ isEnded,
326
+ isReady: isAudioReady,
327
+ isAvailable: true, // HTML5 audio is always available in browsers
328
+ // Actions
329
+ play: async () => play(),
330
+ pause: async () => pause(),
331
+ toggle: async () => toggle(),
332
+ seekTo: async (time) => seekTo(time),
333
+ skipToSegment: async (index) => skipToSegment(index),
334
+ restart,
335
+ };
336
+ }
337
+ export default useAudioSync;
338
+ //# sourceMappingURL=useAudioSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAudioSync.js","sourceRoot":"","sources":["../../src/hooks/useAudioSync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * useDocPlayback Hook
3
+ *
4
+ * Manages the playback state for a visual doc, including which block
5
+ * is currently active, transition states, and synchronization with audio.
6
+ *
7
+ * This hook provides:
8
+ * - Current block determination based on time
9
+ * - Transition tracking (entering/exiting blocks)
10
+ * - Manual navigation (next/prev block)
11
+ * - Time-based seeking
12
+ * - Automatic expansion of template blocks
13
+ */
14
+ import type { Doc, Block } from '@bendyline/squisq/schemas';
15
+ import type { Theme } from '@bendyline/squisq/schemas';
16
+ import { type ViewportConfig } from '@bendyline/squisq/doc';
17
+ interface PlaybackState {
18
+ /** Currently visible block */
19
+ currentBlock: Block | null;
20
+ /** Index of current block */
21
+ currentBlockIndex: number;
22
+ /** Previous block (for transitions) */
23
+ previousBlock: Block | null;
24
+ /** Whether current block is entering */
25
+ isEntering: boolean;
26
+ /** Whether previous block is exiting */
27
+ isExiting: boolean;
28
+ /** Time relative to current block start */
29
+ blockTime: number;
30
+ /** Progress through current block (0-1) */
31
+ blockProgress: number;
32
+ /** Overall progress through doc (0-1) */
33
+ docProgress: number;
34
+ /** Expanded blocks (templates converted to full blocks with layers) */
35
+ blocks: Block[];
36
+ }
37
+ interface PlaybackActions {
38
+ /** Go to next block */
39
+ nextBlock: () => void;
40
+ /** Go to previous block */
41
+ prevBlock: () => void;
42
+ /** Go to specific block by index */
43
+ goToBlock: (index: number) => void;
44
+ }
45
+ export declare function useDocPlayback(script: Doc | null, currentTime: number, viewport?: ViewportConfig, renderMode?: boolean, theme?: Theme): PlaybackState & PlaybackActions;
46
+ export default useDocPlayback;
47
+ //# sourceMappingURL=useDocPlayback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDocPlayback.d.ts","sourceRoot":"","sources":["../../src/hooks/useDocPlayback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAY,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAEvD,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAE/B,UAAU,aAAa;IACrB,8BAA8B;IAC9B,YAAY,EAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,6BAA6B;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,aAAa,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5B,wCAAwC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,SAAS,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,UAAU,eAAe;IACvB,uBAAuB;IACvB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,oCAAoC;IACpC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,GAAG,GAAG,IAAI,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,cAA2C,EACrD,UAAU,GAAE,OAAe,EAC3B,KAAK,CAAC,EAAE,KAAK,GACZ,aAAa,GAAG,eAAe,CA2LjC;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * useDocPlayback Hook
3
+ *
4
+ * Manages the playback state for a visual doc, including which block
5
+ * is currently active, transition states, and synchronization with audio.
6
+ *
7
+ * This hook provides:
8
+ * - Current block determination based on time
9
+ * - Transition tracking (entering/exiting blocks)
10
+ * - Manual navigation (next/prev block)
11
+ * - Time-based seeking
12
+ * - Automatic expansion of template blocks
13
+ */
14
+ import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
15
+ import { getBlockAtTime } from '@bendyline/squisq/schemas';
16
+ import { expandDocBlocks, isTemplateBlock, VIEWPORT_PRESETS, } from '@bendyline/squisq/doc';
17
+ export function useDocPlayback(script, currentTime, viewport = VIEWPORT_PRESETS.landscape, renderMode = false, theme) {
18
+ const [transitionState, setTransitionState] = useState({
19
+ entering: false,
20
+ exiting: false,
21
+ previousBlock: null,
22
+ });
23
+ // Expand any template blocks into full blocks
24
+ const blocks = useMemo(() => {
25
+ if (!script?.blocks) {
26
+ return [];
27
+ }
28
+ // Check if any blocks are templates
29
+ const hasTemplates = script.blocks.some(isTemplateBlock);
30
+ if (hasTemplates) {
31
+ // Extract audio segment timing for proper block synchronization
32
+ const audioSegments = script.audio?.segments?.map((seg) => ({
33
+ startTime: seg.startTime,
34
+ duration: seg.duration,
35
+ }));
36
+ // Expand template blocks with audio segment timing, viewport, and persistent layers
37
+ const expanded = expandDocBlocks(script.blocks, {
38
+ audioSegments,
39
+ viewport,
40
+ persistentLayers: script.persistentLayers,
41
+ theme,
42
+ });
43
+ return expanded;
44
+ }
45
+ // All raw blocks, use as-is
46
+ return script.blocks;
47
+ }, [script?.blocks, script?.audio?.segments, script?.persistentLayers, viewport, theme]);
48
+ // Find current block based on time
49
+ const currentBlock = useMemo(() => getBlockAtTime(blocks, currentTime), [blocks, currentTime]);
50
+ const currentBlockIndex = useMemo(() => (currentBlock ? blocks.indexOf(currentBlock) : -1), [blocks, currentBlock]);
51
+ // Calculate block-relative time
52
+ const blockTime = useMemo(() => {
53
+ if (!currentBlock)
54
+ return 0;
55
+ return Math.max(0, currentTime - currentBlock.startTime);
56
+ }, [currentBlock, currentTime]);
57
+ // Calculate progress values
58
+ const blockProgress = useMemo(() => {
59
+ if (!currentBlock || currentBlock.duration === 0)
60
+ return 0;
61
+ return Math.min(1, blockTime / currentBlock.duration);
62
+ }, [currentBlock, blockTime]);
63
+ const docProgress = useMemo(() => {
64
+ if (!script || script.duration === 0)
65
+ return 0;
66
+ return Math.min(1, currentTime / script.duration);
67
+ }, [script, currentTime]);
68
+ // Track block transitions.
69
+ // In render mode, transitions are computed from blockTime so they stay
70
+ // synchronized with the seekTo timeline. In normal mode, setTimeout drives
71
+ // transitions at the browser's real-time clock speed.
72
+ const _prevBlockRef = useMemo(() => currentBlock,
73
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally keyed on index, not block reference
74
+ [currentBlockIndex]);
75
+ useEffect(() => {
76
+ if (!currentBlock || renderMode)
77
+ return;
78
+ // When block changes, trigger transition (real-time mode only)
79
+ if (transitionState.previousBlock?.id !== currentBlock.id) {
80
+ const transition = currentBlock.transition;
81
+ const transitionDuration = transition?.duration || 0;
82
+ if (transitionDuration > 0) {
83
+ // Start transition
84
+ setTransitionState({
85
+ entering: true,
86
+ exiting: true,
87
+ previousBlock: transitionState.previousBlock,
88
+ });
89
+ // End transition after duration
90
+ const timer = setTimeout(() => {
91
+ setTransitionState({
92
+ entering: false,
93
+ exiting: false,
94
+ previousBlock: currentBlock,
95
+ });
96
+ }, transitionDuration * 1000);
97
+ return () => clearTimeout(timer);
98
+ }
99
+ else {
100
+ // Instant cut
101
+ setTransitionState({
102
+ entering: false,
103
+ exiting: false,
104
+ previousBlock: currentBlock,
105
+ });
106
+ }
107
+ }
108
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally keyed on currentBlock?.id only; reading transitionState.previousBlock without dep to avoid infinite loop
109
+ }, [currentBlock?.id, renderMode]);
110
+ // Render mode: track previous block via ref and compute transition from time
111
+ const renderPrevBlockRef = useRef(null);
112
+ useEffect(() => {
113
+ if (!renderMode || !currentBlock)
114
+ return;
115
+ if (transitionState.previousBlock?.id !== currentBlock.id) {
116
+ // Block changed — remember the old block for crossfade
117
+ const oldPrev = transitionState.previousBlock;
118
+ renderPrevBlockRef.current = oldPrev;
119
+ // Store current block as the "last seen" for next transition
120
+ setTransitionState((prev) => ({
121
+ ...prev,
122
+ previousBlock: currentBlock,
123
+ }));
124
+ }
125
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- same pattern: keyed on block identity change
126
+ }, [currentBlock?.id, renderMode]);
127
+ // In render mode, derive entering/exiting from blockTime
128
+ const renderTransitionDuration = currentBlock?.transition?.duration || 0;
129
+ const renderIsEntering = renderMode && renderTransitionDuration > 0 && blockTime < renderTransitionDuration;
130
+ const renderIsExiting = renderIsEntering && renderPrevBlockRef.current !== null;
131
+ // Manual navigation
132
+ const goToBlock = useCallback((index) => {
133
+ if (!script || index < 0 || index >= blocks.length)
134
+ return;
135
+ // This would need to be coordinated with seekTo from audio sync
136
+ // For now, just return the target block's start time
137
+ const targetBlock = blocks[index];
138
+ if (targetBlock) {
139
+ // Caller should use this time with audio seekTo
140
+ return targetBlock.startTime;
141
+ }
142
+ }, [script, blocks]);
143
+ const nextBlock = useCallback(() => {
144
+ if (currentBlockIndex < blocks.length - 1) {
145
+ return goToBlock(currentBlockIndex + 1);
146
+ }
147
+ }, [currentBlockIndex, blocks.length, goToBlock]);
148
+ const prevBlock = useCallback(() => {
149
+ if (currentBlockIndex > 0) {
150
+ return goToBlock(currentBlockIndex - 1);
151
+ }
152
+ }, [currentBlockIndex, goToBlock]);
153
+ return {
154
+ currentBlock,
155
+ currentBlockIndex,
156
+ previousBlock: renderMode
157
+ ? renderIsExiting
158
+ ? renderPrevBlockRef.current
159
+ : null
160
+ : transitionState.exiting
161
+ ? transitionState.previousBlock
162
+ : null,
163
+ isEntering: renderMode ? renderIsEntering : transitionState.entering,
164
+ isExiting: renderMode ? renderIsExiting : transitionState.exiting,
165
+ blockTime,
166
+ blockProgress,
167
+ docProgress,
168
+ nextBlock,
169
+ prevBlock,
170
+ goToBlock,
171
+ /** Expanded blocks (templates converted to full blocks with layers) */
172
+ blocks,
173
+ };
174
+ }
175
+ export default useDocPlayback;
176
+ //# sourceMappingURL=useDocPlayback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDocPlayback.js","sourceRoot":"","sources":["../../src/hooks/useDocPlayback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * useViewportOrientation Hook
3
+ *
4
+ * Detects the current viewport orientation and returns the appropriate
5
+ * VIEWPORT_PRESET for rendering docs. Automatically updates when
6
+ * the window is resized.
7
+ *
8
+ * Thresholds:
9
+ * - Portrait: height > width * 1.2 (significantly taller than wide)
10
+ * - Square: width and height within 20% of each other
11
+ * - Landscape: width > height * 1.2 (significantly wider than tall)
12
+ */
13
+ import { type ViewportConfig, type ViewportOrientation } from '@bendyline/squisq/doc';
14
+ interface UseViewportOrientationResult {
15
+ /** Current viewport preset configuration */
16
+ viewport: ViewportConfig;
17
+ /** Current orientation name */
18
+ orientation: ViewportOrientation;
19
+ /** Current window dimensions */
20
+ windowSize: {
21
+ width: number;
22
+ height: number;
23
+ };
24
+ }
25
+ /**
26
+ * Hook to detect viewport orientation and return appropriate preset.
27
+ * Updates automatically when window is resized.
28
+ */
29
+ export declare function useViewportOrientation(): UseViewportOrientationResult;
30
+ export default useViewportOrientation;
31
+ //# sourceMappingURL=useViewportOrientation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useViewportOrientation.d.ts","sourceRoot":"","sources":["../../src/hooks/useViewportOrientation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,UAAU,4BAA4B;IACpC,4CAA4C;IAC5C,QAAQ,EAAE,cAAc,CAAC;IACzB,+BAA+B;IAC/B,WAAW,EAAE,mBAAmB,CAAC;IACjC,gCAAgC;IAChC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAsCD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,4BAA4B,CA6CrE;AAED,eAAe,sBAAsB,CAAC"}