@scalemule/nextjs 0.1.22 → 0.1.24
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/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +74 -4
- package/dist/index.mjs +74 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -898,10 +898,11 @@ interface NarrationPlayerProps {
|
|
|
898
898
|
providerLabel?: string;
|
|
899
899
|
narrationLabel?: string;
|
|
900
900
|
refreshing?: boolean;
|
|
901
|
-
onRefresh?: () => void
|
|
901
|
+
onRefresh?: () => void | Promise<void>;
|
|
902
|
+
showRefreshButton?: boolean;
|
|
902
903
|
onPlaybackError?: () => void;
|
|
903
904
|
}
|
|
904
|
-
declare function NarrationPlayer({ audio, className, providerLabel, narrationLabel, refreshing, onRefresh, onPlaybackError, }: NarrationPlayerProps): react_jsx_runtime.JSX.Element | null;
|
|
905
|
+
declare function NarrationPlayer({ audio, className, providerLabel, narrationLabel, refreshing, onRefresh, showRefreshButton, onPlaybackError, }: NarrationPlayerProps): react_jsx_runtime.JSX.Element | null;
|
|
905
906
|
|
|
906
907
|
/**
|
|
907
908
|
* Client-side validation helpers
|
package/dist/index.d.ts
CHANGED
|
@@ -898,10 +898,11 @@ interface NarrationPlayerProps {
|
|
|
898
898
|
providerLabel?: string;
|
|
899
899
|
narrationLabel?: string;
|
|
900
900
|
refreshing?: boolean;
|
|
901
|
-
onRefresh?: () => void
|
|
901
|
+
onRefresh?: () => void | Promise<void>;
|
|
902
|
+
showRefreshButton?: boolean;
|
|
902
903
|
onPlaybackError?: () => void;
|
|
903
904
|
}
|
|
904
|
-
declare function NarrationPlayer({ audio, className, providerLabel, narrationLabel, refreshing, onRefresh, onPlaybackError, }: NarrationPlayerProps): react_jsx_runtime.JSX.Element | null;
|
|
905
|
+
declare function NarrationPlayer({ audio, className, providerLabel, narrationLabel, refreshing, onRefresh, showRefreshButton, onPlaybackError, }: NarrationPlayerProps): react_jsx_runtime.JSX.Element | null;
|
|
905
906
|
|
|
906
907
|
/**
|
|
907
908
|
* Client-side validation helpers
|
package/dist/index.js
CHANGED
|
@@ -11289,6 +11289,7 @@ function FeedbackWidget(props) {
|
|
|
11289
11289
|
] });
|
|
11290
11290
|
}
|
|
11291
11291
|
var SPEEDS = [1, 1.25, 1.5, 2];
|
|
11292
|
+
var EXPIRY_REFRESH_WINDOW_MS = 3e4;
|
|
11292
11293
|
var styles = {
|
|
11293
11294
|
root: {
|
|
11294
11295
|
borderRadius: "1.75rem",
|
|
@@ -11462,10 +11463,14 @@ function NarrationPlayer({
|
|
|
11462
11463
|
narrationLabel = "AI-Narrated",
|
|
11463
11464
|
refreshing = false,
|
|
11464
11465
|
onRefresh,
|
|
11466
|
+
showRefreshButton = false,
|
|
11465
11467
|
onPlaybackError
|
|
11466
11468
|
}) {
|
|
11467
11469
|
const audioRef = React.useRef(null);
|
|
11468
11470
|
const scrubRef = React.useRef(null);
|
|
11471
|
+
const pendingResumeRef = React.useRef(false);
|
|
11472
|
+
const pendingResumeTimeRef = React.useRef(null);
|
|
11473
|
+
const recoveredUrlRef = React.useRef(null);
|
|
11469
11474
|
const [playing, setPlaying] = React.useState(false);
|
|
11470
11475
|
const [currentTime, setCurrentTime] = React.useState(0);
|
|
11471
11476
|
const [duration, setDuration] = React.useState(audio.duration_ms ? audio.duration_ms / 1e3 : 0);
|
|
@@ -11480,10 +11485,26 @@ function NarrationPlayer({
|
|
|
11480
11485
|
React.useEffect(() => {
|
|
11481
11486
|
const element = audioRef.current;
|
|
11482
11487
|
if (!element) return;
|
|
11483
|
-
|
|
11488
|
+
recoveredUrlRef.current = null;
|
|
11489
|
+
const resumeTime = pendingResumeTimeRef.current;
|
|
11490
|
+
setCurrentTime(resumeTime ?? 0);
|
|
11484
11491
|
setPlaying(false);
|
|
11485
11492
|
element.pause();
|
|
11486
|
-
|
|
11493
|
+
try {
|
|
11494
|
+
element.currentTime = resumeTime ?? 0;
|
|
11495
|
+
} catch {
|
|
11496
|
+
element.currentTime = 0;
|
|
11497
|
+
}
|
|
11498
|
+
if (pendingResumeRef.current) {
|
|
11499
|
+
pendingResumeRef.current = false;
|
|
11500
|
+
pendingResumeTimeRef.current = null;
|
|
11501
|
+
element.play().catch(() => {
|
|
11502
|
+
setPlaying(false);
|
|
11503
|
+
onPlaybackError?.();
|
|
11504
|
+
});
|
|
11505
|
+
return;
|
|
11506
|
+
}
|
|
11507
|
+
pendingResumeTimeRef.current = null;
|
|
11487
11508
|
}, [audio.url]);
|
|
11488
11509
|
React.useEffect(() => {
|
|
11489
11510
|
const element = audioRef.current;
|
|
@@ -11491,10 +11512,49 @@ function NarrationPlayer({
|
|
|
11491
11512
|
element.playbackRate = speed;
|
|
11492
11513
|
element.preservesPitch = true;
|
|
11493
11514
|
}, [speed]);
|
|
11515
|
+
function isUrlExpiringSoon() {
|
|
11516
|
+
if (!audio.expires_at) {
|
|
11517
|
+
return false;
|
|
11518
|
+
}
|
|
11519
|
+
const expiresAtMs = Date.parse(audio.expires_at);
|
|
11520
|
+
if (!Number.isFinite(expiresAtMs)) {
|
|
11521
|
+
return false;
|
|
11522
|
+
}
|
|
11523
|
+
return expiresAtMs - Date.now() <= EXPIRY_REFRESH_WINDOW_MS;
|
|
11524
|
+
}
|
|
11525
|
+
async function refreshAndResume() {
|
|
11526
|
+
if (!onRefresh || refreshing) {
|
|
11527
|
+
return false;
|
|
11528
|
+
}
|
|
11529
|
+
if (recoveredUrlRef.current === (audio.url ?? null)) {
|
|
11530
|
+
return false;
|
|
11531
|
+
}
|
|
11532
|
+
recoveredUrlRef.current = audio.url ?? null;
|
|
11533
|
+
pendingResumeRef.current = true;
|
|
11534
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11535
|
+
try {
|
|
11536
|
+
await Promise.resolve(onRefresh());
|
|
11537
|
+
return true;
|
|
11538
|
+
} catch {
|
|
11539
|
+
pendingResumeRef.current = false;
|
|
11540
|
+
pendingResumeTimeRef.current = null;
|
|
11541
|
+
onPlaybackError?.();
|
|
11542
|
+
return false;
|
|
11543
|
+
}
|
|
11544
|
+
}
|
|
11494
11545
|
function togglePlayback() {
|
|
11495
11546
|
const element = audioRef.current;
|
|
11496
11547
|
if (!element) return;
|
|
11497
11548
|
if (element.paused) {
|
|
11549
|
+
if (refreshing) {
|
|
11550
|
+
pendingResumeRef.current = true;
|
|
11551
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11552
|
+
return;
|
|
11553
|
+
}
|
|
11554
|
+
if (onRefresh && isUrlExpiringSoon()) {
|
|
11555
|
+
void refreshAndResume();
|
|
11556
|
+
return;
|
|
11557
|
+
}
|
|
11498
11558
|
element.play().catch(() => {
|
|
11499
11559
|
setPlaying(false);
|
|
11500
11560
|
onPlaybackError?.();
|
|
@@ -11537,7 +11597,17 @@ function NarrationPlayer({
|
|
|
11537
11597
|
onPlay: () => setPlaying(true),
|
|
11538
11598
|
onPause: () => setPlaying(false),
|
|
11539
11599
|
onEnded: () => setPlaying(false),
|
|
11540
|
-
onError: () =>
|
|
11600
|
+
onError: () => {
|
|
11601
|
+
if (onRefresh) {
|
|
11602
|
+
void refreshAndResume().then((didRefresh) => {
|
|
11603
|
+
if (!didRefresh) {
|
|
11604
|
+
onPlaybackError?.();
|
|
11605
|
+
}
|
|
11606
|
+
});
|
|
11607
|
+
return;
|
|
11608
|
+
}
|
|
11609
|
+
onPlaybackError?.();
|
|
11610
|
+
}
|
|
11541
11611
|
}
|
|
11542
11612
|
),
|
|
11543
11613
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.layout, children: [
|
|
@@ -11649,7 +11719,7 @@ function NarrationPlayer({
|
|
|
11649
11719
|
]
|
|
11650
11720
|
}
|
|
11651
11721
|
),
|
|
11652
|
-
onRefresh && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11722
|
+
onRefresh && showRefreshButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11653
11723
|
"button",
|
|
11654
11724
|
{
|
|
11655
11725
|
type: "button",
|
package/dist/index.mjs
CHANGED
|
@@ -11269,6 +11269,7 @@ function FeedbackWidget(props) {
|
|
|
11269
11269
|
] });
|
|
11270
11270
|
}
|
|
11271
11271
|
var SPEEDS = [1, 1.25, 1.5, 2];
|
|
11272
|
+
var EXPIRY_REFRESH_WINDOW_MS = 3e4;
|
|
11272
11273
|
var styles = {
|
|
11273
11274
|
root: {
|
|
11274
11275
|
borderRadius: "1.75rem",
|
|
@@ -11442,10 +11443,14 @@ function NarrationPlayer({
|
|
|
11442
11443
|
narrationLabel = "AI-Narrated",
|
|
11443
11444
|
refreshing = false,
|
|
11444
11445
|
onRefresh,
|
|
11446
|
+
showRefreshButton = false,
|
|
11445
11447
|
onPlaybackError
|
|
11446
11448
|
}) {
|
|
11447
11449
|
const audioRef = useRef(null);
|
|
11448
11450
|
const scrubRef = useRef(null);
|
|
11451
|
+
const pendingResumeRef = useRef(false);
|
|
11452
|
+
const pendingResumeTimeRef = useRef(null);
|
|
11453
|
+
const recoveredUrlRef = useRef(null);
|
|
11449
11454
|
const [playing, setPlaying] = useState(false);
|
|
11450
11455
|
const [currentTime, setCurrentTime] = useState(0);
|
|
11451
11456
|
const [duration, setDuration] = useState(audio.duration_ms ? audio.duration_ms / 1e3 : 0);
|
|
@@ -11460,10 +11465,26 @@ function NarrationPlayer({
|
|
|
11460
11465
|
useEffect(() => {
|
|
11461
11466
|
const element = audioRef.current;
|
|
11462
11467
|
if (!element) return;
|
|
11463
|
-
|
|
11468
|
+
recoveredUrlRef.current = null;
|
|
11469
|
+
const resumeTime = pendingResumeTimeRef.current;
|
|
11470
|
+
setCurrentTime(resumeTime ?? 0);
|
|
11464
11471
|
setPlaying(false);
|
|
11465
11472
|
element.pause();
|
|
11466
|
-
|
|
11473
|
+
try {
|
|
11474
|
+
element.currentTime = resumeTime ?? 0;
|
|
11475
|
+
} catch {
|
|
11476
|
+
element.currentTime = 0;
|
|
11477
|
+
}
|
|
11478
|
+
if (pendingResumeRef.current) {
|
|
11479
|
+
pendingResumeRef.current = false;
|
|
11480
|
+
pendingResumeTimeRef.current = null;
|
|
11481
|
+
element.play().catch(() => {
|
|
11482
|
+
setPlaying(false);
|
|
11483
|
+
onPlaybackError?.();
|
|
11484
|
+
});
|
|
11485
|
+
return;
|
|
11486
|
+
}
|
|
11487
|
+
pendingResumeTimeRef.current = null;
|
|
11467
11488
|
}, [audio.url]);
|
|
11468
11489
|
useEffect(() => {
|
|
11469
11490
|
const element = audioRef.current;
|
|
@@ -11471,10 +11492,49 @@ function NarrationPlayer({
|
|
|
11471
11492
|
element.playbackRate = speed;
|
|
11472
11493
|
element.preservesPitch = true;
|
|
11473
11494
|
}, [speed]);
|
|
11495
|
+
function isUrlExpiringSoon() {
|
|
11496
|
+
if (!audio.expires_at) {
|
|
11497
|
+
return false;
|
|
11498
|
+
}
|
|
11499
|
+
const expiresAtMs = Date.parse(audio.expires_at);
|
|
11500
|
+
if (!Number.isFinite(expiresAtMs)) {
|
|
11501
|
+
return false;
|
|
11502
|
+
}
|
|
11503
|
+
return expiresAtMs - Date.now() <= EXPIRY_REFRESH_WINDOW_MS;
|
|
11504
|
+
}
|
|
11505
|
+
async function refreshAndResume() {
|
|
11506
|
+
if (!onRefresh || refreshing) {
|
|
11507
|
+
return false;
|
|
11508
|
+
}
|
|
11509
|
+
if (recoveredUrlRef.current === (audio.url ?? null)) {
|
|
11510
|
+
return false;
|
|
11511
|
+
}
|
|
11512
|
+
recoveredUrlRef.current = audio.url ?? null;
|
|
11513
|
+
pendingResumeRef.current = true;
|
|
11514
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11515
|
+
try {
|
|
11516
|
+
await Promise.resolve(onRefresh());
|
|
11517
|
+
return true;
|
|
11518
|
+
} catch {
|
|
11519
|
+
pendingResumeRef.current = false;
|
|
11520
|
+
pendingResumeTimeRef.current = null;
|
|
11521
|
+
onPlaybackError?.();
|
|
11522
|
+
return false;
|
|
11523
|
+
}
|
|
11524
|
+
}
|
|
11474
11525
|
function togglePlayback() {
|
|
11475
11526
|
const element = audioRef.current;
|
|
11476
11527
|
if (!element) return;
|
|
11477
11528
|
if (element.paused) {
|
|
11529
|
+
if (refreshing) {
|
|
11530
|
+
pendingResumeRef.current = true;
|
|
11531
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11532
|
+
return;
|
|
11533
|
+
}
|
|
11534
|
+
if (onRefresh && isUrlExpiringSoon()) {
|
|
11535
|
+
void refreshAndResume();
|
|
11536
|
+
return;
|
|
11537
|
+
}
|
|
11478
11538
|
element.play().catch(() => {
|
|
11479
11539
|
setPlaying(false);
|
|
11480
11540
|
onPlaybackError?.();
|
|
@@ -11517,7 +11577,17 @@ function NarrationPlayer({
|
|
|
11517
11577
|
onPlay: () => setPlaying(true),
|
|
11518
11578
|
onPause: () => setPlaying(false),
|
|
11519
11579
|
onEnded: () => setPlaying(false),
|
|
11520
|
-
onError: () =>
|
|
11580
|
+
onError: () => {
|
|
11581
|
+
if (onRefresh) {
|
|
11582
|
+
void refreshAndResume().then((didRefresh) => {
|
|
11583
|
+
if (!didRefresh) {
|
|
11584
|
+
onPlaybackError?.();
|
|
11585
|
+
}
|
|
11586
|
+
});
|
|
11587
|
+
return;
|
|
11588
|
+
}
|
|
11589
|
+
onPlaybackError?.();
|
|
11590
|
+
}
|
|
11521
11591
|
}
|
|
11522
11592
|
),
|
|
11523
11593
|
/* @__PURE__ */ jsxs("div", { style: styles.layout, children: [
|
|
@@ -11629,7 +11699,7 @@ function NarrationPlayer({
|
|
|
11629
11699
|
]
|
|
11630
11700
|
}
|
|
11631
11701
|
),
|
|
11632
|
-
onRefresh && /* @__PURE__ */ jsx(
|
|
11702
|
+
onRefresh && showRefreshButton && /* @__PURE__ */ jsx(
|
|
11633
11703
|
"button",
|
|
11634
11704
|
{
|
|
11635
11705
|
type: "button",
|
package/package.json
CHANGED