@exode-team/react-recorder 1.1.7 → 1.1.8

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.
@@ -12,7 +12,7 @@ interface Props extends Partial<RecorderOptionOverrides> {
12
12
  uploadId?: string;
13
13
  className?: string;
14
14
  onUploadError?: (error: unknown) => void;
15
- onUploaded?: (file: Partial<StorageFileEntity>) => void | Promise<void>;
15
+ onUploaded?: (file: Partial<StorageFileEntity>, duration: number) => void | Promise<void>;
16
16
  }
17
17
  declare const AudioRecorder: (props: Props) => any;
18
18
  export { AudioRecorder };
@@ -1 +1 @@
1
- {"version":3,"file":"AudioRecorder.d.ts","sourceRoot":"","sources":["../../src/components/AudioRecorder.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAErF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC/B,MAAM,UAAU,CAAC;AAGlB,KAAK,uBAAuB,GAAG,IAAI,CAC/B,uBAAuB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EACnD,UAAU,GAAG,YAAY,GAAG,UAAU,CACzC,CAAC;AAEF,UAAU,KAAM,SAAQ,OAAO,CAAC,uBAAuB,CAAC;IACpD,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAGD,QAAA,MAAM,aAAa,GAAI,OAAO,KAAK,QAsHlC,CAAC;AAGF,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"AudioRecorder.d.ts","sourceRoot":"","sources":["../../src/components/AudioRecorder.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAErF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC/B,MAAM,UAAU,CAAC;AAGlB,KAAK,uBAAuB,GAAG,IAAI,CAC/B,uBAAuB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EACnD,UAAU,GAAG,YAAY,GAAG,UAAU,CACzC,CAAC;AAEF,UAAU,KAAM,SAAQ,OAAO,CAAC,uBAAuB,CAAC;IACpD,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7F;AAGD,QAAA,MAAM,aAAa,GAAI,OAAO,KAAK,QAwHlC,CAAC;AAGF,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -8,6 +8,7 @@ interface Props {
8
8
  isPaused: boolean;
9
9
  hasRecording: boolean;
10
10
  isPlaying: boolean;
11
+ lastDuration: number;
11
12
  recordingTime: number;
12
13
  playbackTime: number;
13
14
  playbackDuration: number;
@@ -1 +1 @@
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
+ {"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,YAAY,EAAE,MAAM,CAAC;IACrB,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,QA+JnC,CAAC;AAGF,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -8,8 +8,6 @@ export declare const CancelButton: any;
8
8
  export declare const Track: any;
9
9
  export declare const CircleButton: any;
10
10
  export declare const Waveform: any;
11
- export declare const Bars: any;
12
- export declare const Bar: any;
13
11
  export declare const Timer: any;
14
12
  export declare const SendButton: any;
15
13
  export declare const SpinnerSlot: any;
@@ -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,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
+ {"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,KAAK,KAKjB,CAAC;AAEF,eAAO,MAAM,UAAU,KAyBtB,CAAC;AAEF,eAAO,MAAM,WAAW,KAMvB,CAAC;AAEF,eAAO,MAAM,OAAO,KAoBnB,CAAC"}
@@ -8,11 +8,15 @@ interface Props {
8
8
  scale?: number;
9
9
  divider?: number;
10
10
  values: number[];
11
+ progress?: number;
11
12
  minHeight?: number;
12
13
  styleInterpolator?: (context: {
13
14
  normalized: number;
14
15
  height: number;
15
16
  index: number;
17
+ progress: number;
18
+ barProgress: number;
19
+ isPlayed: boolean;
16
20
  }) => React.CSSProperties;
17
21
  }
18
22
  declare const WaveformBars: (props: Props) => any;
@@ -1 +1 @@
1
- {"version":3,"file":"WaveformBars.d.ts","sourceRoot":"","sources":["../../../src/components/WaveformBars/WaveformBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,UAAU,KAAK;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACjB,KAAK,KAAK,CAAC,aAAa,CAAC;CAC7B;AAGD,QAAA,MAAM,YAAY,GAAI,OAAO,KAAK,QA0BjC,CAAC;AAGF,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"WaveformBars.d.ts","sourceRoot":"","sources":["../../../src/components/WaveformBars/WaveformBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,UAAU,KAAK;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC;KACrB,KAAK,KAAK,CAAC,aAAa,CAAC;CAC7B;AAGD,QAAA,MAAM,YAAY,GAAI,OAAO,KAAK,QAoCjC,CAAC;AAGF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const Bars: any;
2
+ export declare const Bar: any;
3
+ //# sourceMappingURL=WaveformBars.styled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WaveformBars.styled.d.ts","sourceRoot":"","sources":["../../../src/components/WaveformBars/WaveformBars.styled.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,IAAI,KAMhB,CAAC;AAEF,eAAO,MAAM,GAAG,KAOf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioRecorderHandlers.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioRecorderHandlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAG7E,UAAU,+BAA+B;IACrC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAGD,QAAA,MAAM,wBAAwB,GAAI,SAAS,+BAA+B;;;;;;CA2KzE,CAAC;AAGF,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"useAudioRecorderHandlers.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioRecorderHandlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAG7E,UAAU,+BAA+B;IACrC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAGD,QAAA,MAAM,wBAAwB,GAAI,SAAS,+BAA+B;;;;;;CAuKzE,CAAC;AAGF,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useMediaRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useMediaRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGvD,UAAU,sBAAsB;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,QAAA,MAAM,gBAAgB,GAAI,WAAW,sBAAsB,KAAG,sBAkI7D,CAAC;AAGF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"useMediaRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useMediaRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGvD,UAAU,sBAAsB;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,QAAA,MAAM,gBAAgB,GAAI,WAAW,sBAAsB,KAAG,sBAsI7D,CAAC;AAGF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -9,8 +9,9 @@ interface UseRecordingSenderOptions<TFile> {
9
9
  mimeType: string;
10
10
  audioBlob: Blob | null;
11
11
  uploadId: string;
12
+ getDurationMs: () => number;
12
13
  uploader?: UploadStrategy<TFile>;
13
- onUploaded: (file: TFile) => void | Promise<void>;
14
+ onUploaded: (file: TFile, duration: number) => void | Promise<void>;
14
15
  deleteRecording: () => void;
15
16
  autoResetAfterUpload: boolean;
16
17
  onRecordingError?: (error: unknown) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useRecordingSender.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingSender.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,yBAAyB,CAAC,KAAK;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IACjC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAGD,QAAA,MAAM,kBAAkB,GAAI,KAAK,GAAG,OAAO,EAAE,SAAS,yBAAyB,CAAC,KAAK,CAAC;;CA0DrF,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"useRecordingSender.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingSender.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,yBAAyB,CAAC,KAAK;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IACjC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAGD,QAAA,MAAM,kBAAkB,GAAI,KAAK,GAAG,OAAO,EAAE,SAAS,yBAAyB,CAAC,KAAK,CAAC;;CA+DrF,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -5,6 +5,8 @@
5
5
  */
6
6
  interface UseRecordingTimingResult {
7
7
  recordingTime: number;
8
+ lastDuration: number;
9
+ getElapsedMs: () => number;
8
10
  pauseSession: () => void;
9
11
  resetSession: () => void;
10
12
  resumeSession: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useRecordingTiming.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingTiming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,wBAAwB;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,kBAAkB,QAAO,wBAgF9B,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"useRecordingTiming.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingTiming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,wBAAwB;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,kBAAkB,QAAO,wBAwG9B,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGhF,iBAAS,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,uBAAuB,CAAC,KAAK,CAAC,GAAG,sBAAsB,CAuMxG;AAGD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"useVoiceRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGhF,iBAAS,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,uBAAuB,CAAC,KAAK,CAAC,GAAG,sBAAsB,CA2MxG;AAGD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -6,7 +6,7 @@
6
6
  import type { UploadStrategy } from '../types';
7
7
  interface UseVoiceRecorderInputOptions {
8
8
  uploader?: UploadStrategy<unknown>;
9
- onUploaded?: (file: unknown) => void | Promise<void>;
9
+ onUploaded?: (file: unknown, duration: number) => void | Promise<void>;
10
10
  onSend?: (file: File, duration: number) => void | Promise<void>;
11
11
  onError?: (error: unknown) => void;
12
12
  onCancel?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceRecorderInput.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorderInput.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,4BAA4B;IAClC,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,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,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,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;CACrB;AAGD,QAAA,MAAM,qBAAqB,GAAI,SAAS,4BAA4B;;;;;;;;;;CA6MnE,CAAC;AAGF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"useVoiceRecorderInput.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorderInput.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,4BAA4B;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,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,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,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;CACrB;AAGD,QAAA,MAAM,qBAAqB,GAAI,SAAS,4BAA4B;;;;;;;;;;CA6MnE,CAAC;AAGF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
package/dist/index.cjs CHANGED
@@ -276,6 +276,9 @@ const useMediaRecorder = (callbacks) => {
276
276
  if (!mediaRecorderRef.current || !isRecording) {
277
277
  return;
278
278
  }
279
+ if (mediaRecorderRef.current.state === 'paused') {
280
+ mediaRecorderRef.current.resume();
281
+ }
279
282
  mediaRecorderRef.current.stop();
280
283
  }, [isRecording]);
281
284
  const cancelRecording = React.useCallback(() => {
@@ -434,6 +437,7 @@ const useAudioPlayback = () => {
434
437
  * @author: exode <hello@exode.ru>
435
438
  */
436
439
  const useRecordingTiming = () => {
440
+ const [lastDuration, setLastDuration] = React.useState(0);
437
441
  const [recordingTime, setRecordingTime] = React.useState(0);
438
442
  const timerRef = React.useRef(null);
439
443
  const recordingStartRef = React.useRef(null);
@@ -461,6 +465,7 @@ const useRecordingTiming = () => {
461
465
  const startNewSession = React.useCallback(() => {
462
466
  recordingAccumulatedRef.current = 0;
463
467
  setRecordingTime(0);
468
+ setLastDuration(0);
464
469
  recordingStartRef.current = performance.now();
465
470
  startTicker();
466
471
  }, [startTicker]);
@@ -478,7 +483,21 @@ const useRecordingTiming = () => {
478
483
  setRecordingTime(roundTo(recordingAccumulatedRef.current));
479
484
  stopTicker();
480
485
  }, [stopTicker]);
486
+ const getElapsedMs = React.useCallback(() => {
487
+ const accumulated = recordingAccumulatedRef.current;
488
+ const elapsed = recordingStartRef.current !== null
489
+ ? (performance.now() - recordingStartRef.current) / 1000 + accumulated
490
+ : accumulated;
491
+ return Math.round(elapsed * 1000);
492
+ }, []);
481
493
  const resetSession = React.useCallback(() => {
494
+ const accumulated = recordingAccumulatedRef.current;
495
+ const elapsed = recordingStartRef.current !== null
496
+ ? (performance.now() - recordingStartRef.current) / 1000 + accumulated
497
+ : accumulated;
498
+ if (elapsed > 0) {
499
+ setLastDuration(roundTo(elapsed));
500
+ }
482
501
  stopTicker();
483
502
  recordingStartRef.current = null;
484
503
  recordingAccumulatedRef.current = 0;
@@ -490,6 +509,8 @@ const useRecordingTiming = () => {
490
509
  };
491
510
  }, [stopTicker]);
492
511
  return {
512
+ lastDuration,
513
+ getElapsedMs,
493
514
  pauseSession,
494
515
  resetSession,
495
516
  recordingTime,
@@ -591,7 +612,7 @@ const useRecorderVisualization = () => {
591
612
  * @author: exode <hello@exode.ru>
592
613
  */
593
614
  const useRecordingSender = (options) => {
594
- const { uploader, fileName, mimeType, uploadId, audioBlob, onUploaded, onRecordingError, deleteRecording, autoResetAfterUpload, } = options;
615
+ const { uploader, fileName, mimeType, uploadId, audioBlob, onUploaded, getDurationMs, onRecordingError, deleteRecording, autoResetAfterUpload, } = options;
595
616
  const sendRecording = React.useCallback(async () => {
596
617
  if (!audioBlob) {
597
618
  const error = new Error('Voice recording is not available');
@@ -604,11 +625,13 @@ const useRecordingSender = (options) => {
604
625
  throw error;
605
626
  }
606
627
  try {
628
+ const durationMs = getDurationMs();
629
+ const durationSec = durationMs / 1000;
607
630
  const file = new File([audioBlob], fileName, {
608
631
  type: audioBlob.type || mimeType,
609
632
  });
610
633
  const uploaded = await uploader(file, { uploadId });
611
- await onUploaded(uploaded);
634
+ await onUploaded(uploaded, durationSec);
612
635
  if (autoResetAfterUpload) {
613
636
  deleteRecording();
614
637
  }
@@ -624,8 +647,9 @@ const useRecordingSender = (options) => {
624
647
  audioBlob,
625
648
  mimeType,
626
649
  onUploaded,
627
- onRecordingError,
650
+ getDurationMs,
628
651
  deleteRecording,
652
+ onRecordingError,
629
653
  autoResetAfterUpload,
630
654
  ]);
631
655
  return { sendRecording };
@@ -641,7 +665,7 @@ function useVoiceRecorder(props) {
641
665
  const [audioBlob, setAudioBlob] = React.useState(null);
642
666
  const { audioURL, isPlaying, mountBlob, playbackTime, stopPlayback, resetPlayback, togglePlayback: _togglePlayback, playbackDuration, } = useAudioPlayback();
643
667
  const { audioLevels, previewLevels, resetAudioLevels, stopVisualization, resetPreviewLevels, resumeVisualization, cleanupVisualization, generatePreviewLevels, initializeVisualization, } = useRecorderVisualization();
644
- const { recordingTime, pauseSession, resetSession, resumeSession, startNewSession, } = useRecordingTiming();
668
+ const { lastDuration, getElapsedMs, recordingTime, pauseSession, resetSession, resumeSession, startNewSession, } = useRecordingTiming();
645
669
  const resetCurrentRecording = React.useCallback((opts) => {
646
670
  var _a;
647
671
  setAudioBlob(null);
@@ -669,10 +693,11 @@ function useVoiceRecorder(props) {
669
693
  mimeType,
670
694
  uploadId,
671
695
  uploader,
672
- autoResetAfterUpload,
673
696
  onUploaded,
674
- onRecordingError,
675
697
  deleteRecording,
698
+ onRecordingError,
699
+ autoResetAfterUpload,
700
+ getDurationMs: getElapsedMs,
676
701
  });
677
702
  const mountRecordingBlob = React.useCallback((blob) => {
678
703
  setAudioBlob(blob);
@@ -755,6 +780,7 @@ function useVoiceRecorder(props) {
755
780
  isPlaying,
756
781
  isRecording,
757
782
  audioLevels,
783
+ lastDuration,
758
784
  playbackTime,
759
785
  recordingTime,
760
786
  previewLevels,
@@ -1101,9 +1127,6 @@ const useAudioRecorderHandlers = (options) => {
1101
1127
  toggleRecordingPause,
1102
1128
  ]);
1103
1129
  const handleSend = React.useCallback(async () => {
1104
- if (isSending) {
1105
- return;
1106
- }
1107
1130
  shouldSendAfterStopRef.current = false;
1108
1131
  setIsSending(true);
1109
1132
  try {
@@ -1120,7 +1143,6 @@ const useAudioRecorderHandlers = (options) => {
1120
1143
  setIsSending(false);
1121
1144
  }
1122
1145
  }, [
1123
- isSending,
1124
1146
  stopPlayback,
1125
1147
  onUploadError,
1126
1148
  sendRecording,
@@ -1131,6 +1153,7 @@ const useAudioRecorderHandlers = (options) => {
1131
1153
  return;
1132
1154
  }
1133
1155
  if (isRecording) {
1156
+ setIsSending(true);
1134
1157
  shouldSendAfterStopRef.current = true;
1135
1158
  stopRecording();
1136
1159
  return;
@@ -1268,6 +1291,44 @@ const IdleControl = (props) => {
1268
1291
  return (jsxRuntime.jsxs(IdleWrapper, { children: [jsxRuntime.jsxs(IdleButton, { type: "button", onClick: onClick, "aria-label": startAriaLabel, children: [jsxRuntime.jsx(IdleButtonOutline, { "aria-hidden": true }), jsxRuntime.jsx(IdleButtonGlow, { "aria-hidden": true }), jsxRuntime.jsx(icons.Icon32Microphone, { height: 48, width: 48 })] }), jsxRuntime.jsx(IdleInstruction, { children: instruction })] }));
1269
1292
  };
1270
1293
 
1294
+ const Bars = styled.div `
1295
+ position: absolute;
1296
+ inset: 0;
1297
+ display: flex;
1298
+ align-items: flex-end;
1299
+ gap: 3px;
1300
+ `;
1301
+ const Bar = styled.div `
1302
+ flex: 1;
1303
+ min-width: 2px;
1304
+ border-radius: 9999px;
1305
+ background: var(--white, #ffffff);
1306
+ opacity: 0.6;
1307
+ transition: height 120ms ease, opacity 120ms ease;
1308
+ `;
1309
+
1310
+ const WaveformBars = (props) => {
1311
+ const { values, progress, styleInterpolator, scale = 40, minHeight = 6, divider = 100, } = props;
1312
+ return (jsxRuntime.jsx(Bars, { children: values.map((value, index) => {
1313
+ const normalized = clampValue(value);
1314
+ const height = Math.max(minHeight, (normalized / divider) * scale);
1315
+ const barProgress = values.length > 1 ? index / (values.length - 1) : 0;
1316
+ const isPlayed = (progress !== null && progress !== void 0 ? progress : 0) > 0 && barProgress <= (progress !== null && progress !== void 0 ? progress : 0);
1317
+ const interpolated = styleInterpolator === null || styleInterpolator === void 0 ? void 0 : styleInterpolator({
1318
+ normalized,
1319
+ height,
1320
+ index,
1321
+ progress: progress !== null && progress !== void 0 ? progress : 0,
1322
+ barProgress,
1323
+ isPlayed,
1324
+ });
1325
+ return (jsxRuntime.jsx(Bar, { style: {
1326
+ height: `${height}px`,
1327
+ ...interpolated,
1328
+ } }, index));
1329
+ }) }));
1330
+ };
1331
+
1271
1332
  /**
1272
1333
  * RecordingShell styles
1273
1334
  *
@@ -1362,21 +1423,6 @@ const Waveform = styled.div `
1362
1423
  align-items: center;
1363
1424
  overflow: hidden;
1364
1425
  `;
1365
- const Bars = styled.div `
1366
- position: absolute;
1367
- inset: 0;
1368
- display: flex;
1369
- align-items: flex-end;
1370
- gap: 3px;
1371
- `;
1372
- const Bar = styled.div `
1373
- flex: 1;
1374
- min-width: 2px;
1375
- border-radius: 9999px;
1376
- background: var(--white, #ffffff);
1377
- opacity: 0.6;
1378
- transition: height 120ms ease, opacity 120ms ease;
1379
- `;
1380
1426
  const Timer$1 = styled.span `
1381
1427
  text-align: right;
1382
1428
  font-size: 13px;
@@ -1438,31 +1484,33 @@ const Spinner = styled.span `
1438
1484
  }
1439
1485
  `;
1440
1486
 
1441
- const WaveformBars = (props) => {
1442
- const { values, styleInterpolator, scale = 40, minHeight = 6, divider = 100, } = props;
1443
- return (jsxRuntime.jsx(Bars, { children: values.map((value, index) => {
1444
- const normalized = clampValue(value);
1445
- const height = Math.max(minHeight, (normalized / divider) * scale);
1446
- const interpolated = styleInterpolator === null || styleInterpolator === void 0 ? void 0 : styleInterpolator({ normalized, height, index });
1447
- return (jsxRuntime.jsx(Bar, { style: {
1448
- height: `${height}px`,
1449
- ...interpolated,
1450
- } }, index));
1451
- }) }));
1452
- };
1453
-
1454
1487
  const RecordingShell = (props) => {
1455
1488
  const { isPaused, isPlaying, isSending, isRecording, audioLevels, hasRecording, playbackTime, previewLevels, recordingTime, stopAriaLabel, playAriaLabel, sendAriaLabel, startAriaLabel, cancelAriaLabel, playbackDuration, pausePlaybackAriaLabel, pauseRecordingAriaLabel, resumeRecordingAriaLabel, onSend, onCancel, formatTime, onRecordToggle, onTogglePlayback, } = props;
1489
+ const { lastDuration } = props;
1490
+ const isPreview = !isRecording || isPaused;
1456
1491
  const waveformValues = isRecording ? audioLevels : (hasRecording ? previewLevels : audioLevels);
1492
+ const effectiveDuration = recordingTime
1493
+ || playbackDuration
1494
+ || lastDuration
1495
+ || 1;
1496
+ const progress = (isPreview && isPlaying)
1497
+ ? Math.min(1, playbackTime / effectiveDuration)
1498
+ : 0;
1457
1499
  const displayTime = React.useMemo(() => {
1458
- if (isRecording) {
1500
+ if (isPlaying) {
1501
+ return formatTime(playbackTime);
1502
+ }
1503
+ if (isRecording && !isPaused) {
1504
+ return formatTime(recordingTime);
1505
+ }
1506
+ if (isRecording && isPaused) {
1459
1507
  return formatTime(recordingTime);
1460
1508
  }
1509
+ if (lastDuration > 0) {
1510
+ return formatTime(lastDuration);
1511
+ }
1461
1512
  if (hasRecording) {
1462
- if (isPlaying) {
1463
- return formatTime(playbackTime);
1464
- }
1465
- if (playbackDuration > 0) {
1513
+ if (playbackDuration > 0.5) {
1466
1514
  return formatTime(playbackDuration);
1467
1515
  }
1468
1516
  if (recordingTime > 0) {
@@ -1470,7 +1518,17 @@ const RecordingShell = (props) => {
1470
1518
  }
1471
1519
  }
1472
1520
  return formatTime(0);
1473
- }, [formatTime, hasRecording, isPlaying, playbackDuration, playbackTime, recordingTime]);
1521
+ }, [
1522
+ isPaused,
1523
+ isPlaying,
1524
+ formatTime,
1525
+ isRecording,
1526
+ lastDuration,
1527
+ hasRecording,
1528
+ playbackTime,
1529
+ recordingTime,
1530
+ playbackDuration,
1531
+ ]);
1474
1532
  const recordButtonDisabled = isSending;
1475
1533
  const recordButtonIcon = !isRecording || isPaused
1476
1534
  ? jsxRuntime.jsx(icons.Icon16Microphone, { width: 24, height: 24 })
@@ -1488,10 +1546,13 @@ const RecordingShell = (props) => {
1488
1546
  : jsxRuntime.jsx(icons.Icon16Play, { width: 24, height: 24 });
1489
1547
  const playbackAria = isPlaying ? pausePlaybackAriaLabel : playAriaLabel;
1490
1548
  const sendDisabled = isSending || (!hasRecording && !isRecording);
1491
- 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 }) => ({
1549
+ 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, { scale: 42, minHeight: 6, divider: 100, progress: progress, values: waveformValues, styleInterpolator: ({ normalized, isPlayed, progress: p }) => ({
1492
1550
  height: `${12 + normalized / 2}px`,
1493
1551
  maxHeight: '34px',
1494
- opacity: 0.38 + Math.min(0.5, normalized / 120),
1552
+ opacity: p > 0
1553
+ ? (isPlayed ? 0.80 : 0.22)
1554
+ : 0.38 + Math.min(0.5, normalized / 120),
1555
+ transition: 'opacity 80ms ease',
1495
1556
  }) }) }), 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 })) })] }));
1496
1557
  };
1497
1558
 
@@ -1574,9 +1635,9 @@ const AudioRecorder = (props) => {
1574
1635
  messages,
1575
1636
  onUploadError,
1576
1637
  });
1577
- const { isPaused, isPlaying, formatTime, audioLevels, isRecording, playbackTime, hasRecording, previewLevels, recordingTime, playbackDuration, } = recorder;
1578
- const showRecorderBar = isRecording || hasRecording;
1579
- return (jsxRuntime.jsx(Container, { className: className, children: showRecorderBar ? (jsxRuntime.jsx(RecordingShell, { isPaused: isPaused, isSending: isSending, isPlaying: isPlaying, formatTime: formatTime, onCancel: handleCancel, isRecording: isRecording, audioLevels: audioLevels, onSend: handleSendRequest, playbackTime: playbackTime, hasRecording: hasRecording, previewLevels: previewLevels, recordingTime: recordingTime, playbackDuration: playbackDuration, onRecordToggle: handleRecordToggle, sendAriaLabel: messages.buttons.send, onTogglePlayback: handlePlaybackToggle, cancelAriaLabel: messages.buttons.cancel, playAriaLabel: messages.aria.playRecording, stopAriaLabel: messages.aria.stopRecording, startAriaLabel: messages.aria.startRecording, pauseRecordingAriaLabel: messages.aria.pauseRecording, resumeRecordingAriaLabel: messages.aria.resumeRecording, pausePlaybackAriaLabel: messages.aria.pausePlayback })) : (jsxRuntime.jsx(IdleControl, { onClick: handleRecordToggle, startAriaLabel: messages.aria.startRecording, instruction: messages.instruction })) }));
1638
+ const { isPaused, isPlaying, formatTime, audioLevels, isRecording, lastDuration, playbackTime, hasRecording, previewLevels, recordingTime, playbackDuration, } = recorder;
1639
+ const showRecorderBar = isRecording || hasRecording || isSending;
1640
+ return (jsxRuntime.jsx(Container, { className: className, children: showRecorderBar ? (jsxRuntime.jsx(RecordingShell, { isPaused: isPaused, isSending: isSending, isPlaying: isPlaying, formatTime: formatTime, onCancel: handleCancel, isRecording: isRecording, audioLevels: audioLevels, onSend: handleSendRequest, playbackTime: playbackTime, lastDuration: lastDuration, hasRecording: hasRecording, previewLevels: previewLevels, recordingTime: recordingTime, playbackDuration: playbackDuration, onRecordToggle: handleRecordToggle, sendAriaLabel: messages.buttons.send, onTogglePlayback: handlePlaybackToggle, cancelAriaLabel: messages.buttons.cancel, playAriaLabel: messages.aria.playRecording, stopAriaLabel: messages.aria.stopRecording, startAriaLabel: messages.aria.startRecording, pauseRecordingAriaLabel: messages.aria.pauseRecording, resumeRecordingAriaLabel: messages.aria.resumeRecording, pausePlaybackAriaLabel: messages.aria.pausePlayback })) : (jsxRuntime.jsx(IdleControl, { onClick: handleRecordToggle, startAriaLabel: messages.aria.startRecording, instruction: messages.instruction })) }));
1580
1641
  };
1581
1642
 
1582
1643
  /**
@@ -2215,7 +2276,7 @@ const VoiceMessagePlayer = React.forwardRef((props, ref) => {
2215
2276
  observer.disconnect();
2216
2277
  };
2217
2278
  }, []);
2218
- const displayTime = isPlaying
2279
+ const displayTime = (isPlaying || currentTime > 0)
2219
2280
  ? formatTime(currentTime)
2220
2281
  : formatTime(resolvedDuration);
2221
2282
  const handleTrackClick = React.useCallback((e) => {