@bendyline/squisq-video-react 2.2.10 → 2.3.0

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.
@@ -1,10 +1,12 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { Doc, MediaProvider } from '@bendyline/squisq/schemas';
3
- import { a as VideoExportConfig, e as VideoOutputFormat } from '../useVideoExport-raCbwbwb.js';
3
+ import { b as VideoExportConfig, f as VideoOutputFormat } from '../useVideoExport-B2eVCvTX.js';
4
+ export { CoverImageExportFormat, CoverImageExportModal, CoverImageExportModalProps, coverImageFilename, validateCoverImageDimensions } from '../cover-image/index.js';
4
5
  import '@bendyline/squisq/markdown';
6
+ import '@bendyline/squisq/doc';
5
7
  import '@bendyline/squisq-video';
6
8
  import '@bendyline/squisq-react';
7
- import '../mainThreadEncoder-BgcFyYvO.js';
9
+ import '../mainThreadEncoder-BVCLjlfj.js';
8
10
 
9
11
  interface VideoExportModalProps {
10
12
  /** The document to export */
@@ -1,11 +1,20 @@
1
1
  import {
2
2
  VideoExportButton,
3
3
  VideoExportModal
4
- } from "../chunk-ERG6OLLO.js";
5
- import "../chunk-GLOLS2CQ.js";
6
- import "../chunk-2XACUF6E.js";
7
- import "../chunk-MEPETH5V.js";
4
+ } from "../chunk-CRXJOZSH.js";
5
+ import {
6
+ CoverImageExportModal,
7
+ coverImageFilename,
8
+ validateCoverImageDimensions
9
+ } from "../chunk-NTRCMTCF.js";
10
+ import "../chunk-U3RSDWQL.js";
11
+ import "../chunk-YTEDBL6F.js";
12
+ import "../chunk-32QCPFXE.js";
13
+ import "../chunk-5MFQMJ5Z.js";
8
14
  export {
15
+ CoverImageExportModal,
9
16
  VideoExportButton,
10
- VideoExportModal
17
+ VideoExportModal,
18
+ coverImageFilename,
19
+ validateCoverImageDimensions
11
20
  };
@@ -0,0 +1,23 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { Doc, MediaProvider, Theme } from '@bendyline/squisq/schemas';
3
+ import { CoverSlideTemplate } from '@bendyline/squisq/doc';
4
+
5
+ type CoverImageExportFormat = 'png' | 'jpeg' | 'webp';
6
+ interface CoverImageExportModalProps {
7
+ doc: Doc;
8
+ mediaProvider?: MediaProvider | null;
9
+ theme?: Theme;
10
+ coverSlideTemplate?: CoverSlideTemplate;
11
+ defaultWidth?: number;
12
+ defaultHeight?: number;
13
+ defaultFileName?: string;
14
+ colorScheme?: 'light' | 'dark';
15
+ /** Optional host save flow. Return false when the user cancels. */
16
+ saveOutput?: (blob: Blob, filename: string) => boolean | void | Promise<boolean | void>;
17
+ onClose: () => void;
18
+ }
19
+ declare function validateCoverImageDimensions(width: number, height: number): string | null;
20
+ declare function coverImageFilename(requestedName: string | undefined, format: CoverImageExportFormat): string;
21
+ declare function CoverImageExportModal({ doc, mediaProvider, theme, coverSlideTemplate, defaultWidth, defaultHeight, defaultFileName, colorScheme, saveOutput, onClose, }: CoverImageExportModalProps): react_jsx_runtime.JSX.Element;
22
+
23
+ export { type CoverImageExportFormat, CoverImageExportModal, type CoverImageExportModalProps, coverImageFilename, validateCoverImageDimensions };
@@ -0,0 +1,11 @@
1
+ import {
2
+ CoverImageExportModal,
3
+ coverImageFilename,
4
+ validateCoverImageDimensions
5
+ } from "../chunk-NTRCMTCF.js";
6
+ import "../chunk-YTEDBL6F.js";
7
+ export {
8
+ CoverImageExportModal,
9
+ coverImageFilename,
10
+ validateCoverImageDimensions
11
+ };
@@ -1,4 +1,4 @@
1
- export { E as EncoderConfig, a as EncoderFrameSource, M as MainThreadEncoder, c as createEncoder, s as supportsWebCodecs, b as supportsWebCodecsH264 } from '../mainThreadEncoder-BgcFyYvO.js';
1
+ export { E as EncoderConfig, a as EncoderFrameSource, M as MainThreadEncoder, c as createEncoder, s as supportsWebCodecs, b as supportsWebCodecsH264 } from '../mainThreadEncoder-BVCLjlfj.js';
2
2
  export { FfmpegWasmLoadConfig } from '@bendyline/squisq-video';
3
3
 
4
4
  /**
@@ -3,8 +3,8 @@ import {
3
3
  supportsWebCodecs,
4
4
  supportsWebCodecsAac,
5
5
  supportsWebCodecsH264
6
- } from "../chunk-2XACUF6E.js";
7
- import "../chunk-MEPETH5V.js";
6
+ } from "../chunk-32QCPFXE.js";
7
+ import "../chunk-5MFQMJ5Z.js";
8
8
  export {
9
9
  createEncoder,
10
10
  supportsWebCodecs,
@@ -1,21 +1,10 @@
1
- export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoExportConfig, b as VideoExportFramePreview, c as VideoExportResult, d as VideoExportState, e as VideoOutputFormat, r as resolveVideoExportCover, u as useVideoExport } from '../useVideoExport-raCbwbwb.js';
2
- import { Doc } from '@bendyline/squisq/schemas';
1
+ export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoCoverFramePlan, b as VideoExportConfig, c as VideoExportFramePreview, d as VideoExportResult, e as VideoExportState, f as VideoOutputFormat, r as resolveVideoCoverFramePlan, g as resolveVideoExportCover, u as useVideoExport } from '../useVideoExport-B2eVCvTX.js';
2
+ import * as _bendyline_squisq_doc from '@bendyline/squisq/doc';
3
+ import { Doc, MediaProvider } from '@bendyline/squisq/schemas';
3
4
  import { RenderHtmlOptions } from '@bendyline/squisq-video';
4
5
  import { CaptionMode } from '@bendyline/squisq-react';
5
6
  import '@bendyline/squisq/markdown';
6
- import '../mainThreadEncoder-BgcFyYvO.js';
7
-
8
- /**
9
- * useFrameCapture — Hidden div + html2canvas frame capture.
10
- *
11
- * Mounts a DocPlayer in renderMode inside a hidden div (same document),
12
- * then captures individual frames by seeking the player and rendering
13
- * the DOM to a canvas via html2canvas.
14
- *
15
- * Uses React directly — no script injection, no iframes, no eval.
16
- *
17
- * Returns either a reusable canvas or an ImageBitmap snapshot for a Worker.
18
- */
7
+ import '../mainThreadEncoder-BVCLjlfj.js';
19
8
 
20
9
  interface FrameCaptureOptions {
21
10
  /**
@@ -28,6 +17,10 @@ interface FrameCaptureOptions {
28
17
  interface FrameCaptureRenderOptions extends Omit<RenderHtmlOptions, 'playerScript'> {
29
18
  /** Whether the hidden player should materialize its managed cover. */
30
19
  showCoverSlide?: boolean;
20
+ /** Visual template used to materialize the managed cover. */
21
+ coverSlideTemplate?: _bendyline_squisq_doc.CoverSlideTemplate;
22
+ /** Existing provider to use for media resolution. It remains caller-owned. */
23
+ mediaProvider?: MediaProvider;
31
24
  }
32
25
  interface FrameCaptureHandle {
33
26
  /** Initialize the hidden player. Returns the video duration in seconds. */
@@ -1,13 +1,17 @@
1
1
  import {
2
2
  DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS,
3
+ resolveVideoCoverFramePlan,
3
4
  resolveVideoExportCover,
4
- useFrameCapture,
5
5
  useVideoExport
6
- } from "../chunk-GLOLS2CQ.js";
7
- import "../chunk-2XACUF6E.js";
8
- import "../chunk-MEPETH5V.js";
6
+ } from "../chunk-U3RSDWQL.js";
7
+ import {
8
+ useFrameCapture
9
+ } from "../chunk-YTEDBL6F.js";
10
+ import "../chunk-32QCPFXE.js";
11
+ import "../chunk-5MFQMJ5Z.js";
9
12
  export {
10
13
  DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS,
14
+ resolveVideoCoverFramePlan,
11
15
  resolveVideoExportCover,
12
16
  useFrameCapture,
13
17
  useVideoExport
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export { VideoExportButton, VideoExportButtonProps, VideoExportModal, VideoExportModalProps, VideoExportPalette } from './components/index.js';
2
- export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoExportConfig, b as VideoExportFramePreview, c as VideoExportResult, d as VideoExportState, e as VideoOutputFormat, r as resolveVideoExportCover, u as useVideoExport } from './useVideoExport-raCbwbwb.js';
2
+ export { CoverImageExportFormat, CoverImageExportModal, CoverImageExportModalProps, coverImageFilename, validateCoverImageDimensions } from './cover-image/index.js';
3
+ export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoCoverFramePlan, b as VideoExportConfig, c as VideoExportFramePreview, d as VideoExportResult, e as VideoExportState, f as VideoOutputFormat, r as resolveVideoCoverFramePlan, g as resolveVideoExportCover, u as useVideoExport } from './useVideoExport-B2eVCvTX.js';
3
4
  export { FrameCaptureHandle, FrameCaptureOptions, FrameCaptureRenderOptions, useFrameCapture } from './hooks/index.js';
4
- export { E as EncoderConfig, a as EncoderFrameSource, M as MainThreadEncoder, c as createEncoder, s as supportsWebCodecs, b as supportsWebCodecsH264 } from './mainThreadEncoder-BgcFyYvO.js';
5
+ export { E as EncoderConfig, a as EncoderFrameSource, M as MainThreadEncoder, c as createEncoder, s as supportsWebCodecs, b as supportsWebCodecsH264 } from './mainThreadEncoder-BVCLjlfj.js';
5
6
  export { FfmpegWasmLoadConfig } from '@bendyline/squisq-video';
6
7
  export { supportsWebCodecsAac } from './encoder/index.js';
7
8
  import 'react/jsx-runtime';
8
9
  import '@bendyline/squisq/schemas';
10
+ import '@bendyline/squisq/doc';
9
11
  import '@bendyline/squisq/markdown';
10
12
  import '@bendyline/squisq-react';
package/dist/index.js CHANGED
@@ -1,29 +1,41 @@
1
1
  import {
2
2
  VideoExportButton,
3
3
  VideoExportModal
4
- } from "./chunk-ERG6OLLO.js";
4
+ } from "./chunk-CRXJOZSH.js";
5
+ import {
6
+ CoverImageExportModal,
7
+ coverImageFilename,
8
+ validateCoverImageDimensions
9
+ } from "./chunk-NTRCMTCF.js";
5
10
  import {
6
11
  DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS,
12
+ resolveVideoCoverFramePlan,
7
13
  resolveVideoExportCover,
8
- useFrameCapture,
9
14
  useVideoExport
10
- } from "./chunk-GLOLS2CQ.js";
15
+ } from "./chunk-U3RSDWQL.js";
16
+ import {
17
+ useFrameCapture
18
+ } from "./chunk-YTEDBL6F.js";
11
19
  import {
12
20
  createEncoder,
13
21
  supportsWebCodecs,
14
22
  supportsWebCodecsAac,
15
23
  supportsWebCodecsH264
16
- } from "./chunk-2XACUF6E.js";
17
- import "./chunk-MEPETH5V.js";
24
+ } from "./chunk-32QCPFXE.js";
25
+ import "./chunk-5MFQMJ5Z.js";
18
26
  export {
27
+ CoverImageExportModal,
19
28
  DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS,
20
29
  VideoExportButton,
21
30
  VideoExportModal,
31
+ coverImageFilename,
22
32
  createEncoder,
33
+ resolveVideoCoverFramePlan,
23
34
  resolveVideoExportCover,
24
35
  supportsWebCodecs,
25
36
  supportsWebCodecsAac,
26
37
  supportsWebCodecsH264,
27
38
  useFrameCapture,
28
- useVideoExport
39
+ useVideoExport,
40
+ validateCoverImageDimensions
29
41
  };
@@ -31,6 +31,13 @@ interface EncoderConfig {
31
31
  numberOfChannels: number;
32
32
  sampleRate: number;
33
33
  };
34
+ /**
35
+ * Allow the muxer to spill settled output bytes into Blob storage so a long
36
+ * export does not hold the whole MP4 in JS memory. Only valid when the
37
+ * caller will finalize via {@link MainThreadEncoder.finalizeBlob} — byte
38
+ * consumers (GIF transcode, ffmpeg audio muxing) must leave this off.
39
+ */
40
+ spillOutputToBlob?: boolean;
34
41
  }
35
42
  type EncoderFrameSource = ImageBitmap | HTMLCanvasElement;
36
43
  interface MainThreadEncoder {
@@ -44,6 +51,8 @@ interface MainThreadEncoder {
44
51
  addAudioChunk?(chunk: EncodedAudioChunk, meta?: EncodedAudioChunkMetadata): void;
45
52
  /** Flush pending frames and finalize the MP4. Returns the MP4 ArrayBuffer. */
46
53
  finalize(): Promise<ArrayBuffer>;
54
+ /** Finalize directly into a Blob, avoiding a second full-file allocation. */
55
+ finalizeBlob?(): Promise<Blob>;
47
56
  /** Close the encoder without producing output (e.g., on cancel). */
48
57
  close(): void;
49
58
  }
@@ -1,8 +1,9 @@
1
1
  import { MediaProvider, Theme, VideoPresentation, VideoPipSize, VideoPipShape, VideoPipPosition, Doc } from '@bendyline/squisq/schemas';
2
2
  import { ResourcePolicy } from '@bendyline/squisq/markdown';
3
+ import { CoverSlidePlayback } from '@bendyline/squisq/doc';
3
4
  import { VideoQuality, VideoOrientation, FfmpegWasmLoadConfig } from '@bendyline/squisq-video';
4
5
  import { CaptionMode } from '@bendyline/squisq-react';
5
- import { a as EncoderFrameSource } from './mainThreadEncoder-BgcFyYvO.js';
6
+ import { a as EncoderFrameSource } from './mainThreadEncoder-BVCLjlfj.js';
6
7
 
7
8
  /**
8
9
  * useVideoExport — Main orchestration hook for browser video export.
@@ -21,7 +22,7 @@ import { a as EncoderFrameSource } from './mainThreadEncoder-BgcFyYvO.js';
21
22
  * <button onClick={() => startExport(doc, options)}>Export</button>
22
23
  */
23
24
 
24
- declare const DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS = 2;
25
+ declare const DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS: number;
25
26
  type VideoExportState = 'idle' | 'preparing' | 'capturing' | 'encoding' | 'complete' | 'error';
26
27
  /** Browser export container format. */
27
28
  type VideoOutputFormat = 'mp4' | 'gif';
@@ -76,7 +77,17 @@ interface VideoExportConfig {
76
77
  pipPosition?: VideoPipPosition;
77
78
  /** Managed-cover visibility override. Omitted values resolve from Doc frontmatter. */
78
79
  showCoverSlide?: boolean;
79
- /** Seconds to hold an enabled managed cover before story frame zero (default: 2). */
80
+ /**
81
+ * Seconds to show an enabled managed cover. Omitted values resolve from Doc
82
+ * frontmatter, then fall back to 2 seconds.
83
+ */
84
+ coverDuration?: number;
85
+ /** Whether the story advances under the cover or starts after it. */
86
+ coverPlayback?: CoverSlidePlayback;
87
+ /**
88
+ * @deprecated Use `coverDuration` plus `coverPlayback: 'preroll'`.
89
+ * Seconds to hold an enabled managed cover before story frame zero.
90
+ */
80
91
  coverPreRoll?: number;
81
92
  /** Player IIFE bundle (unused in browser export, kept for CLI/Playwright path) */
82
93
  playerScript?: string;
@@ -85,10 +96,23 @@ interface VideoExportConfig {
85
96
  }
86
97
  interface ResolvedVideoExportCover {
87
98
  showCoverSlide: boolean;
99
+ coverDuration: number;
100
+ coverPlayback: CoverSlidePlayback;
101
+ /** Audio/story offset introduced by preroll mode. */
88
102
  coverPreRoll: number;
89
103
  }
90
104
  /** Resolve the cover segment shared by browser MP4/GIF capture. */
91
- declare function resolveVideoExportCover(doc: Doc, config?: Pick<VideoExportConfig, 'showCoverSlide' | 'coverPreRoll'>): ResolvedVideoExportCover;
105
+ declare function resolveVideoExportCover(doc: Doc, config?: Pick<VideoExportConfig, 'showCoverSlide' | 'coverDuration' | 'coverPlayback' | 'coverPreRoll'>): ResolvedVideoExportCover;
106
+ interface VideoCoverFramePlan {
107
+ coverFrameCount: number;
108
+ storyFrameCount: number;
109
+ totalFrames: number;
110
+ totalDuration: number;
111
+ audioOffset: number;
112
+ captureTimeForFrame: (frameIndex: number) => number;
113
+ }
114
+ /** Build the exact frame/audio schedule for overlay and preroll cover timing. */
115
+ declare function resolveVideoCoverFramePlan(docDuration: number, fps: number, cover: ResolvedVideoExportCover): VideoCoverFramePlan;
92
116
  interface VideoExportResult {
93
117
  /** Current export state */
94
118
  state: VideoExportState;
@@ -160,4 +184,4 @@ interface UseVideoExportOptions {
160
184
  }
161
185
  declare function useVideoExport(options?: UseVideoExportOptions): VideoExportResult;
162
186
 
163
- export { DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS as D, type ResolvedVideoExportCover as R, type UseVideoExportOptions as U, type VideoAudioPolicy as V, type VideoExportConfig as a, type VideoExportFramePreview as b, type VideoExportResult as c, type VideoExportState as d, type VideoOutputFormat as e, resolveVideoExportCover as r, useVideoExport as u };
187
+ export { DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS as D, type ResolvedVideoExportCover as R, type UseVideoExportOptions as U, type VideoAudioPolicy as V, type VideoCoverFramePlan as a, type VideoExportConfig as b, type VideoExportFramePreview as c, type VideoExportResult as d, type VideoExportState as e, type VideoOutputFormat as f, resolveVideoExportCover as g, resolveVideoCoverFramePlan as r, useVideoExport as u };
@@ -3,7 +3,7 @@ import {
3
3
  createMp4Muxer,
4
4
  resolveWebCodecsQueueLimit,
5
5
  shouldEncodeFfmpegBatch
6
- } from "../chunk-MEPETH5V.js";
6
+ } from "../chunk-5MFQMJ5Z.js";
7
7
 
8
8
  // src/workers/encode.worker.ts
9
9
  import {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq-video-react",
3
- "version": "2.2.10",
3
+ "version": "2.3.0",
4
4
  "description": "React components for browser-based MP4 and animated-GIF export of Squisq documents",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -38,6 +38,10 @@
38
38
  "types": "./dist/components/index.d.ts",
39
39
  "import": "./dist/components/index.js"
40
40
  },
41
+ "./cover-image": {
42
+ "types": "./dist/cover-image/index.d.ts",
43
+ "import": "./dist/cover-image/index.js"
44
+ },
41
45
  "./hooks": {
42
46
  "types": "./dist/hooks/index.d.ts",
43
47
  "import": "./dist/hooks/index.js"
@@ -65,9 +69,9 @@
65
69
  "react-dom": "^18.0.0 || ^19.0.0"
66
70
  },
67
71
  "dependencies": {
68
- "@bendyline/squisq": "2.4.4",
69
- "@bendyline/squisq-video": "2.2.8",
70
- "@bendyline/squisq-react": "2.4.6",
72
+ "@bendyline/squisq": "2.5.0",
73
+ "@bendyline/squisq-video": "2.2.9",
74
+ "@bendyline/squisq-react": "2.5.0",
71
75
  "@ffmpeg/core": "0.12.9",
72
76
  "@ffmpeg/ffmpeg": "0.12.15",
73
77
  "@ffmpeg/util": "0.12.2",