@bendyline/squisq-editor-react 2.11.16 → 2.11.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-ZDWZRVAY.js → chunk-2XXBDECJ.js} +1 -1
- package/dist/{chunk-4D7QMRTZ.js → chunk-C6QVA6TO.js} +450 -429
- package/dist/{chunk-EN5BYZOE.js → chunk-DPAMJV6A.js} +3 -2
- package/dist/{chunk-27WOOJXR.js → chunk-EJKGXWNK.js} +1 -1
- package/dist/{chunk-DNB32SU2.js → chunk-HTO5MTTJ.js} +1 -1
- package/dist/{chunk-ENDRPV6T.js → chunk-QZWFSSDE.js} +1 -1
- package/dist/{chunk-WDQFWD7Z.js → chunk-UBFNLWCN.js} +2 -2
- package/dist/{chunk-5TYCTE33.js → chunk-US5DALTZ.js} +871 -692
- package/dist/{chunk-34FRFDQ6.js → chunk-XZVMKR5Q.js} +44 -9
- package/dist/index.d.ts +9 -17
- package/dist/index.js +10 -10
- package/dist/json-editor/index.js +3 -3
- package/dist/recorder/index.d.ts +2 -2
- package/dist/recorder/index.js +3 -3
- package/dist/{recorder-C6ArYQBa.d.ts → recorder-CRsw0eC7.d.ts} +6 -5
- package/dist/review/index.js +2 -2
- package/dist/shell/index.js +7 -7
- package/dist/styles/index.css +37 -29
- package/dist/teleprompter/index.d.ts +2 -2
- package/dist/teleprompter/index.js +2 -2
- package/dist/{useNarrationStage-DopDr_P5.d.ts → useNarrationStage-vKtk6H-V.d.ts} +7 -1
- package/package.json +6 -6
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
timingPathFor,
|
|
20
20
|
useNarrationStage,
|
|
21
21
|
useStreamPreview
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-XZVMKR5Q.js";
|
|
23
23
|
|
|
24
24
|
// src/recorder/sources/screenRegion.ts
|
|
25
25
|
function validateScreenCaptureRegion(region, width, height) {
|
|
@@ -1818,8 +1818,9 @@ function isExpandedPanel(mode) {
|
|
|
1818
1818
|
return mode !== "none";
|
|
1819
1819
|
}
|
|
1820
1820
|
function panelModeAfterToggle(current, target, checked) {
|
|
1821
|
-
|
|
1822
|
-
|
|
1821
|
+
const narration = target === "narration" ? checked : current === "narration" || current === "both";
|
|
1822
|
+
const slides = target === "slides" ? checked : current === "slides" || current === "both";
|
|
1823
|
+
return narration ? slides ? "both" : "narration" : slides ? "slides" : "none";
|
|
1823
1824
|
}
|
|
1824
1825
|
function clampSlideIndex(index, count) {
|
|
1825
1826
|
if (count <= 0) return 0;
|
|
@@ -2695,8 +2696,9 @@ function RecorderModal({
|
|
|
2695
2696
|
const [cameraPlaybackUrl, setCameraPlaybackUrl] = useState3(null);
|
|
2696
2697
|
const [playbackPositionMs, setPlaybackPositionMs] = useState3(0);
|
|
2697
2698
|
const [panelMode, setPanelMode] = useState3("none");
|
|
2698
|
-
const narrationOn = panelMode === "narration";
|
|
2699
|
-
const slidesOn = panelMode === "slides";
|
|
2699
|
+
const narrationOn = panelMode === "narration" || panelMode === "both";
|
|
2700
|
+
const slidesOn = panelMode === "slides" || panelMode === "both";
|
|
2701
|
+
const narrationRecording = narrationOn && Boolean(narration?.recording);
|
|
2700
2702
|
const expanded = isExpandedPanel(panelMode);
|
|
2701
2703
|
const [narrationRequesting, setNarrationRequesting] = useState3(false);
|
|
2702
2704
|
const [narrationPreview, setNarrationPreview] = useState3(null);
|
|
@@ -2757,13 +2759,16 @@ function RecorderModal({
|
|
|
2757
2759
|
systemAudio: canIncludeSystemAudio ? includeSystemAudio : false
|
|
2758
2760
|
});
|
|
2759
2761
|
const filenameSeed = recordingFilenameSeed(source, recorder.stream, micOn || includeSystemAudio);
|
|
2760
|
-
const narrationAvailable = Boolean(narration
|
|
2762
|
+
const narrationAvailable = Boolean(narration?.doc);
|
|
2761
2763
|
const basenameRef = useRef2(basename);
|
|
2762
2764
|
basenameRef.current = basename;
|
|
2763
2765
|
const stage = useNarrationStage({
|
|
2764
2766
|
doc: narration?.doc ?? null,
|
|
2765
2767
|
maxRecordingBytes,
|
|
2766
2768
|
recording: narration?.recording ?? null,
|
|
2769
|
+
// A prompter-only stage borrows the take's audio. It never requests or
|
|
2770
|
+
// stops capture tracks; the recorder remains their sole owner.
|
|
2771
|
+
analysisStream: narration?.recording ? void 0 : narrationOn && recorder.state !== "stopped" ? isDual ? recorder.camera?.stream ?? null : recorder.stream : null,
|
|
2767
2772
|
getAudioBasename: () => basenameRef.current.trim() || void 0,
|
|
2768
2773
|
micConstraints: audioConstraints,
|
|
2769
2774
|
cameraConstraints,
|
|
@@ -2818,35 +2823,41 @@ function RecorderModal({
|
|
|
2818
2823
|
useEffect4(() => {
|
|
2819
2824
|
setAdvanceLog(EMPTY_ADVANCE_LOG);
|
|
2820
2825
|
setSlideIndex(0);
|
|
2821
|
-
}, [
|
|
2826
|
+
}, [slidesOn, slideDeckKey]);
|
|
2827
|
+
useEffect4(() => {
|
|
2828
|
+
if (!narrationOn || narrationRecording) return;
|
|
2829
|
+
const controller = stageRef.current.controller;
|
|
2830
|
+
if (recorder.state === "recording") controller.play();
|
|
2831
|
+
else controller.pause();
|
|
2832
|
+
}, [narrationOn, narrationRecording, recorder.state]);
|
|
2822
2833
|
const handleDeviceSettingsChange = useCallback4(
|
|
2823
2834
|
(next) => {
|
|
2824
2835
|
setDeviceSettings(next);
|
|
2825
|
-
if (
|
|
2836
|
+
if (narrationRecording) {
|
|
2826
2837
|
stageRef.current.controller.setPrefs({
|
|
2827
2838
|
micDeviceId: next.audio.deviceId || null
|
|
2828
2839
|
});
|
|
2829
2840
|
}
|
|
2830
2841
|
},
|
|
2831
|
-
[
|
|
2842
|
+
[narrationRecording]
|
|
2832
2843
|
);
|
|
2833
2844
|
const narrationMicDeviceId = stage.controller.prefs.micDeviceId ?? "";
|
|
2834
2845
|
useEffect4(() => {
|
|
2835
|
-
if (!
|
|
2846
|
+
if (!narrationRecording) return;
|
|
2836
2847
|
setDeviceSettings(
|
|
2837
2848
|
(current) => current.audio.deviceId === narrationMicDeviceId ? current : {
|
|
2838
2849
|
...current,
|
|
2839
2850
|
audio: { ...current.audio, deviceId: narrationMicDeviceId }
|
|
2840
2851
|
}
|
|
2841
2852
|
);
|
|
2842
|
-
}, [narrationMicDeviceId,
|
|
2853
|
+
}, [narrationMicDeviceId, narrationRecording]);
|
|
2843
2854
|
const prevNarrationOnRef = useRef2(narrationOn);
|
|
2844
2855
|
useEffect4(() => {
|
|
2845
2856
|
const was = prevNarrationOnRef.current;
|
|
2846
2857
|
prevNarrationOnRef.current = narrationOn;
|
|
2847
2858
|
if (was === narrationOn) return;
|
|
2848
2859
|
if (narrationOn) {
|
|
2849
|
-
recorder.cancel();
|
|
2860
|
+
if (narrationRecording) recorder.cancel();
|
|
2850
2861
|
} else {
|
|
2851
2862
|
const s = stageRef.current;
|
|
2852
2863
|
s.controller.pause();
|
|
@@ -2855,7 +2866,7 @@ function RecorderModal({
|
|
|
2855
2866
|
}
|
|
2856
2867
|
if (s.float.isOpen) s.float.close();
|
|
2857
2868
|
}
|
|
2858
|
-
}, [narrationOn, recorder]);
|
|
2869
|
+
}, [narrationOn, narrationRecording, recorder]);
|
|
2859
2870
|
useEffect4(() => {
|
|
2860
2871
|
if (!narrationOn) return;
|
|
2861
2872
|
const onKey = (event) => {
|
|
@@ -2867,7 +2878,7 @@ function RecorderModal({
|
|
|
2867
2878
|
return () => document.removeEventListener("keydown", onKey, true);
|
|
2868
2879
|
}, [narrationOn]);
|
|
2869
2880
|
const narrationMicLive = stage.controller.mic.status === "live";
|
|
2870
|
-
const narrationPreviewWanted =
|
|
2881
|
+
const narrationPreviewWanted = narrationRecording && stage.recorder.withCamera && narrationMicLive && stage.recorder.cameraStream === null && stage.recorder.state !== "processing" && stage.recorder.state !== "review" && stage.recorder.state !== "saving";
|
|
2871
2882
|
const narrationPreviewRef = useRef2(null);
|
|
2872
2883
|
useEffect4(() => {
|
|
2873
2884
|
const existing = narrationPreviewRef.current;
|
|
@@ -2916,20 +2927,20 @@ function RecorderModal({
|
|
|
2916
2927
|
const handleNarrationRecord = useCallback4(() => {
|
|
2917
2928
|
void stageRef.current.recorder.start();
|
|
2918
2929
|
}, []);
|
|
2919
|
-
const narrationCameraStream =
|
|
2920
|
-
const activePrimaryStream =
|
|
2921
|
-
const activeCameraStream =
|
|
2930
|
+
const narrationCameraStream = narrationRecording ? stage.recorder.cameraStream ?? narrationPreview : null;
|
|
2931
|
+
const activePrimaryStream = narrationRecording ? stage.controller.mic.stream : recorder.stream;
|
|
2932
|
+
const activeCameraStream = narrationRecording ? narrationCameraStream : recorder.camera?.stream ?? null;
|
|
2922
2933
|
const { devices: mediaDevices, refresh: refreshMediaDevices } = useMediaDevices();
|
|
2923
2934
|
useEffect4(() => {
|
|
2924
2935
|
if (activePrimaryStream || activeCameraStream) refreshMediaDevices();
|
|
2925
2936
|
}, [activeCameraStream, activePrimaryStream, refreshMediaDevices]);
|
|
2926
2937
|
useStreamPreview(
|
|
2927
2938
|
previewRef,
|
|
2928
|
-
|
|
2939
|
+
narrationRecording ? narrationCameraStream : recorder.state === "stopped" ? null : recorder.stream
|
|
2929
2940
|
);
|
|
2930
2941
|
useStreamPreview(
|
|
2931
2942
|
cameraPreviewRef,
|
|
2932
|
-
!
|
|
2943
|
+
!narrationRecording && isDual && recorder.state !== "stopped" ? recorder.camera?.stream ?? null : null
|
|
2933
2944
|
);
|
|
2934
2945
|
useEffect4(() => {
|
|
2935
2946
|
setPlaybackPositionMs(0);
|
|
@@ -2967,7 +2978,7 @@ function RecorderModal({
|
|
|
2967
2978
|
}
|
|
2968
2979
|
}, [captureKey, recorder]);
|
|
2969
2980
|
const handleClose = useCallback4(() => {
|
|
2970
|
-
if (!
|
|
2981
|
+
if (!narrationRecording) {
|
|
2971
2982
|
if (isSaving || recorder.state === "stopping" || recorder.state === "requesting") return;
|
|
2972
2983
|
if ((recorder.blob || recorder.camera?.blob || recorder.state === "recording") && !window.confirm(
|
|
2973
2984
|
"Discard this recording? Download or save it before closing to keep a copy."
|
|
@@ -2975,7 +2986,7 @@ function RecorderModal({
|
|
|
2975
2986
|
return;
|
|
2976
2987
|
}
|
|
2977
2988
|
const s = stageRef.current;
|
|
2978
|
-
if (closeNeedsConfirm(
|
|
2989
|
+
if (closeNeedsConfirm(narrationRecording, s.recorder.state, s.recorder.take !== null)) {
|
|
2979
2990
|
if (!window.confirm("Discard the current narration take?")) return;
|
|
2980
2991
|
s.handleDiscard();
|
|
2981
2992
|
}
|
|
@@ -2987,7 +2998,7 @@ function RecorderModal({
|
|
|
2987
2998
|
}
|
|
2988
2999
|
recorder.cancel();
|
|
2989
3000
|
onClose();
|
|
2990
|
-
}, [narrationOn, recorder, onClose, isSaving]);
|
|
3001
|
+
}, [narrationOn, narrationRecording, recorder, onClose, isSaving]);
|
|
2991
3002
|
useModalDialog({
|
|
2992
3003
|
rootRef: overlayRef,
|
|
2993
3004
|
dialogRef,
|
|
@@ -3197,7 +3208,8 @@ function RecorderModal({
|
|
|
3197
3208
|
dualSaveProgressRef.current = {};
|
|
3198
3209
|
setAdvanceLog(EMPTY_ADVANCE_LOG);
|
|
3199
3210
|
recorder.reset();
|
|
3200
|
-
|
|
3211
|
+
if (narrationOn) stageRef.current.controller.restart();
|
|
3212
|
+
}, [narrationOn, recorder]);
|
|
3201
3213
|
const handlePlaybackTimeUpdate = useCallback4(
|
|
3202
3214
|
(media) => {
|
|
3203
3215
|
const currentMs = Number.isFinite(media.currentTime) ? media.currentTime * 1e3 : 0;
|
|
@@ -3234,7 +3246,7 @@ function RecorderModal({
|
|
|
3234
3246
|
);
|
|
3235
3247
|
const timingDownloadFilename = `${downloadFilename}.timing.json`;
|
|
3236
3248
|
useEffect4(() => {
|
|
3237
|
-
if (
|
|
3249
|
+
if (narrationRecording || !canSave) {
|
|
3238
3250
|
setTimingDownloadUrl(null);
|
|
3239
3251
|
return;
|
|
3240
3252
|
}
|
|
@@ -3250,7 +3262,7 @@ function RecorderModal({
|
|
|
3250
3262
|
setTimingDownloadUrl(url);
|
|
3251
3263
|
return () => URL.revokeObjectURL(url);
|
|
3252
3264
|
}, [
|
|
3253
|
-
|
|
3265
|
+
narrationRecording,
|
|
3254
3266
|
canSave,
|
|
3255
3267
|
recorder.durationMs,
|
|
3256
3268
|
slidesOn,
|
|
@@ -3293,9 +3305,9 @@ function RecorderModal({
|
|
|
3293
3305
|
recorder.blob !== null || recorder.camera?.blob != null,
|
|
3294
3306
|
stage.recorder.state
|
|
3295
3307
|
);
|
|
3296
|
-
const deviceSettingsLocked =
|
|
3297
|
-
const microphoneEnabled =
|
|
3298
|
-
const cameraEnabled =
|
|
3308
|
+
const deviceSettingsLocked = narrationRecording ? !narrationRecorderIdle : togglesLocked;
|
|
3309
|
+
const microphoneEnabled = narrationRecording ? true : micOn;
|
|
3310
|
+
const cameraEnabled = narrationRecording ? stage.recorder.withCamera : cameraOn;
|
|
3299
3311
|
const narrationToggleFor = (key) => {
|
|
3300
3312
|
switch (key) {
|
|
3301
3313
|
case "mic":
|
|
@@ -3359,442 +3371,451 @@ function RecorderModal({
|
|
|
3359
3371
|
children: [
|
|
3360
3372
|
/* @__PURE__ */ jsx6("h2", { id: headingId, style: titleStyle, children: title }),
|
|
3361
3373
|
/* @__PURE__ */ jsxs5("div", { style: expanded ? bodyRowStyle : void 0, children: [
|
|
3362
|
-
/* @__PURE__ */ jsxs5(
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
}
|
|
3395
|
-
),
|
|
3396
|
-
"Show narration mode"
|
|
3397
|
-
] }),
|
|
3398
|
-
slidesAvailable && /* @__PURE__ */ jsxs5("label", { style: checkboxRowStyle, children: [
|
|
3399
|
-
/* @__PURE__ */ jsx6(
|
|
3400
|
-
"input",
|
|
3401
|
-
{
|
|
3402
|
-
type: "checkbox",
|
|
3403
|
-
style: { accentColor: "var(--squisq-recorder-accent)" },
|
|
3404
|
-
checked: slidesOn,
|
|
3405
|
-
onChange: (e) => setPanelMode(panelModeAfterToggle(panelMode, "slides", e.target.checked)),
|
|
3406
|
-
disabled: narrationToggleDisabled,
|
|
3407
|
-
title: narrationToggleDisabled ? "Save or discard this recording before switching modes" : void 0
|
|
3408
|
-
}
|
|
3409
|
-
),
|
|
3410
|
-
"Show slides mode"
|
|
3411
|
-
] }),
|
|
3412
|
-
/* @__PURE__ */ jsx6(
|
|
3413
|
-
RecorderDeviceQuickPicks,
|
|
3414
|
-
{
|
|
3415
|
-
devices: mediaDevices,
|
|
3416
|
-
microphoneEnabled,
|
|
3417
|
-
cameraEnabled,
|
|
3418
|
-
audioDeviceId: deviceSettings.audio.deviceId,
|
|
3419
|
-
cameraDeviceId: deviceSettings.camera.deviceId,
|
|
3420
|
-
onAudioDeviceChange: (deviceId) => handleDeviceSettingsChange({
|
|
3421
|
-
...deviceSettings,
|
|
3422
|
-
audio: { ...deviceSettings.audio, deviceId }
|
|
3423
|
-
}),
|
|
3424
|
-
onCameraDeviceChange: (deviceId) => handleDeviceSettingsChange({
|
|
3425
|
-
...deviceSettings,
|
|
3426
|
-
camera: { ...deviceSettings.camera, deviceId }
|
|
3427
|
-
}),
|
|
3428
|
-
disabled: deviceSettingsLocked
|
|
3429
|
-
}
|
|
3430
|
-
),
|
|
3431
|
-
!narrationOn && screenOn && /* @__PURE__ */ jsx6(
|
|
3432
|
-
RecorderScreenSettings,
|
|
3433
|
-
{
|
|
3434
|
-
value: deviceSettings.screen,
|
|
3435
|
-
onChange: (screen) => handleDeviceSettingsChange({ ...deviceSettings, screen }),
|
|
3436
|
-
disabled: deviceSettingsLocked,
|
|
3437
|
-
hasPreview: recorder.state === "ready",
|
|
3438
|
-
onChoose: () => {
|
|
3439
|
-
recorder.cancel();
|
|
3440
|
-
void handleRequest();
|
|
3441
|
-
}
|
|
3442
|
-
}
|
|
3443
|
-
),
|
|
3444
|
-
/* @__PURE__ */ jsx6(
|
|
3445
|
-
RecorderDeviceSettingsPanel,
|
|
3446
|
-
{
|
|
3447
|
-
value: deviceSettings,
|
|
3448
|
-
onChange: handleDeviceSettingsChange,
|
|
3449
|
-
disabled: deviceSettingsLocked,
|
|
3450
|
-
microphoneEnabled,
|
|
3451
|
-
cameraEnabled,
|
|
3452
|
-
screenEnabled: narrationOn ? false : screenOn,
|
|
3453
|
-
systemAudioEnabled: !narrationOn && includeSystemAudio,
|
|
3454
|
-
separateAudioRecorder: narrationOn,
|
|
3455
|
-
primaryStream: activePrimaryStream,
|
|
3456
|
-
cameraStream: activeCameraStream
|
|
3457
|
-
}
|
|
3458
|
-
),
|
|
3459
|
-
!narrationOn && recorder.error && /* @__PURE__ */ jsx6("div", { style: errorStyle, children: recorder.error.message }),
|
|
3460
|
-
!narrationOn && saveError && /* @__PURE__ */ jsxs5("div", { role: "alert", style: errorStyle, children: [
|
|
3461
|
-
saveError,
|
|
3462
|
-
/* @__PURE__ */ jsx6("p", { style: { marginBottom: 0 }, children: "Your recording is still available below. Download a copy before closing, or try saving again." })
|
|
3463
|
-
] }),
|
|
3464
|
-
/* @__PURE__ */ jsxs5("p", { style: summaryStyle, children: [
|
|
3465
|
-
"Recording size:",
|
|
3466
|
-
" ",
|
|
3467
|
-
formatRecordingBytes(
|
|
3468
|
-
narrationOn ? stage.recorder.recordedBytes : recorder.recordedBytes
|
|
3469
|
-
),
|
|
3470
|
-
". Automatically stops at",
|
|
3471
|
-
" ",
|
|
3472
|
-
formatRecordingBytes(
|
|
3473
|
-
narrationOn ? stage.recorder.maxRecordingBytes : recorder.maxRecordingBytes
|
|
3474
|
-
),
|
|
3475
|
-
" ",
|
|
3476
|
-
"total. Final encoding may add more data."
|
|
3477
|
-
] }),
|
|
3478
|
-
!narrationOn && recorder.limitReached && /* @__PURE__ */ jsx6("p", { role: "status", style: recordingStatusStyle, children: "Recording stopped at the size limit. Your complete recording is retained; download a copy or save it to the document." }),
|
|
3479
|
-
narrationOn && (stage.recorder.error ?? stage.controller.mic.error) && /* @__PURE__ */ jsx6("div", { style: errorStyle, children: (stage.recorder.error ?? stage.controller.mic.error)?.message }),
|
|
3480
|
-
narrationOn && narrationCameraStream && /* @__PURE__ */ jsx6("div", { style: previewBoxStyle, children: /* @__PURE__ */ jsx6(
|
|
3481
|
-
"video",
|
|
3482
|
-
{
|
|
3483
|
-
ref: previewRef,
|
|
3484
|
-
autoPlay: true,
|
|
3485
|
-
muted: true,
|
|
3486
|
-
playsInline: true,
|
|
3487
|
-
style: { width: "100%", height: "100%", objectFit: "contain" }
|
|
3488
|
-
}
|
|
3489
|
-
) }),
|
|
3490
|
-
narrationOn && !narrationCameraStream && narrationTakeDone && /* @__PURE__ */ jsx6("div", { style: audioMeterStyle, children: stage.recorder.take ? `\u2713 Recorded ${formatDurationMs(stage.recorder.take.durationSec * 1e3)}` : "\u25CF Processing take\u2026" }),
|
|
3491
|
-
narrationOn && !narrationCameraStream && !narrationTakeDone && stage.recorder.withCamera && /* @__PURE__ */ jsx6("div", { style: previewBoxStyle, children: /* @__PURE__ */ jsx6("span", { children: narrationPreviewWanted ? "Camera starting\u2026" : "Click Start preview to turn on your camera." }) }),
|
|
3492
|
-
narrationOn && !narrationCameraStream && !narrationTakeDone && !stage.recorder.withCamera && /* @__PURE__ */ jsxs5("div", { style: { ...audioMeterStyle, position: "relative", overflow: "hidden" }, children: [
|
|
3493
|
-
/* @__PURE__ */ jsx6(
|
|
3494
|
-
"div",
|
|
3495
|
-
{
|
|
3496
|
-
"aria-hidden": "true",
|
|
3497
|
-
style: {
|
|
3498
|
-
...meterLevelStyle,
|
|
3499
|
-
width: `${Math.round(Math.min(1, Math.max(0, stage.controller.micLevel)) * 100)}%`
|
|
3500
|
-
}
|
|
3501
|
-
}
|
|
3502
|
-
),
|
|
3503
|
-
/* @__PURE__ */ jsx6("span", { style: { position: "relative" }, children: stage.recorder.state === "recording" ? "\u25CF Recording narration" : narrationMicLive ? stage.controller.voiceActive ? "Voice detected" : "Microphone ready" : "Click Start preview to check your mic." })
|
|
3504
|
-
] }),
|
|
3505
|
-
!narrationOn && !showPreview && /* @__PURE__ */ jsx6("div", { style: previewBoxStyle, children: /* @__PURE__ */ jsx6("span", { children: screenOn ? "Choose a screen or window to preview what will be recorded." : "Click Start preview to prepare a recording." }) }),
|
|
3506
|
-
!narrationOn && showPreview && recorder.state !== "stopped" && !isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: isDual ? { ...previewBoxStyle, position: "relative" } : previewBoxStyle, children: [
|
|
3507
|
-
/* @__PURE__ */ jsx6(
|
|
3508
|
-
"video",
|
|
3509
|
-
{
|
|
3510
|
-
ref: previewRef,
|
|
3511
|
-
autoPlay: true,
|
|
3512
|
-
muted: true,
|
|
3513
|
-
playsInline: true,
|
|
3514
|
-
style: { width: "100%", height: "100%", objectFit: "contain" }
|
|
3515
|
-
}
|
|
3516
|
-
),
|
|
3517
|
-
isDual && /* @__PURE__ */ jsx6(
|
|
3518
|
-
"video",
|
|
3519
|
-
{
|
|
3520
|
-
ref: cameraPreviewRef,
|
|
3521
|
-
autoPlay: true,
|
|
3522
|
-
muted: true,
|
|
3523
|
-
playsInline: true,
|
|
3524
|
-
"aria-label": "Camera preview",
|
|
3525
|
-
style: {
|
|
3526
|
-
position: "absolute",
|
|
3527
|
-
right: "3%",
|
|
3528
|
-
bottom: "6%",
|
|
3529
|
-
width: "22%",
|
|
3530
|
-
aspectRatio: "16 / 9",
|
|
3531
|
-
objectFit: "cover",
|
|
3532
|
-
background: "#000",
|
|
3533
|
-
border: "1px solid rgba(255,255,255,0.6)"
|
|
3534
|
-
}
|
|
3535
|
-
}
|
|
3536
|
-
)
|
|
3537
|
-
] }),
|
|
3538
|
-
!narrationOn && showPreview && recorder.state !== "stopped" && isAudioOnly && /* @__PURE__ */ jsx6("div", { style: audioMeterStyle, children: recorder.state === "recording" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3539
|
-
"\u25CF Recording ",
|
|
3540
|
-
formatDurationMs(recorder.durationMs)
|
|
3541
|
-
] }) : /* @__PURE__ */ jsx6(Fragment3, { children: "Microphone ready" }) }),
|
|
3542
|
-
!narrationOn && recorder.state === "stopped" && playbackUrl && !isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: { ...previewBoxStyle, position: "relative" }, children: [
|
|
3543
|
-
/* @__PURE__ */ jsx6(
|
|
3544
|
-
"video",
|
|
3545
|
-
{
|
|
3546
|
-
src: playbackUrl,
|
|
3547
|
-
controls: true,
|
|
3548
|
-
playsInline: true,
|
|
3549
|
-
onTimeUpdate: (event) => handlePlaybackTimeUpdate(event.currentTarget),
|
|
3550
|
-
onSeeking: (event) => handlePlaybackTimeUpdate(event.currentTarget),
|
|
3551
|
-
onEnded: () => setPlaybackPositionMs(recorder.durationMs),
|
|
3552
|
-
style: { width: "100%", height: "100%", objectFit: "contain" }
|
|
3553
|
-
}
|
|
3554
|
-
),
|
|
3555
|
-
/* @__PURE__ */ jsxs5(
|
|
3556
|
-
"div",
|
|
3557
|
-
{
|
|
3558
|
-
role: "timer",
|
|
3559
|
-
"aria-label": `Playback time: ${formatDurationMs(playbackPositionMs)} of ${formatDurationMs(recorder.durationMs)}`,
|
|
3560
|
-
style: playbackTimeStyle,
|
|
3561
|
-
children: [
|
|
3562
|
-
formatDurationMs(playbackPositionMs),
|
|
3563
|
-
" / ",
|
|
3564
|
-
formatDurationMs(recorder.durationMs)
|
|
3565
|
-
]
|
|
3566
|
-
}
|
|
3567
|
-
)
|
|
3568
|
-
] }),
|
|
3569
|
-
!narrationOn && recorder.state === "stopped" && isDual && cameraPlaybackUrl && /* @__PURE__ */ jsxs5("div", { style: { marginBottom: 12 }, children: [
|
|
3570
|
-
/* @__PURE__ */ jsx6("div", { style: summaryStyle, children: "Camera (picture-in-picture)" }),
|
|
3571
|
-
/* @__PURE__ */ jsx6(
|
|
3572
|
-
"video",
|
|
3573
|
-
{
|
|
3574
|
-
src: cameraPlaybackUrl,
|
|
3575
|
-
controls: true,
|
|
3576
|
-
playsInline: true,
|
|
3577
|
-
"aria-label": "Camera recording",
|
|
3578
|
-
style: {
|
|
3579
|
-
width: "48%",
|
|
3580
|
-
display: "block",
|
|
3581
|
-
marginLeft: "auto",
|
|
3582
|
-
background: "#000"
|
|
3583
|
-
}
|
|
3584
|
-
}
|
|
3585
|
-
)
|
|
3586
|
-
] }),
|
|
3587
|
-
!narrationOn && recorder.state === "stopped" && playbackUrl && isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: { marginBottom: 12 }, children: [
|
|
3588
|
-
/* @__PURE__ */ jsxs5("div", { style: { ...audioMeterStyle, marginBottom: 8 }, children: [
|
|
3589
|
-
"\u2713 Recorded ",
|
|
3590
|
-
formatDurationMs(recorder.durationMs)
|
|
3591
|
-
] }),
|
|
3592
|
-
/* @__PURE__ */ jsx6("audio", { src: playbackUrl, controls: true, style: { width: "100%" } })
|
|
3593
|
-
] }),
|
|
3594
|
-
!narrationOn && canSave && playbackUrl && /* @__PURE__ */ jsxs5(
|
|
3595
|
-
"div",
|
|
3596
|
-
{
|
|
3597
|
-
style: {
|
|
3598
|
-
...buttonRowStyle,
|
|
3599
|
-
flexWrap: "wrap",
|
|
3600
|
-
justifyContent: "flex-start",
|
|
3601
|
-
marginBottom: 12
|
|
3602
|
-
},
|
|
3603
|
-
children: [
|
|
3604
|
-
/* @__PURE__ */ jsx6("a", { href: playbackUrl, download: downloadFilename, style: btnSecondary, children: isDual ? "Download screen recording" : "Download recording" }),
|
|
3605
|
-
isDual && cameraPlaybackUrl && /* @__PURE__ */ jsx6(
|
|
3606
|
-
"a",
|
|
3374
|
+
/* @__PURE__ */ jsxs5(
|
|
3375
|
+
"div",
|
|
3376
|
+
{
|
|
3377
|
+
style: expanded ? {
|
|
3378
|
+
...leftColStyle,
|
|
3379
|
+
...panelMode === "both" ? { flex: "0 0 min(280px, 24vw)" } : {}
|
|
3380
|
+
} : void 0,
|
|
3381
|
+
children: [
|
|
3382
|
+
/* @__PURE__ */ jsx6("div", { style: toggleRowStyle, role: "group", "aria-label": "Capture sources", children: TOGGLE_GROUPS.map((group, groupIndex) => /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
3383
|
+
groupIndex > 0 && /* @__PURE__ */ jsx6("div", { "aria-hidden": "true", style: groupDividerStyle }),
|
|
3384
|
+
/* @__PURE__ */ jsx6("div", { style: toggleGroupStyle, children: group.toggles.map((t) => {
|
|
3385
|
+
if (t.key === "systemAudio" && !canIncludeSystemAudio) return null;
|
|
3386
|
+
const props = narrationRecording ? narrationToggleFor(t.key) : simpleToggleProps(t.key);
|
|
3387
|
+
return /* @__PURE__ */ jsx6(
|
|
3388
|
+
"button",
|
|
3389
|
+
{
|
|
3390
|
+
type: "button",
|
|
3391
|
+
"aria-pressed": props.active,
|
|
3392
|
+
style: props.active ? toggleActive : toggleBase,
|
|
3393
|
+
onClick: props.onClick,
|
|
3394
|
+
disabled: props.disabled,
|
|
3395
|
+
title: props.title,
|
|
3396
|
+
children: t.label
|
|
3397
|
+
},
|
|
3398
|
+
t.key
|
|
3399
|
+
);
|
|
3400
|
+
}) })
|
|
3401
|
+
] }, group.label)) }),
|
|
3402
|
+
/* @__PURE__ */ jsx6("p", { style: summaryStyle, children: narrationRecording ? narrationCaptureSummary(stage.recorder.withCamera) : captureSummary(micOn, cameraOn, screenOn, includeSystemAudio) }),
|
|
3403
|
+
narrationAvailable && /* @__PURE__ */ jsxs5("label", { style: checkboxRowStyle, children: [
|
|
3404
|
+
/* @__PURE__ */ jsx6(
|
|
3405
|
+
"input",
|
|
3607
3406
|
{
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
),
|
|
3615
|
-
style: btnSecondary,
|
|
3616
|
-
children: "Download camera recording"
|
|
3407
|
+
type: "checkbox",
|
|
3408
|
+
style: { accentColor: "var(--squisq-recorder-accent)" },
|
|
3409
|
+
checked: narrationOn,
|
|
3410
|
+
onChange: (e) => setPanelMode(panelModeAfterToggle(panelMode, "narration", e.target.checked)),
|
|
3411
|
+
disabled: narrationToggleDisabled,
|
|
3412
|
+
title: narrationToggleDisabled ? narrationRecording ? "Finish or discard the narration take first" : "Save or discard this recording before switching modes" : void 0
|
|
3617
3413
|
}
|
|
3618
3414
|
),
|
|
3619
|
-
|
|
3620
|
-
|
|
3415
|
+
"Show narration mode"
|
|
3416
|
+
] }),
|
|
3417
|
+
slidesAvailable && /* @__PURE__ */ jsxs5("label", { style: checkboxRowStyle, children: [
|
|
3418
|
+
/* @__PURE__ */ jsx6(
|
|
3419
|
+
"input",
|
|
3621
3420
|
{
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3421
|
+
type: "checkbox",
|
|
3422
|
+
style: { accentColor: "var(--squisq-recorder-accent)" },
|
|
3423
|
+
checked: slidesOn,
|
|
3424
|
+
onChange: (e) => setPanelMode(panelModeAfterToggle(panelMode, "slides", e.target.checked)),
|
|
3425
|
+
disabled: narrationToggleDisabled,
|
|
3426
|
+
title: narrationToggleDisabled ? "Save or discard this recording before switching modes" : void 0
|
|
3626
3427
|
}
|
|
3627
|
-
)
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
),
|
|
3631
|
-
!narrationOn && !slidesTimingCapture && source === "mic" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3632
|
-
/* @__PURE__ */ jsx6("label", { style: labelStyle, htmlFor: "recorder-source-text", children: "Script (used to auto-match this narration to a block)" }),
|
|
3633
|
-
/* @__PURE__ */ jsx6(
|
|
3634
|
-
"textarea",
|
|
3635
|
-
{
|
|
3636
|
-
id: "recorder-source-text",
|
|
3637
|
-
style: textareaStyle,
|
|
3638
|
-
placeholder: "Type the text you're going to read aloud.",
|
|
3639
|
-
value: sourceText,
|
|
3640
|
-
onChange: (e) => setSourceText(e.target.value),
|
|
3641
|
-
disabled: recorder.state === "recording"
|
|
3642
|
-
}
|
|
3643
|
-
)
|
|
3644
|
-
] }),
|
|
3645
|
-
/* @__PURE__ */ jsx6("label", { style: labelStyle, htmlFor: "recorder-basename", children: "Filename (optional)" }),
|
|
3646
|
-
/* @__PURE__ */ jsx6(
|
|
3647
|
-
"input",
|
|
3648
|
-
{
|
|
3649
|
-
id: "recorder-basename",
|
|
3650
|
-
type: "text",
|
|
3651
|
-
style: inputStyle2,
|
|
3652
|
-
placeholder: narrationOn ? "narration" : isDual ? "screen + camera" : filenameSeed,
|
|
3653
|
-
value: basename,
|
|
3654
|
-
onChange: (e) => setBasename(e.target.value),
|
|
3655
|
-
disabled: narrationOn ? !narrationRecorderIdle : recorder.state === "recording"
|
|
3656
|
-
}
|
|
3657
|
-
),
|
|
3658
|
-
!narrationOn && recorder.state === "recording" && !isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: recordingStatusStyle, children: [
|
|
3659
|
-
"\u25CF Recording ",
|
|
3660
|
-
formatDurationMs(recorder.durationMs)
|
|
3661
|
-
] }),
|
|
3662
|
-
showTimingCheckbox && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3663
|
-
/* @__PURE__ */ jsxs5("label", { style: checkboxRowStyle, children: [
|
|
3428
|
+
),
|
|
3429
|
+
"Show slides mode"
|
|
3430
|
+
] }),
|
|
3664
3431
|
/* @__PURE__ */ jsx6(
|
|
3665
|
-
|
|
3432
|
+
RecorderDeviceQuickPicks,
|
|
3666
3433
|
{
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3434
|
+
devices: mediaDevices,
|
|
3435
|
+
microphoneEnabled,
|
|
3436
|
+
cameraEnabled,
|
|
3437
|
+
audioDeviceId: deviceSettings.audio.deviceId,
|
|
3438
|
+
cameraDeviceId: deviceSettings.camera.deviceId,
|
|
3439
|
+
onAudioDeviceChange: (deviceId) => handleDeviceSettingsChange({
|
|
3440
|
+
...deviceSettings,
|
|
3441
|
+
audio: { ...deviceSettings.audio, deviceId }
|
|
3442
|
+
}),
|
|
3443
|
+
onCameraDeviceChange: (deviceId) => handleDeviceSettingsChange({
|
|
3444
|
+
...deviceSettings,
|
|
3445
|
+
camera: { ...deviceSettings.camera, deviceId }
|
|
3446
|
+
}),
|
|
3447
|
+
disabled: deviceSettingsLocked
|
|
3672
3448
|
}
|
|
3673
3449
|
),
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
narrationOn && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3690
|
-
narrationRecorderIdle && !narrationMicLive && /* @__PURE__ */ jsx6(
|
|
3691
|
-
"button",
|
|
3450
|
+
!narrationRecording && screenOn && /* @__PURE__ */ jsx6(
|
|
3451
|
+
RecorderScreenSettings,
|
|
3452
|
+
{
|
|
3453
|
+
value: deviceSettings.screen,
|
|
3454
|
+
onChange: (screen) => handleDeviceSettingsChange({ ...deviceSettings, screen }),
|
|
3455
|
+
disabled: deviceSettingsLocked,
|
|
3456
|
+
hasPreview: recorder.state === "ready",
|
|
3457
|
+
onChoose: () => {
|
|
3458
|
+
recorder.cancel();
|
|
3459
|
+
void handleRequest();
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3462
|
+
),
|
|
3463
|
+
/* @__PURE__ */ jsx6(
|
|
3464
|
+
RecorderDeviceSettingsPanel,
|
|
3692
3465
|
{
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3466
|
+
value: deviceSettings,
|
|
3467
|
+
onChange: handleDeviceSettingsChange,
|
|
3468
|
+
disabled: deviceSettingsLocked,
|
|
3469
|
+
microphoneEnabled,
|
|
3470
|
+
cameraEnabled,
|
|
3471
|
+
screenEnabled: narrationRecording ? false : screenOn,
|
|
3472
|
+
systemAudioEnabled: !narrationRecording && includeSystemAudio,
|
|
3473
|
+
separateAudioRecorder: narrationRecording,
|
|
3474
|
+
primaryStream: activePrimaryStream,
|
|
3475
|
+
cameraStream: activeCameraStream
|
|
3698
3476
|
}
|
|
3699
3477
|
),
|
|
3700
|
-
|
|
3478
|
+
!narrationRecording && recorder.error && /* @__PURE__ */ jsx6("div", { style: errorStyle, children: recorder.error.message }),
|
|
3479
|
+
!narrationRecording && saveError && /* @__PURE__ */ jsxs5("div", { role: "alert", style: errorStyle, children: [
|
|
3480
|
+
saveError,
|
|
3481
|
+
/* @__PURE__ */ jsx6("p", { style: { marginBottom: 0 }, children: "Your recording is still available below. Download a copy before closing, or try saving again." })
|
|
3482
|
+
] }),
|
|
3483
|
+
/* @__PURE__ */ jsxs5("p", { style: summaryStyle, children: [
|
|
3484
|
+
"Recording size:",
|
|
3485
|
+
" ",
|
|
3486
|
+
formatRecordingBytes(
|
|
3487
|
+
narrationRecording ? stage.recorder.recordedBytes : recorder.recordedBytes
|
|
3488
|
+
),
|
|
3489
|
+
". Automatically stops at",
|
|
3490
|
+
" ",
|
|
3491
|
+
formatRecordingBytes(
|
|
3492
|
+
narrationRecording ? stage.recorder.maxRecordingBytes : recorder.maxRecordingBytes
|
|
3493
|
+
),
|
|
3494
|
+
" ",
|
|
3495
|
+
"total. Final encoding may add more data."
|
|
3496
|
+
] }),
|
|
3497
|
+
!narrationRecording && recorder.limitReached && /* @__PURE__ */ jsx6("p", { role: "status", style: recordingStatusStyle, children: "Recording stopped at the size limit. Your complete recording is retained; download a copy or save it to the document." }),
|
|
3498
|
+
narrationOn && (stage.recorder.error ?? stage.controller.mic.error) && /* @__PURE__ */ jsx6("div", { style: errorStyle, children: (stage.recorder.error ?? stage.controller.mic.error)?.message }),
|
|
3499
|
+
narrationRecording && narrationCameraStream && /* @__PURE__ */ jsx6("div", { style: previewBoxStyle, children: /* @__PURE__ */ jsx6(
|
|
3500
|
+
"video",
|
|
3501
|
+
{
|
|
3502
|
+
ref: previewRef,
|
|
3503
|
+
autoPlay: true,
|
|
3504
|
+
muted: true,
|
|
3505
|
+
playsInline: true,
|
|
3506
|
+
style: { width: "100%", height: "100%", objectFit: "contain" }
|
|
3507
|
+
}
|
|
3508
|
+
) }),
|
|
3509
|
+
narrationRecording && !narrationCameraStream && narrationTakeDone && /* @__PURE__ */ jsx6("div", { style: audioMeterStyle, children: stage.recorder.take ? `\u2713 Recorded ${formatDurationMs(stage.recorder.take.durationSec * 1e3)}` : "\u25CF Processing take\u2026" }),
|
|
3510
|
+
narrationRecording && !narrationCameraStream && !narrationTakeDone && stage.recorder.withCamera && /* @__PURE__ */ jsx6("div", { style: previewBoxStyle, children: /* @__PURE__ */ jsx6("span", { children: narrationPreviewWanted ? "Camera starting\u2026" : "Click Start preview to turn on your camera." }) }),
|
|
3511
|
+
narrationRecording && !narrationCameraStream && !narrationTakeDone && !stage.recorder.withCamera && /* @__PURE__ */ jsxs5("div", { style: { ...audioMeterStyle, position: "relative", overflow: "hidden" }, children: [
|
|
3701
3512
|
/* @__PURE__ */ jsx6(
|
|
3702
|
-
"
|
|
3513
|
+
"div",
|
|
3703
3514
|
{
|
|
3704
|
-
className: "squisq-recorder-record-dot",
|
|
3705
|
-
style: recordDotFrameStyle,
|
|
3706
3515
|
"aria-hidden": "true",
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
{
|
|
3710
|
-
|
|
3711
|
-
style: recordDotStyle
|
|
3712
|
-
}
|
|
3713
|
-
)
|
|
3516
|
+
style: {
|
|
3517
|
+
...meterLevelStyle,
|
|
3518
|
+
width: `${Math.round(Math.min(1, Math.max(0, stage.controller.micLevel)) * 100)}%`
|
|
3519
|
+
}
|
|
3714
3520
|
}
|
|
3715
3521
|
),
|
|
3716
|
-
"
|
|
3522
|
+
/* @__PURE__ */ jsx6("span", { style: { position: "relative" }, children: stage.recorder.state === "recording" ? "\u25CF Recording narration" : narrationMicLive ? stage.controller.voiceActive ? "Voice detected" : "Microphone ready" : "Click Start preview to check your mic." })
|
|
3717
3523
|
] }),
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
{
|
|
3721
|
-
type: "button",
|
|
3722
|
-
style: btnDanger,
|
|
3723
|
-
onClick: () => void stage.recorder.stop(),
|
|
3724
|
-
children: "Stop"
|
|
3725
|
-
}
|
|
3726
|
-
),
|
|
3727
|
-
stage.recorder.state === "processing" && /* @__PURE__ */ jsx6("span", { style: recordingStatusStyle, children: "Aligning take\u2026" }),
|
|
3728
|
-
stage.recorder.state === "saving" && /* @__PURE__ */ jsx6("span", { style: recordingStatusStyle, children: "Saving\u2026" }),
|
|
3729
|
-
stage.recorder.state === "review" && stage.recorder.take && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3730
|
-
/* @__PURE__ */ jsx6("button", { type: "button", style: btnSecondary, onClick: stage.handleRetake, children: "Discard & re-record" }),
|
|
3524
|
+
!narrationRecording && !showPreview && /* @__PURE__ */ jsx6("div", { style: previewBoxStyle, children: /* @__PURE__ */ jsx6("span", { children: screenOn ? "Choose a screen or window to preview what will be recorded." : "Click Start preview to prepare a recording." }) }),
|
|
3525
|
+
!narrationRecording && showPreview && recorder.state !== "stopped" && !isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: isDual ? { ...previewBoxStyle, position: "relative" } : previewBoxStyle, children: [
|
|
3731
3526
|
/* @__PURE__ */ jsx6(
|
|
3732
|
-
"
|
|
3527
|
+
"video",
|
|
3733
3528
|
{
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3529
|
+
ref: previewRef,
|
|
3530
|
+
autoPlay: true,
|
|
3531
|
+
muted: true,
|
|
3532
|
+
playsInline: true,
|
|
3533
|
+
style: { width: "100%", height: "100%", objectFit: "contain" }
|
|
3534
|
+
}
|
|
3535
|
+
),
|
|
3536
|
+
isDual && /* @__PURE__ */ jsx6(
|
|
3537
|
+
"video",
|
|
3538
|
+
{
|
|
3539
|
+
ref: cameraPreviewRef,
|
|
3540
|
+
autoPlay: true,
|
|
3541
|
+
muted: true,
|
|
3542
|
+
playsInline: true,
|
|
3543
|
+
"aria-label": "Camera preview",
|
|
3544
|
+
style: {
|
|
3545
|
+
position: "absolute",
|
|
3546
|
+
right: "3%",
|
|
3547
|
+
bottom: "6%",
|
|
3548
|
+
width: "22%",
|
|
3549
|
+
aspectRatio: "16 / 9",
|
|
3550
|
+
objectFit: "cover",
|
|
3551
|
+
background: "#000",
|
|
3552
|
+
border: "1px solid rgba(255,255,255,0.6)"
|
|
3553
|
+
}
|
|
3738
3554
|
}
|
|
3739
3555
|
)
|
|
3740
|
-
] })
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
type: "button",
|
|
3747
|
-
style: btnPrimary,
|
|
3748
|
-
onClick: handleRequest,
|
|
3749
|
-
disabled: isBusy || !canCapture,
|
|
3750
|
-
children: recorder.state === "requesting" ? "Requesting\u2026" : "Start preview"
|
|
3751
|
-
}
|
|
3752
|
-
),
|
|
3753
|
-
canRecord && /* @__PURE__ */ jsxs5("button", { type: "button", style: btnRecord, onClick: handleStart, disabled: isBusy, children: [
|
|
3556
|
+
] }),
|
|
3557
|
+
!narrationRecording && showPreview && recorder.state !== "stopped" && isAudioOnly && /* @__PURE__ */ jsx6("div", { style: audioMeterStyle, children: recorder.state === "recording" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3558
|
+
"\u25CF Recording ",
|
|
3559
|
+
formatDurationMs(recorder.durationMs)
|
|
3560
|
+
] }) : /* @__PURE__ */ jsx6(Fragment3, { children: "Microphone ready" }) }),
|
|
3561
|
+
!narrationRecording && recorder.state === "stopped" && playbackUrl && !isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: { ...previewBoxStyle, position: "relative" }, children: [
|
|
3754
3562
|
/* @__PURE__ */ jsx6(
|
|
3755
|
-
"
|
|
3563
|
+
"video",
|
|
3756
3564
|
{
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3565
|
+
src: playbackUrl,
|
|
3566
|
+
controls: true,
|
|
3567
|
+
playsInline: true,
|
|
3568
|
+
onTimeUpdate: (event) => handlePlaybackTimeUpdate(event.currentTarget),
|
|
3569
|
+
onSeeking: (event) => handlePlaybackTimeUpdate(event.currentTarget),
|
|
3570
|
+
onEnded: () => setPlaybackPositionMs(recorder.durationMs),
|
|
3571
|
+
style: { width: "100%", height: "100%", objectFit: "contain" }
|
|
3572
|
+
}
|
|
3573
|
+
),
|
|
3574
|
+
/* @__PURE__ */ jsxs5(
|
|
3575
|
+
"div",
|
|
3576
|
+
{
|
|
3577
|
+
role: "timer",
|
|
3578
|
+
"aria-label": `Playback time: ${formatDurationMs(playbackPositionMs)} of ${formatDurationMs(recorder.durationMs)}`,
|
|
3579
|
+
style: playbackTimeStyle,
|
|
3580
|
+
children: [
|
|
3581
|
+
formatDurationMs(playbackPositionMs),
|
|
3582
|
+
" / ",
|
|
3583
|
+
formatDurationMs(recorder.durationMs)
|
|
3584
|
+
]
|
|
3585
|
+
}
|
|
3586
|
+
)
|
|
3587
|
+
] }),
|
|
3588
|
+
!narrationRecording && recorder.state === "stopped" && isDual && cameraPlaybackUrl && /* @__PURE__ */ jsxs5("div", { style: { marginBottom: 12 }, children: [
|
|
3589
|
+
/* @__PURE__ */ jsx6("div", { style: summaryStyle, children: "Camera (picture-in-picture)" }),
|
|
3590
|
+
/* @__PURE__ */ jsx6(
|
|
3591
|
+
"video",
|
|
3592
|
+
{
|
|
3593
|
+
src: cameraPlaybackUrl,
|
|
3594
|
+
controls: true,
|
|
3595
|
+
playsInline: true,
|
|
3596
|
+
"aria-label": "Camera recording",
|
|
3597
|
+
style: {
|
|
3598
|
+
width: "48%",
|
|
3599
|
+
display: "block",
|
|
3600
|
+
marginLeft: "auto",
|
|
3601
|
+
background: "#000"
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
)
|
|
3605
|
+
] }),
|
|
3606
|
+
!narrationRecording && recorder.state === "stopped" && playbackUrl && isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: { marginBottom: 12 }, children: [
|
|
3607
|
+
/* @__PURE__ */ jsxs5("div", { style: { ...audioMeterStyle, marginBottom: 8 }, children: [
|
|
3608
|
+
"\u2713 Recorded ",
|
|
3609
|
+
formatDurationMs(recorder.durationMs)
|
|
3610
|
+
] }),
|
|
3611
|
+
/* @__PURE__ */ jsx6("audio", { src: playbackUrl, controls: true, style: { width: "100%" } })
|
|
3612
|
+
] }),
|
|
3613
|
+
!narrationRecording && canSave && playbackUrl && /* @__PURE__ */ jsxs5(
|
|
3614
|
+
"div",
|
|
3615
|
+
{
|
|
3616
|
+
style: {
|
|
3617
|
+
...buttonRowStyle,
|
|
3618
|
+
flexWrap: "wrap",
|
|
3619
|
+
justifyContent: "flex-start",
|
|
3620
|
+
marginBottom: 12
|
|
3621
|
+
},
|
|
3622
|
+
children: [
|
|
3623
|
+
/* @__PURE__ */ jsx6("a", { href: playbackUrl, download: downloadFilename, style: btnSecondary, children: isDual ? "Download screen recording" : "Download recording" }),
|
|
3624
|
+
isDual && cameraPlaybackUrl && /* @__PURE__ */ jsx6(
|
|
3625
|
+
"a",
|
|
3762
3626
|
{
|
|
3763
|
-
|
|
3764
|
-
|
|
3627
|
+
href: cameraPlaybackUrl,
|
|
3628
|
+
download: buildFilename(
|
|
3629
|
+
"video",
|
|
3630
|
+
recorder.camera?.extension ?? ".webm",
|
|
3631
|
+
basename.trim() ? `${basename.trim()}-camera` : void 0,
|
|
3632
|
+
micOn ? "camera-audio" : "camera"
|
|
3633
|
+
),
|
|
3634
|
+
style: btnSecondary,
|
|
3635
|
+
children: "Download camera recording"
|
|
3636
|
+
}
|
|
3637
|
+
),
|
|
3638
|
+
timingDownloadUrl && /* @__PURE__ */ jsx6(
|
|
3639
|
+
"a",
|
|
3640
|
+
{
|
|
3641
|
+
href: timingDownloadUrl,
|
|
3642
|
+
download: timingDownloadFilename,
|
|
3643
|
+
style: btnSecondary,
|
|
3644
|
+
children: "Download recording timings"
|
|
3765
3645
|
}
|
|
3766
3646
|
)
|
|
3647
|
+
]
|
|
3648
|
+
}
|
|
3649
|
+
),
|
|
3650
|
+
!narrationOn && !slidesTimingCapture && source === "mic" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3651
|
+
/* @__PURE__ */ jsx6("label", { style: labelStyle, htmlFor: "recorder-source-text", children: "Script (used to auto-match this narration to a block)" }),
|
|
3652
|
+
/* @__PURE__ */ jsx6(
|
|
3653
|
+
"textarea",
|
|
3654
|
+
{
|
|
3655
|
+
id: "recorder-source-text",
|
|
3656
|
+
style: textareaStyle,
|
|
3657
|
+
placeholder: "Type the text you're going to read aloud.",
|
|
3658
|
+
value: sourceText,
|
|
3659
|
+
onChange: (e) => setSourceText(e.target.value),
|
|
3660
|
+
disabled: recorder.state === "recording"
|
|
3767
3661
|
}
|
|
3768
|
-
)
|
|
3769
|
-
"Record"
|
|
3662
|
+
)
|
|
3770
3663
|
] }),
|
|
3771
|
-
|
|
3772
|
-
|
|
3664
|
+
/* @__PURE__ */ jsx6("label", { style: labelStyle, htmlFor: "recorder-basename", children: "Filename (optional)" }),
|
|
3665
|
+
/* @__PURE__ */ jsx6(
|
|
3666
|
+
"input",
|
|
3667
|
+
{
|
|
3668
|
+
id: "recorder-basename",
|
|
3669
|
+
type: "text",
|
|
3670
|
+
style: inputStyle2,
|
|
3671
|
+
placeholder: narrationRecording ? "narration" : isDual ? "screen + camera" : filenameSeed,
|
|
3672
|
+
value: basename,
|
|
3673
|
+
onChange: (e) => setBasename(e.target.value),
|
|
3674
|
+
disabled: narrationRecording ? !narrationRecorderIdle : recorder.state === "recording"
|
|
3675
|
+
}
|
|
3676
|
+
),
|
|
3677
|
+
!narrationRecording && recorder.state === "recording" && !isAudioOnly && /* @__PURE__ */ jsxs5("div", { style: recordingStatusStyle, children: [
|
|
3678
|
+
"\u25CF Recording ",
|
|
3679
|
+
formatDurationMs(recorder.durationMs)
|
|
3680
|
+
] }),
|
|
3681
|
+
showTimingCheckbox && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3682
|
+
/* @__PURE__ */ jsxs5("label", { style: checkboxRowStyle, children: [
|
|
3683
|
+
/* @__PURE__ */ jsx6(
|
|
3684
|
+
"input",
|
|
3685
|
+
{
|
|
3686
|
+
type: "checkbox",
|
|
3687
|
+
style: { accentColor: "var(--squisq-recorder-accent)" },
|
|
3688
|
+
checked: applySlideTimings,
|
|
3689
|
+
onChange: (e) => setApplySlideTimings(e.target.checked),
|
|
3690
|
+
disabled: isSaving
|
|
3691
|
+
}
|
|
3692
|
+
),
|
|
3693
|
+
SLIDE_TIMING_CHECKBOX_LABEL
|
|
3694
|
+
] }),
|
|
3695
|
+
applySlideTimings && slideCoverageWarning && /* @__PURE__ */ jsx6("p", { style: summaryStyle, children: slideCoverageWarning })
|
|
3696
|
+
] }),
|
|
3697
|
+
/* @__PURE__ */ jsxs5("div", { style: buttonRowStyle, children: [
|
|
3773
3698
|
/* @__PURE__ */ jsx6(
|
|
3774
3699
|
"button",
|
|
3775
3700
|
{
|
|
3776
3701
|
type: "button",
|
|
3777
3702
|
style: btnSecondary,
|
|
3778
|
-
onClick:
|
|
3779
|
-
disabled: isBusy,
|
|
3780
|
-
children: "
|
|
3703
|
+
onClick: handleClose,
|
|
3704
|
+
disabled: !narrationRecording && isBusy,
|
|
3705
|
+
children: "Close"
|
|
3781
3706
|
}
|
|
3782
3707
|
),
|
|
3783
|
-
/* @__PURE__ */
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3708
|
+
narrationRecording && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3709
|
+
narrationRecorderIdle && !narrationMicLive && /* @__PURE__ */ jsx6(
|
|
3710
|
+
"button",
|
|
3711
|
+
{
|
|
3712
|
+
type: "button",
|
|
3713
|
+
style: btnPrimary,
|
|
3714
|
+
onClick: () => void handleNarrationPreview(),
|
|
3715
|
+
disabled: narrationRequesting,
|
|
3716
|
+
children: narrationRequesting ? "Requesting\u2026" : "Start preview"
|
|
3717
|
+
}
|
|
3718
|
+
),
|
|
3719
|
+
narrationRecorderIdle && narrationMicLive && /* @__PURE__ */ jsxs5("button", { type: "button", style: btnRecord, onClick: handleNarrationRecord, children: [
|
|
3720
|
+
/* @__PURE__ */ jsx6(
|
|
3721
|
+
"span",
|
|
3722
|
+
{
|
|
3723
|
+
className: "squisq-recorder-record-dot",
|
|
3724
|
+
style: recordDotFrameStyle,
|
|
3725
|
+
"aria-hidden": "true",
|
|
3726
|
+
children: /* @__PURE__ */ jsx6(
|
|
3727
|
+
"span",
|
|
3728
|
+
{
|
|
3729
|
+
className: "squisq-recorder-record-dot-center",
|
|
3730
|
+
style: recordDotStyle
|
|
3731
|
+
}
|
|
3732
|
+
)
|
|
3733
|
+
}
|
|
3734
|
+
),
|
|
3735
|
+
"Record"
|
|
3736
|
+
] }),
|
|
3737
|
+
(stage.recorder.state === "recording" || stage.recorder.state === "starting") && /* @__PURE__ */ jsx6(
|
|
3738
|
+
"button",
|
|
3739
|
+
{
|
|
3740
|
+
type: "button",
|
|
3741
|
+
style: btnDanger,
|
|
3742
|
+
onClick: () => void stage.recorder.stop(),
|
|
3743
|
+
children: "Stop"
|
|
3744
|
+
}
|
|
3745
|
+
),
|
|
3746
|
+
stage.recorder.state === "processing" && /* @__PURE__ */ jsx6("span", { style: recordingStatusStyle, children: "Aligning take\u2026" }),
|
|
3747
|
+
stage.recorder.state === "saving" && /* @__PURE__ */ jsx6("span", { style: recordingStatusStyle, children: "Saving\u2026" }),
|
|
3748
|
+
stage.recorder.state === "review" && stage.recorder.take && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3749
|
+
/* @__PURE__ */ jsx6("button", { type: "button", style: btnSecondary, onClick: stage.handleRetake, children: "Discard & re-record" }),
|
|
3750
|
+
/* @__PURE__ */ jsx6(
|
|
3751
|
+
"button",
|
|
3752
|
+
{
|
|
3753
|
+
type: "button",
|
|
3754
|
+
style: btnPrimary,
|
|
3755
|
+
onClick: () => void stage.handleSave(),
|
|
3756
|
+
children: "Save to document"
|
|
3757
|
+
}
|
|
3758
|
+
)
|
|
3759
|
+
] })
|
|
3760
|
+
] }),
|
|
3761
|
+
!narrationRecording && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3762
|
+
(recorder.state === "idle" || recorder.state === "error" || recorder.state === "requesting") && /* @__PURE__ */ jsx6(
|
|
3763
|
+
"button",
|
|
3764
|
+
{
|
|
3765
|
+
type: "button",
|
|
3766
|
+
style: btnPrimary,
|
|
3767
|
+
onClick: handleRequest,
|
|
3768
|
+
disabled: isBusy || !canCapture,
|
|
3769
|
+
children: recorder.state === "requesting" ? "Requesting\u2026" : "Start preview"
|
|
3770
|
+
}
|
|
3771
|
+
),
|
|
3772
|
+
canRecord && /* @__PURE__ */ jsxs5("button", { type: "button", style: btnRecord, onClick: handleStart, disabled: isBusy, children: [
|
|
3773
|
+
/* @__PURE__ */ jsx6(
|
|
3774
|
+
"span",
|
|
3775
|
+
{
|
|
3776
|
+
className: "squisq-recorder-record-dot",
|
|
3777
|
+
style: recordDotFrameStyle,
|
|
3778
|
+
"aria-hidden": "true",
|
|
3779
|
+
children: /* @__PURE__ */ jsx6(
|
|
3780
|
+
"span",
|
|
3781
|
+
{
|
|
3782
|
+
className: "squisq-recorder-record-dot-center",
|
|
3783
|
+
style: recordDotStyle
|
|
3784
|
+
}
|
|
3785
|
+
)
|
|
3786
|
+
}
|
|
3787
|
+
),
|
|
3788
|
+
"Record"
|
|
3789
|
+
] }),
|
|
3790
|
+
canStop && /* @__PURE__ */ jsx6("button", { type: "button", style: btnDanger, onClick: handleStop, disabled: isBusy, children: "Stop" }),
|
|
3791
|
+
canSave && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3792
|
+
/* @__PURE__ */ jsx6(
|
|
3793
|
+
"button",
|
|
3794
|
+
{
|
|
3795
|
+
type: "button",
|
|
3796
|
+
style: btnSecondary,
|
|
3797
|
+
onClick: handleDiscard,
|
|
3798
|
+
disabled: isBusy,
|
|
3799
|
+
children: "Discard & re-record"
|
|
3800
|
+
}
|
|
3801
|
+
),
|
|
3802
|
+
/* @__PURE__ */ jsx6(
|
|
3803
|
+
"button",
|
|
3804
|
+
{
|
|
3805
|
+
type: "button",
|
|
3806
|
+
style: btnPrimary,
|
|
3807
|
+
onClick: handleSave,
|
|
3808
|
+
disabled: isBusy,
|
|
3809
|
+
children: isSaving ? "Saving\u2026" : "Save to document"
|
|
3810
|
+
}
|
|
3811
|
+
)
|
|
3812
|
+
] })
|
|
3813
|
+
] })
|
|
3793
3814
|
] })
|
|
3794
|
-
]
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
narrationOn && narration && /* @__PURE__ */ jsx6("div", { style: rightColStyle, children: /* @__PURE__ */ jsx6(
|
|
3815
|
+
]
|
|
3816
|
+
}
|
|
3817
|
+
),
|
|
3818
|
+
narrationOn && narration && /* @__PURE__ */ jsx6("div", { style: { ...rightColStyle, flex: "1 1 0" }, children: /* @__PURE__ */ jsx6(
|
|
3798
3819
|
NarrationStage,
|
|
3799
3820
|
{
|
|
3800
3821
|
stage,
|
|
@@ -3806,7 +3827,7 @@ function RecorderModal({
|
|
|
3806
3827
|
showReviewActions: false
|
|
3807
3828
|
}
|
|
3808
3829
|
) }),
|
|
3809
|
-
slidesOn && /* @__PURE__ */ jsx6("div", { style: rightColStyle, children: /* @__PURE__ */ jsx6(
|
|
3830
|
+
slidesOn && /* @__PURE__ */ jsx6("div", { style: { ...rightColStyle, flex: "1 1 0" }, children: /* @__PURE__ */ jsx6(
|
|
3810
3831
|
RecorderSlidesPanel,
|
|
3811
3832
|
{
|
|
3812
3833
|
slides: slideDeck,
|
|
@@ -3815,7 +3836,7 @@ function RecorderModal({
|
|
|
3815
3836
|
viewport: slidesViewport,
|
|
3816
3837
|
basePath: slides?.basePath,
|
|
3817
3838
|
mediaProvider: slides?.mediaProvider ?? mediaProvider,
|
|
3818
|
-
recording: recorder.state === "recording",
|
|
3839
|
+
recording: narrationRecording ? stage.recorder.state === "recording" : recorder.state === "recording",
|
|
3819
3840
|
shownBlockIds
|
|
3820
3841
|
}
|
|
3821
3842
|
) })
|