{"_id":"waveform-navigator","_rev":"31-83e6eb25edbe9f9aaa9bd18053772140","name":"waveform-navigator","dist-tags":{"latest":"0.6.1"},"versions":{"0.1.0":{"name":"waveform-navigator","version":"0.1.0","author":"","license":"MIT","_id":"waveform-navigator@0.1.0","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"cd8def9a7e16351c9bcb0b1581388a4ca8389cb8","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.1.0.tgz","fileCount":53,"integrity":"sha512-ry7pZGbliCezp3zbAxeFgAv6TikQwP1cqz4Bn0uQ3HcZ8G0d488ymdBDjod85mdHP0UvJY1K7DgSYDsZq8CORA==","signatures":[{"sig":"MEUCIQDc2WoUYN78x96MvwVYI7MiPQHdCXpfVVmUaD9hQ8kqCwIgUrCdiqMGXZkYmD+frk9Il2gnX/RQgWcj1Uga4djkCBY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":346412},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"995914af1bce4b5a2abbc8a0ae2a20fd635ff9ce","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","prepare":"npm run build","test:ui":"vitest --ui","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run type-check && npm test"},"_npmUser":{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"10.9.2","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"23.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^6.9.1","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.1.0_1769522255173_0.21799813498236897","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"waveform-navigator","version":"0.2.0","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.0","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"36e97dde89f8b49d0871581f2877dfaecb6484d8","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.0.tgz","fileCount":53,"integrity":"sha512-LWEEHHoNLByrbMr5jp7/MvzH2VffGPIDmcKzzDFxatIXDjdbLo9YJ3KF/1ohTfr3IfoySSq9RNj5xNu0lZ7M/A==","signatures":[{"sig":"MEYCIQCRXHjWzB0LFgQYn+z7WvUVZQAsW5bltMWtTp/YUAmj2AIhANe7jntypEv361e/X+ukytZOAZwxj/Ud+ufhbikR9fdl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":347184},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"4cc6eaf722d4c05b67b9d83562437ec16ecdc2d6","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","prepare":"npm run build","test:ui":"vitest --ui","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^6.9.1","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.0_1769531801076_0.5141275802264644","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"waveform-navigator","version":"0.2.1","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.1","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"f2eb88a174127f1cf985bd8ee6da9943d3f0ba08","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.1.tgz","fileCount":53,"integrity":"sha512-qYpI14t+XsNlI6KJFd37LGvKKjUe35dHc3oTO+uVoZHXyS2Z05kzGioK++AdowxoB1/g2b/BLmXqw1CQx2lqCw==","signatures":[{"sig":"MEUCIQCyWt6CcIyDwy6irYn2c/GwUTuD1R0giQjf7dhdUy+IMwIgcsTqThANTqCBi0C1oL//8NT3DFVHlXVUe5HI0JOGscQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":347184},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"298bfd3af3373318f9b9b790322b5155a5ef0a35","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","prepare":"npm run build","test:ui":"vitest --ui","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^6.9.1","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.1_1769533318444_0.6407612685283495","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"waveform-navigator","version":"0.2.2","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.2","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"2315a16bf0ce2470d20110ef439e54fe7d3f86eb","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.2.tgz","fileCount":53,"integrity":"sha512-cLxlts5ssFV4ZqVE4A0gLRHb3dLmtCKyL7CJQPyuSAwT+8z3zl+A4Vv/HWLn275J0YkOml6F/NBkQi+M2vlsJw==","signatures":[{"sig":"MEUCIQDU3WjCXg8uYO9nzWnijnKiapN+IP9ub62a2U9N7A7StgIgNsju2E6ljGaBeY5nc0guyZ6dTtXXID8JrHGYSl4Np5I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":347237},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"99e879fe8df0eaa4b7b115c4c5db9d441a983961","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","prepare":"npm run build","test:ui":"vitest --ui","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^6.9.1","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.2_1769554904764_0.5461683115832596","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"waveform-navigator","version":"0.2.3","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.3","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"4e1ccf818368e46dcaf54afa20639f18fe4e9642","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.3.tgz","fileCount":53,"integrity":"sha512-Vg+ZxATSShUNyp+Pv8xJm/3hL9BfO0phE0hBFhVDYMUVKgarJMU9G8GdOBzW2u1KRPrro3TR45dh6x4M4ZVgZQ==","signatures":[{"sig":"MEYCIQDbEdqJqjFuvOh7C1aQy9O93CAw6K6XZiDd2uXB8Yvu9AIhALb7Mr1FFe/vuOXmMab86iZc+Leqok9NVoaVFEIwtHRp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":348269},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"32d2aadb7367b07e67b3325683a36717eab6462f","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","prepare":"npm run build","test:ui":"vitest --ui","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^6.9.1","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.3_1769698609150_0.034071208503472894","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"waveform-navigator","version":"0.2.4","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.4","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"8a5897eb1e464a64fc34406fa9b68c3a2dcbd40c","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.4.tgz","fileCount":53,"integrity":"sha512-tK2wHKdHvWjRPilz+IiQ1xHR/mdLZ+Xi4y3zikD/BtnKJ46OAFQOWMWylcz7ISzyf+Jv/UIWE8iC6BJnKGjy6g==","signatures":[{"sig":"MEUCIBtj3Vcxz6UEXFu/TgEEhEzjP5VAcM7CZO1ssdvGn0qUAiEAlpEvInMfAcI8pgUolwYoD+SYkSO8qPJaGLtI2SYd0z8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":349640},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"fdf579fea250147cf0f954c1c2a7467b9134f6d5","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.4_1769704433775_0.03829631286644397","host":"s3://npm-registry-packages-npm-production"}},"0.2.5":{"name":"waveform-navigator","version":"0.2.5","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.5","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"19d774dfe4bcf2feea3f97a27fbd5754bfac1c97","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.5.tgz","fileCount":55,"integrity":"sha512-C5J/+FDxaFmLZC+yYXRcI+gh09p4W0EgBWXe+Eqz6ITBNfbT1HI4Zb2/MmTyc/Uki4zSr4tNg9LiWq0steGVNw==","signatures":[{"sig":"MEUCIQDLHLgu6e4ipjX8jx3z8goiVLzZTJT+mEiBB6zIqrgPogIgSP0FEboGE+3JXZdyAH+6/oz6xi5UEX9GseD6U0Ezg+Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":379103},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"99c745615037cc246ffcbade3562ac3d34156611","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.5_1769721413683_0.10702473778975263","host":"s3://npm-registry-packages-npm-production"}},"0.2.6":{"name":"waveform-navigator","version":"0.2.6","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.6","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"4de27554aab8311dc63d9467bdb91c18d4c5c0ab","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.6.tgz","fileCount":55,"integrity":"sha512-QNuJ598yEmPHpsg1Bg2cXpgAsL669AGgDZkyNF01/gvPXUwvHUOoXd//jtPpCubXWh9nUmPSNTlshMSTX4+VMg==","signatures":[{"sig":"MEUCIQCirAlFS1Jt9gj9oVQ1UOW+orJg4daFBM0S/w/VvRtChAIgPG+sB11RJVhGalD46cG5YS9AQJw90hJGAlKSsNl0X44=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":379105},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"62242c508a0c3e4cd3bc49da5b2df08dac5faf72","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.8.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.6_1769722568323_0.14669492921077865","host":"s3://npm-registry-packages-npm-production"}},"0.2.7":{"name":"waveform-navigator","version":"0.2.7","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.7","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"c730449e7a8380effb0dcceaef0ad5aa24889c04","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.7.tgz","fileCount":55,"integrity":"sha512-EUA6nSNBV/pAF7rQJ7uH/1z3NXONeMJf7tada45VZ1qeQ5cVoiqj/+dHlsCWLI6t7YZNF5Nnoe+vFL/6fDAEVw==","signatures":[{"sig":"MEYCIQDR2AkPmpaLZXfq9XezCbWAAAyFr4Bob26xnfM0HPa6OAIhAN3hdO38snhBwIvk8BPdCKoC2fjzs9uQ2PZ3n/maBNJS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":381826},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"09c911943e52760f6781b59bf4cb7efc1fc13c68","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.7_1774388517995_0.6537565076957939","host":"s3://npm-registry-packages-npm-production"}},"0.2.8":{"name":"waveform-navigator","version":"0.2.8","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.8","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"da4b4cec7d6fdfd349583d7c44741e4c2706c9af","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.8.tgz","fileCount":55,"integrity":"sha512-Zryhr8iE4v2fcc+NCUlcukItXjScgjZAH+ykG3KBO/iVAd0bKh7yLIJxcDxVNfXvShlWRib6J1BBNr1RPeTmHQ==","signatures":[{"sig":"MEYCIQCm5h8l4/Hk3QJPXDWyXRiLfTjIJjQ3sr7dxBy3x92FxAIhAKo4ZL80TFtIbRMCs+c9gFMDnIkV1unf6uzLvqXRVWBU","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":386391},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"00a90655ef20a35dde06d65e08c0b9592b347ebe","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.8_1774440173205_0.2007462954694197","host":"s3://npm-registry-packages-npm-production"}},"0.2.9":{"name":"waveform-navigator","version":"0.2.9","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.9","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"a6115a080e935a3d022c246580ed73f34cf73796","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.9.tgz","fileCount":58,"integrity":"sha512-ryhiprdbEaMPbfwbUu4uI6RdKUy3osp7Yqah3+OHRhrYywTUDCPuep7HLDsQvXg1HlKLwq/CuMCLTmLIIAtsSg==","signatures":[{"sig":"MEYCIQDQaqZv00kw3qpqgZJuzRxzqAwMlCfxB2ypLHZFqW9uUgIhALbSdwOGOdsX3QUyf2Y/z4Ltjg4HsdywoMIc4L4Bhh2v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.9","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":430424},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"3a3fa7ad19dc0c1df1c4e3bad831609e41d21525","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.9_1775490846975_0.1833439155473553","host":"s3://npm-registry-packages-npm-production"}},"0.2.10":{"name":"waveform-navigator","version":"0.2.10","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.10","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"bec107258a25b974c2b727c50e2ade68dfadfab9","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.10.tgz","fileCount":58,"integrity":"sha512-ZRbzDtucepKdoG04RWlVsIPNadBWyt4va+G2+yEzAouwk1S866PRUrI1IQTt8b14OR8zHQpYSxyliCin5OzLrQ==","signatures":[{"sig":"MEUCIQDS4EIC3IPe3nWy/E2k9dTMoP4t5wQIzBWbCPFRBDXVkwIgUjKouR7/k3UWixgYDbU2byBLJ6zMf8YU8u58/g6uYhk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.10","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":452665},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"158d7a0dc98e1928435d2e7ee4d1b119ffe1e12f","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.10_1775501833778_0.05431262784450008","host":"s3://npm-registry-packages-npm-production"}},"0.2.11":{"name":"waveform-navigator","version":"0.2.11","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.11","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"61b11638c149be85310841a87df260f0e7917054","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.11.tgz","fileCount":58,"integrity":"sha512-LLvmc+XMzmYk+lqIJNvHRT9XONEAVjhDafO9ZwOFuKK7KoXEtsqrbAKC4rTjP/EuQBiJWuHSDvE2DTVi8BOmDQ==","signatures":[{"sig":"MEQCICmmQBVpU0ph4OQQdb4ShlyUVAVh7INZMjZ8X8oSAlUlAiBHncgPXtukr/DZEs0wTbtjFOrNwmcpjF2myduGuCJaBw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.11","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":501986},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"05b5216bda69d41ee8fc56dc15b26867c96a88f7","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.11_1775561716173_0.04538815089823145","host":"s3://npm-registry-packages-npm-production"}},"0.2.12":{"name":"waveform-navigator","version":"0.2.12","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.12","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"bb1aff83432aba294cdbdf9447eccdeb22caa281","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.12.tgz","fileCount":58,"integrity":"sha512-4EiBeOVhNfW0mya9Ob6owWmQialNNAFhrYjKEr6OgueLsbkUA/zA6skQtpXRILV348P4lIQTnLiib2d30gXp3Q==","signatures":[{"sig":"MEQCIGnWiJ7DKZUqHITS+7vwHGrFU3YawBWVgYIliVGko1bnAiAaOpXwknntWtoRX6IkmBDz3lilnzXnasGDVJe4ADmQ3Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.12","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":501986},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"3f3318aa58b019eb79cf0a6a5d48f241ad5899f3","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.12_1775567006833_0.9696328674995074","host":"s3://npm-registry-packages-npm-production"}},"0.2.13":{"name":"waveform-navigator","version":"0.2.13","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.13","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"698b216dbb5415c5bdbf0847087c43817b717891","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.13.tgz","fileCount":58,"integrity":"sha512-0pwGOnjIiJx0U6zQrlSGIT47yz6GVirb3OzjnQvA3GVgciEwgLdSYvLfDjxb0XDnVfVDoiAemFHA04toHfbFlA==","signatures":[{"sig":"MEQCIHLRSNu/hlF/blsAnlzerWUsCvh2SF1ABiLQILiTEneZAiAPbIrMEIZUPcAbvuTjy5YKpwHnDqRiw/kCIZ0WAj8Fyw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.13","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":501986},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"92a35573430f106b9c5fc65dda237a87002b07b7","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.13_1775569052162_0.4414164463130532","host":"s3://npm-registry-packages-npm-production"}},"0.2.14":{"name":"waveform-navigator","version":"0.2.14","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.14","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"4d728bddceaf5e41e3e42d4a1fb061ea1b257355","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.14.tgz","fileCount":58,"integrity":"sha512-iZ+I3J8sqg2z24HHrgmgEv70mw7ymNdXrV5jGB/hkt7XdSJcs/AWaIp/ZEbVJvkTk3Fsmta41JfKClR6DQKfug==","signatures":[{"sig":"MEQCIBBlSJ3rwl0444uWtj3lsCUflYKmY9J1FTCBOwkn65raAiAeto1kLmeiYdRghpx2vGfjEwQUEv5AWTOCwTk3Og8Sng==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.14","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":501986},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"5cbaffd5b1084baebf3c15c86a7dfbf1341d7de3","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.14_1775571248550_0.07120029432601904","host":"s3://npm-registry-packages-npm-production"}},"0.2.15":{"name":"waveform-navigator","version":"0.2.15","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.15","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"ccf5e94bdbd443516660a114734a77e5d0e57dd2","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.15.tgz","fileCount":58,"integrity":"sha512-kwXn5IOt9pUBj1XpgUp4ESTGWz2chnWOcFhV3SIcY1ZZlTYnSMBT06fKPVmsCKJKxpcBks9DoagJIQTt/kxZIA==","signatures":[{"sig":"MEQCID0po+QBNfxmkdMbuWQcoAt1rcL9zDqvNpvEOfkGwL/UAiBiYBpErpIafS2N+SRIyDdgv5/eGk2Hodum3HLezq9kQA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.15","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":501986},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"d647f1ea95991bab5c79a49e8942d21f23c279cb","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.12.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.15_1775574784038_0.09441561065644888","host":"s3://npm-registry-packages-npm-production"}},"0.2.16":{"name":"waveform-navigator","version":"0.2.16","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.16","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"8c095a74cc505a9f369e8df5e4af72e2b41fa7a5","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.16.tgz","fileCount":58,"integrity":"sha512-nqkbsfIcowndKmcs/snQLLsIle9i5E5bs0LTap8F6eKnrsr4PWlrAA2Quba6a4SVzkDpE1oxCBT5xqkqwaQi4g==","signatures":[{"sig":"MEUCIFlJwCoURwkPB0y7RRiUGZ913eO/75blSb1SJ3BrEfUbAiEA5HKc78CtVPQg7uOeKwkTfM9Fl85WCCwLbQjU/DUdPUU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.16","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":508102},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"c66154390673003f505d246b2a8a88bebca26bec","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.13.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.16_1777236379258_0.03008647295576994","host":"s3://npm-registry-packages-npm-production"}},"0.2.17":{"name":"waveform-navigator","version":"0.2.17","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.17","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"574ec09e3a66a9344c25a2cb49bd1ef59380fa78","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.17.tgz","fileCount":58,"integrity":"sha512-xWGS+/1cUZGshYNOAqVNR8bGgdQ96ah9nZ04gaNt5gmkNh4eTQb0X3jo+TVwHpsvpaTRwzr7PBJu+DzOO/P9DQ==","signatures":[{"sig":"MEQCIBBWtohWJIj8JHa1nh5+rk7tq2OlYH2cZJSX0EjzlGRzAiBc4G6QO1999Uptjr925mGZmyKKvr2gYulm3H9gWGKDhA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.17","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":508787},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"fdfdafb5701e2707b037bef9f9f081a2850d1ace","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.13.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.17_1777581661862_0.5136831544863356","host":"s3://npm-registry-packages-npm-production"}},"0.2.18":{"name":"waveform-navigator","version":"0.2.18","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.18","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"8483d27ec2ab8553ce57508dbf795604afd821b4","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.18.tgz","fileCount":59,"integrity":"sha512-KuQtNvrXxCD/Bw9IDySTqlPM8sSQdlzLpp1R8yq6YYfKNVPq0Vz5CyK5DHaSC/Q3QsEwDIJxs8BDdJbBtpy8mg==","signatures":[{"sig":"MEYCIQDUd+2kpKEvEGYv0Ij34kwr3t3EYrGNirQoKh1K+DS4CAIhAIihoYFkNYcX4uB/83vzMuiDaPUbNzb4cWBfnLrTfbI0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.18","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":512845},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"50652f4533af28ee22db38a7a69912bc8b9ac075","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.13.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.18_1777843720968_0.3399844304696302","host":"s3://npm-registry-packages-npm-production"}},"0.2.19":{"name":"waveform-navigator","version":"0.2.19","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.2.19","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"1fb7f7ba6ca2770e99691f5f519bcfd4bb8f13e4","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.2.19.tgz","fileCount":60,"integrity":"sha512-pcf4Yt4hTOKJiRBEyIv6fHRjYpEaJgf4xYHzXxTdbpd5/vd+SQHvNA+9XcP2UvUOyZwLMLw76U/AFi5nGvd6Mg==","signatures":[{"sig":"MEYCIQDm6t3QN1ZcVbqGG4V5C5xOqODiBWwtMyVTFBPXbC0lQAIhAI301R1DVlJ0XHmjzlkmjSe7NK862idHv12CDlx/7hKW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.2.19","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":531745},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"082b69aadc24436ebc404615ca3d8d8dfd06b672","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.13.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.2.19_1777912610695_0.7504889415675815","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"waveform-navigator","version":"0.3.0","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.3.0","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"1cf895d30fd157a47d41c1a71cd8c0578c8d625d","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.3.0.tgz","fileCount":60,"integrity":"sha512-yTQ7EtDyzCKaYKbmue6EqOerx3B69k/kNQGlTl3/Cj5NnxBIDgc+jX4QPUNlIG8KfX7U/bB8atPdhY0rQvtYtg==","signatures":[{"sig":"MEQCIDUHSe/J987S6EHkPBQnqoyoDrvBJpMRA/VHpNgzMjctAiBo3F6nZS5477S6Qa0U3mrSqqxdoAG+zNUqyPqutT2+jw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":583661},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"3572c28724b010d58cbac4a4974778e8de1a61d2","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.14.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.3.0_1778169631069_0.4885620182151087","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"waveform-navigator","version":"0.3.1","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.3.1","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"54061b976ecadff7c6cc3e9854280d27a875852a","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.3.1.tgz","fileCount":60,"integrity":"sha512-astsGah9nqwzReALLvkLpf8Y6UNaX10jSMg3WwlSb3Mlbxyf7r5PWCHcsEVOqPvMLuLosaA1ROtgO1fXM7Ecyw==","signatures":[{"sig":"MEYCIQDfhnZ7MDtpcZm46POT0ZPTT1AcSQQ70HkJzHBxexPkTwIhAJkWJX4E4jAClMXM+65GNUipDG2qUBedRswTGHUW234b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":589421},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"c90bcde91dbe32111c0930ef814737ccae917b88","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.14.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.3.1_1778258434188_0.7886622547122037","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"waveform-navigator","version":"0.3.2","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.3.2","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"f303eb8ed56b7e2117ce23fa3cb5fd09f554de20","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.3.2.tgz","fileCount":60,"integrity":"sha512-MZu+Rn88VRZXuHuZNOdKTUCtROC9/KFf4L76V5w10WnidUXp3apiiqi52VIrOacG+fK5NQy/Kfgb8OMoxQsdjQ==","signatures":[{"sig":"MEUCIAJK6j50E6O4bNJzMIn+BBfI7sg/5ofu4kcZVeRKsQP2AiEArMah+8aNXdEO+93wugXH8wKvQ7MiawYdAsRO4Q9omCk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.3.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":601048},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"920954a0527d3322c0284ebac9404a403c2f6b0c","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.14.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.3.2_1778792279306_0.9541357228347804","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"waveform-navigator","version":"0.4.0","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.4.0","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"c6670184971206141fd5d390599b25405980347a","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.4.0.tgz","fileCount":60,"integrity":"sha512-Sm7yc4Sj8akXZNkK0y4FyxUfRlDo+TWtKLXIoP2UJcqU0OkoAdpYBiieQFumuBtCUe/xccVYu1y/dNojdY2r+g==","signatures":[{"sig":"MEUCIQDVs7XIKwFENZkjLeSvWwKCraisGoYRP6HWJH0B9j4WdAIgHpdJ3oIGf/t7TrHnsyujb1haPcQS8g0HD9XopJa0uEc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":608856},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"ecf8d36961b691584c99a017db07cb00a0ea49e3","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.16.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.4.0_1780053026436_0.4003686996928695","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"waveform-navigator","version":"0.4.1","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.4.1","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"9c4e6f614a65cd082c699ab08f5c6b4bfbd2af54","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.4.1.tgz","fileCount":60,"integrity":"sha512-/moICHVLksk/NYMYEktHXP4Z+tJJEpALSjyN9L8VegRrvqTXW7PGPDOLGt7Z10yAIhtmv0rGcZNRqAcRl8ARBA==","signatures":[{"sig":"MEUCIGvohFBOoSjuf47iNr1LoRPDX0eAT8kWXXYaLbcQTwL7AiEA0JLvHkxhccbp47ihivDB0zdyQlZHE3rtaUJuxirqTE8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":641166},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"30ae14a67a32306107e6b2f831cd3ad552319c89","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"11.16.0","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.4.1_1781037879314_0.4200747618046736","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"waveform-navigator","version":"0.4.2","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.4.2","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"117b880bbe749ac84776bb9dc5d1ad7e22157f95","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.4.2.tgz","fileCount":64,"integrity":"sha512-3rBFropaSIudTSB6udyfLwswV3DDZ3iy/RVZ1j0INSI6Fr2Po8oyuIKWcWpgoS4tsrO6TZo3q64HlO5eThOl7Q==","signatures":[{"sig":"MEQCICAXxkqEp/x6aydcnkYWWTpgVxd2LBTPjBPFFnvy8HE3AiAQrEQP84z2TemhJXmhpvLdph/hhJ7sQAkbF0wB/aQd4Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":708694},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"da8c85e4a044de80889cf9f9030e2401333b2802","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"12.0.1","description":"A React component to display and navigate audio waveforms with custom controls.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.4.2_1783972120856_0.06390619160608835","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"waveform-navigator","version":"0.5.0","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.5.0","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"9bd9aa954f7c9ab59b1593b1dea0283c2cb62e57","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.5.0.tgz","fileCount":64,"integrity":"sha512-0o0MjzNbeFP4e+QXaPRU82Pa0F1d1AZUENuAm8i70jU9rRnx26AnLDq0ev4eKPt6VIoD6h79RgHCY1hB67N1ew==","signatures":[{"sig":"MEQCIG5hX8ApjiWJ6OqPHZ1EO0ygi1jGQx0OT6VH8/v8IZ57AiBW9+k2knbD/N46degUGCLv8D+/67BxUUqJ9SmEBSUeLw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":708713},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"976cd2e10d7d9e4d496f5773314950abfdfec88b","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"12.0.1","description":"A React component to display and navigate audio waveforms with custom controls and custom markers.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.5.0_1783972713820_0.11777788290632385","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"waveform-navigator","version":"0.5.1","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.5.1","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"6d3f263ecade86585e0faec7e2aa979180b70730","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.5.1.tgz","fileCount":64,"integrity":"sha512-5Zwut6fDpxFL4gufd+VFQUQOGX/9LR4aBwKCSzRiBawwj7oy1eYYJ8bIhFBBWE09pvARbnZB+dOlsQUFVqJL7A==","signatures":[{"sig":"MEYCIQCRHUPs9gv8v0uDDoTY99UPF0dokoYl097y3AUGbh+ryQIhAMok17tsEarx2uRZ+gfQjdTM2bTFRwz4fW6Ks645mdHi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.5.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":708713},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"9ba35ef9164f1d8efef749ab9f7e68d8940bdafd","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"12.0.1","description":"A React component to display and navigate audio waveforms with custom controls and custom markers.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.5.1_1785018717689_0.047411000386645696","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"waveform-navigator","version":"0.6.0","author":{"name":"KHeavyy"},"license":"MIT","_id":"waveform-navigator@0.6.0","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"dist":{"shasum":"2743e58db120213232eb750fce8df17dbc609492","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.6.0.tgz","fileCount":76,"integrity":"sha512-isOoOlm1cBH1kxXn3aSsAhbpNbTMzaKLpbT1fCX8yUqFg3mfzfvFbdkbdk2iF0TQDlNtiOHx6h+NrKsn2fh/Kg==","signatures":[{"sig":"MEUCIQDRaIbYg05EqAvLFc24KuqEqqpRwsTq3WliZBgRZTSZzgIgCY3nPw+pKG8BGqpGj/uQRLNfVSyRkXbLBly4ookPslE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":8085596},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"ab4a5eac3ca29687e1c532ef28bc5a1d1b94f631","scripts":{"dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\"","e2e":"playwright test","lint":"npm run type-check","test":"vitest run","build":"npm run clean && vite build && vite build --mode worker","clean":"rimraf dist","e2e:ui":"playwright test --ui","format":"prettier --write .","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"vite build --watch","format:check":"prettier --check .","test:coverage":"vitest run --coverage","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","prepublishOnly":"npm run build && npm run type-check && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"repository":{"url":"git+https://github.com/KHeavyy/waveform-navigator.git","type":"git"},"_npmVersion":"12.0.2","description":"A React component to display and navigate audio waveforms with custom controls and custom markers.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","vite":"^7.3.1","jsdom":"^27.4.0","pngjs":"^7.0.0","eslint":"^9.39.2","rimraf":"^6.1.2","vitest":"^4.0.17","prettier":"^3.8.1","happy-dom":"^20.3.4","@vitest/ui":"^4.0.17","pixelmatch":"^7.1.0","typescript":"^5.1.6","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","concurrently":"^8.2.0","vite-plugin-dts":"^4.5.4","@playwright/test":"^1.57.0","@types/react-dom":"^18.2.7","@vitest/coverage-v8":"^4.0.17","@axe-core/playwright":"^4.11.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.3.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@testing-library/jest-dom":"^6.9.1","@typescript-eslint/parser":"^8.54.0","eslint-plugin-react-hooks":"^7.0.1","@testing-library/user-event":"^14.6.1","@typescript-eslint/eslint-plugin":"^8.54.0"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/waveform-navigator_0.6.0_1785968389058_0.09035851036621634","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"waveform-navigator","version":"0.6.1","description":"A React component to display and navigate audio waveforms with custom controls and custom markers.","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"author":{"name":"KHeavyy"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/KHeavyy/waveform-navigator.git"},"homepage":"https://github.com/KHeavyy/waveform-navigator#readme","bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"engines":{"node":">=14.0.0"},"publishConfig":{"access":"public"},"sideEffects":["*.css"],"peerDependencies":{"react":">=18","react-dom":">=18"},"scripts":{"test":"vitest run","test:watch":"vitest","test:ui":"vitest --ui","test:coverage":"vitest run --coverage","e2e":"playwright test","e2e:ui":"playwright test --ui","e2e:debug":"playwright test --debug","e2e:headed":"playwright test --headed","visual:update":"UPDATE_SNAPSHOTS=1 playwright test e2e/visual.spec.ts","clean":"rimraf dist","build":"npm run clean && vite build && vite build --mode worker","build:watch":"vite build --watch","type-check":"tsc --noEmit","lint":"npm run type-check","lint:fix":"eslint --ext .ts,.tsx,.js,.jsx . --fix","lint:ci":"eslint --ext .ts,.tsx,.js,.jsx . --max-warnings 0","format":"prettier --write .","format:check":"prettier --check .","prepublishOnly":"npm run build && npm run type-check && npm test","prepare":"npm run build","dev":"concurrently \"npm run build:watch\" \"(cd demo && npm run dev)\""},"devDependencies":{"@axe-core/playwright":"^4.11.0","@playwright/test":"^1.57.0","@testing-library/jest-dom":"^6.9.1","@testing-library/react":"^16.3.2","@testing-library/user-event":"^14.6.1","@types/pngjs":"^6.0.5","@types/react":"^18.2.21","@types/react-dom":"^18.2.7","@typescript-eslint/eslint-plugin":"^8.54.0","@typescript-eslint/parser":"^8.54.0","@vitejs/plugin-react":"^5.1.2","@vitest/coverage-v8":"^4.0.17","@vitest/ui":"^4.0.17","c8":"^10.1.3","concurrently":"^8.2.0","eslint":"^9.39.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-react-hooks":"^7.0.1","happy-dom":"^20.3.4","jsdom":"^27.4.0","pixelmatch":"^7.1.0","pngjs":"^7.0.0","prettier":"^3.8.1","rimraf":"^6.1.2","typescript":"^5.1.6","vite":"^7.3.1","vite-plugin-dts":"^4.5.4","vitest":"^4.0.17"},"gitHead":"544648bd905d622f15b6f075fdb9840fe6150f27","_id":"waveform-navigator@0.6.1","_nodeVersion":"24.18.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-oc8j0xC5yX7XGbQzM2od7agJBya9Ldn8dw9wrt0E9F6UvgrazBFm5+fW97Yhxa/Yonhh01ewkudXseauKXWiSw==","shasum":"d9ecaf2309be95742be93bc1c76f38fdca5d4b48","tarball":"https://registry.npmjs.org/waveform-navigator/-/waveform-navigator-0.6.1.tgz","fileCount":77,"unpackedSize":8092403,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/waveform-navigator@0.6.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDxiC5kh4kfIVZaY8SizjEFfSy2CsP/KyGOx6EsCw1AjAIhAIuZy/up38VHwvLYCkB+v6ZfWqvkb/6HPY3ABy8DbaaA"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f3684c4e-3a21-49fd-98a9-6e2c4de197a2"}},"directories":{},"maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/waveform-navigator_0.6.1_1786138531695_0.3908630409310294"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-27T13:57:35.123Z","modified":"2026-08-07T21:35:32.254Z","0.1.0":"2026-01-27T13:57:35.353Z","0.2.0":"2026-01-27T16:36:41.244Z","0.2.1":"2026-01-27T17:01:58.595Z","0.2.2":"2026-01-27T23:01:44.927Z","0.2.3":"2026-01-29T14:56:49.374Z","0.2.4":"2026-01-29T16:33:53.941Z","0.2.5":"2026-01-29T21:16:53.824Z","0.2.6":"2026-01-29T21:36:08.515Z","0.2.7":"2026-03-24T21:41:58.140Z","0.2.8":"2026-03-25T12:02:53.352Z","0.2.9":"2026-04-06T15:54:07.135Z","0.2.10":"2026-04-06T18:57:13.964Z","0.2.11":"2026-04-07T11:35:16.386Z","0.2.12":"2026-04-07T13:03:27.027Z","0.2.13":"2026-04-07T13:37:32.382Z","0.2.14":"2026-04-07T14:14:08.852Z","0.2.15":"2026-04-07T15:13:04.227Z","0.2.16":"2026-04-26T20:46:19.438Z","0.2.17":"2026-04-30T20:41:02.054Z","0.2.18":"2026-05-03T21:28:41.156Z","0.2.19":"2026-05-04T16:36:50.841Z","0.3.0":"2026-05-07T16:00:31.328Z","0.3.1":"2026-05-08T16:40:34.391Z","0.3.2":"2026-05-14T20:57:59.447Z","0.4.0":"2026-05-29T11:10:26.611Z","0.4.1":"2026-06-09T20:44:39.490Z","0.4.2":"2026-07-13T19:48:41.043Z","0.5.0":"2026-07-13T19:58:33.997Z","0.5.1":"2026-07-25T22:31:57.859Z","0.6.0":"2026-08-05T22:19:49.327Z","0.6.1":"2026-08-07T21:35:31.938Z"},"bugs":{"url":"https://github.com/KHeavyy/waveform-navigator/issues"},"author":{"name":"KHeavyy"},"license":"MIT","homepage":"https://github.com/KHeavyy/waveform-navigator#readme","repository":{"type":"git","url":"git+https://github.com/KHeavyy/waveform-navigator.git"},"description":"A React component to display and navigate audio waveforms with custom controls and custom markers.","maintainers":[{"name":"kheavyy","email":"righter-lancet-0a@icloud.com"}],"readme":"# waveform-navigator\n\nA small React component to render an audio waveform and provide navigation + playback controls.\n\n**[Live Demo →](https://kheavyy.github.io/waveform-navigator/)**\n\n## Installation\n\n```\nnpm install waveform-navigator\n```\n\n## Visual Examples\n\nHere are examples demonstrating the waveform navigator's visual customization options:\n\n### Default Theme\n\n<img src=\"screenshots/default-theme.png\" alt=\"Waveform with default theme showing playhead position and progress\" width=\"800\"/>\n\nThe default blue theme with playhead (red line) showing current position and progress bar (darker blue) showing elapsed audio.\n\n### All Customizable Colors\n\n<img src=\"screenshots/custom-colors.png\" alt=\"Waveform with all custom colors including waveform, buttons, icons, and volume slider\" width=\"800\"/>\n\nDemonstrates every customizable color property with playhead and progress: waveform colors (bar, progress, playhead), button colors (play, rewind, forward), icon colors, and volume slider fill color.\n\n### Minimal UI\n\n<img src=\"screenshots/minimal-ui.png\" alt=\"Waveform navigator showing only the waveform visualization without playback controls\" width=\"800\"/>\n\nWaveform only (`showControls={false}`), perfect for custom UI implementations using the component's ref API.\n\n## Basic Usage\n\n```jsx\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport WaveformNavigator from 'waveform-navigator';\nimport 'waveform-navigator/styles.css'; // Don't forget to import styles!\n\nfunction App() {\n  // `audio` can be a URL string or a `File` object (from an `<input type=\"file\"/>`).\n  const url = '/path/to/audio.mp3';\n  return (\n    <div style={{ width: 900 }}>\n      <WaveformNavigator audio={url} width={900} height={140} />\n    </div>\n  );\n}\n\nReactDOM.render(<App />, document.getElementById('root'));\n```\n\n### TypeScript Support\n\nThe package includes full TypeScript type definitions. Types are automatically available when you import the component:\n\n```tsx\nimport WaveformNavigator from 'waveform-navigator';\nimport type { WaveformNavigatorProps } from 'waveform-navigator';\n```\n\n## API Reference\n\n### Props\n\n#### Basic Props\n\n- **`audio`** (string | File | null | undefined): The audio source - can be a URL string or a File object from an `<input type=\"file\"/>`.\n- **`width`** (number, default: 800): Width of the waveform canvas in pixels. When `responsive` is enabled, this serves as the fallback width.\n- **`height`** (number, default: 120): Height of the waveform canvas in pixels.\n- **`className`** (string, default: ''): Additional CSS class name for the container.\n\n#### Responsive Props\n\n- **`responsive`** (boolean, default: true): Enable automatic resizing to match container width using ResizeObserver. When enabled, the waveform adjusts the number of displayed bars by resampling the canonical peaks for the new width — the audio is not re-decoded and the saved canonical version is preserved.\n- **`responsiveDebounceMs`** (number, default: 150): Debounce delay in milliseconds for resize events. Higher values reduce resample frequency during continuous resizing.\n\n#### Worker Configuration Props\n\n- **`workerUrl`** (string | undefined): Optional custom URL for the Web Worker that computes waveform peaks. When not provided, the component uses the bundled worker. Use this when hosting the worker file separately (e.g., on a CDN) or when your bundler requires a specific worker path.\n- **`forceMainThread`** (boolean, default: false): Force peak computation to run on the main thread instead of using a Web Worker. Set to `true` to disable worker usage (useful for debugging or environments where workers are restricted).\n\n#### Pre-computed Peaks\n\n- **`precomputedPeaks`** (Float32Array | number[] | undefined): Optional pre-computed peaks data for instant waveform rendering without waiting for audio to load and decode.\n- **`peakComputationWidth`** (number, default: 1400): Standard width in pixels used to determine how many peak samples are computed from the audio, independent of the rendered component width. Peaks are resampled at render time so the waveform fits the responsive display width. Setting this to a typical desktop width ensures peaks captured on a small screen still look good when reloaded on a large one.\n\n`precomputedPeaks` accepts either a `Float32Array` (as returned by `onPeaksComputed`) or a plain `number[]` (e.g. after deserializing from JSON storage).\n\n**How it works:**\n- Peaks are always computed at `peakComputationWidth` (default 1400), so the canonical (saved) version is independent of the rendered width.\n- For display, the canonical peaks are resampled to `Math.floor(width / (barWidth + gap))` so the waveform fits the responsive container.\n- When `precomputedPeaks` is provided, it is treated as the canonical source — regardless of length — and the fetch and decode steps are **skipped entirely**. No network request is made for peak computation on subsequent views.\n- When the `audio` prop changes, `precomputedPeaks` is treated as stale and ignored — the new audio always produces a freshly computed waveform.\n- `onPeaksComputed` only fires when fresh peaks have actually been computed from the audio buffer (or progressively refined by the worker). It never fires for display-only resampling — your saved version is not overwritten with a smaller resampled copy when the user loads on a small screen.\n\n**Typical workflow:**\n\n```tsx\n// First visit — audio loads, peaks are computed and exposed via callback\n<WaveformNavigator\n  audio={audioUrl}\n  onPeaksComputed={(peaks) => {\n    // Persist peaks (localStorage, database, cache, etc.)\n    localStorage.setItem('peaks', JSON.stringify(Array.from(peaks)));\n  }}\n/>\n\n// Subsequent visits — pass saved peaks for instant rendering\nconst savedPeaks = JSON.parse(localStorage.getItem('peaks') ?? 'null');\n\n<WaveformNavigator\n  audio={audioUrl}\n  precomputedPeaks={savedPeaks ?? undefined}\n  onPeaksComputed={(peaks) => {\n    // Only called when freshly computed peaks differ from precomputedPeaks\n    localStorage.setItem('peaks', JSON.stringify(Array.from(peaks)));\n  }}\n/>\n```\n\nThis is especially useful for large audio files on slow connections: the waveform is immediately visible while the audio element itself continues loading in the background.\n\n#### Integrated Loudness (LUFS)\n\nITU-R BS.1770 integrated (gated) loudness is measured from the **same** `AudioBuffer` already decoded for peaks — no extra network request and no second `decodeAudioData` call. Hosts that omit `onLoudnessComputed` do zero additional work.\n\n- **`onLoudnessComputed`** ((result: `LoudnessResult`) => void): Fired once per decoded source, after `onPeaksComputed`, with:\n\n  | Field | Meaning |\n  |---|---|\n  | `integratedLufs` | BS.1770 integrated loudness in LUFS. `-Infinity` for digital silence, files shorter than 400 ms, or when no gating block survives. Never `NaN`. |\n  | `sampleRate` | Sample rate of the decoded buffer (Hz). |\n  | `channels` | Channel count of the decoded buffer. |\n\n- **`precomputedLoudness`** (number | undefined): When provided, skips loudness computation entirely (mirrors `precomputedPeaks`). Pass a previously persisted `integratedLufs` value.\n\n**Interaction with `precomputedPeaks`:** when `precomputedPeaks` causes fetch/decode to be skipped, there is no `AudioBuffer` to measure — loudness cannot be computed either. Persist peaks and loudness together on the first load, and pass both back on subsequent mounts.\n\n**Mono vs dual-mono:** a mono file and the same content as dual-mono stereo measure roughly **3 LU apart**, because the channel sum has two contributing channels rather than one. This is correct per BS.1770 (ffmpeg's `loudnorm` `input_i` shows the same gap).\n\n**Typical workflow:**\n\n```tsx\n<WaveformNavigator\n  audio={audioUrl}\n  onLoudnessComputed={(result) => {\n    // Persist for A/B level matching / skip on next mount\n    localStorage.setItem('lufs', String(result.integratedLufs));\n  }}\n/>\n\n// Later — skip recomputation\n<WaveformNavigator\n  audio={audioUrl}\n  precomputedLoudness={Number(localStorage.getItem('lufs'))}\n  onLoudnessComputed={(result) => {\n    localStorage.setItem('lufs', String(result.integratedLufs));\n  }}\n/>\n```\n\nMeasurement is time-sliced on the main thread so a multi-minute stereo file does not block the UI. The pure `computeIntegratedLoudness(channels, sampleRate)` helper is also exported for offline use.\n\n- **`barWidth`** (number, default: 3): Width of each waveform bar in pixels.\n- **`gap`** (number, default: 2): Gap between waveform bars in pixels.\n- **`styles`** (WaveformNavigatorStyles | undefined): A centralized style configuration object for customizing all visual aspects of the waveform and controls. Provides a clean way to configure colors without needing individual props for each element.\n\n##### WaveformNavigatorStyles Interface\n\nThe `styles` prop accepts an object with the following optional properties:\n\n**Waveform Colors:**\n\n- `barColor` (string, default: '#2b6ef6'): Color of the waveform bars.\n- `progressColor` (string, default: '#0747a6'): Color of the played portion of the waveform.\n- `backgroundColor` (string, default: 'transparent'): Background color of the waveform canvas.\n- `playheadColor` (string, default: '#ff4d4f'): Color of the playhead indicator.\n\n**Marker Colors:**\n\n- `markerColor` (string, default: '#10b981'): Color of marker lines and background for default marker labels.\n- `markerLabelColor` (string, default: '#ffffff'): Text color for default marker labels.\n\n**Control Button Colors:**\n\n- `playButtonColor` (string, default: '#111827'): Background color of the play/pause button.\n- `playIconColor` (string, default: '#fff'): Color of the play/pause icon.\n- `rewindButtonColor` (string, default: '#fff'): Background color of the rewind button.\n- `rewindIconColor` (string, default: '#111827'): Color of the rewind icon.\n- `forwardButtonColor` (string, default: '#fff'): Background color of the forward button.\n- `forwardIconColor` (string, default: '#111827'): Color of the forward icon.\n\n**Volume Control Colors:**\n\n- `volumeSliderFillColor` (string, default: '#111827'): Color of the volume slider fill and thumb.\n- `volumeIconColor` (string, default: '#374151'): Color of the volume icon. The icon dynamically changes based on volume level (muted, low, high).\n\n**Time Display Colors:**\n\n- `timeColor` (string, default: '#374151'): Color of the elapsed/total time display below the waveform.\n\n**Example:**\n\n```tsx\n<WaveformNavigator\n  audio=\"/audio.mp3\"\n  styles={{\n    barColor: '#8b5cf6',\n    progressColor: '#6d28d9',\n    playheadColor: '#ec4899',\n    playButtonColor: '#7c3aed',\n    playIconColor: '#fff',\n    volumeSliderFillColor: '#7c3aed',\n  }}\n/>\n```\n\n**Note:** The volume icon is clickable and will toggle mute/unmute. When unmuted, it automatically restores the previous volume level.\n\n#### Markers\n\nThe component supports displaying markers at specific time positions on the waveform. Markers can be used to indicate important moments, chapters, or annotations in the audio.\n\n- **`markers`** (Marker[] | undefined): Array of marker objects to display on the waveform. Each marker specifies a time position and optionally custom rendering.\n- **`onMarkerClick`** ((marker, index, event) => void | undefined): Fires when a marker's hit region is clicked or tapped. Supplying this (or `onMarkerHover`) enables marker hit-testing; when a click hits a marker, the default click-to-seek is suppressed so your handler decides what happens.\n- **`onMarkerHover`** ((marker | null, index | null) => void | undefined): Fires when the hovered marker changes — with `(marker, index)` on enter/change and `(null, null)` when the pointer leaves all markers.\n- **`markerHitRadius`** (number, default: `2`): Extra padding in CSS pixels around the default M1/M2/… label badge hit region. The stem below the label is not part of the default hit target.\n\n**Marker Interface:**\n\n```tsx\nimport type {\n  Marker,\n  MarkerRenderProps,\n  MarkerHitTestArgs,\n} from 'waveform-navigator';\n\ninterface Marker {\n  time: number; // Time position in seconds where the marker should be displayed\n  id?: string; // Optional stable identity echoed back in onMarkerClick/onMarkerHover\n  markup?: (props: MarkerRenderProps) => void; // Optional custom rendering function\n  hitTest?: (args: MarkerHitTestArgs) => boolean; // Optional custom hit region\n}\n\ninterface MarkerRenderProps {\n  ctx: CanvasRenderingContext2D; // Canvas context for drawing\n  x: number; // X position of the marker in pixels\n  height: number; // Height of the waveform canvas in pixels\n  index: number; // Index of the marker in the markers array\n  marker: Marker; // The marker object\n  hovered?: boolean; // True while the pointer is over this marker's hit region\n}\n\ninterface MarkerHitTestArgs {\n  x: number; // Pointer x in canvas bounding-rect (CSS px) coordinates\n  y: number; // Pointer y in canvas bounding-rect (CSS px) coordinates\n  markerX: number; // (marker.time / duration) * width\n  width: number; // Canvas bounding-rect width\n  height: number; // Canvas bounding-rect height\n}\n```\n\n**Default Marker Appearance:**\n\nBy default, markers are rendered as a vertical line spanning the full height of the waveform with a label showing the marker number (M1, M2, etc.):\n\n```tsx\n<WaveformNavigator\n  audio=\"/audio.mp3\"\n  markers={[\n    { time: 10 },  // Marker at 10 seconds (labeled M1)\n    { time: 30 },  // Marker at 30 seconds (labeled M2)\n    { time: 60 },  // Marker at 60 seconds (labeled M3)\n  ]}\n/>\n```\n\n<img src=\"screenshots/markers-default.png\" alt=\"Default marker appearance showing three green markers (M1, M2, M3) on the waveform\" width=\"800\"/>\n\n**Custom Marker Rendering:**\n\nYou can provide a custom `markup` function to render markers with your own design:\n\n```tsx\nconst customMarker = ({ ctx, x, height }: MarkerRenderProps) => {\n  // Draw a custom flag-style marker\n  ctx.fillStyle = '#ff6b6b';\n  ctx.beginPath();\n  ctx.moveTo(x, 10);\n  ctx.lineTo(x + 15, 20);\n  ctx.lineTo(x, 30);\n  ctx.closePath();\n  ctx.fill();\n  \n  // Draw the pole\n  ctx.fillRect(x - 1, 10, 2, height - 10);\n};\n\n<WaveformNavigator\n  audio=\"/audio.mp3\"\n  markers={[\n    { time: 15 },                          // Default marker at 15s\n    { time: 45, markup: customMarker },   // Custom marker at 45s\n  ]}\n/>\n```\n\n<img src=\"screenshots/markers-custom.png\" alt=\"Custom marker rendering showing default green markers and a custom red flag-style marker (M2)\" width=\"800\"/>\n\n**Customizing Marker Colors:**\n\nUse the `styles` prop to customize the default marker colors:\n\n```tsx\n<WaveformNavigator\n  audio=\"/audio.mp3\"\n  markers={[\n    { time: 20 },\n    { time: 40 },\n  ]}\n  styles={{\n    markerColor: '#ff6b6b',      // Red marker lines and label backgrounds\n    markerLabelColor: '#ffffff',  // White label text\n  }}\n/>\n```\n\n**Interactive Markers (click & hover):**\n\nProvide `onMarkerClick` and/or `onMarkerHover` to make markers individually clickable and hoverable — for example, to render speech-bubble comment markers and know exactly which comment was clicked:\n\n```tsx\nconst commentMarker = ({ ctx, x, height, hovered, marker }: MarkerRenderProps) => {\n  ctx.fillStyle = hovered ? '#1d4ed8' : '#2b6ef6';\n  ctx.beginPath();\n  ctx.arc(x, 16, hovered ? 10 : 8, 0, Math.PI * 2);\n  ctx.fill();\n  ctx.fillRect(x - 1, 16, 2, height - 16);\n};\n\nconst comments = [\n  { time: 12, id: 'comment-1' },\n  { time: 48, id: 'comment-2' },\n];\n\n<WaveformNavigator\n  audio=\"/audio.mp3\"\n  markers={comments.map((c) => ({ time: c.time, id: c.id, markup: commentMarker }))}\n  onMarkerClick={(marker) => openComment(marker.id)}\n  onMarkerHover={(marker) => setHoveredCommentId(marker?.id ?? null)}\n/>\n```\n\nWhen neither `onMarkerClick` nor `onMarkerHover` is supplied, markers remain purely decorative and clicking anywhere on the waveform always seeks — the same behavior as before these props existed.\n\n**Notes:**\n\n- Markers are positioned based on their `time` value relative to the audio duration.\n- Markers outside the valid time range (time < 0 or time > duration) will not be rendered.\n- The marker index (shown in default labels as M1, M2, etc.) corresponds to the marker's position in the array, starting from 1.\n- Custom markup functions receive the canvas context and should handle all drawing operations.\n- The default hit region for a marker is the M1/M2/… label badge (plus `markerHitRadius` padding), not the full-height stem — so clicks on the waveform near markers can still seek. Override the region per-marker with `hitTest`.\n- When multiple markers' hit regions overlap, the nearest one to the pointer wins; ties resolve to the lowest array index.\n- On touch devices, tapping a marker fires `onMarkerClick` without seeking; dragging away from the initial touch point falls back to the normal scrub-seek behavior.\n\n#### Controlled Props\n\nThe component supports both controlled and uncontrolled modes for playback position:\n\n- **`controlledCurrentTime`** (number | undefined): When provided, the component operates in controlled mode where the parent manages the playback position. The audio element's currentTime will be synced with this value.\n- **`onCurrentTimeChange`** ((time: number) => void): Callback fired when the internal time changes (in uncontrolled mode). Use this with `controlledCurrentTime` to implement controlled mode.\n- **`audioElementRef`** (React.MutableRefObject<HTMLAudioElement | null>): A ref that will be populated with the internal audio element, allowing direct access to the HTMLAudioElement API.\n\n#### Event Callbacks\n\n- **`onPlay`** (() => void): Callback fired when audio playback starts.\n- **`onPause`** (() => void): Callback fired when audio playback pauses.\n- **`onEnded`** (() => void): Callback fired when audio playback ends.\n- **`onLoaded`** ((duration: number) => void): Callback fired when audio metadata is loaded, providing the duration in seconds.\n- **`onTimeUpdate`** ((currentTime: number) => void): Callback fired during playback as the current time updates, providing the current time in seconds.\n- **`onPeaksComputed`** ((peaks: Float32Array) => void): Callback fired when canonical waveform peaks are freshly computed (and differ from any provided `precomputedPeaks`). The reported peaks are sampled at `peakComputationWidth`, not the current rendered width, so the same value renders well on any screen size. Use this to persist peaks for faster future loads. If `precomputedPeaks` were provided and the computed result matches, this callback is skipped. It does not fire for display-only resampling on resize.\n- **`onLoudnessComputed`** ((result: `LoudnessResult`) => void): Callback fired once per decoded source with ITU-R BS.1770 integrated loudness, after `onPeaksComputed`. Only computed when this prop is set and `precomputedLoudness` is not provided. See [Integrated Loudness (LUFS)](#integrated-loudness-lufs).\n- **`onLoadingChange`** ((isLoading: boolean) => void): Callback fired whenever the audio loading/buffering state changes. Receives `true` while the browser is fetching or buffering after play is requested, and `false` once playback starts, pauses, or errors. Mirrors the spinner shown on the play button during loading.\n- **`onVolumeChange`** ((volume: number) => void): Callback fired whenever the user changes the volume via the slider or mute/unmute toggle. Receives the new clamped value (0–1). Pair with `defaultVolume` to persist and restore volume across sessions (e.g. `localStorage`).\n- **`onError`** ((error: Error, type: 'audio' | 'waveform') => void): Callback fired when an error occurs during audio loading or waveform computation. The `type` parameter indicates whether the error occurred during audio playback ('audio') or waveform generation ('waveform'). Common errors include CORS issues, unsupported audio formats, and decoding failures.\n\n#### Accessibility Props\n\n- **`keyboardSmallStep`** (number, default: 5): Step size in seconds for small seek operations (ArrowLeft/ArrowRight keys).\n- **`keyboardLargeStep`** (number | undefined): Step size in seconds for large seek operations (PageUp/PageDown keys). If not provided, defaults to 10% of the audio duration.\n- **`disableKeyboardControls`** (boolean, default: false): Disable built-in keyboard navigation. Set to `true` if you want to implement custom keyboard handling.\n- **`ariaLabel`** (string, default: 'Audio waveform seek bar'): Accessible label for the waveform control, announced to screen readers.\n\n#### UI Control Props\n\n- **`showControls`** (boolean, default: true): Show or hide the built-in playback controls. Set to `false` to display only the waveform, useful when implementing custom controls or minimal UI. When hidden, you can control playback programmatically using the component ref.\n- **`showTime`** (boolean, default: true): Show or hide the playback time display inside the controls bar. Has no effect when `showControls` is `false`.\n- **`showVolume`** (boolean, default: true): Show or hide the volume control inside the controls bar. Has no effect when `showControls` is `false`.\n- **`defaultVolume`** (number, default: 1): Initial volume on mount, clamped to 0–1. Use this to restore a previously persisted level (e.g. from `localStorage`). The value is only read once on mount; it does not update the volume if changed after render.\n- **`onVolumeChange`** ((volume: number) => void): Callback fired whenever the user changes the volume via the slider or mute/unmute toggle. Receives the new clamped value (0–1). Use this alongside `defaultVolume` to persist and restore volume across sessions.\n- **`renderButtons`** ((props: `RenderButtonsProps`) => ReactNode | undefined): Render function that replaces the built-in rewind/play/forward button group with custom content. The function receives current playback state and control handlers (see `RenderButtonsProps` below). `showTime` and `showVolume` still apply, so you can keep the built-in time display and volume slider while supplying entirely custom buttons. Has no effect when `showControls` is `false`.\n- **`preload`** (`'none'` | `'metadata'` | `'auto'`, default: `'none'`): Controls the initial [`preload`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio#preload) attribute of the underlying `<audio>` element.\n  - `'none'` (default) — no bytes are downloaded until the user presses play. Combine with `precomputedPeaks` for a fully deferred-load experience.\n  - `'metadata'` — only file headers are fetched on mount, enabling accurate duration display before the user interacts.\n  - `'auto'` — the browser eagerly downloads the full file on mount (pre-v2 behaviour).\n- **`initialDuration`** (number | undefined): Seed the displayed duration (in seconds) before the audio element has loaded any metadata. This is required when using `preload=\"none\"` together with `precomputedPeaks` — without it `duration` stays at 0 and click-to-seek is disabled. Persist this value alongside your peaks (e.g. save it from `onLoaded`) and pass it back on subsequent page loads. The real duration reported by the audio element will override it once `loadedmetadata` fires.\n\n### Programmatic Control (Ref Forwarding)\n\nThe component supports ref forwarding to expose imperative methods for programmatic control. This is useful for implementing custom UI controls or controlling playback from parent components.\n\n#### Ref Handle Type\n\n```tsx\nimport type { WaveformNavigatorHandle } from 'waveform-navigator';\n\ninterface WaveformNavigatorHandle {\n  play: () => Promise<void>;\n  pause: () => void;\n  seek: (time: number) => void;\n  resumeAudioContext: () => Promise<void>;\n}\n```\n\n#### Methods\n\n- **`play()`**: Start or resume audio playback. Returns a Promise that resolves when playback starts.\n- **`pause()`**: Pause audio playback.\n- **`seek(time)`**: Seek to a specific time in seconds.\n- **`resumeAudioContext()`**: Resume any suspended AudioContext (required for Safari/iOS before playing audio). Returns a Promise that resolves when the context is resumed.\n\n### RenderButtonsProps Type\n\nProps passed to the `renderButtons` render function. Import this type when building custom button components.\n\n```tsx\nimport type { RenderButtonsProps } from 'waveform-navigator';\n\ninterface RenderButtonsProps {\n  /** Whether audio is currently playing */\n  isPlaying: boolean;\n  /** Whether audio is buffering/loading */\n  isLoading: boolean;\n  /** Toggle play/pause */\n  onTogglePlay: () => void;\n  /** Seek by a relative delta in seconds (negative = rewind) */\n  seek: (delta: number) => void;\n  /** Seek to an absolute time in seconds */\n  seekTo: (time: number) => void;\n}\n```\n\n## Usage Examples\n\n### Custom Buttons with Built-in Time and Volume\n\nReplace only the button group while keeping the time display and volume slider:\n\n```tsx\nimport WaveformNavigator from 'waveform-navigator';\nimport type { RenderButtonsProps } from 'waveform-navigator';\nimport 'waveform-navigator/styles.css';\n\nfunction App() {\n  const renderButtons = ({\n    isPlaying,\n    isLoading,\n    onTogglePlay,\n    seek,\n  }: RenderButtonsProps) => (\n    <>\n      <button onClick={() => seek(-10)}>⏮ −10s</button>\n      <button onClick={onTogglePlay} disabled={isLoading}>\n        {isPlaying ? '⏸ Pause' : '▶ Play'}\n      </button>\n      <button onClick={() => seek(10)}>+10s ⏭</button>\n      {/* Add extra actions e.g. next track */}\n      <button onClick={handleNextTrack}>Next ›</button>\n    </>\n  );\n\n  return (\n    <WaveformNavigator\n      audio=\"/path/to/audio.mp3\"\n      renderButtons={renderButtons}\n      showTime={true}   // keep built-in time display (default)\n      showVolume={true} // keep built-in volume slider (default)\n    />\n  );\n}\n```\n\n### Programmatic Control with Custom UI\n\nControl playback from parent component without showing built-in controls:\n\n```tsx\nimport { useRef } from 'react';\nimport WaveformNavigator from 'waveform-navigator';\nimport type { WaveformNavigatorHandle } from 'waveform-navigator';\nimport 'waveform-navigator/styles.css';\n\nfunction App() {\n  const waveformRef = useRef<WaveformNavigatorHandle>(null);\n\n  const handlePlay = async () => {\n    // Resume AudioContext first (required for Safari/iOS)\n    await waveformRef.current?.resumeAudioContext();\n    await waveformRef.current?.play();\n  };\n\n  const handlePause = () => {\n    waveformRef.current?.pause();\n  };\n\n  const handleSeekTo30 = () => {\n    waveformRef.current?.seek(30);\n  };\n\n  return (\n    <div>\n      <WaveformNavigator\n        ref={waveformRef}\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        showControls={false} // Hide built-in controls\n      />\n\n      {/* Custom controls */}\n      <div style={{ marginTop: 16, display: 'flex', gap: 8 }}>\n        <button onClick={handlePlay}>Play</button>\n        <button onClick={handlePause}>Pause</button>\n        <button onClick={handleSeekTo30}>Jump to 30s</button>\n      </div>\n    </div>\n  );\n}\n```\n\n### Minimal Waveform-Only UI\n\nDisplay only the waveform for visualization purposes:\n\n```tsx\nfunction App() {\n  return (\n    <div style={{ width: '100%', maxWidth: 1200 }}>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        height={80}\n        showControls={false}\n        styles={{\n          barColor: '#38bdf8',\n          progressColor: '#0284c7',\n          playheadColor: '#f43f5e',\n        }}\n      />\n    </div>\n  );\n}\n```\n\n### Custom Styled Controls\n\nCustomize the appearance of the waveform and playback controls:\n\n```tsx\nfunction App() {\n  return (\n    <div style={{ width: '100%', maxWidth: 1200 }}>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        styles={{\n          // Waveform colors\n          barColor: '#8b5cf6',\n          progressColor: '#6d28d9',\n          playheadColor: '#ec4899',\n          // Control button colors\n          playButtonColor: '#7c3aed',\n          playIconColor: '#fff',\n          rewindButtonColor: '#f3f4f6',\n          rewindIconColor: '#6b7280',\n          forwardButtonColor: '#f3f4f6',\n          forwardIconColor: '#6b7280',\n          // Volume control colors\n          volumeSliderFillColor: '#7c3aed',\n          volumeIconColor: '#6b7280',\n        }}\n      />\n    </div>\n  );\n}\n```\n\n**Note:** The volume icon automatically changes based on the volume level:\n\n- **Muted** (0%): Speaker with slash\n- **Low** (< 50%): Speaker with one sound wave\n- **High** (>50%): Speaker with two sound waves\n\nClick the volume icon to toggle mute/unmute. When unmuted, it restores the previous volume level.\n\n### Combining Ref Control with Event Callbacks\n\n```tsx\nfunction App() {\n  const waveformRef = useRef<WaveformNavigatorHandle>(null);\n  const [isPlaying, setIsPlaying] = useState(false);\n  const [currentTime, setCurrentTime] = useState(0);\n\n  const togglePlayback = async () => {\n    if (isPlaying) {\n      waveformRef.current?.pause();\n    } else {\n      await waveformRef.current?.resumeAudioContext();\n      await waveformRef.current?.play();\n    }\n  };\n\n  return (\n    <div>\n      <WaveformNavigator\n        ref={waveformRef}\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        showControls={false}\n        onPlay={() => setIsPlaying(true)}\n        onPause={() => setIsPlaying(false)}\n        onTimeUpdate={setCurrentTime}\n      />\n\n      <div style={{ marginTop: 16 }}>\n        <button onClick={togglePlayback}>{isPlaying ? 'Pause' : 'Play'}</button>\n        <span style={{ marginLeft: 16 }}>\n          Current time: {currentTime.toFixed(2)}s\n        </span>\n      </div>\n    </div>\n  );\n}\n```\n\n### Uncontrolled Mode (Default)\n\nThe component manages its own playback state:\n\n```jsx\nfunction App() {\n  return (\n    <WaveformNavigator\n      audio=\"/path/to/audio.mp3\"\n      width={900}\n      height={140}\n      onPlay={() => console.log('Playing')}\n      onPause={() => console.log('Paused')}\n      onTimeUpdate={(time) => console.log('Current time:', time)}\n    />\n  );\n}\n```\n\n### Controlled Mode\n\nParent component manages the playback position:\n\n```jsx\nfunction App() {\n  const [currentTime, setCurrentTime] = useState(0);\n\n  return (\n    <div>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        controlledCurrentTime={currentTime}\n        onCurrentTimeChange={setCurrentTime}\n        onTimeUpdate={(time) => console.log('Time update:', time)}\n      />\n      <button onClick={() => setCurrentTime(30)}>Jump to 30s</button>\n    </div>\n  );\n}\n```\n\n### Accessing the Audio Element\n\n```tsx\nfunction App() {\n  const audioRef = useRef<HTMLAudioElement | null>(null);\n\n  const handleCustomControl = () => {\n    if (audioRef.current) {\n      audioRef.current.playbackRate = 1.5; // Speed up playback\n    }\n  };\n\n  return (\n    <div>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        audioElementRef={audioRef}\n      />\n      <button onClick={handleCustomControl}>Speed up 1.5x</button>\n    </div>\n  );\n}\n```\n\n### Monitoring Waveform Computation\n\n```jsx\nfunction App() {\n  const [peaksReady, setPeaksReady] = useState(false);\n\n  return (\n    <div>\n      {!peaksReady && <div>Computing waveform...</div>}\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        onPeaksComputed={(peaks) => {\n          console.log('Peaks computed:', peaks.length, 'bars');\n          setPeaksReady(true);\n        }}\n        onLoaded={(duration) => {\n          console.log('Audio loaded, duration:', duration, 'seconds');\n        }}\n      />\n    </div>\n  );\n}\n```\n\n### Pre-computed Peaks for Instant Rendering\n\nFor large files or slow connections, save the peaks from the first load and pass them back on subsequent visits so the waveform renders before any audio is fetched:\n\n```tsx\nfunction AudioPlayer({ audioUrl }: { audioUrl: string }) {\n  const storageKey = `peaks:${audioUrl}`;\n\n  // Load any previously saved peaks from storage\n  const [savedPeaks] = useState<number[] | null>(() => {\n    try {\n      const raw = localStorage.getItem(storageKey);\n      return raw ? JSON.parse(raw) : null;\n    } catch {\n      return null;\n    }\n  });\n\n  return (\n    <WaveformNavigator\n      audio={audioUrl}\n      // savedPeaks (if present) seed the waveform instantly and are\n      // resampled to fit the current display width\n      precomputedPeaks={savedPeaks ?? undefined}\n      onPeaksComputed={(peaks) => {\n        // Fired only when freshly computed peaks differ from savedPeaks\n        // (or when no savedPeaks were provided)\n        localStorage.setItem(storageKey, JSON.stringify(Array.from(peaks)));\n      }}\n    />\n  );\n}\n```\n\n**Notes:**\n- `precomputedPeaks` accepts both `Float32Array` (direct from `onPeaksComputed`) and `number[]` (JSON-deserialized).\n- The provided array is treated as the canonical source regardless of length and resampled to fit the current display width — saved peaks always render even if their length doesn't match the current dimensions.\n- When `audio` changes (e.g. user selects a different file), `precomputedPeaks` is ignored for the new load so fresh peaks are always computed and exposed.\n\n### Error Handling\n\nThe component provides comprehensive error handling for common failure scenarios:\n\n```tsx\nfunction App() {\n  const [error, setError] = useState<string | null>(null);\n\n  return (\n    <div>\n      {error && (\n        <div style={{ color: 'red', padding: 12, marginBottom: 12 }}>\n          Error: {error}\n        </div>\n      )}\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        onError={(err, type) => {\n          console.error(`${type} error:`, err.message);\n          setError(err.message);\n        }}\n        onLoaded={() => {\n          setError(null); // Clear error on successful load\n        }}\n      />\n    </div>\n  );\n}\n```\n\nThe `onError` callback receives two parameters:\n\n- **error**: An Error object with a descriptive message\n- **type**: Either 'audio' (playback errors) or 'waveform' (visualization errors)\n\nCommon error types and their meanings:\n\n- **\"Audio format not supported or CORS error\"**: The audio file format is not supported by the browser, or cross-origin restrictions are preventing access\n- **\"Audio decode error: File format may be unsupported or corrupted\"**: The audio file could not be decoded (may be corrupted or in an unsupported format)\n- **\"CORS error: Audio file cannot be loaded due to cross-origin restrictions\"**: Cross-Origin Resource Sharing (CORS) policy is blocking access to the audio file\n- **\"Network error: Unable to fetch audio file\"**: Network connectivity issue or the file doesn't exist\n\nWhen an error occurs, the component displays a user-friendly error overlay on the waveform canvas with an icon and message.\n\n### Responsive Mode (Default)\n\nThe component automatically adapts to container width changes:\n\n```jsx\nfunction App() {\n  return (\n    <div style={{ width: '100%', maxWidth: 1200 }}>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        height={140}\n        // responsive is true by default\n      />\n    </div>\n  );\n}\n```\n\n#### Mobile-Adaptive Controls\n\nThe playback controls automatically reflow based on the **component's own width** (not the viewport), using CSS Container Queries. This means the layout adapts correctly whether the component is embedded in a narrow column, a modal, or an actual mobile browser.\n\n- **≤ 640px container** — the horizontal volume slider narrows to save space.\n- **≤ 480px container** — all controls collapse onto a single compact row (time · buttons · speaker icon). Button sizes reduce and the horizontal volume slider is hidden.\n- **Volume on narrow containers** — tapping the speaker icon opens a floating vertical volume popup anchored above the speaker button. Tapping the icon again (or clicking anywhere outside) closes it. This keeps the layout stable without pushing content up or down.\n\nNo configuration is needed — this behaviour is automatic.\n\nTo disable responsive behavior and use fixed width:\n\n```jsx\nfunction App() {\n  return (\n    <div style={{ width: 900 }}>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        width={900}\n        height={140}\n        responsive={false}\n      />\n    </div>\n  );\n}\n```\n\nCustomize debounce delay for responsive resizing:\n\n```jsx\nfunction App() {\n  return (\n    <div style={{ width: '100%' }}>\n      <WaveformNavigator\n        audio=\"/path/to/audio.mp3\"\n        height={140}\n        responsive={true}\n        responsiveDebounceMs={200} // Wait 200ms before recomputing\n      />\n    </div>\n  );\n}\n```\n\n## Web Worker and Performance\n\n### How Peak Computation Works\n\nThe component uses a Web Worker to compute waveform peaks off the main thread for better performance, especially with large audio files. The worker processes audio data in chunks and streams partial results back, enabling progressive waveform rendering.\n\n**Key features:**\n\n- **Automatic fallback:** If Web Workers are not supported or worker creation fails (e.g., due to CSP restrictions), the component automatically falls back to main-thread computation.\n- **Immediate display:** Initial peaks are computed synchronously on the main thread for instant display, then refined by the worker.\n- **No blocking:** The worker runs asynchronously, keeping the UI responsive during peak computation.\n\n### Bundler Configuration\n\n**Default Behavior:** The component uses an inline worker that is bundled directly into the library (as a base64-encoded data URL). This works out of the box with all modern bundlers and requires no additional configuration. The worker code is automatically extracted and executed in a separate thread when needed.\n\nThe component is designed to work with modern bundlers that support `new URL(..., import.meta.url)` syntax for worker bundling.\n\n#### Vite (Recommended - Works Out of the Box)\n\nVite automatically handles Web Worker bundling with no additional configuration needed:\n\n```jsx\nimport WaveformNavigator from 'waveform-navigator';\n\nfunction App() {\n  return (\n    <WaveformNavigator audio=\"/path/to/audio.mp3\" width={900} height={140} />\n  );\n}\n```\n\nThe component will use the inline worker by default, with zero configuration required.\n\n#### Webpack 5\n\nWebpack 5 supports the same syntax as Vite. No additional configuration is required for the bundled worker:\n\n```jsx\nimport WaveformNavigator from 'waveform-navigator';\n\nfunction App() {\n  return (\n    <WaveformNavigator audio=\"/path/to/audio.mp3\" width={900} height={140} />\n  );\n}\n```\n\n#### Rollup\n\nFor Rollup, ensure you're using `@rollup/plugin-node-resolve` and your output format supports dynamic imports:\n\n```js\n// rollup.config.js\nimport resolve from '@rollup/plugin-node-resolve';\n\nexport default {\n  // ... other config\n  plugins: [\n    resolve(),\n    // ... other plugins\n  ],\n  output: {\n    format: 'esm', // or 'system'\n    // ...\n  },\n};\n```\n\n#### Custom Worker Hosting\n\nIn most cases, you don't need to use custom worker hosting. However, if you have specific requirements (e.g., strict Content Security Policy that blocks data URLs, or you want to host the worker on a CDN), you can provide a custom worker URL:\n\n```jsx\nimport WaveformNavigator from 'waveform-navigator';\n\nfunction App() {\n  return (\n    <WaveformNavigator\n      audio=\"/path/to/audio.mp3\"\n      width={900}\n      height={140}\n      workerUrl=\"https://cdn.example.com/peaks.worker.js\"\n    />\n  );\n}\n```\n\n**Note:** The compiled worker file is available at `dist/peaks.worker.js` in the published package for custom hosting scenarios.\n\n### Forcing Main-Thread Computation\n\nFor debugging or environments where Web Workers are problematic, you can force main-thread computation:\n\n```jsx\nimport WaveformNavigator from 'waveform-navigator';\n\nfunction App() {\n  return (\n    <WaveformNavigator\n      audio=\"/path/to/audio.mp3\"\n      width={900}\n      height={140}\n      forceMainThread={true}\n    />\n  );\n}\n```\n\n### Fallback Behavior\n\nThe component automatically detects and handles worker failures:\n\n1. **Worker supported and created successfully:** Peak computation runs in worker (default behavior)\n2. **Worker not supported:** Falls back to main-thread computation with a console warning\n3. **Worker creation fails (CSP, CORS, etc.):** Falls back to main-thread computation with a console warning\n4. **`forceMainThread={true}` provided:** Skips worker creation entirely and uses main-thread\n\nIn all cases, the waveform is rendered correctly—worker usage is a performance optimization, not a requirement.\n\n## Accessibility\n\nThe waveform component is designed to be fully accessible to keyboard users and screen readers.\n\n### Keyboard Navigation\n\nThe waveform can be focused and controlled entirely via keyboard:\n\n| Key                    | Action                                                          |\n| ---------------------- | --------------------------------------------------------------- |\n| **Tab**                | Focus the waveform control                                      |\n| **Arrow Left**         | Seek backward by small step (default: 5 seconds)                |\n| **Arrow Right**        | Seek forward by small step (default: 5 seconds)                 |\n| **Page Up**            | Seek backward by large step (default: 10% of duration)          |\n| **Page Down**          | Seek forward by large step (default: 10% of duration)           |\n| **Home**               | Jump to the start of the audio                                  |\n| **End**                | Jump to the final moments of the audio (seeks close to the end) |\n| **Space** or **Enter** | Toggle play/pause                                               |\n\n### Screen Reader Support\n\n- The waveform is exposed as a slider control (`role=\"slider\"`) to assistive technologies\n- Current time and duration are announced via `aria-valuetext` (e.g., \"2:30 of 4:43\")\n- The control has an accessible name via `aria-label` (default: \"Audio waveform seek bar\")\n- `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` provide the numeric state\n\n### Focus Indicators\n\n- When focused via keyboard, the waveform displays a high-contrast blue outline\n- The focus indicator meets WCAG AA contrast requirements\n- Uses `:focus-visible` to show focus only for keyboard navigation (not mouse clicks)\n\n### Customizing Accessibility\n\n```jsx\n<WaveformNavigator\n  audio=\"/audio.mp3\"\n  ariaLabel=\"Podcast episode waveform\"\n  keyboardSmallStep={10} // Seek 10 seconds with arrow keys\n  keyboardLargeStep={60} // Seek 60 seconds with PageUp/PageDown\n  disableKeyboardControls={false} // Set true to disable built-in keyboard handling\n/>\n```\n\n### Color Contrast\n\nThe default colors meet WCAG AA contrast requirements:\n\n- Focus outline: `#0066cc` against white backgrounds (`#ffffff`, contrast ratio ≈4.54:1)\n- Playhead: `#ff4d4f` (red) is visible against the waveform\n- Hover tooltip: `rgba(17,24,39,0.95)` background with white text (contrast ratio 15:1)\n\nFor custom themes, ensure your colors maintain sufficient contrast for accessibility.\n\n## Build and Development\n\n### Building the Package\n\nThe package is built using Vite in library mode, which produces optimized ESM and CJS outputs along with TypeScript declarations.\n\n```bash\n# Build the library\nnpm run build\n\n# Build in watch mode (useful during development)\nnpm run build:watch\n\n# Run demo app alongside watch mode\nnpm run dev\n```\n\n#### Build Outputs\n\nThe build process generates the following files in `dist/`:\n\n- **`index.mjs`** - ES module build (for modern bundlers and Node.js with ESM)\n- **`index.cjs`** - CommonJS build (for older bundlers and Node.js with CJS)\n- **`index.d.ts`** - TypeScript type declarations\n- **`styles.css`** - Component styles (must be imported separately)\n- **`peaks.worker.js`** - Compiled Web Worker script (for custom hosting scenarios)\n- **Source maps** - For debugging (`.map` files)\n\n### Package Exports\n\nThe package uses the modern `exports` field for proper ESM/CJS support and TypeScript types:\n\n```json\n{\n  \"main\": \"./dist/index.cjs\",\n  \"module\": \"./dist/index.mjs\",\n  \"types\": \"./dist/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"import\": {\n        \"types\": \"./dist/index.d.ts\",\n        \"default\": \"./dist/index.mjs\"\n      },\n      \"require\": {\n        \"types\": \"./dist/index.d.ts\",\n        \"default\": \"./dist/index.cjs\"\n      }\n    },\n    \"./styles.css\": \"./dist/styles.css\"\n  }\n}\n```\n\nThis configuration ensures that:\n\n- **ESM consumers** (modern bundlers, Node.js with `\"type\": \"module\"`) get the `.mjs` file\n- **CJS consumers** (older Node.js, some bundlers) get the `.cjs` file\n- **TypeScript users** get proper type definitions automatically\n- **Bundlers** can perform optimal tree-shaking (package is marked with `\"sideEffects\": [\"*.css\"]`)\n\n### Available Import Patterns\n\n```jsx\n// Default import (recommended)\nimport WaveformNavigator from 'waveform-navigator'\n\n// Named import also available\nimport { WaveformNavigator } from 'waveform-navigator'\n\n// Import styles\nimport 'waveform-navigator/styles.css'\n\n// TypeScript types\nimport type { WaveformNavigatorProps } from 'waveform-navigator'\n```\n\n### Publishing\n\nBefore publishing to npm:\n\n1. Ensure all changes are committed\n2. Update version in `package.json` (e.g., `npm version patch/minor/major`)\n3. Run `npm run build` to create fresh build outputs\n4. Run `npm publish`\n\nThe package includes automated safeguards:\n\n- The `prepare` script automatically runs the build before publishing, ensuring the latest code is always published\n- The `prepublishOnly` script runs type-checking and tests before allowing a publish, preventing broken releases\n\n### Available Scripts\n\n```bash\n# Build the library (cleans dist, builds main library + worker)\nnpm run build\n\n# Clean build artifacts\nnpm run clean\n\n# Type-check without emitting files\nnpm run type-check\n\n# Run tests\nnpm test\n\n# Build in watch mode (useful during development)\nnpm run build:watch\n\n# Run demo app alongside watch mode\nnpm run dev\n```\n\n### Development Setup\n\nTo work on this package:\n\n**Prerequisites:**\n\n- Node.js 20+ (required for development dependencies)\n- The package itself supports Node.js 14+ for consumers\n\n```bash\n# Install dependencies\nnpm install\n\n# Build the package\nnpm run build\n\n# Run demo app for testing changes\ncd demo\nnpm install\nnpm run dev\n```\n\nThe demo app imports the library from the parent directory, allowing you to test changes in a real application context.\n\n## Notes\n\n- This package expects a modern browser with `AudioContext` support.\n- For remote audio URLs, ensure CORS is enabled to allow waveform decoding.\n- In controlled mode, the component will sync the audio element's currentTime when `controlledCurrentTime` changes (with a threshold of 0.01 seconds to avoid feedback loops).\n- The `onCurrentTimeChange` callback is only fired in uncontrolled mode (when `controlledCurrentTime` is undefined).\n- **Canvas is HiDPI-aware.** The component automatically renders sharp waveforms on Retina displays and high-DPI devices (devicePixelRatio > 1). No extra work required from the consumer.\n- **Responsive by default.** The component uses `ResizeObserver` to automatically adjust to container width changes. When the container is resized, the waveform recomputes peaks from the cached audio buffer without re-fetching the audio file.\n- **Fallback for older browsers.** If `ResizeObserver` is not available (older browsers), a console warning is logged and the component falls back to using the fixed `width` prop.\n- **Performance.** Peak resampling on resize is debounced (default 150ms) to avoid excessive computation during continuous resizing. The audio buffer is cached in memory to enable fast resampling without re-decoding.\n\n## Troubleshooting\n\n### CORS Errors\n\n**Problem:** You see errors like \"CORS error: Audio file cannot be loaded due to cross-origin restrictions\" or \"Audio format not supported or CORS error\".\n\n**Solution:** The component requires CORS to be properly configured when loading audio from remote URLs. This is necessary because the Web Audio API needs to decode the audio data to generate the waveform visualization.\n\n**How to fix:**\n\n1. **Server-side (Recommended):** Configure your server to include proper CORS headers:\n\n   ```\n   Access-Control-Allow-Origin: *\n   # Or specify your domain:\n   Access-Control-Allow-Origin: https://yourdomain.com\n   ```\n\n2. **Proxy through your backend:** If you don't control the audio server, proxy the audio through your own backend that adds CORS headers.\n\n3. **For development:** Use a local development server that serves audio files with CORS headers, or use a CORS proxy service (not recommended for production).\n\n4. **File objects:** If possible, use File objects from `<input type=\"file\">` instead of remote URLs to avoid CORS issues entirely.\n\n**Note:** The component sets `crossOrigin=\"anonymous\"` on the audio element automatically. If your server requires credentials for CORS, you'll need to modify the component or proxy the requests.\n\n### Audio Decoding Errors\n\n**Problem:** You see \"Audio decode error\" or \"Audio format not supported\" messages.\n\n**Causes:**\n\n- The audio file is corrupted or incomplete\n- The file format is not supported by the browser\n- The file extension doesn't match the actual audio format\n\n**Solutions:**\n\n1. **Verify the file:** Ensure the audio file plays correctly in your browser by opening it directly\n2. **Check browser support:** Use widely supported formats like MP3, WAV, or OGG. Check [MDN's audio format compatibility table](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs)\n3. **Re-encode the file:** Use tools like FFmpeg to convert to a compatible format:\n   ```bash\n   ffmpeg -i input.audio -acodec libmp3lame -ab 192k output.mp3\n   ```\n4. **Check Content-Type:** Ensure your server sends the correct `Content-Type` header (e.g., `audio/mpeg` for MP3, `audio/wav` for WAV)\n\n### Safari and iOS Limitations\n\n**Problem:** Audio playback doesn't start, or you see AudioContext-related errors on Safari/iOS.\n\n**Important Safari/iOS Behavior:**\n\nSafari and iOS have special restrictions for audio playback to prevent unwanted sounds and conserve battery:\n\n1. **User Gesture Requirement:** On Safari (especially iOS), audio playback and AudioContext must be initiated by a user gesture (click, tap, etc.). The browser will block playback that starts without user interaction.\n\n2. **AudioContext Suspended State:** When you create an AudioContext on iOS Safari outside of a user gesture context, it will typically start in a \"suspended\" state. You should always check its state before attempting to resume it:\n\n   ```jsx\n   function App() {\n     const audioRef = useRef<HTMLAudioElement | null>(null);\n\n     const handleUserGesture = async () => {\n       // Resume AudioContext on user gesture (required for Safari/iOS)\n       const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;\n       if (AudioContextClass) {\n         const tempCtx = new AudioContextClass();\n         if (tempCtx.state === 'suspended') {\n           await tempCtx.resume();\n         }\n         tempCtx.close();\n       }\n\n       // Now the audio element can play\n       if (audioRef.current) {\n         audioRef.current.play();\n       }\n     };\n\n     return (\n       <div>\n         <button onClick={handleUserGesture}>Start Audio</button>\n         <WaveformNavigator\n           audio=\"/path/to/audio.mp3\"\n           audioElementRef={audioRef}\n         />\n       </div>\n     );\n   }\n   ```\n\n3. **Best Practices for Safari/iOS:**\n   - Always initiate playback through a user action (button click, tap, etc.)\n   - Display a \"Tap to play\" or \"Enable audio\" button before attempting playback\n   - Handle the `play()` promise rejection gracefully when autoplay is blocked\n   - Test your implementation on actual iOS devices, not just Safari on macOS\n\n4. **Low Power Mode:** iOS Low Power Mode may further restrict audio playback\n\n**More information:**\n\n- [Apple's Web Audio Best Practices](https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari)\n- [MDN: Autoplay guide for media and Web Audio APIs](https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide)\n\n### Network Errors\n\n**Problem:** \"Network error: Unable to fetch audio file\" or fetch failures.\n\n**Solutions:**\n\n1. Verify the URL is correct and accessible\n2. Check network connectivity\n3. Ensure the server is running and responding\n4. Check for firewall or security software blocking the request\n5. Verify the file exists at the specified path\n\n### Performance Issues with Large Files\n\n**Problem:** The waveform takes a long time to load or the UI becomes unresponsive.\n\n**Solutions:**\n\n1. **Use Web Worker (default):** The component uses a Web Worker by default for peak computation. Ensure you haven't disabled it with `forceMainThread={true}`.\n2. **Optimize audio files:** Use compressed formats (MP3, OGG) instead of uncompressed (WAV, AIFF).\n3. **Reduce file size:** Lower the bitrate or sample rate of your audio files if waveform quality is more important than audio quality.\n4. **Adjust responsive debounce:** Increase `responsiveDebounceMs` to reduce recomputation frequency during resizing.\n\n## Development\n\n### Running Tests\n\nThis project includes comprehensive test coverage with unit tests, integration tests, and visual regression tests.\n\n#### Unit Tests\n\nRun unit tests with Vitest:\n\n```bash\n# Run tests once\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Run tests with coverage\nnpm run test:coverage\n\n# Open Vitest UI\nnpm run test:ui\n```\n\nUnit tests cover:\n\n- Utility functions (formatTime, peaksComputation, syncCanvasSize)\n- Custom React hooks\n- Component rendering logic\n\n#### Integration and E2E Tests\n\nRun integration tests with Playwright:\n\n```bash\n# Run all e2e tests\nnpm run e2e\n\n# Run with UI mode (interactive)\nnpm run e2e:ui\n\n# Run in headed mode (see browser)\nnpm run e2e:headed\n\n# Debug tests\nnpm run e2e:debug\n```\n\nIntegration tests cover:\n\n- Audio loading and playback\n- Seek/click-to-seek functionality\n- Responsive resizing behavior\n- Event callbacks\n- Accessibility (a11y) with axe-core\n\n#### Visual Regression Tests\n\nVisual tests capture canvas snapshots and compare them to baselines:\n\n```bash\n# Run visual tests\nnpm run e2e -- e2e/visual.spec.ts\n\n# Update visual snapshots (when making intentional visual changes)\nnpm run visual:update\n```\n\nVisual tests verify:\n\n- Waveform rendering at DPR 1 and DPR 2\n- Consistent rendering at different viewport widths\n- Correct aspect ratios and canvas dimensions\n\n**Updating Visual Snapshots:**\n\nWhen you make intentional changes to the visual appearance of the waveform:\n\n1. Run `npm run visual:update` to generate new baseline snapshots\n2. Review the new snapshots in `e2e/__snapshots__/`\n3. Commit the updated snapshots to version control\n4. CI will use these baselines for future visual regression checks\n\n### Type Checking and Linting\n\n```bash\n# Type check with TypeScript\nnpm run type-check\n\n# Lint (currently runs type-check)\nnpm run lint\n```\n\n### Code Formatting\n\nThis project uses Prettier for code formatting with the following configuration:\n\n- Tabs for indentation\n- Always use semicolons\n- Single quotes for strings\n\n```bash\n# Format all files\nnpm run format\n\n# Check if files are formatted correctly\nnpm run format:check\n```\n\nThe repository includes VS Code settings that automatically format files on save. For other editors, install the Prettier extension and configure it to format on save.\n\n### Building\n\n```bash\n# Build the library\nnpm run build\n\n# Build in watch mode\nnpm run build:watch\n```\n\n### CI/CD\n\nThis project uses GitHub Actions for continuous integration. The CI pipeline runs on every push and pull request:\n\n- **Lint and Type Check:** Validates code quality and type safety\n- **Unit Tests:** Runs unit tests with coverage reporting (Node 20)\n- **Integration Tests:** Runs e2e tests with Playwright\n- **Visual Tests:** Compares visual snapshots against baselines\n- **Build:** Ensures the library builds successfully\n\nCoverage reports are uploaded to Codecov, and test artifacts (screenshots, reports) are available for failed runs.\n\n### Test Coverage\n\nThe project maintains these coverage thresholds:\n\n- **Lines:** 70%\n- **Functions:** 70%\n- **Branches:** 70%\n- **Statements:** 70%\n\nRun `npm run test:coverage` to generate a detailed coverage report in the `coverage/` directory.\n","readmeFilename":"README.md"}