@times-components/ts-components 1.112.0 → 1.112.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/components/article-audio/ArticleAudio.d.ts +6 -0
  3. package/dist/components/article-audio/ArticleAudio.js +51 -0
  4. package/dist/components/article-audio/ArticleAudio.stories.d.ts +1 -0
  5. package/dist/components/article-audio/ArticleAudio.stories.js +8 -0
  6. package/dist/components/article-audio/__tests__/ArticleAudio.test.d.ts +1 -0
  7. package/dist/components/article-audio/__tests__/ArticleAudio.test.js +129 -0
  8. package/dist/components/article-audio/__tests__/Styles.test.d.ts +2 -0
  9. package/dist/components/article-audio/__tests__/Styles.test.js +45 -0
  10. package/dist/components/article-audio/styles.d.ts +1 -0
  11. package/dist/components/article-audio/styles.js +26 -0
  12. package/dist/components/audio-player-components/AudioPlayer.d.ts +3 -0
  13. package/dist/components/audio-player-components/AudioPlayer.js +180 -0
  14. package/dist/components/audio-player-components/AudioPlayer.stories.d.ts +1 -0
  15. package/dist/components/audio-player-components/AudioPlayer.stories.js +204 -0
  16. package/dist/components/audio-player-components/CollapseIcon.d.ts +3 -0
  17. package/dist/components/audio-player-components/CollapseIcon.js +12 -0
  18. package/dist/components/audio-player-components/PlaybackControls.d.ts +3 -0
  19. package/dist/components/audio-player-components/PlaybackControls.js +32 -0
  20. package/dist/components/audio-player-components/SeekBar.d.ts +3 -0
  21. package/dist/components/audio-player-components/SeekBar.js +8 -0
  22. package/dist/components/audio-player-components/TabletDesktopPlayer.d.ts +3 -0
  23. package/dist/components/audio-player-components/TabletDesktopPlayer.js +37 -0
  24. package/dist/components/audio-player-components/TimeDisplay.d.ts +3 -0
  25. package/dist/components/audio-player-components/TimeDisplay.js +10 -0
  26. package/dist/components/audio-player-components/TitleScroller.d.ts +3 -0
  27. package/dist/components/audio-player-components/TitleScroller.js +8 -0
  28. package/dist/components/audio-player-components/__tests__/AudioPlayer.test.d.ts +1 -0
  29. package/dist/components/audio-player-components/__tests__/AudioPlayer.test.js +196 -0
  30. package/dist/components/audio-player-components/__tests__/CollapseIcon.test.d.ts +1 -0
  31. package/dist/components/audio-player-components/__tests__/CollapseIcon.test.js +44 -0
  32. package/dist/components/audio-player-components/__tests__/PlaybackControls.test.d.ts +1 -0
  33. package/dist/components/audio-player-components/__tests__/PlaybackControls.test.js +129 -0
  34. package/dist/components/audio-player-components/__tests__/SeekBar.test.d.ts +1 -0
  35. package/dist/components/audio-player-components/__tests__/SeekBar.test.js +60 -0
  36. package/dist/components/audio-player-components/__tests__/Styles.test.d.ts +1 -0
  37. package/dist/components/audio-player-components/__tests__/Styles.test.js +510 -0
  38. package/dist/components/audio-player-components/__tests__/TabletDesktopPlayer.test.d.ts +1 -0
  39. package/dist/components/audio-player-components/__tests__/TabletDesktopPlayer.test.js +199 -0
  40. package/dist/components/audio-player-components/__tests__/TimeDisplay.test.d.ts +1 -0
  41. package/dist/components/audio-player-components/__tests__/TimeDisplay.test.js +71 -0
  42. package/dist/components/audio-player-components/__tests__/TitleScroller.test.d.ts +1 -0
  43. package/dist/components/audio-player-components/__tests__/TitleScroller.test.js +47 -0
  44. package/dist/components/audio-player-components/__tests__/Utils.test.d.ts +1 -0
  45. package/dist/components/audio-player-components/__tests__/Utils.test.js +31 -0
  46. package/dist/components/audio-player-components/styles.d.ts +49 -0
  47. package/dist/components/audio-player-components/styles.js +568 -0
  48. package/dist/components/audio-player-components/types.d.ts +83 -0
  49. package/dist/components/audio-player-components/types.js +2 -0
  50. package/dist/components/audio-player-components/utils.d.ts +1 -0
  51. package/dist/components/audio-player-components/utils.js +6 -0
  52. package/dist/fixtures/analytics-actions/__tests__/AnalyticsActions.test.d.ts +1 -0
  53. package/dist/fixtures/analytics-actions/__tests__/AnalyticsActions.test.js +49 -0
  54. package/dist/index.d.ts +1 -0
  55. package/dist/index.js +2 -1
  56. package/jest.config.js +3 -3
  57. package/package.json +3 -3
  58. package/rnw.js +1 -1
  59. package/src/components/article-audio/ArticleAudio.stories.tsx +14 -0
  60. package/src/components/article-audio/ArticleAudio.tsx +93 -0
  61. package/src/components/article-audio/__tests__/ArticleAudio.test.tsx +192 -0
  62. package/src/components/article-audio/__tests__/Styles.test.tsx +61 -0
  63. package/src/components/article-audio/styles.ts +26 -0
  64. package/src/components/audio-player-components/AudioPlayer.stories.tsx +209 -0
  65. package/src/components/audio-player-components/AudioPlayer.tsx +324 -0
  66. package/src/components/audio-player-components/CollapseIcon.tsx +25 -0
  67. package/src/components/audio-player-components/PlaybackControls.tsx +104 -0
  68. package/src/components/audio-player-components/SeekBar.tsx +27 -0
  69. package/src/components/audio-player-components/TabletDesktopPlayer.tsx +157 -0
  70. package/src/components/audio-player-components/TimeDisplay.tsx +18 -0
  71. package/src/components/audio-player-components/TitleScroller.tsx +13 -0
  72. package/src/components/audio-player-components/__tests__/AudioPlayer.test.tsx +267 -0
  73. package/src/components/audio-player-components/__tests__/CollapseIcon.test.tsx +89 -0
  74. package/src/components/audio-player-components/__tests__/PlaybackControls.test.tsx +330 -0
  75. package/src/components/audio-player-components/__tests__/SeekBar.test.tsx +96 -0
  76. package/src/components/audio-player-components/__tests__/Styles.test.tsx +777 -0
  77. package/src/components/audio-player-components/__tests__/TabletDesktopPlayer.test.tsx +304 -0
  78. package/src/components/audio-player-components/__tests__/TimeDisplay.test.tsx +103 -0
  79. package/src/components/audio-player-components/__tests__/TitleScroller.test.tsx +60 -0
  80. package/src/components/audio-player-components/__tests__/Utils.test.tsx +37 -0
  81. package/src/components/audio-player-components/__tests__/__snapshots__/Styles.test.tsx.snap +3 -0
  82. package/src/components/audio-player-components/__tests__/__snapshots__/TitleScroller.test.tsx.snap +19 -0
  83. package/src/components/audio-player-components/styles.ts +631 -0
  84. package/src/components/audio-player-components/types.ts +90 -0
  85. package/src/components/audio-player-components/utils.ts +5 -0
  86. package/src/fixtures/analytics-actions/__tests__/AnalyticsActions.test.tsx +62 -0
  87. package/src/index.ts +1 -0
  88. package/src/types/externs.d.ts +9 -0
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import { ArticleAudio } from './ArticleAudio';
4
+
5
+ storiesOf('Typescript Component/Article Audio', module).add(
6
+ 'Article Audio',
7
+ () => {
8
+ return (
9
+ <div style={{ padding: '10px' }}>
10
+ <ArticleAudio audioSrc="https://www.kozco.com/tech/LRMonoPhase4.mp3" />
11
+ </div>
12
+ );
13
+ }
14
+ );
@@ -0,0 +1,93 @@
1
+ import React, { FC, useState, useRef } from 'react';
2
+ import { AudioButton } from './styles';
3
+ import { AudioPlayer } from '../audio-player-components/AudioPlayer';
4
+ import { PlayIcon, PauseIcon } from '@times-components/icons';
5
+ export interface ArticleAudioProps {
6
+ audioSrc: string;
7
+ }
8
+
9
+ export const ArticleAudio: FC<ArticleAudioProps> = ({ audioSrc }) => {
10
+ const [audioState, setAudioState] = useState<
11
+ 'not-started' | 'playing' | 'paused'
12
+ >('not-started');
13
+ const [isAudioPlayerVisible, setisAudioPlayerVisible] = useState<boolean>(
14
+ false
15
+ );
16
+ const [duration, setDuration] = useState<string | null>(null);
17
+
18
+ const audioRef = useRef<HTMLAudioElement | null>(null);
19
+
20
+ const handleLoadedMetadata = () => {
21
+ if (audioRef.current) {
22
+ const totalSeconds = Math.floor(audioRef.current.duration);
23
+ const minutes = Math.floor(totalSeconds / 60) + 1;
24
+ setDuration(`${minutes}`);
25
+ }
26
+ };
27
+
28
+ const handlePlayPause = () => {
29
+ setisAudioPlayerVisible(true);
30
+
31
+ if (audioState === 'playing') {
32
+ setAudioState('paused');
33
+ } else {
34
+ setAudioState('playing');
35
+ }
36
+ };
37
+
38
+ const hidePlayer = () => {
39
+ setisAudioPlayerVisible(false);
40
+ };
41
+
42
+ return (
43
+ <div>
44
+ <audio
45
+ ref={audioRef}
46
+ src={audioSrc}
47
+ onLoadedMetadata={handleLoadedMetadata}
48
+ preload="metadata"
49
+ />
50
+ <AudioButton
51
+ onClick={handlePlayPause}
52
+ style={{
53
+ backgroundColor: audioState !== 'not-started' ? '#1D1D1B' : 'unset',
54
+ color: audioState === 'not-started' ? '#333' : '#fff'
55
+ }}
56
+ >
57
+ {audioState === 'playing' ? (
58
+ <>
59
+ <PauseIcon width={16} height={16} fill="#fff" /> Playing
60
+ </>
61
+ ) : audioState === 'paused' ? (
62
+ <>
63
+ <PlayIcon width={16} height={16} fill="#fff" /> Paused
64
+ </>
65
+ ) : (
66
+ <>
67
+ <PlayIcon width={16} height={16} /> Listen
68
+ </>
69
+ )}
70
+ <span
71
+ style={{
72
+ color: audioState === 'not-started' ? '#696969' : '#fff'
73
+ }}
74
+ >
75
+ {' '}
76
+ {duration} min
77
+ </span>
78
+ </AudioButton>
79
+ {isAudioPlayerVisible && (
80
+ <AudioPlayer
81
+ src={audioSrc}
82
+ isPlayingProp={audioState === 'playing'}
83
+ onPlay={() => setAudioState('playing')}
84
+ onPause={() => setAudioState('paused')}
85
+ onEnded={() => setAudioState('not-started')}
86
+ onClose={() => hidePlayer()}
87
+ />
88
+ )}
89
+ </div>
90
+ );
91
+ };
92
+
93
+ export default ArticleAudio;
@@ -0,0 +1,192 @@
1
+ import React from 'react';
2
+ import { render, fireEvent, act } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
+ import { ArticleAudio } from '../ArticleAudio';
5
+
6
+ jest.mock('../styles', () => ({
7
+ AudioButton: ({ children, onClick, style }: any) => (
8
+ <button data-testid="audio-button" onClick={onClick} style={style}>
9
+ {children}
10
+ </button>
11
+ )
12
+ }));
13
+
14
+ jest.mock('@times-components/icons', () => ({
15
+ __esModule: true,
16
+ PlayIcon: ({ color }: any) => (
17
+ <svg data-testid="play-icon" style={{ color: color || '#333' }} />
18
+ ),
19
+ PauseIcon: ({ color }: any) => (
20
+ <svg data-testid="pause-icon" style={{ color: color || '#333' }} />
21
+ )
22
+ }));
23
+
24
+ jest.mock('../../audio-player-components/AudioPlayer', () => ({
25
+ AudioPlayer: ({ onPlay, onPause, onEnded, onClose }: any) => (
26
+ <div data-testid="audio-player">
27
+ <button onClick={onPlay}>Play</button>
28
+ <button onClick={onPause}>Pause</button>
29
+ <button onClick={onEnded}>Ended</button>
30
+ <button onClick={onClose}>Close</button>
31
+ </div>
32
+ )
33
+ }));
34
+
35
+ describe('ArticleAudio', () => {
36
+ beforeEach(() => {
37
+ // Mock the duration of the audio element
38
+ Object.defineProperty(HTMLMediaElement.prototype, 'duration', {
39
+ get(): number {
40
+ return 120; // 2 minutes
41
+ }
42
+ });
43
+ });
44
+
45
+ afterEach(() => {
46
+ jest.clearAllMocks();
47
+ });
48
+
49
+ test('renders audio button with correct initial state', () => {
50
+ const { getByTestId, getByText, container } = render(
51
+ <ArticleAudio audioSrc="https://www.kozco.com/tech/LRMonoPhase4.mp3" />
52
+ );
53
+
54
+ // Trigger the 'loadedmetadata' event to set the duration
55
+ const audio = container.querySelector('audio') as HTMLAudioElement;
56
+ act(() => {
57
+ fireEvent.loadedMetadata(audio);
58
+ });
59
+
60
+ const audioButton = getByTestId('audio-button');
61
+ expect(audioButton).toBeInTheDocument();
62
+
63
+ expect(audioButton.style.backgroundColor).toBe('');
64
+ expect(audioButton).toHaveStyle('color: #333');
65
+
66
+ // The initial state should display 'Listen' and the duration
67
+ expect(getByText('Listen')).toBeInTheDocument();
68
+ expect(getByText('3 min')).toBeInTheDocument();
69
+
70
+ // Since audioState is 'not-started', duration color should be '#696969'
71
+ const durationSpan = getByText('3 min');
72
+ expect(durationSpan).toHaveStyle('color: #696969');
73
+ });
74
+
75
+ test('hides AudioPlayer when close button is clicked (using mocked AudioPlayer)', () => {
76
+ const { getByTestId, queryByTestId, container, getByText } = render(
77
+ <ArticleAudio audioSrc="https://www.kozco.com/tech/LRMonoPhase4.mp3" />
78
+ );
79
+
80
+ // Trigger the 'loadedmetadata' event to set the duration
81
+ const audio = container.querySelector('audio') as HTMLAudioElement;
82
+ act(() => {
83
+ fireEvent.loadedMetadata(audio);
84
+ });
85
+
86
+ // Initially, the AudioPlayer should not be visible
87
+ expect(queryByTestId('audio-player')).not.toBeInTheDocument();
88
+
89
+ // Click the audio button to start playback
90
+ const audioButton = getByTestId('audio-button');
91
+ fireEvent.click(audioButton);
92
+
93
+ // The mocked AudioPlayer should now be visible
94
+ expect(getByTestId('audio-player')).toBeInTheDocument();
95
+
96
+ // Use the mocked Close button inside the AudioPlayer to close it
97
+ const closeButton = getByText('Close');
98
+ fireEvent.click(closeButton);
99
+
100
+ // The AudioPlayer should no longer be visible
101
+ expect(queryByTestId('audio-player')).not.toBeInTheDocument();
102
+ });
103
+
104
+ test('handles play and pause', () => {
105
+ const { getByTestId, getByText, container } = render(
106
+ <ArticleAudio audioSrc="https://www.kozco.com/tech/LRMonoPhase4.mp3" />
107
+ );
108
+
109
+ // Trigger the 'loadedmetadata' event to set the duration
110
+ const audio = container.querySelector('audio') as HTMLAudioElement;
111
+ act(() => {
112
+ fireEvent.loadedMetadata(audio);
113
+ });
114
+
115
+ const audioButton = getByTestId('audio-button');
116
+
117
+ // Simulate clicking the play button
118
+ fireEvent.click(audioButton);
119
+
120
+ // Now, audioState should be 'playing'
121
+ expect(audioButton).toHaveStyle('background-color: #1D1D1B');
122
+ expect(audioButton).toHaveStyle('color: #fff');
123
+ expect(getByText('Playing')).toBeInTheDocument();
124
+
125
+ // Since audioState is 'playing', duration color should be '#fff'
126
+ const durationSpan = getByText('3 min');
127
+ expect(durationSpan).toHaveStyle('color: #fff');
128
+
129
+ // Simulate clicking the pause button
130
+ fireEvent.click(audioButton);
131
+
132
+ expect(getByText('Paused')).toBeInTheDocument();
133
+ expect(audioButton).toHaveStyle('background-color: #1D1D1B');
134
+ expect(audioButton).toHaveStyle('color: #fff');
135
+
136
+ // Simulate clicking the play button again
137
+ fireEvent.click(audioButton);
138
+
139
+ expect(getByText('Playing')).toBeInTheDocument();
140
+ });
141
+
142
+ test('shows AudioPlayer when audio is played', () => {
143
+ const { getByTestId, queryByTestId, container } = render(
144
+ <ArticleAudio audioSrc="https://www.kozco.com/tech/LRMonoPhase4.mp3" />
145
+ );
146
+
147
+ // Trigger the 'loadedmetadata' event to set the duration
148
+ const audio = container.querySelector('audio') as HTMLAudioElement;
149
+ act(() => {
150
+ fireEvent.loadedMetadata(audio);
151
+ });
152
+
153
+ expect(queryByTestId('audio-player')).not.toBeInTheDocument();
154
+
155
+ const audioButton = getByTestId('audio-button');
156
+ fireEvent.click(audioButton);
157
+
158
+ expect(getByTestId('audio-player')).toBeInTheDocument();
159
+ });
160
+
161
+ test('updates audioState based on AudioPlayer callbacks', () => {
162
+ const { getByTestId, getByText, container } = render(
163
+ <ArticleAudio audioSrc="https://www.kozco.com/tech/LRMonoPhase4.mp3" />
164
+ );
165
+
166
+ // Trigger the 'loadedmetadata' event to set the duration
167
+ const audio = container.querySelector('audio') as HTMLAudioElement;
168
+ act(() => {
169
+ fireEvent.loadedMetadata(audio);
170
+ });
171
+
172
+ const audioButton = getByTestId('audio-button');
173
+ fireEvent.click(audioButton); // Start playing
174
+
175
+ expect(getByText('Playing')).toBeInTheDocument();
176
+
177
+ const pauseButton = getByText('Pause');
178
+ fireEvent.click(pauseButton);
179
+
180
+ expect(getByText('Paused')).toBeInTheDocument();
181
+
182
+ const playButton = getByText('Play');
183
+ fireEvent.click(playButton);
184
+
185
+ expect(getByText('Playing')).toBeInTheDocument();
186
+
187
+ const endedButton = getByText('Ended');
188
+ fireEvent.click(endedButton);
189
+
190
+ expect(getByText('Listen')).toBeInTheDocument();
191
+ });
192
+ });
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
+ import 'jest-styled-components';
5
+ import { AudioButton } from '../styles';
6
+
7
+ describe('AudioButton', () => {
8
+ test('renders correctly with default styles', () => {
9
+ const { getByTestId } = render(
10
+ <AudioButton data-testid="audio-button">Test Button</AudioButton>
11
+ );
12
+
13
+ const button = getByTestId('audio-button');
14
+
15
+ expect(button).toHaveStyleRule('background-color', 'unset');
16
+ expect(button).toHaveStyleRule('border-radius', '0');
17
+ expect(button).toHaveStyleRule('padding', '7px 11px');
18
+ expect(button).toHaveStyleRule('border', '1px solid #333333');
19
+ expect(button).toHaveStyleRule('display', 'flex');
20
+ expect(button).toHaveStyleRule('align-items', 'center');
21
+ expect(button).toHaveStyleRule('color', '#333333');
22
+ expect(button).toHaveStyleRule('font-family', 'Roboto');
23
+ expect(button).toHaveStyleRule('font-weight', '500');
24
+ expect(button).toHaveStyleRule('font-size', '14px');
25
+ expect(button).toHaveStyleRule('line-height', '18px');
26
+ });
27
+
28
+ test('renders svg child with correct styles', () => {
29
+ const { getByTestId } = render(
30
+ <AudioButton data-testid="audio-button">
31
+ <svg data-testid="icon" />
32
+ </AudioButton>
33
+ );
34
+
35
+ const button = getByTestId('audio-button');
36
+
37
+ expect(button).toHaveStyleRule('margin-right', '8px', {
38
+ modifier: 'svg'
39
+ });
40
+ });
41
+
42
+ test('renders span child with correct styles', () => {
43
+ const { getByTestId } = render(
44
+ <AudioButton data-testid="audio-button">
45
+ <span data-testid="span">Test Span</span>
46
+ </AudioButton>
47
+ );
48
+
49
+ const button = getByTestId('audio-button');
50
+
51
+ expect(button).toHaveStyleRule('margin-left', '4px', {
52
+ modifier: 'span'
53
+ });
54
+ expect(button).toHaveStyleRule('font-size', '12px', {
55
+ modifier: 'span'
56
+ });
57
+ expect(button).toHaveStyleRule('color', '#696969', {
58
+ modifier: 'span'
59
+ });
60
+ });
61
+ });
@@ -0,0 +1,26 @@
1
+ import styled from 'styled-components';
2
+ import { colours } from '@times-components/ts-styleguide';
3
+
4
+ export const AudioButton = styled.button`
5
+ background-color: unset;
6
+ border-radius: 0;
7
+ padding: 7px 11px;
8
+ border: 1px solid ${colours.functional.primary};
9
+ display: flex;
10
+ align-items: center;
11
+ color: ${colours.functional.primary};
12
+ font-family: Roboto;
13
+ font-weight: 500;
14
+ font-size: 14px;
15
+ line-height: 18px;
16
+
17
+ svg {
18
+ margin-right: 8px;
19
+ }
20
+
21
+ span {
22
+ margin-left: 4px;
23
+ font-size: 12px;
24
+ color: ${colours.functional.secondary};
25
+ }
26
+ `;
@@ -0,0 +1,209 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import { AudioPlayer } from './AudioPlayer';
4
+ import { withKnobs, boolean, number, text } from '@storybook/addon-knobs';
5
+
6
+ storiesOf('Typescript Component/Audio Player Components', module)
7
+ .addDecorator(withKnobs)
8
+ .addParameters({
9
+ component: AudioPlayer,
10
+ docs: {
11
+ description: {
12
+ component: `
13
+
14
+ A customizable audio player component with various controls.
15
+
16
+ ## Props
17
+
18
+ ### \`src\` (Required)
19
+
20
+ - **Type**: \`string\`
21
+ - **Description**: The URL of the audio source file to be played.
22
+
23
+ ### \`title\`
24
+
25
+ - **Type**: \`string\`
26
+ - **Default**: \`'Audio Title'\`
27
+ - **Description**: The title of the audio track displayed in the player.
28
+
29
+ ### \`autoPlay\`
30
+
31
+ - **Type**: \`boolean\`
32
+ - **Default**: \`false\`
33
+ - **Description**: Determines whether the audio should start playing automatically when the component mounts.
34
+
35
+ ### \`initialVolume\`
36
+
37
+ - **Type**: \`number\` (Range between \`0\` and \`1\`)
38
+ - **Default**: \`1\`
39
+ - **Description**: Sets the initial volume level of the audio player.
40
+
41
+ ### \`playbackRate\`
42
+
43
+ - **Type**: \`number\`
44
+ - **Default**: \`1\`
45
+ - **Description**: Sets the initial playback speed of the audio.
46
+
47
+ ### \`isPlayingProp\`
48
+
49
+ - **Type**: \`boolean\`
50
+ - **Description**: Controls the play/pause state externally. When provided, it overrides the internal state.
51
+
52
+ ### \`isExpandedProp\`
53
+
54
+ - **Type**: \`boolean\`
55
+ - **Description**: Controls the expanded/collapsed state externally. When provided, it overrides the internal state.
56
+
57
+ ### \`allowTogglePlay\`
58
+
59
+ - **Type**: \`boolean\`
60
+ - **Default**: \`true\`
61
+ - **Description**: Enables or disables the play/pause functionality.
62
+
63
+ ### \`allowSeek\`
64
+
65
+ - **Type**: \`boolean\`
66
+ - **Default**: \`true\`
67
+ - **Description**: Enables or disables the ability to seek through the audio track.
68
+
69
+ ### \`allowVolumeChange\`
70
+
71
+ - **Type**: \`boolean\`
72
+ - **Default**: \`true\`
73
+ - **Description**: Enables or disables the volume control. Volume control is available on tablet and desktop views.
74
+
75
+ ### \`allowPlaybackRateChange\`
76
+
77
+ - **Type**: \`boolean\`
78
+ - **Default**: \`true\`
79
+ - **Description**: Enables or disables the ability to change the playback speed.
80
+
81
+ ### \`allowExpandCollapse\`
82
+
83
+ - **Type**: \`boolean\`
84
+ - **Default**: \`true\`
85
+ - **Description**: Enables or disables the ability to expand or collapse the audio player interface.
86
+
87
+ ### \`onPlay\`
88
+
89
+ - **Type**: \`() => void\`
90
+ - **Description**: Callback function invoked when the audio starts playing.
91
+
92
+ ### \`onPause\`
93
+
94
+ - **Type**: \`() => void\`
95
+ - **Description**: Callback function invoked when the audio is paused.
96
+
97
+ ### \`onEnded\`
98
+
99
+ - **Type**: \`() => void\`
100
+ - **Description**: Callback function invoked when the audio playback ends.
101
+
102
+ ### \`onTimeUpdate\`
103
+
104
+ - **Type**: \`(currentTime: number) => void\`
105
+ - **Description**: Callback function invoked when the current playback time updates.
106
+
107
+ ### \`onVolumeChange\`
108
+
109
+ - **Type**: \`(volume: number) => void\`
110
+ - **Description**: Callback function invoked when the volume level changes.
111
+
112
+ ### \`onPlaybackRateChange\`
113
+
114
+ - **Type**: \`(rate: number) => void\`
115
+ - **Description**: Callback function invoked when the playback rate changes.
116
+
117
+ ### \`onSeek\`
118
+
119
+ - **Type**: \`(time: number) => void\`
120
+ - **Description**: Callback function invoked when the playback position changes due to seeking.
121
+
122
+ ### \`onClose\`
123
+
124
+ - **Type**: \`() => void\`
125
+ - **Description**: Callback function invoked when the audio player is closed.
126
+
127
+ ## Usage Examples
128
+
129
+ ### Basic Usage
130
+
131
+
132
+ \`\`\`jsx
133
+ <AudioPlayer src="https://example.com/audio-file.mp3" />
134
+ \`\`\`
135
+
136
+ ### With Custom Title and AutoPlay
137
+
138
+ \`\`\`jsx
139
+ <AudioPlayer
140
+ src="https://example.com/audio-file.mp3"
141
+ title="Episode 1: The Beginning"
142
+ autoPlay={true}
143
+ />
144
+ \`\`\`
145
+
146
+ ### Handling Events
147
+
148
+ \`\`\`jsx
149
+ <AudioPlayer
150
+ src="https://example.com/audio-file.mp3"
151
+ onPlay={() => console.log('Playing')}
152
+ onPause={() => console.log('Paused')}
153
+ onEnded={() => console.log('Ended')}
154
+ onTimeUpdate={(currentTime) => console.log('Current Time:', currentTime)}
155
+ onVolumeChange={(volume) => console.log('Volume:', volume)}
156
+ onPlaybackRateChange={(rate) => console.log('Playback Rate:', rate)}
157
+ onSeek={(time) => console.log('Seeked to:', time)}
158
+ onClose={() => console.log('Player Closed')}
159
+ />
160
+ \`\`\`
161
+
162
+ `
163
+ }
164
+ }
165
+ })
166
+ .add('Default Audio Player', () => {
167
+ const src = text(
168
+ 'src',
169
+ 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3'
170
+ );
171
+ const title = text('title', 'Sample Audio Title for Testing');
172
+ const autoPlay = boolean('autoPlay', false);
173
+ const initialVolume = number('initialVolume', 0.5, {
174
+ range: true,
175
+ min: 0,
176
+ max: 1,
177
+ step: 0.1
178
+ });
179
+ const playbackRate = number('playbackRate', 1, {
180
+ range: true,
181
+ min: 0.5,
182
+ max: 2,
183
+ step: 0.1
184
+ });
185
+ const isPlayingProp = boolean('isPlayingProp', false);
186
+ const isExpandedProp = boolean('isExpandedProp', true);
187
+ const allowTogglePlay = boolean('allowTogglePlay', true);
188
+ const allowSeek = boolean('allowSeek', true);
189
+ const allowVolumeChange = boolean('allowVolumeChange', true);
190
+ const allowPlaybackRateChange = boolean('allowPlaybackRateChange', true);
191
+ const allowExpandCollapse = boolean('allowExpandCollapse', true);
192
+
193
+ const mockProps = {
194
+ src,
195
+ title,
196
+ autoPlay,
197
+ initialVolume,
198
+ playbackRate,
199
+ isPlayingProp,
200
+ isExpandedProp,
201
+ allowTogglePlay,
202
+ allowSeek,
203
+ allowVolumeChange,
204
+ allowPlaybackRateChange,
205
+ allowExpandCollapse
206
+ };
207
+
208
+ return <AudioPlayer {...mockProps} />;
209
+ });