@exode-team/react-recorder 1.1.2 → 1.1.3
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/components/AudioRecorder.styled.d.ts.map +1 -1
- package/dist/components/RecordingShell/RecordingShell.d.ts.map +1 -1
- package/dist/components/RecordingShell/RecordingShell.styled.d.ts.map +1 -1
- package/dist/components/VoiceMessagePlayer/VoiceMessagePlayer.d.ts.map +1 -1
- package/dist/components/VoiceRecorderInput/PreviewBars.d.ts +1 -1
- package/dist/components/VoiceRecorderInput/PreviewBars.d.ts.map +1 -1
- package/dist/components/VoiceRecorderInput/TimelineBars.d.ts +1 -1
- package/dist/components/VoiceRecorderInput/TimelineBars.d.ts.map +1 -1
- package/dist/components/VoiceRecorderInput/VoiceRecorderInput.d.ts.map +1 -1
- package/dist/components/VoiceRecorderInput/VoiceRecorderInput.styled.d.ts.map +1 -1
- package/dist/hooks/useAudioBlobLoader.d.ts.map +1 -1
- package/dist/index.cjs +76 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +78 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioRecorder.styled.d.ts","sourceRoot":"","sources":["../../src/components/AudioRecorder.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"AudioRecorder.styled.d.ts","sourceRoot":"","sources":["../../src/components/AudioRecorder.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,SAAS,KAKrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordingShell.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"RecordingShell.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA2BH,UAAU,KAAK;IACX,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3C;AAGD,QAAA,MAAM,cAAc,GAAI,OAAO,KAAK,QA6HnC,CAAC;AAGF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordingShell.styled.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"RecordingShell.styled.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,OAAO,KAOnB,CAAC;AAEF,eAAO,MAAM,YAAY,KAqBxB,CAAC;AAEF,eAAO,MAAM,KAAK,KAQjB,CAAC;AAEF,eAAO,MAAM,YAAY,KA2CxB,CAAC;AAEF,eAAO,MAAM,QAAQ,KAOpB,CAAC;AAEF,eAAO,MAAM,IAAI,KAMhB,CAAC;AAEF,eAAO,MAAM,GAAG,KAOf,CAAC;AAEF,eAAO,MAAM,KAAK,KAKjB,CAAC;AAEF,eAAO,MAAM,UAAU,KAyBtB,CAAC;AAEF,eAAO,MAAM,WAAW,KAMvB,CAAC;AAEF,eAAO,MAAM,OAAO,KAoBnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoiceMessagePlayer.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceMessagePlayer/VoiceMessagePlayer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAeD,QAAA,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"VoiceMessagePlayer.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceMessagePlayer/VoiceMessagePlayer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAeD,QAAA,MAAM,kBAAkB,KA8MtB,CAAC;AAGH,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -10,7 +10,7 @@ interface PreviewBarsProps {
|
|
|
10
10
|
recordingTime: number;
|
|
11
11
|
previewLevels: number[];
|
|
12
12
|
timelineLevels: number[];
|
|
13
|
-
|
|
13
|
+
visibleBarsCount: number;
|
|
14
14
|
}
|
|
15
15
|
declare const PreviewBars: (props: PreviewBarsProps) => any;
|
|
16
16
|
export { PreviewBars };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreviewBars.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/PreviewBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,gBAAgB;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,
|
|
1
|
+
{"version":3,"file":"PreviewBars.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/PreviewBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,gBAAgB;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAGD,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,QA0E3C,CAAC;AAGF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimelineBars.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/TimelineBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,iBAAiB;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,
|
|
1
|
+
{"version":3,"file":"TimelineBars.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/TimelineBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,iBAAiB;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAGD,QAAA,MAAM,YAAY,GAAI,OAAO,iBAAiB,QAkC7C,CAAC;AAGF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoiceRecorderInput.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/VoiceRecorderInput.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"VoiceRecorderInput.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/VoiceRecorderInput.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAuBrE,UAAU,KAAK;IACX,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAGD,QAAA,MAAM,kBAAkB,GAAI,OAAO,KAAK,QAmIvC,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoiceRecorderInput.styled.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/VoiceRecorderInput.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,OAAO,KAOnB,CAAC;AAEF,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"VoiceRecorderInput.styled.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceRecorderInput/VoiceRecorderInput.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,OAAO,KAOnB,CAAC;AAEF,eAAO,MAAM,YAAY,KAcxB,CAAC;AAEF,eAAO,MAAM,WAAW,KASvB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,UAAU,KAMtB,CAAC;AAEF,eAAO,MAAM,UAAU,KA0BtB,CAAC;AAEF,eAAO,MAAM,YAAY,KAUxB,CAAC;AAEF,eAAO,MAAM,KAAK,KAMjB,CAAC;AAEF,eAAO,MAAM,UAAU,KAuBtB,CAAC;AAEF,eAAO,MAAM,YAAY,KAqBxB,CAAC;AAEF,eAAO,MAAM,eAAe,KAqB3B,CAAC;AAEF,eAAO,MAAM,WAAW,KAcvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioBlobLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioBlobLoader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,UAAU,yBAAyB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,iBAAiB,CAAC;CACxC;AAED,UAAU,wBAAwB;IAC9B,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,QAAA,MAAM,kBAAkB,GAAI,SAAS,yBAAyB,KAAG,
|
|
1
|
+
{"version":3,"file":"useAudioBlobLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioBlobLoader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,UAAU,yBAAyB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,iBAAiB,CAAC;CACxC;AAED,UAAU,wBAAwB;IAC9B,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,QAAA,MAAM,kBAAkB,GAAI,SAAS,yBAAyB,KAAG,wBAoIhE,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -784,6 +784,7 @@ const useAudioBlobLoader = (options) => {
|
|
|
784
784
|
const audioRef = React.useRef(null);
|
|
785
785
|
const objectUrlRef = React.useRef(null);
|
|
786
786
|
const abortControllerRef = React.useRef(null);
|
|
787
|
+
const failedSrcRef = React.useRef(null);
|
|
787
788
|
const callbacksRef = React.useRef(playbackCallbacks);
|
|
788
789
|
callbacksRef.current = playbackCallbacks;
|
|
789
790
|
const createAudioFromBlob = React.useCallback((blob) => {
|
|
@@ -820,7 +821,7 @@ const useAudioBlobLoader = (options) => {
|
|
|
820
821
|
}, [waveformData, createAudioFromBlob]);
|
|
821
822
|
const ensureAudioLoaded = React.useCallback(async () => {
|
|
822
823
|
var _a;
|
|
823
|
-
if (audioRef.current) {
|
|
824
|
+
if (audioRef.current || failedSrcRef.current === src) {
|
|
824
825
|
return;
|
|
825
826
|
}
|
|
826
827
|
if (preloadedBlob) {
|
|
@@ -851,6 +852,7 @@ const useAudioBlobLoader = (options) => {
|
|
|
851
852
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
852
853
|
return;
|
|
853
854
|
}
|
|
855
|
+
failedSrcRef.current = src;
|
|
854
856
|
console.warn('[voice-player] Failed to load audio', error);
|
|
855
857
|
}
|
|
856
858
|
finally {
|
|
@@ -861,6 +863,7 @@ const useAudioBlobLoader = (options) => {
|
|
|
861
863
|
}, [src, waveformData, preloadedBlob, mountFromBlob, createAudioFromBlob]);
|
|
862
864
|
/** Cleanup on src change or unmount */
|
|
863
865
|
React.useEffect(() => {
|
|
866
|
+
failedSrcRef.current = null;
|
|
864
867
|
return () => {
|
|
865
868
|
var _a;
|
|
866
869
|
(_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
|
|
@@ -1190,7 +1193,6 @@ const useAudioRecorderHandlers = (options) => {
|
|
|
1190
1193
|
const Container = styled.div `
|
|
1191
1194
|
position: relative;
|
|
1192
1195
|
width: 100%;
|
|
1193
|
-
padding: 16px;
|
|
1194
1196
|
transition: color 200ms ease, background-color 200ms ease;
|
|
1195
1197
|
color: var(--text_primary, #0a0a0a);
|
|
1196
1198
|
`;
|
|
@@ -1275,29 +1277,28 @@ const Wrapper$1 = styled.div `
|
|
|
1275
1277
|
gap: 12px;
|
|
1276
1278
|
padding: 10px 14px;
|
|
1277
1279
|
border-radius: 9999px;
|
|
1278
|
-
background: var(--
|
|
1279
|
-
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text_primary, #0a0a0a) 6%, transparent);
|
|
1280
|
+
background: var(--background_hover, color-mix(in srgb, var(--text_primary, #0a0a0a) 6%, transparent));
|
|
1280
1281
|
`;
|
|
1281
1282
|
const CancelButton$1 = styled.button `
|
|
1282
|
-
width:
|
|
1283
|
-
height:
|
|
1283
|
+
width: 38px;
|
|
1284
|
+
height: 38px;
|
|
1284
1285
|
display: inline-flex;
|
|
1285
1286
|
align-items: center;
|
|
1286
1287
|
justify-content: center;
|
|
1287
|
-
border-radius:
|
|
1288
|
-
background: transparent;
|
|
1288
|
+
border-radius: 19px;
|
|
1289
|
+
background: color-mix(in srgb, var(--exode_red) 10%, transparent);
|
|
1289
1290
|
border: 0;
|
|
1291
|
+
flex-shrink: 0;
|
|
1290
1292
|
color: color-mix(in srgb, var(--text_primary, #0a0a0a) 54%, transparent);
|
|
1291
1293
|
cursor: pointer;
|
|
1292
|
-
transition:
|
|
1294
|
+
transition: transform 160ms ease;
|
|
1293
1295
|
|
|
1294
|
-
&:hover {
|
|
1295
|
-
|
|
1296
|
-
color: color-mix(in srgb, var(--text_primary, #0a0a0a) 76%, transparent);
|
|
1296
|
+
&:hover:not(:disabled) {
|
|
1297
|
+
transform: translateY(-1px);
|
|
1297
1298
|
}
|
|
1298
1299
|
|
|
1299
|
-
&:active {
|
|
1300
|
-
|
|
1300
|
+
&:active:not(:disabled) {
|
|
1301
|
+
transform: translateY(0);
|
|
1301
1302
|
}
|
|
1302
1303
|
`;
|
|
1303
1304
|
const Track = styled.div `
|
|
@@ -1305,7 +1306,7 @@ const Track = styled.div `
|
|
|
1305
1306
|
display: flex;
|
|
1306
1307
|
align-items: center;
|
|
1307
1308
|
gap: 12px;
|
|
1308
|
-
padding: 8px
|
|
1309
|
+
padding: 8px 10px;
|
|
1309
1310
|
border-radius: 9999px;
|
|
1310
1311
|
background: color-mix(in srgb, var(--text_primary, #0a0a0a) 10%, transparent);
|
|
1311
1312
|
`;
|
|
@@ -1469,7 +1470,9 @@ const RecordingShell = (props) => {
|
|
|
1469
1470
|
return formatTime(0);
|
|
1470
1471
|
}, [formatTime, hasRecording, isPlaying, playbackDuration, playbackTime, recordingTime]);
|
|
1471
1472
|
const recordButtonDisabled = isSending;
|
|
1472
|
-
const recordButtonIcon = !isRecording || isPaused
|
|
1473
|
+
const recordButtonIcon = !isRecording || isPaused
|
|
1474
|
+
? jsxRuntime.jsx(icons.Icon16Microphone, { width: 24, height: 24 })
|
|
1475
|
+
: jsxRuntime.jsx(icons.Icon16Pause, { width: 24, height: 24 });
|
|
1473
1476
|
const recordButtonVariant = !isRecording || isPaused ? 'resume' : 'record';
|
|
1474
1477
|
const recordButtonAria = !isRecording
|
|
1475
1478
|
? startAriaLabel
|
|
@@ -1478,14 +1481,16 @@ const RecordingShell = (props) => {
|
|
|
1478
1481
|
: pauseRecordingAriaLabel || stopAriaLabel;
|
|
1479
1482
|
const canShowPlayback = !isRecording || isPaused;
|
|
1480
1483
|
const playbackDisabled = !hasRecording && !isRecording;
|
|
1481
|
-
const playbackIcon = isPlaying
|
|
1484
|
+
const playbackIcon = isPlaying
|
|
1485
|
+
? jsxRuntime.jsx(icons.Icon16Pause, { width: 24, height: 24 })
|
|
1486
|
+
: jsxRuntime.jsx(icons.Icon16Play, { width: 24, height: 24 });
|
|
1482
1487
|
const playbackAria = isPlaying ? pausePlaybackAriaLabel : playAriaLabel;
|
|
1483
1488
|
const sendDisabled = isSending || (!hasRecording && !isRecording);
|
|
1484
|
-
return (jsxRuntime.jsxs(Wrapper$1, { children: [jsxRuntime.jsx(CancelButton$1, { type: "button", onClick: onCancel, "aria-label": cancelAriaLabel, children: jsxRuntime.jsx(icons.
|
|
1489
|
+
return (jsxRuntime.jsxs(Wrapper$1, { children: [jsxRuntime.jsx(CancelButton$1, { type: "button", onClick: onCancel, "aria-label": cancelAriaLabel, children: jsxRuntime.jsx(icons.Icon28DeleteOutlineAndroid, { fill: "var(--exode_red)", width: 24, height: 24, style: { minWidth: 24 } }) }), jsxRuntime.jsxs(Track, { children: [jsxRuntime.jsx(CircleButton, { type: "button", "$variant": recordButtonVariant, onClick: onRecordToggle, "aria-label": recordButtonAria, disabled: recordButtonDisabled, children: recordButtonIcon }), !canShowPlayback ? null : (jsxRuntime.jsx(CircleButton, { type: "button", "$variant": "play", onClick: onTogglePlayback, "aria-label": playbackAria, disabled: playbackDisabled, children: playbackIcon })), jsxRuntime.jsx(Waveform, { "$expanded": canShowPlayback, children: jsxRuntime.jsx(WaveformBars, { values: waveformValues, divider: 100, scale: 42, minHeight: 6, styleInterpolator: ({ normalized }) => ({
|
|
1485
1490
|
height: `${12 + normalized / 2}px`,
|
|
1486
1491
|
maxHeight: '34px',
|
|
1487
1492
|
opacity: 0.38 + Math.min(0.5, normalized / 120),
|
|
1488
|
-
}) }) }), jsxRuntime.jsx(Timer$1, { children: displayTime })] }), jsxRuntime.jsx(SendButton$1, { type: "button", onClick: onSend, disabled: sendDisabled, "aria-label": sendAriaLabel, children: isSending ? (jsxRuntime.jsx(SpinnerSlot, { children: jsxRuntime.jsx(Spinner, {}) })) : (jsxRuntime.jsx(icons.Icon28SendOutline, { width:
|
|
1493
|
+
}) }) }), jsxRuntime.jsx(Timer$1, { children: displayTime })] }), jsxRuntime.jsx(SendButton$1, { type: "button", onClick: onSend, disabled: sendDisabled, "aria-label": sendAriaLabel, children: isSending ? (jsxRuntime.jsx(SpinnerSlot, { children: jsxRuntime.jsx(Spinner, {}) })) : (jsxRuntime.jsx(icons.Icon28SendOutline, { width: 24, height: 24 })) })] }));
|
|
1489
1494
|
};
|
|
1490
1495
|
|
|
1491
1496
|
/**
|
|
@@ -1745,8 +1750,8 @@ const useVoiceRecorderInput = (options) => {
|
|
|
1745
1750
|
|
|
1746
1751
|
const PreviewBars = (props) => {
|
|
1747
1752
|
var _a, _b;
|
|
1748
|
-
const { isPlaying, playbackTime, lastDuration, previewLevels, recordingTime, timelineLevels,
|
|
1749
|
-
const maxBars =
|
|
1753
|
+
const { isPlaying, playbackTime, lastDuration, previewLevels, recordingTime, timelineLevels, visibleBarsCount, } = props;
|
|
1754
|
+
const maxBars = visibleBarsCount;
|
|
1750
1755
|
const sourceLevels = timelineLevels.length > 0
|
|
1751
1756
|
? timelineLevels
|
|
1752
1757
|
: previewLevels;
|
|
@@ -1790,8 +1795,8 @@ const PreviewBars = (props) => {
|
|
|
1790
1795
|
};
|
|
1791
1796
|
|
|
1792
1797
|
const TimelineBars = (props) => {
|
|
1793
|
-
const { timelineLevels,
|
|
1794
|
-
const maxBars =
|
|
1798
|
+
const { timelineLevels, visibleBarsCount } = props;
|
|
1799
|
+
const maxBars = visibleBarsCount;
|
|
1795
1800
|
const visible = timelineLevels.slice(-maxBars);
|
|
1796
1801
|
const padded = [
|
|
1797
1802
|
...visible,
|
|
@@ -1836,15 +1841,11 @@ const CancelButton = styled.button `
|
|
|
1836
1841
|
border-radius: 16px;
|
|
1837
1842
|
background: transparent;
|
|
1838
1843
|
border: 0;
|
|
1844
|
+
margin-right: 4px;
|
|
1839
1845
|
flex-shrink: 0;
|
|
1840
1846
|
color: color-mix(in srgb, var(--text_primary, #0a0a0a) 45%, transparent);
|
|
1841
1847
|
cursor: pointer;
|
|
1842
1848
|
transition: color 160ms ease, background-color 160ms ease;
|
|
1843
|
-
|
|
1844
|
-
&:hover {
|
|
1845
|
-
background-color: color-mix(in srgb, var(--text_primary, #0a0a0a) 8%, transparent);
|
|
1846
|
-
color: color-mix(in srgb, var(--text_primary, #0a0a0a) 72%, transparent);
|
|
1847
|
-
}
|
|
1848
1849
|
`;
|
|
1849
1850
|
const RecordTrack = styled.div `
|
|
1850
1851
|
flex: 1;
|
|
@@ -1860,7 +1861,8 @@ const RecordTrack = styled.div `
|
|
|
1860
1861
|
const ButtonSlot = styled.div `
|
|
1861
1862
|
display: flex;
|
|
1862
1863
|
align-items: center;
|
|
1863
|
-
gap:
|
|
1864
|
+
gap: 4px;
|
|
1865
|
+
padding: 2px;
|
|
1864
1866
|
flex-shrink: 0;
|
|
1865
1867
|
`;
|
|
1866
1868
|
const StopButton = styled.button `
|
|
@@ -1997,19 +1999,39 @@ const VoiceRecorderInput = (props) => {
|
|
|
1997
1999
|
const waveformRef = React.useRef(null);
|
|
1998
2000
|
const { recorder, isSending, isPreview, timelineLevels, lastDurationRef, handleResume, handlePause, handleCancel, handleSendRequest, } = useVoiceRecorderInput(inputOptions);
|
|
1999
2001
|
const { isPlaying, isRecording, recordingTime, hasRecording, previewLevels, playbackTime, formatTime, togglePlayback, } = recorder;
|
|
2000
|
-
const
|
|
2002
|
+
const [visibleBarsCount, setVisibleBarsCount] = React.useState(0);
|
|
2003
|
+
const measureBars = () => {
|
|
2001
2004
|
const el = waveformRef.current;
|
|
2002
2005
|
if (!el) {
|
|
2003
|
-
return
|
|
2006
|
+
return;
|
|
2004
2007
|
}
|
|
2005
|
-
|
|
2008
|
+
setVisibleBarsCount(Math.floor(el.clientWidth / (TIMELINE_BAR_WIDTH + TIMELINE_BAR_GAP)));
|
|
2009
|
+
};
|
|
2010
|
+
/** Sync recalc before paint — catches layout shifts from button changes */
|
|
2011
|
+
React.useLayoutEffect(measureBars);
|
|
2012
|
+
/** ResizeObserver for external size changes (window resize, container resize) */
|
|
2013
|
+
React.useEffect(() => {
|
|
2014
|
+
const el = waveformRef.current;
|
|
2015
|
+
if (!el) {
|
|
2016
|
+
return;
|
|
2017
|
+
}
|
|
2018
|
+
let rafId = 0;
|
|
2019
|
+
const observer = new ResizeObserver(() => {
|
|
2020
|
+
cancelAnimationFrame(rafId);
|
|
2021
|
+
rafId = requestAnimationFrame(measureBars);
|
|
2022
|
+
});
|
|
2023
|
+
observer.observe(el);
|
|
2024
|
+
return () => {
|
|
2025
|
+
cancelAnimationFrame(rafId);
|
|
2026
|
+
observer.disconnect();
|
|
2027
|
+
};
|
|
2006
2028
|
}, []);
|
|
2007
2029
|
const displayTime = (isPreview && isPlaying)
|
|
2008
2030
|
? formatTime(playbackTime)
|
|
2009
2031
|
: formatTime(recordingTime || lastDurationRef.current);
|
|
2010
|
-
return (jsxRuntime.jsxs(Wrapper, { className: className, children: [jsxRuntime.jsx(CancelButton, { type: "button", onClick: handleCancel, "aria-label": "Cancel", children: jsxRuntime.jsx(icons.
|
|
2032
|
+
return (jsxRuntime.jsxs(Wrapper, { className: className, children: [jsxRuntime.jsx(CancelButton, { type: "button", onClick: handleCancel, "aria-label": "Cancel", children: jsxRuntime.jsx(icons.Icon28DeleteOutlineAndroid, { fill: "var(--exode_red)", width: 28, height: 28, style: { minWidth: 28 } }) }), jsxRuntime.jsxs(RecordTrack, { children: [jsxRuntime.jsx(ButtonSlot, { children: isPreview ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MicIndicator, { type: "button", onClick: handleResume, "aria-label": "Resume recording", children: jsxRuntime.jsx(icons.Icon20Voice, { width: 14, height: 14 }) }), jsxRuntime.jsx(PlayPauseButton, { type: "button", onClick: togglePlayback, "aria-label": isPlaying ? 'Pause' : 'Play', children: isPlaying
|
|
2011
2033
|
? jsxRuntime.jsx(icons.Icon16Pause, { width: 14, height: 14 })
|
|
2012
|
-
: jsxRuntime.jsx(icons.Icon16Play, { width: 14, height: 14 }) })] })) : (jsxRuntime.jsx(StopButton, { type: "button", onClick: handlePause, "aria-label": "Pause recording", children: jsxRuntime.jsx(icons.
|
|
2034
|
+
: jsxRuntime.jsx(icons.Icon16Play, { width: 14, height: 14 }) })] })) : (jsxRuntime.jsx(StopButton, { type: "button", onClick: handlePause, "aria-label": "Pause recording", children: jsxRuntime.jsx(icons.Icon16Pause, { width: 14, height: 14 }) })) }), jsxRuntime.jsx(WaveformArea, { ref: waveformRef, children: isPreview ? (jsxRuntime.jsx(PreviewBars, { timelineLevels: timelineLevels, previewLevels: previewLevels, isPlaying: isPlaying, playbackTime: playbackTime, recordingTime: recordingTime, lastDuration: lastDurationRef.current, visibleBarsCount: visibleBarsCount })) : (jsxRuntime.jsx(TimelineBars, { timelineLevels: timelineLevels, visibleBarsCount: visibleBarsCount })) }), jsxRuntime.jsx(Timer, { children: displayTime })] }), jsxRuntime.jsx(SendButton, { type: "button", onClick: handleSendRequest, disabled: isSending || (!hasRecording && !isRecording), "aria-label": "Send", children: isSending ? (jsxRuntime.jsx(SpinnerIcon, {})) : (jsxRuntime.jsx(icons.Icon28SendOutline, {})) })] }));
|
|
2013
2035
|
};
|
|
2014
2036
|
|
|
2015
2037
|
/**
|
|
@@ -2185,11 +2207,29 @@ const VoiceMessagePlayer = React.forwardRef((props, ref) => {
|
|
|
2185
2207
|
return VoicePlaybackChain.register(chainId, () => play());
|
|
2186
2208
|
}
|
|
2187
2209
|
}, [chainId, play]);
|
|
2188
|
-
|
|
2189
|
-
React.useLayoutEffect(() => {
|
|
2210
|
+
const measureTrackWidth = () => {
|
|
2190
2211
|
if (trackRef.current) {
|
|
2191
2212
|
setTrackWidth(trackRef.current.clientWidth);
|
|
2192
2213
|
}
|
|
2214
|
+
};
|
|
2215
|
+
/** Sync recalc before paint — catches layout shifts */
|
|
2216
|
+
React.useLayoutEffect(measureTrackWidth);
|
|
2217
|
+
/** ResizeObserver for external size changes (window resize, container resize) */
|
|
2218
|
+
React.useEffect(() => {
|
|
2219
|
+
const el = trackRef.current;
|
|
2220
|
+
if (!el) {
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
let rafId = 0;
|
|
2224
|
+
const observer = new ResizeObserver(() => {
|
|
2225
|
+
cancelAnimationFrame(rafId);
|
|
2226
|
+
rafId = requestAnimationFrame(measureTrackWidth);
|
|
2227
|
+
});
|
|
2228
|
+
observer.observe(el);
|
|
2229
|
+
return () => {
|
|
2230
|
+
cancelAnimationFrame(rafId);
|
|
2231
|
+
observer.disconnect();
|
|
2232
|
+
};
|
|
2193
2233
|
}, []);
|
|
2194
2234
|
const displayTime = isPlaying
|
|
2195
2235
|
? formatTime(currentTime)
|