@bendyline/squisq-editor-react 2.3.4 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/{chunk-GNIVYDZH.js → chunk-KR4VLXUM.js} +10998 -8247
- package/dist/{chunk-6VDYKI3L.js → chunk-LJRHKXDV.js} +3 -1
- package/dist/chunk-LOTY7AOS.js +1925 -0
- package/dist/{chunk-5JMHFAVW.js → chunk-PDCKJCOS.js} +1200 -868
- package/dist/chunk-V4NBQF5C.js +62 -0
- package/dist/chunk-V6Z7GG55.js +16 -0
- package/dist/{chunk-54UGTQBO.js → chunk-WDX6UDL5.js} +1 -1
- package/dist/{chunk-NITZVAXL.js → chunk-WLJ623UZ.js} +24 -0
- package/dist/index.d.ts +289 -118
- package/dist/index.js +52 -20
- package/dist/json-editor/index.js +2 -2
- package/dist/monaco.d.ts +26 -0
- package/dist/monaco.js +144 -10
- package/dist/monacoLanguageDetection-DEyUW-BS.d.ts +18 -0
- package/dist/monacoSuggestions-MDBODZ7F.js +3 -0
- package/dist/recorder/index.d.ts +7 -407
- package/dist/recorder/index.js +3 -3
- package/dist/recorder-C5tAYUE3.d.ts +508 -0
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.js +6 -5
- package/dist/{shell-C-KkTBz7.d.ts → shell-CU4GpGuq.d.ts} +76 -6
- package/dist/styles/index.css +845 -26
- package/dist/teleprompter/index.d.ts +57 -246
- package/dist/teleprompter/index.js +12 -3
- package/dist/useNarrationStage-Bqo18PBw.d.ts +313 -0
- package/package.json +8 -6
- package/dist/chunk-5Q4JN4I5.js +0 -132
- package/dist/chunk-MJJK7YQB.js +0 -949
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { Doc, Theme, MediaProvider } from '@bendyline/squisq/schemas';
|
|
3
3
|
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { i as TeleprompterRecordingDeps, f as NarrationStageHandle, T as TeleprompterController, b as FloatingWindowHandle } from '../useNarrationStage-Bqo18PBw.js';
|
|
5
|
+
export { C as CanvasSink, D as DEFAULT_TELEPROMPTER_PREFS, F as FloatOpenOptions, a as FloatTier, c as FloatingWindowManager, M as MicAnalysisHandle, d as MicAnalysisStatus, N as NarrationRecorderController, e as NarrationRecorderState, g as NarrationTake, P as PrompterTransport, p as TELEPROMPTER_PREF_LIMITS, h as TeleprompterPrefs, U as UseNarrationStageOptions, j as createFloatingWindowManager, k as detectFloatTiers, q as normalizeTeleprompterPrefs, u as useFloatingWindow, l as useMicAnalysis, m as useNarrationRecorder, n as useNarrationStage, o as useTeleprompter, v as vadConfigForSensitivity } from '../useNarrationStage-Bqo18PBw.js';
|
|
6
|
+
import { NarrationTimingJsonV3, NarrationScript, NarrationAlignment } from '@bendyline/squisq/narration';
|
|
7
|
+
import { ReactNode } from 'react';
|
|
6
8
|
|
|
7
|
-
/** Editor plumbing the recording flow needs; omit for prompter-only use. */
|
|
8
|
-
interface TeleprompterRecordingDeps {
|
|
9
|
-
mediaProvider: MediaProvider;
|
|
10
|
-
container: ContentContainer | null;
|
|
11
|
-
markdownSource: string;
|
|
12
|
-
setMarkdownSource: (next: string) => void;
|
|
13
|
-
bumpMediaRevision: () => void;
|
|
14
|
-
}
|
|
15
9
|
interface TeleprompterViewProps {
|
|
16
10
|
doc: Doc | null;
|
|
17
11
|
theme: Theme;
|
|
@@ -30,96 +24,45 @@ interface TeleprompterViewProps {
|
|
|
30
24
|
}
|
|
31
25
|
declare function TeleprompterView(props: TeleprompterViewProps): react_jsx_runtime.JSX.Element;
|
|
32
26
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* getUserMedia → AudioContext → AudioWorklet tap → subscriber callbacks
|
|
37
|
-
* with 1024-sample Float32Array hops on the main thread. The DSP itself
|
|
38
|
-
* lives in core (`@bendyline/squisq/narration`) — this hook only moves
|
|
39
|
-
* samples. Falls back to a ScriptProcessorNode when `audioWorklet` is
|
|
40
|
-
* unavailable (same push model, so pacing still isn't tied to rAF).
|
|
41
|
-
*/
|
|
42
|
-
type MicAnalysisStatus = 'idle' | 'starting' | 'live' | 'error';
|
|
43
|
-
type PcmHopListener = (pcm: Float32Array, audioTimeSec: number) => void;
|
|
44
|
-
interface MicAnalysisHandle {
|
|
45
|
-
status: MicAnalysisStatus;
|
|
46
|
-
error: Error | null;
|
|
47
|
-
/** The live mic stream (feeds the narration recorder too), or null. */
|
|
48
|
-
stream: MediaStream | null;
|
|
49
|
-
/** AudioContext sample rate once live. */
|
|
50
|
-
sampleRate: number | null;
|
|
51
|
-
/** Known audio inputs (labels appear after the first grant). */
|
|
52
|
-
devices: MediaDeviceInfo[];
|
|
27
|
+
interface NarrationStageProps {
|
|
28
|
+
stage: NarrationStageHandle;
|
|
29
|
+
theme: Theme;
|
|
53
30
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* hazard right after an await). Null on failure/supersession.
|
|
31
|
+
* Optional audience-window portal owned by the editor's Presentation mode.
|
|
32
|
+
* The main controller remains authoritative; only this live surface is
|
|
33
|
+
* mirrored into the target.
|
|
58
34
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
cameraMime: string | null;
|
|
89
|
-
cameraExt: string | null;
|
|
90
|
-
durationSec: number;
|
|
91
|
-
cameraOffsetSec: number | undefined;
|
|
92
|
-
trace: NarrationTrace;
|
|
93
|
-
alignment: NarrationAlignment | null;
|
|
94
|
-
script: NarrationScript;
|
|
95
|
-
}
|
|
96
|
-
interface UseNarrationRecorderOptions {
|
|
97
|
-
mic: MicAnalysisHandle;
|
|
98
|
-
getScript: () => NarrationScript | null;
|
|
99
|
-
/** Live prompter position, sampled into the trace while recording. */
|
|
100
|
-
getWordPos: () => number;
|
|
101
|
-
getMicDeviceId: () => string | null;
|
|
102
|
-
/** Fired when capture actually starts (View starts the prompter). */
|
|
103
|
-
onRecordingStart?: () => void;
|
|
104
|
-
onRecordingStop?: () => void;
|
|
105
|
-
}
|
|
106
|
-
interface NarrationRecorderController {
|
|
107
|
-
state: NarrationRecorderState;
|
|
108
|
-
error: Error | null;
|
|
109
|
-
withCamera: boolean;
|
|
110
|
-
setWithCamera: (on: boolean) => void;
|
|
111
|
-
/** Live camera stream for the self-view while recording. */
|
|
112
|
-
cameraStream: MediaStream | null;
|
|
113
|
-
take: NarrationTake | null;
|
|
114
|
-
start: () => Promise<void>;
|
|
115
|
-
stop: () => Promise<void>;
|
|
116
|
-
retake: () => void;
|
|
117
|
-
discard: () => void;
|
|
118
|
-
/** Transition into/out of 'saving'; the View owns the actual I/O. */
|
|
119
|
-
beginSave: () => void;
|
|
120
|
-
finishSave: (ok: boolean, error?: Error) => void;
|
|
35
|
+
presentationTarget?: HTMLElement | null;
|
|
36
|
+
/**
|
|
37
|
+
* Camera corner-overlay on the prompter. Hosts that show the camera stream
|
|
38
|
+
* in their own chrome (the recorder dialog's preview box) pass false.
|
|
39
|
+
*/
|
|
40
|
+
showSelfView?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* The record slot's own "camera" checkbox. Hosts whose chrome already owns
|
|
43
|
+
* the camera toggle (the recorder dialog's Camera source button) pass false.
|
|
44
|
+
*/
|
|
45
|
+
showCameraToggleInRecordSlot?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The whole Record/Stop slot in the control rail. Hosts that surface their
|
|
48
|
+
* own record affordance (the recorder dialog's Start preview → Record flow)
|
|
49
|
+
* pass false; the review bar still renders.
|
|
50
|
+
*/
|
|
51
|
+
showRecordSlot?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The control rail's Start/Pause transport button. Hosts whose record flow
|
|
54
|
+
* drives the prompter (recording start = prompter start) pass false;
|
|
55
|
+
* Restart and Countdown remain.
|
|
56
|
+
*/
|
|
57
|
+
showTransportPlay?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* The review bar's Save/Retake/Discard buttons. Hosts that render those in
|
|
60
|
+
* their own action row (the recorder dialog) pass false; the take info and
|
|
61
|
+
* the prompter-scrubbing audio playback stay.
|
|
62
|
+
*/
|
|
63
|
+
showReviewActions?: boolean;
|
|
121
64
|
}
|
|
122
|
-
declare function
|
|
65
|
+
declare function NarrationStage(props: NarrationStageProps): react_jsx_runtime.JSX.Element;
|
|
123
66
|
|
|
124
67
|
/**
|
|
125
68
|
* Pure save-plan builder for a narration take, plus its executor.
|
|
@@ -147,6 +90,8 @@ interface NarrationSavePlanArgs {
|
|
|
147
90
|
cameraExt: string | null;
|
|
148
91
|
baseWpm: number;
|
|
149
92
|
cameraOffsetSec?: number;
|
|
93
|
+
/** User-chosen filename base for the audio file; default timestamped `narration-…`. */
|
|
94
|
+
audioBasename?: string;
|
|
150
95
|
}
|
|
151
96
|
interface NarrationSavePlan {
|
|
152
97
|
audioRelativeName: string;
|
|
@@ -265,162 +210,28 @@ interface TeleprompterSurfaceProps {
|
|
|
265
210
|
theme: Theme;
|
|
266
211
|
/** Hide block markers / tighten padding for small float windows. */
|
|
267
212
|
compact?: boolean;
|
|
268
|
-
/**
|
|
213
|
+
/** Double-click a word to jump the prompter there. */
|
|
269
214
|
onSeekToken?: (tokenIndex: number) => void;
|
|
215
|
+
/** Move by whole words in response to direct surface input. */
|
|
216
|
+
onNudge?: (deltaTokens: number) => void;
|
|
217
|
+
/** Pause or resume voice/constant-rate automatic advancement. */
|
|
218
|
+
onToggleAutoAdvance?: () => void;
|
|
270
219
|
}
|
|
271
|
-
declare function TeleprompterSurface({ script, wordPos, fontSizePx, mirrored, lineGuide, countdownRemaining, recordingIndicator, theme, compact, onSeekToken, }: TeleprompterSurfaceProps): react_jsx_runtime.JSX.Element;
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Shared types for the Narrate (teleprompter) display mode.
|
|
275
|
-
*/
|
|
276
|
-
interface TeleprompterPrefs {
|
|
277
|
-
/** Prompter type size in px (28–96). */
|
|
278
|
-
fontSizePx: number;
|
|
279
|
-
/** Beam-splitter mirror flip. */
|
|
280
|
-
mirrored: boolean;
|
|
281
|
-
/** Base speaking rate in words per minute (80–260). */
|
|
282
|
-
baseWpm: number;
|
|
283
|
-
/** Voice-adaptive pacing on/off; off = constant-rate manual mode. */
|
|
284
|
-
voiceTracking: boolean;
|
|
285
|
-
/** VAD sensitivity 0–1 (0.5 = engine defaults). */
|
|
286
|
-
vadSensitivity: number;
|
|
287
|
-
/** Countdown before the prompter starts rolling. */
|
|
288
|
-
countdownSec: 0 | 3 | 5 | 10;
|
|
289
|
-
/** Eye-line chevrons + focus band. */
|
|
290
|
-
lineGuide: boolean;
|
|
291
|
-
/** Preferred mic device id (null = system default). */
|
|
292
|
-
micDeviceId: string | null;
|
|
293
|
-
}
|
|
294
|
-
declare const DEFAULT_TELEPROMPTER_PREFS: TeleprompterPrefs;
|
|
295
|
-
type PrompterTransport = 'stopped' | 'countdown' | 'rolling' | 'paused' | 'finished';
|
|
296
|
-
/** Floating-surface tier, best first. */
|
|
297
|
-
type FloatTier = 'document-pip' | 'video-pip' | 'popup' | 'docked';
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* The teleprompter controller — single source of truth, always in the
|
|
301
|
-
* MAIN window (floats are render targets only).
|
|
302
|
-
*
|
|
303
|
-
* Loop-ownership rule: **the audio worklet owns time; the main window
|
|
304
|
-
* owns state; the visible surface owns pixels.** Voice-mode position
|
|
305
|
-
* advances on worklet PCM hops (immune to rAF/timer throttling while
|
|
306
|
-
* the browser is occluded by recording software); manual constant-rate
|
|
307
|
-
* mode uses rAF and is documented as best-effort under occlusion. React
|
|
308
|
-
* state publishes at ~15 Hz; per-hop subscribers (`subscribeTick`)
|
|
309
|
-
* exist for the video-PiP canvas pump.
|
|
310
|
-
*/
|
|
311
|
-
|
|
312
|
-
interface TeleprompterController {
|
|
313
|
-
script: NarrationScript | null;
|
|
314
|
-
transport: PrompterTransport;
|
|
315
|
-
countdownRemaining: number | null;
|
|
316
|
-
/** Fractional word position (published ~15 Hz). */
|
|
317
|
-
wordPos: number;
|
|
318
|
-
/** Smoothed mic level 0–1 for the meter. */
|
|
319
|
-
micLevel: number;
|
|
320
|
-
/** VAD flag for the meter tint. */
|
|
321
|
-
voiceActive: boolean;
|
|
322
|
-
mic: MicAnalysisHandle;
|
|
323
|
-
prefs: TeleprompterPrefs;
|
|
324
|
-
setPrefs: (patch: Partial<TeleprompterPrefs>) => void;
|
|
325
|
-
play: () => void;
|
|
326
|
-
pause: () => void;
|
|
327
|
-
restart: () => void;
|
|
328
|
-
/** Move the prompter by whole tokens and re-anchor voice tracking. */
|
|
329
|
-
nudge: (deltaTokens: number) => void;
|
|
330
|
-
/** Jump to an absolute token index (e.g. click a block marker). */
|
|
331
|
-
seekToToken: (tokenIndex: number) => void;
|
|
332
|
-
/** Per-analysis-tick subscription (video-PiP pump). Not throttled. */
|
|
333
|
-
subscribeTick: (cb: (wordPos: number) => void) => () => void;
|
|
334
|
-
handleKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
|
|
335
|
-
}
|
|
336
|
-
/** Map the 0–1 sensitivity pref onto VAD thresholds (0.5 = engine defaults). */
|
|
337
|
-
declare function vadConfigForSensitivity(sensitivity: number): Partial<VadConfig>;
|
|
338
|
-
declare function useTeleprompter(opts: {
|
|
339
|
-
doc: Doc | null;
|
|
340
|
-
}): TeleprompterController;
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Floating-teleprompter window manager — framework-free.
|
|
344
|
-
*
|
|
345
|
-
* Capability ladder, best first:
|
|
346
|
-
* 1. `document-pip` — Document Picture-in-Picture (Chromium 116+,
|
|
347
|
-
* Firefox 151+): a true always-on-top window hosting live DOM; the
|
|
348
|
-
* React surface portals into it.
|
|
349
|
-
* 2. `video-pip` — canvas → `captureStream(0)` → `<video>` →
|
|
350
|
-
* `requestPictureInPicture()` (Safari's only always-on-top path;
|
|
351
|
-
* `webkitSetPresentationMode` fallback). Read-only: the main
|
|
352
|
-
* window draws frames and calls `requestFrame()` on analysis
|
|
353
|
-
* ticks — never rAF, which throttles under occlusion.
|
|
354
|
-
* 3. `popup` — `window.open` (positionable, not always-on-top).
|
|
355
|
-
* 4. `docked` — no float.
|
|
356
|
-
*
|
|
357
|
-
* Every tier is feature-detected at open time and falls through to the
|
|
358
|
-
* next on ANY failure. All interactive state stays in the main window;
|
|
359
|
-
* floats are render targets only.
|
|
360
|
-
*/
|
|
361
|
-
|
|
362
|
-
interface FloatOpenOptions {
|
|
363
|
-
width: number;
|
|
364
|
-
height: number;
|
|
365
|
-
/** Try this tier first; the ladder continues below it on failure. */
|
|
366
|
-
preferredTier?: FloatTier;
|
|
367
|
-
title: string;
|
|
368
|
-
}
|
|
369
|
-
interface CanvasSink {
|
|
370
|
-
canvas: HTMLCanvasElement;
|
|
371
|
-
width: number;
|
|
372
|
-
height: number;
|
|
373
|
-
/** Push the freshly drawn canvas frame into the PiP video. */
|
|
374
|
-
requestFrame: () => void;
|
|
375
|
-
}
|
|
376
|
-
type FloatEvent = 'closed' | 'tierchange';
|
|
377
|
-
interface FloatingWindowManager {
|
|
378
|
-
readonly tier: FloatTier;
|
|
379
|
-
readonly isOpen: boolean;
|
|
380
|
-
/** Resolves with the tier that actually opened ('docked' if none could). */
|
|
381
|
-
open(opts: FloatOpenOptions): Promise<FloatTier>;
|
|
382
|
-
/** Idempotent; restores docked and emits 'closed'. */
|
|
383
|
-
close(): void;
|
|
384
|
-
/** Portal container for 'document-pip' | 'popup'; null otherwise. */
|
|
385
|
-
getPortalTarget(): HTMLElement | null;
|
|
386
|
-
/** Canvas sink for 'video-pip'; null otherwise. */
|
|
387
|
-
getCanvasSink(): CanvasSink | null;
|
|
388
|
-
on(event: FloatEvent, cb: (tier: FloatTier) => void): () => void;
|
|
389
|
-
/** Tear everything down (unmount); like close() but silent-safe. */
|
|
390
|
-
dispose(): void;
|
|
391
|
-
}
|
|
392
|
-
/** Feature-detect the available float tiers, best first. */
|
|
393
|
-
declare function detectFloatTiers(): FloatTier[];
|
|
394
|
-
declare function createFloatingWindowManager(deps: {
|
|
395
|
-
styleCss: string;
|
|
396
|
-
}): FloatingWindowManager;
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* React binding over {@link createFloatingWindowManager}: exposes the
|
|
400
|
-
* current tier + portal target as state and guarantees the float closes
|
|
401
|
-
* when the owning view unmounts (mode switch, Use-tab exit, shell
|
|
402
|
-
* teardown).
|
|
403
|
-
*/
|
|
404
|
-
|
|
405
|
-
interface FloatingWindowHandle {
|
|
406
|
-
tier: FloatTier;
|
|
407
|
-
isOpen: boolean;
|
|
408
|
-
/** Non-docked tiers this browser supports, best first. */
|
|
409
|
-
supportedTiers: FloatTier[];
|
|
410
|
-
portalTarget: HTMLElement | null;
|
|
411
|
-
canvasSink: CanvasSink | null;
|
|
412
|
-
open: (preferredTier?: FloatTier) => Promise<void>;
|
|
413
|
-
close: () => void;
|
|
414
|
-
}
|
|
415
|
-
declare function useFloatingWindow(styleCss: string): FloatingWindowHandle;
|
|
220
|
+
declare function TeleprompterSurface({ script, wordPos, fontSizePx, mirrored, lineGuide, countdownRemaining, recordingIndicator, theme, compact, onSeekToken, onNudge, onToggleAutoAdvance, }: TeleprompterSurfaceProps): react_jsx_runtime.JSX.Element;
|
|
416
221
|
|
|
417
222
|
interface TeleprompterControlsProps {
|
|
418
223
|
controller: TeleprompterController;
|
|
419
224
|
float: FloatingWindowHandle;
|
|
420
225
|
/** Phase B mounts the narration Record button here. */
|
|
421
226
|
recordSlot?: ReactNode;
|
|
227
|
+
/**
|
|
228
|
+
* Show the Start/Pause transport button (default true). Hosts whose own
|
|
229
|
+
* chrome drives playback — the Record media dialog starts the prompter
|
|
230
|
+
* through its Record button — pass false; Restart and Countdown stay.
|
|
231
|
+
*/
|
|
232
|
+
showPlayPause?: boolean;
|
|
422
233
|
}
|
|
423
|
-
declare function TeleprompterControls({ controller, float, recordSlot }: TeleprompterControlsProps): react_jsx_runtime.JSX.Element;
|
|
234
|
+
declare function TeleprompterControls({ controller, float, recordSlot, showPlayPause, }: TeleprompterControlsProps): react_jsx_runtime.JSX.Element;
|
|
424
235
|
|
|
425
236
|
/**
|
|
426
237
|
* The PCM tap AudioWorklet, shipped as an inline source string.
|
|
@@ -494,4 +305,4 @@ declare function prompterVarsFromTheme(theme: Theme): Record<string, string>;
|
|
|
494
305
|
declare function ensureTeleprompterStyles(doc: Document): void;
|
|
495
306
|
declare const TELEPROMPTER_CSS = "\n.squisq-teleprompter-root {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n background: var(--squisq-bg, #f5f5f5);\n outline: none;\n}\n.squisq-teleprompter-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n display: flex;\n}\n\n.squisq-teleprompter-surface {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n background: var(--squisq-prompter-bg, #101014);\n color: var(--squisq-prompter-text, #f5f5f2);\n font-family: var(--squisq-prompter-font, system-ui, sans-serif);\n user-select: none;\n}\n.squisq-teleprompter-flip {\n position: absolute;\n inset: 0;\n}\n.squisq-teleprompter-surface--mirrored .squisq-teleprompter-flip {\n transform: scaleX(-1);\n}\n.squisq-teleprompter-scroll {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n will-change: transform;\n padding: 40vh 8% 60vh;\n box-sizing: border-box;\n}\n.squisq-teleprompter-line-guide {\n position: absolute;\n left: 0;\n right: 0;\n pointer-events: none;\n z-index: 2;\n}\n.squisq-teleprompter-line-guide::before,\n.squisq-teleprompter-line-guide::after {\n content: '';\n position: absolute;\n top: 50%;\n border: 9px solid transparent;\n transform: translateY(-50%);\n}\n.squisq-teleprompter-line-guide::before {\n left: 6px;\n border-left-color: var(--squisq-prompter-accent, #e8b64c);\n}\n.squisq-teleprompter-line-guide::after {\n right: 6px;\n border-right-color: var(--squisq-prompter-accent, #e8b64c);\n}\n.squisq-teleprompter-guide-band {\n position: absolute;\n left: 0;\n right: 0;\n background: color-mix(in srgb, var(--squisq-prompter-accent, #e8b64c) 9%, transparent);\n pointer-events: none;\n z-index: 1;\n}\n\n.squisq-teleprompter-block-marker {\n display: block;\n margin: 1.1em 0 0.35em;\n font-size: 0.38em;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--squisq-prompter-muted, #9a9aa0);\n border-top: 1px solid color-mix(in srgb, var(--squisq-prompter-muted, #9a9aa0) 35%, transparent);\n padding-top: 0.6em;\n}\n.squisq-teleprompter-para {\n margin: 0 0 0.55em;\n line-height: 1.4;\n font-weight: 500;\n}\n.squisq-teleprompter-word {\n opacity: 0.45;\n transition: color 0.1s linear, opacity 0.1s linear;\n}\n.squisq-teleprompter-word--read {\n opacity: 0.9;\n}\n.squisq-teleprompter-word--active {\n opacity: 1;\n font-weight: 800;\n color: var(--squisq-prompter-accent, #e8b64c);\n}\n\n.squisq-teleprompter-countdown {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 3;\n background: color-mix(in srgb, var(--squisq-prompter-bg, #101014) 72%, transparent);\n}\n.squisq-teleprompter-countdown-digit {\n font-size: 18vmin;\n font-weight: 800;\n color: var(--squisq-prompter-accent, #e8b64c);\n animation: squisq-prompter-pulse 1s ease-in-out infinite;\n}\n.squisq-teleprompter-recdot {\n position: absolute;\n top: 14px;\n right: 16px;\n z-index: 4;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: #e5484d;\n box-shadow: 0 0 0 3px color-mix(in srgb, #e5484d 30%, transparent);\n animation: squisq-prompter-pulse 1.4s ease-in-out infinite;\n}\n/* Counter-flip overlays so they stay readable in mirror mode. */\n.squisq-teleprompter-surface--mirrored .squisq-teleprompter-countdown,\n.squisq-teleprompter-surface--mirrored .squisq-teleprompter-recdot {\n transform: scaleX(-1);\n}\n\n.squisq-teleprompter-selfview {\n position: absolute;\n right: 14px;\n bottom: 14px;\n width: 160px;\n border-radius: 8px;\n border: 2px solid color-mix(in srgb, #e5484d 60%, transparent);\n z-index: 5;\n background: #000;\n}\n\n.squisq-teleprompter-review {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n padding: 8px 12px;\n border-top: 1px solid var(--squisq-border, #e5e7eb);\n background: var(--squisq-surface, var(--squisq-bg, #fff));\n color: var(--squisq-text, #111827);\n font-size: 12.5px;\n}\n.squisq-teleprompter-review audio {\n height: 28px;\n max-width: 260px;\n}\n.squisq-teleprompter-review button {\n font: inherit;\n color: inherit;\n background: var(--squisq-input-bg, #fff);\n border: 1px solid var(--squisq-border, #d1d5db);\n border-radius: 6px;\n padding: 4px 10px;\n cursor: pointer;\n}\n\n.squisq-teleprompter-float-note {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n color: var(--squisq-text-muted, #6b7280);\n font-size: 14px;\n}\n\n.squisq-teleprompter-controls {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n padding: 8px 12px;\n border-top: 1px solid var(--squisq-border, #e5e7eb);\n background: var(--squisq-surface, var(--squisq-bg, #fff));\n color: var(--squisq-text, #111827);\n font-size: 12.5px;\n}\n.squisq-teleprompter-controls .squisq-teleprompter-group {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n white-space: nowrap;\n}\n.squisq-teleprompter-controls button {\n font: inherit;\n color: inherit;\n background: var(--squisq-input-bg, #fff);\n border: 1px solid var(--squisq-border, #d1d5db);\n border-radius: 6px;\n padding: 4px 10px;\n cursor: pointer;\n}\n.squisq-teleprompter-controls button:hover {\n background: var(--squisq-surface-hover, #f3f4f6);\n}\n.squisq-teleprompter-controls button[aria-pressed='true'] {\n background: var(--squisq-text, #111827);\n color: var(--squisq-bg, #fff);\n border-color: var(--squisq-text, #111827);\n}\n.squisq-teleprompter-controls select,\n.squisq-teleprompter-controls input[type='range'] {\n font: inherit;\n color: inherit;\n background: var(--squisq-input-bg, #fff);\n border: 1px solid var(--squisq-border, #d1d5db);\n border-radius: 6px;\n max-width: 170px;\n}\n.squisq-teleprompter-controls input[type='range'] {\n border: none;\n background: transparent;\n width: 110px;\n}\n.squisq-teleprompter-meter {\n position: relative;\n width: 64px;\n height: 8px;\n border-radius: 4px;\n overflow: hidden;\n background: var(--squisq-border, #e5e7eb);\n}\n.squisq-teleprompter-meter-fill {\n position: absolute;\n inset: 0 auto 0 0;\n background: #9ca3af;\n transition: width 0.08s linear;\n}\n.squisq-teleprompter-meter--voice .squisq-teleprompter-meter-fill {\n background: #30a46c;\n}\n\n@keyframes squisq-prompter-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.45; }\n}\n@media (prefers-reduced-motion: reduce) {\n .squisq-teleprompter-countdown-digit,\n .squisq-teleprompter-recdot {\n animation: none;\n }\n .squisq-teleprompter-word {\n transition: none;\n }\n}\n";
|
|
496
307
|
|
|
497
|
-
export {
|
|
308
|
+
export { EYE_LINE_FRACTION, FloatingWindowHandle, type NarrationSavePlan, type NarrationSaveResult, NarrationStage, NarrationStageHandle, type NarrationStageProps, PCM_WORKLET_NAME, PCM_WORKLET_SOURCE, TELEPROMPTER_CSS, TeleprompterController, TeleprompterControls, type TeleprompterControlsProps, TeleprompterRecordingDeps, TeleprompterSurface, type TeleprompterSurfaceProps, TeleprompterView, type TeleprompterViewProps, type TokenLineMap, buildNarrationSavePlan, cameraVideoLine, ensureTeleprompterStyles, executeNarrationSave, insertNarrationPreamble, measureTokenLines, narrationAnnotationLine, prompterVarsFromTheme, registerPcmWorklet, stepScroll, targetOffsetFor };
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TeleprompterView
|
|
3
|
+
} from "../chunk-V6Z7GG55.js";
|
|
1
4
|
import {
|
|
2
5
|
DEFAULT_TELEPROMPTER_PREFS,
|
|
3
6
|
EYE_LINE_FRACTION,
|
|
7
|
+
NarrationStage,
|
|
4
8
|
PCM_WORKLET_NAME,
|
|
5
9
|
PCM_WORKLET_SOURCE,
|
|
6
10
|
TELEPROMPTER_CSS,
|
|
11
|
+
TELEPROMPTER_PREF_LIMITS,
|
|
7
12
|
TeleprompterControls,
|
|
8
13
|
TeleprompterSurface,
|
|
9
|
-
TeleprompterView,
|
|
10
14
|
buildNarrationSavePlan,
|
|
11
15
|
cameraVideoLine,
|
|
12
16
|
createFloatingWindowManager,
|
|
@@ -16,6 +20,7 @@ import {
|
|
|
16
20
|
insertNarrationPreamble,
|
|
17
21
|
measureTokenLines,
|
|
18
22
|
narrationAnnotationLine,
|
|
23
|
+
normalizeTeleprompterPrefs,
|
|
19
24
|
prompterVarsFromTheme,
|
|
20
25
|
registerPcmWorklet,
|
|
21
26
|
stepScroll,
|
|
@@ -23,16 +28,18 @@ import {
|
|
|
23
28
|
useFloatingWindow,
|
|
24
29
|
useMicAnalysis,
|
|
25
30
|
useNarrationRecorder,
|
|
31
|
+
useNarrationStage,
|
|
26
32
|
useTeleprompter,
|
|
27
33
|
vadConfigForSensitivity
|
|
28
|
-
} from "../chunk-
|
|
29
|
-
import "../chunk-5Q4JN4I5.js";
|
|
34
|
+
} from "../chunk-PDCKJCOS.js";
|
|
30
35
|
export {
|
|
31
36
|
DEFAULT_TELEPROMPTER_PREFS,
|
|
32
37
|
EYE_LINE_FRACTION,
|
|
38
|
+
NarrationStage,
|
|
33
39
|
PCM_WORKLET_NAME,
|
|
34
40
|
PCM_WORKLET_SOURCE,
|
|
35
41
|
TELEPROMPTER_CSS,
|
|
42
|
+
TELEPROMPTER_PREF_LIMITS,
|
|
36
43
|
TeleprompterControls,
|
|
37
44
|
TeleprompterSurface,
|
|
38
45
|
TeleprompterView,
|
|
@@ -45,6 +52,7 @@ export {
|
|
|
45
52
|
insertNarrationPreamble,
|
|
46
53
|
measureTokenLines,
|
|
47
54
|
narrationAnnotationLine,
|
|
55
|
+
normalizeTeleprompterPrefs,
|
|
48
56
|
prompterVarsFromTheme,
|
|
49
57
|
registerPcmWorklet,
|
|
50
58
|
stepScroll,
|
|
@@ -52,6 +60,7 @@ export {
|
|
|
52
60
|
useFloatingWindow,
|
|
53
61
|
useMicAnalysis,
|
|
54
62
|
useNarrationRecorder,
|
|
63
|
+
useNarrationStage,
|
|
55
64
|
useTeleprompter,
|
|
56
65
|
vadConfigForSensitivity
|
|
57
66
|
};
|