@bendyline/squisq-react 1.3.1 → 1.3.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 (187) hide show
  1. package/dist/index.d.ts +710 -35
  2. package/dist/index.js +4288 -33
  3. package/dist/index.js.map +1 -1
  4. package/dist/squisq-player.global.js +1 -1
  5. package/dist/standalone-source.js +1 -1
  6. package/package.json +2 -2
  7. package/dist/BlockRenderer.d.ts +0 -37
  8. package/dist/BlockRenderer.d.ts.map +0 -1
  9. package/dist/BlockRenderer.js +0 -54
  10. package/dist/BlockRenderer.js.map +0 -1
  11. package/dist/CaptionOverlay.d.ts +0 -33
  12. package/dist/CaptionOverlay.d.ts.map +0 -1
  13. package/dist/CaptionOverlay.js +0 -44
  14. package/dist/CaptionOverlay.js.map +0 -1
  15. package/dist/DocControlsBottom.d.ts +0 -28
  16. package/dist/DocControlsBottom.d.ts.map +0 -1
  17. package/dist/DocControlsBottom.js +0 -27
  18. package/dist/DocControlsBottom.js.map +0 -1
  19. package/dist/DocControlsOverlay.d.ts +0 -28
  20. package/dist/DocControlsOverlay.d.ts.map +0 -1
  21. package/dist/DocControlsOverlay.js +0 -80
  22. package/dist/DocControlsOverlay.js.map +0 -1
  23. package/dist/DocControlsSidebar.d.ts +0 -27
  24. package/dist/DocControlsSidebar.d.ts.map +0 -1
  25. package/dist/DocControlsSidebar.js +0 -10
  26. package/dist/DocControlsSidebar.js.map +0 -1
  27. package/dist/DocControlsSlideshow.d.ts +0 -20
  28. package/dist/DocControlsSlideshow.d.ts.map +0 -1
  29. package/dist/DocControlsSlideshow.js +0 -69
  30. package/dist/DocControlsSlideshow.js.map +0 -1
  31. package/dist/DocPlayer.d.ts +0 -97
  32. package/dist/DocPlayer.d.ts.map +0 -1
  33. package/dist/DocPlayer.js +0 -657
  34. package/dist/DocPlayer.js.map +0 -1
  35. package/dist/DocPlayerWithSidebar.d.ts +0 -41
  36. package/dist/DocPlayerWithSidebar.d.ts.map +0 -1
  37. package/dist/DocPlayerWithSidebar.js +0 -69
  38. package/dist/DocPlayerWithSidebar.js.map +0 -1
  39. package/dist/DocProgressBar.d.ts +0 -31
  40. package/dist/DocProgressBar.d.ts.map +0 -1
  41. package/dist/DocProgressBar.js +0 -122
  42. package/dist/DocProgressBar.js.map +0 -1
  43. package/dist/InlineAudioPlayer.d.ts +0 -15
  44. package/dist/InlineAudioPlayer.d.ts.map +0 -1
  45. package/dist/InlineAudioPlayer.js +0 -22
  46. package/dist/InlineAudioPlayer.js.map +0 -1
  47. package/dist/InlineVideoPlayer.d.ts +0 -21
  48. package/dist/InlineVideoPlayer.d.ts.map +0 -1
  49. package/dist/InlineVideoPlayer.js +0 -29
  50. package/dist/InlineVideoPlayer.js.map +0 -1
  51. package/dist/LinearDocView.d.ts +0 -73
  52. package/dist/LinearDocView.d.ts.map +0 -1
  53. package/dist/LinearDocView.js +0 -451
  54. package/dist/LinearDocView.js.map +0 -1
  55. package/dist/MarkdownRenderer.d.ts +0 -32
  56. package/dist/MarkdownRenderer.d.ts.map +0 -1
  57. package/dist/MarkdownRenderer.js +0 -259
  58. package/dist/MarkdownRenderer.js.map +0 -1
  59. package/dist/SocialCaptionOverlay.d.ts +0 -27
  60. package/dist/SocialCaptionOverlay.d.ts.map +0 -1
  61. package/dist/SocialCaptionOverlay.js +0 -185
  62. package/dist/SocialCaptionOverlay.js.map +0 -1
  63. package/dist/__tests__/BlockRenderer.test.d.ts +0 -2
  64. package/dist/__tests__/BlockRenderer.test.d.ts.map +0 -1
  65. package/dist/__tests__/BlockRenderer.test.js +0 -82
  66. package/dist/__tests__/BlockRenderer.test.js.map +0 -1
  67. package/dist/__tests__/DocControlsSlideshow.test.d.ts +0 -2
  68. package/dist/__tests__/DocControlsSlideshow.test.d.ts.map +0 -1
  69. package/dist/__tests__/DocControlsSlideshow.test.js +0 -89
  70. package/dist/__tests__/DocControlsSlideshow.test.js.map +0 -1
  71. package/dist/__tests__/JsonView.test.d.ts +0 -2
  72. package/dist/__tests__/JsonView.test.d.ts.map +0 -1
  73. package/dist/__tests__/JsonView.test.js +0 -93
  74. package/dist/__tests__/JsonView.test.js.map +0 -1
  75. package/dist/__tests__/LinearDocView.test.d.ts +0 -2
  76. package/dist/__tests__/LinearDocView.test.d.ts.map +0 -1
  77. package/dist/__tests__/LinearDocView.test.js +0 -250
  78. package/dist/__tests__/LinearDocView.test.js.map +0 -1
  79. package/dist/__tests__/MarkdownRenderer.test.d.ts +0 -2
  80. package/dist/__tests__/MarkdownRenderer.test.d.ts.map +0 -1
  81. package/dist/__tests__/MarkdownRenderer.test.js +0 -208
  82. package/dist/__tests__/MarkdownRenderer.test.js.map +0 -1
  83. package/dist/__tests__/TableLayer.test.d.ts +0 -2
  84. package/dist/__tests__/TableLayer.test.d.ts.map +0 -1
  85. package/dist/__tests__/TableLayer.test.js +0 -121
  86. package/dist/__tests__/TableLayer.test.js.map +0 -1
  87. package/dist/__tests__/exports.test.d.ts +0 -2
  88. package/dist/__tests__/exports.test.d.ts.map +0 -1
  89. package/dist/__tests__/exports.test.js +0 -48
  90. package/dist/__tests__/exports.test.js.map +0 -1
  91. package/dist/hooks/AudioProvider.d.ts +0 -71
  92. package/dist/hooks/AudioProvider.d.ts.map +0 -1
  93. package/dist/hooks/AudioProvider.js +0 -52
  94. package/dist/hooks/AudioProvider.js.map +0 -1
  95. package/dist/hooks/MediaContext.d.ts +0 -35
  96. package/dist/hooks/MediaContext.d.ts.map +0 -1
  97. package/dist/hooks/MediaContext.js +0 -72
  98. package/dist/hooks/MediaContext.js.map +0 -1
  99. package/dist/hooks/index.d.ts +0 -6
  100. package/dist/hooks/index.d.ts.map +0 -1
  101. package/dist/hooks/index.js +0 -5
  102. package/dist/hooks/index.js.map +0 -1
  103. package/dist/hooks/useAudioSync.d.ts +0 -18
  104. package/dist/hooks/useAudioSync.d.ts.map +0 -1
  105. package/dist/hooks/useAudioSync.js +0 -340
  106. package/dist/hooks/useAudioSync.js.map +0 -1
  107. package/dist/hooks/useAutoSurface.d.ts +0 -11
  108. package/dist/hooks/useAutoSurface.d.ts.map +0 -1
  109. package/dist/hooks/useAutoSurface.js +0 -24
  110. package/dist/hooks/useAutoSurface.js.map +0 -1
  111. package/dist/hooks/useDocPlayback.d.ts +0 -47
  112. package/dist/hooks/useDocPlayback.d.ts.map +0 -1
  113. package/dist/hooks/useDocPlayback.js +0 -179
  114. package/dist/hooks/useDocPlayback.js.map +0 -1
  115. package/dist/hooks/useViewportOrientation.d.ts +0 -31
  116. package/dist/hooks/useViewportOrientation.d.ts.map +0 -1
  117. package/dist/hooks/useViewportOrientation.js +0 -92
  118. package/dist/hooks/useViewportOrientation.js.map +0 -1
  119. package/dist/index.d.ts.map +0 -1
  120. package/dist/jsonView/JsonView.d.ts +0 -26
  121. package/dist/jsonView/JsonView.d.ts.map +0 -1
  122. package/dist/jsonView/JsonView.js +0 -12
  123. package/dist/jsonView/JsonView.js.map +0 -1
  124. package/dist/jsonView/RenderNode.d.ts +0 -22
  125. package/dist/jsonView/RenderNode.d.ts.map +0 -1
  126. package/dist/jsonView/RenderNode.js +0 -30
  127. package/dist/jsonView/RenderNode.js.map +0 -1
  128. package/dist/jsonView/index.d.ts +0 -3
  129. package/dist/jsonView/index.d.ts.map +0 -1
  130. package/dist/jsonView/index.js +0 -2
  131. package/dist/jsonView/index.js.map +0 -1
  132. package/dist/jsonView/useJsonViewTokens.d.ts +0 -14
  133. package/dist/jsonView/useJsonViewTokens.d.ts.map +0 -1
  134. package/dist/jsonView/useJsonViewTokens.js +0 -34
  135. package/dist/jsonView/useJsonViewTokens.js.map +0 -1
  136. package/dist/jsonView/viewers.d.ts +0 -30
  137. package/dist/jsonView/viewers.d.ts.map +0 -1
  138. package/dist/jsonView/viewers.js +0 -226
  139. package/dist/jsonView/viewers.js.map +0 -1
  140. package/dist/layers/ImageLayer.d.ts +0 -23
  141. package/dist/layers/ImageLayer.d.ts.map +0 -1
  142. package/dist/layers/ImageLayer.js +0 -104
  143. package/dist/layers/ImageLayer.js.map +0 -1
  144. package/dist/layers/MapLayer.d.ts +0 -29
  145. package/dist/layers/MapLayer.d.ts.map +0 -1
  146. package/dist/layers/MapLayer.js +0 -97
  147. package/dist/layers/MapLayer.js.map +0 -1
  148. package/dist/layers/ShapeLayer.d.ts +0 -20
  149. package/dist/layers/ShapeLayer.d.ts.map +0 -1
  150. package/dist/layers/ShapeLayer.js +0 -39
  151. package/dist/layers/ShapeLayer.js.map +0 -1
  152. package/dist/layers/TableLayer.d.ts +0 -23
  153. package/dist/layers/TableLayer.d.ts.map +0 -1
  154. package/dist/layers/TableLayer.js +0 -58
  155. package/dist/layers/TableLayer.js.map +0 -1
  156. package/dist/layers/TextLayer.d.ts +0 -23
  157. package/dist/layers/TextLayer.d.ts.map +0 -1
  158. package/dist/layers/TextLayer.js +0 -126
  159. package/dist/layers/TextLayer.js.map +0 -1
  160. package/dist/layers/VideoLayer.d.ts +0 -40
  161. package/dist/layers/VideoLayer.d.ts.map +0 -1
  162. package/dist/layers/VideoLayer.js +0 -105
  163. package/dist/layers/VideoLayer.js.map +0 -1
  164. package/dist/layers/index.d.ts +0 -6
  165. package/dist/layers/index.d.ts.map +0 -1
  166. package/dist/layers/index.js +0 -6
  167. package/dist/layers/index.js.map +0 -1
  168. package/dist/standalone-entry.d.ts +0 -69
  169. package/dist/standalone-entry.d.ts.map +0 -1
  170. package/dist/standalone-entry.js +0 -185
  171. package/dist/standalone-entry.js.map +0 -1
  172. package/dist/types.d.ts +0 -154
  173. package/dist/types.d.ts.map +0 -1
  174. package/dist/types.js +0 -21
  175. package/dist/types.js.map +0 -1
  176. package/dist/utils/animationUtils.d.ts +0 -8
  177. package/dist/utils/animationUtils.d.ts.map +0 -1
  178. package/dist/utils/animationUtils.js +0 -8
  179. package/dist/utils/animationUtils.js.map +0 -1
  180. package/dist/utils/layerUtils.d.ts +0 -17
  181. package/dist/utils/layerUtils.d.ts.map +0 -1
  182. package/dist/utils/layerUtils.js +0 -37
  183. package/dist/utils/layerUtils.js.map +0 -1
  184. package/dist/utils/mapTileUtils.d.ts +0 -105
  185. package/dist/utils/mapTileUtils.d.ts.map +0 -1
  186. package/dist/utils/mapTileUtils.js +0 -268
  187. package/dist/utils/mapTileUtils.js.map +0 -1
@@ -1,72 +0,0 @@
1
- /**
2
- * MediaContext — React context for providing a MediaProvider to layer components.
3
- *
4
- * When a MediaProvider is available in context, layer components (ImageLayer,
5
- * VideoLayer) will use it to resolve media URLs instead of the basePath prop.
6
- * This enables slot-based media storage where binary assets are served from
7
- * IndexedDB as blob URLs.
8
- *
9
- * Usage:
10
- * const provider = createSlotMediaProvider(slotId);
11
- * <MediaContext.Provider value={provider}>
12
- * <DocPlayer doc={doc} basePath="/" />
13
- * </MediaContext.Provider>
14
- */
15
- import { createContext, useContext, useState, useEffect, useMemo } from 'react';
16
- /**
17
- * React context holding the current MediaProvider (or null if none provided).
18
- */
19
- export const MediaContext = createContext(null);
20
- /**
21
- * Hook to access the current MediaProvider from context.
22
- * Returns null if no provider is set.
23
- */
24
- export function useMediaProvider() {
25
- return useContext(MediaContext);
26
- }
27
- /**
28
- * Hook to resolve a media URL via the MediaProvider (if available),
29
- * falling back to basePath-based resolution.
30
- *
31
- * Returns the resolved URL string. Updates when the provider or path changes.
32
- *
33
- * @param relativePath - Relative media path from the document (e.g., 'hero.jpg')
34
- * @param basePath - Fallback base path for URL construction
35
- */
36
- export function useMediaUrl(relativePath, basePath) {
37
- const provider = useMediaProvider();
38
- // Defensive: callers (esp. preview surfaces like InlinePreviewGutter)
39
- // sometimes feed in template-generated layers whose `content.src` is
40
- // undefined while the user is still authoring the block. Treat that
41
- // as an empty string rather than crashing the whole React tree.
42
- const safePath = typeof relativePath === 'string' ? relativePath : '';
43
- // For absolute/http URLs, skip resolution entirely
44
- const isAbsolute = !safePath ||
45
- safePath.startsWith('http') ||
46
- safePath.startsWith('/') ||
47
- safePath.startsWith('data:') ||
48
- safePath.startsWith('blob:');
49
- // Memoize fallback to avoid recalculating on every render
50
- const fallback = useMemo(() => (isAbsolute ? safePath : `${basePath}/${safePath}`), [isAbsolute, safePath, basePath]);
51
- // Fast path: no provider or absolute URL — return synchronously, skip effect entirely
52
- const needsProvider = !isAbsolute && !!provider;
53
- const [url, setUrl] = useState(fallback);
54
- useEffect(() => {
55
- if (!needsProvider) {
56
- setUrl(fallback);
57
- return;
58
- }
59
- let cancelled = false;
60
- provider.resolveUrl(safePath).then((resolved) => {
61
- if (!cancelled)
62
- setUrl(resolved);
63
- });
64
- return () => {
65
- cancelled = true;
66
- };
67
- }, [needsProvider, provider, safePath, fallback]);
68
- // When provider is not needed, return fallback directly to avoid
69
- // the one-frame delay from the initial useState → useEffect cycle
70
- return needsProvider ? url : fallback;
71
- }
72
- //# sourceMappingURL=MediaContext.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MediaContext.js","sourceRoot":"","sources":["../../src/hooks/MediaContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGhF;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAuB,IAAI,CAAC,CAAC;AAEtE;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,UAAU,CAAC,YAAY,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB,EAAE,QAAgB;IAChE,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IAEpC,sEAAsE;IACtE,qEAAqE;IACrE,oEAAoE;IACpE,gEAAgE;IAChE,MAAM,QAAQ,GAAG,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtE,mDAAmD;IACnD,MAAM,UAAU,GACd,CAAC,QAAQ;QACT,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;QACxB,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAE/B,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAC,EACzD,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CACjC,CAAC;IAEF,sFAAsF;IACtF,MAAM,aAAa,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,QAAQ,CAAC;IAEhD,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,QAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC/C,IAAI,CAAC,SAAS;gBAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAElD,iEAAiE;IACjE,kEAAkE;IAClE,OAAO,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AACxC,CAAC"}
@@ -1,6 +0,0 @@
1
- export { calculateSegmentTiming, findSegmentAtTime } from './AudioProvider';
2
- export type { AudioState, AudioActions, AudioProvider, AudioProviderConfig } from './AudioProvider';
3
- export { useAudioSync } from './useAudioSync';
4
- export { useDocPlayback } from './useDocPlayback';
5
- export { useViewportOrientation } from './useViewportOrientation';
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC5E,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEpG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -1,5 +0,0 @@
1
- export { calculateSegmentTiming, findSegmentAtTime } from './AudioProvider';
2
- export { useAudioSync } from './useAudioSync';
3
- export { useDocPlayback } from './useDocPlayback';
4
- export { useViewportOrientation } from './useViewportOrientation';
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -1,18 +0,0 @@
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 type { RefObject } from 'react';
14
- import type { AudioTrack } from '@bendyline/squisq/schemas';
15
- import type { AudioProvider } from './AudioProvider';
16
- export declare function useAudioSync(audioRef: RefObject<HTMLAudioElement>, audioTrack: AudioTrack | undefined, basePath?: string): AudioProvider;
17
- export default useAudioSync;
18
- //# sourceMappingURL=useAudioSync.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAudioSync.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,SAAS,CAAC,gBAAgB,CAAC,EACrC,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,QAAQ,GAAE,MAAW,GACpB,aAAa,CAgXf;AAED,eAAe,YAAY,CAAC"}
@@ -1,340 +0,0 @@
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
- // When totalDuration is 0 (no audio segments), don't clamp — allow
245
- // seeking by block timing alone (used in render mode / preview).
246
- const clampedTime = totalDuration > 0 ? Math.max(0, Math.min(time, totalDuration)) : Math.max(0, time);
247
- // Find which segment this time falls into
248
- let segmentIndex = 0;
249
- let segmentStart = 0;
250
- for (let i = 0; i < audioTrack.segments.length; i++) {
251
- const segEnd = segmentStart + audioTrack.segments[i].duration;
252
- if (clampedTime < segEnd) {
253
- segmentIndex = i;
254
- break;
255
- }
256
- segmentStart = segEnd;
257
- // Handle edge case: time exactly at end goes to last segment
258
- if (i === audioTrack.segments.length - 1) {
259
- segmentIndex = i;
260
- }
261
- }
262
- const wasPlaying = !audio.paused;
263
- setIsEnded(false);
264
- // Check if we need to switch segments
265
- if (segmentIndex !== currentSegment) {
266
- // Store pending seek time - will be applied after segment loads
267
- pendingSeekTime.current = clampedTime;
268
- shouldPlayAfterLoad.current = wasPlaying;
269
- setCurrentSegment(segmentIndex);
270
- }
271
- else {
272
- // Same segment - seek directly
273
- const segmentTime = clampedTime - segmentStart;
274
- audio.currentTime = Math.max(0, segmentTime);
275
- setCurrentTime(clampedTime);
276
- }
277
- }, [audioRef, audioTrack, currentSegment, totalDuration]);
278
- const skipToSegment = useCallback((index) => {
279
- if (!audioTrack?.segments || index < 0 || index >= audioTrack.segments.length) {
280
- return;
281
- }
282
- setCurrentSegment(index);
283
- setIsEnded(false);
284
- }, [audioTrack]);
285
- // Restart from beginning
286
- const restart = useCallback(async () => {
287
- seekTo(0);
288
- // Small delay to ensure seek completes before playing
289
- await new Promise((resolve) => setTimeout(resolve, 50));
290
- play();
291
- }, [seekTo, play]);
292
- // Fallback timer: advance currentTime synthetically when audio.play() was blocked
293
- // (e.g., autoplay policy or missing audio). Blocks progress at real-time pace
294
- // without sound. Stops when audio actually starts playing or playback is paused.
295
- useEffect(() => {
296
- if (!isPlaying || !fallbackMode.current || !totalDuration)
297
- return;
298
- let lastTime = performance.now();
299
- let raf;
300
- const tick = (now) => {
301
- // Audio started playing for real — stop the fallback
302
- if (!fallbackMode.current)
303
- return;
304
- const dt = (now - lastTime) / 1000;
305
- lastTime = now;
306
- setCurrentTime((prev) => {
307
- const next = prev + dt;
308
- if (next >= totalDuration) {
309
- fallbackMode.current = false;
310
- setIsEnded(true);
311
- setIsPlaying(false);
312
- return totalDuration;
313
- }
314
- return next;
315
- });
316
- raf = requestAnimationFrame(tick);
317
- };
318
- raf = requestAnimationFrame(tick);
319
- return () => cancelAnimationFrame(raf);
320
- }, [isPlaying, totalDuration]);
321
- return {
322
- // State
323
- currentTime,
324
- isPlaying,
325
- currentSegment,
326
- totalDuration,
327
- isEnded,
328
- isReady: isAudioReady,
329
- isAvailable: true, // HTML5 audio is always available in browsers
330
- // Actions
331
- play: async () => play(),
332
- pause: async () => pause(),
333
- toggle: async () => toggle(),
334
- seekTo: async (time) => seekTo(time),
335
- skipToSegment: async (index) => skipToSegment(index),
336
- restart,
337
- };
338
- }
339
- export default useAudioSync;
340
- //# sourceMappingURL=useAudioSync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAudioSync.js","sourceRoot":"","sources":["../../src/hooks/useAudioSync.ts"],"names":[],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- import { type SurfaceScheme } from '@bendyline/squisq/schemas';
2
- /**
3
- * Live-track `prefers-color-scheme` and return a stable SurfaceScheme.
4
- * `enabled: false` short-circuits to LIGHT_SURFACE (callers pass `false`
5
- * when a static surface was provided so the hook never observes the
6
- * media query). The `MediaQueryList` and the `subscribe`/`getSnapshot`
7
- * callbacks are memoized so `useSyncExternalStore` doesn't resubscribe on
8
- * every parent render.
9
- */
10
- export declare function useAutoSurface(enabled: boolean): SurfaceScheme;
11
- //# sourceMappingURL=useAutoSurface.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAutoSurface.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutoSurface.ts"],"names":[],"mappings":"AACA,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAK5F;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAkB9D"}
@@ -1,24 +0,0 @@
1
- import { useCallback, useMemo, useSyncExternalStore } from 'react';
2
- import { DARK_SURFACE, LIGHT_SURFACE } from '@bendyline/squisq/schemas';
3
- const DARK_QUERY = '(prefers-color-scheme: dark)';
4
- const getServerSnapshot = () => LIGHT_SURFACE;
5
- /**
6
- * Live-track `prefers-color-scheme` and return a stable SurfaceScheme.
7
- * `enabled: false` short-circuits to LIGHT_SURFACE (callers pass `false`
8
- * when a static surface was provided so the hook never observes the
9
- * media query). The `MediaQueryList` and the `subscribe`/`getSnapshot`
10
- * callbacks are memoized so `useSyncExternalStore` doesn't resubscribe on
11
- * every parent render.
12
- */
13
- export function useAutoSurface(enabled) {
14
- const mql = useMemo(() => (enabled && typeof window !== 'undefined' ? window.matchMedia(DARK_QUERY) : null), [enabled]);
15
- const subscribe = useCallback((cb) => {
16
- if (!mql)
17
- return () => { };
18
- mql.addEventListener('change', cb);
19
- return () => mql.removeEventListener('change', cb);
20
- }, [mql]);
21
- const getSnapshot = useCallback(() => (mql?.matches ? DARK_SURFACE : LIGHT_SURFACE), [mql]);
22
- return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
23
- }
24
- //# sourceMappingURL=useAutoSurface.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAutoSurface.js","sourceRoot":"","sources":["../../src/hooks/useAutoSurface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAsB,MAAM,2BAA2B,CAAC;AAE5F,MAAM,UAAU,GAAG,8BAA8B,CAAC;AAClD,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,OAAO,CACjB,GAAG,EAAE,CAAC,CAAC,OAAO,IAAI,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EACvF,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,EAAc,EAAE,EAAE;QACjB,IAAI,CAAC,GAAG;YAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;QAC1B,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACnC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC,EACD,CAAC,GAAG,CAAC,CACN,CAAC;IAEF,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5F,OAAO,oBAAoB,CAAC,SAAS,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC;AACzE,CAAC"}
@@ -1,47 +0,0 @@
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
@@ -1 +0,0 @@
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,EAKL,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,CA+LjC;AAED,eAAe,cAAc,CAAC"}