react-audio-wavekit 0.2.4 → 0.2.6

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/README.md CHANGED
@@ -38,6 +38,8 @@ Static waveform visualization with playhead and drag-to-seek.
38
38
 
39
39
  ```tsx
40
40
  <AudioWaveform
41
+ // Also accepts classnames, compatible with tailwind.
42
+ className=""
41
43
  blob={audioBlob}
42
44
  currentTime={currentTime}
43
45
  duration={duration}
@@ -47,6 +49,11 @@ Static waveform visualization with playhead and drag-to-seek.
47
49
  audio.currentTime = time;
48
50
  audio.play();
49
51
  }}
52
+ style={{
53
+ // Or use classNames with Tailwind
54
+ width: '400px',
55
+ height: '100px',
56
+ }}
50
57
  />
51
58
  ```
52
59
 
@@ -63,6 +70,8 @@ Static waveform visualization with playhead and drag-to-seek.
63
70
  | `suspense` | `boolean` | `false` | Enable React Suspense mode |
64
71
  | `appearance` | `AudioWaveformAppearance` | - | See [Appearance Options](#appearance-options) |
65
72
 
73
+ **SSR note:** When `suspense` is `true`, decoding only starts on the client after mount. On the server (and during the first client render), the waveform renders without peaks, so wrap the component in a Suspense boundary to show a fallback during hydration.
74
+
66
75
  ---
67
76
 
68
77
  ## Recorder
@@ -228,6 +237,11 @@ Components accept `className`, `style`, and all standard canvas HTML attributes.
228
237
  <AudioWaveform
229
238
  blob={blob}
230
239
  className="h-32 w-full rounded-lg bg-slate-900 p-4"
240
+ // or style prop
241
+ style={{
242
+ width: "100%",
243
+ height: "100%",
244
+ }}
231
245
  appearance={{
232
246
  barColor: "#3b82f6",
233
247
  barWidth: 2,
@@ -24,9 +24,13 @@ const AudioWaveform = react.forwardRef(function AudioWaveform2({
24
24
  }, ref) {
25
25
  const [decodedPeaks, setDecodedPeaks] = react.useState(null);
26
26
  const [error, setError] = react.useState(null);
27
+ const [isMounted, setIsMounted] = react.useState(false);
27
28
  const blobRef = react.useRef(null);
28
29
  const rendererRef = react.useRef(null);
29
30
  const sampleCount = react.useMemo(() => getInitialSampleCount(), []);
31
+ react.useEffect(() => {
32
+ setIsMounted(true);
33
+ }, []);
30
34
  react.useEffect(() => {
31
35
  if (ref && typeof ref === "function") {
32
36
  ref({ canvas: rendererRef.current?.canvas || null });
@@ -35,7 +39,7 @@ const AudioWaveform = react.forwardRef(function AudioWaveform2({
35
39
  }
36
40
  }, [ref]);
37
41
  const shouldDecode = !precomputedPeaks && blob;
38
- const suspensePeaks = shouldDecode && suspense ? utilSuspense.unwrapPromise(utilAudioDecoder.getAudioData(blob, sampleCount)) : null;
42
+ const suspensePeaks = shouldDecode && suspense && isMounted ? utilSuspense.unwrapPromise(utilAudioDecoder.getAudioData(blob, sampleCount)) : null;
39
43
  react.useEffect(() => {
40
44
  if (!shouldDecode || suspense) {
41
45
  if (!shouldDecode) {
@@ -22,9 +22,13 @@ const AudioWaveform = forwardRef(function AudioWaveform2({
22
22
  }, ref) {
23
23
  const [decodedPeaks, setDecodedPeaks] = useState(null);
24
24
  const [error, setError] = useState(null);
25
+ const [isMounted, setIsMounted] = useState(false);
25
26
  const blobRef = useRef(null);
26
27
  const rendererRef = useRef(null);
27
28
  const sampleCount = useMemo(() => getInitialSampleCount(), []);
29
+ useEffect(() => {
30
+ setIsMounted(true);
31
+ }, []);
28
32
  useEffect(() => {
29
33
  if (ref && typeof ref === "function") {
30
34
  ref({ canvas: rendererRef.current?.canvas || null });
@@ -33,7 +37,7 @@ const AudioWaveform = forwardRef(function AudioWaveform2({
33
37
  }
34
38
  }, [ref]);
35
39
  const shouldDecode = !precomputedPeaks && blob;
36
- const suspensePeaks = shouldDecode && suspense ? unwrapPromise(getAudioData(blob, sampleCount)) : null;
40
+ const suspensePeaks = shouldDecode && suspense && isMounted ? unwrapPromise(getAudioData(blob, sampleCount)) : null;
37
41
  useEffect(() => {
38
42
  if (!shouldDecode || suspense) {
39
43
  if (!shouldDecode) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-audio-wavekit",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "React component library for audio waveform visualization and live recording",
5
5
  "license": "CC0-1.0",
6
6
  "author": "semanticist21",
@@ -72,7 +72,7 @@
72
72
  "@storybook/react": "10.1.4",
73
73
  "@storybook/react-vite": "10.1.4",
74
74
  "@tailwindcss/vite": "4.1.17",
75
- "@testing-library/react": "^16.3.0",
75
+ "@testing-library/react": "^16.3.1",
76
76
  "@types/node": "24.10.1",
77
77
  "@types/react": "19.2.7",
78
78
  "@types/react-dom": "19.2.3",
@@ -87,7 +87,7 @@
87
87
  "typescript": "5.9.3",
88
88
  "vite": "7.2.6",
89
89
  "vite-plugin-dts": "4.5.4",
90
- "vitest": "^4.0.15"
90
+ "vitest": "^4.0.16"
91
91
  },
92
92
  "dependencies": {
93
93
  "mpg123-decoder": "^1.0.3"